@zintrust/core 0.4.8 → 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.
Files changed (65) hide show
  1. package/package.json +1 -1
  2. package/src/boot/bootstrap.js +7 -0
  3. package/src/boot/registry/registerRoute.d.ts.map +1 -1
  4. package/src/boot/registry/registerRoute.js +23 -0
  5. package/src/bootstrap/service-manifest.d.ts +4 -0
  6. package/src/bootstrap/service-manifest.d.ts.map +1 -0
  7. package/src/bootstrap/service-manifest.js +2 -0
  8. package/src/cli/commands/InitContainerCommand.d.ts.map +1 -1
  9. package/src/cli/commands/InitContainerCommand.js +1 -60
  10. package/src/cli/commands/MigrateCommand.js +1 -1
  11. package/src/cli/commands/RoutesCommand.d.ts.map +1 -1
  12. package/src/cli/commands/RoutesCommand.js +36 -1
  13. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  14. package/src/cli/commands/StartCommand.js +73 -35
  15. package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
  16. package/src/cli/scaffolding/RouteGenerator.js +4 -2
  17. package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
  18. package/src/cli/scaffolding/ServiceScaffolder.js +147 -29
  19. package/src/common/ExternalServiceUtils.d.ts +2 -2
  20. package/src/functions/cloudflare.d.ts.map +1 -1
  21. package/src/functions/cloudflare.js +76 -16
  22. package/src/index.d.ts +16 -13
  23. package/src/index.d.ts.map +1 -1
  24. package/src/index.js +16 -14
  25. package/src/microservices/MicroserviceBootstrap.d.ts +1 -0
  26. package/src/microservices/MicroserviceBootstrap.d.ts.map +1 -1
  27. package/src/microservices/MicroserviceBootstrap.js +51 -7
  28. package/src/microservices/MicroserviceGenerator.d.ts.map +1 -1
  29. package/src/microservices/MicroserviceGenerator.js +12 -14
  30. package/src/microservices/MicroserviceManager.d.ts +1 -0
  31. package/src/microservices/MicroserviceManager.d.ts.map +1 -1
  32. package/src/microservices/MicroserviceManager.js +85 -62
  33. package/src/microservices/ServiceManifest.d.ts +50 -0
  34. package/src/microservices/ServiceManifest.d.ts.map +1 -0
  35. package/src/microservices/ServiceManifest.js +82 -0
  36. package/src/runtime/OverrideValueMerge.d.ts +3 -0
  37. package/src/runtime/OverrideValueMerge.d.ts.map +1 -0
  38. package/src/runtime/OverrideValueMerge.js +14 -0
  39. package/src/runtime/PluginAutoImports.d.ts.map +1 -1
  40. package/src/runtime/PluginAutoImports.js +1 -5
  41. package/src/runtime/ProjectRuntime.d.ts +13 -0
  42. package/src/runtime/ProjectRuntime.d.ts.map +1 -0
  43. package/src/runtime/ProjectRuntime.js +111 -0
  44. package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -1
  45. package/src/runtime/StartupConfigFileRegistry.js +33 -8
  46. package/src/scripts/TemplateImportsCheck.js +0 -2
  47. package/src/start.d.ts +3 -0
  48. package/src/start.d.ts.map +1 -1
  49. package/src/start.js +17 -0
  50. package/src/templates/project/basic/src/bootstrap/service-manifest.ts.tpl +5 -0
  51. package/src/templates/project/basic/src/zintrust.runtime.ts.tpl +9 -0
  52. package/src/templates/project/basic/src/zintrust.runtime.wg.ts.tpl +9 -0
  53. package/src/templates/project/basic/wrangler.jsonc.tpl +1 -0
  54. package/src/zintrust.comon.d.ts +9 -0
  55. package/src/zintrust.comon.d.ts.map +1 -0
  56. package/src/zintrust.comon.js +15 -0
  57. package/src/zintrust.plugins.d.ts +6 -3
  58. package/src/zintrust.plugins.d.ts.map +1 -1
  59. package/src/zintrust.plugins.js +27 -3
  60. package/src/zintrust.runtime.d.ts +4 -0
  61. package/src/zintrust.runtime.d.ts.map +1 -0
  62. package/src/zintrust.runtime.js +3 -0
  63. package/src/zintrust.runtime.wg.d.ts +4 -0
  64. package/src/zintrust.runtime.wg.d.ts.map +1 -0
  65. package/src/zintrust.runtime.wg.js +3 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -9,6 +9,7 @@ import { appConfig } from '../config/app.js';
