@zintrust/core 0.4.42 → 0.4.49

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 (41) hide show
  1. package/package.json +2 -2
  2. package/src/boot/bootstrap.js +9 -3
  3. package/src/boot/registry/runtime.d.ts.map +1 -1
  4. package/src/boot/registry/runtime.js +13 -65
  5. package/src/cli/commands/DebuggerCommands.d.ts.map +1 -1
  6. package/src/cli/commands/DebuggerCommands.js +128 -46
  7. package/src/cli/commands/MigrateCommand.js +1 -1
  8. package/src/config/database.d.ts.map +1 -1
  9. package/src/config/database.js +7 -1
  10. package/src/functions/cloudflare.d.ts.map +1 -1
  11. package/src/functions/cloudflare.js +8 -27
  12. package/src/index.d.ts +2 -1
  13. package/src/index.d.ts.map +1 -1
  14. package/src/index.js +5 -4
  15. package/src/orm/Database.d.ts +1 -0
  16. package/src/orm/Database.d.ts.map +1 -1
  17. package/src/orm/Database.js +21 -2
  18. package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
  19. package/src/orm/DatabaseRuntimeRegistration.js +9 -3
  20. package/src/orm/Model.d.ts +2 -1
  21. package/src/orm/Model.d.ts.map +1 -1
  22. package/src/orm/Model.js +68 -7
  23. package/src/orm/RelationBootstrapDiagnostics.d.ts +21 -0
  24. package/src/orm/RelationBootstrapDiagnostics.d.ts.map +1 -0
  25. package/src/orm/RelationBootstrapDiagnostics.js +102 -0
  26. package/src/runtime/plugins/system-debugger-runtime.d.ts.map +1 -1
  27. package/src/zintrust.plugins.d.ts +3 -7
  28. package/src/zintrust.plugins.d.ts.map +1 -1
  29. package/src/zintrust.plugins.js +3 -9
  30. package/src/zintrust.plugins.wg.d.ts +0 -1
  31. package/src/zintrust.plugins.wg.d.ts.map +1 -1
  32. package/src/zintrust.plugins.wg.js +0 -3
  33. package/src/zintrust.runtime.d.ts +5 -2
  34. package/src/zintrust.runtime.d.ts.map +1 -1
  35. package/src/zintrust.runtime.js +5 -2
  36. package/src/zintrust.runtime.wg.d.ts +5 -2
  37. package/src/zintrust.runtime.wg.d.ts.map +1 -1
  38. package/src/zintrust.runtime.wg.js +5 -2
  39. package/src/zintrust.comon.d.ts +0 -9
  40. package/src/zintrust.comon.d.ts.map +0 -1
  41. package/src/zintrust.comon.js +0 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.4.42",
3
+ "version": "0.4.49",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@cloudflare/containers": "^0.2.0",
61
- "@zintrust/workers": "^0.4.42",
61
+ "@zintrust/workers": "0.4.49",
62
62
  "bcryptjs": "^3.0.3",
63
63
  "bullmq": "^5.71.1",
64
64
  "chalk": "^5.6.2",
@@ -6,6 +6,7 @@
6
6
  import { Application } from './Application.js';
7
7
  import { Server } from './Server.js';
8
8
  import { appConfig } from '../config/app.js';
9
+ import { Cloudflare } from '../config/cloudflare.js';
9
10
  import { Env } from '../config/env.js';
10
11
  import { Logger } from '../config/logger.js';
11
12
  import { ErrorFactory } from '../exceptions/ZintrustError.js';
@@ -16,6 +17,9 @@ let appInstance;
16
17
  let serverInstance;
17
18
  let isShuttingDown = false;
18
19
  let shutdownHandlersRegistered = false;
