@zintrust/core 0.1.41 → 0.1.42
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 +17 -1
- package/src/boot/bootstrap.js +27 -11
- package/src/boot/registry/runtime.d.ts.map +1 -1
- package/src/boot/registry/runtime.js +11 -0
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +12 -0
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/ConfigCommand.js +3 -5
- package/src/cli/commands/D1LearnCommand.d.ts +9 -0
- package/src/cli/commands/D1LearnCommand.d.ts.map +1 -0
- package/src/cli/commands/D1LearnCommand.js +143 -0
- package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/D1MigrateCommand.js +55 -16
- package/src/cli/commands/InitContainerCommand.d.ts.map +1 -1
- package/src/cli/commands/InitContainerCommand.js +21 -6
- package/src/cli/commands/InitEcosystemCommand.d.ts +6 -0
- package/src/cli/commands/InitEcosystemCommand.d.ts.map +1 -0
- package/src/cli/commands/InitEcosystemCommand.js +51 -0
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +78 -36
- package/src/cli/commands/MigrateWorkerCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateWorkerCommand.js +36 -2
- package/src/cli/commands/PutCommand.d.ts +6 -0
- package/src/cli/commands/PutCommand.d.ts.map +1 -0
- package/src/cli/commands/PutCommand.js +173 -0
- package/src/cli/commands/QueueRecoveryCommand.d.ts.map +1 -1
- package/src/cli/commands/QueueRecoveryCommand.js +113 -14
- package/src/cli/commands/ScheduleListCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleListCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleListCommand.js +62 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleRunCommand.js +32 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleStartCommand.js +40 -0
- package/src/cli/commands/SecretsCommand.d.ts.map +1 -1
- package/src/cli/commands/SecretsCommand.js +2 -2
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts +6 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.js +55 -0
- package/src/cli/config/ConfigManager.d.ts.map +1 -1
- package/src/cli/config/ConfigManager.js +8 -1
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
- package/src/cli/d1/D1SqlMigrations.js +11 -1
- package/src/cli/d1/WranglerConfig.d.ts.map +1 -1
- package/src/cli/d1/WranglerConfig.js +34 -2
- package/src/cli/services/VersionChecker.d.ts.map +1 -1
- package/src/cli/services/VersionChecker.js +5 -1
- package/src/cli/utils/DatabaseCliUtils.d.ts.map +1 -1
- package/src/cli/utils/DatabaseCliUtils.js +6 -1
- package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
- package/src/cli/utils/EnvFileLoader.js +33 -14
- package/src/cli.d.ts +5 -0
- package/src/cli.d.ts.map +1 -0
- package/src/cli.js +4 -0
- package/src/collections/index.d.ts +2 -2
- package/src/collections/index.d.ts.map +1 -1
- package/src/collections/index.js +1 -1
- package/src/common/RemoteSignedJson.d.ts.map +1 -1
- package/src/common/RemoteSignedJson.js +49 -23
- package/src/common/utility.d.ts.map +1 -1
- package/src/common/utility.js +2 -6
- package/src/config/cloudflare.d.ts.map +1 -1
- package/src/config/cloudflare.js +19 -8
- package/src/config/env.js +2 -2
- package/src/helper/index.d.ts +225 -0
- package/src/helper/index.d.ts.map +1 -0
- package/src/helper/index.js +347 -0
- package/src/index.d.ts +3 -6
- package/src/index.d.ts.map +1 -1
- package/src/index.js +7 -9
- package/src/migrations/MigrationDiscovery.d.ts.map +1 -1
- package/src/migrations/MigrationDiscovery.js +2 -1
- package/src/orm/DatabaseAdapter.d.ts +1 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/SchemaStatemenWriter.d.ts +15 -0
- package/src/orm/SchemaStatemenWriter.d.ts.map +1 -0
- package/src/orm/SchemaStatemenWriter.js +78 -0
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/D1Adapter.js +52 -2
- package/src/orm/adapters/D1RemoteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/D1RemoteAdapter.js +137 -89
- package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLProxyAdapter.js +100 -81
- package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/PostgreSQLProxyAdapter.js +26 -10
- package/src/orm/adapters/SqlProxyAdapterUtils.d.ts.map +1 -1
- package/src/orm/adapters/SqlProxyAdapterUtils.js +2 -1
- package/src/orm/adapters/SqlProxyRegistryMode.d.ts +12 -0
- package/src/orm/adapters/SqlProxyRegistryMode.d.ts.map +1 -0
- package/src/orm/adapters/SqlProxyRegistryMode.js +24 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts +3 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SqlServerProxyAdapter.js +125 -117
- package/src/orm/migrations/MigrationStore.js +1 -1
- package/src/proxy/ProxyRequestParsing.d.ts +9 -0
- package/src/proxy/ProxyRequestParsing.d.ts.map +1 -0
- package/src/proxy/ProxyRequestParsing.js +16 -0
- package/src/proxy/RequestValidator.d.ts.map +1 -1
- package/src/proxy/RequestValidator.js +2 -1
- package/src/proxy/SigningService.js +2 -2
- package/src/proxy/SqlProxyDbOverrides.d.ts +17 -0
- package/src/proxy/SqlProxyDbOverrides.d.ts.map +1 -0
- package/src/proxy/SqlProxyDbOverrides.js +1 -0
- package/src/proxy/SqlProxyServerDeps.d.ts +12 -0
- package/src/proxy/SqlProxyServerDeps.d.ts.map +1 -0
- package/src/proxy/SqlProxyServerDeps.js +9 -0
- package/src/proxy/StatementPayloadValidator.d.ts +13 -0
- package/src/proxy/StatementPayloadValidator.d.ts.map +1 -0
- package/src/proxy/StatementPayloadValidator.js +18 -0
- package/src/proxy/StatementRegistryLoader.d.ts +2 -0
- package/src/proxy/StatementRegistryLoader.d.ts.map +1 -0
- package/src/proxy/StatementRegistryLoader.js +36 -0
- package/src/proxy/StatementRegistryResolver.d.ts +15 -0
- package/src/proxy/StatementRegistryResolver.d.ts.map +1 -0
- package/src/proxy/StatementRegistryResolver.js +34 -0
- package/src/proxy/d1/ZintrustD1Proxy.d.ts +2 -1
- package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
- package/src/proxy/d1/ZintrustD1Proxy.js +2 -1
- package/src/proxy/isMutatingSql.d.ts +2 -0
- package/src/proxy/isMutatingSql.d.ts.map +1 -0
- package/src/proxy/isMutatingSql.js +12 -0
- package/src/proxy/kv/ZintrustKvProxy.d.ts +2 -1
- package/src/proxy/kv/ZintrustKvProxy.d.ts.map +1 -1
- package/src/proxy/kv/ZintrustKvProxy.js +2 -1
- package/src/proxy/mysql/MySqlProxyServer.d.ts +2 -8
- package/src/proxy/mysql/MySqlProxyServer.d.ts.map +1 -1
- package/src/proxy/mysql/MySqlProxyServer.js +84 -51
- package/src/proxy/postgres/PostgresProxyServer.d.ts +2 -8
- package/src/proxy/postgres/PostgresProxyServer.d.ts.map +1 -1
- package/src/proxy/postgres/PostgresProxyServer.js +86 -48
- package/src/proxy/smtp/SmtpProxyServer.d.ts.map +1 -1
- package/src/proxy/smtp/SmtpProxyServer.js +6 -5
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts +2 -8
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts.map +1 -1
- package/src/proxy/sqlserver/SqlServerProxyServer.js +84 -49
- package/src/proxy.d.ts +4 -0
- package/src/proxy.d.ts.map +1 -0
- package/src/proxy.js +3 -0
- package/src/scheduler/Schedule.d.ts +36 -0
- package/src/scheduler/Schedule.d.ts.map +1 -0
- package/src/scheduler/Schedule.js +197 -0
- package/src/scheduler/ScheduleHttpGateway.d.ts +8 -0
- package/src/scheduler/ScheduleHttpGateway.d.ts.map +1 -0
- package/src/scheduler/ScheduleHttpGateway.js +196 -0
- package/src/scheduler/ScheduleRunner.d.ts +6 -0
- package/src/scheduler/ScheduleRunner.d.ts.map +1 -1
- package/src/scheduler/ScheduleRunner.js +166 -29
- package/src/scheduler/SchedulerRuntime.d.ts +15 -0
- package/src/scheduler/SchedulerRuntime.d.ts.map +1 -0
- package/src/scheduler/SchedulerRuntime.js +79 -0
- package/src/scheduler/cron/Cron.d.ts +19 -0
- package/src/scheduler/cron/Cron.d.ts.map +1 -0
- package/src/scheduler/cron/Cron.js +200 -0
- package/src/scheduler/leader/SchedulerLeader.d.ts +14 -0
- package/src/scheduler/leader/SchedulerLeader.d.ts.map +1 -0
- package/src/scheduler/leader/SchedulerLeader.js +187 -0
- package/src/scheduler/state/ScheduleStateStore.d.ts +27 -0
- package/src/scheduler/state/ScheduleStateStore.d.ts.map +1 -0
- package/src/scheduler/state/ScheduleStateStore.js +27 -0
- package/src/scheduler/types.d.ts +10 -0
- package/src/scheduler/types.d.ts.map +1 -1
- package/src/schedules/index.d.ts +1 -0
- package/src/schedules/index.d.ts.map +1 -1
- package/src/schedules/index.js +1 -0
- package/src/schedules/job-tracking-cleanup.d.ts +4 -0
- package/src/schedules/job-tracking-cleanup.d.ts.map +1 -0
- package/src/schedules/job-tracking-cleanup.js +116 -0
- package/src/schedules/log-cleanup.d.ts +1 -2
- package/src/schedules/log-cleanup.d.ts.map +1 -1
- package/src/schedules/log-cleanup.js +12 -15
- package/src/security/Sanitizer.d.ts.map +1 -1
- package/src/security/Sanitizer.js +1 -9
- package/src/security/SignedRequest.d.ts.map +1 -1
- package/src/security/SignedRequest.js +2 -2
- package/src/templates/docker/docker-compose.ecosystem.yml.tpl +301 -0
- package/src/templates/docker/docker-compose.schedules.yml.tpl +84 -0
- package/src/templates/project/basic/app/Schedules/index.ts.tpl +0 -0
- package/src/templates/project/basic/config/database.ts.tpl +1 -1
- package/src/toolkit/Secrets/Manifest.d.ts.map +1 -1
- package/src/toolkit/Secrets/Manifest.js +5 -7
- package/src/tools/mail/drivers/Smtp.d.ts.map +1 -1
- package/src/tools/mail/drivers/Smtp.js +7 -1
- package/src/tools/queue/JobReconciliationRunner.d.ts.map +1 -1
- package/src/tools/queue/JobReconciliationRunner.js +7 -39
- package/src/tools/queue/JobRecoveryDaemon.d.ts.map +1 -1
- package/src/tools/queue/JobRecoveryDaemon.js +116 -18
- package/src/tools/queue/JobStateTracker.d.ts +10 -1
- package/src/tools/queue/JobStateTracker.d.ts.map +1 -1
- package/src/tools/queue/JobStateTracker.js +24 -2
- package/src/tools/queue/JobStateTrackerDbPersistence.d.ts.map +1 -1
- package/src/tools/queue/JobStateTrackerDbPersistence.js +93 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.42",
|
|
4
4
|
"description": "Production-grade TypeScript backend framework for JavaScript",
|
|
5
5
|
"homepage": "https://zintrust.com",
|
|
6
6
|
"repository": {
|
|
@@ -22,6 +22,22 @@
|
|
|
22
22
|
"types": "./src/start.d.ts",
|
|
23
23
|
"import": "./src/start.js"
|
|
24
24
|
},
|
|
25
|
+
"./cli": {
|
|
26
|
+
"types": "./src/cli.d.ts",
|
|
27
|
+
"import": "./src/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"./proxy": {
|
|
30
|
+
"types": "./src/proxy.d.ts",
|
|
31
|
+
"import": "./src/proxy.js"
|
|
32
|
+
},
|
|
33
|
+
"./collections": {
|
|
34
|
+
"types": "./src/collections/index.d.ts",
|
|
35
|
+
"import": "./src/collections/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./helper": {
|
|
38
|
+
"types": "./src/helper/index.d.ts",
|
|
39
|
+
"import": "./src/helper/index.js"
|
|
40
|
+
},
|
|
25
41
|
"./node": {
|
|
26
42
|
"types": "./src/node.d.ts",
|
|
27
43
|
"import": "./src/node.js"
|
package/src/boot/bootstrap.js
CHANGED
|
@@ -37,29 +37,45 @@ const logBootstrapErrorDetails = (error) => {
|
|
|
37
37
|
// best-effort logging
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
-
const startSchedulesIfNeeded = async (
|
|
40
|
+
const startSchedulesIfNeeded = async (application) => {
|
|
41
41
|
try {
|
|
42
|
+
if (Env.getBool('SCHEDULES_ENABLED', false) === false)
|
|
43
|
+
return;
|
|
42
44
|
const runtime = appConfig.detectRuntime();
|
|
43
45
|
if (runtime !== 'nodejs' && runtime !== 'fargate')
|
|
44
46
|
return;
|
|
45
|
-
const {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const { SchedulerRuntime } = await import('../scheduler/SchedulerRuntime.js');
|
|
48
|
+
const coreSchedules = await import('../schedules/index.js');
|
|
49
|
+
let appSchedules = {};
|
|
50
|
+
try {
|
|
51
|
+
const appSchedulesModuleId = '@app/' + 'Schedules';
|
|
52
|
+
appSchedules = (await import(appSchedulesModuleId));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* v8 ignore next */
|
|
56
|
+
appSchedules = {};
|
|
52
57
|
}
|
|
53
|
-
|
|
58
|
+
const isSchedule = (value) => {
|
|
59
|
+
if (value === null || value === undefined || typeof value !== 'object')
|
|
60
|
+
return false;
|
|
61
|
+
return ('name' in value &&
|
|
62
|
+
typeof value.name === 'string' &&
|
|
63
|
+
value.name.trim().length > 0);
|
|
64
|
+
};
|
|
65
|
+
const coreScheduleEntries = Object.values(coreSchedules).filter(isSchedule);
|
|
66
|
+
const appScheduleEntries = Object.values(appSchedules).filter(isSchedule);
|
|
67
|
+
SchedulerRuntime.registerMany(coreScheduleEntries, 'core');
|
|
68
|
+
SchedulerRuntime.registerMany(appScheduleEntries, 'app');
|
|
69
|
+
SchedulerRuntime.start();
|
|
54
70
|
// Add shutdown hook to stop schedules gracefully
|
|
55
|
-
const shutdownManager =
|
|
71
|
+
const shutdownManager = application.getContainer().get('shutdownManager');
|
|
56
72
|
if ((typeof shutdownManager === 'object' || typeof shutdownManager === 'function') &&
|
|
57
73
|
shutdownManager !== null &&
|
|
58
74
|
'add' in shutdownManager &&
|
|
59
75
|
typeof shutdownManager.add === 'function') {
|
|
60
76
|
shutdownManager.add(async () => {
|
|
61
77
|
const scheduleTimeoutMs = Env.getInt('SCHEDULE_SHUTDOWN_TIMEOUT_MS', 30000);
|
|
62
|
-
await
|
|
78
|
+
await SchedulerRuntime.stop(scheduleTimeoutMs);
|
|
63
79
|
});
|
|
64
80
|
}
|
|
65
81
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/runtime.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAOvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AA+I9C,eAAO,MAAM,8BAA8B,GAAI,iBAAiB,gBAAgB,KAAG,IA4BlF,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/runtime.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAOvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AA+I9C,eAAO,MAAM,8BAA8B,GAAI,iBAAiB,gBAAgB,KAAG,IA4BlF,CAAC;AAyLF,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;CAuE7D,CAAC"}
|
|
@@ -293,6 +293,16 @@ const initializeQueueHttpGateway = async (router) => {
|
|
|
293
293
|
Logger.warn('Failed to register Queue HTTP gateway routes', error);
|
|
294
294
|
}
|
|
295
295
|
};
|
|
296
|
+
const initializeScheduleHttpGateway = async (router) => {
|
|
297
|
+
try {
|
|
298
|
+
const { ScheduleHttpGateway } = await import('../../scheduler/ScheduleHttpGateway.js');
|
|
299
|
+
ScheduleHttpGateway.create().registerRoutes(router);
|
|
300
|
+
Logger.info('Schedule HTTP gateway route registered at /api/_sys/schedule/rpc');
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
Logger.warn('Failed to register Schedule HTTP gateway routes', error);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
296
306
|
export const createLifecycle = (params) => {
|
|
297
307
|
const boot = async () => {
|
|
298
308
|
if (params.getBooted())
|
|
@@ -324,6 +334,7 @@ export const createLifecycle = (params) => {
|
|
|
324
334
|
await initializeWorkers(params.router);
|
|
325
335
|
await initializeQueueMonitor(params.router);
|
|
326
336
|
await initializeQueueHttpGateway(params.router);
|
|
337
|
+
await initializeScheduleHttpGateway(params.router);
|
|
327
338
|
}
|
|
328
339
|
// Register service providers
|
|
329
340
|
// Bootstrap services
|
package/src/cli/CLI.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,IAAI,OAAO,CAAC;CACvB;AAuPD;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;cACJ,IAAI;EAed,CAAC"}
|
package/src/cli/CLI.js
CHANGED
|
@@ -8,6 +8,7 @@ import { ConfigCommand } from './commands/ConfigCommand.js';
|
|
|
8
8
|
import { ContainerProxiesCommand } from './commands/ContainerProxiesCommand.js';
|
|
9
9
|
import { ContainerWorkersCommand } from './commands/ContainerWorkersCommand.js';
|
|
10
10
|
import { AddMigrationCommand, CreateCommand, CreateMigrationCommand, } from './commands/CreateCommand.js';
|
|
11
|
+
import { D1LearnCommand } from './commands/D1LearnCommand.js';
|
|
11
12
|
import { D1MigrateCommand } from './commands/D1MigrateCommand.js';
|
|
12
13
|
import { DbSeedCommand } from './commands/DbSeedCommand.js';
|
|
13
14
|
import { DebugCommand } from './commands/DebugCommand.js';
|
|
@@ -17,6 +18,7 @@ import { DeployContainerWorkersCommand } from './commands/DeployContainerWorkers
|
|
|
17
18
|
import { DoctorArchitectureCommand } from './commands/DoctorArchitectureCommand.js';
|
|
18
19
|
import { FixCommand } from './commands/FixCommand.js';
|
|
19
20
|
import { InitContainerCommand } from './commands/InitContainerCommand.js';
|
|
21
|
+
import { InitEcosystemCommand } from './commands/InitEcosystemCommand.js';
|
|
20
22
|
import { InitProducerCommand } from './commands/InitProducerCommand.js';
|
|
21
23
|
import { InitProxyCommand } from './commands/InitProxyCommand.js';
|
|
22
24
|
import { JwtDevCommand } from './commands/JwtDevCommand.js';
|
|
@@ -34,12 +36,16 @@ import { PostgresProxyCommand } from './commands/PostgresProxyCommand.js';
|
|
|
34
36
|
import { PrepareCommand } from './commands/PrepareCommand.js';
|
|
35
37
|
import { ProxyCommand } from './commands/ProxyCommand.js';
|
|
36
38
|
import { PublishCommand } from './commands/PublishCommand.js';
|
|
39
|
+
import { PutCommand } from './commands/PutCommand.js';
|
|
37
40
|
import { QACommand } from './commands/QACommand.js';
|
|
38
41
|
import { QueueCommand } from './commands/QueueCommand.js';
|
|
39
42
|
import { QueueRecoveryCommand } from './commands/QueueRecoveryCommand.js';
|
|
40
43
|
import { RedisProxyCommand } from './commands/RedisProxyCommand.js';
|
|
41
44
|
import { ResourceControlCommand } from './commands/ResourceControlCommand.js';
|
|
42
45
|
import { RoutesCommand } from './commands/RoutesCommand.js';
|
|
46
|
+
import { ScheduleListCommand } from './commands/ScheduleListCommand.js';
|
|
47
|
+
import { ScheduleRunCommand } from './commands/ScheduleRunCommand.js';
|
|
48
|
+
import { ScheduleStartCommand } from './commands/ScheduleStartCommand.js';
|
|
43
49
|
import { SecretsCommand } from './commands/SecretsCommand.js';
|
|
44
50
|
import { SimulateCommand } from './commands/SimulateCommand.js';
|
|
45
51
|
import { SmtpProxyCommand } from './commands/SmtpProxyCommand.js';
|
|
@@ -71,6 +77,7 @@ const buildCommandRegistry = () => {
|
|
|
71
77
|
InitContainerCommand.create(),
|
|
72
78
|
InitProxyCommand.create(),
|
|
73
79
|
InitProducerCommand.create(),
|
|
80
|
+
InitEcosystemCommand.create(),
|
|
74
81
|
DoctorArchitectureCommand.create(),
|
|
75
82
|
AddCommand.create(),
|
|
76
83
|
CreateCommand.create(),
|
|
@@ -79,12 +86,16 @@ const buildCommandRegistry = () => {
|
|
|
79
86
|
StartCommand.create(),
|
|
80
87
|
QueueCommand.create(),
|
|
81
88
|
QueueRecoveryCommand.create(),
|
|
89
|
+
ScheduleListCommand.create(),
|
|
90
|
+
ScheduleRunCommand.create(),
|
|
91
|
+
ScheduleStartCommand.create(),
|
|
82
92
|
BroadcastWorkCommand.create(),
|
|
83
93
|
NotificationWorkCommand.create(),
|
|
84
94
|
ResourceControlCommand,
|
|
85
95
|
MigrateWorkerCommand.create(),
|
|
86
96
|
MigrateCommand.create(),
|
|
87
97
|
DbSeedCommand.create(),
|
|
98
|
+
D1LearnCommand.create(),
|
|
88
99
|
D1MigrateCommand.create(),
|
|
89
100
|
DebugCommand.create(),
|
|
90
101
|
SecretsCommand.create(),
|
|
@@ -93,6 +104,7 @@ const buildCommandRegistry = () => {
|
|
|
93
104
|
ContainerProxiesCommand.create(),
|
|
94
105
|
PluginCommand.create(),
|
|
95
106
|
PublishCommand.create(),
|
|
107
|
+
PutCommand.create(),
|
|
96
108
|
DeployCommand.create(),
|
|
97
109
|
DeployContainerWorkersCommand.create(),
|
|
98
110
|
DeployContainerProxiesCommand.create(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ConfigCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfigCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ConfigCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAiVrE;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB;;OAEG;cACO,YAAY;EAsEtB,CAAC"}
|
|
@@ -8,6 +8,7 @@ import { ConfigValidator } from '../config/ConfigValidator.js';
|
|
|
8
8
|
import { ErrorHandler } from '../ErrorHandler.js';
|
|
9
9
|
import { PromptHelper } from '../PromptHelper.js';
|
|
10
10
|
import { Logger } from '../../config/logger.js';
|
|
11
|
+
import { isArray, isObject } from '../../helper/index.js';
|
|
11
12
|
import chalk from 'chalk';
|
|
12
13
|
const addOptions = (command) => {
|
|
13
14
|
command.argument('[action]', 'Action: get, set, list, reset, edit, export');
|
|
@@ -225,9 +226,8 @@ const handleEdit = async (cmd, manager) => {
|
|
|
225
226
|
const handleExport = (cmd, manager) => {
|
|
226
227
|
cmd.info(typeof manager.export === 'function' ? manager.export() : '{}');
|
|
227
228
|
};
|
|
228
|
-
const isUnknownArray = (value) => Array.isArray(value);
|
|
229
229
|
const getArg = (args, index) => {
|
|
230
|
-
if (!
|
|
230
|
+
if (!isArray(args))
|
|
231
231
|
return undefined;
|
|
232
232
|
const value = args[index];
|
|
233
233
|
return typeof value === 'string' ? value : undefined;
|
|
@@ -236,9 +236,7 @@ const executeConfig = async (cmd, options) => {
|
|
|
236
236
|
const typedCmd = cmd;
|
|
237
237
|
const command = cmd.getCommand();
|
|
238
238
|
const toRecord = (value) => {
|
|
239
|
-
|
|
240
|
-
return {};
|
|
241
|
-
return value;
|
|
239
|
+
return isObject(value) ? value : {};
|
|
242
240
|
};
|
|
243
241
|
const commandOpts = typeof command.opts === 'function' ? toRecord(command.opts()) : {};
|
|
244
242
|
const mergedOptions = {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D1 Learn Command
|
|
3
|
+
* Runs a command in "learning mode" to capture D1 SQL statements for the registry.
|
|
4
|
+
*/
|
|
5
|
+
import { type IBaseCommand } from '../BaseCommand';
|
|
6
|
+
export declare const D1LearnCommand: Readonly<{
|
|
7
|
+
create(): IBaseCommand;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=D1LearnCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"D1LearnCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/D1LearnCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgGvF,eAAO,MAAM,cAAc;cACf,YAAY;EAiEtB,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D1 Learn Command
|
|
3
|
+
* Runs a command in "learning mode" to capture D1 SQL statements for the registry.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
6
|
+
import { Logger } from '../../config/logger.js';
|
|
7
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
8
|
+
import { isNonEmptyString, isObject } from '../../helper/index.js';
|
|
9
|
+
import * as fs from '../../node-singletons/fs.js';
|
|
10
|
+
import { StatementRegistryBuild } from '../../orm/SchemaStatemenWriter.js';
|
|
11
|
+
import { spawn } from 'node:child_process';
|
|
12
|
+
const LEARN_FILE = 'storage/d1-learned.jsonl';
|
|
13
|
+
const isRecord = (value) => isObject(value);
|
|
14
|
+
const coerceStringRegistry = (value) => {
|
|
15
|
+
if (!isRecord(value))
|
|
16
|
+
return {};
|
|
17
|
+
const out = {};
|
|
18
|
+
for (const [k, v] of Object.entries(value)) {
|
|
19
|
+
if (isNonEmptyString(v))
|
|
20
|
+
out[k] = v;
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
};
|
|
24
|
+
const readExistingRegistryFile = async (outputFile) => {
|
|
25
|
+
try {
|
|
26
|
+
await fs.stat(outputFile);
|
|
27
|
+
const existingContent = await fs.readFile(outputFile, 'utf-8');
|
|
28
|
+
const existingJson = JSON.parse(existingContent);
|
|
29
|
+
if (isRecord(existingJson) && 'queries' in existingJson) {
|
|
30
|
+
return coerceStringRegistry(existingJson['queries']);
|
|
31
|
+
}
|
|
32
|
+
return coerceStringRegistry(existingJson);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const cleanLearnFile = async () => {
|
|
39
|
+
try {
|
|
40
|
+
await fs.rm(LEARN_FILE, { force: true });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// ignore
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const parseLearnedFile = async () => {
|
|
47
|
+
try {
|
|
48
|
+
const content = await fs.readFile(LEARN_FILE, 'utf-8');
|
|
49
|
+
return StatementRegistryBuild.fromJsonl(content);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if (err.code === 'ENOENT') {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const runLearner = async (cmd, args) => {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
Logger.info(`Starting learner: ${cmd} ${args.join(' ')}`);
|
|
61
|
+
Logger.info(`Capturing queries to ${LEARN_FILE}...`);
|
|
62
|
+
const child = spawn(cmd, args, {
|
|
63
|
+
stdio: 'inherit',
|
|
64
|
+
env: {
|
|
65
|
+
...process.env,
|
|
66
|
+
ZT_D1_LEARN_FILE: LEARN_FILE,
|
|
67
|
+
D1_REMOTE_MODE: 'sql',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
child.on('close', (code) => {
|
|
71
|
+
// Allow code 0 or 1 (tests fail sometimes but still run queries)
|
|
72
|
+
// Actually, we resolve regardless so we can harvest what ran
|
|
73
|
+
if (code === 0) {
|
|
74
|
+
resolve();
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// We log error but resolve to process partial results
|
|
78
|
+
Logger.error(`Command exited with code ${code}`);
|
|
79
|
+
resolve();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
child.on('error', (err) => {
|
|
83
|
+
reject(err);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
export const D1LearnCommand = Object.freeze({
|
|
88
|
+
create() {
|
|
89
|
+
const cmd = BaseCommand.create({
|
|
90
|
+
name: 'd1:learn',
|
|
91
|
+
description: 'Run a command to learn D1 queries and generate a statement registry',
|
|
92
|
+
addOptions: (c) => {
|
|
93
|
+
c.argument('<command>', 'The command to run (e.g. "npm test")')
|
|
94
|
+
.option('-o, --output <file>', 'Output JSON file (default: d1-statements.json)')
|
|
95
|
+
.option('-a, --append', 'Append to existing output file instead of overwriting');
|
|
96
|
+
},
|
|
97
|
+
async execute(options) {
|
|
98
|
+
const learnOptions = options;
|
|
99
|
+
// In BaseCommand, positional arguments are stored in options.args array
|
|
100
|
+
// We defined .argument('<command>') so it's the first element.
|
|
101
|
+
const commandStr = options.args && options.args.length > 0 ? options.args[0] : '';
|
|
102
|
+
if (commandStr === '') {
|
|
103
|
+
Logger.error('Missing command argument');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const outputFile = learnOptions.output ?? 'd1-statements.json';
|
|
107
|
+
const append = learnOptions.append === true;
|
|
108
|
+
// 1. Prepare
|
|
109
|
+
await cleanLearnFile();
|
|
110
|
+
const parts = commandStr.split(' ');
|
|
111
|
+
const cmdExe = parts[0];
|
|
112
|
+
const args = parts.slice(1);
|
|
113
|
+
// 2. Run command
|
|
114
|
+
try {
|
|
115
|
+
await runLearner(cmdExe, args);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
throw ErrorFactory.createCliError(`Learner failed to start: ${err.message}`);
|
|
119
|
+
}
|
|
120
|
+
// 3. Process results
|
|
121
|
+
const learned = await parseLearnedFile();
|
|
122
|
+
const count = Object.keys(learned).length;
|
|
123
|
+
if (count === 0) {
|
|
124
|
+
Logger.warn('No D1 queries were captured.');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
Logger.info(`Captured ${count} unique queries.`);
|
|
128
|
+
// 4. Merge with existing if needed
|
|
129
|
+
let finalMap = learned;
|
|
130
|
+
if (append) {
|
|
131
|
+
const existingMap = await readExistingRegistryFile(outputFile);
|
|
132
|
+
finalMap = StatementRegistryBuild.merge(existingMap, learned);
|
|
133
|
+
}
|
|
134
|
+
// 5. Output
|
|
135
|
+
// One-line JSON is easiest to paste into `wrangler secret put ZT_D1_STATEMENTS_JSON`.
|
|
136
|
+
const outputContent = StatementRegistryBuild.toStatementsJson(finalMap);
|
|
137
|
+
await fs.writeFile(outputFile, outputContent);
|
|
138
|
+
Logger.info(`Registry written to ${outputFile}`);
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
return cmd;
|
|
142
|
+
},
|
|
143
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/D1MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"D1MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/D1MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8GrE;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;OAEG;cACO,YAAY;EAyBtB,CAAC"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { BaseCommand } from '../BaseCommand.js';
|
|
2
|
+
import { D1SqlMigrations } from '../d1/D1SqlMigrations.js';
|
|
3
|
+
import { WranglerConfig } from '../d1/WranglerConfig.js';
|
|
2
4
|
import { WranglerD1 } from '../d1/WranglerD1.js';
|
|
3
5
|
import { resolveNpmPath } from '../../common/index.js';
|
|
4
6
|
import { appConfig } from '../../config/app.js';
|
|
7
|
+
import { databaseConfig } from '../../config/database.js';
|
|
5
8
|
import { Logger } from '../../config/logger.js';
|
|
6
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
|
+
import * as path from '../../node-singletons/path.js';
|
|
7
11
|
const RESOLVED_VOID = Promise.resolve();
|
|
8
12
|
const runWrangler = async (cmd, args) => {
|
|
9
13
|
// Back-compat entrypoint for tests; we only use this for D1 migrations apply.
|
|
@@ -13,30 +17,64 @@ const runWrangler = async (cmd, args) => {
|
|
|
13
17
|
await RESOLVED_VOID;
|
|
14
18
|
return WranglerD1.applyMigrations({ cmd, dbName, isLocal });
|
|
15
19
|
};
|
|
16
|
-
const
|
|
20
|
+
const getDbName = (options) => {
|
|
21
|
+
const value = options['database'];
|
|
22
|
+
return typeof value === 'string' && value.trim() !== '' ? value : 'zintrust_db';
|
|
23
|
+
};
|
|
24
|
+
const buildExecutionContext = (options) => {
|
|
25
|
+
const isWorkerCommand = process.argv.includes('d1:migrate:worker');
|
|
17
26
|
const isLocal = options['local'] === true || options['remote'] !== true;
|
|
18
|
-
const dbName =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
const dbName = getDbName(options);
|
|
28
|
+
const projectRoot = process.cwd();
|
|
29
|
+
const migrationsRelDir = isWorkerCommand
|
|
30
|
+
? path.join('database', 'migrations', 'd1')
|
|
31
|
+
: WranglerConfig.getD1MigrationsDir(projectRoot, dbName);
|
|
32
|
+
const sourceMigrationsDir = isWorkerCommand
|
|
33
|
+
? path.join('packages', 'workers', 'migrations')
|
|
34
|
+
: databaseConfig.migrations.directory;
|
|
35
|
+
return {
|
|
36
|
+
isLocal,
|
|
37
|
+
dbName,
|
|
38
|
+
projectRoot,
|
|
39
|
+
migrationsRelDir,
|
|
40
|
+
sourceMigrationsDir,
|
|
41
|
+
outputDir: path.join(projectRoot, migrationsRelDir),
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const handleMigrationError = (cmd, error) => {
|
|
45
|
+
Logger.error('D1 Migration failed', error);
|
|
46
|
+
ErrorFactory.createCliError('D1 Migration failed', error);
|
|
47
|
+
const err = error;
|
|
48
|
+
if (err.stdout !== undefined && err.stdout.length > 0)
|
|
49
|
+
cmd.info(err.stdout.toString());
|
|
50
|
+
if (err.stderr !== undefined && err.stderr.length > 0) {
|
|
51
|
+
const stderr = err.stderr.toString();
|
|
52
|
+
Logger.error('Wrangler stderr', stderr);
|
|
53
|
+
ErrorFactory.createCliError('Wrangler stderr', stderr);
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
};
|
|
57
|
+
const executeD1Migrate = async (cmd, options) => {
|
|
58
|
+
const ctx = buildExecutionContext(options);
|
|
59
|
+
cmd.info(`Running D1 migrations for ${ctx.dbName} (${ctx.isLocal ? 'local' : 'remote'})...`);
|
|
60
|
+
cmd.info(`Generating D1 SQL migrations into ${ctx.migrationsRelDir}...`);
|
|
22
61
|
await RESOLVED_VOID;
|
|
23
62
|
try {
|
|
24
|
-
const
|
|
63
|
+
const generated = await D1SqlMigrations.compileAndWrite({
|
|
64
|
+
projectRoot: ctx.projectRoot,
|
|
65
|
+
globalDir: ctx.sourceMigrationsDir,
|
|
66
|
+
extension: databaseConfig.migrations.extension,
|
|
67
|
+
includeGlobal: true,
|
|
68
|
+
outputDir: ctx.outputDir,
|
|
69
|
+
});
|
|
70
|
+
cmd.info(`Generated ${generated.length} SQL migration file(s).`);
|
|
71
|
+
const output = WranglerD1.applyMigrations({ cmd, dbName: ctx.dbName, isLocal: ctx.isLocal });
|
|
25
72
|
if (output !== '')
|
|
26
73
|
cmd.info(output);
|
|
27
74
|
cmd.info('✓ D1 migrations completed successfully');
|
|
28
75
|
}
|
|
29
76
|
catch (error) {
|
|
30
|
-
|
|
31
|
-
ErrorFactory.createCliError('D1 Migration failed', error);
|
|
32
|
-
const err = error;
|
|
33
|
-
if (err.stdout !== undefined && err.stdout.length > 0)
|
|
34
|
-
cmd.info(err.stdout.toString());
|
|
35
|
-
if (err.stderr !== undefined && err.stderr.length > 0)
|
|
36
|
-
Logger.error('Wrangler stderr', err.stderr.toString());
|
|
37
|
-
if (err.stderr !== undefined && err.stderr.length > 0)
|
|
38
|
-
ErrorFactory.createCliError('Wrangler stderr', err.stderr.toString());
|
|
39
|
-
throw error;
|
|
77
|
+
handleMigrationError(cmd, error);
|
|
40
78
|
}
|
|
41
79
|
};
|
|
42
80
|
/**
|
|
@@ -60,6 +98,7 @@ export const D1MigrateCommand = Object.freeze({
|
|
|
60
98
|
const cmd = BaseCommand.create({
|
|
61
99
|
name: 'd1:migrate',
|
|
62
100
|
description: 'Run Cloudflare D1 migrations',
|
|
101
|
+
aliases: ['d1:migrate:worker'],
|
|
63
102
|
addOptions,
|
|
64
103
|
execute: async (options) => executeD1Migrate(cmd, options),
|
|
65
104
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitContainerCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/InitContainerCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"InitContainerCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/InitContainerCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAmOlE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAkBtB,CAAC"}
|
|
@@ -76,6 +76,22 @@ services:
|
|
|
76
76
|
- DB_DATABASE_MYSQL=\${DB_DATABASE_MYSQL:-zintrust}
|
|
77
77
|
- DB_USERNAME_MYSQL=\${DB_USERNAME_MYSQL:-zintrust}
|
|
78
78
|
- DB_PASSWORD_MYSQL=\${DB_PASSWORD_MYSQL:-secret}
|
|
79
|
+
|
|
80
|
+
# Cloudflare D1
|
|
81
|
+
- D1_DATABASE_ID=\${D1_DATABASE_ID}
|
|
82
|
+
- D1_ACCOUNT_ID=\${D1_ACCOUNT_ID}
|
|
83
|
+
- D1_API_TOKEN=\${D1_API_TOKEN}
|
|
84
|
+
- D1_REMOTE_URL=\${D1_REMOTE_URL}
|
|
85
|
+
- D1_REMOTE_KEY_ID=\${D1_REMOTE_KEY_ID}
|
|
86
|
+
- D1_REMOTE_SECRET=\${D1_REMOTE_SECRET}
|
|
87
|
+
|
|
88
|
+
# Cloudflare KV
|
|
89
|
+
- KV_NAMESPACE_ID=\${KV_NAMESPACE_ID}
|
|
90
|
+
- KV_ACCOUNT_ID=\${KV_ACCOUNT_ID}
|
|
91
|
+
- KV_API_TOKEN=\${KV_API_TOKEN}
|
|
92
|
+
- KV_REMOTE_URL=\${KV_REMOTE_URL}
|
|
93
|
+
- KV_REMOTE_KEY_ID=\${KV_REMOTE_KEY_ID}
|
|
94
|
+
- KV_REMOTE_SECRET=\${KV_REMOTE_SECRET}
|
|
79
95
|
ports:
|
|
80
96
|
- '7772:7772'
|
|
81
97
|
|
|
@@ -101,7 +117,7 @@ RUN apk add --no-cache python3 make g++
|
|
|
101
117
|
COPY package.json package-lock.json ./
|
|
102
118
|
|
|
103
119
|
# Install dependencies (including dev dependencies needed for build)
|
|
104
|
-
RUN --mount=type=cache,target=/root/.npm \
|
|
120
|
+
RUN --mount=type=cache,target=/root/.npm,id=zintrust-npm-cache,sharing=locked \
|
|
105
121
|
npm config set fetch-retries 5 \
|
|
106
122
|
&& npm config set fetch-retry-mintimeout 20000 \
|
|
107
123
|
&& npm config set fetch-retry-maxtimeout 120000 \
|
|
@@ -112,7 +128,7 @@ COPY . .
|
|
|
112
128
|
|
|
113
129
|
# Build TypeScript to JavaScript
|
|
114
130
|
ARG BUILD_VARIANT=full
|
|
115
|
-
RUN --mount=type=cache,target=/root/.npm npm run build:dk
|
|
131
|
+
RUN --mount=type=cache,target=/root/.npm,id=zintrust-npm-cache,sharing=locked npm run build:dk
|
|
116
132
|
|
|
117
133
|
# Runtime Stage - Production image
|
|
118
134
|
FROM node:20-alpine AS runtime
|
|
@@ -131,11 +147,10 @@ RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
|
|
131
147
|
COPY package.json package-lock.json ./
|
|
132
148
|
|
|
133
149
|
# Install only production dependencies (requires build tools for native modules)
|
|
134
|
-
RUN --mount=type=cache,target=/root/.npm \
|
|
150
|
+
RUN --mount=type=cache,target=/root/.npm,id=zintrust-npm-cache,sharing=locked \
|
|
135
151
|
apk add --no-cache --virtual .build-deps python3 make g++ \
|
|
136
152
|
&& npm ci --omit=dev \
|
|
137
|
-
&& apk del .build-deps
|
|
138
|
-
&& npm cache clean --force
|
|
153
|
+
&& apk del .build-deps
|
|
139
154
|
|
|
140
155
|
# Copy compiled code from builder stage
|
|
141
156
|
COPY --from=builder /app/dist ./dist
|
|
@@ -157,7 +172,7 @@ EXPOSE 7772
|
|
|
157
172
|
# Start application (compiled JS; no tsx needed in runtime)
|
|
158
173
|
CMD ["node", "dist/src/boot/bootstrap.js"]
|
|
159
174
|
`;
|
|
160
|
-
const backupSuffix = () => new Date().toISOString().
|
|
175
|
+
const backupSuffix = () => new Date().toISOString().replaceAll(/[:.]/g, '-');
|
|
161
176
|
const backupFileIfExists = (filePath) => {
|
|
162
177
|
if (!existsSync(filePath))
|
|
163
178
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InitEcosystemCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/InitEcosystemCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAoDlE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAOtB,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
2
|
+
import { PromptHelper } from '../PromptHelper.js';
|
|
3
|
+
import { Logger } from '../../config/logger.js';
|
|
4
|
+
import { copyFileSync, existsSync, readFileSync, writeFileSync } from '../../node-singletons/fs.js';
|
|
5
|
+
import { join } from '../../node-singletons/path.js';
|
|
6
|
+
import { fileURLToPath } from '../../node-singletons/url.js';
|
|
7
|
+
const backupSuffix = () => new Date().toISOString().replaceAll(/[:.]/g, '-');
|
|
8
|
+
const backupFileIfExists = (filePath) => {
|
|
9
|
+
if (!existsSync(filePath))
|
|
10
|
+
return;
|
|
11
|
+
const backupPath = `${filePath}.bak.${backupSuffix()}`;
|
|
12
|
+
copyFileSync(filePath, backupPath);
|
|
13
|
+
Logger.info(`🗂️ Backup created: ${backupPath}`);
|
|
14
|
+
};
|
|
15
|
+
const readTemplate = (relPathFromThisModule) => {
|
|
16
|
+
const absPath = fileURLToPath(new URL(relPathFromThisModule, import.meta.url));
|
|
17
|
+
return readFileSync(absPath, 'utf-8');
|
|
18
|
+
};
|
|
19
|
+
const TEMPLATE_ECOSYSTEM = readTemplate('../../templates/docker/docker-compose.ecosystem.yml.tpl');
|
|
20
|
+
const TEMPLATE_SCHEDULES = readTemplate('../../templates/docker/docker-compose.schedules.yml.tpl');
|
|
21
|
+
const writeScaffoldFile = async (cwd, fileName, content) => {
|
|
22
|
+
const outPath = join(cwd, fileName);
|
|
23
|
+
let shouldWrite = true;
|
|
24
|
+
if (existsSync(outPath)) {
|
|
25
|
+
shouldWrite = await PromptHelper.confirm(`${fileName} already exists. Overwrite?`, false);
|
|
26
|
+
}
|
|
27
|
+
if (!shouldWrite) {
|
|
28
|
+
Logger.info(`Skipped ${fileName}`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
backupFileIfExists(outPath);
|
|
32
|
+
writeFileSync(outPath, content);
|
|
33
|
+
Logger.info(`✅ Created ${fileName}`);
|
|
34
|
+
};
|
|
35
|
+
const execute = async () => {
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
await writeScaffoldFile(cwd, 'docker-compose.ecosystem.yml', TEMPLATE_ECOSYSTEM);
|
|
38
|
+
await writeScaffoldFile(cwd, 'docker-compose.schedules.yml', TEMPLATE_SCHEDULES);
|
|
39
|
+
Logger.info('✅ Ecosystem scaffolding complete.');
|
|
40
|
+
Logger.info('Next: docker compose -f docker-compose.ecosystem.yml up -d');
|
|
41
|
+
};
|
|
42
|
+
export const InitEcosystemCommand = Object.freeze({
|
|
43
|
+
create() {
|
|
44
|
+
return BaseCommand.create({
|
|
45
|
+
name: 'init:ecosystem',
|
|
46
|
+
description: 'Scaffold docker-compose.ecosystem.yml and docker-compose.schedules.yml',
|
|
47
|
+
execute,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
export default InitEcosystemCommand;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,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;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA0erE;;GAEG;AACH,eAAO,MAAM,cAAc;IACzB;;OAEG;cACO,YAAY;EAUtB,CAAC"}
|