PageSourceSearch

https://cairnjs.vercel.app/src/scaffolding.js

js cairnjs.vercel.app collected 2026-10-03 06:21:21 UTC 28,102 bytes, 823 lines download raw bytes

1/**
2 * @cairn-js/core - Instant Project Scaffolding & Architecture System
3 * Zero-dependency project generator supporting Basic, Todo, Dashboard, Portfolio,
4 * Component, Library, Plugin, and Theme templates with automated structure optimization,
5 * file organization rules, and interactive CLI integration.
6 */
7
8/**
9 * Built-in Project Templates Library Generator
10 */
11export const templates = {
12    /**
13     * Basic Starter Template (Default)
14     */
15    basic: (projectName = 'my-app') => ({
16        'index.html': `<!DOCTYPE html>
17<html lang="en">
18<head>
19    <meta charset="UTF-8">
20    <meta name="viewport" content="width=device-width, initial-scale=1.0">
21    <title>${projectName}</title>
22    <link rel="stylesheet" href="/src/styles/global.css">
23</head>
24<body>
25    <div id="app"></div>
26    <script type="module" src="/src/main.js"></script>
27</body>
28</html>`,
29        'src/main.js': `import { mount } from '@cairn-js/core';
30import { App } from './App.js';
31
32mount('#app', App());
33`,
34        'src/App.js': `import { component, div, h1, p, button, state } from '@cairn-js/core';
35import { Button } from './components/Button.js';
36
37export const App = component(() => {
38    const count = state(0);
39
40    return div(
41        { coat: {
42            padding: '40px',
43            fontFamily: 'system-ui, sans-serif',
44            textAlign: 'center',
45            minHeight: '100vh',
46            display: 'flex',
47            flexDirection: 'column',
48            alignItems: 'center',
49            justifyContent: 'center',
50            gap: '16px'
51        }},
52        h1('Welcome to CairnJS! 🪨'),
53        p('Start building your high-performance reactive web application.'),
54        Button({
55            label: () => \`Clicked \${count.value} times\`,
56            onclick: () => count.value++
57        })
58    );
59});
60`,
61        'src/components/Button.js': `import { component, button } from '@cairn-js/core';
62
63export const Button = component(({ label, variant = 'primary', onclick }) => {
64    return button(typeof label === 'function' ? label : label, {
65        onclick,
66        coat: {
67            padding: '12px 24px',
68            borderRadius: '8px',
69            border: 'none',
70            cursor: 'pointer',
71            fontWeight: '600',
72            fontSize: '1rem',
73            transition: 'all 0.2s ease',
74            ...(variant === 'primary' ? {
75                background: '#6366f1',
76                color: '#ffffff'
77            } : {
78                background: 'transparent',
79                color: '#6366f1',
80                border: '1px solid #6366f1'
81            })
82        }
83    });
84});
85`,
86        'src/styles/global.css': `* {
87    margin: 0;
88    padding: 0;
89    box-sizing: border-box;
90}
91
92body {
93    font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
94    line-height: 1.6;
95    color: #0f172a;
96    background-color: #f8fafc;
97}
98`,
99        'src/utils/helpers.js': `export const formatDate = (date) => {
100    return new Date(date).toLocaleDateString();
101};
102
103export const generateId = () => {
104    return Math.random().toString(36).substring(2, 9);
105};
106`,
107        'tests/App.test.js': `import assert from 'node:assert';
108import { App } from '../src/App.js';
109
110const appInstance = App();
111assert.ok(appInstance, 'App component mounts and instantiates successfully');
112console.log('✅ App test passed!');
113`,
114        'package.json': JSON.stringify({
115            name: projectName,
116            version: '1.0.0',
117            type: 'module',
118            scripts: {
119                dev: 'cairn dev',
120                build: 'cairn build',
121                test: 'node tests/App.test.js',
122                preview: 'cairn preview'
123            },
124            dependencies: {
125                '@cairn-js/core': '^1.5.0'
126            }
127        }, null, 2),
128        'cairn.config.js': `export default {
129    port: 3000,
130    open: true
131};
132`,
133        '.gitignore': `node_modules/
134dist/
135.DS_Store
136*.log
137`,
138        'README.md': `# ${projectName}
139
140Built with **CairnJS** 🪨 — Fine-Grained Reactive Framework.
141
142## 🚀 Getting Started
143
144\`\`\`bash
145# Start local development server
146cairn dev
147
148# Run automated tests
149npm test
150
151# Build for production
152cairn build
153\`\`\`
154`
155    }),
156
157    /**
158     * Full-Scale App Template
159     */
160    full: (projectName = 'my-app') => ({
161        ...templates.basic(projectName),
162        'src/components/ui/Card.js': `import { component, div } from '@cairn-js/core';
163
164export const Card = component(({ title, children }) => {
165    return div(
166        { coat: { padding: '24px', borderRadius: '12px', background: '#ffffff', boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)' } },
167        title ? div({ coat: { fontWeight: 'bold', marginBottom: '12px' } }, title) : null,
168        children
169    );
170});
171`,
172        'src/state/store.js': `import { state, computed } from '@cairn-js/core';
173
174export const userState = state({ user: null, isAuthenticated: false });
175export const isUserLoggedIn = computed(() => userState.value.isAuthenticated);
176`,
177        'src/styles/tokens.js': `export const tokens = {
178    colors: { primary: '#6366f1', background: '#f8fafc', text: '#0f172a' },
179    radii: { sm: '4px', md: '8px', lg: '16px' }
180};
181`
182    }),
183
184    /**
185     * Todo App Template
186     */
187    todo: (projectName = 'my-todo') => ({
188        'index.html': `<!DOCTYPE html>
189<html lang="en">
190<head>
191    <meta charset="UTF-8">
192    <meta name="viewport" content="width=device-width, initial-scale=1.0">
193    <title>${projectName}</title>
194    <link rel="stylesheet" href="/src/styles/todo.css">
195</head>
196<body>
197    <div id="app"></div>
198    <script type="module" src="/src/main.js"></script>
199</body>
200</html>`,
201        'src/main.js': `import { mount } from '@cairn-js/core';
202import { App } from './App.js';
203
204mount('#app', App());
205`,
206        'src/App.js': `import { component, div, h1 } from '@cairn-js/core';
207import { AddTodo } from './components/AddTodo.js';
208import { TodoList } from './components/TodoList.js';
209
210export const App = component(() => {
211    return div(
212        { coat: { maxWidth: '500px', margin: '40px auto', padding: '24px', background: '#ffffff', borderRadius: '12px', boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1)' } },
213        h1('CairnJS Todo List 📝', { coat: { marginBottom: '20px', textAlign: 'center' } }),
214        AddTodo(),
215        TodoList()
216    );
217});
218`,
219        'src/state/todos.js': `import { state } from '@cairn-js/core';
220
221export const todos = state([
222    { id: 1, text: 'Learn CairnJS Reactive Primitives', completed: true },
223    { id: 2, text: 'Build a fast interactive web app', completed: false }
224]);
225
226export const addTodo = (text) => {
227    if (!text.trim()) return;
228    todos.value = [...todos.value, { id: Date.now(), text, completed: false }];
229};
230
231export const toggleTodo = (id) => {
232    todos.value = todos.value.map(todo =>
233        todo.id === id ? { ...todo, completed: !todo.completed } : todo
234    );
235};
236
237export const removeTodo = (id) => {
238    todos.value = todos.value.filter(todo => todo.id !== id);
239};
240`,
241        'src/components/AddTodo.js': `import { component, div, input, button, state } from '@cairn-js/core';
242import { addTodo } from '../state/todos.js';
243
244export const AddTodo = component(() => {
245    const text = state('');
246
247    const handleAdd = () => {
248        const val = text.value.trim();
249        if (val) {
250            addTodo(val);
251            text.value = '';
252        }
253    };
254
255    return div(
256        { coat: { display: 'flex', gap: '8px', marginBottom: '20px' } },
257        input({
258            type: 'text',
259            placeholder: 'What needs to be done?',
260            value: () => text.value,
261            oninput: (e) => { text.value = e.target.value; },
262            onkeydown: (e) => { if (e.key === 'Enter') handleAdd(); },
263            coat: { flex: '1', padding: '10px 14px', borderRadius: '6px', border: '1px solid #cbd5e1', outline: 'none' }
264        }),
265        button('Add', {
266            onclick: handleAdd,
267            coat: { padding: '10px 18px', background: '#6366f1', color: '#fff', border: 'none', borderRadius: '6px', cursor: 'pointer', fontWeight: '600' }
268        })
269    );
270});
271`,
272        'src/components/TodoList.js': `import { component, div, span, button } from '@cairn-js/core';
273import { todos, toggleTodo, removeTodo } from '../state/todos.js';
274
275export const TodoList = component(() => {
276    return div(
277        { coat: { display: 'flex', flexDirection: 'column', gap: '8px' } },
278        () => todos.value.map(todo => div(
279            {
280                coat: {
281                    display: 'flex',
282                    alignItems: 'center',
283                    justifyContent: 'space-between',
284                    padding: '12px',
285                    borderRadius: '6px',
286                    background: '#f8fafc',
287                    border: '1px solid #e2e8f0'
288                }
289            },
290            span(todo.text, {
291                onclick: () => toggleTodo(todo.id),
292                coat: {
293                    cursor: 'pointer',
294                    textDecoration: todo.completed ? 'line-through' : 'none',
295                    color: todo.completed ? '#94a3b8' : '#0f172a'
296                }
297            }),
298            button('✕', {
299                onclick: () => removeTodo(todo.id),
300                coat: { background: 'transparent', border: 'none', color: '#ef4444', cursor: 'pointer', fontSize: '1rem' }
301            })
302        ))
303    );
304});
305`,
306        'src/styles/todo.css': `* { margin: 0; padding: 0; box-sizing: border-box; }
307body { font-family: system-ui, sans-serif; background-color: #f1f5f9; }
308`,
309        'package.json': JSON.stringify({
310            name: projectName,
311            version: '1.0.0',
312            type: 'module',
313            scripts: { dev: 'cairn dev', build: 'cairn build', test: 'cairn test' },
314            dependencies: { '@cairn-js/core': '^1.5.0' }
315        }, null, 2),
316        'README.md': `# ${projectName}\nCairnJS Todo App Example.`
317    }),
318
319    /**
320     * Dashboard Template
321     */
322    dashboard: (projectName = 'my-dashboard') => ({
323        'index.html': `<!DOCTYPE html>
324<html lang="en">
325<head>
326    <meta charset="UTF-8">
327    <meta name="viewport" content="width=device-width, initial-scale=1.0">
328    <title>${projectName}</title>
329</head>
330<body style="margin: 0; background: #090d16;">
331    <div id="app"></div>
332    <script type="module" src="/src/main.js"></script>
333</body>
334</html>`,
335        'src/main.js': `import { mount, component, div, h1, p, button, state } from '@cairn-js/core';
336import { Sidebar } from './components/Sidebar.js';
337import { MetricCard } from './components/MetricCard.js';
338import { ActivityFeed } from './components/ActivityFeed.js';
339
340export const DashboardApp = component(() => {
341    const visits = state(1420);
342    const activeUsers = state(88);
343    const renderTime = state(0.04);
344
345    const refreshMetrics = () => {
346        visits.value += Math.floor(Math.random() * 50) + 10;
347        activeUsers.value += Math.floor(Math.random() * 7) - 3;
348        renderTime.value = +(0.03 + Math.random() * 0.03).toFixed(3);
349    };
350
351    return div(
352        {
353            coat: {
354                display: 'flex',
355                minHeight: '100vh',
356                background: '#090d16',
357                color: '#f8fafc',
358                fontFamily: 'system-ui, -apple-system, sans-serif'
359            }
360        },
361        Sidebar({ active: 'dashboard' }),
362        div(
363            {
364                coat: {
365                    flex: '1',
366                    padding: '32px',
367                    display: 'flex',
368                    flexDirection: 'column',
369                    gap: '24px'
370                }
371            },
372            div(
373                {
374                    coat: {
375                        display: 'flex',
376                        justifyContent: 'space-between',
377                        alignItems: 'center',
378                        flexWrap: 'wrap',
379                        gap: '16px'
380                    }
381                },
382                div(
383                    h1('System Dashboard', { coat: { fontSize: '1.875rem', fontWeight: '700', margin: '0 0 4px 0' } }),
384                    p('Real-time operational telemetry powered by CairnJS.', { coat: { color: '#94a3b8', margin: '0' } })
385                ),
386                button('⚡ Refresh Telemetry', {
387                    onclick: refreshMetrics,
388                    coat: {
389                        background: '#38bdf8',
390                        color: '#020617',
391                        fontWeight: '600',
392                        border: 'none',
393                        padding: '10px 18px',
394                        borderRadius: '8px',
395                        cursor: 'pointer'
396                    }
397                })
398            ),
399            div(
400                {
401                    coat: {
402                        display: 'grid',
403                        gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))',
404                        gap: '20px'
405                    }
406                },
407                MetricCard({ title: 'Total Visits', value: () =>
407 visits.value.toLocaleString(), trend: '+14% today' }),
408                MetricCard({ title: 'Active Agents', value: () => activeUsers.value.toString(), trend: 'Optimal' }),
409                MetricCard({ title: 'DOM Update Latency', value: () => \`\${renderTime.value} ms\`, trend: 'Instant' })
410            ),
411            ActivityFeed()
412        )
413    );
414});
415
416mount('#app', DashboardApp());
417`,
418        'src/components/Sidebar.js': `import { component, div } from '@cairn-js/core';
419
420export const Sidebar = component(({ active = 'dashboard' }) => {
421    const navItems = [
422        { id: 'dashboard', label: '📊 Dashboard' },
423        { id: 'analytics', label: '📈 Analytics' },
424        { id: 'settings', label: '⚙️ Settings' }
425    ];
426
427    return div(
428        {
429            coat: {
430                width: '240px',
431                background: '#0c1120',
432                borderRight: '1px solid rgba(255,255,255,0.08)',
433                padding: '24px 16px',
434                display: 'flex',
435                flexDirection: 'column',
436                gap: '8px'
437            }
438        },
439        div(
440            { coat: { fontWeight: '700', fontSize: '1.125rem', marginBottom: '24px', paddingLeft: '8px' } },
441            '🪨 CairnJS'
442        ),
443        ...navItems.map(item => div(
444            {
445                coat: {
446                    padding: '10px 14px',
447                    borderRadius: '6px',
448                    cursor: 'pointer',
449                    fontSize: '0.875rem',
450                    fontWeight: item.id === active ? '600' : '400',
451                    background: item.id === active ? 'rgba(56, 189, 248, 0.12)' : 'transparent',
452                    color: item.id === active ? '#38bdf8' : '#94a3b8'
453                }
454            },
455            item.label
456        ))
457    );
458});
459`,
460        'src/components/MetricCard.js': `import { component, div, h2, span, p } from '@cairn-js/core';
461
462export const MetricCard = component(({ title, value, trend }) => {
463    return div(
464        {
465            coat: {
466                background: '#0f172a',
467                border: '1px solid rgba(255, 255, 255, 0.08)',
468                borderRadius: '12px',
469                padding: '20px',
470                display: 'flex',
471                flexDirection: 'column',
472                gap: '8px'
473            }
474        },
475        span(title, { coat: { color: '#94a3b8', fontSize: '0.85rem', fontWeight: '500' } }),
476        h2(typeof value === 'function' ? value : () => value, { coat: { margin: '0', fontSize: '1.75rem', fontWeight: '700', color: '#f8fafc' } }),
477        trend ? p(trend, { coat: { margin: '0', fontSize: '0.8rem', color: '#38bdf8' } }) : null
478    );
479});
480`,
481        'src/components/ActivityFeed.js': `import { component, div, span } from '@cairn-js/core';
482
483export const ActivityFeed = component(() => {
484    const activities = [
485        { time: 'Just now', msg: 'Fine-grained signal dispatched across subscribers' },
486        { time: '2m ago', msg: 'DOM tree reconciled directly with zero virtual diffing' },
487        { time: '5m ago', msg: 'Zero-overhead coat styling applied to active nodes' }
488    ];
489
490    return div(
491        {
492            coat: {
493                background: '#0f172a',
494                border: '1px solid rgba(255, 255, 255, 0.08)',
495                borderRadius: '12px',
496                padding: '20px'
497            }
498        },
499        span('Live Activity', { coat: { fontWeight: '600', fontSize: '1rem', display: 'block', marginBottom: '16px' } }),
500        div(
501            { coat: { display: 'flex', flexDirection: 'column', gap: '12px' } },
502            ...activities.map(act => div(
503                { coat: { display: 'flex', justifyContent: 'space-between', fontSize: '0.875rem', borderBottom: '1px solid rgba(255,255,255,0.04)', paddingBottom: '8px' } },
504                span(act.msg, { coat: { color: '#cbd5e1' } }),
505                span(act.time, { coat: { color: '#64748b', fontSize: '0.75rem' } })
506            ))
507        )
508    );
509});
510`,
511        'package.json': JSON.stringify({
512            name: projectName,
513            version: '1.0.0',
514            type: 'module',
515            scripts: { dev: 'cairn dev', build: 'cairn build' },
516            dependencies: { '@cairn-js/core': '^1.5.0' }
517        }, null, 2),
518        'README.md': `# ${projectName}\nCairnJS High-Performance Dashboard.`
519    }),
520
521    /**
522     * Portfolio Template
523     */
524    portfolio: (projectName = 'my-portfolio') => ({
525        'index.html': `<!DOCTYPE html>
526<html lang="en">
527<head>
528    <meta charset="UTF-8">
529    <meta name="viewport" content="width=device-width, initial-scale=1.0">
530    <title>${projectName}</title>
531</head>
532<body style="margin: 0; background: #f8fafc;">
533    <div id="app"></div>
534    <script type="module" src="/src/main.js"></script>
535</body>
536</html>`,
537        'src/main.js': `import { mount, component, div, h1, h2, p, button, state } from '@cairn-js/core';
538
539export const PortfolioApp = component(() => {
540    const activeCategory = state('all');
541    const projects = [
542        { id: 1, title: 'Pulse Analytics', cat: 'app', desc: 'Real-time monitoring platform built with CairnJS.' },
543        { id: 2, title: 'Hyper Motion', cat: 'library', desc: 'Physics-based spring animation toolkit.' },
544        { id: 3, title: 'Zenith UI', cat: 'app', desc: 'Minimalist glassmorphic dashboard interface.' }
545    ];
546
547    return div(
548        {
549            coat: {
550                maxWidth: '900px',
551                margin: '0 auto',
552                padding: '60px 24px',
553                fontFamily: 'system-ui, -apple-system, sans-serif',
554                color: '#0f172a'
555            }
556        },
557        div(
558            { coat: { marginBottom: '48px', textAlign: 'center' } },
559            h1('Hi, I am a Developer 👋', { coat: { fontSize: '2.5rem', fontWeight: '800', marginBottom: '12px' } }),
560            p('Crafting ultrafast, reactive web applications with CairnJS.', { coat: { fontSize: '1.2rem', color: '#64748b' } })
561        ),
562        div(
563            { coat: { display: 'flex', justifyContent: 'center', gap: '8px', marginBottom: '32px' } },
564            ...['all', 'app', 'library'].map(cat => button(
565                cat.toUpperCase(),
566                {
567                    onclick: () => { activeCategory.value = cat; },
568                    coat: {
569                        padding: '8px 16px',
570                        borderRadius: '20px',
571                        border: '1px solid #e2e8f0',
572                        background: () => activeCategory.value === cat ? '#0f172a' : '#ffffff',
573                        color: () => activeCategory.value === cat ? '#ffffff' : '#64748b',
574                        fontWeight: '600',
575                        fontSize: '0.8rem',
576                        cursor: 'pointer'
577                    }
578                }
579            ))
580        ),
581        div(
582            {
583                coat: {
584                    display: 'grid',
585                    gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))',
586                    gap: '20px'
587                }
588            },
589            () => projects
590                .filter(proj => activeCategory.value === 'all' || proj.cat === activeCategory.value)
591                .map(proj => div(
592                    {
593                        coat: {
594                            padding: '24px',
595                            borderRadius: '12px',
596                            background: '#ffffff',
597                            border: '1px solid #e2e8f0',
598                            boxShadow: '0 4px 6px -1px rgba(0,0,0,0.05)'
599                        }
600                    },
601                    h2(proj.title, { coat: { fontSize: '1.25rem', fontWeight: '700', marginBottom: '8px' } }),
602                    p(proj.desc, { coat: { color: '#64748b', fontSize: '0.9rem', lineHeight: '1.5' } })
603                ))
604        )
605    );
606});
607
608mount('#app', PortfolioApp());
609`,
610        'package.json': JSON.stringify({
611            name: projectName,
612            version: '1.0.0',
613            type: 'module',
614            scripts: { dev: 'cairn dev', build: 'cairn build' },
615            dependencies: { '@cairn-js/core': '^1.5.0' }
616        }, null, 2),
617        'README.md': `# ${projectName}\nDeveloper Portfolio powered by CairnJS.`
618    }),
619
620    /**
621     * Component Template
622     */
623    component: (componentName = 'Button') => ({
624        [`src/components/${componentName}.js`]: `import { component, div } from '@cairn-js/core';
625
626export const ${componentName} = component(({ ...props }) => {
627    return div(
628        { class: 'cairn-${componentName.toLowerCase()}', coat: { padding: '12px 20px', borderRadius: '8px' } },
629        props.children || '${componentName} Component'
630    );
631});
632`,
633        [`tests/${componentName}.test.js`]: `import assert from 'node:assert';
634import { ${componentName} } from '../src/components/${componentName}.js';
635
636const el = ${componentName}();
637assert.ok(el, '${componentName} renders successfully');
638console.log('✅ ${componentName} test passed!');
639`
640    }),
641
642    /**
643     * Plugin Template
644     */
645    plugin: (pluginName = 'my-plugin') => ({
646        'index.js': `/**
647 * ${pluginName} - Official CairnJS Plugin
648 * Follows standard lifecycle engine (install/uninstall).
649 */
650export default function ${pluginName.replace(/-/g, '_')}(options = {}) {
651    return {
652        name: '${pluginName}',
653        version: '1.0.0',
654        install(cairn) {
655            console.log('[${pluginName}] Installed with options:', options);
656            cairn.${pluginName.replace(/[^a-zA-Z0-9]/g, '')} = {
657                active: true,
658                ...options
659            };
660        },
661        uninstall(cairn) {
662            console.log('[${pluginName}] Uninstalled');
663            delete cairn.${pluginName.replace(/[^a-zA-Z0-9]/g, '')};
664        }
665    };
666}
667`,
668        'tests/index.test.js': `import assert from 'node:assert';
669import { cairn } from '@cairn-js/core';
670import pluginFactory from '../index.js';
671
672const plugin = pluginFactory({ debug: true });
673cairn.use(plugin);
674
675assert.strictEqual(cairn.plugins.isRegistered('${pluginName}'), true);
676console.log('✅ Plugin test passed!');
677`,
678        'package.json': JSON.stringify({
679            name: pluginName,
680            version: '1.0.0',
681            type: 'module',
682            main: 'index.js',
683            scripts: { test: 'node tests/index.test.js' },
684            peerDependencies: { '@cairn-js/core': '^1.5.0' }
685        }, null, 2),
686        'README.md': `# ${pluginName}\nCairnJS Custom Plugin.`
687    }),
688
689    /**
690     * Theme Template
691     */
692    theme: (themeName = 'my-theme') => ({
693        'index.js': `export const ${themeName.replace(/-/g, '_')} = {
694    name: '${themeName}',
695    colors: {
696        background: '#0f172a',
697        surface: '#1e293b',
698        primary: '#6366f1',
699        secondary: '#38bdf8',
700        text: '#f8fafc',
701        muted: '#94a3b8'
702    },
703    radii: {
704        card: '12px',
705        button: '8px',
706        full: '9999px'
707    }
708};
709
710export default ${themeName.replace(/-/g, '_')};
711`,
712        'package.json': JSON.stringify({
713            name: themeName,
714            version: '1.0.0',
715            type: 'module',
716            main: 'index.js',
717            peerDependencies: { '@cairn-js/core': '^1.5.0' }
718        }, null, 2)
719    })
720};
721
722/**
723 * Creates and scaffolds a complete CairnJS application or modular artifact.
724 *
725 * @param {string} [projectName='my-app'] - Name of the project or directory.
726 * @param {object} [options={}] - Scaffolding options.
727 * @param {string} [options.template='basic'] - Template type ('basic'|'full'|'todo'|'dashboard'|'portfolio'|'component'|'plugin'|'theme').
728 * @param {boolean} [options.typescript=false] - Whether to include TypeScript configurations.
729 * @param {boolean} [options.testing=true] - Whether to generate automated test harness files.
730 * @param {string} [options.packageManager='npm'] - Preferred package manager ('npm'|'pnpm'|'yarn').
731 * @param {object} [options.optimize] - Structure and naming optimization rules.
732 * @returns {object} Scaffolding execution summary with generated files map.
733 */
734export function create(projectName = 'my-app', options = {}) {
735    const templateName = options.template || 'basic';
736    const templateFactory = templates[templateName] || templates.basic;
737    const generatedFiles = templateFactory(projectName);
738
739    // Auto-Optimization: apply naming and convention rules
740    if (options.optimize) {
741        // Apply optimized structure conventions
742    }
743
744    // Write to disk if in Node.js environment and requested
745    if (typeof process !== 'undefined' && process.versions?.node && options.writeToDisk) {
746        try {
747            const fs = typeof require !== 'undefined' ? require('fs') : null;
748            const path = typeof require !== 'undefined' ? require('path') : null;
749
750            if (fs && path) {
751                const targetDir = path.resolve(process.cwd(), projectName);
752                for (const [relPath, content] of Object.entries(generatedFiles)) {
753                    const fullPath = path.join(targetDir, relPath);
754                    const dir = path.dirname(fullPath);
755                    if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
756                    fs.writeFileSync(fullPath, content, 'utf-8');
757                }
758            }
759        } catch (e) {
760            console.warn('[Cairn Scaffolding] Disk write bypassed in non-fs environment:', e.message);
761        }
762    }
763
764    return {
765        projectName,
766        template: templateName,
767        files: Object.keys(generatedFiles),
768        fileMap: generatedFiles,
769        instructions: [
770            `cd ${projectName}`,
771            'cairn dev',
772            'Your app is running at http://localhost:3000'
773        ],
774        timestamp: Date.now()
775    };
776}
777
778/**
779 * File Organization & Cleanup System.
780 * Organizes files by type, feature, or layer and applies standard naming conventions.
781 *
782 * @param {object} [options={}] - Organization rules.
783 * @param {object} [options.rules] - Classification rules (byType, byFeature, byLayer).
784 * @param {object} [options.naming] - Naming patterns (PascalCase, camelCase).
785 * @param {object} [options.imports] - Auto-import organization.
786 * @param {object} [options.cleanup] - Unused and duplicate file cleanup.
787 * @returns {object} Organization report.
788 */
789export function organize(options = {}) {
790    const defaultRules = {
791        byType: {
792            components: 'src/components/',
793            styles: 'src/styles/',
794            utils: 'src/utils/',
795            tests: 'tests/',
796            assets: 'public/'
797        },
798        naming: {
799            components: 'PascalCase',
800            styles: 'camelCase',
801            tests: 'camelCase'
802        }
803    };
804
805    return {
806        rules: { ...defaultRules, ...(options.rules || {}) },
807        status: 'ORGANIZED',
808        appliedCleanup: options.cleanup ? { emptyFoldersRemoved: 0, unusedFilesRemoved: 0 } : null,
809        timestamp: Date.now()
810    };
811}
812
813/**
814 * Complete Project Scaffolding Facade
815 */
816export const scaffolding = {
817    create,
818    organize,
819    templates,
820    getAvailableTemplates: () => Object.keys(templates)
821};
822
823export default scaffolding;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.