@zintrust/core 0.4.14 → 0.4.16

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 (35) hide show
  1. package/package.json +1 -1
  2. package/src/boot/bootstrap.js +5 -3
  3. package/src/boot/registry/registerRoute.d.ts.map +1 -1
  4. package/src/boot/registry/registerRoute.js +35 -19
  5. package/src/cli/PromptHelper.d.ts.map +1 -1
  6. package/src/cli/PromptHelper.js +1 -0
  7. package/src/cli/commands/AddCommand.d.ts +4 -0
  8. package/src/cli/commands/AddCommand.d.ts.map +1 -1
  9. package/src/cli/commands/AddCommand.js +119 -4
  10. package/src/cli/commands/NewCommand.d.ts +1 -1
  11. package/src/cli/commands/NewCommand.d.ts.map +1 -1
  12. package/src/cli/commands/NewCommand.js +4 -1
  13. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  14. package/src/cli/commands/StartCommand.js +32 -3
  15. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  16. package/src/cli/scaffolding/ProjectScaffolder.js +1 -0
  17. package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
  18. package/src/cli/scaffolding/ServiceScaffolder.js +2 -0
  19. package/src/config/middleware.d.ts +4 -1
  20. package/src/config/middleware.d.ts.map +1 -1
  21. package/src/config/middleware.js +24 -1
  22. package/src/index.js +3 -3
  23. package/src/microservices/ServiceManifest.d.ts +1 -0
  24. package/src/microservices/ServiceManifest.d.ts.map +1 -1
  25. package/src/microservices/ServiceManifest.js +5 -0
  26. package/src/middleware/CsrfMiddleware.d.ts +1 -1
  27. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  28. package/src/runtime/ProjectRuntime.d.ts.map +1 -1
  29. package/src/runtime/ProjectRuntime.js +21 -11
  30. package/src/runtime/WorkerAdapterImports.d.ts.map +1 -1
  31. package/src/runtime/WorkerAdapterImports.js +17 -0
  32. package/src/runtime/WorkersModule.d.ts.map +1 -1
  33. package/src/runtime/WorkersModule.js +46 -8
  34. package/src/templates/project/basic/config/middleware.ts.tpl +18 -5
  35. package/src/templates/project/basic/src/zintrust.plugins.wg.ts.tpl +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -199,9 +199,11 @@ const BootstrapFunctions = Object.freeze({
199
199
  // (This is driven by src/zintrust.plugins.ts generated by `zin plugin install`.)
200
200
  try {
201
201
  const { PluginAutoImports } = await import('../runtime/PluginAutoImports.js');
202
- const officialImports = await PluginAutoImports.tryImportRuntimeAutoImports('base');
203
- if (!officialImports.ok) {
204
- Logger.warn('Official plugin auto-imports failed:', ErrorFactory.createGeneralError('officialImports', officialImports.errorMessage));
202
+ if (appConfig.dockerWorker === true) {
203
+ const officialImports = await PluginAutoImports.tryImportRuntimeAutoImports('base');
204
+ if (!officialImports.ok) {
205
+ Logger.warn('Official plugin auto-imports failed:', ErrorFactory.createGeneralError('officialImports', officialImports.errorMessage));
206
+ }
205
207
  }
206
208
  const projectImports = await PluginAutoImports.tryImportProjectAutoImports();
207
209
  if (!projectImports.ok && projectImports.reason !== 'not-found') {
@@ -1 +1 @@
1
- {"version":3,"file":"registerRoute.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/registerRoute.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAc3D,eAAO,MAAM,kBAAkB,QAAO,OAKrC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAMpF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAOrF,CAAC;AAiKF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAqBd,CAAC"}
1
+ {"version":3,"file":"registerRoute.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/registerRoute.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAc3D,eAAO,MAAM,kBAAkB,QAAO,OAKrC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAMpF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,CAAC,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAOrF,CAAC;AA2LF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAqBd,CAAC"}
@@ -89,6 +89,8 @@ const resolveServicePrefix = (entry) => {
89
89
  const ensureManifestServiceEnvLoaded = async (entry) => {
90
90
  if (isCloudflare)
91
91
  return;
92
+ if (entry.loadEnv === false)
93
+ return;
92
94
  const { EnvFileLoader } = await import('../../cli/utils/EnvFileLoader.js');
93
95
  const projectRoot = getProjectRoot();
94
96
  const envPath = resolveManifestServiceEnvDir(projectRoot, entry);
@@ -98,6 +100,35 @@ const ensureManifestServiceEnvLoaded = async (entry) => {
98
100
  envPaths: [envPath],
99
101
  });
100
102
  };
103
+ const shouldRegisterManifestEntry = (entry, activeService) => {
104
+ if (entry.monolithEnabled === false || typeof entry.loadRoutes !== 'function') {
105
+ return false;
106
+ }
107
+ if (activeService !== undefined && activeService.id !== entry.id) {
108
+ return false;
109
+ }
110
+ return true;
111
+ };
112
+ const loadRuntimeManifest = async () => {
113
+ if (isCloudflare) {
114
+ await ProjectRuntime.tryLoadWorkerRuntime();
115
+ return;
116
+ }
117
+ await ProjectRuntime.tryLoadNodeRuntime();
118
+ };
119
+ const registerManifestEntryRoutes = async (router, entry, activeService) => {
120
+ try {
121
+ await ensureManifestServiceEnvLoaded(entry);
122
+ const mod = await entry.loadRoutes?.();
123
+ const registerRoutes = isObject(mod) ? mod.registerRoutes : undefined;
124
+ if (typeof registerRoutes === 'function') {
125
+ registerLoadedRoutes(router, entry, registerRoutes, activeService);
126
+ }
127
+ }
128
+ catch (error) {
129
+ Logger.warn(`Failed to register manifest routes for ${entry.id}`, error);
130
+ }
131
+ };
101
132
  const registerLoadedRoutes = (router, entry, registerRoutes, activeService) => {
102
133
  const servicePrefix = resolveServicePrefix(entry);
103
134
  if (activeService?.id === entry.id) {
@@ -109,7 +140,7 @@ const registerLoadedRoutes = (router, entry, registerRoutes, activeService) => {
109
140
  });
110
141
  };
111
142
  const registerManifestRoutes = async (router) => {
112
- await ProjectRuntime.tryLoadNodeRuntime();
143
+ await loadRuntimeManifest();
113
144
  const serviceManifest = ProjectRuntime.getServiceManifest();
114
145
  if (serviceManifest.length === 0)
115
146
  return;
@@ -117,25 +148,10 @@ const registerManifestRoutes = async (router) => {
117
148
  if (activeService !== undefined && isCloudflare)
118
149
  return;
119
150
  for (const entry of serviceManifest) {
120
- if (entry.monolithEnabled === false || typeof entry.loadRoutes !== 'function') {
151
+ if (!shouldRegisterManifestEntry(entry, activeService))
121
152
  continue;
122
- }
123
- if (activeService !== undefined && activeService.id !== entry.id) {
124
- continue;
125
- }
126
- try {
127
- // eslint-disable-next-line no-await-in-loop
128
- await ensureManifestServiceEnvLoaded(entry);
129
- // eslint-disable-next-line no-await-in-loop
130
- const mod = await entry.loadRoutes();
131
- const registerRoutes = isObject(mod) ? mod.registerRoutes : undefined;
132
- if (typeof registerRoutes === 'function') {
133
- registerLoadedRoutes(router, entry, registerRoutes, activeService);
134
- }
135
- }
136
- catch (error) {
137
- Logger.warn(`Failed to register manifest routes for ${entry.id}`, error);
138
- }
153
+ // eslint-disable-next-line no-await-in-loop
154
+ await registerManifestEntryRoutes(router, entry, activeService);
139
155
  }
140
156
  };
141
157
  const registerFrameworkRoutes = async (resolvedBasePath, router) => {
@@ -1 +1 @@
1
- {"version":3,"file":"PromptHelper.d.ts","sourceRoot":"","sources":["../../../src/cli/PromptHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;sBACqB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMlE;;OAEG;8BAC6B,MAAM,gBAAe,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAuBrF;;OAEG;6BAEU,MAAM,gBACJ,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;IAuBlB;;OAEG;uBACqB,MAAM,gBAAsB,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAqBpF;;OAEG;uCAEkB,MAAM,EAAE,gBACd,OAAO,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;IAkBpB;;OAEG;qBAEQ,MAAM,mBACC,OAAO,gBACV,OAAO,GACnB,OAAO,CAAC,OAAO,CAAC;IAiBnB;;OAEG;wBAEQ,MAAM,WACN,MAAM,EAAE,kBACF,MAAM,gBACR,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;IAkBlB;;OAEG;uBAEQ,MAAM,iBACD,MAAM,gBACP,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;EAgBlB,CAAC"}
1
+ {"version":3,"file":"PromptHelper.d.ts","sourceRoot":"","sources":["../../../src/cli/PromptHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;sBACqB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMlE;;OAEG;8BAC6B,MAAM,gBAAe,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAuBrF;;OAEG;6BAEU,MAAM,gBACJ,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;IAwBlB;;OAEG;uBACqB,MAAM,gBAAsB,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAqBpF;;OAEG;uCAEkB,MAAM,EAAE,gBACd,OAAO,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;IAkBpB;;OAEG;qBAEQ,MAAM,mBACC,OAAO,gBACV,OAAO,GACnB,OAAO,CAAC,OAAO,CAAC;IAiBnB;;OAEG;wBAEQ,MAAM,WACN,MAAM,EAAE,kBACF,MAAM,gBACR,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;IAkBlB;;OAEG;uBAEQ,MAAM,iBACD,MAAM,gBACP,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;EAgBlB,CAAC"}
@@ -54,6 +54,7 @@ export const PromptHelper = Object.freeze({
54
54
  { name: 'PostgreSQL — Production-ready relational DB', value: 'postgresql' },
55
55
  { name: 'MySQL — Production-ready relational DB', value: 'mysql' },
56
56
  { name: 'SQLite — Local dev (file-based)', value: 'sqlite' },
57
+ { name: 'd1 — Cloudflare D1 database', value: 'd1' },
57
58
  { name: 'd1-proxy — Cloudflare D1 via HTTPS proxy', value: 'd1-remote' },
58
59
  ],
59
60
  default: defaultDb,
@@ -32,6 +32,9 @@ interface ControllerPromptAnswers {
32
32
  interface RoutesPromptAnswers {
33
33
  name: string;
34
34
  }
35
+ interface MiddlewarePromptAnswers {
36
+ name: string;
37
+ }
35
38
  interface FactoryPromptAnswers {
36
39
  name: string;
37
40
  model: string;
@@ -80,6 +83,7 @@ export declare const AddCommand: Readonly<{
80
83
  promptModelConfig: () => Promise<ModelPromptAnswers>;
81
84
  promptControllerConfig: () => Promise<ControllerPromptAnswers>;
82
85
  promptRoutesConfig: () => Promise<RoutesPromptAnswers>;
86
+ promptMiddlewareConfig: () => Promise<MiddlewarePromptAnswers>;
83
87
  promptFactoryConfig: () => Promise<FactoryPromptAnswers>;
84
88
  promptSeederConfig: () => Promise<SeederPromptAnswers>;
85
89
  promptRequestFactoryConfig: () => Promise<RequestFactoryPromptAnswers>;
@@ -1 +1 @@
1
- {"version":3,"file":"AddCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/AddCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAarE,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,2CAA2C,CAAC;AAwCnD,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAAC;IAChC,IAAI,EAAE,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;CAC7C;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,2BAA2B;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,4BAA4B;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAsmCD;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;cACO,YAAY;IAWtB;;;OAGG;;2CAnlC2C,MAAM,KAAG,OAAO,CAAC,oBAAoB,CAAC;mCA2EhD,OAAO,CAAC,oBAAoB,CAAC;qCA8D3B,OAAO,CAAC,sBAAsB,CAAC;iCAwGnC,OAAO,CAAC,kBAAkB,CAAC;sCA4DtB,OAAO,CAAC,uBAAuB,CAAC;kCAwDpC,OAAO,CAAC,mBAAmB,CAAC;mCAkE3B,OAAO,CAAC,oBAAoB,CAAC;kCA8I9B,OAAO,CAAC,mBAAmB,CAAC;0CAiHpB,OAAO,CAAC,2BAA2B,CAAC;yCAwFrC,OAAO,CAAC,MAAM,CAAC;2DAkBpC,MAAM,KAC1B,OAAO,CAAC,4BAA4B,CAAC;4CAoHzB,MAAM,KAClB,OAAO,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,GAAG,KAAK,CAAA;SAAE,CAAC;iDAlE5C,MAAM,KAAG,aAAa,EAAE;;EA+RtE,CAAC"}
1
+ {"version":3,"file":"AddCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/AddCommand.ts"],"names":[],"mappings":"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"}
@@ -24,8 +24,8 @@ import { PluginManager } from '../../runtime/PluginManager.js';
24
24
  import inquirer from 'inquirer';
25
25
  const addOptions = (command) => {
26
26
  command
27
- .argument('<type>', 'What to add: service, feature, migration, model, controller, routes, factory, seeder, requestfactory, responsefactory, workflow, or governance')
28
- .argument('[name]', 'Name of service/feature/migration/model/controller/factory/seeder/requestfactory/responsefactory/workflow (governance takes no name)')
27
+ .argument('<type>', 'What to add: service, feature, migration, model, controller, routes, middleware, factory, seeder, requestfactory, responsefactory, workflow, or governance')
28
+ .argument('[name]', 'Name of service/feature/migration/model/controller/middleware/factory/seeder/requestfactory/responsefactory/workflow (governance takes no name)')
29
29
  .option('--package-manager <pm>', 'Specify package manager to use when installing plugins (npm|yarn|pnpm)')
30
30
  .option('--domain <name>', 'Service domain (e.g., ecommerce, payments) - for services')
31
31
  .option('--database <type>', 'Database (shared|isolated) - for services')
@@ -369,6 +369,119 @@ const addRoutes = async (cmd, routeName, opts) => {
369
369
  cmd.info(`File: ${path.basename(result.routeFile)}`);
370
370
  cmd.info(`\nNext steps:\n • Add route definitions\n • Import controllers\n • Register in main router`);
371
371
  };
372
+ const promptMiddlewareConfig = async () => {
373
+ return inquirer.prompt([
374
+ {
375
+ type: 'input',
376
+ name: 'name',
377
+ message: 'Middleware name (PascalCase, e.g., AuthMiddleware):',
378
+ validate: (value) => {
379
+ return /^[A-Z][a-zA-Z\d]*Middleware$/.test(value)
380
+ ? true
381
+ : 'Must be PascalCase ending with "Middleware"';
382
+ },
383
+ },
384
+ ]);
385
+ };
386
+ const buildMiddlewareKey = (middlewareName) => {
387
+ const withoutSuffix = middlewareName.replace(/Middleware$/, '');
388
+ return `${CommonUtils.camelCase(withoutSuffix)}Middleware`;
389
+ };
390
+ const buildMiddlewareSource = (middlewareName) => {
391
+ return `import type { Middleware } from '../../index.js';
392
+
393
+ export const ${middlewareName}: Middleware = async (_req, _res, next) => {
394
+ await next();
395
+ };
396
+ `;
397
+ };
398
+ const registerMiddlewareImport = (configSource, middlewareName) => {
399
+ const importLine = `import { ${middlewareName} } from '@app/Middleware/${middlewareName}';`;
400
+ if (configSource.includes(importLine))
401
+ return configSource;
402
+ const lines = configSource.split('\n');
403
+ let insertAt = -1;
404
+ for (let index = 0; index < lines.length; index += 1) {
405
+ if (lines[index]?.startsWith('import '))
406
+ insertAt = index;
407
+ }
408
+ if (insertAt === -1) {
409
+ return `${importLine}\n${configSource}`;
410
+ }
411
+ lines.splice(insertAt + 1, 0, importLine);
412
+ return lines.join('\n');
413
+ };
414
+ const registerMiddlewareRouteKey = (configSource, middlewareName, middlewareKey) => {
415
+ if (configSource.includes(`${middlewareKey}: ${middlewareName}`)) {
416
+ return { content: configSource, updated: true };
417
+ }
418
+ const routeBlockPattern = /route:\s*\{([\s\S]*?)\n\s*\},/;
419
+ if (routeBlockPattern.test(configSource)) {
420
+ return {
421
+ content: configSource.replace(routeBlockPattern, (_match, inner) => {
422
+ const prefix = inner.trim() === '' ? '' : inner.replace(/\s*$/, '');
423
+ const nextInner = prefix === ''
424
+ ? `\n ${middlewareKey}: ${middlewareName},`
425
+ : `${prefix}\n ${middlewareKey}: ${middlewareName},`;
426
+ return `route: {${nextInner}\n },`;
427
+ }),
428
+ updated: true,
429
+ };
430
+ }
431
+ const closingPattern = /\n\} as MiddlewaresType;\s*$/;
432
+ if (!closingPattern.test(configSource)) {
433
+ return { content: configSource, updated: false };
434
+ }
435
+ const inserted = configSource.replace(closingPattern, `\n global: [],\n route: {\n ${middlewareKey}: ${middlewareName},\n },\n} as MiddlewaresType;\n`);
436
+ return { content: inserted, updated: true };
437
+ };
438
+ const printManualMiddlewareRegistrationSnippet = (cmd, middlewareName, middlewareKey) => {
439
+ cmd.warn('Could not update config/middleware.ts automatically. Add this manually:');
440
+ cmd.info(`import { ${middlewareName} } from '@app/Middleware/${middlewareName}';`);
441
+ cmd.info(`route: { ${middlewareKey}: ${middlewareName} }`);
442
+ cmd.info(`Route typing example: type AppMiddlewareKey = MiddlewareKey | '${middlewareKey}';`);
443
+ };
444
+ const addMiddleware = async (cmd, middlewareName, opts) => {
445
+ const projectRoot = process.cwd();
446
+ let name = middlewareName ?? '';
447
+ if (name === '' && opts.noInteractive !== true) {
448
+ const answers = await promptMiddlewareConfig();
449
+ name = answers.name;
450
+ }
451
+ else if (name === '') {
452
+ throw ErrorFactory.createValidationError('Middleware name is required');
453
+ }
454
+ if (!/^[A-Z][a-zA-Z\d]*Middleware$/.test(name)) {
455
+ throw ErrorFactory.createValidationError('Middleware name must be PascalCase ending with "Middleware"');
456
+ }
457
+ const middlewareDir = path.join(projectRoot, 'app', 'Middleware');
458
+ const middlewarePath = path.join(middlewareDir, `${name}.ts`);
459
+ const configPath = path.join(projectRoot, 'config', 'middleware.ts');
460
+ const middlewareKey = buildMiddlewareKey(name);
461
+ ensureDirectoryExists(middlewareDir);
462
+ const created = FileGenerator.writeFile(middlewarePath, buildMiddlewareSource(name), {
463
+ overwrite: false,
464
+ });
465
+ if (!FileGenerator.fileExists(configPath)) {
466
+ cmd.success(`Middleware '${name}' created successfully!`);
467
+ cmd.warn('config/middleware.ts was not found, so registration was skipped.');
468
+ printManualMiddlewareRegistrationSnippet(cmd, name, middlewareKey);
469
+ return;
470
+ }
471
+ const currentConfig = FileGenerator.readFile(configPath);
472
+ const withImport = registerMiddlewareImport(currentConfig, name);
473
+ const registered = registerMiddlewareRouteKey(withImport, name, middlewareKey);
474
+ if (!registered.updated) {
475
+ cmd.success(`Middleware '${name}' created successfully!`);
476
+ printManualMiddlewareRegistrationSnippet(cmd, name, middlewareKey);
477
+ return;
478
+ }
479
+ fs.writeFileSync(configPath, registered.content, 'utf-8');
480
+ cmd.success(`Middleware '${name}' ${created ? 'created' : 'updated'} successfully!`);
481
+ cmd.info(`File: ${path.basename(middlewarePath)}`);
482
+ cmd.info(`Registered route key: ${middlewareKey}`);
483
+ cmd.info(`\nNext steps:\n • Use '${middlewareKey}' in route metadata\n • If your route file uses MiddlewareKey, extend it locally: type AppMiddlewareKey = MiddlewareKey | '${middlewareKey}'`);
484
+ };
372
485
  const getFactoryInitialConfig = (factoryName, opts) => {
373
486
  return {
374
487
  name: factoryName ?? '',
@@ -833,6 +946,7 @@ const TYPE_HANDLERS = {
833
946
  model: addModel,
834
947
  controller: addController,
835
948
  routes: addRoutes,
949
+ middleware: addMiddleware,
836
950
  factory: addFactory,
837
951
  seeder: addSeeder,
838
952
  requestfactory: addRequestFactory,
@@ -845,7 +959,7 @@ const TYPE_HANDLERS = {
845
959
  const handleType = async (cmd, type, name, opts) => {
846
960
  const handler = TYPE_HANDLERS[type];
847
961
  if (handler === undefined) {
848
- throw ErrorFactory.createCliError(`Unknown type "${type}". Use: service, feature, migration, model, controller, routes, factory, seeder, requestfactory, responsefactory, workflow, or governance`);
962
+ throw ErrorFactory.createCliError(`Unknown type "${type}". Use: service, feature, migration, model, controller, routes, middleware, factory, seeder, requestfactory, responsefactory, workflow, or governance`);
849
963
  }
850
964
  await handler(cmd, name, opts);
851
965
  };
@@ -874,7 +988,7 @@ const executeAdd = async (cmd, options) => {
874
988
  const addOpts = { ...options, ...commandOpts };
875
989
  try {
876
990
  if (type === undefined || type === '') {
877
- throw ErrorFactory.createCliError('Please specify what to add: service, feature, migration, model, controller, routes, factory, or seeder');
991
+ throw ErrorFactory.createCliError('Please specify what to add: service, feature, migration, model, controller, routes, middleware, factory, or seeder');
878
992
  }
879
993
  // Planned modular adapter syntax: `zin add db:sqlite` (delegate to plugin installer)
880
994
  const normalizedType = type.toLowerCase();
@@ -921,6 +1035,7 @@ export const AddCommand = Object.freeze({
921
1035
  promptModelConfig,
922
1036
  promptControllerConfig,
923
1037
  promptRoutesConfig,
1038
+ promptMiddlewareConfig,
924
1039
  promptFactoryConfig,
925
1040
  promptSeederConfig,
926
1041
  promptRequestFactoryConfig,
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { CommandOptions, IBaseCommand } from '../BaseCommand';
6
6
  type TemplateType = 'basic' | 'api' | 'microservice' | 'fullstack';
7
- type DatabaseType = 'sqlite' | 'mysql' | 'postgresql' | 'mongodb' | 'd1-remote';
7
+ type DatabaseType = 'sqlite' | 'mysql' | 'postgresql' | 'mongodb' | 'd1' | 'd1-remote';
8
8
  interface NewProjectConfigResult {
9
9
  template: TemplateType;
10
10
  database: DatabaseType;
@@ -1 +1 @@
1
- {"version":3,"file":"NewCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/NewCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgBrE,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,cAAc,GAAG,WAAW,CAAC;AACnE,KAAK,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AAYhF,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAwPhD,UAAU,WAAY,SAAQ,YAAY;IACxC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACxF,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACzF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,gBAAgB,EAAE,CAAC;IACjF,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC;IAChC,YAAY,IAAI,MAAM,CAAC;IACvB,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,sBAAsB,EAC9B,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpE;AA0RD;;;GAGG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;cACO,WAAW;EAGrB,CAAC"}
1
+ {"version":3,"file":"NewCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/NewCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgBrE,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,cAAc,GAAG,WAAW,CAAC;AACnE,KAAK,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,IAAI,GAAG,WAAW,CAAC;AAYvF,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA0PhD,UAAU,WAAY,SAAQ,YAAY;IACxC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACxF,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACzF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,gBAAgB,EAAE,CAAC;IACjF,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC;IAChC,YAAY,IAAI,MAAM,CAAC;IACvB,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,sBAAsB,EAC9B,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpE;AA8RD;;;GAGG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;cACO,WAAW;EAGrB,CAAC"}
@@ -54,6 +54,8 @@ const getProjectDefaults = (name, options) => {
54
54
  const v = value.trim();
55
55
  if (v === 'd1-proxy')
56
56
  return 'd1-remote';
57
+ if (v === 'd1')
58
+ return 'd1';
57
59
  if (v === 'd1-remote')
58
60
  return 'd1-remote';
59
61
  if (v === 'sqlite')
@@ -99,6 +101,7 @@ const getQuestions = (name, defaults) => {
99
101
  { name: 'sqlite — Local dev (file-based)', value: 'sqlite' },
100
102
  { name: 'postgresql — Production-ready relational DB', value: 'postgresql' },
101
103
  { name: 'mysql — Production-ready relational DB', value: 'mysql' },
104
+ { name: 'd1 — Cloudflare D1 database', value: 'd1' },
102
105
  { name: 'd1-proxy — Cloudflare D1 via HTTPS proxy', value: 'd1-remote' },
103
106
  { name: 'mongodb — Document DB (may require additional setup)', value: 'mongodb' },
104
107
  ],
@@ -223,7 +226,7 @@ const installDependencies = async (projectPath, log, packageManager, force = fal
223
226
  const addOptions = (command) => {
224
227
  command.argument('<name>', 'Project name');
225
228
  command.option('--template <type>', 'Project template (basic, api, microservice, fullstack)', 'basic');
226
- command.option('--database <type>', 'Database driver (sqlite, mysql, postgresql)', 'sqlite');
229
+ command.option('--database <type>', 'Database driver (sqlite, mysql, postgresql, d1, d1-remote, mongodb)', 'sqlite');
227
230
  command.option('--port <number>', 'Default port number', '7777');
228
231
  command.option('--author <name>', 'Project author');
229
232
  command.option('--description <text>', 'Project description');
@@ -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;AA21BvF,eAAO,MAAM,YAAY;cACb,YAAY;EAmCtB,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;AAs4BvF,eAAO,MAAM,YAAY;cACb,YAAY;EAmCtB,CAAC"}
@@ -2,9 +2,9 @@ import { BaseCommand } from '../BaseCommand.js';
2
2
  import { createDenoRunnerSource, createLambdaRunnerSource } from '../commands/runner/index.js';
3
3
  import { EnvFileLoader } from '../utils/EnvFileLoader.js';
4
4
  import { SpawnUtil } from '../utils/spawn.js';
5
- import { generateUuid } from '../../common/utility.js';
6
5
  import { readEnvString } from '../../common/ExternalServiceUtils.js';
7
6
  import * as Common from '../../common/index.js';
7
+ import { generateUuid } from '../../common/utility.js';
8
8
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
9
9
  import { isNonEmptyString } from '../../helper/index.js';
10
10
  import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from '../../node-singletons/fs.js';
@@ -303,7 +303,7 @@ const preloadManifestServiceEnv = async (context, options) => {
303
303
  process.env['ZINTRUST_PROJECT_ROOT'] = context.projectRoot;
304
304
  ProjectRuntime.clear();
305
305
  await ProjectRuntime.tryLoadNodeRuntime();
306
- const manifest = ProjectRuntime.getServiceManifest().filter((entry) => entry.monolithEnabled !== false);
306
+ const manifest = ProjectRuntime.getServiceManifest().filter((entry) => entry.monolithEnabled !== false && entry.loadEnv !== false);
307
307
  if (manifest.length === 0)
308
308
  return;
309
309
  const envPaths = manifest
@@ -418,6 +418,7 @@ const executeWranglerStart = async (cmd, context, port, runtime, envName, wrangl
418
418
  if (configPath === undefined && entry === undefined) {
419
419
  throw ErrorFactory.createCliError("Error: wrangler config not found (wrangler.toml/json). Run 'wrangler init' first.");
420
420
  }
421
+ warnOnUnsafeWranglerBootstrap(cmd, context.cwd, entry);
421
422
  const wranglerArgs = ['dev'];
422
423
  if (normalizedConfig !== '') {
423
424
  wranglerArgs.push('--config', normalizedConfig);
@@ -434,14 +435,42 @@ const executeWranglerStart = async (cmd, context, port, runtime, envName, wrangl
434
435
  logMySqlProxyHint(cmd);
435
436
  cmd.info('Starting in Wrangler dev mode...');
436
437
  const exitCode = await withWranglerEnvSnapshot(context.cwd, envName, async () => {
438
+ const startEnv = {
439
+ ...buildStartEnv(context.projectRoot),
440
+ WORKER_ENABLED: 'false',
441
+ CLOUDFLARE_WORKER: 'true',
442
+ DOCKER_WORKER: 'false',
443
+ };
437
444
  return SpawnUtil.spawnAndWait({
438
445
  command: 'wrangler',
439
446
  args: wranglerArgs,
440
- env: buildStartEnv(context.projectRoot),
447
+ env: startEnv,
441
448
  });
442
449
  });
443
450
  process.exit(exitCode);
444
451
  };
452
+ const isUnsafeWranglerBootstrapSource = (source) => {
453
+ const getKernelIndex = source.indexOf('getKernel(');
454
+ const cloudflareFetchIndex = source.indexOf('cloudflareWorker.fetch');
455
+ return (getKernelIndex !== -1 && cloudflareFetchIndex !== -1 && getKernelIndex < cloudflareFetchIndex);
456
+ };
457
+ const warnOnUnsafeWranglerBootstrap = (cmd, cwd, entry) => {
458
+ if (entry === undefined)
459
+ return;
460
+ const entryPath = path.join(cwd, entry);
461
+ if (!existsSync(entryPath))
462
+ return;
463
+ try {
464
+ const source = readFileSync(entryPath, 'utf-8');
465
+ if (!isUnsafeWranglerBootstrapSource(source))
466
+ return;
467
+ cmd.warn(`Unsafe Worker bootstrap detected in ${entry}: getKernel() runs before the core Cloudflare handler initializes Worker bindings.`);
468
+ cmd.warn('Use `export { default } from "../../start.js"` and keep custom middleware registration in config/middleware.ts or route metadata.');
469
+ }
470
+ catch {
471
+ // Best-effort warning only.
472
+ }
473
+ };
445
474
  const ensureTmpRunnerFile = (cwd, filename, content) => {
446
475
  const tmpDir = path.join(cwd, 'tmp');
447
476
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ProjectScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACtD,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IACpE,cAAc,IAAI,MAAM,CAAC;IACzB,sBAAsB,IAAI,OAAO,CAAC;IAClC,iBAAiB,IAAI,MAAM,CAAC;IAC5B,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAAC;IACtD,gBAAgB,IAAI,OAAO,CAAC;IAC5B,aAAa,IAAI,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC3E;AAodD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAsBrE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG;IAChE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAsBA;AA4ID;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,GAAE,MAAsB,GAAG,kBAAkB,CAsB/F;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAEhC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;EAM5B,CAAC"}
1
+ {"version":3,"file":"ProjectScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ProjectScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACtD,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IACpE,cAAc,IAAI,MAAM,CAAC;IACzB,sBAAsB,IAAI,OAAO,CAAC;IAClC,iBAAiB,IAAI,MAAM,CAAC;IAC5B,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAAC;IACtD,gBAAgB,IAAI,OAAO,CAAC;IAC5B,aAAa,IAAI,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC3E;AAodD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAsBrE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG;IAChE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAsBA;AA6ID;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,GAAE,MAAsB,GAAG,kBAAkB,CAsB/F;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAEhC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;EAM5B,CAAC"}
@@ -480,6 +480,7 @@ dist/
480
480
  .env
481
481
  .env.*
482
482
  .env.local
483
+ .dev*
483
484
  .DS_Store
484
485
  coverage/
485
486
  logs/
@@ -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;AAaD;;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;AAkcD,eAAO,MAAM,iBAAiB;;;;EAI5B,CAAC"}
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;AAaD;;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;AAocD,eAAO,MAAM,iBAAiB;;;;EAI5B,CAAC"}
@@ -110,6 +110,7 @@ export const serviceManifest: ReadonlyArray<ServiceManifestEntry> = [
110
110
  name: '${options.name}',
111
111
  configRoot: '${getServiceConfigRoot(domain, options.name)}',
112
112
  prefix: '${serviceId}',
113
+ loadEnv: false,
113
114
  port: ${options.port ?? 3001},
114
115
  monolithEnabled: true,
115
116
  loadRoutes: async () => ${routeImportExpression},
@@ -152,6 +153,7 @@ function updateServiceManifest(projectRoot, options) {
152
153
  name: '${options.name}',
153
154
  configRoot: '${getServiceConfigRoot(domain, options.name)}',
154
155
  prefix: '${serviceId}',
156
+ loadEnv: false,
155
157
  port: ${options.port ?? 3001},
156
158
  monolithEnabled: true,
157
159
  loadRoutes: async () => ${routeImportExpression},
@@ -1,4 +1,5 @@
1
1
  import type { MiddlewareConfigType } from './type';
2
+ import type { Middleware } from '../middleware/MiddlewareStack';
2
3
  export declare const MiddlewareBody: {
3
4
  readonly email: "email";
4
5
  readonly password: "password";
@@ -6,7 +7,7 @@ export declare const MiddlewareBody: {
6
7
  readonly count: "count";
7
8
  };
8
9
  export type MiddlewaresType = {
9
- skipPaths: string[];
10
+ skipPaths: ReadonlyArray<string>;
10
11
  fillRateLimit: {
11
12
  windowMs: number;
12
13
  max: number;
@@ -22,6 +23,8 @@ export type MiddlewaresType = {
22
23
  max: number;
23
24
  message: string;
24
25
  };
26
+ global?: ReadonlyArray<Middleware>;
27
+ route?: Record<string, Middleware>;
25
28
  };
26
29
  export declare const MiddlewareKeys: Readonly<{
27
30
  log: true;
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/config/middleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAiEzD,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,qBAAqB,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EAkBuB,CAAC;AAEnD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,cAAc,CAAC;AA2MxD,wBAAgB,sBAAsB,IAAI,oBAAoB,CAkC7D;AAID;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAAO,IAE7C,CAAC;AAwBF,eAAO,MAAM,gBAAgB,EAAE,oBAY7B,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/config/middleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAUzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAwD9D,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjC,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,qBAAqB,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E,MAAM,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EAkBuB,CAAC;AAEnD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,cAAc,CAAC;AAoOxD,wBAAgB,sBAAsB,IAAI,oBAAoB,CAwC7D;AAID;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAAO,IAE7C,CAAC;AAwBF,eAAO,MAAM,gBAAgB,EAAE,oBAY7B,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { Env } from './env.js';
2
+ import { isArray, isObject } from '../helper/index.js';
2
3
  import { bodyParsingMiddleware } from '../http/middleware/BodyParsingMiddleware.js';
3
4
  import { fileUploadMiddleware } from '../http/middleware/FileUploadMiddleware.js';
4
5
  import { AuthMiddleware } from '../middleware/AuthMiddleware.js';
@@ -157,6 +158,22 @@ function createSharedMiddlewares(loadMiddlewareConfig) {
157
158
  ...validations,
158
159
  });
159
160
  }
161
+ const resolveProjectGlobalMiddlewares = (loadMiddlewareConfig) => {
162
+ if (!isArray(loadMiddlewareConfig.global))
163
+ return [];
164
+ return loadMiddlewareConfig.global.filter((middleware) => {
165
+ return typeof middleware === 'function';
166
+ });
167
+ };
168
+ const resolveProjectRouteMiddlewares = (loadMiddlewareConfig) => {
169
+ if (!isObject(loadMiddlewareConfig.route))
170
+ return {};
171
+ const entries = Object.entries(loadMiddlewareConfig.route).filter((entry) => {
172
+ const [name, middleware] = entry;
173
+ return typeof name === 'string' && name.trim() !== '' && typeof middleware === 'function';
174
+ });
175
+ return Object.fromEntries(entries);
176
+ };
160
177
  export function createMiddlewareConfig() {
161
178
  const loadMiddlewareConfig = StartupConfigFileRegistry.get(StartupConfigFile.Middleware) ?? {};
162
179
  const skipPathsFromEnv = Env.get('CSRF_SKIP_PATHS', '')
@@ -170,6 +187,8 @@ export function createMiddlewareConfig() {
170
187
  : skipPathsFromEnv,
171
188
  };
172
189
  const shared = createSharedMiddlewares(effectiveMiddlewareConfig);
190
+ const projectGlobal = resolveProjectGlobalMiddlewares(effectiveMiddlewareConfig);
191
+ const projectRoute = resolveProjectRouteMiddlewares(effectiveMiddlewareConfig);
173
192
  const middlewareConfigObj = {
174
193
  global: [
175
194
  shared.log,
@@ -180,8 +199,12 @@ export function createMiddlewareConfig() {
180
199
  bodyParsingMiddleware,
181
200
  shared.csrf,
182
201
  shared.sanitizeBody,
202
+ ...projectGlobal,
183
203
  ],
184
- route: shared,
204
+ route: {
205
+ ...shared,
206
+ ...projectRoute,
207
+ },
185
208
  };
186
209
  return Object.freeze(middlewareConfigObj);
187
210
  }
package/src/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @zintrust/core v0.4.14
2
+ * @zintrust/core v0.4.16
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-23T16:59:39.933Z
8
+ * Built: 2026-03-24T13:49:16.905Z
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-23T16:59:39.858Z'; // Replaced during build
24
+ export const ZINTRUST_BUILD_DATE = '2026-03-24T13:49:16.870Z'; // 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';
@@ -5,6 +5,7 @@ export interface ServiceManifestEntry {
5
5
  name: string;
6
6
  prefix?: string;
7
7
  configRoot?: string;
8
+ loadEnv?: boolean;
8
9
  version?: string;
9
10
  description?: string;
10
11
  port?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceManifest.d.ts","sourceRoot":"","sources":["../../../src/microservices/ServiceManifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ServiceManifest.d.ts","sourceRoot":"","sources":["../../../src/microservices/ServiceManifest.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,10 @@ export const isServiceManifestEntry = (value) => {
50
50
  if (configRoot !== undefined && typeof configRoot !== 'string') {
51
51
  return false;
52
52
  }
53
+ const loadEnv = value['loadEnv'];
54
+ if (loadEnv !== undefined && typeof loadEnv !== 'boolean') {
55
+ return false;
56
+ }
53
57
  const loadRoutes = value['loadRoutes'];
54
58
  if (loadRoutes !== undefined && !isFunction(loadRoutes)) {
55
59
  return false;
@@ -64,6 +68,7 @@ export const normalizeServiceManifest = (value) => {
64
68
  id: toCanonicalServiceId(entry),
65
69
  prefix: getServicePrefix(entry),
66
70
  ...(isNonEmptyString(entry.configRoot) ? { configRoot: entry.configRoot } : {}),
71
+ loadEnv: entry.loadEnv !== false,
67
72
  monolithEnabled: entry.monolithEnabled !== false,
68
73
  }));
69
74
  };
@@ -17,7 +17,7 @@ export interface CsrfOptions {
17
17
  * - `/api/*`
18
18
  * - `/api/v1/auth/login`
19
19
  */
20
- skipPaths?: string[];
20
+ skipPaths?: ReadonlyArray<string>;
21
21
  }
22
22
  export declare const CsrfMiddleware: Readonly<{
23
23
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"CsrfMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/CsrfMiddleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAK9D,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAkDD,eAAO,MAAM,cAAc;IACzB;;OAEG;qBACa,WAAW,GAAQ,UAAU;EA6D7C,CAAC"}
1
+ {"version":3,"file":"CsrfMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/CsrfMiddleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAK9D,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACnC;AAkDD,eAAO,MAAM,cAAc;IACzB;;OAEG;qBACa,WAAW,GAAQ,UAAU;EA6D7C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectRuntime.d.ts","sourceRoot":"","sources":["../../../src/runtime/ProjectRuntime.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,gCAAgC,CAAC;AA+ExC,eAAO,MAAM,cAAc;aAChB,IAAI;iBAIA,oBAAoB,GAAG,SAAS;gBAIjC,OAAO,GAAG,oBAAoB;oCAIV,OAAO,GAAG,oBAAoB,GAAG,SAAS;0BAM9C,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;4BAgBvC,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;0BAejD,aAAa,CAAC,oBAAoB,CAAC;wBAIrC,oBAAoB,GAAG,SAAS;EAGpD,CAAC;AAEH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"ProjectRuntime.d.ts","sourceRoot":"","sources":["../../../src/runtime/ProjectRuntime.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,gCAAgC,CAAC;AAoGxC,eAAO,MAAM,cAAc;aAChB,IAAI;iBAIA,oBAAoB,GAAG,SAAS;gBAIjC,OAAO,GAAG,oBAAoB;oCAIV,OAAO,GAAG,oBAAoB,GAAG,SAAS;0BAM9C,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;4BAgBvC,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;0BAOjD,aAAa,CAAC,oBAAoB,CAAC;wBAIrC,oBAAoB,GAAG,SAAS;EAGpD,CAAC;AAEH,eAAe,cAAc,CAAC"}
@@ -52,10 +52,27 @@ const tryImportNodeRuntimeCandidate = async (candidate) => {
52
52
  return undefined;
53
53
  }
54
54
  };
55
- const tryImportWorkerRuntimeCandidate = async (moduleId) => {
55
+ const tryImportWorkerRuntimeLiteralCandidates = async () => {
56
56
  try {
57
- const runtimeModule = (await import(moduleId));
58
- return cacheProjectRuntime(runtimeModule);
57
+ return cacheProjectRuntime((await import('../zintrust.runtime.wg.js')));
58
+ }
59
+ catch {
60
+ // continue
61
+ }
62
+ try {
63
+ return cacheProjectRuntime((await import('../zintrust.runtime.js')));
64
+ }
65
+ catch {
66
+ // continue
67
+ }
68
+ try {
69
+ return cacheProjectRuntime((await import('../index.js' + 'zintrust.runtime.wg.js')));
70
+ }
71
+ catch {
72
+ // continue
73
+ }
74
+ try {
75
+ return cacheProjectRuntime((await import('../index.js' + 'zintrust.runtime.js')));
59
76
  }
60
77
  catch {
61
78
  return undefined;
@@ -95,14 +112,7 @@ export const ProjectRuntime = Object.freeze({
95
112
  const cached = getCachedProjectRuntime();
96
113
  if (hasLoadedServiceManifest(cached))
97
114
  return cached;
98
- const workerModuleIds = ['../' + 'zintrust.runtime.wg.js', '../' + 'zintrust.runtime.js'];
99
- for (const moduleId of workerModuleIds) {
100
- // eslint-disable-next-line no-await-in-loop
101
- const loaded = await tryImportWorkerRuntimeCandidate(moduleId);
102
- if (loaded !== undefined)
103
- return loaded;
104
- }
105
- return undefined;
115
+ return tryImportWorkerRuntimeLiteralCandidates();
106
116
  },
107
117
  getServiceManifest() {
108
118
  return getCachedProjectRuntime()?.serviceManifest ?? [];
@@ -1 +1 @@
1
- {"version":3,"file":"WorkerAdapterImports.d.ts","sourceRoot":"","sources":["../../../src/runtime/WorkerAdapterImports.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,oBAAoB;;;EAG/B,CAAC"}
1
+ {"version":3,"file":"WorkerAdapterImports.d.ts","sourceRoot":"","sources":["../../../src/runtime/WorkerAdapterImports.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,oBAAoB;;;EAG/B,CAAC"}
@@ -1,8 +1,25 @@
1
1
  // Worker-only adapter auto-imports for bundler-based runtimes (e.g. Cloudflare Workers).
2
2
  // Keep this list limited to database adapters needed by runtime config.
3
+ import { ProjectRuntime } from './ProjectRuntime.js';
4
+ const tryImportProjectRuntime = async () => {
5
+ try {
6
+ ProjectRuntime.set(await import('../zintrust.runtime.wg.js'));
7
+ return;
8
+ }
9
+ catch {
10
+ // continue
11
+ }
12
+ try {
13
+ ProjectRuntime.set(await import('../zintrust.runtime.js'));
14
+ }
15
+ catch {
16
+ // Ignore missing runtime modules. Worker startup can still proceed without them.
17
+ }
18
+ };
3
19
  // These imports resolve against the host project (developer working directory)
4
20
  // via the @/ alias configured by the ZinTrust app templates.
5
21
  const tryImportOptional = async () => {
22
+ await tryImportProjectRuntime();
6
23
  try {
7
24
  await import('../zintrust.plugins.wg.js');
8
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WorkersModule.d.ts","sourceRoot":"","sources":["../../../src/runtime/WorkersModule.ts"],"names":[],"mappings":"AAOA,KAAK,aAAa,GAAG,cAAc,mBAAmB,CAAC,CAAC;AACxD,KAAK,kBAAkB,GAAG,cAAc,yBAAyB,CAAC,CAAC;AA+TnE,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,aAAa,CAwB/D,CAAC;AA2CF,eAAO,MAAM,sBAAsB,QAAa,OAAO,CAAC,kBAAkB,CAiBzE,CAAC"}
1
+ {"version":3,"file":"WorkersModule.d.ts","sourceRoot":"","sources":["../../../src/runtime/WorkersModule.ts"],"names":[],"mappings":"AAOA,KAAK,aAAa,GAAG,cAAc,mBAAmB,CAAC,CAAC;AACxD,KAAK,kBAAkB,GAAG,cAAc,yBAAyB,CAAC,CAAC;AA4WnE,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,aAAa,CAwB/D,CAAC;AA4CF,eAAO,MAAM,sBAAsB,QAAa,OAAO,CAAC,kBAAkB,CAkBzE,CAAC"}
@@ -194,6 +194,9 @@ const importLocalModule = async (packageDir, packageName) => {
194
194
  };
195
195
  const importLocalWorkersModule = async () => importLocalModule('workers', '@zintrust/workers');
196
196
  const importLocalQueueMonitorModule = async () => importLocalModule('queue-monitor', '@zintrust/queue-monitor');
197
+ const importOptionalPackage = async (specifier) => {
198
+ return (await import(specifier));
199
+ };
197
200
  let workersModulePromise;
198
201
  let patchAttempted = false;
199
202
  let patchAfterFailureAttempted = false;
@@ -234,12 +237,35 @@ const applyInitialPatches = () => {
234
237
  Logger.warn('Rewrote @zintrust/queue-monitor ESM specifiers before import', monitorPatch);
235
238
  }
236
239
  };
240
+ const getErrorChain = (error) => {
241
+ const chain = [];
242
+ const seen = new Set();
243
+ let current = error;
244
+ while (current !== null && current !== undefined && !seen.has(current)) {
245
+ seen.add(current);
246
+ const entry = current;
247
+ chain.push({
248
+ message: typeof entry.message === 'string' && entry.message !== '' ? entry.message : String(current),
249
+ code: typeof entry.code === 'string' ? entry.code : undefined,
250
+ });
251
+ current = entry.cause;
252
+ }
253
+ return chain;
254
+ };
237
255
  const shouldRetryAfterFailure = (error) => {
238
256
  if (patchAfterFailureAttempted)
239
257
  return false;
240
- const message = error instanceof Error ? error.message : String(error);
241
- const code = error?.code;
242
- return code === 'ERR_MODULE_NOT_FOUND' && message.includes('@zintrust/workers');
258
+ return getErrorChain(error).some(({ message, code }) => code === 'ERR_MODULE_NOT_FOUND' && message.includes('@zintrust/workers'));
259
+ };
260
+ const isMissingOptionalWorkersModuleError = (error) => {
261
+ return getErrorChain(error).some(({ message, code }) => {
262
+ if (!message.includes('@zintrust/workers'))
263
+ return false;
264
+ return (code === 'ERR_MODULE_NOT_FOUND' ||
265
+ message.includes('ERR_MODULE_NOT_FOUND') ||
266
+ message.includes('Cannot find package') ||
267
+ message.includes('No such module'));
268
+ });
243
269
  };
244
270
  const handleImportFailure = async (error) => {
245
271
  if (shouldRetryAfterFailure(error)) {
@@ -250,8 +276,13 @@ const handleImportFailure = async (error) => {
250
276
  filesChanged,
251
277
  replacements,
252
278
  });
253
- workersModulePromise = import('@zintrust/workers');
254
- return workersModulePromise;
279
+ workersModulePromise = importOptionalPackage('@zintrust/workers');
280
+ try {
281
+ return await workersModulePromise;
282
+ }
283
+ catch (retryError) {
284
+ error = retryError;
285
+ }
255
286
  }
256
287
  }
257
288
  const localFallback = await importLocalWorkersModule();
@@ -259,6 +290,11 @@ const handleImportFailure = async (error) => {
259
290
  workersModulePromise = Promise.resolve(localFallback);
260
291
  return localFallback;
261
292
  }
293
+ if (isMissingOptionalWorkersModuleError(error)) {
294
+ Logger.info('Optional @zintrust/workers package is unavailable; worker routes are disabled.');
295
+ workersModulePromise = Promise.resolve(createDisabledWorkersModule());
296
+ return workersModulePromise;
297
+ }
262
298
  throw error;
263
299
  };
264
300
  const tryLocalFallback = async () => {
@@ -283,7 +319,7 @@ export const loadWorkersModule = async () => {
283
319
  }
284
320
  }
285
321
  logWorkersResolverDiagnostics();
286
- workersModulePromise ??= import('@zintrust/workers');
322
+ workersModulePromise ??= importOptionalPackage('@zintrust/workers');
287
323
  try {
288
324
  return await workersModulePromise;
289
325
  }
@@ -307,7 +343,8 @@ const handleQueueMonitorImportFailure = async (error) => {
307
343
  filesChanged,
308
344
  replacements,
309
345
  });
310
- queueMonitorModulePromise = import('@zintrust/queue-monitor');
346
+ queueMonitorModulePromise =
347
+ importOptionalPackage('@zintrust/queue-monitor');
311
348
  return queueMonitorModulePromise;
312
349
  }
313
350
  }
@@ -334,7 +371,8 @@ export const loadQueueMonitorModule = async () => {
334
371
  return localFallback;
335
372
  }
336
373
  }
337
- queueMonitorModulePromise ??= import('@zintrust/queue-monitor');
374
+ queueMonitorModulePromise ??=
375
+ importOptionalPackage('@zintrust/queue-monitor');
338
376
  try {
339
377
  return await queueMonitorModulePromise;
340
378
  }
@@ -1,14 +1,21 @@
1
1
  // @ts-ignore - config templates are excluded from the main TS project in this repo
2
+ import { Env } from '@zintrust/core';
3
+ import type { MiddlewaresType } from '@zintrust/core';
2
4
  /**
3
5
  * Middleware Configuration (template)
4
6
  *
5
- * Keep this file declarative:
6
- * - Core owns middleware construction / any runtime behavior.
7
- * - Projects can override by editing `middlewareConfigObj`.
7
+ * Full project middleware flow:
8
+ * 1. Create `app/Middleware/YourMiddleware.ts` and export a `Middleware` function.
9
+ * 2. Import it below.
10
+ * 3. Register route middleware under `route` or append global middleware under `global`.
11
+ * 4. Use the route key in `routes/*.ts`.
12
+ *
13
+ * For custom route keys, extend the framework type locally in your route file:
14
+ * `type AppMiddlewareKey = MiddlewareKey | 'yourMiddleware';`
8
15
  */
9
16
 
10
- import { Env } from '@zintrust/core';
11
- import type { MiddlewaresType } from '@zintrust/core';
17
+ // Example custom middleware import:
18
+ // import { AuthMiddleware } from '@app/Middleware/AuthMiddleware';
12
19
 
13
20
  export default {
14
21
  skipPaths: Env.get('CSRF_SKIP_PATHS', '')
@@ -30,4 +37,10 @@ export default {
30
37
  max: 20,
31
38
  message: 'Too many user mutation requests, please try again later.',
32
39
  },
40
+ global: [
41
+ // AuthMiddleware,
42
+ ],
43
+ route: {
44
+ // authMiddleware: AuthMiddleware,
45
+ },
33
46
  } as MiddlewaresType;
@@ -6,3 +6,8 @@
6
6
  */
7
7
 
8
8
  // Intentionally empty by default.
9
+
10
+ import { ProjectRuntime } from '@zintrust/core';
11
+ import serviceManifest from './bootstrap/service-manifest';
12
+
13
+ ProjectRuntime.set({ serviceManifest });