@zintrust/core 0.1.20 → 0.1.21

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 (98) hide show
  1. package/package.json +2 -1
  2. package/src/boot/Application.d.ts.map +1 -1
  3. package/src/boot/Application.js +48 -10
  4. package/src/boot/bootstrap.js +2 -0
  5. package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
  6. package/src/cli/commands/MigrateCommand.js +36 -3
  7. package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
  8. package/src/cli/d1/D1SqlMigrations.js +6 -1
  9. package/src/cli/scaffolding/ControllerGenerator.js +4 -4
  10. package/src/cli/scaffolding/GovernanceScaffolder.js +1 -1
  11. package/src/cli/scaffolding/MigrationGenerator.js +1 -1
  12. package/src/cli/scaffolding/ModelGenerator.js +1 -1
  13. package/src/cli/scaffolding/RouteGenerator.js +1 -1
  14. package/src/cli/scaffolding/ServiceScaffolder.js +4 -4
  15. package/src/config/broadcast.d.ts +14 -28
  16. package/src/config/broadcast.d.ts.map +1 -1
  17. package/src/config/broadcast.js +69 -35
  18. package/src/config/cache.d.ts +13 -45
  19. package/src/config/cache.d.ts.map +1 -1
  20. package/src/config/cache.js +69 -25
  21. package/src/config/database.d.ts +22 -64
  22. package/src/config/database.d.ts.map +1 -1
  23. package/src/config/database.js +99 -31
  24. package/src/config/env.d.ts +6 -0
  25. package/src/config/env.d.ts.map +1 -1
  26. package/src/config/env.js +7 -0
  27. package/src/config/index.d.ts +32 -136
  28. package/src/config/index.d.ts.map +1 -1
  29. package/src/config/mail.d.ts +19 -55
  30. package/src/config/mail.d.ts.map +1 -1
  31. package/src/config/mail.js +63 -21
  32. package/src/config/middleware.d.ts +24 -0
  33. package/src/config/middleware.d.ts.map +1 -1
  34. package/src/config/middleware.js +72 -52
  35. package/src/config/notification.d.ts +14 -27
  36. package/src/config/notification.d.ts.map +1 -1
  37. package/src/config/notification.js +82 -36
  38. package/src/config/queue.d.ts +21 -51
  39. package/src/config/queue.d.ts.map +1 -1
  40. package/src/config/queue.js +72 -27
  41. package/src/config/storage.d.ts +27 -34
  42. package/src/config/storage.d.ts.map +1 -1
  43. package/src/config/storage.js +97 -56
  44. package/src/config/type.d.ts +12 -1
  45. package/src/config/type.d.ts.map +1 -1
  46. package/src/http/parsers/MultipartParser.d.ts.map +1 -1
  47. package/src/http/parsers/MultipartParser.js +69 -42
  48. package/src/index.d.ts +9 -5
  49. package/src/index.d.ts.map +1 -1
  50. package/src/index.js +1 -0
  51. package/src/microservices/PostgresAdapter.d.ts.map +1 -1
  52. package/src/microservices/PostgresAdapter.js +0 -1
  53. package/src/migrations/MigratorFactory.d.ts.map +1 -1
  54. package/src/migrations/MigratorFactory.js +18 -2
  55. package/src/node-singletons/fs.d.ts +1 -1
  56. package/src/node-singletons/fs.d.ts.map +1 -1
  57. package/src/node-singletons/fs.js +1 -1
  58. package/src/orm/Database.d.ts +2 -1
  59. package/src/orm/Database.d.ts.map +1 -1
  60. package/src/orm/Database.js +110 -67
  61. package/src/orm/DatabaseAdapter.d.ts +1 -0
  62. package/src/orm/DatabaseAdapter.d.ts.map +1 -1
  63. package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
  64. package/src/orm/DatabaseRuntimeRegistration.js +12 -0
  65. package/src/orm/QueryBuilder.d.ts +1 -1
  66. package/src/orm/QueryBuilder.d.ts.map +1 -1
  67. package/src/orm/QueryBuilder.js +4 -3
  68. package/src/orm/adapters/SQLiteAdapter.js +1 -1
  69. package/src/performance/Optimizer.d.ts +6 -6
  70. package/src/performance/Optimizer.d.ts.map +1 -1
  71. package/src/performance/Optimizer.js +133 -52
  72. package/src/routing/doc.d.ts +4 -5
  73. package/src/routing/doc.d.ts.map +1 -1
  74. package/src/routing/doc.js +35 -20
  75. package/src/routing/publicRoot.d.ts +9 -0
  76. package/src/routing/publicRoot.d.ts.map +1 -1
  77. package/src/routing/publicRoot.js +63 -2
  78. package/src/runtime/StartupConfigFileRegistry.d.ts +20 -0
  79. package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -0
  80. package/src/runtime/StartupConfigFileRegistry.js +44 -0
  81. package/src/runtime/useFileLoader.d.ts +26 -0
  82. package/src/runtime/useFileLoader.d.ts.map +1 -0
  83. package/src/runtime/useFileLoader.js +188 -0
  84. package/src/scripts/TemplateSync.js +4 -4
  85. package/src/security/XssProtection.d.ts.map +1 -1
  86. package/src/security/XssProtection.js +62 -14
  87. package/src/templates/project/basic/config/broadcast.ts.tpl +33 -17
  88. package/src/templates/project/basic/config/cache.ts.tpl +35 -17
  89. package/src/templates/project/basic/config/database.ts.tpl +68 -32
  90. package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +7 -114
  91. package/src/templates/project/basic/config/mail.ts.tpl +59 -13
  92. package/src/templates/project/basic/config/notification.ts.tpl +28 -17
  93. package/src/templates/project/basic/config/queue.ts.tpl +49 -17
  94. package/src/templates/project/basic/config/storage.ts.tpl +55 -18
  95. package/src/templates/project/basic/config/type.ts.tpl +0 -1
  96. package/src/templates/project/basic/src/index.ts.tpl +3 -0
  97. package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +0 -181
  98. package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +0 -156
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -34,6 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "bcrypt": "^6.0.0",
37
+ "bg": "^1.0.0",
37
38
  "chalk": "^5.6.2",