9
9
  import { Env } from '../config/env.js';
10
10
  import { Logger } from '../config/logger.js';
11
11
  import { ErrorFactory } from '../exceptions/ZintrustError.js';
12
+ import { ProjectRuntime } from '../runtime/ProjectRuntime.js';
12
13
  import { loadWorkersModule } from '../runtime/WorkersModule.js';
13
14
  let appInstance;
14
15
  let serverInstance;
@@ -211,6 +212,12 @@ const BootstrapFunctions = Object.freeze({
211
212
  // best-effort; run without plugins if loader fails (e.g. non-Node runtime)
212
213
  Logger.warn('Plugin auto-imports loader skipped:', error);
213
214
  }
215
+ try {
216
+ await ProjectRuntime.tryLoadNodeRuntime();
217
+ }
218
+ catch (error) {
219
+ Logger.warn('Project runtime hook loader skipped:', error);
220
+ }
214
221
  // Create application instance
215
222
  // if (Env.ZINTRUST_PROJECT_ROOT) {
216
223
  // }
@@ -1 +1 @@
1
- {"version":3,"file":"registerRoute.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/registerRoute.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAQnD,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;AAkEF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAmBd,CAAC"}
1
+ {"version":3,"file":"registerRoute.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/registerRoute.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAUnD,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;AAuFF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAoBd,CAAC"}
@@ -1,8 +1,10 @@
1
1
  import { appConfig } from '../../config/index.js';
2
2
  import Logger from '../../config/logger.js';
3
+ import { isObject } from '../../helper/index.js';
3
4
  import * as path from '../../node-singletons/path.js';
4
5
  import { pathToFileURL } from '../../node-singletons/url.js';
5
6
  import { detectRuntime } from '../../runtime/detectRuntime.js';
7
+ import { ProjectRuntime } from '../../runtime/ProjectRuntime.js';
6
8
  const isCloudflare = detectRuntime().isCloudflare;
7
9
  export const isCompiledJsModule = () => {
8
10
  // When running from dist, this module is compiled to .js and Node ESM resolution
@@ -59,6 +61,26 @@ const registerAppRoutes = async (resolvedBasePath, router) => {
59
61
  mod.registerRoutes(router);
60
62
  }
61
63
  };
64
+ const registerManifestRoutes = async (router) => {
65
+ const serviceManifest = ProjectRuntime.getServiceManifest();
66
+ if (serviceManifest.length === 0)
67
+ return;
68
+ for (const entry of serviceManifest) {
69
+ if (entry.monolithEnabled === false || typeof entry.loadRoutes !== 'function') {
70
+ continue;
71
+ }
72
+ try {
73
+ // eslint-disable-next-line no-await-in-loop
74
+ const mod = await entry.loadRoutes();
75
+ if (isObject(mod) && typeof mod.registerRoutes === 'function') {
76
+ mod.registerRoutes(router);
77
+ }
78
+ }
79
+ catch (error) {
80
+ Logger.warn(`Failed to register manifest routes for ${entry.id}`, error);
81
+ }
82
+ }
83
+ };
62
84
  const registerFrameworkRoutes = async (resolvedBasePath, router) => {
63
85
  const frameworkRoutes = await tryImportRoutesFromAppBase(resolvedBasePath);
64
86
  if (frameworkRoutes && typeof frameworkRoutes.registerRoutes === 'function') {
@@ -82,6 +104,7 @@ export const registerMasterRoutes = async (resolvedBasePath, router) => {
82
104
  if (!isCloudflare) {
83
105
  await registerAppRoutes(resolvedBasePath, router);
84
106
  }
107
+ await registerManifestRoutes(router);
85
108
  if (router.routes.length === 0) {
86
109
  await registerFrameworkRoutes(resolvedBasePath, router);
87
110
  }
@@ -0,0 +1,4 @@
1
+ import type { ServiceManifestEntry } from '../microservices/ServiceManifest';
2
+ export declare const serviceManifest: ReadonlyArray<ServiceManifestEntry>;
3
+ export default serviceManifest;
4
+ //# sourceMappingURL=service-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-manifest.d.ts","sourceRoot":"","sources":["../../../src/bootstrap/service-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,oBAAoB,CAAM,CAAC;AAEvE,eAAe,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const serviceManifest = [];
2
+ export default serviceManifest;
@@ -1 +1 @@
1
- {"version":3,"file":"InitContainerCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/InitContainerCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAoOlE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAkBtB,CAAC"}
1
+ {"version":3,"file":"InitContainerCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/InitContainerCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyKlE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAkBtB,CAAC"}
@@ -97,80 +97,21 @@ services:
97
97
  - '7772:7772'
98
98
 
99
99
  `;
100
- const DOCKERFILE_TEMPLATE = String.raw `# syntax=docker/dockerfile:1.6
101
- # Build Stage - Compile TypeScript
102
- FROM node:20-bookworm-slim AS builder
100
+ const DOCKERFILE_TEMPLATE = String.raw `FROM zintrust/zintrust:latest AS runtime
103
101
 
104
102
  WORKDIR /app
105
103
 
106
- # Reuse npm cache across builds (requires BuildKit)
107
- ENV NPM_CONFIG_CACHE=/root/.npm
108
- ENV NPM_CONFIG_PREFER_OFFLINE=true
109
-
110
- # Install build dependencies for native modules (better-sqlite3, bcrypt)
111
- RUN apt-get update \
112
- && apt-get install -y --no-install-recommends python3 make g++ \
113
- && rm -rf /var/lib/apt/lists/*
114
-
115
- # Copy package files
116
- COPY package.json package-lock.json ./
117
-
118
- # Install dependencies (including dev dependencies needed for build)
119
- RUN --mount=type=cache,target=/root/.npm,id=zintrust-npm-cache,sharing=locked \
120
- npm config set fetch-retries 5 \
121
- && npm config set fetch-retry-mintimeout 20000 \
122
- && npm config set fetch-retry-maxtimeout 120000 \
123
- && npm ci
124
-
125
- # Copy source code using COPY . . to handle optional folders automatically
126
- COPY . .
127
-
128
- # Build TypeScript to JavaScript
129
- ARG BUILD_VARIANT=full
130
- RUN --mount=type=cache,target=/root/.npm,id=zintrust-npm-cache,sharing=locked npm run build:dk
131
-
132
- # Runtime Stage - Production image
133
- FROM node:20-bookworm-slim AS runtime
134
-
135
- WORKDIR /app
136
-
137
- # Set environment variables
138
104
  ENV NODE_ENV=production
139
105
  ENV PORT=7772
140
106
  ENV HOST=0.0.0.0
141
107
 
142
- # Create non-root user for security
143
- RUN groupadd -g 1001 nodejs && useradd -u 1001 -g 1001 -m -s /usr/sbin/nologin nodejs
144
-
145
- # Copy package files for production dependencies
146
- COPY package.json package-lock.json ./
147
-
148
- # Install only production dependencies (requires build tools for native modules)
149
- RUN --mount=type=cache,target=/root/.npm,id=zintrust-npm-cache,sharing=locked \
150
- apt-get update \
151
- && apt-get install -y --no-install-recommends python3 make g++ \
152
- && npm ci --omit=dev \
153
- && apt-get purge -y --auto-remove python3 make g++ \
154
- && rm -rf /var/lib/apt/lists/*
155
-
156
- # Copy compiled code from builder stage
157
- COPY --from=builder /app/dist ./dist
158
-
159
-
160
- # Change ownership to nodejs user
161
- RUN chown -R nodejs:nodejs /app
162
-
163
- # Switch to non-root user
164
108
  USER nodejs
165
109
 
166
- # Health check
167
110
  HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
168
111
  CMD node -e "require('node:http').get('http://localhost:7772/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
169
112
 
170
- # Expose port
171
113
  EXPOSE 7772
172
114
 
173
- # Start application (compiled JS; no tsx needed in runtime)
174
115
  CMD ["node", "dist/src/boot/bootstrap.js"]
175
116
  `;
176
117
  const backupSuffix = () => new Date().toISOString().replaceAll(/[:.]/g, '-');
@@ -215,7 +215,7 @@ const warnIfAdapterMissing = (cmd, conn) => {
215
215
  if (conn.driver === 'mysql' && DatabaseAdapterRegistry.get('mysql') === undefined) {
216
216
  cmd.warn('MySQL adapter is not installed/registered; migrations may not hit a real MySQL DB.');
217
217
  cmd.warn('Install via `zin plugin install adapter:mysql` (or `zin add db:mysql`).');
218
- cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "@zintrust/db-mysql/register";');
218
+ cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "../../../packages/db-mysql/src/register";');
219
219
  }
220
220
  if (conn.driver === 'postgresql' && DatabaseAdapterRegistry.get('postgresql') === undefined) {
221
221
  cmd.warn('PostgreSQL adapter is not installed/registered; migrations may not hit a real PostgreSQL DB.');
@@ -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;AAsSvF,eAAO,MAAM,aAAa;cACd,YAAY;EAatB,CAAC;AAEH,eAAe,aAAa,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;AAspBvF,eAAO,MAAM,YAAY;cACb,YAAY;EA6BtB,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 readPackageJson = (cwd) => {
172
- const packagePath = path.join(cwd, 'package.json');
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, cwd, port, runtime, envName, wranglerConfig) => {
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: process.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, cwd, mode, watchEnabled, _port, runtime) => {
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({ command: 'tsx', args, env: process.env });
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, cwd, mode, watchEnabled, _port, runtime) => {
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({ command: 'tsx', args, env: process.env });
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, cwd, mode, watchEnabled, _port) => {
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: process.env,
408
+ env: buildStartEnv(context.projectRoot),
372
409
  });
373
410
  process.exit(exitCode);
374
411
  }
375
- const packageJson = readPackageJson(cwd);
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: process.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: process.env,
428
+ env: buildStartEnv(context.projectRoot),
393
429
  });
394
430
  process.exit(exitCode);
395
431
  };
396
- const executeSplitStart = async (cmd, cwd, _options) => {
432
+ const executeSplitStart = async (cmd, context, _options) => {
397
433
  cmd.info('🚀 Starting in split mode (Producer + Consumer)...');
398
- const packageJson = readPackageJson(cwd);
399
- const webDev = resolveNodeDevCommand(cwd, packageJson);
434
+ const webDev = resolveNodeDevCommand(context.cwd, requirePackageJson(context));
400
435
  // Producer Environment
401
436
  const producerEnv = {
402
- ...process.env,
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
- ...process.env,
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(cwd, 'bin/zin.ts'))
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(cwd, 'bin/zin.ts')) ? 'tsx' : 'node';
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, cwd, options);
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, cwd, port, runtime, envName === '' ? undefined : envName, wranglerConfig);
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, cwd, mode, watchEnabled, port, runtime);
518
+ await executeDenoStart(cmd, context, mode, watchEnabled, port, runtime);
481
519
  return;