20
+ const shouldSkipProjectPluginAutoImports = () => {
21
+ return appConfig.cloudflareWorker === true || Cloudflare.getWorkersEnv() !== null;
22
+ };
19
23
  const logBootstrapErrorDetails = (error) => {
20
24
  // Best-effort: surface startup config validation details (already redacted)
21
25
  // so container runs show which env vars are missing/misconfigured.
@@ -210,9 +214,11 @@ const BootstrapFunctions = Object.freeze({
210
214
  Logger.warn('Official plugin auto-imports failed:', ErrorFactory.createGeneralError('officialImports', officialImports.errorMessage));
211
215
  }
212
216
  }
213
- const projectImports = await PluginAutoImports.tryImportProjectAutoImports();
214
- if (!projectImports.ok && projectImports.reason !== 'not-found') {
215
- Logger.warn('Project plugin auto-imports failed:', ErrorFactory.createGeneralError('projectImports', projectImports.errorMessage));
217
+ if (!shouldSkipProjectPluginAutoImports()) {
218
+ const projectImports = await PluginAutoImports.tryImportProjectAutoImports();
219
+ if (!projectImports.ok && projectImports.reason !== 'not-found') {
220
+ Logger.warn('Project plugin auto-imports failed:', ErrorFactory.createGeneralError('projectImports', projectImports.errorMessage));
221
+ }
216
222
  }
217
223
  }
218
224
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/runtime.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAOvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AA+N9C,eAAO,MAAM,8BAA8B,GAAI,iBAAiB,gBAAgB,KAAG,IA4BlF,CAAC;AA6RF,eAAO,MAAM,eAAe,GAAI,QAAQ;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,gBAAgB,CAAC;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC,KAAG;IAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CA8E7D,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/runtime.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAOvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAiN9C,eAAO,MAAM,8BAA8B,GAAI,iBAAiB,gBAAgB,KAAG,IA4BlF,CAAC;AA8NF,eAAO,MAAM,eAAe,GAAI,QAAQ;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,gBAAgB,CAAC;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC,KAAG;IAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CA8E7D,CAAC"}
@@ -5,6 +5,7 @@ import { registerCachesFromRuntimeConfig } from '../../cache/CacheRuntimeRegistr
5
5
  import { readEnvString } from '../../common/ExternalServiceUtils.js';
6
6
  import broadcastConfig from '../../config/broadcast.js';
7
7
  import { Cloudflare } from '../../config/cloudflare.js';
8
+ import { databaseConfig as liveDatabaseConfig } from '../../config/database.js';
8
9
  import { FeatureFlags } from '../../config/features.js';
9
10
  import { Logger } from '../../config/logger.js';
10
11
  import notificationConfig from '../../config/notification.js';
@@ -12,7 +13,6 @@ import { StartupConfigValidator } from '../../config/StartupConfigValidator.js';
12
13
  import { existsSync } from '../../node-singletons/fs.js';
13
14
  import * as path from '../../node-singletons/path.js';
14
15
  import { pathToFileURL } from '../../node-singletons/url.js';
15
- import { useDatabase } from '../../orm/Database.js';
16
16
  import { registerDatabasesFromRuntimeConfig } from '../../orm/DatabaseRuntimeRegistration.js';
17
17
  import { registerMasterRoutes, tryImportOptional } from './registerRoute.js';
18
18
  import { registerWorkerShutdownHook } from './worker.js';
@@ -85,15 +85,14 @@ const appConfig = readRuntimeConfig('appConfig', {
85
85
  });
86
86
  // exported solely for tests to exercise the default detectRuntime handler
87
87
  const cacheConfig = readRuntimeConfig('cacheConfig', RuntimeConfig.cacheConfig);
88
- const databaseConfig = readRuntimeConfig('databaseConfig', {
89
- default: 'sqlite',
90
- connections: {},
91
- });
92
88
  const queueConfig = readRuntimeConfig('queueConfig', RuntimeConfig.queueConfig);
93
89
  const storageConfig = readRuntimeConfig('storageConfig', RuntimeConfig.storageConfig);
90
+ const getDatabaseConfig = () => {
91
+ return readRuntimeConfig('databaseConfig', liveDatabaseConfig);
92
+ };
94
93
  // eslint-disable-next-line @typescript-eslint/require-await
95
94
  const dbLoader = async () => {
96
- registerDatabasesFromRuntimeConfig(databaseConfig);
95
+ registerDatabasesFromRuntimeConfig(getDatabaseConfig());
97
96
  };
98
97
  const queuesLoader = async () => {
99
98
  await registerQueuesFromRuntimeConfig(queueConfig);
@@ -356,75 +355,24 @@ const isSystemDebuggerPluginRequested = () => {
356
355
  const globalDebuggerPluginState = globalThis;
357
356
  return globalDebuggerPluginState.__zintrust_system_debugger_plugin_requested__ === true;
358
357
  };
359
- const resolveDebuggerBasePath = () => {
360
- const raw = readEnvString('DEBUGGER_BASE_PATH').trim();
361
- if (raw === '')
362
- return '/debugger';
363
- return raw.startsWith('/') ? raw : `/${raw}`;
364
- };
365
- const resolveDebuggerMiddleware = () => {
366
- const raw = readEnvString('DEBUGGER_MIDDLEWARE').trim();
367
- if (raw === '')
368
- return [];
369
- return raw
370
- .split(',')
371
- .map((segment) => segment.trim())
372
- .filter((segment) => segment !== '');
373
- };
374
- const resolveDebuggerConnectionName = (configuredConnection) => {
375
- const explicitConnection = configuredConnection?.trim();
376
- if (explicitConnection !== undefined && explicitConnection !== '')
377
- return explicitConnection;
378
- const defaultConnection = readEnvString('DB_CONNECTION').trim();
379
- if (defaultConnection === '')
380
- return 'default';
381
- return defaultConnection;
382
- };
383
- const hasDebuggerRouteRegistered = (router, basePath) => {
384
- return router.routes.some((route) => {
385
- return (route.path === basePath ||
386
- route.path === `${basePath}/*` ||
387
- route.path.startsWith(`${basePath}/api`));
388
- });
389
- };
390
- const initializeSystemDebugger = async (router) => {
358
+ const initializeSystemDebugger = async () => {
391
359
  if (!isSystemDebuggerPluginRequested()) {
392
- Logger.debug('System Debugger plugin is not enabled in zintrust.plugins.*. Skipping mount.');
360
+ Logger.debug('System Debugger plugin is not enabled in zintrust.plugins.*. Skipping init.');
393
361
  return;
394
362
  }
395
363
  if (!isDebuggerEnabled())
396
364
  return;
397
- const debuggerModule = (await tryImportOptional('@zintrust/system-debugger')) ??
398
- (await loadLocalSystemDebuggerModule());
399
- if (debuggerModule === undefined) {
365
+ const debuggerModule = (await tryImportOptional('@runtime/plugins/system-debugger-runtime')) ?? (await loadLocalSystemDebuggerModule());
366
+ if (debuggerModule === undefined || debuggerModule.isAvailable?.() === false) {
400
367
  Logger.debug('System Debugger is enabled but the optional package is unavailable.');
401
368
  return;
402
369
  }
403
- const debuggerRegisterModule = await tryImportOptional('@zintrust/system-debugger/register');
404
- if (debuggerRegisterModule === undefined) {
405
- const localDebuggerModule = await loadLocalSystemDebuggerModule();
406
- if (localDebuggerModule === undefined) {
407
- Logger.warn('System Debugger plugin was requested but the register module could not be loaded.');
408
- return;
409
- }
410
- Logger.debug('System Debugger register module is unavailable in source mode. Mounting dashboard routes without source fallback auto-registration.');
411
- }
412
- const config = debuggerModule.DebuggerConfig.merge();
413
- const basePath = resolveDebuggerBasePath();
414
- if (hasDebuggerRouteRegistered(router, basePath))
415
- return;
416
370
  try {
417
- const db = useDatabase(undefined, resolveDebuggerConnectionName(config.connection));
418
- const storage = debuggerModule.DebuggerStorage.resolveStorage(db);
419
- const middleware = resolveDebuggerMiddleware();
420
- debuggerModule.registerDebuggerRoutes(router, storage, {
421
- basePath,
422
- middleware: middleware.length > 0 ? middleware : undefined,
423
- });
424
- Logger.info(`System Debugger routes registered at http://127.0.0.1:${appConfig.port}${basePath}`);
371
+ await debuggerModule.ensureSystemDebuggerRegistered();
372
+ Logger.info('System Debugger runtime activated. Register dashboard routes manually if needed.');
425
373
  }
426
374
  catch (error) {
427
- Logger.warn('Failed to register System Debugger routes', error);
375
+ Logger.warn('Failed to initialize System Debugger runtime', error);
428
376
  }
429
377
  };
430
378
  export const createLifecycle = (params) => {
@@ -454,7 +402,7 @@ export const createLifecycle = (params) => {
454
402
  await registerFromRuntimeConfig();
455
403
  await initializeArtifactDirectories(params.resolvedBasePath);
456
404
  await registerMasterRoutes(params.resolvedBasePath, params.router);
457
- await initializeSystemDebugger(params.router);
405
+ await initializeSystemDebugger();
458
406
  if (Cloudflare.getWorkersEnv() === null &&
459
407
  appConfig.dockerWorker === false &&
460
408
  appConfig.worker === true) {
@@ -1 +1 @@
1
- {"version":3,"file":"DebuggerCommands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DebuggerCommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAqBrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqhBzC,eAAO,MAAM,gBAAgB;sCACK,YAAY;sCAQZ,YAAY;uCAaX,YAAY;wCAgBX,YAAY;;cA7C5B,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;EAoEnD,CAAC"}
1
+ {"version":3,"file":"DebuggerCommands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DebuggerCommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAsBrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0oBzC,eAAO,MAAM,gBAAgB;sCACK,YAAY;sCAQZ,YAAY;uCAaX,YAAY;wCAgBX,YAAY;;cA7C5B,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;EAoEnD,CAAC"}
@@ -9,6 +9,7 @@ import { Logger } from '../../config/logger.js';
9
9
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
10
10
  import { isNonEmptyString } from '../../helper/index.js';
11
11
  import { Migrator } from '../../migrations/Migrator.js';
12
+ import { existsSync } from '../../node-singletons/fs.js';
12
13
  import { createRequire } from '../../node-singletons/module.js';
13
14
  import * as path from '../../node-singletons/path.js';
14
15
  import { Database } from '../../orm/Database.js';
@@ -56,14 +57,47 @@ const resolveDashboardUrl = () => {
56
57
  const port = readEnvString('PORT').trim() || readEnvString('APP_PORT').trim() || '7777';
57
58
  return `http://${host}:${port}${resolveDashboardBasePath()}`;
58
59
  };
59
- const resolveDebuggerMigrationDir = () => {
60
+ const resolveDebuggerMigrationTargetFromResolvedPath = (resolvedPath) => {
61
+ const extension = path.extname(resolvedPath).toLowerCase();
62
+ const dir = path.dirname(resolvedPath);
63
+ if (extension === '.js' || extension === '.mjs' || extension === '.cjs') {
64
+ return {
65
+ dir,
66
+ extension: extension.slice(1),
67
+ };
68
+ }
69
+ if (extension === '.ts') {
70
+ const baseName = path.basename(resolvedPath, extension);
71
+ for (const candidateExt of ['.js', '.mjs', '.cjs']) {
72
+ const candidatePath = path.join(dir, `${baseName}${candidateExt}`);
73
+ if (!existsSync(candidatePath))
74
+ continue;
75
+ return {
76
+ dir,
77
+ extension: candidateExt.slice(1),
78
+ };
79
+ }
80
+ throw ErrorFactory.createCliError('Installed package "@zintrust/system-debugger" exposes TypeScript-only migrations. Upgrade to a version that publishes runnable JavaScript migrations.');
81
+ }
82
+ return {
83
+ dir,
84
+ extension: databaseConfig.migrations.extension,
85
+ };
86
+ };
87
+ const resolveDebuggerMigrationTarget = () => {
60
88
  const requireFromProject = createRequire(path.join(process.cwd(), 'package.json'));
61
89
  try {
62
90
  const resolved = requireFromProject.resolve('@zintrust/system-debugger/migrations');
63
- return path.dirname(resolved);
91
+ return resolveDebuggerMigrationTargetFromResolvedPath(resolved);
64
92
  }
65
- catch {
66
- return path.join(process.cwd(), 'packages', 'system-debugger', 'migrations');
93
+ catch (error) {
94
+ if (error instanceof Error && error.message.includes('TypeScript-only migrations')) {
95
+ throw error;
96
+ }
97
+ return {
98
+ dir: path.join(process.cwd(), 'packages', 'system-debugger', 'migrations'),
99
+ extension: 'ts',
100
+ };
67
101
  }
68
102
  };
69
103
  const getD1DatabaseName = (options) => {
@@ -82,11 +116,40 @@ const getD1DatabaseName = (options) => {
82
116
  return 'zintrust_db';
83
117
  };
84
118
  const getInteractive = (options) => options['interactive'] !== false;
119
+ const resolveRuntimeDefaultConnectionName = () => {
120
+ const configuredDefault = String(databaseConfig.default ?? '').trim();
121
+ return configuredDefault === '' ? 'default' : configuredDefault;
122
+ };
123
+ const normalizeConnectionName = (value) => {
124
+ const normalized = value.trim();
125
+ if (normalized === '' || normalized === 'default') {
126
+ return resolveRuntimeDefaultConnectionName();
127
+ }
128
+ return normalized;
129
+ };
85
130
  const resolveDebuggerConnectionName = (options) => {
86
131
  if (isNonEmptyString(options['connection'])) {
87
- return String(options['connection']).trim();
132
+ return normalizeConnectionName(String(options['connection']));
88
133
  }
89
- return readEnvString('DEBUGGER_DB_CONNECTION').trim() || 'default';
134
+ return normalizeConnectionName(readEnvString('DEBUGGER_DB_CONNECTION').trim());
135
+ };
136
+ const withConfiguredDebuggerConnection = (options, configuredConnection) => {
137
+ if (isNonEmptyString(options['connection'])) {
138
+ return {
139
+ ...options,
140
+ connection: resolveDebuggerConnectionName(options),
141
+ };
142
+ }
143
+ if (isNonEmptyString(configuredConnection)) {
144
+ return {
145
+ ...options,
146
+ connection: normalizeConnectionName(configuredConnection),
147
+ };
148
+ }
149
+ return {
150
+ ...options,
151
+ connection: resolveDebuggerConnectionName(options),
152
+ };
90
153
  };
91
154
  const resolveDebuggerConnectionConfig = (options) => {
92
155
  const selected = resolveDebuggerConnectionName(options);
@@ -97,9 +160,24 @@ const isD1ConnectionDriver = (driver) => driver === 'd1' || driver === 'd1-remot
97
160
  const resolveD1ExecutionMode = (options) => {
98
161
  return options['local'] === true || options['remote'] !== true;
99
162
  };
100
- const ANSI_ESCAPE_PATTERN = new RegExp(String.raw `\u001b\[[0-9;]*m`, 'g');
163
+ const ANSI_ESCAPE = String.fromCodePoint(27);
101
164
  const stripAnsi = (value) => {
102
- return value.replaceAll(ANSI_ESCAPE_PATTERN, '');
165
+ let output = '';
166
+ for (let index = 0; index < value.length; index += 1) {
167
+ const char = value[index];
168
+ if (char !== ANSI_ESCAPE) {
169
+ output += char;
170
+ continue;
171
+ }
172
+ if (value[index + 1] !== '[') {
173
+ continue;
174
+ }
175
+ index += 2;
176
+ while (index < value.length && value[index] !== 'm') {
177
+ index += 1;
178
+ }
179
+ }
180
+ return output;
103
181
  };
104
182
  const extractWranglerJson = (output) => {
105
183
  const normalized = stripAnsi(output);
@@ -131,6 +209,26 @@ const parseWranglerTable = (output) => {
131
209
  return Object.fromEntries(headers.map((header, index) => [header, cells[index] ?? '']));
132
210
  });
133
211
  };
212
+ const buildStatsFromJsonPayload = (payload) => {
213
+ const stats = {};
214
+ for (const row of payload[0]?.results ?? []) {
215
+ if (typeof row.type === 'string') {
216
+ stats[row.type] = typeof row.cnt === 'number' ? row.cnt : 0;
217
+ }
218
+ }
219
+ return stats;
220
+ };
221
+ const buildStatsFromTableRows = (rows) => {
222
+ const stats = {};
223
+ for (const row of rows) {
224
+ const key = row['type'] ?? '';
225
+ const count = Number.parseInt(row['cnt'] ?? '0', 10);
226
+ if (key !== '') {
227
+ stats[key] = Number.isNaN(count) ? 0 : count;
228
+ }
229
+ }
230
+ return stats;
231
+ };
134
232
  const withSqlDebuggerStorage = async (options, callback) => {
135
233
  const { DebuggerStorage } = await loadDebuggerModule();
136
234
  const conn = resolveDebuggerConnectionConfig(options);
@@ -152,24 +250,9 @@ const executeD1Stats = (options) => {
152
250
  });
153
251
  const payload = extractWranglerJson(output);
154
252
  if (payload !== null) {
155
- const stats = {};
156
- for (const row of payload[0]?.results ?? []) {
157
- if (typeof row.type === 'string') {
158
- stats[row.type] = typeof row.cnt === 'number' ? row.cnt : 0;
159
- }
160
- }
161
- return stats;
162
- }
163
- const rows = parseWranglerTable(output);
164
- const stats = {};
165
- for (const row of rows) {
166
- const key = row['type'] ?? '';
167
- const count = Number.parseInt(row['cnt'] ?? '0', 10);
168
- if (key !== '') {
169
- stats[key] = Number.isNaN(count) ? 0 : count;
170
- }
253
+ return buildStatsFromJsonPayload(payload);
171
254
  }
172
- return stats;
255
+ return buildStatsFromTableRows(parseWranglerTable(output));
173
256
  };
174
257
  const executeD1Delete = (options, sql) => {
175
258
  const output = WranglerD1.executeSql({
@@ -196,53 +279,50 @@ const isDestructiveAction = (options) => options['fresh'] === true || options['r
196
279
  const executePrune = async (options) => {
197
280
  const { DebuggerConfig } = await loadDebuggerModule();
198
281
  const config = DebuggerConfig.merge();
282
+ const resolvedOptions = withConfiguredDebuggerConnection(options, config.connection);
199
283
  const hours = typeof options['hours'] === 'string' && options['hours'] !== ''
200
284
  ? Number.parseInt(options['hours'], 10)
201
285
  : config.pruneAfterHours;
202
286
  const olderThanMs = hours * 60 * 60 * 1000;
203
287
  const keepExceptions = options['keepExceptions'] === true;
204
- const conn = resolveDebuggerConnectionConfig({
205
- ...options,
206
- connection: config.connection ?? 'default',
207
- });
288
+ const conn = resolveDebuggerConnectionConfig(resolvedOptions);
208
289
  const threshold = Date.now() - olderThanMs;
209
290
  const pruneSql = keepExceptions
210
291
  ? `DELETE FROM zin_debugger_entries WHERE created_at < ${String(threshold)} AND type != 'exception'`
211
292
  : `DELETE FROM zin_debugger_entries WHERE created_at < ${String(threshold)}`;
212
293
  Logger.info(`Pruning debugger entries older than ${hours}h...`);
213
294
  const deleted = isD1ConnectionDriver(conn.driver)
214
- ? await executeD1Delete(options, pruneSql)
215
- : await withSqlDebuggerStorage({ ...options, connection: config.connection ?? 'default' }, async (storage) => storage.prune(olderThanMs, keepExceptions));
295
+ ? executeD1Delete(options, pruneSql)
296
+ : await withSqlDebuggerStorage(resolvedOptions, async (storage) => storage.prune(olderThanMs, keepExceptions));
216
297
  Logger.info(`Done - removed ${deleted} entries.`);
217
298
  };
218
299
  const executeClear = async (options) => {
219
300
  const { DebuggerConfig } = await loadDebuggerModule();
220
301
  const config = DebuggerConfig.merge();
221
- const conn = resolveDebuggerConnectionConfig({
222
- ...options,
223
- connection: config.connection ?? 'default',
224
- });
302
+ const resolvedOptions = withConfiguredDebuggerConnection(options, config.connection);
303
+ const conn = resolveDebuggerConnectionConfig(resolvedOptions);
225
304
  Logger.info('Clearing all debugger entries...');
226
305
  if (isD1ConnectionDriver(conn.driver)) {
227
- await executeD1Delete(options, 'DELETE FROM zin_debugger_entries');
306
+ executeD1Delete(options, 'DELETE FROM zin_debugger_entries');
228
307
  }
229
308
  else {
230
- await withSqlDebuggerStorage({ ...options, connection: config.connection ?? 'default' }, async (storage) => storage.clear());
309
+ await withSqlDebuggerStorage(resolvedOptions, async (storage) => storage.clear());
231
310
  }
232
311
  Logger.info('Done - all entries cleared.');
233
312
  };
234
313
  const executeStatus = async (options, cmd) => {
235
314
  const { DebuggerConfig } = await loadDebuggerModule();
236
315
  const config = DebuggerConfig.merge();
237
- const connection = config.connection ?? 'default';
238
- const conn = resolveDebuggerConnectionConfig({ ...options, connection });
316
+ const resolvedOptions = withConfiguredDebuggerConnection(options, config.connection);
317
+ const connection = resolveDebuggerConnectionName(resolvedOptions);
318
+ const conn = resolveDebuggerConnectionConfig(resolvedOptions);
239
319
  const stats = isD1ConnectionDriver(conn.driver)
240
- ? await executeD1Stats(options)
241
- : await withSqlDebuggerStorage({ ...options, connection }, async (storage) => storage.stats());
320
+ ? executeD1Stats(options)
321
+ : await withSqlDebuggerStorage(resolvedOptions, async (storage) => storage.stats());
242
322
  cmd.info(`Debugger enabled via env: ${readEnvString('DEBUGGER_ENABLED').trim() || 'false'}`);
243
323
  cmd.info(`Connection: ${connection}`);
244
324
  cmd.info(`Prune after hours: ${String(config.pruneAfterHours)}`);
245
- cmd.info(`Dashboard: ${resolveDashboardUrl()}`);
325
+ cmd.info(`Expected dashboard URL (if mounted): ${resolveDashboardUrl()}`);
246
326
  const keys = Object.keys(stats).sort((left, right) => left.localeCompare(right));
247
327
  if (keys.length === 0) {
248
328
  cmd.info('Stored entries: 0');
@@ -322,14 +402,15 @@ const runMigrationsForConnection = async (conn, options, cmd, interactive) => {
322
402
  options['rollback'] === true) {
323
403
  throw ErrorFactory.createCliError('D1-backed debugger migrations currently support apply only. Run `zin migrate:debugger --local|--remote` without status or rollback flags.');
324
404
  }
405
+ const migrationTarget = resolveDebuggerMigrationTarget();
325
406
  const projectRoot = process.cwd();
326
407
  const dbName = getD1DatabaseName(options);
327
408
  const isLocal = options['local'] === true || options['remote'] !== true;
328
409
  const outputDir = path.join(projectRoot, WranglerConfig.getD1MigrationsDir(projectRoot, dbName));
329
410
  await D1SqlMigrations.compileAndWrite({
330
411
  projectRoot,
331
- globalDir: resolveDebuggerMigrationDir(),
332
- extension: databaseConfig.migrations.extension,
412
+ globalDir: migrationTarget.dir,
413
+ extension: migrationTarget.extension,
333
414
  includeGlobal: true,
334
415
  outputDir,
335
416
  });
@@ -344,11 +425,12 @@ const runMigrationsForConnection = async (conn, options, cmd, interactive) => {
344
425
  const db = Database.create(ormConfig);
345
426
  await db.connect();
346
427
  try {
428
+ const migrationTarget = resolveDebuggerMigrationTarget();
347
429
  const migrator = Migrator.create({
348
430
  db,
349
431
  projectRoot: process.cwd(),
350
- globalDir: resolveDebuggerMigrationDir(),
351
- extension: databaseConfig.migrations.extension,
432
+ globalDir: migrationTarget.dir,
433
+ extension: migrationTarget.extension,
352
434
  separateTracking: true,
353
435
  });
354
436
  await runMigrationActions(migrator, options, cmd, conn.driver);
@@ -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 "../../../packages/db-mysql/src/register";');
218
+ cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "@zintrust/db-mysql/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":"database.d.ts","sourceRoot":"","sources":["../../../src/config/database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAItB,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,mBAAmB,CAAC;IACjC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC,CAAC,CAAC;AAuQH,QAAA,MAAM,oBAAoB,QAAO;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,wBAAwB,CAAC;IACvE,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAyEhC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAqBrE,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAC"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/config/database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAItB,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,mBAAmB,CAAC;IACjC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC,CAAC,CAAC;AA+QH,QAAA,MAAM,oBAAoB,QAAO;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,mBAAmB,CAAC;IACjC,aAAa,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,wBAAwB,CAAC;IACvE,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAyEhC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAqBrE,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAC"}
@@ -152,15 +152,21 @@ const normalizeReadHosts = (primaryHost, hosts) => {
152
152
  const filtered = hosts.filter((host) => host !== '' && host !== primary);
153
153
  return filtered.length > 0 ? filtered : undefined;
154
154
  };
155
+ const resolveImplicitDefaultConnection = (connections) => {
156
+ return hasOwn(connections, 'sqlite') ? 'sqlite' : (Object.keys(connections)[0] ?? 'sqlite');
157
+ };
155
158
  const getDefaultConnection = (connections) => {
156
159
  const envSelectedRaw = Env.get('DB_CONNECTION', '');
157
160
  const value = String(envSelectedRaw ?? '').trim();
158
161
  if (value.length > 0 && hasOwn(connections, value))
159
162
  return value;
163
+ if (value === 'default') {
164
+ return resolveImplicitDefaultConnection(connections);
165
+ }
160
166
  if (envSelectedRaw.trim().length > 0) {
161
167
  throw ErrorFactory.createConfigError(`Database connection not configured: ${value}`);
162
168
  }
163
- return hasOwn(connections, 'sqlite') ? 'sqlite' : (Object.keys(connections)[0] ?? 'sqlite');
169
+ return resolveImplicitDefaultConnection(connections);
164
170
  };
165
171
  const getDatabaseConnection = (config) => {
166
172
  const connName = config.default;
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/functions/cloudflare.ts"],"names":[],"mappings":";mBAqPuB,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;;AADhF,wBAwCE"}
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/functions/cloudflare.ts"],"names":[],"mappings":";mBAgOuB,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;;AADhF,wBAmCE"}
@@ -1,8 +1,5 @@
1
- import { appConfig } from '../config/index.js';
2
- import { Application } from '../boot/Application.js';
3
1
  import { Logger } from '../config/logger.js';
4
2
  import { clearMiddlewareConfigCache } from '../config/middleware.js';
5
- import { Kernel } from '../http/Kernel.js';
6
3
  import { CloudflareAdapter } from '../runtime/adapters/CloudflareAdapter.js';
7
4
  import mergeOverrideValues from '../runtime/OverrideValueMerge.js';
8
5
  import { ProjectRuntime } from '../runtime/ProjectRuntime.js';
@@ -174,17 +171,6 @@ const ensureStartupConfigOverridesLoaded = async () => {
174
171
  startupConfigOverridesPromise ??= applyStartupConfigOverrides();
175
172
  await startupConfigOverridesPromise;
176
173
  };
177
- const resolveRequestKernel = async () => {
178
- if (!appConfig.isDevelopment()) {
179
- return { kernel: await getKernel() };
180
- }
181
- const app = Application.create();
182
- await app.boot();
183
- return {
184
- kernel: Kernel.create(app.getRouter(), app.getContainer()),
185
- shutdown: app.shutdown,
186
- };
187
- };
188
174
  export default {
189
175
  async fetch(request, _env, _ctx) {
190
176
  try {
@@ -199,19 +185,14 @@ export default {
199
185
  await ensureStartupConfigOverridesLoaded();
200
186
  await WorkerAdapterImports.ready; // NOSONAR - Ensure adapter imports are ready before handling requests.
201
187
  await injectIoredisModule();
202
- const runtimeKernel = await resolveRequestKernel();
203
- try {
204
- const adapter = CloudflareAdapter.create({
205
- handler: async (req, res) => {
206
- await runtimeKernel.kernel.handle(req, res);
207
- },
208
- });
209
- const platformResponse = await adapter.handle(request);
210
- return adapter.formatResponse(platformResponse);
211
- }
212
- finally {
213
- await runtimeKernel.shutdown?.();
214
- }
188
+ const kernel = await getKernel();
189
+ const adapter = CloudflareAdapter.create({
190
+ handler: async (req, res) => {
191
+ await kernel.handle(req, res);
192
+ },
193
+ });
194
+ const platformResponse = await adapter.handle(request);
195
+ return adapter.formatResponse(platformResponse);
215
196
  }
216
197
  catch (error) {
217
198
  const err = error;
package/src/index.d.ts CHANGED
@@ -46,6 +46,7 @@ export { SQLiteAdapter } from './orm/adapters/SQLiteAdapter';
46
46
  export { SQLServerAdapter } from './orm/adapters/SQLServerAdapter';
47
47
  export { Database, resetDatabase, useDatabase, useEnsureDbConnected } from './orm/Database';
48
48
  export type { IDatabase } from './orm/Database';
49
+ export { DatabaseConnectionRegistry } from './orm/DatabaseConnectionRegistry';
49
50
  export { Model } from './orm/Model';
50
51
  export type { IModel, ModelConfig, ModelStatic } from './orm/Model';
51
52
  export { QueryBuilder } from './orm/QueryBuilder';
@@ -98,9 +99,9 @@ export { Xss } from './security/Xss';
98
99
  export { XssProtection } from './security/XssProtection';
99
100
  export { ErrorFactory } from './exceptions/ZintrustError';
100
101
  export { detectCloudflareWorkers, detectRuntimePlatform, RUNTIME_PLATFORM, RuntimeServices, type RuntimeCrypto, type RuntimeEnvReader, type RuntimeFs, type RuntimePlatform, type RuntimeServices as RuntimeServicesType, type RuntimeTimers, } from './runtime/RuntimeServices';
102
+ export { SystemDebuggerBridge } from './debugger/SystemDebuggerBridge';
101
103
  export { EventDispatcher } from './events/EventDispatcher';
102
104
  export type { EventListener, EventMap, IEventDispatcher } from './events/EventDispatcher';
103
- export { SystemDebuggerBridge } from './debugger/SystemDebuggerBridge';
104
105
  export { SessionManager } from './session/SessionManager';
105
106
  export type { ISession, ISessionManager, SessionData, SessionManagerOptions, } from './session/SessionManager';
106
107
  export { defaultMiddlewareFailureResponder, respondWithMiddlewareFailure, } from './middleware/MiddlewareFailureResponder';