38
39
  "commander": "^14.0.2",
39
40
  "inquirer": "^13.2.0",
@@ -1 +1 @@
1
- {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/boot/Application.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,kBAAkB,CAAC;AASxD,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC;IACpB,aAAa,IAAI,OAAO,CAAC;IACzB,YAAY,IAAI,OAAO,CAAC;IACxB,SAAS,IAAI,OAAO,CAAC;IACrB,cAAc,IAAI,MAAM,CAAC;IACzB,SAAS,IAAI,OAAO,CAAC;IACrB,YAAY,IAAI,iBAAiB,CAAC;IAClC,kBAAkB,IAAI,gBAAgB,CAAC;IACvC,WAAW,IAAI,MAAM,CAAC;CACvB;AAqVD;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;sBACe,MAAM,GAAG,YAAY;EA0CvC,CAAC;AAEH,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/boot/Application.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,kBAAkB,CAAC;AAUxD,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC;IACpB,aAAa,IAAI,OAAO,CAAC;IACzB,YAAY,IAAI,OAAO,CAAC;IACxB,SAAS,IAAI,OAAO,CAAC;IACrB,cAAc,IAAI,MAAM,CAAC;IACzB,SAAS,IAAI,OAAO,CAAC;IACrB,YAAY,IAAI,iBAAiB,CAAC;IAClC,kBAAkB,IAAI,gBAAgB,CAAC;IACvC,WAAW,IAAI,MAAM,CAAC;CACvB;AAyYD;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;sBACe,MAAM,GAAG,YAAY;EA0CvC,CAAC;AAEH,eAAe,WAAW,CAAC"}
@@ -7,6 +7,7 @@ import { ServiceContainer } from '../container/ServiceContainer.js';
7
7
  import { StartupHealthChecks } from '../health/StartupHealthChecks.js';
8
8
  import { MiddlewareStack } from '../middleware/MiddlewareStack.js';
9
9
  import { Router } from '../routing/Router.js';
10
+ import { StartupConfigFile, StartupConfigFileRegistry } from '../runtime/StartupConfigFileRegistry.js';
10
11
  import broadcastConfig from '../config/broadcast.js';
11
12
  import { FeatureFlags } from '../config/features.js';
12
13
  import { Logger } from '../config/logger.js';
@@ -220,21 +221,47 @@ const tryImportOptional = async (modulePath) => {
220
221
  return undefined;
221
222
  }
222
223
  };
