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.
- package/dist/index.js +37 -319
- 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
|
-
|
|
30
|
-
|
|
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) => {
|