482
520
  }
483
521
  if (variant === 'lambda') {
484
- await executeLambdaStart(cmd, cwd, mode, watchEnabled, port, runtime);
522
+ await executeLambdaStart(cmd, context, mode, watchEnabled, port, runtime);
485
523
  return;
486
524
  }
487
- await executeNodeStart(cmd, cwd, mode, watchEnabled, port);
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":"RouteGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/RouteGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAuBD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAqB3F;AAED;;GAEG;AAEH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4CnF;AA4LD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,EAAE,CAsCpD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,eAAe,EAAE,CA6BjD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,eAAe,EAAE,CA+BlD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,EAAE,CAEhD;AAED;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;EAOzB,CAAC"}
1
+ {"version":3,"file":"RouteGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/RouteGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAuBD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAqB3F;AAED;;GAEG;AAEH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4CnF;AA8LD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,EAAE,CAsCpD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,eAAe,EAAE,CA6BjD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,eAAe,EAAE,CA+BlD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,EAAE,CAEhD;AAED;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;EAOzB,CAAC"}
@@ -115,7 +115,9 @@ ${routeRegistration}
115
115
  * Build import statements
116
116
  */
117
117
  function buildImports(options) {
118
- const imports = ["import { Router, type IRouter } from '../../index.js';"];
118
+ const imports = [
119
+ "import { Router, type IRequest, type IResponse, type IRouter } from '../../index.js';",
120
+ ];
119
121
  // Collect unique controllers
120
122
  const controllers = new Set();
121
123
  for (const route of options.routes) {
@@ -208,7 +210,7 @@ function buildMethodRoute(route, router, groupMiddlewareList) {
208
210
  const middlewareProp = buildMiddlewareProp(route, groupMiddlewareList);
209
211
  const metaProp = `meta: { summary: ${escapeUnsafeChars(JSON.stringify(summary))}, tags: [${escapeUnsafeChars(JSON.stringify(tag))}] }`;
210
212
  const options = `{ ${[middlewareProp, metaProp].filter((v) => v !== '').join(', ')} }`;
211
- return ` Router.${method}(${router}, '${routePath}', (req, res) => ${controllerVar}.${action}(req, res), ${options});\n`;
213
+ return ` Router.${method}(${router}, '${routePath}', (req: IRequest, res: IResponse) => ${controllerVar}.${action}(req, res), ${options});\n`;
212
214
  }
213
215
  /**
214
216
  * Build resource route (RESTful CRUD)
@@ -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;AAED;;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,CA+ChC;AAmUD,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;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"}