@zintrust/core 0.4.9 → 0.4.10
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/package.json +1 -1
- package/src/cli/commands/RoutesCommand.d.ts.map +1 -1
- package/src/cli/commands/RoutesCommand.js +36 -1
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +73 -35
- package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +29 -15
- package/src/index.js +3 -3
- package/src/runtime/OverrideValueMerge.d.ts.map +1 -1
- package/src/runtime/OverrideValueMerge.js +2 -1
- package/src/templates/project/basic/src/zintrust.runtime.ts.tpl +5 -1
- package/src/templates/project/basic/src/zintrust.runtime.wg.ts.tpl +5 -1
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoutesCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/RoutesCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"RoutesCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/RoutesCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAuVvF,eAAO,MAAM,aAAa;cACd,YAAY;EAatB,CAAC;AAEH,eAAe,aAAa,CAAC"}
|
|
@@ -6,6 +6,8 @@ import { BaseCommand } from '../BaseCommand.js';
|
|
|
6
6
|
import { Env } from '../../config/env.js';
|
|
7
7
|
import { Router } from '../../routes/Router.js';
|
|
8
8
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
9
|
+
import { isObject } from '../../helper/index.js';
|
|
10
|
+
import { ProjectRuntime } from '../../runtime/ProjectRuntime.js';
|
|
9
11
|
const parseGroupBy = (value) => {
|
|
10
12
|
const raw = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
11
13
|
if (raw === '' || raw === 'group')
|
|
@@ -157,6 +159,37 @@ const renderTable = (rows) => {
|
|
|
157
159
|
console.log(bottom);
|
|
158
160
|
/* eslint-enable no-console */
|
|
159
161
|
};
|
|
162
|
+
const annotateManifestRoutes = (router, beforeCount, serviceId) => {
|
|
163
|
+
const routes = Router.getRoutes(router);
|
|
164
|
+
for (const route of routes.slice(beforeCount)) {
|
|
165
|
+
route.__zintrustServiceId = serviceId;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const getRouteServiceId = (route) => {
|
|
169
|
+
return route.__zintrustServiceId ?? '';
|
|
170
|
+
};
|
|
171
|
+
const registerManifestRoutes = async (router) => {
|
|
172
|
+
await ProjectRuntime.tryLoadNodeRuntime();
|
|
173
|
+
const serviceManifest = ProjectRuntime.getServiceManifest();
|
|
174
|
+
if (serviceManifest.length === 0)
|
|
175
|
+
return;
|
|
176
|
+
for (const entry of serviceManifest) {
|
|
177
|
+
if (entry.monolithEnabled === false || typeof entry.loadRoutes !== 'function')
|
|
178
|
+
continue;
|
|
179
|
+
try {
|
|
180
|
+
const beforeCount = Router.getRoutes(router).length;
|
|
181
|
+
// eslint-disable-next-line no-await-in-loop
|
|
182
|
+
const mod = await entry.loadRoutes();
|
|
183
|
+
if (isObject(mod) && typeof mod.registerRoutes === 'function') {
|
|
184
|
+
mod.registerRoutes(router);
|
|
185
|
+
annotateManifestRoutes(router, beforeCount, entry.id);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Ignore broken optional service routes and keep listing what is available.
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
160
193
|
const buildRows = async (options) => {
|
|
161
194
|
const groupBy = parseGroupBy(options.groupBy);
|
|
162
195
|
const filterText = typeof options.filter === 'string' ? options.filter.trim().toLowerCase() : '';
|
|
@@ -174,12 +207,14 @@ const buildRows = async (options) => {
|
|
|
174
207
|
catch {
|
|
175
208
|
// routes/api.ts not found, continue with just core routes
|
|
176
209
|
}
|
|
210
|
+
await registerManifestRoutes(router);
|
|
177
211
|
const routes = Router.getRoutes(router);
|
|
178
212
|
const rows = routes.map((route) => {
|
|
179
213
|
const path = normalizePath(route.path);
|
|
214
|
+
const serviceId = getRouteServiceId(route);
|
|
180
215
|
let group = '';
|
|
181
216
|
if (groupBy === 'service') {
|
|
182
|
-
group = deriveService(path);
|
|
217
|
+
group = serviceId === '' ? deriveService(path) : serviceId;
|
|
183
218
|
}
|
|
184
219
|
else if (groupBy === 'group') {
|
|
185
220
|
group = deriveGroup(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/StartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"StartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/StartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA2sBvF,eAAO,MAAM,YAAY;cACb,YAAY;EA6BtB,CAAC"}
|
|
@@ -168,8 +168,19 @@ const resolveCacheEnabledPreference = (options) => {
|
|
|
168
168
|
return options.cache;
|
|
169
169
|
return undefined;
|
|
170
170
|
};
|
|
171
|
-
const
|
|
172
|
-
|
|
171
|
+
const findNearestPackageJsonDir = (cwd) => {
|
|
172
|
+
let current = path.resolve(cwd);
|
|
173
|
+
while (true) {
|
|
174
|
+
if (existsSync(path.join(current, 'package.json')))
|
|
175
|
+
return current;
|
|
176
|
+
const parent = path.dirname(current);
|
|
177
|
+
if (parent === current)
|
|
178
|
+
return undefined;
|
|
179
|
+
current = parent;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const readPackageJsonFromDir = (dir) => {
|
|
183
|
+
const packagePath = path.join(dir, 'package.json');
|
|
173
184
|
if (!existsSync(packagePath)) {
|
|
174
185
|
throw ErrorFactory.createCliError("Error: No ZinTrust app found. Run 'zin new <project>' or ensure package.json exists.");
|
|
175
186
|
}
|
|
@@ -181,6 +192,24 @@ const readPackageJson = (cwd) => {
|
|
|
181
192
|
throw ErrorFactory.createTryCatchError('Failed to read package.json', error);
|
|
182
193
|
}
|
|
183
194
|
};
|
|
195
|
+
const resolveStartContext = (cwd) => {
|
|
196
|
+
const projectRoot = findNearestPackageJsonDir(cwd) ?? cwd;
|
|
197
|
+
const packageDir = findNearestPackageJsonDir(cwd);
|
|
198
|
+
return {
|
|
199
|
+
cwd,
|
|
200
|
+
projectRoot,
|
|
201
|
+
...(packageDir === undefined ? {} : { packageJson: readPackageJsonFromDir(packageDir) }),
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
const requirePackageJson = (context) => {
|
|
205
|
+
if (context.packageJson !== undefined)
|
|
206
|
+
return context.packageJson;
|
|
207
|
+
throw ErrorFactory.createCliError("Error: No ZinTrust app found. Run 'zin new <project>' or ensure package.json exists.");
|
|
208
|
+
};
|
|
209
|
+
const buildStartEnv = (projectRoot) => ({
|
|
210
|
+
...process.env,
|
|
211
|
+
ZINTRUST_PROJECT_ROOT: projectRoot,
|
|
212
|
+
});
|
|
184
213
|
const isFrameworkRepo = (packageJson) => packageJson.name === '@zintrust/core';
|
|
185
214
|
const hasDevScript = (packageJson) => {
|
|
186
215
|
const scripts = packageJson.scripts;
|
|
@@ -263,14 +292,14 @@ const resolveNodeProdCommand = (cwd) => {
|
|
|
263
292
|
}
|
|
264
293
|
return { command: 'node', args: [compiled] };
|
|
265
294
|
};
|
|
266
|
-
const executeWranglerStart = async (cmd,
|
|
295
|
+
const executeWranglerStart = async (cmd, context, port, runtime, envName, wranglerConfig) => {
|
|
267
296
|
if (runtime !== undefined) {
|
|
268
297
|
throw ErrorFactory.createCliError('Error: --runtime is not supported with --wrangler (Wrangler controls Workers runtime).');
|
|
269
298
|
}
|
|
270
299
|
const normalizedConfig = typeof wranglerConfig === 'string' ? wranglerConfig.trim() : '';
|
|
271
|
-
const explicitConfigFullPath = normalizedConfig.length > 0 ? path.join(cwd, normalizedConfig) : undefined;
|
|
272
|
-
const configPath = explicitConfigFullPath ?? findWranglerConfig(cwd);
|
|
273
|
-
const entry = resolveWranglerEntry(cwd);
|
|
300
|
+
const explicitConfigFullPath = normalizedConfig.length > 0 ? path.join(context.cwd, normalizedConfig) : undefined;
|
|
301
|
+
const configPath = explicitConfigFullPath ?? findWranglerConfig(context.cwd);
|
|
302
|
+
const entry = resolveWranglerEntry(context.cwd);
|
|
274
303
|
if (explicitConfigFullPath !== undefined) {
|
|
275
304
|
if (existsSync(explicitConfigFullPath)) {
|
|
276
305
|
// ok
|
|
@@ -300,7 +329,7 @@ const executeWranglerStart = async (cmd, cwd, port, runtime, envName, wranglerCo
|
|
|
300
329
|
const exitCode = await SpawnUtil.spawnAndWait({
|
|
301
330
|
command: 'wrangler',
|
|
302
331
|
args: wranglerArgs,
|
|
303
|
-
env:
|
|
332
|
+
env: buildStartEnv(context.projectRoot),
|
|
304
333
|
});
|
|
305
334
|
process.exit(exitCode);
|
|
306
335
|
};
|
|
@@ -321,92 +350,98 @@ const ensureTmpRunnerFile = (cwd, filename, content) => {
|
|
|
321
350
|
}
|
|
322
351
|
return fullPath;
|
|
323
352
|
};
|
|
324
|
-
const executeDenoStart = async (cmd,
|
|
353
|
+
const executeDenoStart = async (cmd, context, mode, watchEnabled, _port, runtime) => {
|
|
325
354
|
if (runtime !== undefined) {
|
|
326
355
|
throw ErrorFactory.createCliError('Error: --runtime cannot be used with --deno.');
|
|
327
356
|
}
|
|
328
357
|
if (mode === 'testing') {
|
|
329
358
|
throw ErrorFactory.createCliError('Error: Cannot start server in testing mode. Use development or production.');
|
|
330
359
|
}
|
|
331
|
-
const startModuleSpecifier = resolveRuntimeStartModuleSpecifier(cwd);
|
|
332
|
-
const denoRunner = ensureTmpRunnerFile(cwd, 'zin-start-deno.ts', createDenoRunnerSource(startModuleSpecifier));
|
|
360
|
+
const startModuleSpecifier = resolveRuntimeStartModuleSpecifier(context.cwd);
|
|
361
|
+
const denoRunner = ensureTmpRunnerFile(context.cwd, 'zin-start-deno.ts', createDenoRunnerSource(startModuleSpecifier));
|
|
333
362
|
const args = [];
|
|
334
363
|
if (mode === 'development' && watchEnabled)
|
|
335
364
|
args.push('watch');
|
|
336
365
|
args.push(denoRunner);
|
|
337
366
|
cmd.info('Starting in Deno adapter mode...');
|
|
338
|
-
const exitCode = await SpawnUtil.spawnAndWait({
|
|
367
|
+
const exitCode = await SpawnUtil.spawnAndWait({
|
|
368
|
+
command: 'tsx',
|
|
369
|
+
args,
|
|
370
|
+
env: buildStartEnv(context.projectRoot),
|
|
371
|
+
});
|
|
339
372
|
process.exit(exitCode);
|
|
340
373
|
};
|
|
341
|
-
const executeLambdaStart = async (cmd,
|
|
374
|
+
const executeLambdaStart = async (cmd, context, mode, watchEnabled, _port, runtime) => {
|
|
342
375
|
if (runtime !== undefined) {
|
|
343
376
|
throw ErrorFactory.createCliError('Error: --runtime cannot be used with --lambda.');
|
|
344
377
|
}
|
|
345
378
|
if (mode === 'testing') {
|
|
346
379
|
throw ErrorFactory.createCliError('Error: Cannot start server in testing mode. Use development or production.');
|
|
347
380
|
}
|
|
348
|
-
const startModuleSpecifier = resolveRuntimeStartModuleSpecifier(cwd);
|
|
349
|
-
const lambdaRunner = ensureTmpRunnerFile(cwd, 'zin-start-lambda.ts', createLambdaRunnerSource(startModuleSpecifier));
|
|
381
|
+
const startModuleSpecifier = resolveRuntimeStartModuleSpecifier(context.cwd);
|
|
382
|
+
const lambdaRunner = ensureTmpRunnerFile(context.cwd, 'zin-start-lambda.ts', createLambdaRunnerSource(startModuleSpecifier));
|
|
350
383
|
const args = [];
|
|
351
384
|
if (mode === 'development' && watchEnabled)
|
|
352
385
|
args.push('watch');
|
|
353
386
|
args.push(lambdaRunner);
|
|
354
387
|
cmd.info('Starting in Lambda adapter mode...');
|
|
355
|
-
const exitCode = await SpawnUtil.spawnAndWait({
|
|
388
|
+
const exitCode = await SpawnUtil.spawnAndWait({
|
|
389
|
+
command: 'tsx',
|
|
390
|
+
args,
|
|
391
|
+
env: buildStartEnv(context.projectRoot),
|
|
392
|
+
});
|
|
356
393
|
process.exit(exitCode);
|
|
357
394
|
};
|
|
358
|
-
const executeNodeStart = async (cmd,
|
|
395
|
+
const executeNodeStart = async (cmd, context, mode, watchEnabled, _port) => {
|
|
359
396
|
if (mode === 'testing') {
|
|
360
397
|
throw ErrorFactory.createCliError('Error: Cannot start server in testing mode. Use --force to override (not supported).');
|
|
361
398
|
}
|
|
362
399
|
if (mode === 'development') {
|
|
363
400
|
if (!watchEnabled) {
|
|
364
401
|
cmd.warn('Watch mode disabled; starting once.');
|
|
365
|
-
const bootstrap = resolveBootstrapEntryTs(cwd);
|
|
402
|
+
const bootstrap = resolveBootstrapEntryTs(context.cwd);
|
|
366
403
|
const args = bootstrap === undefined ? ['src/index.ts'] : [bootstrap];
|
|
367
404
|
const exitCode = await SpawnUtil.spawnAndWait({
|
|
368
405
|
command: 'tsx',
|
|
369
406
|
args,
|
|
370
407
|
forwardSignals: false,
|
|
371
|
-
env:
|
|
408
|
+
env: buildStartEnv(context.projectRoot),
|
|
372
409
|
});
|
|
373
410
|
process.exit(exitCode);
|
|
374
411
|
}
|
|
375
|
-
const
|
|
376
|
-
const dev = resolveNodeDevCommand(cwd, packageJson);
|
|
412
|
+
const dev = resolveNodeDevCommand(context.cwd, requirePackageJson(context));
|
|
377
413
|
cmd.info('Starting in development mode (watch enabled)...');
|
|
378
414
|
const exitCode = await SpawnUtil.spawnAndWait({
|
|
379
415
|
command: dev.command,
|
|
380
416
|
args: dev.args,
|
|
381
417
|
forwardSignals: false,
|
|
382
|
-
env:
|
|
418
|
+
env: buildStartEnv(context.projectRoot),
|
|
383
419
|
});
|
|
384
420
|
process.exit(exitCode);
|
|
385
421
|
}
|
|
386
|
-
const prod = resolveNodeProdCommand(cwd);
|
|
422
|
+
const prod = resolveNodeProdCommand(context.cwd);
|
|
387
423
|
cmd.info('Starting in production mode...');
|
|
388
424
|
const exitCode = await SpawnUtil.spawnAndWait({
|
|
389
425
|
command: prod.command,
|
|
390
426
|
args: prod.args,
|
|
391
427
|
forwardSignals: false,
|
|
392
|
-
env:
|
|
428
|
+
env: buildStartEnv(context.projectRoot),
|
|
393
429
|
});
|
|
394
430
|
process.exit(exitCode);
|
|
395
431
|
};
|
|
396
|
-
const executeSplitStart = async (cmd,
|
|
432
|
+
const executeSplitStart = async (cmd, context, _options) => {
|
|
397
433
|
cmd.info('🚀 Starting in split mode (Producer + Consumer)...');
|
|
398
|
-
const
|
|
399
|
-
const webDev = resolveNodeDevCommand(cwd, packageJson);
|
|
434
|
+
const webDev = resolveNodeDevCommand(context.cwd, requirePackageJson(context));
|
|
400
435
|
// Producer Environment
|
|
401
436
|
const producerEnv = {
|
|
402
|
-
...
|
|
437
|
+
...buildStartEnv(context.projectRoot),
|
|
403
438
|
WORKER_ENABLED: 'false',
|
|
404
439
|
QUEUE_ENABLED: 'true',
|
|
405
440
|
RUNTIME_MODE: 'node-server',
|
|
406
441
|
};
|
|
407
442
|
// Consumer Environment
|
|
408
443
|
const consumerEnv = {
|
|
409
|
-
...
|
|
444
|
+
...buildStartEnv(context.projectRoot),
|
|
410
445
|
WORKER_ENABLED: 'true',
|
|
411
446
|
QUEUE_ENABLED: 'true',
|
|
412
447
|
RUNTIME_MODE: 'containers',
|
|
@@ -417,10 +452,10 @@ const executeSplitStart = async (cmd, cwd, _options) => {
|
|
|
417
452
|
};
|
|
418
453
|
// Resolve Consumer Command (zintrust worker:start-all)
|
|
419
454
|
// We try to use tsx against the source bin if possible
|
|
420
|
-
const workerArgs = existsSync(path.join(
|
|
455
|
+
const workerArgs = existsSync(path.join(context.projectRoot, 'bin/zin.ts'))
|
|
421
456
|
? ['bin/zin.ts', 'worker:start-all']
|
|
422
457
|
: ['dist/bin/zin.js', 'worker:start-all'];
|
|
423
|
-
const workerCommand = existsSync(path.join(
|
|
458
|
+
const workerCommand = existsSync(path.join(context.projectRoot, 'bin/zin.ts')) ? 'tsx' : 'node';
|
|
424
459
|
cmd.info('-------------------------------------------');
|
|
425
460
|
cmd.info('🔹 [Producer] Web Server starting...');
|
|
426
461
|
cmd.info('🔸 [Consumer] Worker Process starting...');
|
|
@@ -428,12 +463,14 @@ const executeSplitStart = async (cmd, cwd, _options) => {
|
|
|
428
463
|
const pProducer = SpawnUtil.spawnAndWait({
|
|
429
464
|
command: webDev.command,
|
|
430
465
|
args: webDev.args,
|
|
466
|
+
cwd: context.cwd,
|
|
431
467
|
env: producerEnv,
|
|
432
468
|
forwardSignals: true,
|
|
433
469
|
});
|
|
434
470
|
const pConsumer = SpawnUtil.spawnAndWait({
|
|
435
471
|
command: workerCommand,
|
|
436
472
|
args: workerArgs,
|
|
473
|
+
cwd: context.projectRoot,
|
|
437
474
|
env: consumerEnv,
|
|
438
475
|
forwardSignals: true,
|
|
439
476
|
});
|
|
@@ -441,6 +478,7 @@ const executeSplitStart = async (cmd, cwd, _options) => {
|
|
|
441
478
|
};
|
|
442
479
|
const executeStart = async (options, cmd) => {
|
|
443
480
|
const cwd = process.cwd();
|
|
481
|
+
const context = resolveStartContext(cwd);
|
|
444
482
|
EnvFileLoader.ensureLoaded();
|
|
445
483
|
const mode = resolveMode(options);
|
|
446
484
|
const port = resolvePort(options);
|
|
@@ -454,7 +492,7 @@ const executeStart = async (options, cmd) => {
|
|
|
454
492
|
if (variant === 'lambda')
|
|
455
493
|
effectiveRuntime = 'lambda';
|
|
456
494
|
if (mode === 'split') {
|
|
457
|
-
await executeSplitStart(cmd,
|
|
495
|
+
await executeSplitStart(cmd, context, options);
|
|
458
496
|
return;
|
|
459
497
|
}
|
|
460
498
|
assertCompatibleStartVariant(variant, configuredRuntime);
|
|
@@ -469,7 +507,7 @@ const executeStart = async (options, cmd) => {
|
|
|
469
507
|
const wranglerConfig = typeof options.wranglerConfig === 'string' && options.wranglerConfig.trim() !== ''
|
|
470
508
|
? options.wranglerConfig.trim()
|
|
471
509
|
: undefined;
|
|
472
|
-
await executeWranglerStart(cmd,
|
|
510
|
+
await executeWranglerStart(cmd, context, port, runtime, envName === '' ? undefined : envName, wranglerConfig);
|
|
473
511
|
return;
|
|
474
512
|
}
|
|
475
513
|
if (envName !== '') {
|
|
@@ -477,14 +515,14 @@ const executeStart = async (options, cmd) => {
|
|
|
477
515
|
}
|
|
478
516
|
const watchEnabled = resolveWatchPreference(options, mode);
|
|
479
517
|
if (variant === 'deno') {
|
|
480
|
-
await executeDenoStart(cmd,
|
|
518
|
+
await executeDenoStart(cmd, context, mode, watchEnabled, port, runtime);
|
|
481
519
|
return;
|
|
482
520
|
}
|
|
483
521
|
if (variant === 'lambda') {
|
|
484
|
-
await executeLambdaStart(cmd,
|
|
522
|
+
await executeLambdaStart(cmd, context, mode, watchEnabled, port, runtime);
|
|
485
523
|
return;
|
|
486
524
|
}
|
|
487
|
-
await executeNodeStart(cmd,
|
|
525
|
+
await executeNodeStart(cmd, context, mode, watchEnabled, port);
|
|
488
526
|
};
|
|
489
527
|
export const StartCommand = Object.freeze({
|
|
490
528
|
create() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ServiceScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"ServiceScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ServiceScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD;;GAEG;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAuB7F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAGnF;AAED;;GAEG;AAEH,wBAAgB,QAAQ,CACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,qBAAqB,CAAC,CAiDhC;AA8bD,eAAO,MAAM,iBAAiB;;;;EAI5B,CAAC"}
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
import { FileGenerator } from '../scaffolding/FileGenerator.js';
|
|
6
6
|
import { Logger } from '../../config/logger.js';
|
|
7
7
|
import * as path from '../../node-singletons/path.js';
|
|
8
|
+
const coreModuleSpecifier = ['@zintrust', 'core'].join('/');
|
|
9
|
+
const coreStartModuleSpecifier = `${coreModuleSpecifier}/start`;
|
|
10
|
+
const serviceManifestImportExpression = "import('./bootstrap/service-manifest.ts').catch(() => import('./bootstrap/service-manifest.js'))";
|
|
11
|
+
const buildRouteImportExpression = (domain, serviceName) => `import('../services/${domain}/${serviceName}/routes/api.ts').catch(() => import('../services/${domain}/${serviceName}/routes/api.js'))`;
|
|
8
12
|
/**
|
|
9
13
|
* ServiceScaffolder generates microservices with all necessary files
|
|
10
14
|
*/
|
|
@@ -91,11 +95,12 @@ export function scaffold(projectRoot, options) {
|
|
|
91
95
|
function ensureProjectRuntimeFiles(projectRoot, options) {
|
|
92
96
|
const domain = options.domain ?? 'default';
|
|
93
97
|
const serviceId = `${domain}/${options.name}`;
|
|
98
|
+
const routeImportExpression = buildRouteImportExpression(domain, options.name);
|
|
94
99
|
const bootstrapDir = path.join(projectRoot, 'src', 'bootstrap');
|
|
95
100
|
FileGenerator.createDirectory(bootstrapDir);
|
|
96
101
|
const manifestPath = path.join(bootstrapDir, 'service-manifest.ts');
|
|
97
102
|
if (!FileGenerator.fileExists(manifestPath)) {
|
|
98
|
-
const initialManifest = `import type { ServiceManifestEntry } from '
|
|
103
|
+
const initialManifest = `import type { ServiceManifestEntry } from '${coreModuleSpecifier}';
|
|
99
104
|
|
|
100
105
|
export const serviceManifest: ReadonlyArray<ServiceManifestEntry> = [
|
|
101
106
|
{
|
|
@@ -104,7 +109,7 @@ export const serviceManifest: ReadonlyArray<ServiceManifestEntry> = [
|
|
|
104
109
|
name: '${options.name}',
|
|
105
110
|
port: ${options.port ?? 3001},
|
|
106
111
|
monolithEnabled: true,
|
|
107
|
-
loadRoutes: async () =>
|
|
112
|
+
loadRoutes: async () => ${routeImportExpression},
|
|
108
113
|
},
|
|
109
114
|
];
|
|
110
115
|
|
|
@@ -112,7 +117,9 @@ export default serviceManifest;
|
|
|
112
117
|
`;
|
|
113
118
|
FileGenerator.writeFile(manifestPath, initialManifest);
|
|
114
119
|
}
|
|
115
|
-
const runtimeModule = `
|
|
120
|
+
const runtimeModule = `const serviceManifestModule = await ${serviceManifestImportExpression};
|
|
121
|
+
|
|
122
|
+
const serviceManifest = serviceManifestModule.default ?? serviceManifestModule.serviceManifest ?? [];
|
|
116
123
|
|
|
117
124
|
export { serviceManifest };
|
|
118
125
|
|
|
@@ -128,6 +135,7 @@ export default Object.freeze({ serviceManifest });
|
|
|
128
135
|
function updateServiceManifest(projectRoot, options) {
|
|
129
136
|
const domain = options.domain ?? 'default';
|
|
130
137
|
const serviceId = `${domain}/${options.name}`;
|
|
138
|
+
const routeImportExpression = buildRouteImportExpression(domain, options.name);
|
|
131
139
|
const manifestPath = path.join(projectRoot, 'src', 'bootstrap', 'service-manifest.ts');
|
|
132
140
|
if (!FileGenerator.fileExists(manifestPath))
|
|
133
141
|
return;
|
|
@@ -141,7 +149,7 @@ function updateServiceManifest(projectRoot, options) {
|
|
|
141
149
|
name: '${options.name}',
|
|
142
150
|
port: ${options.port ?? 3001},
|
|
143
151
|
monolithEnabled: true,
|
|
144
|
-
loadRoutes: async () =>
|
|
152
|
+
loadRoutes: async () => ${routeImportExpression},
|
|
145
153
|
},
|
|
146
154
|
`;
|
|
147
155
|
const marker = '];';
|
|
@@ -234,7 +242,7 @@ function generateServiceIndex(options) {
|
|
|
234
242
|
* Auth: ${options.auth ?? 'api-key'}
|
|
235
243
|
*/
|
|
236
244
|
|
|
237
|
-
import { bootStandaloneService } from '
|
|
245
|
+
import { bootStandaloneService } from '${coreStartModuleSpecifier}';
|
|
238
246
|
|
|
239
247
|
await bootStandaloneService(import.meta.url, {
|
|
240
248
|
id: '${serviceId}',
|
|
@@ -244,7 +252,7 @@ await bootStandaloneService(import.meta.url, {
|
|
|
244
252
|
});
|
|
245
253
|
|
|
246
254
|
// Cloudflare Workers entry.
|
|
247
|
-
export { default } from '
|
|
255
|
+
export { default } from '${coreStartModuleSpecifier}';
|
|
248
256
|
`;
|
|
249
257
|
}
|
|
250
258
|
/**
|
|
@@ -255,7 +263,7 @@ function generateServiceRoutes(options) {
|
|
|
255
263
|
* ${options.name} Service Routes
|
|
256
264
|
*/
|
|
257
265
|
|
|
258
|
-
import { Router, type IRequest, type IResponse, type IRouter } from '
|
|
266
|
+
import { Router, type IRequest, type IResponse, type IRouter } from '${coreModuleSpecifier}';
|
|
259
267
|
|
|
260
268
|
export function registerRoutes(router: IRouter): void {
|
|
261
269
|
// Example route
|
|
@@ -326,8 +334,7 @@ function generateExampleController(options) {
|
|
|
326
334
|
* Example Controller for ${options.name} Service
|
|
327
335
|
*/
|
|
328
336
|
|
|
329
|
-
import { type IRequest, type IResponse, Controller } from '
|
|
330
|
-
|
|
337
|
+
import { type IRequest, type IResponse, Controller } from '${coreModuleSpecifier}';
|
|
331
338
|
const controller = Object.freeze({
|
|
332
339
|
...Controller,
|
|
333
340
|
|
|
@@ -389,7 +396,7 @@ function generateExampleModel(options) {
|
|
|
389
396
|
* Example Model for ${options.name} Service
|
|
390
397
|
*/
|
|
391
398
|
|
|
392
|
-
import { Model } from '
|
|
399
|
+
import { Model } from '${coreModuleSpecifier}';
|
|
393
400
|
|
|
394
401
|
export const Example = Model.define({
|
|
395
402
|
table: '${options.name}',
|
|
@@ -447,6 +454,8 @@ function getServiceConfig(options) {
|
|
|
447
454
|
*/
|
|
448
455
|
function generateServiceReadme(options) {
|
|
449
456
|
const config = getServiceConfig(options);
|
|
457
|
+
const serviceDir = `src/services/${config.domain}/${options.name}`;
|
|
458
|
+
const serviceId = `${config.domain}/${options.name}`;
|
|
450
459
|
return `# ${options.name} Service
|
|
451
460
|
|
|
452
461
|
Microservice for ${config.domain} domain.
|
|
@@ -460,14 +469,19 @@ Microservice for ${config.domain} domain.
|
|
|
460
469
|
## Getting Started
|
|
461
470
|
|
|
462
471
|
\`\`\`bash
|
|
463
|
-
# Start service
|
|
464
|
-
|
|
472
|
+
# Start this service from its service directory (Node)
|
|
473
|
+
cd ${serviceDir}
|
|
474
|
+
zin s
|
|
475
|
+
|
|
476
|
+
# Start this service with Cloudflare Workers dev
|
|
477
|
+
cd ${serviceDir}
|
|
478
|
+
zin s --wg
|
|
479
|
+
|
|
480
|
+
# List this service routes from the project root
|
|
481
|
+
MICROSERVICES=true SERVICES=${serviceId} zin routes
|
|
465
482
|
|
|
466
483
|
# Run tests
|
|
467
484
|
npm test
|
|
468
|
-
|
|
469
|
-
# Run migrations
|
|
470
|
-
npm run migrate
|
|
471
485
|
\`\`\`
|
|
472
486
|
|
|
473
487
|
## Environment Variables
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v0.4.
|
|
2
|
+
* @zintrust/core v0.4.10
|
|
3
3
|
*
|
|
4
4
|
* ZinTrust Framework - Production-Grade TypeScript Backend
|
|
5
5
|
* Built for performance, type safety, and exceptional developer experience
|
|
6
6
|
*
|
|
7
7
|
* Build Information:
|
|
8
|
-
* Built: 2026-03-
|
|
8
|
+
* Built: 2026-03-23T12:53:44.665Z
|
|
9
9
|
* Node: >=20.0.0
|
|
10
10
|
* License: MIT
|
|
11
11
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Available at runtime for debugging and health checks
|
|
22
22
|
*/
|
|
23
23
|
export const ZINTRUST_VERSION = '0.1.41';
|
|
24
|
-
export const ZINTRUST_BUILD_DATE = '2026-03-
|
|
24
|
+
export const ZINTRUST_BUILD_DATE = '2026-03-23T12:53:44.591Z'; // Replaced during build
|
|
25
25
|
export { Application } from './boot/Application.js';
|
|
26
26
|
export { AwsSigV4 } from './common/index.js';
|
|
27
27
|
export { SignedRequest } from './security/SignedRequest.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverrideValueMerge.d.ts","sourceRoot":"","sources":["../../../src/runtime/OverrideValueMerge.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,GAAI,MAAM,OAAO,EAAE,UAAU,OAAO,KAAG,
|
|
1
|
+
{"version":3,"file":"OverrideValueMerge.d.ts","sourceRoot":"","sources":["../../../src/runtime/OverrideValueMerge.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,GAAI,MAAM,OAAO,EAAE,UAAU,OAAO,KAAG,OAatE,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -6,7 +6,8 @@ export const mergeOverrideValues = (base, override) => {
|
|
|
6
6
|
const merged = { ...base };
|
|
7
7
|
for (const [key, value] of Object.entries(override)) {
|
|
8
8
|
const current = merged[key];
|
|
9
|
-
merged[key] =
|
|
9
|
+
merged[key] =
|
|
10
|
+
isObject(current) && isObject(value) ? mergeOverrideValues(current, value) : value;
|
|
10
11
|
}
|
|
11
12
|
return merged;
|
|
12
13
|
};
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
const serviceManifestModule = await import('./bootstrap/service-manifest.ts').catch(() =>
|
|
2
|
+
import('./bootstrap/service-manifest.js')
|
|
3
|
+
);
|
|
4
|
+
|
|
5
|
+
const serviceManifest = serviceManifestModule.default ?? serviceManifestModule.serviceManifest ?? [];
|
|
2
6
|
|
|
3
7
|
export { serviceManifest };
|
|
4
8
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
const serviceManifestModule = await import('./bootstrap/service-manifest.ts').catch(() =>
|
|
2
|
+
import('./bootstrap/service-manifest.js')
|
|
3
|
+
);
|
|
4
|
+
|
|
5
|
+
const serviceManifest = serviceManifestModule.default ?? serviceManifestModule.serviceManifest ?? [];
|
|
2
6
|
|
|
3
7
|
export { serviceManifest };
|
|
4
8
|
|