@zintrust/core 0.4.13 → 0.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -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;AAW3D,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;AA4FF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAoBd,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;AAiKF,eAAO,MAAM,oBAAoB,GAC/B,kBAAkB,MAAM,EACxB,QAAQ,OAAO,KACd,OAAO,CAAC,IAAI,CAqBd,CAAC"}
@@ -1,8 +1,7 @@
1
1
  import { appConfig } from '../../config/index.js';
2
2
  import Logger from '../../config/logger.js';
3
3
  import { Router } from '../../routes/Router.js';
4
- import { isObject } from '../../helper/index.js';
5
- import { getServicePrefix } from '../../microservices/ServiceManifest.js';
4
+ import { isNonEmptyString, isObject } from '../../helper/index.js';
6
5
  import * as path from '../../node-singletons/path.js';
7
6
  import { pathToFileURL } from '../../node-singletons/url.js';
8
7
  import { detectRuntime } from '../../runtime/detectRuntime.js';
@@ -63,23 +62,75 @@ const registerAppRoutes = async (resolvedBasePath, router) => {
63
62
  mod.registerRoutes(router);
64
63
  }
65
64
  };
65
+ const getProjectRoot = () => {
66
+ const fromEnv = process.env?.['ZINTRUST_PROJECT_ROOT'] ?? '';
67
+ if (fromEnv.trim() !== '')
68
+ return fromEnv.trim();
69
+ return process.cwd();
70
+ };
71
+ const resolveManifestServiceEnvDir = (projectRoot, entry) => {
72
+ const configRoot = entry.configRoot;
73
+ if (isNonEmptyString(configRoot)) {
74
+ return path.dirname(path.join(projectRoot, configRoot));
75
+ }
76
+ return path.join(projectRoot, 'src', 'services', entry.domain, entry.name);
77
+ };
78
+ const resolveServicePrefix = (entry) => {
79
+ const prefix = entry.prefix;
80
+ if (isNonEmptyString(prefix)) {
81
+ const segments = prefix
82
+ .split('/')
83
+ .map((segment) => segment.trim())
84
+ .filter((segment) => segment !== '');
85
+ return segments.length === 0 ? '/' : `/${segments.join('/')}`;
86
+ }
87
+ return `/${entry.domain}/${entry.name}`;
88
+ };
89
+ const ensureManifestServiceEnvLoaded = async (entry) => {
90
+ if (isCloudflare)
91
+ return;
92
+ const { EnvFileLoader } = await import('../../cli/utils/EnvFileLoader.js');
93
+ const projectRoot = getProjectRoot();
94
+ const envPath = resolveManifestServiceEnvDir(projectRoot, entry);
95
+ EnvFileLoader.ensureLoaded({
96
+ cwd: projectRoot,
97
+ includeCwd: true,
98
+ envPaths: [envPath],
99
+ });
100
+ };
101
+ const registerLoadedRoutes = (router, entry, registerRoutes, activeService) => {
102
+ const servicePrefix = resolveServicePrefix(entry);
103
+ if (activeService?.id === entry.id) {
104
+ registerRoutes(router);
105
+ return;
106
+ }
107
+ Router.group(router, servicePrefix, (scopedRouter) => {
108
+ registerRoutes(scopedRouter);
109
+ });
110
+ };
66
111
  const registerManifestRoutes = async (router) => {
67
112
  await ProjectRuntime.tryLoadNodeRuntime();
68
113
  const serviceManifest = ProjectRuntime.getServiceManifest();
69
114
  if (serviceManifest.length === 0)
70
115
  return;
116
+ const activeService = ProjectRuntime.getActiveService();
117
+ if (activeService !== undefined && isCloudflare)
118
+ return;
71
119
  for (const entry of serviceManifest) {
72
120
  if (entry.monolithEnabled === false || typeof entry.loadRoutes !== 'function') {
73
121
  continue;
74
122
  }
123
+ if (activeService !== undefined && activeService.id !== entry.id) {
124
+ continue;
125
+ }
75
126
  try {
127
+ // eslint-disable-next-line no-await-in-loop
128
+ await ensureManifestServiceEnvLoaded(entry);
76
129
  // eslint-disable-next-line no-await-in-loop
77
130
  const mod = await entry.loadRoutes();
78
131
  const registerRoutes = isObject(mod) ? mod.registerRoutes : undefined;
79
132
  if (typeof registerRoutes === 'function') {
80
- Router.group(router, getServicePrefix(entry), (scopedRouter) => {
81
- registerRoutes(scopedRouter);
82
- });
133
+ registerLoadedRoutes(router, entry, registerRoutes, activeService);
83
134
  }
84
135
  }
85
136
  catch (error) {
@@ -104,14 +155,15 @@ const registerGlobalRoutes = (router) => {
104
155
  };
105
156
  export const registerMasterRoutes = async (resolvedBasePath, router) => {
106
157
  try {
158
+ const activeService = ProjectRuntime.getActiveService();
107
159
  if (isCloudflare) {
108
160
  registerGlobalRoutes(router);
109
161
  }
110
- if (!isCloudflare) {
162
+ if (!isCloudflare && activeService === undefined) {
111
163
  await registerAppRoutes(resolvedBasePath, router);
112
164
  }
113
165
  await registerManifestRoutes(router);
114
- if (router.routes.length === 0) {
166
+ if (router.routes.length === 0 && activeService === undefined) {
115
167
  await registerFrameworkRoutes(resolvedBasePath, router);
116
168
  }
117
169
  // Always register core framework routes (health, metrics, doc) after app routes
@@ -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;AAmvBvF,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;AA21BvF,eAAO,MAAM,YAAY;cACb,YAAY;EAmCtB,CAAC"}
@@ -2,11 +2,15 @@ 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';
5
6
  import { readEnvString } from '../../common/ExternalServiceUtils.js';
6
7
  import * as Common from '../../common/index.js';
7
8
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
8
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from '../../node-singletons/fs.js';
9
+ import { isNonEmptyString } from '../../helper/index.js';
10
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from '../../node-singletons/fs.js';
9
11
  import * as path from '../../node-singletons/path.js';
12
+ import { ProjectRuntime } from '../../runtime/ProjectRuntime.js';
13
+ const isWranglerVarName = (value) => /^[A-Za-z_]\w*$/.test(value);
10
14
  const isAbsolutePath = (value) => value.startsWith('/') || /^[A-Za-z]:[\\/]/.test(value);
11
15
  const resolveNpmPath = () => {
12
16
  try {
@@ -231,6 +235,55 @@ const buildStartEnv = (projectRoot) => ({
231
235
  ...process.env,
232
236
  ZINTRUST_PROJECT_ROOT: projectRoot,
233
237
  });
238
+ const buildWorkerDevVarsContent = () => {
239
+ return (Object.entries(process.env)
240
+ .filter((entry) => {
241
+ const [key, value] = entry;
242
+ return isWranglerVarName(key) && typeof value === 'string';
243
+ })
244
+ .map(([key, value]) => `${key}=${JSON.stringify(value)}`)
245
+ .join('\n') + '\n');
246
+ };
247
+ async function withWranglerEnvSnapshot(cwd, envName, fn) {
248
+ const normalizedEnv = typeof envName === 'string' ? envName.trim() : '';
249
+ const targetName = normalizedEnv === '' ? '.dev.vars' : `.dev.vars.${normalizedEnv}`;
250
+ const targetPath = path.join(cwd, targetName);
251
+ const backupPath = existsSync(targetPath)
252
+ ? `${targetPath}.disabled-by-zin-${generateUuid()}`
253
+ : undefined;
254
+ if (backupPath !== undefined) {
255
+ renameSync(targetPath, backupPath);
256
+ }
257
+ try {
258
+ writeFileSync(targetPath, buildWorkerDevVarsContent(), 'utf-8');
259
+ return await fn();
260
+ }
261
+ finally {
262
+ try {
263
+ if (existsSync(targetPath))
264
+ unlinkSync(targetPath);
265
+ }
266
+ catch {
267
+ // noop
268
+ }
269
+ if (backupPath !== undefined) {
270
+ try {
271
+ if (existsSync(backupPath))
272
+ renameSync(backupPath, targetPath);
273
+ }
274
+ catch {
275
+ // noop
276
+ }
277
+ }
278
+ }
279
+ }
280
+ const resolveManifestServiceEnvDir = (projectRoot, entry) => {
281
+ const configRoot = entry.configRoot;
282
+ if (isNonEmptyString(configRoot)) {
283
+ return path.dirname(path.join(projectRoot, configRoot));
284
+ }
285
+ return path.join(projectRoot, 'src', 'services', entry.domain, entry.name);
286
+ };
234
287
  const ensureStartEnvLoaded = (context, options) => {
235
288
  const envPath = resolveEnvPath(options, context.projectRoot);
236
289
  const rootEnv = resolveRootEnvPreference(options);
@@ -242,6 +295,28 @@ const ensureStartEnvLoaded = (context, options) => {
242
295
  ...(envPath === undefined ? {} : { envPaths: [envPath] }),
243
296
  });
244
297
  };
298
+ const preloadManifestServiceEnv = async (context, options) => {
299
+ if (context.cwd !== context.projectRoot)
300
+ return;
301
+ if (resolveEnvPath(options, context.projectRoot) !== undefined)
302
+ return;
303
+ process.env['ZINTRUST_PROJECT_ROOT'] = context.projectRoot;
304
+ ProjectRuntime.clear();
305
+ await ProjectRuntime.tryLoadNodeRuntime();
306
+ const manifest = ProjectRuntime.getServiceManifest().filter((entry) => entry.monolithEnabled !== false);
307
+ if (manifest.length === 0)
308
+ return;
309
+ const envPaths = manifest
310
+ .map((entry) => resolveManifestServiceEnvDir(context.projectRoot, entry))
311
+ .filter((value, index, items) => items.indexOf(value) === index);
312
+ if (envPaths.length === 0)
313
+ return;
314
+ EnvFileLoader.ensureLoaded({
315
+ cwd: context.projectRoot,
316
+ includeCwd: resolveRootEnvPreference(options),
317
+ envPaths,
318
+ });
319
+ };
245
320
  const isFrameworkRepo = (packageJson) => packageJson.name === '@zintrust/core';
246
321
  const hasDevScript = (packageJson) => {
247
322
  const scripts = packageJson.scripts;
@@ -358,10 +433,12 @@ const executeWranglerStart = async (cmd, context, port, runtime, envName, wrangl
358
433
  }
359
434
  logMySqlProxyHint(cmd);
360
435
  cmd.info('Starting in Wrangler dev mode...');
361
- const exitCode = await SpawnUtil.spawnAndWait({
362
- command: 'wrangler',
363
- args: wranglerArgs,
364
- env: buildStartEnv(context.projectRoot),
436
+ const exitCode = await withWranglerEnvSnapshot(context.cwd, envName, async () => {
437
+ return SpawnUtil.spawnAndWait({
438
+ command: 'wrangler',
439
+ args: wranglerArgs,
440
+ env: buildStartEnv(context.projectRoot),
441
+ });
365
442
  });
366
443
  process.exit(exitCode);
367
444
  };
@@ -511,7 +588,9 @@ const executeSplitStart = async (cmd, context, _options) => {
511
588
  const executeStart = async (options, cmd) => {
512
589
  const cwd = process.cwd();
513
590
  const context = resolveStartContext(cwd);
591
+ process.env['ZINTRUST_PROJECT_ROOT'] = context.projectRoot;
514
592
  ensureStartEnvLoaded(context, options);
593
+ await preloadManifestServiceEnv(context, options);
515
594
  const mode = resolveMode(options);
516
595
  const port = resolvePort(options);
517
596
  const runtime = resolveRuntime(options);
@@ -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;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;AAgcD,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;AAkcD,eAAO,MAAM,iBAAiB;;;;EAI5B,CAAC"}
@@ -9,6 +9,7 @@ const coreModuleSpecifier = ['@zintrust', 'core'].join('/');
9
9
  const coreStartModuleSpecifier = `${coreModuleSpecifier}/start`;
10
10
  const serviceManifestImportExpression = "import('./bootstrap/service-manifest.ts').catch(() => import('./bootstrap/service-manifest.js'))";
11
11
  const buildRouteImportExpression = (domain, serviceName) => `import('../services/${domain}/${serviceName}/routes/api.ts').catch(() => import('../services/${domain}/${serviceName}/routes/api.js'))`;
12
+ const getServiceConfigRoot = (domain, serviceName) => `src/services/${domain}/${serviceName}/config`;
12
13
  /**
13
14
  * ServiceScaffolder generates microservices with all necessary files
14
15
  */
@@ -107,6 +108,7 @@ export const serviceManifest: ReadonlyArray<ServiceManifestEntry> = [
107
108
  id: '${serviceId}',
108
109
  domain: '${domain}',
109
110
  name: '${options.name}',
111
+ configRoot: '${getServiceConfigRoot(domain, options.name)}',
110
112
  prefix: '${serviceId}',
111
113
  port: ${options.port ?? 3001},
112
114
  monolithEnabled: true,
@@ -148,6 +150,7 @@ function updateServiceManifest(projectRoot, options) {
148
150
  id: '${serviceId}',
149
151
  domain: '${domain}',
150
152
  name: '${options.name}',
153
+ configRoot: '${getServiceConfigRoot(domain, options.name)}',
151
154
  prefix: '${serviceId}',
152
155
  port: ${options.port ?? 3001},
153
156
  monolithEnabled: true,
@@ -236,7 +239,7 @@ function generateServiceConfig(options) {
236
239
  function generateServiceIndex(options) {
237
240
  const domain = options.domain ?? 'default';
238
241
  const serviceId = `${domain}/${options.name}`;
239
- const configRoot = `src/services/${domain}/${options.name}/config`;
242
+ const configRoot = getServiceConfigRoot(domain, options.name);
240
243
  return `/**
241
244
  * ${options.name} Service - Entry Point
242
245
  * Port: ${options.port ?? 3001}
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAuBlF,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,SAAwB,CAAC;AAEzE,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,MAKzE,CAAC;AAGF,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,EAAE,cAAc,MAAM,KAAG,MAI1D,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAI7D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,eAAe,OAAO,KAAG,OAI7D,CAAC;AAEF,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,KAAG,IAGhD,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,KAAG,IAInC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,QAAQ,SAAS,GAAG,IAAI,KAAG,IAEpD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAOhD,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAKjE,CAAC;AACF,eAAO,MAAM,mBAAmB,QAAuC,CAAC;AAKxE,eAAO,MAAM,GAAG;eA3DS,MAAM,iBAAiB,MAAM,KAAG,MAAM;kBAMnC,MAAM,gBAAgB,MAAM,KAAG,MAAM;mBAYpC,MAAM,iBAAiB,OAAO,KAAG,OAAO;oBANvC,MAAM,iBAAiB,MAAM,KAAG,MAAM;eAY3C,MAAM,SAAS,MAAM,KAAG,IAAI;iBAK1B,MAAM,KAAG,IAAI;wBAMN,SAAS,GAAG,IAAI,KAAG,IAAI;oBAI7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAgCJ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAgOpB,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoFxF,CAAC;AAEH,eAAO,MAAM,aAAa,QAAO,MAchC,CAAC"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAsClF,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,SAAwB,CAAC;AAEzE,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,MAKzE,CAAC;AAGF,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,EAAE,cAAc,MAAM,KAAG,MAI1D,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAI7D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,eAAe,OAAO,KAAG,OAI7D,CAAC;AAEF,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,KAAG,IAGhD,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,KAAG,IAInC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,QAAQ,SAAS,GAAG,IAAI,KAAG,IAEpD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAOhD,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAKjE,CAAC;AACF,eAAO,MAAM,mBAAmB,QAAuC,CAAC;AAKxE,eAAO,MAAM,GAAG;eA3DS,MAAM,iBAAiB,MAAM,KAAG,MAAM;kBAMnC,MAAM,gBAAgB,MAAM,KAAG,MAAM;mBAYpC,MAAM,iBAAiB,OAAO,KAAG,OAAO;oBANvC,MAAM,iBAAiB,MAAM,KAAG,MAAM;eAY3C,MAAM,SAAS,MAAM,KAAG,IAAI;iBAK1B,MAAM,KAAG,IAAI;wBAMN,SAAS,GAAG,IAAI,KAAG,IAAI;oBAI7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAgCJ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAgOpB,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoFxF,CAAC;AAEH,eAAO,MAAM,aAAa,QAAO,MAchC,CAAC"}
package/src/config/env.js CHANGED
@@ -8,11 +8,24 @@
8
8
  // Cache process check once at module load time
9
9
  const processLike = typeof process === 'undefined' ? undefined : process;
10
10
  let externalEnvSource = null;
11
+ const getGlobalEnv = () => {
12
+ const env = globalThis.env;
13
+ if (env === undefined || env === null || typeof env !== 'object')
14
+ return undefined;
15
+ return env;
16
+ };
11
17
  const getEnvSource = () => {
12
18
  if (typeof externalEnvSource === 'function')
13
19
  return externalEnvSource();
14
20
  if (externalEnvSource !== null)
15
21
  return externalEnvSource;
22
+ const globalEnv = getGlobalEnv();
23
+ if (globalEnv !== undefined) {
24
+ return {
25
+ ...processLike?.env,
26
+ ...globalEnv,
27
+ };
28
+ }
16
29
  return processLike?.env ?? {};
17
30
  };
18
31
  const normalizeEnvValue = (value) => {
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/functions/cloudflare.ts"],"names":[],"mappings":";mBAmIuB,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;;AADhF,wBAmCE"}
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/functions/cloudflare.ts"],"names":[],"mappings":";mBA0JuB,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;;AADhF,wBAoCE"}
@@ -101,6 +101,25 @@ const injectIoredisModule = async () => {
101
101
  }
102
102
  };
103
103
  let startupConfigOverridesPromise;
104
+ const WORKER_ENV_SNAPSHOT_KEY = 'ZINTRUST_WORKER_ENV_SNAPSHOT';
105
+ const resolveWorkersEnv = (env) => {
106
+ const bindings = typeof env === 'object' && env !== null ? { ...env } : {};
107
+ const rawSnapshot = bindings[WORKER_ENV_SNAPSHOT_KEY];
108
+ if (typeof rawSnapshot !== 'string' || rawSnapshot.trim() === '') {
109
+ return bindings;
110
+ }
111
+ try {
112
+ const parsed = JSON.parse(rawSnapshot);
113
+ Reflect.deleteProperty(bindings, WORKER_ENV_SNAPSHOT_KEY);
114
+ return {
115
+ ...parsed,
116
+ ...bindings,
117
+ };
118
+ }
119
+ catch {
120
+ return bindings;
121
+ }
122
+ };
104
123
  const ensureStartupConfigOverridesLoaded = async () => {
105
124
  startupConfigOverridesPromise ??= applyStartupConfigOverrides();
106
125
  await startupConfigOverridesPromise;
@@ -108,8 +127,9 @@ const ensureStartupConfigOverridesLoaded = async () => {
108
127
  export default {
109
128
  async fetch(request, _env, _ctx) {
110
129
  try {
130
+ const workersEnv = resolveWorkersEnv(_env);
111
131
  // Make bindings available to framework code in Workers
112
- globalThis.env = _env;
132
+ globalThis.env = workersEnv;
113
133
  const AppRoutes = (await import('@routes/' + 'api.ts'));
114
134
  if (AppRoutes !== undefined) {
115
135
  globalThis.__zintrustRoutes = AppRoutes;
package/src/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @zintrust/core v0.4.13
2
+ * @zintrust/core v0.4.14
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-23T14:57:40.299Z
8
+ * Built: 2026-03-23T16:59:39.933Z
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-23T14:57:40.266Z'; // Replaced during build
24
+ export const ZINTRUST_BUILD_DATE = '2026-03-23T16:59:39.858Z'; // 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';
@@ -4,6 +4,7 @@ export interface ServiceManifestEntry {
4
4
  domain: string;
5
5
  name: string;
6
6
  prefix?: string;
7
+ configRoot?: string;
7
8
  version?: string;
8
9
  description?: string;
9
10
  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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"}
@@ -46,6 +46,10 @@ export const isServiceManifestEntry = (value) => {
46
46
  if (prefix !== undefined && typeof prefix !== 'string') {
47
47
  return false;
48
48
  }
49
+ const configRoot = value['configRoot'];
50
+ if (configRoot !== undefined && typeof configRoot !== 'string') {
51
+ return false;
52
+ }
49
53
  const loadRoutes = value['loadRoutes'];
50
54
  if (loadRoutes !== undefined && !isFunction(loadRoutes)) {
51
55
  return false;
@@ -59,6 +63,7 @@ export const normalizeServiceManifest = (value) => {
59
63
  ...entry,
60
64
  id: toCanonicalServiceId(entry),
61
65
  prefix: getServicePrefix(entry),
66
+ ...(isNonEmptyString(entry.configRoot) ? { configRoot: entry.configRoot } : {}),
62
67
  monolithEnabled: entry.monolithEnabled !== false,
63
68
  }));
64
69
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../../src/orm/Database.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAWxD,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,MAAM,MAAM,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,SAAS;IACxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,WAAW,IAAI,OAAO,CAAC;IACvB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACjF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrF,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IACnC,aAAa,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1F,cAAc,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1E,aAAa,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3F,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACvD,OAAO,IAAI,eAAe,CAAC;IAC3B,SAAS,IAAI,cAAc,CAAC;IAC5B,OAAO,IAAI,IAAI,CAAC;CACjB;AAqhBD,eAAO,MAAM,QAAQ;IACnB;;OAEG;oBACa,cAAc,GAAG,SAAS;EAI1C,CAAC;AAIH,eAAO,MAAM,oBAAoB,GAC/B,SAAQ,cAAc,GAAG,SAAqB,EAC9C,uBAA0B,KACzB,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAMxC,CAAC;AAEF,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,UAAU,SAAY,GAAG,SAAS,CAoBtF;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAWnD"}
1
+ {"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../../src/orm/Database.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAYxD,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,MAAM,MAAM,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,SAAS;IACxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,WAAW,IAAI,OAAO,CAAC;IACvB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACjF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrF,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IACnC,aAAa,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1F,cAAc,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1E,aAAa,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3F,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACvD,OAAO,IAAI,eAAe,CAAC;IAC3B,SAAS,IAAI,cAAc,CAAC;IAC5B,OAAO,IAAI,IAAI,CAAC;CACjB;AAqhBD,eAAO,MAAM,QAAQ;IACnB;;OAEG;oBACa,cAAc,GAAG,SAAS;EAI1C,CAAC;AAIH,eAAO,MAAM,oBAAoB,GAC/B,SAAQ,cAAc,GAAG,SAAqB,EAC9C,uBAA0B,KACzB,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAMxC,CAAC;AAEF,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,UAAU,SAAY,GAAG,SAAS,CAsBtF;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAYnD"}
@@ -12,6 +12,7 @@ import { D1Adapter } from './adapters/D1Adapter.js';
12
12
  import { D1RemoteAdapter } from './adapters/D1RemoteAdapter.js';
13
13
  import { MySQLAdapter } from './adapters/MySQLAdapter.js';
14
14
  import { MySQLProxyAdapter } from './adapters/MySQLProxyAdapter.js';
15
+ import { DatabaseConnectionRegistry } from './DatabaseConnectionRegistry.js';
15
16
  import { PostgreSQLAdapter } from './adapters/PostgreSQLAdapter.js';
16
17
  import { PostgreSQLProxyAdapter } from './adapters/PostgreSQLProxyAdapter.js';
17
18
  import { SQLiteAdapter } from './adapters/SQLiteAdapter.js';
@@ -432,14 +433,15 @@ export const useEnsureDbConnected = async (config = undefined, connectionName =
432
433
  };
433
434
  export function useDatabase(config, connection = 'default') {
434
435
  if (databaseInstances.has(connection) === false) {
435
- if (config === undefined) {
436
+ const resolvedConfig = config ?? DatabaseConnectionRegistry.get(connection);
437
+ if (resolvedConfig === undefined) {
436
438
  // Diagnostic logging
437
439
  Logger.error('[DEBUG] Database instances keys:', Array.from(databaseInstances.keys()));
438
440
  Logger.error('[DEBUG] Requesting connection:', connection);
439
441
  throw ErrorFactory.createConfigError(`Database connection '${connection}' is not registered. ` +
440
442
  `Call useDatabase(config, '${connection}') during startup to register it.`);
441
443
  }
442
- databaseInstances.set(connection, Database.create(config));
444
+ databaseInstances.set(connection, Database.create(resolvedConfig));
443
445
  }
444
446
  const instance = databaseInstances.get(connection);
445
447
  if (instance === undefined) {
@@ -459,4 +461,5 @@ export async function resetDatabase() {
459
461
  });
460
462
  await Promise.all(promises);
461
463
  databaseInstances.clear();
464
+ DatabaseConnectionRegistry.clear();
462
465
  }
@@ -0,0 +1,8 @@
1
+ import type { DatabaseConfig } from './DatabaseAdapter';
2
+ export declare const DatabaseConnectionRegistry: Readonly<{
3
+ clear(): void;
4
+ set(name: string, config: DatabaseConfig): void;
5
+ get(name: string): DatabaseConfig | undefined;
6
+ }>;
7
+ export default DatabaseConnectionRegistry;
8
+ //# sourceMappingURL=DatabaseConnectionRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseConnectionRegistry.d.ts","sourceRoot":"","sources":["../../../src/orm/DatabaseConnectionRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,eAAO,MAAM,0BAA0B;aAC5B,IAAI;cAIH,MAAM,UAAU,cAAc,GAAG,IAAI;cAIrC,MAAM,GAAG,cAAc,GAAG,SAAS;EAG7C,CAAC;AAEH,eAAe,0BAA0B,CAAC"}
@@ -0,0 +1,13 @@
1
+ const state = new Map();
2
+ export const DatabaseConnectionRegistry = Object.freeze({
3
+ clear() {
4
+ state.clear();
5
+ },
6
+ set(name, config) {
7
+ state.set(name, config);
8
+ },
9
+ get(name) {
10
+ return state.get(name);
11
+ },
12
+ });
13
+ export default DatabaseConnectionRegistry;
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseRuntimeRegistration.d.ts","sourceRoot":"","sources":["../../../src/orm/DatabaseRuntimeRegistration.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,mBAAmB,EAGpB,MAAM,cAAc,CAAC;AA0DtB;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAYpF"}
1
+ {"version":3,"file":"DatabaseRuntimeRegistration.d.ts","sourceRoot":"","sources":["../../../src/orm/DatabaseRuntimeRegistration.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,mBAAmB,EAGpB,MAAM,cAAc,CAAC;AA4DtB;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAapF"}
@@ -5,6 +5,7 @@
5
5
  * instances that can be selected via `useDatabase(undefined, name)`.
6
6
  */
7
7
  import { ErrorFactory } from '../exceptions/ZintrustError.js';
8
+ import { DatabaseConnectionRegistry } from './DatabaseConnectionRegistry.js';
8
9
  import { useDatabase } from './Database.js';
9
10
  const toOrmConfig = (cfg) => {
10
11
  switch (cfg.driver) {
@@ -50,9 +51,9 @@ const toOrmConfig = (cfg) => {
50
51
  }
51
52
  };
52
53
  const registerConnections = (connections) => {
54
+ DatabaseConnectionRegistry.clear();
53
55
  for (const [name, runtimeCfg] of Object.entries(connections)) {
54
- // Register instance by name; a later call without config may now resolve.
55
- useDatabase(toOrmConfig(runtimeCfg), name);
56
+ DatabaseConnectionRegistry.set(name, toOrmConfig(runtimeCfg));
56
57
  }
57
58
  };
58
59
  import { Logger } from '../config/logger.js';
@@ -71,5 +72,6 @@ export function registerDatabasesFromRuntimeConfig(config) {
71
72
  throw ErrorFactory.createConfigError(`Database default connection not configured: ${String(config.default ?? '')}`);
72
73
  }
73
74
  Logger.info(`✓ Registering default database connection: ${config.default}`);
75
+ useDatabase(toOrmConfig(defaultCfg), config.default);
74
76
  useDatabase(toOrmConfig(defaultCfg), 'default');
75
77
  }
@@ -0,0 +1,6 @@
1
+ export declare function loadProjectBootstrap(): Promise<void>;
2
+ declare const _default: Readonly<{
3
+ loadProjectBootstrap: typeof loadProjectBootstrap;
4
+ }>;
5
+ export default _default;
6
+ //# sourceMappingURL=ProjectBootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectBootstrap.d.ts","sourceRoot":"","sources":["../../../src/runtime/ProjectBootstrap.ts"],"names":[],"mappings":"AAgCA,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAU1D;;;;AAED,wBAEG"}
@@ -0,0 +1,43 @@
1
+ import { Logger } from '../config/logger.js';
2
+ import { existsSync } from '../node-singletons/fs.js';
3
+ import * as path from '../node-singletons/path.js';
4
+ import { pathToFileURL } from '../node-singletons/url.js';
5
+ const getProjectRoot = () => {
6
+ const fromEnv = process.env?.['ZINTRUST_PROJECT_ROOT'] ?? '';
7
+ if (fromEnv.trim() !== '')
8
+ return fromEnv.trim();
9
+ return process.cwd();
10
+ };
11
+ const getBootstrapCandidates = (projectRoot) => [
12
+ path.join(projectRoot, 'src', 'boot', 'bootstrap.ts'),
13
+ path.join(projectRoot, 'dist', 'src', 'boot', 'bootstrap.js'),
14
+ path.join(projectRoot, 'src', 'boot', 'bootstrap.js'),
15
+ ];
16
+ const tryImportBootstrapCandidate = async (candidate) => {
17
+ if (!existsSync(candidate))
18
+ return false;
19
+ try {
20
+ await import(pathToFileURL(candidate).href);
21
+ return true;
22
+ }
23
+ catch (error) {
24
+ Logger.warn('Failed to import project bootstrap candidate', {
25
+ candidate,
26
+ error: error instanceof Error ? error.message : String(error),
27
+ });
28
+ return false;
29
+ }
30
+ };
31
+ export async function loadProjectBootstrap() {
32
+ const projectRoot = getProjectRoot();
33
+ for (const candidate of getBootstrapCandidates(projectRoot)) {
34
+ // eslint-disable-next-line no-await-in-loop
35
+ const loaded = await tryImportBootstrapCandidate(candidate);
36
+ if (loaded)
37
+ return;
38
+ }
39
+ await import('../boot/bootstrap.js');
40
+ }
41
+ export default Object.freeze({
42
+ loadProjectBootstrap,
43
+ });
@@ -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;AA2ExC,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;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"}
@@ -33,6 +33,9 @@ const cacheProjectRuntime = (module) => {
33
33
  const getCachedProjectRuntime = () => {
34
34
  return getRuntimeGlobal().__zintrustProjectRuntime;
35
35
  };
36
+ const hasLoadedServiceManifest = (runtime) => {
37
+ return Array.isArray(runtime?.serviceManifest);
38
+ };
36
39
  const tryImportNodeRuntimeCandidate = async (candidate) => {
37
40
  if (!existsSync(candidate))
38
41
  return undefined;
@@ -76,7 +79,7 @@ export const ProjectRuntime = Object.freeze({
76
79
  },
77
80
  async tryLoadNodeRuntime() {
78
81
  const cached = getCachedProjectRuntime();
79
- if (cached !== undefined)
82
+ if (hasLoadedServiceManifest(cached))
80
83
  return cached;
81
84
  const projectRoot = getProjectRoot();
82
85
  const candidates = getNodeRuntimeCandidates(projectRoot);
@@ -90,7 +93,7 @@ export const ProjectRuntime = Object.freeze({
90
93
  },
91
94
  async tryLoadWorkerRuntime() {
92
95
  const cached = getCachedProjectRuntime();
93
- if (cached !== undefined)
96
+ if (hasLoadedServiceManifest(cached))
94
97
  return cached;
95
98
  const workerModuleIds = ['../' + 'zintrust.runtime.wg.js', '../' + 'zintrust.runtime.js'];
96
99
  for (const moduleId of workerModuleIds) {
@@ -1 +1 @@
1
- {"version":3,"file":"CloudflareAdapter.d.ts","sourceRoot":"","sources":["../../../../src/runtime/adapters/CloudflareAdapter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,aAAa,EAGb,cAAc,EACf,MAAM,yBAAyB,CAAC;AAGjC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;IAC5B;;OAEG;mBACY,aAAa,GAAG,cAAc;IAwD7C;;;OAGG;qBACc,OAAO;IAKxB;;;OAGG;qBACc,MAAM,GAAG,OAAO;EAIjC,CAAC;AAiKH;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACjC,EAAE,CAAC,EAAE;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH"}
1
+ {"version":3,"file":"CloudflareAdapter.d.ts","sourceRoot":"","sources":["../../../../src/runtime/adapters/CloudflareAdapter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,aAAa,EAGb,cAAc,EACf,MAAM,yBAAyB,CAAC;AAGjC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;IAC5B;;OAEG;mBACY,aAAa,GAAG,cAAc;IA8D7C;;;OAGG;qBACc,OAAO;IAKxB;;;OAGG;qBACc,MAAM,GAAG,OAAO;EAIjC,CAAC;AAiKH;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACjC,EAAE,CAAC,EAAE;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH"}
@@ -4,7 +4,7 @@
4
4
  import { appConfig } from '../../config/index.js';
5
5
  import { isUndefinedOrNull } from '../../helper/index.js';
6
6
  import { Cloudflare } from '../../config/cloudflare.js';
7
- import { Env } from '../../config/env.js';
7
+ import { Env, getProcessLike } from '../../config/env.js';
8
8
  import { Logger } from '../../config/logger.js';
9
9
  import { createMockHttpObjects, ErrorResponse, HttpResponse } from '../RuntimeAdapter.js';
10
10
  /**
@@ -19,7 +19,13 @@ export const CloudflareAdapter = Object.freeze({
19
19
  create(config) {
20
20
  const workersEnv = Cloudflare.getWorkersEnv();
21
21
  if (workersEnv !== null) {
22
- Env.setSource(() => workersEnv);
22
+ const processEnv = getProcessLike()?.env;
23
+ const resolveEnvSource = () => {
24
+ if (processEnv === undefined)
25
+ return workersEnv;
26
+ return { ...processEnv, ...workersEnv };
27
+ };
28
+ Env.setSource(resolveEnvSource);
23
29
  }
24
30
  const logger = config.logger ?? createDefaultLogger();
25
31
  return {
package/src/start.js CHANGED
@@ -112,10 +112,8 @@ export const bootStandaloneService = async (importMetaUrl, activeService) => {
112
112
  export const start = async () => {
113
113
  if (!isNodeRuntime())
114
114
  return;
115
- // Compiled output places bootstrap at `dist/src/boot/bootstrap.js`.
116
- // This file compiles to `dist/src/start.js`, so relative import is stable.
117
- // In unit tests, importing bootstrap has heavy side effects (starts server + exits).
118
- await import('./boot/bootstrap.js');
115
+ const projectBootstrapModule = (await import('./runtime/ProjectBootstrap.js'));
116
+ await projectBootstrapModule.loadProjectBootstrap();
119
117
  };
120
118
  /**
121
119
  * Cloudflare Workers entry (module worker style).