create-elit 3.2.6 → 3.2.7

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 (2) hide show
  1. package/dist/index.js +37 -319
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,9 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { mkdir, writeFile } from "fs/promises";
5
- import { join, resolve } from "path";
4
+ import { mkdir, writeFile, readFile, readdir } from "fs/promises";
5
+ import { join, resolve, dirname } from "path";
6
6
  import { existsSync } from "fs";
7
+ import { fileURLToPath } from "url";
8
+ var __filename = fileURLToPath(import.meta.url);
9
+ var __dirname = dirname(__filename);
10
+ async function getElitVersion() {
11
+ const packageJsonPath = resolve(__dirname, "../package.json");
12
+ const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
13
+ return packageJson.version;
14
+ }
7
15
  var colors = {
8
16
  reset: "\x1B[0m",
9
17
  cyan: "\x1B[36m",
@@ -19,15 +27,40 @@ function getProjectName() {
19
27
  const args = process.argv.slice(2);
20
28
  return args[0] || "my-elit-app";
21
29
  }
30
+ async function copyDirectory(src, dest, replacements) {
31
+ await mkdir(dest, { recursive: true });
32
+ const entries = await readdir(src, { withFileTypes: true });
33
+ for (const entry of entries) {
34
+ const srcPath = join(src, entry.name);
35
+ const destPath = join(dest, entry.name);
36
+ if (entry.isDirectory()) {
37
+ await copyDirectory(srcPath, destPath, replacements);
38
+ } else {
39
+ await copyAndReplaceFile(srcPath, destPath, replacements);
40
+ }
41
+ }
42
+ }
43
+ async function copyAndReplaceFile(src, dest, replacements) {
44
+ let content = await readFile(src, "utf-8");
45
+ for (const [placeholder, value] of Object.entries(replacements)) {
46
+ content = content.split(placeholder).join(value);
47
+ }
48
+ await writeFile(dest, content, "utf-8");
49
+ }
22
50
  async function createProject(projectName2) {
23
51
  const projectPath = resolve(process.cwd(), projectName2);
52
+ const templatesPath = resolve(__dirname, "templates");
24
53
  if (existsSync(projectPath)) {
25
54
  log(`Error: Directory "${projectName2}" already exists!`, "red");
26
55
  process.exit(1);
27
56
  }
28
57
  log(`Creating a new Elit app in ${projectPath}...`, "cyan");
29
- await mkdir(projectPath, { recursive: true });
30
- await generateTemplate(projectPath, projectName2);
58
+ const elitVersion = await getElitVersion();
59
+ const replacements = {
60
+ "ELIT_PROJECT_NAME": projectName2,
61
+ "ELIT_VERSION": elitVersion
62
+ };
63
+ await copyDirectory(templatesPath, projectPath, replacements);
31
64
  log("\nSuccess! Created " + projectName2, "green");
32
65
  log("\nInside that directory, you can run several commands:", "dim");
33
66
  log("\n npm run dev", "cyan");
@@ -42,321 +75,6 @@ async function createProject(projectName2) {
42
75
  log(" npm run dev\n", "cyan");
43
76
  log("Happy coding! \u{1F680}", "green");
44
77
  }
45
- async function generateTemplate(projectPath, projectName2) {
46
- const packageJson = {
47
- name: projectName2,
48
- version: "0.0.0",
49
- type: "module",
50
- scripts: {
51
- dev: "elit dev",
52
- build: "elit build",
53
- preview: "elit preview"
54
- },
55
- dependencies: {
56
- elit: "^3.2.6"
57
- }
58
- };
59
- await writeFile(
60
- join(projectPath, "package.json"),
61
- JSON.stringify(packageJson, null, 2)
62
- );
63
- const tsConfig = {
64
- compilerOptions: {
65
- target: "ES2020",
66
- module: "ESNext",
67
- moduleResolution: "bundler",
68
- lib: ["ES2020", "DOM", "DOM.Iterable"],
69
- strict: true,
70
- esModuleInterop: true,
71
- skipLibCheck: true,
72
- resolveJsonModule: true,
73
- isolatedModules: true,
74
- types: ["node"]
75
- },
76
- include: ["src"]
77
- };
78
- await writeFile(
79
- join(projectPath, "tsconfig.json"),
80
- JSON.stringify(tsConfig, null, 2)
81
- );
82
- const gitignore = `node_modules
83
- dist
84
- .env
85
- .env.local
86
- *.log
87
- .DS_Store
88
- `;
89
- await writeFile(join(projectPath, ".gitignore"), gitignore);
90
- const readme = `# ${projectName2}
91
-
92
- A new Elit project created with create-elit.
93
-
94
- ## Getting Started
95
-
96
- \`\`\`bash
97
- npm install
98
- npm run dev
99
- \`\`\`
100
-
101
- Visit http://localhost:3000 to view your app.
102
-
103
- ## Available Scripts
104
-
105
- - \`npm run dev\` - Start development server with HMR
106
- - \`npm run build\` - Build for production
107
- - \`npm run preview\` - Preview production build
108
-
109
- ## Learn More
110
-
111
- - [Elit Documentation](https://d-osc.github.io/elit)
112
- - [GitHub Repository](https://github.com/d-osc/elit)
113
- `;
114
- await writeFile(join(projectPath, "README.md"), readme);
115
- const elitConfig = `import { server } from './src/server';
116
- import { client } from './src/client';
117
-
118
- export default {
119
- dev: {
120
- port: 3000,
121
- host: 'localhost',
122
- open: true,
123
- logging: true,
124
- clients: [{
125
- root: '.',
126
- basePath: '',
127
- ssr: () => client,
128
- api: server
129
- }]
130
- },
131
- build: [{
132
- entry: './src/main.ts',
133
- outDir: './dist',
134
- outFile: 'main.js',
135
- format: 'esm',
136
- minify: true,
137
- sourcemap: true,
138
- target: 'es2020',
139
- copy: [
140
- { from: './public/index.html', to: './index.html' }
141
- ]
142
- }],
143
- preview: {
144
- port: 3000,
145
- host: 'localhost',
146
- open: false,
147
- logging: true,
148
- root: './dist',
149
- basePath: '',
150
- index: './index.html'
151
- }
152
- };
153
- `;
154
- await writeFile(join(projectPath, "elit.config.ts"), elitConfig);
155
- await mkdir(join(projectPath, "public"), { recursive: true });
156
- const indexHtml = `<!DOCTYPE html>
157
- <html lang="en">
158
- <head>
159
- <meta charset="UTF-8">
160
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
161
- <title>${projectName2}</title>
162
- <link rel="icon" type="image/svg+xml" href="favicon.svg">
163
- <meta name="description" content="Built with Elit - Full-stack TypeScript framework">
164
- </head>
165
- <body>
166
- <div id="root"></div>
167
- <script type="module" src="/main.js"></script>
168
- </body>
169
- </html>
170
- `;
171
- await writeFile(join(projectPath, "public", "index.html"), indexHtml);
172
- await mkdir(join(projectPath, "src"), { recursive: true });
173
- const mainTs = `import { div, h1, h2, button, p } from 'elit/el';
174
- import { createState, reactive } from 'elit/state';
175
- import { render } from 'elit/dom';
176
- import './styles.ts';
177
-
178
- // Create reactive state
179
- export const count = createState(0);
180
-
181
- // Create app
182
- export const app = div({ className: 'container' },
183
- div({ className: 'card' },
184
- h1('Welcome to Elit! \u{1F680}'),
185
- p('A lightweight TypeScript framework with reactive state management'),
186
-
187
- div({ className: 'counter' },
188
- h2('Counter Example'),
189
- reactive(count, (value) =>
190
- div({ className: 'count-display' }, \`Count: \${value}\`)
191
- ),
192
- div({ className: 'button-group' },
193
- button({
194
- onclick: () => count.value--,
195
- className: 'btn btn-secondary'
196
- }, '- Decrement'),
197
- button({
198
- onclick: () => count.value = 0,
199
- className: 'btn btn-secondary'
200
- }, 'Reset'),
201
- button({
202
- onclick: () => count.value++,
203
- className: 'btn btn-primary'
204
- }, '+ Increment')
205
- )
206
- )
207
- )
208
- );
209
-
210
- render('root', app);
211
- console.log('[Main] App rendered');
212
- `;
213
- await writeFile(join(projectPath, "src", "main.ts"), mainTs);
214
- const stylesTs = `import styles from 'elit/style';
215
-
216
- // Global styles
217
- styles.addTag('*', {
218
- margin: 0,
219
- padding: 0,
220
- boxSizing: 'border-box'
221
- });
222
-
223
- styles.addTag('body', {
224
- fontFamily: 'system-ui, -apple-system, sans-serif',
225
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
226
- minHeight: '100vh',
227
- display: 'flex',
228
- alignItems: 'center',
229
- justifyContent: 'center',
230
- padding: '2rem'
231
- });
232
-
233
- // Container
234
- styles.addClass('container', {
235
- width: '100%',
236
- maxWidth: '600px'
237
- });
238
-
239
- // Card
240
- styles.addClass('card', {
241
- background: 'white',
242
- borderRadius: '16px',
243
- padding: '3rem',
244
- boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)'
245
- });
246
-
247
- // Typography
248
- styles.addTag('h1', {
249
- fontSize: '2.5rem',
250
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
251
- WebkitBackgroundClip: 'text',
252
- WebkitTextFillColor: 'transparent',
253
- backgroundClip: 'text',
254
- marginBottom: '1rem'
255
- });
256
-
257
- styles.addTag('h2', {
258
- fontSize: '1.5rem',
259
- color: '#333',
260
- marginBottom: '1rem'
261
- });
262
-
263
- styles.addTag('p', {
264
- color: '#666',
265
- marginBottom: '2rem',
266
- lineHeight: 1.6
267
- });
268
-
269
- // Counter section
270
- styles.addClass('counter', {
271
- marginTop: '2rem',
272
- paddingTop: '2rem',
273
- borderTop: '2px solid #f0f0f0'
274
- });
275
-
276
- styles.addClass('count-display', {
277
- fontSize: '3rem',
278
- fontWeight: 'bold',
279
- color: '#667eea',
280
- textAlign: 'center',
281
- margin: '2rem 0'
282
- });
283
-
284
- // Button group
285
- styles.addClass('button-group', {
286
- display: 'flex',
287
- gap: '1rem',
288
- justifyContent: 'center'
289
- });
290
-
291
- // Buttons
292
- styles.addClass('btn', {
293
- padding: '0.75rem 1.5rem',
294
- border: 'none',
295
- borderRadius: '8px',
296
- fontSize: '1rem',
297
- fontWeight: 600,
298
- cursor: 'pointer',
299
- transition: 'all 0.2s'
300
- });
301
-
302
- styles.addClass('btn-primary', {
303
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
304
- color: 'white'
305
- });
306
-
307
- styles.addPseudoClass('hover', {
308
- transform: 'translateY(-2px)',
309
- boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)'
310
- }, '.btn-primary');
311
-
312
- styles.addClass('btn-secondary', {
313
- background: '#f0f0f0',
314
- color: '#333'
315
- });
316
-
317
- styles.addPseudoClass('hover', {
318
- background: '#e0e0e0',
319
- transform: 'translateY(-2px)'
320
- }, '.btn-secondary');
321
-
322
- styles.addPseudoClass('active', {
323
- transform: 'translateY(0)'
324
- }, '.btn');
325
-
326
- styles.inject('global-styles');
327
- export default styles;
328
- `;
329
- await writeFile(join(projectPath, "src", "styles.ts"), stylesTs);
330
- const clientTs = `import { div, html, head, body, title, link, script, meta } from 'elit/el';
331
-
332
- export const client = html(
333
- head(
334
- title('${projectName2} - Elit App'),
335
- link({ rel: 'icon', type: 'image/svg+xml', href: 'favicon.svg' }),
336
- meta({ charset: 'UTF-8' }),
337
- meta({ name: 'viewport', content: 'width=device-width, initial-scale=1.0' }),
338
- meta({ name: 'description', content: 'Elit - Full-stack TypeScript framework with dev server, HMR, routing, SSR, and REST API.' })
339
- ),
340
- body(
341
- div({ id: 'root' }),
342
- script({ type: 'module', src: '/src/main.js' })
343
- )
344
- );
345
- `;
346
- await writeFile(join(projectPath, "src", "client.ts"), clientTs);
347
- const serverTs = `import { ServerRouter } from 'elit/server';
348
-
349
- export const router = new ServerRouter();
350
-
351
- router.get('/api/hello', async (ctx) => {
352
- ctx.res.setHeader('Content-Type', 'application/json');
353
- ctx.res.end(JSON.stringify({ message: 'Hello from Elit ServerRouter!' }));
354
- });
355
-
356
- export const server = router;
357
- `;
358
- await writeFile(join(projectPath, "src", "server.ts"), serverTs);
359
- }
360
78
  var projectName = getProjectName();
361
79
  log("\n\u{1F680} Create Elit App\n", "cyan");
362
80
  createProject(projectName).catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-elit",
3
- "version": "3.2.6",
3
+ "version": "3.2.7",
4
4
  "description": "Scaffolding tool for creating Elit projects",
5
5
  "type": "module",
6
6
  "bin": {