@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.
- package/package.json +2 -1
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +48 -10
- package/src/boot/bootstrap.js +2 -0
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +36 -3
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
- package/src/cli/d1/D1SqlMigrations.js +6 -1
- package/src/cli/scaffolding/ControllerGenerator.js +4 -4
- package/src/cli/scaffolding/GovernanceScaffolder.js +1 -1
- package/src/cli/scaffolding/MigrationGenerator.js +1 -1
- package/src/cli/scaffolding/ModelGenerator.js +1 -1
- package/src/cli/scaffolding/RouteGenerator.js +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +4 -4
- package/src/config/broadcast.d.ts +14 -28
- package/src/config/broadcast.d.ts.map +1 -1
- package/src/config/broadcast.js +69 -35
- package/src/config/cache.d.ts +13 -45
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cache.js +69 -25
- package/src/config/database.d.ts +22 -64
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +99 -31
- package/src/config/env.d.ts +6 -0
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +7 -0
- package/src/config/index.d.ts +32 -136
- package/src/config/index.d.ts.map +1 -1
- package/src/config/mail.d.ts +19 -55
- package/src/config/mail.d.ts.map +1 -1
- package/src/config/mail.js +63 -21
- package/src/config/middleware.d.ts +24 -0
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +72 -52
- package/src/config/notification.d.ts +14 -27
- package/src/config/notification.d.ts.map +1 -1
- package/src/config/notification.js +82 -36
- package/src/config/queue.d.ts +21 -51
- package/src/config/queue.d.ts.map +1 -1
- package/src/config/queue.js +72 -27
- package/src/config/storage.d.ts +27 -34
- package/src/config/storage.d.ts.map +1 -1
- package/src/config/storage.js +97 -56
- package/src/config/type.d.ts +12 -1
- package/src/config/type.d.ts.map +1 -1
- package/src/http/parsers/MultipartParser.d.ts.map +1 -1
- package/src/http/parsers/MultipartParser.js +69 -42
- package/src/index.d.ts +9 -5
- package/src/index.d.ts.map +1 -1
- package/src/index.js +1 -0
- package/src/microservices/PostgresAdapter.d.ts.map +1 -1
- package/src/microservices/PostgresAdapter.js +0 -1
- package/src/migrations/MigratorFactory.d.ts.map +1 -1
- package/src/migrations/MigratorFactory.js +18 -2
- package/src/node-singletons/fs.d.ts +1 -1
- package/src/node-singletons/fs.d.ts.map +1 -1
- package/src/node-singletons/fs.js +1 -1
- package/src/orm/Database.d.ts +2 -1
- package/src/orm/Database.d.ts.map +1 -1
- package/src/orm/Database.js +110 -67
- package/src/orm/DatabaseAdapter.d.ts +1 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.js +12 -0
- package/src/orm/QueryBuilder.d.ts +1 -1
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +4 -3
- package/src/orm/adapters/SQLiteAdapter.js +1 -1
- package/src/performance/Optimizer.d.ts +6 -6
- package/src/performance/Optimizer.d.ts.map +1 -1
- package/src/performance/Optimizer.js +133 -52
- package/src/routing/doc.d.ts +4 -5
- package/src/routing/doc.d.ts.map +1 -1
- package/src/routing/doc.js +35 -20
- package/src/routing/publicRoot.d.ts +9 -0
- package/src/routing/publicRoot.d.ts.map +1 -1
- package/src/routing/publicRoot.js +63 -2
- package/src/runtime/StartupConfigFileRegistry.d.ts +20 -0
- package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -0
- package/src/runtime/StartupConfigFileRegistry.js +44 -0
- package/src/runtime/useFileLoader.d.ts +26 -0
- package/src/runtime/useFileLoader.d.ts.map +1 -0
- package/src/runtime/useFileLoader.js +188 -0
- package/src/scripts/TemplateSync.js +4 -4
- package/src/security/XssProtection.d.ts.map +1 -1
- package/src/security/XssProtection.js +62 -14
- package/src/templates/project/basic/config/broadcast.ts.tpl +33 -17
- package/src/templates/project/basic/config/cache.ts.tpl +35 -17
- package/src/templates/project/basic/config/database.ts.tpl +68 -32
- package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +7 -114
- package/src/templates/project/basic/config/mail.ts.tpl +59 -13
- package/src/templates/project/basic/config/notification.ts.tpl +28 -17
- package/src/templates/project/basic/config/queue.ts.tpl +49 -17
- package/src/templates/project/basic/config/storage.ts.tpl +55 -18
- package/src/templates/project/basic/config/type.ts.tpl +0 -1
- package/src/templates/project/basic/src/index.ts.tpl +3 -0
- package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +0 -181
- 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.
|
|
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;
|
|
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"}
|
package/src/boot/Application.js
CHANGED
|
@@ -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
|
|
224
|
-
|
|
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
|
-
|
|
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
|
-
|
|
240
|
+
};
|
|
241
|
+
const cachesLoader = async () => {
|
|
242
|
+
const caches = await tryImportOptional(isCompiledJsModule()
|
|
243
|
+
? '../cache/CacheRuntimeRegistration.js'
|
|
244
|
+
: '../cache/CacheRuntimeRegistration');
|
|
229
245
|
caches?.registerCachesFromRuntimeConfig?.(cacheConfig);
|
|
230
|
-
|
|
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(
|
|
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(
|
|
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: () =>
|
|
306
|
-
isProduction: () =>
|
|
307
|
-
isTesting: () =>
|
|
343
|
+
isDevelopment: () => appConfig.isDevelopment(),
|
|
344
|
+
isProduction: () => appConfig.isProduction(),
|
|
345
|
+
isTesting: () => appConfig.isTesting(),
|
|
308
346
|
getEnvironment: () => environment,
|
|
309
347
|
getRouter: () => router,
|
|
310
348
|
getContainer: () => container,
|
package/src/boot/bootstrap.js
CHANGED
|
@@ -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;
|
|
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
|
|
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;
|
|
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(
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
163
|
+
return `import { MigrationSchema, type Blueprint, type IDatabase } from '../../index.js';`;
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
166
|
* Generate CREATE migration
|
|
@@ -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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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;
|
|
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"}
|
package/src/config/broadcast.js
CHANGED
|
@@ -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
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
84
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Normalized broadcast driver name for the default broadcaster.
|
|
97
|
+
*/
|
|
98
|
+
getDriverName() {
|
|
99
|
+
return normalizeDriverName(this.default);
|
|
85
100
|
},
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
getDriverName() {
|
|
94
|
-
return normalizeDriverName(this.default);
|
|
129
|
+
ownKeys() {
|
|
130
|
+
ensureBroadcastConfig();
|
|
131
|
+
return Reflect.ownKeys(proxyTarget);
|
|
95
132
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
|
137
|
+
});
|
|
138
|
+
export default broadcastConfig;
|
package/src/config/cache.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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;
|
|
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"}
|