223
- const registerFromRuntimeConfig = async () => {
224
- const db = await tryImportOptional('@orm/DatabaseRuntimeRegistration');
224
+ const isCompiledJsModule = () => {
225
+ // When running from dist, this module is compiled to .js and Node ESM resolution
226
+ // requires explicit file extensions for relative imports.
227
+ return import.meta.url.endsWith('.js');
228
+ };
229
+ const dbLoader = async () => {
230
+ const db = await tryImportOptional(isCompiledJsModule()
231
+ ? '../orm/DatabaseRuntimeRegistration.js'
232
+ : '../orm/DatabaseRuntimeRegistration');
225
233
  db?.registerDatabasesFromRuntimeConfig?.(databaseConfig);
226
- const queues = await tryImportOptional('@tools/queue/QueueRuntimeRegistration');
234
+ };
235
+ const queuesLoader = async () => {
236
+ const queues = await tryImportOptional(isCompiledJsModule()
237
+ ? '../tools/queue/QueueRuntimeRegistration.js'
238
+ : '../tools/queue/QueueRuntimeRegistration');
227
239
  queues?.registerQueuesFromRuntimeConfig?.(queueConfig);
228
- const caches = await tryImportOptional('@cache/CacheRuntimeRegistration');
240
+ };
241
+ const cachesLoader = async () => {
242
+ const caches = await tryImportOptional(isCompiledJsModule()
243
+ ? '../cache/CacheRuntimeRegistration.js'
244
+ : '../cache/CacheRuntimeRegistration');
229
245
  caches?.registerCachesFromRuntimeConfig?.(cacheConfig);
230
- const broadcasters = await tryImportOptional('@broadcast/BroadcastRuntimeRegistration');
246
+ };
247
+ const registerFromRuntimeConfig = async () => {
248
+ await dbLoader();
249
+ await queuesLoader();
250
+ await cachesLoader();
251
+ const broadcasters = await tryImportOptional(isCompiledJsModule()
252
+ ? '../tools/broadcast/BroadcastRuntimeRegistration.js'
253
+ : '../tools/broadcast/BroadcastRuntimeRegistration');
231
254
  broadcasters?.registerBroadcastersFromRuntimeConfig?.({
232
255
  default: broadcastConfig.default,
233
256
  drivers: broadcastConfig.drivers,
234
257
  });
235
- const disks = await tryImportOptional('@storage/StorageRuntimeRegistration');
258
+ const disks = await tryImportOptional(isCompiledJsModule()
259
+ ? '../tools/storage/StorageRuntimeRegistration.js'
260
+ : '../tools/storage/StorageRuntimeRegistration');
236
261
  disks?.registerDisksFromRuntimeConfig?.(storageConfig);
237
- const notifications = await tryImportOptional('@notification/NotificationRuntimeRegistration');
262
+ const notifications = await tryImportOptional(isCompiledJsModule()
263
+ ? '../tools/notification/NotificationRuntimeRegistration.js'
264
+ : '../tools/notification/NotificationRuntimeRegistration');
238
265
  notifications?.registerNotificationChannelsFromRuntimeConfig?.({
239
266
  default: notificationConfig.default,
240
267
  drivers: notificationConfig.drivers,
@@ -246,6 +273,17 @@ const createLifecycle = (params) => {
246
273
  return;
247
274
  Logger.info(`🚀 Booting Zintrust Application in ${params.environment} mode...`);
248
275
  StartupConfigValidator.assertValid();
276
+ // Preload project-owned config overrides that must be available synchronously.
277
+ await StartupConfigFileRegistry.preload([
278
+ StartupConfigFile.Middleware,
279
+ StartupConfigFile.Cache,
280
+ StartupConfigFile.Database,
281
+ StartupConfigFile.Queue,
282
+ StartupConfigFile.Storage,
283
+ StartupConfigFile.Mail,
284
+ StartupConfigFile.Broadcast,
285
+ StartupConfigFile.Notification,
286
+ ]);
249
287
  FeatureFlags.initialize();
250
288
  await StartupHealthChecks.assertHealthy();
251
289
  await registerFromRuntimeConfig();
@@ -302,9 +340,9 @@ export const Application = Object.freeze({
302
340
  boot,
303
341
  shutdown,
304
342
  isBooted: () => booted,
305
- isDevelopment: () => environment === 'development',
306
- isProduction: () => environment === 'production',
307
- isTesting: () => environment === 'testing',
343
+ isDevelopment: () => appConfig.isDevelopment(),
344
+ isProduction: () => appConfig.isProduction(),
345
+ isTesting: () => appConfig.isTesting(),
308
346
  getEnvironment: () => environment,
309
347
  getRouter: () => router,
310
348
  getContainer: () => container,
@@ -8,6 +8,8 @@ import { Server } from './Server.js';
8
8
  import { Env } from '../config/env.js';
9
9
  import { Logger } from '../config/logger.js';
10
10
  import { ErrorFactory } from '../exceptions/ZintrustError.js';
11
+ // Register plugins (adapters, drivers, etc.)
12
+ // import '@/zintrust.plugins';
11
13
  let appInstance;
12
14
  let serverInstance;
13
15
  let isShuttingDown = false;
@@ -1 +1 @@
1
- {"version":3,"file":"MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAsarE;;GAEG;AACH,eAAO,MAAM,cAAc;IACzB;;OAEG;cACO,YAAY;EAUtB,CAAC"}
1
+ {"version":3,"file":"MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAidrE;;GAEG;AACH,eAAO,MAAM,cAAc;IACzB;;OAEG;cACO,YAAY;EAUtB,CAAC"}
@@ -27,6 +27,7 @@ const addMigrateOptions = (command) => {
27
27
  .option('--local', 'D1 only: run against local D1 database')
28
28
  .option('--remote', 'D1 only: run against remote D1 database')
29
29
  .option('--database <name>', 'D1 only: Wrangler D1 database binding name (not DB_DATABASE env var)')
30
+ .option('--all', 'Run migrations for all configured database connections')
30
31
  .option('--no-interactive', 'Disable interactive prompts (useful for CI/CD)');
31
32
  };
32
33
  const getInteractive = (options) => options['interactive'] !== false;
@@ -57,6 +58,8 @@ const describeTargetDatabase = (conn) => {
57
58
  return `postgresql:${conn.host}:${conn.port}/${conn.database}`;
58
59
  case 'mysql':
59
60
  return `mysql:${conn.host}:${conn.port}/${conn.database}`;
61
+ case 'sqlserver':
62
+ return `sqlserver:${conn.host}:${conn.port}/${conn.database}`;
60
63
  default:
61
64
  return `${conn.driver}`;
62
65
  }
@@ -83,6 +86,15 @@ const mapConnectionToOrmConfig = (conn) => {
83
86
  username: conn.username,
84
87
  password: conn.password,
85
88
  };
89
+ case 'sqlserver':
90
+ return {
91
+ driver: 'sqlserver',
92
+ host: conn.host,
93
+ port: conn.port,
94
+ database: conn.database,
95
+ username: conn.username,
96
+ password: conn.password,
97
+ };
86
98
  default:
87
99
  return { driver: 'sqlite', database: ':memory:' };
88
100
  }
@@ -225,9 +237,7 @@ const runD1Actions = async (params) => {
225
237
  cmd.info(output);
226
238
  cmd.success('D1 migrations completed successfully');
227
239
  };
228
- const executeMigrate = async (options, cmd) => {
229
- const interactive = getInteractive(options);
230
- const conn = databaseConfig.getConnection();
240
+ const processConnection = async (conn, options, cmd, interactive) => {
231
241
  // Avoid confusion: `--database` is a D1-only option (Wrangler binding name), not DB_DATABASE.
232
242
  if (isD1Driver(conn.driver)) {
233
243
  cmd.debug(`Migrate command executed with options: ${JSON.stringify(options)}`);
@@ -293,6 +303,29 @@ const executeMigrate = async (options, cmd) => {
293
303
  await db.disconnect();
294
304
  }
295
305
  };
306
+ const executeMigrate = async (options, cmd) => {
307
+ const interactive = getInteractive(options);
308
+ const targets = [];
309
+ if (options['all'] === true) {
310
+ for (const [name, config] of Object.entries(databaseConfig.connections)) {
311
+ targets.push({ name, config });
312
+ }
313
+ }
314
+ else {
315
+ targets.push({ name: 'default', config: databaseConfig.getConnection() });
316
+ }
317
+ // Run sequentially (to preserve ordering and interactive prompts), but avoid `await` inside a loop.
318
+ let sequence = Promise.resolve();
319
+ for (const { name, config } of targets) {
320
+ sequence = sequence.then(async () => {
321
+ if (targets.length > 1) {
322
+ cmd.info(`\n--- Connection: ${name} (${config.driver}) ---`);
323
+ }
324
+ await processConnection(config, options, cmd, interactive);
325
+ });
326
+ }
327
+ await sequence;
328
+ };
296
329
  /**
297
330
  * Migrate Command Factory
298
331
  */
@@ -1 +1 @@
1
- {"version":3,"file":"D1SqlMigrations.d.ts","sourceRoot":"","sources":["../../../../src/cli/d1/D1SqlMigrations.ts"],"names":[],"mappings":"AAWA,KAAK,6BAA6B,GAAG;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AA4NF,eAAO,MAAM,eAAe;0BACE,6BAA6B,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;EAmC5F,CAAC"}
1
+ {"version":3,"file":"D1SqlMigrations.d.ts","sourceRoot":"","sources":["../../../../src/cli/d1/D1SqlMigrations.ts"],"names":[],"mappings":"AAWA,KAAK,6BAA6B,GAAG;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAiOF,eAAO,MAAM,eAAe;0BACE,6BAA6B,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;EAmC5F,CAAC"}
@@ -121,9 +121,14 @@ const createCaptureDb = (onSql) => {
121
121
  await RESOLVED_VOID;
122
122
  return null;
123
123
  },
124
+ async execute(sql, parameters = []) {
125
+ captureSql(onSql, sql, parameters);
126
+ await RESOLVED_VOID;
127
+ return { rows: [], rowCount: 0 };
128
+ },
124
129
  async transaction(callback) {
125
130
  await RESOLVED_VOID;
126
- return callback(db);
131
+ return callback(this);
127
132
  },
128
133
  table() {
129
134
  throw ErrorFactory.createCliError('D1 SQL compilation does not support QueryBuilder-based migrations yet. Use db.query(...) with explicit SQL.');
@@ -117,7 +117,7 @@ function generateCrudController(options) {
117
117
  * Auto-generated CRUD controller
118
118
  */
119
119
 
120
- import { type IRequest, type IResponse, Controller } from '@zintrust/core';
120
+ import { type IRequest, type IResponse, Controller } from '../../index.js';
121
121
  import { ${modelName} } from '@app/Models/${modelName}';
122
122
 
123
123
  function handleError(res: IResponse, error: unknown): void {
@@ -286,7 +286,7 @@ function generateApiController(options) {
286
286
  * Auto-generated API controller
287
287
  */
288
288
 
289
- import { type IRequest, type IResponse, Controller } from '@zintrust/core';
289
+ import { type IRequest, type IResponse, Controller } from '../../index.js';
290
290
 
291
291
  function handleError(res: IResponse, error: unknown): void {
292
292
  const message = error instanceof Error ? error.message : 'Internal server error';
@@ -387,7 +387,7 @@ function generateGraphQLController(options) {
387
387
  * Auto-generated GraphQL controller
388
388
  */
389
389
 
390
- import { type IRequest, type IResponse, Controller } from '@zintrust/core';
390
+ import { type IRequest, type IResponse, Controller } from '../../index.js';
391
391
 
392
392
  function handleError(res: IResponse, error: unknown): void {
393
393
  const message = error instanceof Error ? error.message : 'GraphQL error';
@@ -494,7 +494,7 @@ function generateWebhookController(options) {
494
494
  * Auto-generated Webhook controller
495
495
  */
496
496
 
497
- import { type IRequest, type IResponse, Controller } from '@zintrust/core';
497
+ import { type IRequest, type IResponse, Controller } from '../../index.js';
498
498
  import { Logger } from '../../config/logger';
499
499
 
500
500
  function handleError(res: IResponse, error: unknown): void {
@@ -200,7 +200,7 @@ describe('Architecture: import boundaries', () => {
200
200
  `;
201
201
  const ROUTE_MIDDLEWARE_REGISTRY_ARCH_TEST_CONTENT = `import { middlewareConfigObj } from '../../config/middleware';
202
202
  import { registerRoutes } from '../../../routes/api';
203
- import { RouteRegistry, Router } from '@zintrust/core';
203
+ import { RouteRegistry, Router } from '../../index.js';
204
204
  import { beforeEach, describe, expect, it } from 'vitest';
205
205
 
206
206
  describe('Architecture: route middleware registry', () => {
@@ -160,7 +160,7 @@ function resolveMigrationImportBlock(migrationsPath) {
160
160
  // fall through
161
161
  }
162
162
  }
163
- return `import { MigrationSchema, type Blueprint, type IDatabase } from '@zintrust/core';`;
163
+ return `import { MigrationSchema, type Blueprint, type IDatabase } from '../../index.js';`;
164
164
  }
165
165
  /**
166
166
  * Generate CREATE migration
@@ -84,7 +84,7 @@ function buildModelCode(options) {
84
84
  * Auto-generated model file
85
85
  */
86
86
 
87
- import { type IModel, Model } from '@zintrust/core';
87
+ import { type IModel, Model } from '../../index.js';
88
88
 
89
89
  export const ${options.name} = Object.freeze(
90
90
  Model.define({
@@ -96,7 +96,7 @@ ${routeRegistration}
96
96
  * Build import statements
97
97
  */
98
98
  function buildImports(options) {
99
- const imports = ["import { Router, type IRouter } from '@zintrust/core';"];
99
+ const imports = ["import { Router, type IRouter } from '../../index.js';"];
100
100
  // Collect unique controllers
101
101
  const controllers = new Set();
102
102
  for (const route of options.routes) {
@@ -162,7 +162,7 @@ function generateServiceIndex(options) {
162
162
  * Auth: ${options.auth ?? 'api-key'}
163
163
  */
164
164
 
165
- import { Application, Server } from '@zintrust/core';
165
+ import { Application, Server } from '../../index.js';
166
166
  import { Logger } from '../../config/logger';
167
167
  import { Env } from '../../config/env';
168
168
  import { esmDirname } from '../../common/index';
@@ -192,7 +192,7 @@ function generateServiceRoutes(options) {
192
192
  * ${options.name} Service Routes
193
193
  */
194
194
 
195
- import { Router, type IRouter } from '@zintrust/core';
195
+ import { Router, type IRouter } from '../../index.js';
196
196
 
197
197
  export function registerRoutes(router: IRouter): void {
198
198
  // Example route
@@ -222,7 +222,7 @@ function generateExampleController(options) {
222
222
  * Example Controller for ${options.name} Service
223
223
  */
224
224
 
225
- import { type IRequest, type IResponse, Controller } from '@zintrust/core';
225
+ import { type IRequest, type IResponse, Controller } from '../../index.js';
226
226
 
227
227
  const controller = Object.freeze({
228
228
  ...Controller,
@@ -285,7 +285,7 @@ function generateExampleModel(options) {
285
285
  * Example Model for ${options.name} Service
286
286
  */
287
287
 
288
- import { Model } from '@zintrust/core';
288
+ import { Model } from '../../index.js';
289
289
 
290
290
  export const Example = Model.define({
291
291
  table: '${options.name}',
@@ -4,33 +4,19 @@
4
4
  * Centralizes broadcast driver selection and provider env mappings.
5
5
  * Driver selection must be dynamic (tests may mutate process.env).
6
6
  */
7
- import type { InMemoryBroadcastDriverConfig, KnownBroadcastDriverConfig, PusherBroadcastDriverConfig, RedisBroadcastDriverConfig, RedisHttpsBroadcastDriverConfig } from './type';
8
- declare const _default: Readonly<{
9
- /**
10
- * Default broadcaster name (normalized).
11
- */
12
- readonly default: string;
13
- /**
14
- * Broadcast drivers.
15
- *
16
- * You may add custom named broadcasters (e.g. `ops`, `billing`) that point to any
17
- * known driver config.
18
- */
19
- readonly drivers: {
20
- readonly inmemory: InMemoryBroadcastDriverConfig;
21
- readonly pusher: PusherBroadcastDriverConfig;
22
- readonly redis: RedisBroadcastDriverConfig;
23
- readonly redishttps: RedisHttpsBroadcastDriverConfig;
24
- };
25
- /**
26
- * Normalized broadcast driver name for the default broadcaster.
27
- */
28
- readonly getDriverName: () => string;
29
- /**
30
- * Get a config object for the currently selected driver.
31
- * Defaults to inmemory for unknown/unsupported names.
32
- */
33
- readonly getDriverConfig: (name?: string) => KnownBroadcastDriverConfig;
7
+ import type { BroadcastDrivers, KnownBroadcastDriverConfig } from './type';
8
+ export type BroadcastConfigOverrides = Partial<{
9
+ default: string;
10
+ drivers: Record<string, KnownBroadcastDriverConfig>;
34
11
  }>;
35
- export default _default;
12
+ type BroadcastRuntimeConfig = {
13
+ default: string;
14
+ drivers: BroadcastDrivers;
15
+ getDriverName: () => string;
16
+ getDriverConfig: (name?: string) => KnownBroadcastDriverConfig;
17
+ };
18
+ declare const createBroadcastConfig: () => BroadcastRuntimeConfig;
19
+ export type BroadcastConfig = ReturnType<typeof createBroadcastConfig>;
20
+ declare const broadcastConfig: BroadcastConfig;
21
+ export default broadcastConfig;
36
22
  //# sourceMappingURL=broadcast.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../../src/config/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAGV,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,+BAA+B,EAChC,MAAM,cAAc,CAAC;;IA4EpB;;OAEG;sBACY,MAAM;IAIrB;;;;;OAKG;;2BAEe,6BAA6B;;;;;IAc/C;;OAEG;kCACc,MAAM;IAIvB;;;OAGG;sCACoB,MAAM,KAAG,0BAA0B;;AAK5D,wBAAiD"}
1
+ {"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../../src/config/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAEV,gBAAgB,EAEhB,0BAA0B,EAI3B,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;CACrD,CAAC,CAAC;AAEH,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,aAAa,EAAE,MAAM,MAAM,CAAC;IAC5B,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,0BAA0B,CAAC;CAChE,CAAC;AA0EF,QAAA,MAAM,qBAAqB,QAAO,sBAoDjC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAqBvE,QAAA,MAAM,eAAe,EAAE,eAYrB,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -4,6 +4,7 @@
4
4
  * Centralizes broadcast driver selection and provider env mappings.
5
5
  * Driver selection must be dynamic (tests may mutate process.env).
6
6
  */
7
+ import { StartupConfigFile, StartupConfigFileRegistry } from '../runtime/StartupConfigFileRegistry.js';
7
8
  import { Env } from './env.js';
8
9
  import { ErrorFactory } from '../exceptions/ZintrustError.js';
9
10
  const normalizeDriverName = (value) => value.trim().toLowerCase();
@@ -60,45 +61,78 @@ const getBroadcastDriver = (config, name) => {
60
61
  return fallback;
61
62
  throw ErrorFactory.createConfigError('No broadcast drivers are configured');
62
63
  };
63
- const broadcastConfigObj = {
64
- /**
65
- * Default broadcaster name (normalized).
66
- */
67
- get default() {
68
- return getDefaultBroadcaster(this.drivers);
69
- },
70
- /**
71
- * Broadcast drivers.
72
- *
73
- * You may add custom named broadcasters (e.g. `ops`, `billing`) that point to any
74
- * known driver config.
75
- */
76
- drivers: {
77
- get inmemory() {
78
- return { driver: 'inmemory' };
64
+ const createBroadcastConfig = () => {
65
+ const overrides = StartupConfigFileRegistry.get(StartupConfigFile.Broadcast) ?? {};
66
+ const broadcastConfigObj = {
67
+ /**
68
+ * Default broadcaster name (normalized).
69
+ */
70
+ get default() {
71
+ const overrideDefault = overrides.default;
72
+ if (typeof overrideDefault === 'string' && overrideDefault.trim().length > 0) {
73
+ const value = normalizeDriverName(overrideDefault);
74
+ if (value.length > 0 && hasOwn(this.drivers, value))
75
+ return value;
76
+ throw ErrorFactory.createConfigError(`Broadcast driver not configured: ${value}`);
77
+ }
78
+ return getDefaultBroadcaster(this.drivers);
79
79
  },
80
- get pusher() {
81
- return getPusherConfig();
80
+ /**
81
+ * Broadcast drivers.
82
+ *
83
+ * You may add custom named broadcasters (e.g. `ops`, `billing`) that point to any
84
+ * known driver config.
85
+ */
86
+ get drivers() {
87
+ return {
88
+ inmemory: { driver: 'inmemory' },
89
+ pusher: getPusherConfig(),
90
+ redis: getRedisConfig(),
91
+ redishttps: getRedisHttpsConfig(),
92
+ ...(overrides.drivers ?? {}),
93
+ };
82
94
  },
83
- get redis() {
84
- return getRedisConfig();
95
+ /**
96
+ * Normalized broadcast driver name for the default broadcaster.
97
+ */
98
+ getDriverName() {
99
+ return normalizeDriverName(this.default);
85
100
  },
86
- get redishttps() {
87
- return getRedisHttpsConfig();
101
+ /**
102
+ * Get a config object for the currently selected driver.
103
+ * Defaults to inmemory for unknown/unsupported names.
104
+ */
105
+ getDriverConfig(name) {
106
+ return getBroadcastDriver(this, name);
88
107
  },
108
+ };
109
+ return Object.freeze(broadcastConfigObj);
110
+ };
111
+ let cached = null;
112
+ const proxyTarget = {};
113
+ const ensureBroadcastConfig = () => {
114
+ if (cached)
115
+ return cached;
116
+ cached = createBroadcastConfig();
117
+ try {
118
+ Object.defineProperties(proxyTarget, Object.getOwnPropertyDescriptors(cached));
119
+ }
120
+ catch {
121
+ // best-effort
122
+ }
123
+ return cached;
124
+ };
125
+ const broadcastConfig = new Proxy(proxyTarget, {
126
+ get(_target, prop) {
127
+ return ensureBroadcastConfig()[prop];
89
128
  },
90
- /**
91
- * Normalized broadcast driver name for the default broadcaster.
92
- */
93
- getDriverName() {
94
- return normalizeDriverName(this.default);
129
+ ownKeys() {
130
+ ensureBroadcastConfig();
131
+ return Reflect.ownKeys(proxyTarget);
95
132
  },
96
- /**
97
- * Get a config object for the currently selected driver.
98
- * Defaults to inmemory for unknown/unsupported names.
99
- */
100
- getDriverConfig(name) {
101
- return getBroadcastDriver(this, name);
133
+ getOwnPropertyDescriptor(_target, prop) {
134
+ ensureBroadcastConfig();
135
+ return Object.getOwnPropertyDescriptor(proxyTarget, prop);
102
136
  },
103
- };
104
- export default Object.freeze(broadcastConfigObj);
137
+ });
138
+ export default broadcastConfig;
@@ -3,53 +3,21 @@
3
3
  * Caching drivers and settings
4
4
  * Sealed namespace for immutability
5
5
  */
6
- import type { CacheDriverConfig } from './type';
7
- export declare const cacheConfig: Readonly<{
8
- /**
9
- * Default cache driver
10
- */
6
+ import type { CacheConfigInput, CacheDriverConfig } from './type';
7
+ export type CacheConfigOverrides = Partial<{
11
8
  default: string;
12
- /**
13
- * Cache drivers
14
- */
15
- drivers: {
16
- memory: {
17
- driver: "memory";
18
- ttl: number;
19
- };
20
- redis: {
21
- driver: "redis";
22
- host: string;
23
- port: number;
24
- ttl: number;
25
- };
26
- mongodb: {
27
- driver: "mongodb";
28
- uri: string;
29
- db: string;
30
- ttl: number;
31
- };
32
- kv: {
33
- driver: "kv";
34
- ttl: number;
35
- };
36
- 'kv-remote': {
37
- driver: "kv-remote";
38
- ttl: number;
39
- };
40
- };
41
- /**
42
- * Get cache driver config
43
- */
44
- getDriver(name?: string): CacheDriverConfig;
45
- /**
46
- * Key prefix for all cache keys
47
- */
9
+ drivers: CacheConfigInput['drivers'];
48
10
  keyPrefix: string;
49
- /**
50
- * Default cache TTL (seconds)
51
- */
52
11
  ttl: number;
53
12
  }>;
54
- export type CacheConfig = typeof cacheConfig;
13
+ declare const createCacheConfig: () => {
14
+ default: string;
15
+ drivers: CacheConfigInput["drivers"];
16
+ getDriver: (name?: string) => CacheDriverConfig;
17
+ keyPrefix: string;
18
+ ttl: number;
19
+ };
20
+ export type CacheConfig = ReturnType<typeof createCacheConfig>;
21
+ export declare const cacheConfig: CacheConfig;
22
+ export {};
55
23
  //# sourceMappingURL=cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AA2FxE,eAAO,MAAM,WAAW;IA/DtB;;OAEG;;IAaH;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BH;;OAEG;qBACc,MAAM,GAAG,iBAAiB;IAI3C;;OAEG;;IAGH;;OAEG;;EAImD,CAAC;AACzD,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGxE,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAAC;AA0BH,QAAA,MAAM,iBAAiB,QAAO;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;IACrC,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,iBAAiB,CAAC;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CA4Fb,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAqB/D,eAAO,MAAM,WAAW,EAAE,WAYxB,CAAC"}