create-elit 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +115 -0
  2. package/dist/index.js +664 -0
  3. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # create-elit
2
+
3
+ Scaffolding tool for creating new Elit projects.
4
+
5
+ ## Usage
6
+
7
+ With npm:
8
+ ```bash
9
+ npm create elit@latest my-app
10
+ ```
11
+
12
+ With yarn:
13
+ ```bash
14
+ yarn create elit my-app
15
+ ```
16
+
17
+ With pnpm:
18
+ ```bash
19
+ pnpm create elit my-app
20
+ ```
21
+
22
+ With bun:
23
+ ```bash
24
+ bun create elit my-app
25
+ ```
26
+
27
+ With deno:
28
+ ```bash
29
+ deno run -A npm:create-elit my-app
30
+ ```
31
+
32
+ ## Templates
33
+
34
+ Choose a template with the `--template` flag:
35
+
36
+ ```bash
37
+ npm create elit@latest my-app --template=basic
38
+ ```
39
+
40
+ Available templates:
41
+
42
+ - **basic** (default) - Full-featured app with styled counter using CSS-in-JS
43
+ - **full** - Full-stack app with dev server, API routes, and CSS-in-JS
44
+ - **minimal** - Minimal setup with just DOM rendering
45
+
46
+ ## Features
47
+
48
+ ✨ **Zero Configuration** - Works out of the box
49
+ 🎨 **CSS-in-JS** - Uses Elit's `CreateStyle` for type-safe styling
50
+ 📦 **TypeScript Ready** - Full TypeScript support
51
+ 🚀 **Fast Setup** - Creates project in seconds
52
+ 🎯 **Multiple Templates** - Choose the right starting point
53
+
54
+ ## What's Included
55
+
56
+ Each template includes:
57
+ - TypeScript configuration
58
+ - Package.json with Elit scripts (`dev`, `build`, `preview`)
59
+ - Elit config file (`elit.config.mjs`)
60
+ - 100% TypeScript - no HTML files needed
61
+ - Type-safe CSS-in-JS with `CreateStyle`
62
+ - Server-side rendering with `dom.renderServer`
63
+ - Client-side hydration with `client.ts`
64
+ - Example code showing best practices
65
+ - Auto-generated README and .gitignore
66
+
67
+ ## Example
68
+
69
+ ```bash
70
+ # Create a new project
71
+ npm create elit@latest my-elit-app
72
+
73
+ # Navigate to project
74
+ cd my-elit-app
75
+
76
+ # Install dependencies
77
+ npm install
78
+
79
+ # Start dev server
80
+ npm run dev
81
+ ```
82
+
83
+ Visit http://localhost:3003 to see your app!
84
+
85
+ ## Template Details
86
+
87
+ ### Basic Template
88
+ - Counter example with increment/decrement
89
+ - Beautiful gradient UI with CSS-in-JS
90
+ - Reactive state management demo
91
+ - Type-safe styling with `CreateStyle`
92
+ - Server-side rendering with `dom.renderServer`
93
+
94
+ ### Full Template
95
+ - Counter and API call examples
96
+ - Server-side routing with middleware
97
+ - CORS and logging setup
98
+ - Client-server communication
99
+ - Full-stack TypeScript setup
100
+
101
+ ### Minimal Template
102
+ - Just the essentials
103
+ - Simple "Hello Elit!" example
104
+ - Perfect for learning or prototyping
105
+ - Pure TypeScript - zero HTML
106
+
107
+ ## Learn More
108
+
109
+ - [Elit Documentation](https://d-osc.github.io/elit)
110
+ - [GitHub Repository](https://github.com/d-osc/elit)
111
+ - [npm Package](https://www.npmjs.com/package/elit)
112
+
113
+ ## License
114
+
115
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,664 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { mkdir, writeFile } from "fs/promises";
5
+ import { join, resolve } from "path";
6
+ import { existsSync } from "fs";
7
+ var templates = {
8
+ basic: "Basic Elit app with counter example",
9
+ full: "Full-stack app with dev server and API routes",
10
+ minimal: "Minimal setup with just DOM rendering"
11
+ };
12
+ var colors = {
13
+ reset: "\x1B[0m",
14
+ cyan: "\x1B[36m",
15
+ green: "\x1B[32m",
16
+ yellow: "\x1B[33m",
17
+ red: "\x1B[31m",
18
+ dim: "\x1B[2m"
19
+ };
20
+ function log(message, color = "reset") {
21
+ console.log(`${colors[color]}${message}${colors.reset}`);
22
+ }
23
+ function getProjectName() {
24
+ const args = process.argv.slice(2);
25
+ return args[0] || "my-elit-app";
26
+ }
27
+ function getTemplate() {
28
+ const args = process.argv.slice(2);
29
+ const templateArg = args.find((arg) => arg.startsWith("--template="));
30
+ if (templateArg) {
31
+ const template2 = templateArg.split("=")[1];
32
+ if (template2 in templates) return template2;
33
+ }
34
+ return "basic";
35
+ }
36
+ async function createProject(projectName2, template2) {
37
+ const projectPath = resolve(process.cwd(), projectName2);
38
+ if (existsSync(projectPath)) {
39
+ log(`Error: Directory "${projectName2}" already exists!`, "red");
40
+ process.exit(1);
41
+ }
42
+ log(`Creating a new Elit app in ${projectPath}...`, "cyan");
43
+ await mkdir(projectPath, { recursive: true });
44
+ await generateTemplate(projectPath, projectName2, template2);
45
+ log("\nSuccess! Created " + projectName2, "green");
46
+ log("\nInside that directory, you can run several commands:", "dim");
47
+ log("\n npm run dev", "cyan");
48
+ log(" Starts the development server with HMR\n", "dim");
49
+ log(" npm run build", "cyan");
50
+ log(" Builds the app for production\n", "dim");
51
+ log(" npm run preview", "cyan");
52
+ log(" Preview the production build\n", "dim");
53
+ log("\nWe suggest that you begin by typing:\n", "dim");
54
+ log(` cd ${projectName2}`, "cyan");
55
+ log(" npm install", "cyan");
56
+ log(" npm run dev\n", "cyan");
57
+ log("Happy coding! \u{1F680}", "green");
58
+ }
59
+ async function generateTemplate(projectPath, projectName2, template2) {
60
+ const packageJson = {
61
+ name: projectName2,
62
+ version: "0.0.0",
63
+ type: "module",
64
+ scripts: {
65
+ dev: "elit dev",
66
+ build: "elit build",
67
+ preview: "elit preview"
68
+ },
69
+ dependencies: {
70
+ elit: "^2.0.0"
71
+ }
72
+ };
73
+ await writeFile(
74
+ join(projectPath, "package.json"),
75
+ JSON.stringify(packageJson, null, 2)
76
+ );
77
+ const tsConfig = {
78
+ compilerOptions: {
79
+ target: "ES2020",
80
+ module: "ESNext",
81
+ moduleResolution: "bundler",
82
+ lib: ["ES2020", "DOM", "DOM.Iterable"],
83
+ strict: true,
84
+ esModuleInterop: true,
85
+ skipLibCheck: true,
86
+ resolveJsonModule: true,
87
+ isolatedModules: true,
88
+ types: ["node"]
89
+ },
90
+ include: ["src"]
91
+ };
92
+ await writeFile(
93
+ join(projectPath, "tsconfig.json"),
94
+ JSON.stringify(tsConfig, null, 2)
95
+ );
96
+ const gitignore = `node_modules
97
+ dist
98
+ .env
99
+ .env.local
100
+ *.log
101
+ .DS_Store
102
+ `;
103
+ await writeFile(join(projectPath, ".gitignore"), gitignore);
104
+ const readme = `# ${projectName2}
105
+
106
+ A new Elit project created with create-elit.
107
+
108
+ ## Getting Started
109
+
110
+ \`\`\`bash
111
+ npm install
112
+ npm run dev
113
+ \`\`\`
114
+
115
+ Visit http://localhost:3003 to view your app.
116
+
117
+ ## Available Scripts
118
+
119
+ - \`npm run dev\` - Start development server with HMR
120
+ - \`npm run build\` - Build for production
121
+ - \`npm run preview\` - Preview production build
122
+
123
+ ## Learn More
124
+
125
+ - [Elit Documentation](https://d-osc.github.io/elit)
126
+ - [GitHub Repository](https://github.com/d-osc/elit)
127
+ `;
128
+ await writeFile(join(projectPath, "README.md"), readme);
129
+ const elitConfig = `import { server } from './src/server';
130
+ import { client } from './src/client';
131
+
132
+ export default {
133
+ dev: {
134
+ port: 3003,
135
+ host: '0.0.0.0',
136
+ open: ${template2 === "basic" ? "true" : "false"},
137
+ logging: true,
138
+ clients: [{
139
+ root: '.',
140
+ basePath: '',
141
+ ssr: () => client,
142
+ api: server
143
+ }]
144
+ },
145
+ build: [{
146
+ entry: './src/main.ts',
147
+ outDir: './dist',
148
+ outFile: 'main.js',
149
+ format: 'esm',
150
+ minify: true,
151
+ sourcemap: true,
152
+ target: 'es2020',
153
+ copy: [
154
+ { from: './public/index.html', to: './index.html' }
155
+ ]
156
+ }],
157
+ preview: {
158
+ port: 3000,
159
+ host: '0.0.0.0',
160
+ open: false,
161
+ logging: true,
162
+ root: './dist',
163
+ basePath: '',
164
+ index: './index.html'
165
+ }
166
+ };
167
+ `;
168
+ await writeFile(join(projectPath, "elit.config.ts"), elitConfig);
169
+ await mkdir(join(projectPath, "public"), { recursive: true });
170
+ const indexHtml = `<!DOCTYPE html>
171
+ <html lang="en">
172
+ <head>
173
+ <meta charset="UTF-8">
174
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
175
+ <title>${projectName2}</title>
176
+ <link rel="icon" type="image/svg+xml" href="favicon.svg">
177
+ <meta name="description" content="Built with Elit - Full-stack TypeScript framework">
178
+ </head>
179
+ <body>
180
+ <div id="root"></div>
181
+ <script type="module" src="/main.js"></script>
182
+ </body>
183
+ </html>
184
+ `;
185
+ await writeFile(join(projectPath, "public", "index.html"), indexHtml);
186
+ await mkdir(join(projectPath, "src"), { recursive: true });
187
+ if (template2 === "basic") {
188
+ await generateBasicTemplate(projectPath, projectName2);
189
+ } else if (template2 === "full") {
190
+ await generateFullTemplate(projectPath, projectName2);
191
+ } else {
192
+ await generateMinimalTemplate(projectPath, projectName2);
193
+ }
194
+ }
195
+ async function generateBasicTemplate(projectPath, projectName2) {
196
+ const mainTs = `import { div, h1, h2, button, p } from 'elit/el';
197
+ import { createState, reactive } from 'elit/state';
198
+ import { render } from 'elit/dom';
199
+ import './styles.ts';
200
+
201
+ // Create reactive state (shared between SSR and client)
202
+ export const count = createState(0);
203
+
204
+ // Create app (shared between SSR and client)
205
+ export const app = div({ className: 'container' },
206
+ div({ className: 'card' },
207
+ h1('Welcome to Elit! \u{1F680}'),
208
+ p('A lightweight TypeScript framework with reactive state management'),
209
+
210
+ div({ className: 'counter' },
211
+ h2('Counter Example'),
212
+ reactive(count, (value) =>
213
+ div({ className: 'count-display' }, \`Count: \${value}\`)
214
+ ),
215
+ div({ className: 'button-group' },
216
+ button({
217
+ onclick: () => count.value--,
218
+ className: 'btn btn-secondary'
219
+ }, '- Decrement'),
220
+ button({
221
+ onclick: () => count.value = 0,
222
+ className: 'btn btn-secondary'
223
+ }, 'Reset'),
224
+ button({
225
+ onclick: () => count.value++,
226
+ className: 'btn btn-primary'
227
+ }, '+ Increment')
228
+ )
229
+ )
230
+ )
231
+ );
232
+
233
+ render('root', app);
234
+ console.log('[Main] App rendered');
235
+ `;
236
+ await writeFile(join(projectPath, "src", "main.ts"), mainTs);
237
+ const stylesTs = `import styles from 'elit/style';
238
+
239
+ // Global styles
240
+ styles.addTag('*', {
241
+ margin: 0,
242
+ padding: 0,
243
+ boxSizing: 'border-box'
244
+ });
245
+
246
+ styles.addTag('body', {
247
+ fontFamily: 'system-ui, -apple-system, sans-serif',
248
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
249
+ minHeight: '100vh',
250
+ display: 'flex',
251
+ alignItems: 'center',
252
+ justifyContent: 'center',
253
+ padding: '2rem'
254
+ });
255
+
256
+ // Container
257
+ styles.addClass('container', {
258
+ width: '100%',
259
+ maxWidth: '600px'
260
+ });
261
+
262
+ // Card
263
+ styles.addClass('card', {
264
+ background: 'white',
265
+ borderRadius: '16px',
266
+ padding: '3rem',
267
+ boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)'
268
+ });
269
+
270
+ // Typography
271
+ styles.addTag('h1', {
272
+ fontSize: '2.5rem',
273
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
274
+ WebkitBackgroundClip: 'text',
275
+ WebkitTextFillColor: 'transparent',
276
+ backgroundClip: 'text',
277
+ marginBottom: '1rem'
278
+ });
279
+
280
+ styles.addTag('h2', {
281
+ fontSize: '1.5rem',
282
+ color: '#333',
283
+ marginBottom: '1rem'
284
+ });
285
+
286
+ styles.addTag('p', {
287
+ color: '#666',
288
+ marginBottom: '2rem',
289
+ lineHeight: 1.6
290
+ });
291
+
292
+ // Counter section
293
+ styles.addClass('counter', {
294
+ marginTop: '2rem',
295
+ paddingTop: '2rem',
296
+ borderTop: '2px solid #f0f0f0'
297
+ });
298
+
299
+ styles.addClass('count-display', {
300
+ fontSize: '3rem',
301
+ fontWeight: 'bold',
302
+ color: '#667eea',
303
+ textAlign: 'center',
304
+ margin: '2rem 0'
305
+ });
306
+
307
+ // Button group
308
+ styles.addClass('button-group', {
309
+ display: 'flex',
310
+ gap: '1rem',
311
+ justifyContent: 'center'
312
+ });
313
+
314
+ // Buttons
315
+ styles.addClass('btn', {
316
+ padding: '0.75rem 1.5rem',
317
+ border: 'none',
318
+ borderRadius: '8px',
319
+ fontSize: '1rem',
320
+ fontWeight: 600,
321
+ cursor: 'pointer',
322
+ transition: 'all 0.2s'
323
+ });
324
+
325
+ styles.addClass('btn-primary', {
326
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
327
+ color: 'white'
328
+ });
329
+
330
+ styles.addPseudoClass('hover', {
331
+ transform: 'translateY(-2px)',
332
+ boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)'
333
+ }, '.btn-primary');
334
+
335
+ styles.addClass('btn-secondary', {
336
+ background: '#f0f0f0',
337
+ color: '#333'
338
+ });
339
+
340
+ styles.addPseudoClass('hover', {
341
+ background: '#e0e0e0',
342
+ transform: 'translateY(-2px)'
343
+ }, '.btn-secondary');
344
+
345
+ styles.addPseudoClass('active', {
346
+ transform: 'translateY(0)'
347
+ }, '.btn');
348
+
349
+ styles.inject('global-styles');
350
+ export default styles;
351
+ `;
352
+ await writeFile(join(projectPath, "src", "styles.ts"), stylesTs);
353
+ const clientTs = `import { div, html, head, body, title, link, script, meta } from 'elit/el';
354
+
355
+ export const client = html(
356
+ head(
357
+ title('${projectName2} - Elit App'),
358
+ link({ rel: 'icon', type: 'image/svg+xml', href: 'favicon.svg' }),
359
+ meta({ charset: 'UTF-8' }),
360
+ meta({ name: 'viewport', content: 'width=device-width, initial-scale=1.0' }),
361
+ meta({ name: 'description', content: 'Elit - Full-stack TypeScript framework with dev server, HMR, routing, SSR, and REST API.' })
362
+ ),
363
+ body(
364
+ div({ id: 'root' }),
365
+ script({ type: 'module', src: '/src/main.js' })
366
+ )
367
+ );
368
+ `;
369
+ await writeFile(join(projectPath, "src", "client.ts"), clientTs);
370
+ const serverTs = `import { ServerRouter } from 'elit/server';
371
+
372
+ export const router = new ServerRouter();
373
+
374
+ router.get('/api/hello', async (ctx) => {
375
+ ctx.res.setHeader('Content-Type', 'application/json');
376
+ ctx.res.end(JSON.stringify({ message: 'Hello from Elit ServerRouter!' }));
377
+ });
378
+
379
+ export const server = router;
380
+ `;
381
+ await writeFile(join(projectPath, "src", "server.ts"), serverTs);
382
+ }
383
+ async function generateFullTemplate(projectPath, projectName2) {
384
+ const mainTs = `import { div, h1, h2, button, p } from 'elit/el';
385
+ import { createState, reactive } from 'elit/state';
386
+ import { render } from 'elit/dom';
387
+ import './styles.ts';
388
+
389
+ // Create reactive state
390
+ export const count = createState(0);
391
+ export const message = createState<string>('');
392
+
393
+ // Fetch from API
394
+ async function fetchMessage() {
395
+ try {
396
+ const res = await fetch('/api/hello');
397
+ const data = await res.json();
398
+ message.value = data.message;
399
+ } catch (err) {
400
+ message.value = 'Error loading message';
401
+ }
402
+ }
403
+
404
+ // Create app
405
+ export const app = div({ className: 'container' },
406
+ div({ className: 'card' },
407
+ h1('Elit Full-Stack App \u{1F680}'),
408
+ p('Counter and API integration example'),
409
+
410
+ div({ className: 'counter' },
411
+ h2('Counter Example'),
412
+ reactive(count, (value) =>
413
+ div({ className: 'count-display' }, \`Count: \${value}\`)
414
+ ),
415
+ div({ className: 'button-group' },
416
+ button({
417
+ onclick: () => count.value--,
418
+ className: 'btn btn-secondary'
419
+ }, '- Decrement'),
420
+ button({
421
+ onclick: () => count.value = 0,
422
+ className: 'btn btn-secondary'
423
+ }, 'Reset'),
424
+ button({
425
+ onclick: () => count.value++,
426
+ className: 'btn btn-primary'
427
+ }, '+ Increment')
428
+ )
429
+ ),
430
+
431
+ div({ className: 'api-section' },
432
+ h2('API Example'),
433
+ button({
434
+ onclick: () => fetchMessage(),
435
+ className: 'btn btn-primary'
436
+ }, 'Fetch from API'),
437
+ reactive(message, (msg) =>
438
+ msg ? p({ className: 'api-message' }, \`API says: \${msg}\`) : p('')
439
+ )
440
+ )
441
+ )
442
+ );
443
+
444
+ render('root', app);
445
+ console.log('[Main] App rendered');
446
+ `;
447
+ await writeFile(join(projectPath, "src", "main.ts"), mainTs);
448
+ const serverTs = `import { ServerRouter } from 'elit/server';
449
+
450
+ export const router = new ServerRouter();
451
+
452
+ router.get('/api/hello', async (ctx) => {
453
+ ctx.res.setHeader('Content-Type', 'application/json');
454
+ ctx.res.end(JSON.stringify({ message: 'Hello from Elit ServerRouter!' }));
455
+ });
456
+
457
+ router.get('/api/count', async (ctx) => {
458
+ ctx.res.setHeader('Content-Type', 'application/json');
459
+ ctx.res.end(JSON.stringify({ count: Math.floor(Math.random() * 100) }));
460
+ });
461
+
462
+ export const server = router;
463
+ `;
464
+ await writeFile(join(projectPath, "src", "server.ts"), serverTs);
465
+ const stylesTs = `import styles from 'elit/style';
466
+
467
+ // Global styles
468
+ styles.addTag('*', {
469
+ margin: 0,
470
+ padding: 0,
471
+ boxSizing: 'border-box'
472
+ });
473
+
474
+ styles.addTag('body', {
475
+ fontFamily: 'system-ui, -apple-system, sans-serif',
476
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
477
+ minHeight: '100vh',
478
+ display: 'flex',
479
+ alignItems: 'center',
480
+ justifyContent: 'center',
481
+ padding: '2rem'
482
+ });
483
+
484
+ // Container
485
+ styles.addClass('container', {
486
+ width: '100%',
487
+ maxWidth: '600px'
488
+ });
489
+
490
+ // Card
491
+ styles.addClass('card', {
492
+ background: 'white',
493
+ borderRadius: '16px',
494
+ padding: '3rem',
495
+ boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)'
496
+ });
497
+
498
+ // Typography
499
+ styles.addTag('h1', {
500
+ fontSize: '2.5rem',
501
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
502
+ WebkitBackgroundClip: 'text',
503
+ WebkitTextFillColor: 'transparent',
504
+ backgroundClip: 'text',
505
+ marginBottom: '1rem'
506
+ });
507
+
508
+ styles.addTag('h2', {
509
+ fontSize: '1.5rem',
510
+ color: '#333',
511
+ marginBottom: '1rem'
512
+ });
513
+
514
+ styles.addTag('p', {
515
+ color: '#666',
516
+ marginBottom: '2rem',
517
+ lineHeight: 1.6
518
+ });
519
+
520
+ // Counter section
521
+ styles.addClass('counter', {
522
+ marginTop: '2rem',
523
+ paddingTop: '2rem',
524
+ borderTop: '2px solid #f0f0f0'
525
+ });
526
+
527
+ styles.addClass('count-display', {
528
+ fontSize: '3rem',
529
+ fontWeight: 'bold',
530
+ color: '#667eea',
531
+ textAlign: 'center',
532
+ margin: '2rem 0'
533
+ });
534
+
535
+ // API section
536
+ styles.addClass('api-section', {
537
+ marginTop: '2rem',
538
+ paddingTop: '2rem',
539
+ borderTop: '2px solid #f0f0f0'
540
+ });
541
+
542
+ styles.addClass('api-message', {
543
+ marginTop: '1rem',
544
+ padding: '1rem',
545
+ background: '#f0f0f0',
546
+ borderRadius: '8px',
547
+ color: '#333',
548
+ textAlign: 'center'
549
+ });
550
+
551
+ // Button group
552
+ styles.addClass('button-group', {
553
+ display: 'flex',
554
+ gap: '1rem',
555
+ justifyContent: 'center'
556
+ });
557
+
558
+ // Buttons
559
+ styles.addClass('btn', {
560
+ padding: '0.75rem 1.5rem',
561
+ border: 'none',
562
+ borderRadius: '8px',
563
+ fontSize: '1rem',
564
+ fontWeight: 600,
565
+ cursor: 'pointer',
566
+ transition: 'all 0.2s'
567
+ });
568
+
569
+ styles.addClass('btn-primary', {
570
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
571
+ color: 'white'
572
+ });
573
+
574
+ styles.addPseudoClass('hover', {
575
+ transform: 'translateY(-2px)',
576
+ boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)'
577
+ }, '.btn-primary');
578
+
579
+ styles.addClass('btn-secondary', {
580
+ background: '#f0f0f0',
581
+ color: '#333'
582
+ });
583
+
584
+ styles.addPseudoClass('hover', {
585
+ background: '#e0e0e0',
586
+ transform: 'translateY(-2px)'
587
+ }, '.btn-secondary');
588
+
589
+ styles.addPseudoClass('active', {
590
+ transform: 'translateY(0)'
591
+ }, '.btn');
592
+
593
+ styles.inject('global-styles');
594
+ export default styles;
595
+ `;
596
+ await writeFile(join(projectPath, "src", "styles.ts"), stylesTs);
597
+ const clientTs = `import { div, html, head, body, title, link, script, meta } from 'elit/el';
598
+
599
+ export const client = html(
600
+ head(
601
+ title('${projectName2} - Elit Full-Stack App'),
602
+ link({ rel: 'icon', type: 'image/svg+xml', href: 'favicon.svg' }),
603
+ meta({ charset: 'UTF-8' }),
604
+ meta({ name: 'viewport', content: 'width=device-width, initial-scale=1.0' }),
605
+ meta({ name: 'description', content: 'Full-stack TypeScript framework with dev server, HMR, routing, SSR, and REST API.' })
606
+ ),
607
+ body(
608
+ div({ id: 'root' }),
609
+ script({ type: 'module', src: '/src/main.js' })
610
+ )
611
+ );
612
+ `;
613
+ await writeFile(join(projectPath, "src", "client.ts"), clientTs);
614
+ }
615
+ async function generateMinimalTemplate(projectPath, projectName2) {
616
+ const mainTs = `import { div, h1 } from 'elit/el';
617
+ import { render } from 'elit/dom';
618
+
619
+ // Create app
620
+ export const app = div(
621
+ h1('Hello Elit! \u{1F44B}')
622
+ );
623
+
624
+ render('root', app);
625
+ console.log('[Main] App rendered');
626
+ `;
627
+ await writeFile(join(projectPath, "src", "main.ts"), mainTs);
628
+ const clientTs = `import { div, html, head, body, title, meta, script } from 'elit/el';
629
+
630
+ export const client = html(
631
+ head(
632
+ title('${projectName2}'),
633
+ meta({ charset: 'UTF-8' }),
634
+ meta({ name: 'viewport', content: 'width=device-width, initial-scale=1.0' })
635
+ ),
636
+ body(
637
+ div({ id: 'root' }),
638
+ script({ type: 'module', src: '/src/main.js' })
639
+ )
640
+ );
641
+ `;
642
+ await writeFile(join(projectPath, "src", "client.ts"), clientTs);
643
+ const serverTs = `import { ServerRouter } from 'elit/server';
644
+
645
+ export const router = new ServerRouter();
646
+
647
+ // Add your API routes here
648
+ // Example:
649
+ // router.get('/api/hello', async (ctx) => {
650
+ // ctx.res.setHeader('Content-Type', 'application/json');
651
+ // ctx.res.end(JSON.stringify({ message: 'Hello!' }));
652
+ // });
653
+
654
+ export const server = router;
655
+ `;
656
+ await writeFile(join(projectPath, "src", "server.ts"), serverTs);
657
+ }
658
+ var projectName = getProjectName();
659
+ var template = getTemplate();
660
+ log("\n\u{1F680} Create Elit App\n", "cyan");
661
+ createProject(projectName, template).catch((err) => {
662
+ log(`Error: ${err.message}`, "red");
663
+ process.exit(1);
664
+ });
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "create-elit",
3
+ "version": "3.0.0",
4
+ "description": "Scaffolding tool for creating Elit projects",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-elit": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "templates"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup",
15
+ "dev": "tsup --watch"
16
+ },
17
+ "keywords": [
18
+ "create-elit",
19
+ "elit",
20
+ "scaffolding",
21
+ "cli",
22
+ "template",
23
+ "boilerplate"
24
+ ],
25
+ "author": "",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/d-osc/elit.git",
30
+ "directory": "packages/create-elit"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/d-osc/elit/issues"
34
+ },
35
+ "homepage": "https://d-osc.github.io/elit/",
36
+ "devDependencies": {
37
+ "tsup": "^8.0.0",
38
+ "typescript": "^5.3.0"
39
+ }
40
+ }