elit 3.0.1 → 3.0.3
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/build.d.ts +4 -12
- package/dist/build.d.ts.map +1 -0
- package/dist/chokidar.d.ts +7 -9
- package/dist/chokidar.d.ts.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +250 -21
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/dom.d.ts +7 -14
- package/dist/dom.d.ts.map +1 -0
- package/dist/el.d.ts +19 -191
- package/dist/el.d.ts.map +1 -0
- package/dist/fs.d.ts +35 -35
- package/dist/fs.d.ts.map +1 -0
- package/dist/hmr.d.ts +3 -3
- package/dist/hmr.d.ts.map +1 -0
- package/dist/http.d.ts +20 -22
- package/dist/http.d.ts.map +1 -0
- package/dist/https.d.ts +12 -15
- package/dist/https.d.ts.map +1 -0
- package/dist/index.d.ts +10 -629
- package/dist/index.d.ts.map +1 -0
- package/dist/mime-types.d.ts +9 -9
- package/dist/mime-types.d.ts.map +1 -0
- package/dist/path.d.ts +22 -19
- package/dist/path.d.ts.map +1 -0
- package/dist/router.d.ts +10 -17
- package/dist/router.d.ts.map +1 -0
- package/dist/runtime.d.ts +5 -6
- package/dist/runtime.d.ts.map +1 -0
- package/dist/server.d.ts +109 -7
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +712 -137
- package/dist/server.mjs +711 -137
- package/dist/state.d.ts +21 -27
- package/dist/state.d.ts.map +1 -0
- package/dist/style.d.ts +14 -55
- package/dist/style.d.ts.map +1 -0
- package/dist/types.d.ts +26 -240
- package/dist/types.d.ts.map +1 -0
- package/dist/ws.d.ts +14 -17
- package/dist/ws.d.ts.map +1 -0
- package/dist/wss.d.ts +16 -16
- package/dist/wss.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/build.ts +337 -0
- package/src/chokidar.ts +401 -0
- package/src/cli.ts +638 -0
- package/src/config.ts +205 -0
- package/src/dom.ts +817 -0
- package/src/el.ts +164 -0
- package/src/fs.ts +727 -0
- package/src/hmr.ts +137 -0
- package/src/http.ts +775 -0
- package/src/https.ts +411 -0
- package/src/index.ts +14 -0
- package/src/mime-types.ts +222 -0
- package/src/path.ts +493 -0
- package/src/router.ts +237 -0
- package/src/runtime.ts +97 -0
- package/src/server.ts +1593 -0
- package/src/state.ts +468 -0
- package/src/style.ts +524 -0
- package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
- package/src/ws.ts +506 -0
- package/src/wss.ts +241 -0
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -207
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -163
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -629
- package/dist/mime-types.d.mts +0 -48
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -47
- package/dist/runtime.d.mts +0 -97
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -111
- package/dist/style.d.mts +0 -159
- package/dist/types-C0nGi6MX.d.mts +0 -346
- package/dist/types.d.mts +0 -452
- package/dist/ws.d.mts +0 -195
- package/dist/wss.d.mts +0 -108
package/src/cli.ts
ADDED
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Main CLI for Elit
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { loadConfig, mergeConfig, loadEnv } from './config';
|
|
7
|
+
import { createDevServer } from './server';
|
|
8
|
+
import { build } from './build';
|
|
9
|
+
import type { DevServerOptions, BuildOptions, PreviewOptions } from './types';
|
|
10
|
+
|
|
11
|
+
const COMMANDS = ['dev', 'build', 'preview', 'help', 'version'] as const;
|
|
12
|
+
type Command = typeof COMMANDS[number];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Helper: Setup graceful shutdown handlers (eliminates duplication in runDev and runPreview)
|
|
16
|
+
*/
|
|
17
|
+
function setupShutdownHandlers(closeFunc: () => Promise<void>): void {
|
|
18
|
+
const shutdown = async () => {
|
|
19
|
+
console.log('\n[Server] Shutting down...');
|
|
20
|
+
await closeFunc();
|
|
21
|
+
process.exit(0);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
process.on('SIGINT', shutdown);
|
|
25
|
+
process.on('SIGTERM', shutdown);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Helper: Execute build with error handling (eliminates duplication in runBuild)
|
|
30
|
+
*/
|
|
31
|
+
async function executeBuild(options: BuildOptions): Promise<void> {
|
|
32
|
+
try {
|
|
33
|
+
await build(options);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Helper: Validate entry file (eliminates duplication in runBuild)
|
|
41
|
+
*/
|
|
42
|
+
function validateEntry(entry: string | undefined, buildIndex?: number): void {
|
|
43
|
+
if (!entry) {
|
|
44
|
+
if (buildIndex !== undefined) {
|
|
45
|
+
console.error(`Error: Entry file is required for build #${buildIndex + 1}`);
|
|
46
|
+
} else {
|
|
47
|
+
console.error('Error: Entry file is required');
|
|
48
|
+
console.error('Specify in config file or use --entry <file>');
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Helper: Ensure env is set (eliminates duplication in runBuild)
|
|
56
|
+
*/
|
|
57
|
+
function ensureEnv(options: BuildOptions, env: Record<string, string>): void {
|
|
58
|
+
if (!options.env) {
|
|
59
|
+
options.env = env;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Helper: Generic argument parser (eliminates duplication in parseDevArgs, parseBuildArgs, parsePreviewArgs)
|
|
65
|
+
*/
|
|
66
|
+
type ArgHandler<T> = (options: T, value: string, index: { current: number }) => void;
|
|
67
|
+
|
|
68
|
+
function parseArgs<T>(args: string[], handlers: Record<string, ArgHandler<T>>, options: T): T {
|
|
69
|
+
for (let i = 0; i < args.length; i++) {
|
|
70
|
+
const arg = args[i];
|
|
71
|
+
const handler = handlers[arg];
|
|
72
|
+
if (handler) {
|
|
73
|
+
const index = { current: i };
|
|
74
|
+
handler(options, args[i + 1], index);
|
|
75
|
+
i = index.current;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return options;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function main() {
|
|
82
|
+
const args = process.argv.slice(2);
|
|
83
|
+
const command = (args[0] as Command) || 'help';
|
|
84
|
+
|
|
85
|
+
if (!COMMANDS.includes(command)) {
|
|
86
|
+
console.error(`Unknown command: ${command}`);
|
|
87
|
+
printHelp();
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
switch (command) {
|
|
92
|
+
case 'dev':
|
|
93
|
+
await runDev(args.slice(1));
|
|
94
|
+
break;
|
|
95
|
+
case 'build':
|
|
96
|
+
await runBuild(args.slice(1));
|
|
97
|
+
break;
|
|
98
|
+
case 'preview':
|
|
99
|
+
await runPreview(args.slice(1));
|
|
100
|
+
break;
|
|
101
|
+
case 'version':
|
|
102
|
+
printVersion();
|
|
103
|
+
break;
|
|
104
|
+
case 'help':
|
|
105
|
+
default:
|
|
106
|
+
printHelp();
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function runDev(args: string[]) {
|
|
112
|
+
const cliOptions = parseDevArgs(args);
|
|
113
|
+
const config = await loadConfig();
|
|
114
|
+
|
|
115
|
+
const options = config?.dev
|
|
116
|
+
? mergeConfig(config.dev, cliOptions)
|
|
117
|
+
: cliOptions as DevServerOptions;
|
|
118
|
+
|
|
119
|
+
// Ensure we have at least root or clients
|
|
120
|
+
if (!options.root && (!options.clients || options.clients.length === 0)) {
|
|
121
|
+
options.root = process.cwd();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Set mode to 'dev' for dev command
|
|
125
|
+
options.mode = 'dev';
|
|
126
|
+
|
|
127
|
+
const devServer = createDevServer(options);
|
|
128
|
+
|
|
129
|
+
// Handle graceful shutdown
|
|
130
|
+
setupShutdownHandlers(() => devServer.close());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function runBuild(args: string[]) {
|
|
134
|
+
const cliOptions = parseBuildArgs(args);
|
|
135
|
+
const config = await loadConfig();
|
|
136
|
+
|
|
137
|
+
// Load environment variables
|
|
138
|
+
const mode = process.env.MODE || 'production';
|
|
139
|
+
const env = loadEnv(mode);
|
|
140
|
+
|
|
141
|
+
// Check if config has build array or single build
|
|
142
|
+
if (config?.build) {
|
|
143
|
+
const builds = Array.isArray(config.build) ? config.build : [config.build];
|
|
144
|
+
|
|
145
|
+
// If CLI options provided, merge with first build or use as standalone
|
|
146
|
+
if (Object.keys(cliOptions).length > 0) {
|
|
147
|
+
const options = mergeConfig(builds[0] || {}, cliOptions) as BuildOptions;
|
|
148
|
+
|
|
149
|
+
ensureEnv(options, env);
|
|
150
|
+
validateEntry(options.entry);
|
|
151
|
+
|
|
152
|
+
await executeBuild(options);
|
|
153
|
+
} else {
|
|
154
|
+
// Run all builds from config
|
|
155
|
+
console.log(`Building ${builds.length} ${builds.length === 1 ? 'entry' : 'entries'}...\n`);
|
|
156
|
+
|
|
157
|
+
for (let i = 0; i < builds.length; i++) {
|
|
158
|
+
const buildConfig = builds[i];
|
|
159
|
+
|
|
160
|
+
ensureEnv(buildConfig, env);
|
|
161
|
+
validateEntry(buildConfig.entry, i);
|
|
162
|
+
|
|
163
|
+
console.log(`[${i + 1}/${builds.length}] Building ${buildConfig.entry}...`);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
await build(buildConfig);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error(`Build #${i + 1} failed`);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (i < builds.length - 1) {
|
|
173
|
+
console.log(''); // Empty line between builds
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log(`\n✓ All ${builds.length} builds completed successfully`);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
// No config, use CLI options only
|
|
181
|
+
const options = cliOptions as BuildOptions;
|
|
182
|
+
|
|
183
|
+
ensureEnv(options, env);
|
|
184
|
+
validateEntry(options.entry);
|
|
185
|
+
|
|
186
|
+
await executeBuild(options);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function runPreview(args: string[]) {
|
|
191
|
+
const cliOptions = parsePreviewArgs(args);
|
|
192
|
+
const config = await loadConfig();
|
|
193
|
+
|
|
194
|
+
const previewConfig = config?.preview || {};
|
|
195
|
+
const mergedOptions: PreviewOptions = {
|
|
196
|
+
...previewConfig,
|
|
197
|
+
...Object.fromEntries(
|
|
198
|
+
Object.entries(cliOptions).filter(([_, v]) => v !== undefined)
|
|
199
|
+
)
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Build DevServerOptions from PreviewOptions
|
|
203
|
+
const options: DevServerOptions = {
|
|
204
|
+
port: mergedOptions.port || 4173,
|
|
205
|
+
host: mergedOptions.host || 'localhost',
|
|
206
|
+
open: mergedOptions.open ?? true,
|
|
207
|
+
logging: mergedOptions.logging ?? true
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// Support both single root and clients array
|
|
211
|
+
if (mergedOptions.clients && mergedOptions.clients.length > 0) {
|
|
212
|
+
options.clients = mergedOptions.clients;
|
|
213
|
+
console.log('Starting preview server with multiple clients...');
|
|
214
|
+
console.log(` Clients: ${mergedOptions.clients.length}`);
|
|
215
|
+
mergedOptions.clients.forEach((client, i) => {
|
|
216
|
+
console.log(` ${i + 1}. ${client.basePath} -> ${client.root}`);
|
|
217
|
+
});
|
|
218
|
+
} else {
|
|
219
|
+
// Get outDir from build config (use first build if array)
|
|
220
|
+
const buildConfig = config?.build;
|
|
221
|
+
const defaultOutDir = Array.isArray(buildConfig) ? buildConfig[0]?.outDir : buildConfig?.outDir;
|
|
222
|
+
|
|
223
|
+
options.root = mergedOptions.root || defaultOutDir || 'dist';
|
|
224
|
+
options.basePath = mergedOptions.basePath;
|
|
225
|
+
options.index = mergedOptions.index;
|
|
226
|
+
console.log('Starting preview server...');
|
|
227
|
+
console.log(` Root: ${options.root}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Add global proxy if configured
|
|
231
|
+
if (mergedOptions.proxy && mergedOptions.proxy.length > 0) {
|
|
232
|
+
options.proxy = mergedOptions.proxy;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Add global worker if configured
|
|
236
|
+
if (mergedOptions.worker && mergedOptions.worker.length > 0) {
|
|
237
|
+
options.worker = mergedOptions.worker;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Add API router if configured
|
|
241
|
+
if (mergedOptions.api) {
|
|
242
|
+
options.api = mergedOptions.api;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Add HTTPS if configured
|
|
246
|
+
if (mergedOptions.https) {
|
|
247
|
+
options.https = mergedOptions.https;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Add middleware if configured
|
|
251
|
+
if (mergedOptions.middleware) {
|
|
252
|
+
options.middleware = mergedOptions.middleware;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Add SSR if configured
|
|
256
|
+
if (mergedOptions.ssr) {
|
|
257
|
+
options.ssr = mergedOptions.ssr;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Set mode to 'preview' for preview command
|
|
261
|
+
options.mode = 'preview';
|
|
262
|
+
|
|
263
|
+
const devServer = createDevServer(options);
|
|
264
|
+
|
|
265
|
+
setupShutdownHandlers(() => devServer.close());
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function parseDevArgs(args: string[]): Partial<DevServerOptions> {
|
|
269
|
+
const options: Partial<DevServerOptions> = {};
|
|
270
|
+
|
|
271
|
+
const handlers: Record<string, ArgHandler<Partial<DevServerOptions>>> = {
|
|
272
|
+
'-p': (opts, value, index) => { opts.port = parseInt(value, 10); index.current++; },
|
|
273
|
+
'--port': (opts, value, index) => { opts.port = parseInt(value, 10); index.current++; },
|
|
274
|
+
'-h': (opts, value, index) => { opts.host = value; index.current++; },
|
|
275
|
+
'--host': (opts, value, index) => { opts.host = value; index.current++; },
|
|
276
|
+
'-r': (opts, value, index) => { opts.root = value; index.current++; },
|
|
277
|
+
'--root': (opts, value, index) => { opts.root = value; index.current++; },
|
|
278
|
+
'--no-open': (opts) => { opts.open = false; },
|
|
279
|
+
'--silent': (opts) => { opts.logging = false; },
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
return parseArgs(args, handlers, options);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function parseBuildArgs(args: string[]): Partial<BuildOptions> {
|
|
286
|
+
const options: Partial<BuildOptions> = {};
|
|
287
|
+
|
|
288
|
+
const handlers: Record<string, ArgHandler<Partial<BuildOptions>>> = {
|
|
289
|
+
'-e': (opts, value, index) => { opts.entry = value; index.current++; },
|
|
290
|
+
'--entry': (opts, value, index) => { opts.entry = value; index.current++; },
|
|
291
|
+
'-o': (opts, value, index) => { opts.outDir = value; index.current++; },
|
|
292
|
+
'--out-dir': (opts, value, index) => { opts.outDir = value; index.current++; },
|
|
293
|
+
'--no-minify': (opts) => { opts.minify = false; },
|
|
294
|
+
'--sourcemap': (opts) => { opts.sourcemap = true; },
|
|
295
|
+
'-f': (opts, value, index) => { opts.format = value as BuildOptions['format']; index.current++; },
|
|
296
|
+
'--format': (opts, value, index) => { opts.format = value as BuildOptions['format']; index.current++; },
|
|
297
|
+
'--silent': (opts) => { opts.logging = false; },
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
return parseArgs(args, handlers, options);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function parsePreviewArgs(args: string[]): Partial<{ port: number; host: string; root: string; basePath: string; open: boolean; logging: boolean }> {
|
|
304
|
+
const options: Partial<{ port: number; host: string; root: string; basePath: string; open: boolean; logging: boolean }> = {};
|
|
305
|
+
|
|
306
|
+
type PreviewOptions = { port: number; host: string; root: string; basePath: string; open: boolean; logging: boolean };
|
|
307
|
+
|
|
308
|
+
const handlers: Record<string, ArgHandler<Partial<PreviewOptions>>> = {
|
|
309
|
+
'-p': (opts, value, index) => { opts.port = parseInt(value, 10); index.current++; },
|
|
310
|
+
'--port': (opts, value, index) => { opts.port = parseInt(value, 10); index.current++; },
|
|
311
|
+
'-h': (opts, value, index) => { opts.host = value; index.current++; },
|
|
312
|
+
'--host': (opts, value, index) => { opts.host = value; index.current++; },
|
|
313
|
+
'-r': (opts, value, index) => { opts.root = value; index.current++; },
|
|
314
|
+
'--root': (opts, value, index) => { opts.root = value; index.current++; },
|
|
315
|
+
'-b': (opts, value, index) => { opts.basePath = value; index.current++; },
|
|
316
|
+
'--base-path': (opts, value, index) => { opts.basePath = value; index.current++; },
|
|
317
|
+
'--no-open': (opts) => { opts.open = false; },
|
|
318
|
+
'--silent': (opts) => { opts.logging = false; },
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
return parseArgs(args, handlers, options);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function printHelp() {
|
|
325
|
+
console.log(`
|
|
326
|
+
Elit - Modern Web Development Toolkit
|
|
327
|
+
|
|
328
|
+
Usage:
|
|
329
|
+
elit <command> [options]
|
|
330
|
+
|
|
331
|
+
Commands:
|
|
332
|
+
dev Start development server
|
|
333
|
+
build Build for production
|
|
334
|
+
preview Preview production build
|
|
335
|
+
version Show version number
|
|
336
|
+
help Show this help message
|
|
337
|
+
|
|
338
|
+
Dev Options:
|
|
339
|
+
-p, --port <number> Port to run server on (default: 3000)
|
|
340
|
+
-h, --host <string> Host to bind to (default: localhost)
|
|
341
|
+
-r, --root <path> Root directory to serve
|
|
342
|
+
--no-open Don't open browser automatically
|
|
343
|
+
--silent Disable logging
|
|
344
|
+
|
|
345
|
+
Build Options:
|
|
346
|
+
-e, --entry <file> Entry file to build (required)
|
|
347
|
+
-o, --out-dir <dir> Output directory (default: dist)
|
|
348
|
+
-f, --format <format> Output format: esm, cjs, iife (default: esm)
|
|
349
|
+
--no-minify Disable minification
|
|
350
|
+
--sourcemap Generate sourcemap
|
|
351
|
+
--silent Disable logging
|
|
352
|
+
|
|
353
|
+
Note: Build configuration supports both single and multiple builds:
|
|
354
|
+
- Single build: build: { entry: 'src/app.ts', outDir: 'dist' }
|
|
355
|
+
- Multiple builds: build: [{ entry: 'src/app1.ts' }, { entry: 'src/app2.ts' }]
|
|
356
|
+
When using array, all builds run sequentially.
|
|
357
|
+
|
|
358
|
+
Preview Options:
|
|
359
|
+
-p, --port <number> Port to run server on (default: 4173)
|
|
360
|
+
-h, --host <string> Host to bind to (default: localhost)
|
|
361
|
+
-r, --root <dir> Root directory to serve (default: dist or build.outDir)
|
|
362
|
+
-b, --base-path <path> Base path for the application
|
|
363
|
+
--no-open Don't open browser automatically
|
|
364
|
+
--silent Disable logging
|
|
365
|
+
|
|
366
|
+
Note: Preview mode has full feature parity with dev mode:
|
|
367
|
+
- Single root and multi-client configurations (use clients[] in config)
|
|
368
|
+
- REST API endpoints (use api option in config)
|
|
369
|
+
- Proxy forwarding and Web Workers
|
|
370
|
+
- HTTPS support, custom middleware, and SSR
|
|
371
|
+
|
|
372
|
+
Config File:
|
|
373
|
+
Create elit.config.ts, elit.config.js, or elit.config.json in project root
|
|
374
|
+
|
|
375
|
+
Proxy Configuration:
|
|
376
|
+
Configure proxy in the config file to forward requests to backend servers.
|
|
377
|
+
Supports both global proxy (applies to all clients) and client-specific proxy.
|
|
378
|
+
|
|
379
|
+
Options:
|
|
380
|
+
- context: Path prefix to match (required, e.g., '/api', '/graphql')
|
|
381
|
+
- target: Backend server URL (required, e.g., 'http://localhost:8080')
|
|
382
|
+
- changeOrigin: Change the origin header to match target (default: false)
|
|
383
|
+
- pathRewrite: Rewrite request paths (e.g., { '^/api': '/v1/api' })
|
|
384
|
+
- headers: Add custom headers to proxied requests
|
|
385
|
+
- ws: Enable WebSocket proxying (default: false)
|
|
386
|
+
|
|
387
|
+
Proxy Priority:
|
|
388
|
+
1. Client-specific proxy (defined in clients[].proxy)
|
|
389
|
+
2. Global proxy (defined in dev.proxy)
|
|
390
|
+
The first matching proxy configuration will be used.
|
|
391
|
+
|
|
392
|
+
Worker Configuration:
|
|
393
|
+
Configure Web Workers in the config file for background processing.
|
|
394
|
+
Supports both global workers (applies to all clients) and client-specific workers.
|
|
395
|
+
|
|
396
|
+
Options:
|
|
397
|
+
- path: Worker script path relative to root directory (required)
|
|
398
|
+
- name: Worker name/identifier (optional, defaults to filename)
|
|
399
|
+
- type: Worker type - 'module' (ESM) or 'classic' (default: 'module')
|
|
400
|
+
|
|
401
|
+
Worker Priority:
|
|
402
|
+
1. Client-specific workers (defined in clients[].worker)
|
|
403
|
+
2. Global workers (defined in dev.worker or preview.worker)
|
|
404
|
+
Both global and client-specific workers will be loaded.
|
|
405
|
+
|
|
406
|
+
API and Middleware Configuration:
|
|
407
|
+
Configure REST API endpoints and custom middleware per client or globally.
|
|
408
|
+
Supports both global configuration and client-specific configuration.
|
|
409
|
+
|
|
410
|
+
Client-specific API and Middleware:
|
|
411
|
+
- Each client can have its own API router (clients[].api)
|
|
412
|
+
- Each client can have its own middleware chain (clients[].middleware)
|
|
413
|
+
- Client-specific configuration is isolated to that client's routes
|
|
414
|
+
- API paths are automatically prefixed with the client's basePath
|
|
415
|
+
Example: If basePath is '/app1' and route is '/api/health',
|
|
416
|
+
the full path will be '/app1/api/health'
|
|
417
|
+
|
|
418
|
+
Priority:
|
|
419
|
+
1. Client-specific middleware runs first (defined in clients[].middleware)
|
|
420
|
+
2. Global middleware runs second (defined in dev.middleware or preview.middleware)
|
|
421
|
+
3. Client-specific API routes are matched (defined in clients[].api)
|
|
422
|
+
4. Global API routes are matched (defined in dev.api or preview.api)
|
|
423
|
+
|
|
424
|
+
Examples:
|
|
425
|
+
elit dev
|
|
426
|
+
elit dev --port 8080
|
|
427
|
+
elit build --entry src/app.ts
|
|
428
|
+
elit preview
|
|
429
|
+
elit preview --port 5000
|
|
430
|
+
|
|
431
|
+
Config file example (elit.config.ts):
|
|
432
|
+
export default {
|
|
433
|
+
dev: {
|
|
434
|
+
port: 3000,
|
|
435
|
+
clients: [
|
|
436
|
+
{
|
|
437
|
+
root: './app1',
|
|
438
|
+
basePath: '/app1',
|
|
439
|
+
proxy: [
|
|
440
|
+
{
|
|
441
|
+
context: '/api',
|
|
442
|
+
target: 'http://localhost:8080',
|
|
443
|
+
changeOrigin: true
|
|
444
|
+
}
|
|
445
|
+
],
|
|
446
|
+
worker: [
|
|
447
|
+
{
|
|
448
|
+
path: 'workers/data-processor.js',
|
|
449
|
+
name: 'dataProcessor',
|
|
450
|
+
type: 'module'
|
|
451
|
+
}
|
|
452
|
+
],
|
|
453
|
+
// API routes are prefixed with basePath
|
|
454
|
+
// This route becomes: /app1/api/health
|
|
455
|
+
api: router()
|
|
456
|
+
.get('/api/health', (req, res) => {
|
|
457
|
+
res.json({ status: 'ok', app: 'app1' });
|
|
458
|
+
}),
|
|
459
|
+
middleware: [
|
|
460
|
+
(req, res, next) => {
|
|
461
|
+
console.log('App1 middleware:', req.url);
|
|
462
|
+
next();
|
|
463
|
+
}
|
|
464
|
+
]
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
root: './app2',
|
|
468
|
+
basePath: '/app2',
|
|
469
|
+
proxy: [
|
|
470
|
+
{
|
|
471
|
+
context: '/graphql',
|
|
472
|
+
target: 'http://localhost:4000',
|
|
473
|
+
changeOrigin: true
|
|
474
|
+
}
|
|
475
|
+
],
|
|
476
|
+
worker: [
|
|
477
|
+
{
|
|
478
|
+
path: 'workers/image-worker.js',
|
|
479
|
+
type: 'module'
|
|
480
|
+
}
|
|
481
|
+
],
|
|
482
|
+
// API routes are prefixed with basePath
|
|
483
|
+
// This route becomes: /app2/api/status
|
|
484
|
+
api: router()
|
|
485
|
+
.get('/api/status', (req, res) => {
|
|
486
|
+
res.json({ status: 'running', app: 'app2' });
|
|
487
|
+
}),
|
|
488
|
+
middleware: [
|
|
489
|
+
(req, res, next) => {
|
|
490
|
+
console.log('App2 middleware:', req.url);
|
|
491
|
+
next();
|
|
492
|
+
}
|
|
493
|
+
]
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
// Global proxy (applies to all clients)
|
|
497
|
+
proxy: [
|
|
498
|
+
{
|
|
499
|
+
context: '/shared-api',
|
|
500
|
+
target: 'http://localhost:9000',
|
|
501
|
+
changeOrigin: true
|
|
502
|
+
}
|
|
503
|
+
],
|
|
504
|
+
// Global workers (applies to all clients)
|
|
505
|
+
worker: [
|
|
506
|
+
{
|
|
507
|
+
path: 'workers/shared-worker.js',
|
|
508
|
+
name: 'sharedWorker',
|
|
509
|
+
type: 'module'
|
|
510
|
+
}
|
|
511
|
+
]
|
|
512
|
+
},
|
|
513
|
+
// Single build configuration
|
|
514
|
+
build: {
|
|
515
|
+
entry: 'src/app.ts',
|
|
516
|
+
outDir: 'dist',
|
|
517
|
+
format: 'esm'
|
|
518
|
+
},
|
|
519
|
+
// Alternative: Multiple builds
|
|
520
|
+
// build: [
|
|
521
|
+
// {
|
|
522
|
+
// entry: 'src/app1.ts',
|
|
523
|
+
// outDir: 'dist/app1',
|
|
524
|
+
// outFile: 'app1.js',
|
|
525
|
+
// format: 'esm',
|
|
526
|
+
// minify: true
|
|
527
|
+
// },
|
|
528
|
+
// {
|
|
529
|
+
// entry: 'src/app2.ts',
|
|
530
|
+
// outDir: 'dist/app2',
|
|
531
|
+
// outFile: 'app2.js',
|
|
532
|
+
// format: 'esm',
|
|
533
|
+
// minify: true
|
|
534
|
+
// },
|
|
535
|
+
// {
|
|
536
|
+
// entry: 'src/worker.ts',
|
|
537
|
+
// outDir: 'dist/workers',
|
|
538
|
+
// outFile: 'worker.js',
|
|
539
|
+
// format: 'esm',
|
|
540
|
+
// platform: 'browser'
|
|
541
|
+
// }
|
|
542
|
+
// ],
|
|
543
|
+
preview: {
|
|
544
|
+
port: 4173,
|
|
545
|
+
// Single client preview
|
|
546
|
+
root: 'dist',
|
|
547
|
+
basePath: '/app',
|
|
548
|
+
https: false,
|
|
549
|
+
// API router (import from elit/server)
|
|
550
|
+
api: router()
|
|
551
|
+
.get('/api/data', (req, res) => {
|
|
552
|
+
res.json({ message: 'Hello from preview API' });
|
|
553
|
+
}),
|
|
554
|
+
// Custom middleware
|
|
555
|
+
middleware: [
|
|
556
|
+
(req, res, next) => {
|
|
557
|
+
console.log('Preview request:', req.url);
|
|
558
|
+
next();
|
|
559
|
+
}
|
|
560
|
+
],
|
|
561
|
+
// SSR render function
|
|
562
|
+
ssr: () => '<h1>Server-rendered content</h1>',
|
|
563
|
+
proxy: [
|
|
564
|
+
{
|
|
565
|
+
context: '/api',
|
|
566
|
+
target: 'http://localhost:8080'
|
|
567
|
+
}
|
|
568
|
+
],
|
|
569
|
+
worker: [
|
|
570
|
+
{
|
|
571
|
+
path: 'workers/cache-worker.js',
|
|
572
|
+
type: 'module'
|
|
573
|
+
}
|
|
574
|
+
]
|
|
575
|
+
// Multi-client preview (alternative)
|
|
576
|
+
// clients: [
|
|
577
|
+
// {
|
|
578
|
+
// root: './dist/app1',
|
|
579
|
+
// basePath: '/app1',
|
|
580
|
+
// proxy: [
|
|
581
|
+
// {
|
|
582
|
+
// context: '/api',
|
|
583
|
+
// target: 'http://localhost:8080'
|
|
584
|
+
// }
|
|
585
|
+
// ],
|
|
586
|
+
// worker: [
|
|
587
|
+
// {
|
|
588
|
+
// path: 'workers/app1-worker.js',
|
|
589
|
+
// type: 'module'
|
|
590
|
+
// }
|
|
591
|
+
// ],
|
|
592
|
+
// api: router()
|
|
593
|
+
// .get('/api/health', (req, res) => {
|
|
594
|
+
// res.json({ status: 'ok', app: 'app1' });
|
|
595
|
+
// }),
|
|
596
|
+
// middleware: [
|
|
597
|
+
// (req, res, next) => {
|
|
598
|
+
// console.log('App1 request:', req.url);
|
|
599
|
+
// next();
|
|
600
|
+
// }
|
|
601
|
+
// ]
|
|
602
|
+
// },
|
|
603
|
+
// {
|
|
604
|
+
// root: './dist/app2',
|
|
605
|
+
// basePath: '/app2',
|
|
606
|
+
// worker: [
|
|
607
|
+
// {
|
|
608
|
+
// path: 'workers/app2-worker.js',
|
|
609
|
+
// type: 'module'
|
|
610
|
+
// }
|
|
611
|
+
// ],
|
|
612
|
+
// api: router()
|
|
613
|
+
// .get('/api/status', (req, res) => {
|
|
614
|
+
// res.json({ status: 'running', app: 'app2' });
|
|
615
|
+
// }),
|
|
616
|
+
// middleware: [
|
|
617
|
+
// (req, res, next) => {
|
|
618
|
+
// console.log('App2 request:', req.url);
|
|
619
|
+
// next();
|
|
620
|
+
// }
|
|
621
|
+
// ]
|
|
622
|
+
// }
|
|
623
|
+
// ]
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
`);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function printVersion() {
|
|
630
|
+
const pkg = require('../package.json');
|
|
631
|
+
console.log(`elit v${pkg.version}`);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Run CLI
|
|
635
|
+
main().catch((error) => {
|
|
636
|
+
console.error('Fatal error:', error);
|
|
637
|
+
process.exit(1);
|
|
638
|
+
});
|