@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.
Files changed (193) hide show
  1. package/package.json +17 -1
  2. package/src/boot/bootstrap.js +27 -11
  3. package/src/boot/registry/runtime.d.ts.map +1 -1
  4. package/src/boot/registry/runtime.js +11 -0
  5. package/src/cli/CLI.d.ts.map +1 -1
  6. package/src/cli/CLI.js +12 -0
  7. package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
  8. package/src/cli/commands/ConfigCommand.js +3 -5
  9. package/src/cli/commands/D1LearnCommand.d.ts +9 -0
  10. package/src/cli/commands/D1LearnCommand.d.ts.map +1 -0
  11. package/src/cli/commands/D1LearnCommand.js +143 -0
  12. package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
  13. package/src/cli/commands/D1MigrateCommand.js +55 -16
  14. package/src/cli/commands/InitContainerCommand.d.ts.map +1 -1
  15. package/src/cli/commands/InitContainerCommand.js +21 -6
  16. package/src/cli/commands/InitEcosystemCommand.d.ts +6 -0
  17. package/src/cli/commands/InitEcosystemCommand.d.ts.map +1 -0
  18. package/src/cli/commands/InitEcosystemCommand.js +51 -0
  19. package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
  20. package/src/cli/commands/MigrateCommand.js +78 -36
  21. package/src/cli/commands/MigrateWorkerCommand.d.ts.map +1 -1
  22. package/src/cli/commands/MigrateWorkerCommand.js +36 -2
  23. package/src/cli/commands/PutCommand.d.ts +6 -0
  24. package/src/cli/commands/PutCommand.d.ts.map +1 -0
  25. package/src/cli/commands/PutCommand.js +173 -0
  26. package/src/cli/commands/QueueRecoveryCommand.d.ts.map +1 -1
  27. package/src/cli/commands/QueueRecoveryCommand.js +113 -14
  28. package/src/cli/commands/ScheduleListCommand.d.ts +6 -0
  29. package/src/cli/commands/ScheduleListCommand.d.ts.map +1 -0
  30. package/src/cli/commands/ScheduleListCommand.js +62 -0
  31. package/src/cli/commands/ScheduleRunCommand.d.ts +6 -0
  32. package/src/cli/commands/ScheduleRunCommand.d.ts.map +1 -0
  33. package/src/cli/commands/ScheduleRunCommand.js +32 -0
  34. package/src/cli/commands/ScheduleStartCommand.d.ts +6 -0
  35. package/src/cli/commands/ScheduleStartCommand.d.ts.map +1 -0
  36. package/src/cli/commands/ScheduleStartCommand.js +40 -0
  37. package/src/cli/commands/SecretsCommand.d.ts.map +1 -1
  38. package/src/cli/commands/SecretsCommand.js +2 -2
  39. package/src/cli/commands/schedule/ScheduleCliSupport.d.ts +6 -0
  40. package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -0
  41. package/src/cli/commands/schedule/ScheduleCliSupport.js +55 -0
  42. package/src/cli/config/ConfigManager.d.ts.map +1 -1
  43. package/src/cli/config/ConfigManager.js +8 -1
  44. package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
  45. package/src/cli/d1/D1SqlMigrations.js +11 -1
  46. package/src/cli/d1/WranglerConfig.d.ts.map +1 -1
  47. package/src/cli/d1/WranglerConfig.js +34 -2
  48. package/src/cli/services/VersionChecker.d.ts.map +1 -1
  49. package/src/cli/services/VersionChecker.js +5 -1
  50. package/src/cli/utils/DatabaseCliUtils.d.ts.map +1 -1
  51. package/src/cli/utils/DatabaseCliUtils.js +6 -1
  52. package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
  53. package/src/cli/utils/EnvFileLoader.js +33 -14
  54. package/src/cli.d.ts +5 -0
  55. package/src/cli.d.ts.map +1 -0
  56. package/src/cli.js +4 -0
  57. package/src/collections/index.d.ts +2 -2
  58. package/src/collections/index.d.ts.map +1 -1
  59. package/src/collections/index.js +1 -1
  60. package/src/common/RemoteSignedJson.d.ts.map +1 -1
  61. package/src/common/RemoteSignedJson.js +49 -23
  62. package/src/common/utility.d.ts.map +1 -1
  63. package/src/common/utility.js +2 -6
  64. package/src/config/cloudflare.d.ts.map +1 -1
  65. package/src/config/cloudflare.js +19 -8
  66. package/src/config/env.js +2 -2
  67. package/src/helper/index.d.ts +225 -0
  68. package/src/helper/index.d.ts.map +1 -0
  69. package/src/helper/index.js +347 -0
  70. package/src/index.d.ts +3 -6
  71. package/src/index.d.ts.map +1 -1
  72. package/src/index.js +7 -9
  73. package/src/migrations/MigrationDiscovery.d.ts.map +1 -1
  74. package/src/migrations/MigrationDiscovery.js +2 -1
  75. package/src/orm/DatabaseAdapter.d.ts +1 -0
  76. package/src/orm/DatabaseAdapter.d.ts.map +1 -1
  77. package/src/orm/SchemaStatemenWriter.d.ts +15 -0
  78. package/src/orm/SchemaStatemenWriter.d.ts.map +1 -0
  79. package/src/orm/SchemaStatemenWriter.js +78 -0
  80. package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
  81. package/src/orm/adapters/D1Adapter.js +52 -2
  82. package/src/orm/adapters/D1RemoteAdapter.d.ts.map +1 -1
  83. package/src/orm/adapters/D1RemoteAdapter.js +137 -89
  84. package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
  85. package/src/orm/adapters/MySQLProxyAdapter.js +100 -81
  86. package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts.map +1 -1
  87. package/src/orm/adapters/PostgreSQLProxyAdapter.js +26 -10
  88. package/src/orm/adapters/SqlProxyAdapterUtils.d.ts.map +1 -1
  89. package/src/orm/adapters/SqlProxyAdapterUtils.js +2 -1
  90. package/src/orm/adapters/SqlProxyRegistryMode.d.ts +12 -0
  91. package/src/orm/adapters/SqlProxyRegistryMode.d.ts.map +1 -0
  92. package/src/orm/adapters/SqlProxyRegistryMode.js +24 -0
  93. package/src/orm/adapters/SqlServerProxyAdapter.d.ts +3 -0
  94. package/src/orm/adapters/SqlServerProxyAdapter.d.ts.map +1 -1
  95. package/src/orm/adapters/SqlServerProxyAdapter.js +125 -117
  96. package/src/orm/migrations/MigrationStore.js +1 -1
  97. package/src/proxy/ProxyRequestParsing.d.ts +9 -0
  98. package/src/proxy/ProxyRequestParsing.d.ts.map +1 -0
  99. package/src/proxy/ProxyRequestParsing.js +16 -0
  100. package/src/proxy/RequestValidator.d.ts.map +1 -1
  101. package/src/proxy/RequestValidator.js +2 -1
  102. package/src/proxy/SigningService.js +2 -2
  103. package/src/proxy/SqlProxyDbOverrides.d.ts +17 -0
  104. package/src/proxy/SqlProxyDbOverrides.d.ts.map +1 -0
  105. package/src/proxy/SqlProxyDbOverrides.js +1 -0
  106. package/src/proxy/SqlProxyServerDeps.d.ts +12 -0
  107. package/src/proxy/SqlProxyServerDeps.d.ts.map +1 -0
  108. package/src/proxy/SqlProxyServerDeps.js +9 -0
  109. package/src/proxy/StatementPayloadValidator.d.ts +13 -0
  110. package/src/proxy/StatementPayloadValidator.d.ts.map +1 -0
  111. package/src/proxy/StatementPayloadValidator.js +18 -0
  112. package/src/proxy/StatementRegistryLoader.d.ts +2 -0
  113. package/src/proxy/StatementRegistryLoader.d.ts.map +1 -0
  114. package/src/proxy/StatementRegistryLoader.js +36 -0
  115. package/src/proxy/StatementRegistryResolver.d.ts +15 -0
  116. package/src/proxy/StatementRegistryResolver.d.ts.map +1 -0
  117. package/src/proxy/StatementRegistryResolver.js +34 -0
  118. package/src/proxy/d1/ZintrustD1Proxy.d.ts +2 -1
  119. package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
  120. package/src/proxy/d1/ZintrustD1Proxy.js +2 -1
  121. package/src/proxy/isMutatingSql.d.ts +2 -0
  122. package/src/proxy/isMutatingSql.d.ts.map +1 -0
  123. package/src/proxy/isMutatingSql.js +12 -0
  124. package/src/proxy/kv/ZintrustKvProxy.d.ts +2 -1
  125. package/src/proxy/kv/ZintrustKvProxy.d.ts.map +1 -1
  126. package/src/proxy/kv/ZintrustKvProxy.js +2 -1
  127. package/src/proxy/mysql/MySqlProxyServer.d.ts +2 -8
  128. package/src/proxy/mysql/MySqlProxyServer.d.ts.map +1 -1
  129. package/src/proxy/mysql/MySqlProxyServer.js +84 -51
  130. package/src/proxy/postgres/PostgresProxyServer.d.ts +2 -8
  131. package/src/proxy/postgres/PostgresProxyServer.d.ts.map +1 -1
  132. package/src/proxy/postgres/PostgresProxyServer.js +86 -48
  133. package/src/proxy/smtp/SmtpProxyServer.d.ts.map +1 -1
  134. package/src/proxy/smtp/SmtpProxyServer.js +6 -5
  135. package/src/proxy/sqlserver/SqlServerProxyServer.d.ts +2 -8
  136. package/src/proxy/sqlserver/SqlServerProxyServer.d.ts.map +1 -1
  137. package/src/proxy/sqlserver/SqlServerProxyServer.js +84 -49
  138. package/src/proxy.d.ts +4 -0
  139. package/src/proxy.d.ts.map +1 -0
  140. package/src/proxy.js +3 -0
  141. package/src/scheduler/Schedule.d.ts +36 -0
  142. package/src/scheduler/Schedule.d.ts.map +1 -0
  143. package/src/scheduler/Schedule.js +197 -0
  144. package/src/scheduler/ScheduleHttpGateway.d.ts +8 -0
  145. package/src/scheduler/ScheduleHttpGateway.d.ts.map +1 -0
  146. package/src/scheduler/ScheduleHttpGateway.js +196 -0
  147. package/src/scheduler/ScheduleRunner.d.ts +6 -0
  148. package/src/scheduler/ScheduleRunner.d.ts.map +1 -1
  149. package/src/scheduler/ScheduleRunner.js +166 -29
  150. package/src/scheduler/SchedulerRuntime.d.ts +15 -0
  151. package/src/scheduler/SchedulerRuntime.d.ts.map +1 -0
  152. package/src/scheduler/SchedulerRuntime.js +79 -0
  153. package/src/scheduler/cron/Cron.d.ts +19 -0
  154. package/src/scheduler/cron/Cron.d.ts.map +1 -0
  155. package/src/scheduler/cron/Cron.js +200 -0
  156. package/src/scheduler/leader/SchedulerLeader.d.ts +14 -0
  157. package/src/scheduler/leader/SchedulerLeader.d.ts.map +1 -0
  158. package/src/scheduler/leader/SchedulerLeader.js +187 -0
  159. package/src/scheduler/state/ScheduleStateStore.d.ts +27 -0
  160. package/src/scheduler/state/ScheduleStateStore.d.ts.map +1 -0
  161. package/src/scheduler/state/ScheduleStateStore.js +27 -0
  162. package/src/scheduler/types.d.ts +10 -0
  163. package/src/scheduler/types.d.ts.map +1 -1
  164. package/src/schedules/index.d.ts +1 -0
  165. package/src/schedules/index.d.ts.map +1 -1
  166. package/src/schedules/index.js +1 -0
  167. package/src/schedules/job-tracking-cleanup.d.ts +4 -0
  168. package/src/schedules/job-tracking-cleanup.d.ts.map +1 -0
  169. package/src/schedules/job-tracking-cleanup.js +116 -0
  170. package/src/schedules/log-cleanup.d.ts +1 -2
  171. package/src/schedules/log-cleanup.d.ts.map +1 -1
  172. package/src/schedules/log-cleanup.js +12 -15
  173. package/src/security/Sanitizer.d.ts.map +1 -1
  174. package/src/security/Sanitizer.js +1 -9
  175. package/src/security/SignedRequest.d.ts.map +1 -1
  176. package/src/security/SignedRequest.js +2 -2
  177. package/src/templates/docker/docker-compose.ecosystem.yml.tpl +301 -0
  178. package/src/templates/docker/docker-compose.schedules.yml.tpl +84 -0
  179. package/src/templates/project/basic/app/Schedules/index.ts.tpl +0 -0
  180. package/src/templates/project/basic/config/database.ts.tpl +1 -1
  181. package/src/toolkit/Secrets/Manifest.d.ts.map +1 -1
  182. package/src/toolkit/Secrets/Manifest.js +5 -7
  183. package/src/tools/mail/drivers/Smtp.d.ts.map +1 -1
  184. package/src/tools/mail/drivers/Smtp.js +7 -1
  185. package/src/tools/queue/JobReconciliationRunner.d.ts.map +1 -1
  186. package/src/tools/queue/JobReconciliationRunner.js +7 -39
  187. package/src/tools/queue/JobRecoveryDaemon.d.ts.map +1 -1
  188. package/src/tools/queue/JobRecoveryDaemon.js +116 -18
  189. package/src/tools/queue/JobStateTracker.d.ts +10 -1
  190. package/src/tools/queue/JobStateTracker.d.ts.map +1 -1
  191. package/src/tools/queue/JobStateTracker.js +24 -2
  192. package/src/tools/queue/JobStateTrackerDbPersistence.d.ts.map +1 -1
  193. package/src/tools/queue/JobStateTrackerDbPersistence.js +93 -2
@@ -1,23 +1,17 @@
1
- import { Env } from '../../config/env.js';
2
- import { Logger } from '../../config/logger.js';
3
- import { ErrorHandler } from '../ErrorHandler.js';
4
- import { createProxyServer } from '../ProxyServer.js';
5
- import { resolveBaseConfig, resolveBaseSigningConfig, verifyRequestSignature, } from '../ProxyServerUtils.js';
6
- import { RequestValidator } from '../RequestValidator.js';
7
- import { validateSqlPayload } from '../SqlPayloadValidator.js';
1
+ import * as Deps from '../SqlProxyServerDeps.js';
8
2
  const resolveDatabaseConfig = (overrides = {}) => {
9
- const dbHost = overrides.dbHost ?? Env.get('DB_HOST_MSSQL', Env.get('DB_HOST', '127.0.0.1'));
10
- const dbPort = overrides.dbPort ?? Env.getInt('DB_PORT_MSSQL', 1433);
11
- const dbName = overrides.dbName ?? Env.get('DB_DATABASE_MSSQL', 'zintrust');
12
- const dbUser = overrides.dbUser ?? Env.get('DB_USERNAME_MSSQL', 'sa');
13
- const dbPass = overrides.dbPass ?? Env.get('DB_PASSWORD_MSSQL', '');
14
- const connectionLimit = overrides.connectionLimit ?? Env.getInt('SQLSERVER_PROXY_POOL_LIMIT', 10);
3
+ const dbHost = overrides.dbHost ?? Deps.Env.get('DB_HOST_MSSQL', Deps.Env.get('DB_HOST', '127.0.0.1'));
4
+ const dbPort = overrides.dbPort ?? Deps.Env.getInt('DB_PORT_MSSQL', 1433);
5
+ const dbName = overrides.dbName ?? Deps.Env.get('DB_DATABASE_MSSQL', 'zintrust');
6
+ const dbUser = overrides.dbUser ?? Deps.Env.get('DB_USERNAME_MSSQL', 'sa');
7
+ const dbPass = overrides.dbPass ?? Deps.Env.get('DB_PASSWORD_MSSQL', '');
8
+ const connectionLimit = overrides.connectionLimit ?? Deps.Env.getInt('SQLSERVER_PROXY_POOL_LIMIT', 10);
15
9
  return { dbHost, dbPort, dbName, dbUser, dbPass, connectionLimit };
16
10
  };
17
11
  const resolveConfig = (overrides = {}) => {
18
- const proxyConfig = resolveBaseConfig(overrides, 'SQLSERVER');
12
+ const proxyConfig = Deps.resolveBaseConfig(overrides, 'SQLSERVER');
19
13
  const dbConfig = resolveDatabaseConfig(overrides);
20
- const signingConfig = resolveBaseSigningConfig(overrides, 'SQLSERVER');
14
+ const signingConfig = Deps.resolveBaseSigningConfig(overrides, 'SQLSERVER');
21
15
  const poolConfig = {
22
16
  server: dbConfig.dbHost,
23
17
  port: dbConfig.dbPort,
@@ -45,10 +39,11 @@ const resolveConfig = (overrides = {}) => {
45
39
  require: signingConfig.requireSigning,
46
40
  windowMs: signingConfig.signingWindowMs,
47
41
  },
42
+ statements: Deps.loadStatementRegistry('SQLSERVER'),
48
43
  };
49
44
  };
50
45
  const validateQueryPayload = (payload) => {
51
- const base = validateSqlPayload(payload);
46
+ const base = Deps.validateSqlPayload(payload);
52
47
  if (!base.valid) {
53
48
  return { valid: false, error: base.error };
54
49
  }
@@ -95,42 +90,82 @@ const handleEndpoint = (path, result) => {
95
90
  },
96
91
  };
97
92
  }
98
- return ErrorHandler.toProxyError(404, 'NOT_FOUND', 'Unknown endpoint');
93
+ if (path === '/zin/sqlserver/statement') {
94
+ // Statement endpoint returns query-shaped response for non-mutating SQL.
95
+ return { status: 200, body: { rows, rowCount: rowsAffected[0] ?? 0 } };
96
+ }
97
+ return Deps.ErrorHandler.toProxyError(404, 'NOT_FOUND', 'Unknown endpoint');
98
+ };
99
+ const toMutatingStatementResponse = (result) => {
100
+ const rowsAffected = result['rowsAffected'];
101
+ return {
102
+ status: 200,
103
+ body: {
104
+ ok: true,
105
+ meta: { changes: rowsAffected[0] ?? 0 },
106
+ },
107
+ };
108
+ };
109
+ const handleStatementRequest = async (pool, statements, requestPath, payload) => {
110
+ const resolved = Deps.resolveStatementOrError(statements, payload);
111
+ if (!resolved.ok)
112
+ return resolved.response;
113
+ try {
114
+ const result = await executeQuery(pool, resolved.value.sql, resolved.value.params);
115
+ if (!resolved.value.mutating)
116
+ return handleEndpoint('/zin/sqlserver/statement', result);
117
+ return toMutatingStatementResponse(result);
118
+ }
119
+ catch (error) {
120
+ Deps.Logger.error('[SqlServerProxyServer] Statement execution failed', {
121
+ path: requestPath,
122
+ statementId: resolved.value.statementId,
123
+ mutating: resolved.value.mutating,
124
+ paramsCount: resolved.value.params.length,
125
+ error: error instanceof Error ? error.message : String(error),
126
+ });
127
+ return Deps.ErrorHandler.toProxyError(500, 'SQLSERVER_ERROR', String(error));
128
+ }
129
+ };
130
+ const handleSqlRequest = async (pool, requestPath, payload) => {
131
+ const sqlValidation = validateQueryPayload(payload);
132
+ if (!sqlValidation.valid) {
133
+ const error = sqlValidation.error ?? {
134
+ code: 'VALIDATION_ERROR',
135
+ message: 'Invalid SQL payload',
136
+ };
137
+ return Deps.ErrorHandler.toProxyError(400, error.code, error.message);
138
+ }
139
+ try {
140
+ const result = await executeQuery(pool, sqlValidation.sql ?? '', sqlValidation.params ?? []);
141
+ return handleEndpoint(requestPath, result);
142
+ }
143
+ catch (error) {
144
+ return Deps.ErrorHandler.toProxyError(500, 'SQLSERVER_ERROR', String(error));
145
+ }
99
146
  };
100
- const createBackend = (pool) => ({
147
+ const handleProxyRequest = async (pool, statements, request) => {
148
+ const validationError = Deps.validateProxyRequest(request);
149
+ if (validationError !== null)
150
+ return validationError;
151
+ const parsed = Deps.parseJsonBody(request.body);
152
+ if ('status' in parsed)
153
+ return parsed;
154
+ if (request.path === '/zin/sqlserver/statement') {
155
+ return handleStatementRequest(pool, statements, request.path, parsed.value);
156
+ }
157
+ return handleSqlRequest(pool, request.path, parsed.value);
158
+ };
159
+ const createBackend = (pool, statements) => ({
101
160
  name: 'sqlserver',
102
- handle: async (request) => {
103
- const methodError = RequestValidator.requirePost(request.method);
104
- if (methodError) {
105
- return ErrorHandler.toProxyError(405, methodError.code, methodError.message);
106
- }
107
- const parsed = RequestValidator.parseJson(request.body);
108
- if (!parsed.ok) {
109
- return ErrorHandler.toProxyError(400, parsed.error.code, parsed.error.message);
110
- }
111
- const sqlValidation = validateQueryPayload(parsed.value);
112
- if (!sqlValidation.valid) {
113
- const error = sqlValidation.error ?? {
114
- code: 'VALIDATION_ERROR',
115
- message: 'Invalid SQL payload',
116
- };
117
- return ErrorHandler.toProxyError(400, error.code, error.message);
118
- }
119
- try {
120
- const result = await executeQuery(pool, sqlValidation.sql ?? '', sqlValidation.params ?? []);
121
- return handleEndpoint(request.path, result);
122
- }
123
- catch (error) {
124
- return ErrorHandler.toProxyError(500, 'SQLSERVER_ERROR', String(error));
125
- }
126
- },
161
+ handle: async (request) => handleProxyRequest(pool, statements, request),
127
162
  health: async () => {
128
163
  try {
129
164
  await executeQuery(pool, 'SELECT 1', []);
130
165
  return { status: 200, body: { status: 'healthy' } };
131
166
  }
132
167
  catch (error) {
133
- return ErrorHandler.toProxyError(503, 'UNHEALTHY', String(error));
168
+ return Deps.ErrorHandler.toProxyError(503, 'UNHEALTHY', String(error));
134
169
  }
135
170
  },
136
171
  shutdown: async () => {
@@ -142,20 +177,20 @@ export const SqlServerProxyServer = Object.freeze({
142
177
  async start(overrides = {}) {
143
178
  const config = resolveConfig(overrides);
144
179
  try {
145
- Logger.info(`SQL Server proxy config: proxyHost=${config.host} proxyPort=${config.port} dbHost=${String(config.poolConfig['server'])} dbPort=${String(config.poolConfig['port'])} dbName=${String(config.poolConfig['database'])} dbUser=${String(config.poolConfig['user'])}`);
180
+ Deps.Logger.info(`SQL Server proxy config: proxyHost=${config.host} proxyPort=${config.port} dbHost=${String(config.poolConfig['server'])} dbPort=${String(config.poolConfig['port'])} dbName=${String(config.poolConfig['database'])} dbUser=${String(config.poolConfig['user'])}`);
146
181
  }
147
182
  catch {
148
183
  // noop - logging must not block startup
149
184
  }
150
185
  const pool = await createPool(config.poolConfig);
151
- const backend = createBackend(pool);
152
- const proxy = createProxyServer({
186
+ const backend = createBackend(pool, config.statements);
187
+ const proxy = Deps.createProxyServer({
153
188
  host: config.host,
154
189
  port: config.port,
155
190
  maxBodyBytes: config.maxBodyBytes,
156
191
  backend,
157
192
  verify: async (req, body) => {
158
- const verified = await verifyRequestSignature(req, body, config, 'SqlServerProxyServer');
193
+ const verified = await Deps.verifyRequestSignature(req, body, config, 'SqlServerProxyServer');
159
194
  if (!verified.ok && verified.error) {
160
195
  return { ok: false, status: verified.error.status, message: verified.error.message };
161
196
  }
@@ -163,6 +198,6 @@ export const SqlServerProxyServer = Object.freeze({
163
198
  },
164
199
  });
165
200
  await proxy.start();
166
- Logger.info(`✓ SQL Server proxy listening on ${config.host}:${config.port}`);
201
+ Deps.Logger.info(`✓ SQL Server proxy listening on ${config.host}:${config.port}`);
167
202
  },
168
203
  });
package/src/proxy.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { ErrorHandler } from './proxy/ErrorHandler';
2
+ export { RequestValidator } from './proxy/RequestValidator';
3
+ export { SigningService } from './proxy/SigningService';
4
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
package/src/proxy.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ErrorHandler } from './proxy/ErrorHandler.js';
2
+ export { RequestValidator } from './proxy/RequestValidator.js';
3
+ export { SigningService } from './proxy/SigningService.js';
@@ -0,0 +1,36 @@
1
+ import type { ISchedule, IScheduleBackoffPolicy } from './types';
2
+ type CronOptions = {
3
+ timezone?: string;
4
+ };
5
+ type WithoutOverlappingOptions = {
6
+ provider?: string;
7
+ ttlMs?: number;
8
+ key?: string;
9
+ };
10
+ export type ScheduleBuilderApi = Readonly<{
11
+ everyMinute: () => ScheduleBuilderApi;
12
+ everyMinutes: (minutes: number) => ScheduleBuilderApi;
13
+ everyHour: () => ScheduleBuilderApi;
14
+ everyHours: (hours: number) => ScheduleBuilderApi;
15
+ intervalMs: (ms: number) => ScheduleBuilderApi;
16
+ cron: (expr: string, options?: CronOptions) => ScheduleBuilderApi;
17
+ timezone: (tz: string) => ScheduleBuilderApi;
18
+ jitterMs: (ms: number) => ScheduleBuilderApi;
19
+ backoff: (policy: IScheduleBackoffPolicy) => ScheduleBuilderApi;
20
+ leaderOnly: () => ScheduleBuilderApi;
21
+ runOnStart: () => ScheduleBuilderApi;
22
+ enabledWhen: (value: boolean) => ScheduleBuilderApi;
23
+ withoutOverlapping: (options?: WithoutOverlappingOptions) => ScheduleBuilderApi;
24
+ build: () => ISchedule;
25
+ }>;
26
+ export declare const Schedule: Readonly<{
27
+ define(name: string, handler: ISchedule["handler"]): ScheduleBuilderApi;
28
+ }>;
29
+ export declare const ScheduleBuilder: Readonly<{
30
+ create(input: {
31
+ name: string;
32
+ handler: ISchedule["handler"];
33
+ }): ScheduleBuilderApi;
34
+ }>;
35
+ export default Schedule;
36
+ //# sourceMappingURL=Schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Schedule.d.ts","sourceRoot":"","sources":["../../../src/scheduler/Schedule.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1E,KAAK,WAAW,GAAG;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,WAAW,EAAE,MAAM,kBAAkB,CAAC;IACtC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,kBAAkB,CAAC;IACtD,SAAS,EAAE,MAAM,kBAAkB,CAAC;IACpC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,kBAAkB,CAAC;IAClD,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,kBAAkB,CAAC;IAC/C,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,kBAAkB,CAAC;IAClE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,kBAAkB,CAAC;IAC7C,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,kBAAkB,CAAC;IAC7C,OAAO,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,kBAAkB,CAAC;IAChE,UAAU,EAAE,MAAM,kBAAkB,CAAC;IACrC,UAAU,EAAE,MAAM,kBAAkB,CAAC;IACrC,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,kBAAkB,CAAC;IACpD,kBAAkB,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,kBAAkB,CAAC;IAChF,KAAK,EAAE,MAAM,SAAS,CAAC;CACxB,CAAC,CAAC;AA4HH,eAAO,MAAM,QAAQ;iBACN,MAAM,WAAW,SAAS,CAAC,SAAS,CAAC,GAAG,kBAAkB;EAGvE,CAAC;AAqFH,eAAO,MAAM,eAAe;kBACZ;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;KAAE,GAAG,kBAAkB;EAQlF,CAAC;AAEH,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,197 @@
1
+ import { Env } from '../config/env.js';
2
+ import { Logger } from '../config/logger.js';
3
+ import { ZintrustLang } from '../lang/lang.js';
4
+ import { createAdvancedQueue } from '../tools/queue/AdvancedQueue.js';
5
+ import { getLockProvider } from '../tools/queue/LockProvider.js';
6
+ const toIntervalMs = (ms) => {
7
+ if (!Number.isFinite(ms) || ms <= 0)
8
+ return 0;
9
+ return Math.floor(ms);
10
+ };
11
+ const normalizeOptionalString = (value) => {
12
+ const s = typeof value === 'string' ? value.trim() : '';
13
+ return s.length > 0 ? s : undefined;
14
+ };
15
+ const toPositiveInt = (value) => {
16
+ const n = typeof value === 'number' ? value : Number(value);
17
+ if (!Number.isFinite(n) || n <= 0)
18
+ return undefined;
19
+ return Math.floor(n);
20
+ };
21
+ const resolveLockProvider = (providerName) => {
22
+ const name = providerName.trim().toLowerCase();
23
+ if (name.length === 0)
24
+ return undefined;
25
+ // Ensure provider is registered. createAdvancedQueue triggers lock-provider registration.
26
+ createAdvancedQueue({
27
+ name: ZintrustLang.CLI_LOCKS,
28
+ connection: undefined,
29
+ defaultDedupTtl: Env.getInt('SCHEDULE_OVERLAP_LOCK_TTL_MS', 300000),
30
+ lockProvider: name,
31
+ });
32
+ return getLockProvider(name);
33
+ };
34
+ const normalizeBackoffFactor = (factor) => {
35
+ if (factor === undefined)
36
+ return undefined;
37
+ return Number.isFinite(factor) ? factor : undefined;
38
+ };
39
+ const wrapWithoutOverlapping = (scheduleName, handler, options) => {
40
+ const providerName = (options.provider ?? 'redis').trim();
41
+ const lockKey = (options.key ?? `schedule:${scheduleName}`).trim();
42
+ const ttlMs = Env.getInt('SCHEDULE_OVERLAP_LOCK_TTL_MS', options.ttlMs ?? 300000);
43
+ const acquireTimeoutMs = Env.getInt('SCHEDULE_OVERLAP_LOCK_ACQUIRE_TIMEOUT_MS', 2000);
44
+ const withTimeout = async (promise, timeoutMs) => {
45
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
46
+ return promise;
47
+ let timeoutId;
48
+ try {
49
+ return await Promise.race([
50
+ promise,
51
+ new Promise((_, reject) => {
52
+ timeoutId = globalThis.setTimeout(() => {
53
+ // eslint-disable-next-line no-restricted-syntax
54
+ reject(new Error('Lock acquire timed out'));
55
+ }, timeoutMs);
56
+ }),
57
+ ]);
58
+ }
59
+ finally {
60
+ if (timeoutId !== undefined)
61
+ globalThis.clearTimeout(timeoutId);
62
+ }
63
+ };
64
+ return async (kernel) => {
65
+ const provider = resolveLockProvider(providerName);
66
+ if (!provider) {
67
+ Logger.warn('Schedule withoutOverlapping requested but lock provider not available; running anyway', {
68
+ schedule: scheduleName,
69
+ provider: providerName,
70
+ });
71
+ await handler(kernel);
72
+ return;
73
+ }
74
+ let lock;
75
+ try {
76
+ lock = await withTimeout(provider.acquire(lockKey, { ttl: ttlMs }), acquireTimeoutMs);
77
+ }
78
+ catch (error) {
79
+ Logger.warn('Schedule lock acquire failed; running anyway', {
80
+ schedule: scheduleName,
81
+ provider: providerName,
82
+ timeoutMs: acquireTimeoutMs,
83
+ message: error instanceof Error ? error.message : String(error),
84
+ });
85
+ await handler(kernel);
86
+ return;
87
+ }
88
+ if (!lock.acquired) {
89
+ Logger.info(`Skipping overlapping run for schedule: ${scheduleName}`);
90
+ return;
91
+ }
92
+ try {
93
+ await handler(kernel);
94
+ }
95
+ finally {
96
+ try {
97
+ await provider.release(lock);
98
+ }
99
+ catch {
100
+ // best-effort
101
+ }
102
+ }
103
+ };
104
+ };
105
+ export const Schedule = Object.freeze({
106
+ define(name, handler) {
107
+ return ScheduleBuilder.create({ name, handler });
108
+ },
109
+ });
110
+ const createScheduleApi = (state) => {
111
+ const api = Object.freeze({
112
+ everyMinute: () => api.everyMinutes(1),
113
+ everyMinutes: (minutes) => {
114
+ const resolved = Math.max(1, Math.floor(minutes));
115
+ state.intervalMs = resolved * 60_000;
116
+ return api;
117
+ },
118
+ everyHour: () => api.everyHours(1),
119
+ everyHours: (hours) => {
120
+ const resolved = Math.max(1, Math.floor(hours));
121
+ state.intervalMs = resolved * 3_600_000;
122
+ return api;
123
+ },
124
+ intervalMs: (ms) => {
125
+ state.intervalMs = toIntervalMs(ms);
126
+ return api;
127
+ },
128
+ cron: (expr, options) => {
129
+ state.cron = normalizeOptionalString(expr);
130
+ if (options?.timezone !== undefined) {
131
+ state.timezone = normalizeOptionalString(options.timezone);
132
+ }
133
+ return api;
134
+ },
135
+ timezone: (tz) => {
136
+ state.timezone = normalizeOptionalString(tz);
137
+ return api;
138
+ },
139
+ jitterMs: (ms) => {
140
+ state.jitterMs = toPositiveInt(ms);
141
+ return api;
142
+ },
143
+ backoff: (policy) => {
144
+ state.backoff = {
145
+ initialMs: toPositiveInt(policy.initialMs) ?? 0,
146
+ maxMs: toPositiveInt(policy.maxMs) ?? 0,
147
+ factor: normalizeBackoffFactor(policy.factor),
148
+ };
149
+ return api;
150
+ },
151
+ leaderOnly: () => {
152
+ state.leaderOnly = true;
153
+ return api;
154
+ },
155
+ runOnStart: () => {
156
+ state.runOnStart = true;
157
+ return api;
158
+ },
159
+ enabledWhen: (value) => {
160
+ state.enabled = value;
161
+ return api;
162
+ },
163
+ withoutOverlapping: (options) => {
164
+ state.overlap = options ?? {};
165
+ return api;
166
+ },
167
+ build: () => {
168
+ const handler = state.overlap === undefined
169
+ ? state.handler
170
+ : wrapWithoutOverlapping(state.name, state.handler, state.overlap);
171
+ const schedule = {
172
+ name: state.name,
173
+ intervalMs: state.intervalMs,
174
+ cron: state.cron,
175
+ timezone: state.timezone,
176
+ jitterMs: state.jitterMs,
177
+ backoff: state.backoff,
178
+ leaderOnly: state.leaderOnly,
179
+ handler,
180
+ enabled: state.enabled,
181
+ runOnStart: state.runOnStart,
182
+ };
183
+ return schedule;
184
+ },
185
+ });
186
+ return api;
187
+ };
188
+ export const ScheduleBuilder = Object.freeze({
189
+ create(input) {
190
+ const state = {
191
+ name: input.name,
192
+ handler: input.handler,
193
+ };
194
+ return createScheduleApi(state);
195
+ },
196
+ });
197
+ export default Schedule;
@@ -0,0 +1,8 @@
1
+ import type { IRouter } from '../routes/Router';
2
+ export declare const ScheduleHttpGateway: Readonly<{
3
+ create(): {
4
+ registerRoutes: (router: IRouter) => void;
5
+ };
6
+ }>;
7
+ export default ScheduleHttpGateway;
8
+ //# sourceMappingURL=ScheduleHttpGateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleHttpGateway.d.ts","sourceRoot":"","sources":["../../../src/scheduler/ScheduleHttpGateway.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AA8QnD,eAAO,MAAM,mBAAmB;cACpB;QAAE,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE;EAWvD,CAAC;AAEH,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,196 @@
1
+ import { Env } from '../config/env.js';
2
+ import { Logger } from '../config/logger.js';
3
+ import { Router } from '../routes/Router.js';
4
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
5
+ import { SchedulerRuntime } from './SchedulerRuntime.js';
6
+ import { SignedRequest } from '../security/SignedRequest.js';
7
+ const nonces = new Map();
8
+ const nowMs = () => Date.now();
9
+ const normalizePath = (value) => {
10
+ const trimmed = value.trim();
11
+ if (trimmed === '')
12
+ return '/api/_sys/schedule/rpc';
13
+ return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
14
+ };
15
+ const parseMiddleware = (value) => value
16
+ .split(',')
17
+ .map((entry) => entry.trim())
18
+ .filter((entry) => entry.length > 0);
19
+ const readSettings = () => {
20
+ const configuredSecret = Env.get('SCHEDULE_HTTP_PROXY_KEY', '').trim();
21
+ const secret = configuredSecret === '' ? Env.APP_KEY : configuredSecret;
22
+ return {
23
+ basePath: normalizePath(Env.get('SCHEDULE_HTTP_PROXY_PATH', '/api/_sys/schedule/rpc')),
24
+ keyId: Env.get('SCHEDULE_HTTP_PROXY_KEY_ID', Env.APP_NAME || 'zintrust').trim(),
25
+ secret,
26
+ signingWindowMs: Env.getInt('SCHEDULE_HTTP_PROXY_MAX_SKEW_MS', 60000),
27
+ nonceTtlMs: Env.getInt('SCHEDULE_HTTP_PROXY_NONCE_TTL_MS', 120000),
28
+ middleware: parseMiddleware(Env.get('SCHEDULE_HTTP_PROXY_MIDDLEWARE', '')),
29
+ };
30
+ };
31
+ const cleanupExpiredNonces = () => {
32
+ const current = nowMs();
33
+ for (const [nonceKey, expiresAt] of nonces.entries()) {
34
+ if (expiresAt <= current)
35
+ nonces.delete(nonceKey);
36
+ }
37
+ };
38
+ // eslint-disable-next-line @typescript-eslint/require-await
39
+ const storeNonce = async (keyId, nonce, ttlMs) => {
40
+ cleanupExpiredNonces();
41
+ const nonceKey = `${keyId}:${nonce}`;
42
+ if (nonces.has(nonceKey))
43
+ return false;
44
+ nonces.set(nonceKey, nowMs() + Math.max(ttlMs, 1));
45
+ return true;
46
+ };
47
+ const getBodyRecord = (req) => {
48
+ const body = req.getBody?.() ?? req.body;
49
+ if (typeof body === 'object' && body !== null && !Array.isArray(body)) {
50
+ return body;
51
+ }
52
+ return {};
53
+ };
54
+ const getRawBody = (req) => {
55
+ const rawText = req.context?.['rawBodyText'];
56
+ if (typeof rawText === 'string')
57
+ return rawText;
58
+ return JSON.stringify(getBodyRecord(req));
59
+ };
60
+ const toIncomingHeaders = (req) => {
61
+ const headers = req.getHeaders();
62
+ const normalize = (value) => {
63
+ if (Array.isArray(value))
64
+ return value.join(',');
65
+ return value;
66
+ };
67
+ return {
68
+ 'x-zt-key-id': normalize(headers['x-zt-key-id']),
69
+ 'x-zt-nonce': normalize(headers['x-zt-nonce']),
70
+ 'x-zt-timestamp': normalize(headers['x-zt-timestamp']),
71
+ 'x-zt-body-sha256': normalize(headers['x-zt-body-sha256']),
72
+ 'x-zt-signature': normalize(headers['x-zt-signature']),
73
+ 'content-type': normalize(headers['content-type']),
74
+ };
75
+ };
76
+ const parseRequest = (req) => {
77
+ const body = getBodyRecord(req);
78
+ const action = String(body['action'] ?? '')
79
+ .trim()
80
+ .toLowerCase();
81
+ const requestId = String(body['requestId'] ?? '').trim();
82
+ if (requestId.length === 0) {
83
+ throw ErrorFactory.createValidationError('requestId is required');
84
+ }
85
+ if (action !== 'list' && action !== 'run') {
86
+ throw ErrorFactory.createValidationError('Invalid action');
87
+ }
88
+ const payload = typeof body['payload'] === 'object' && body['payload'] !== null
89
+ ? body['payload']
90
+ : undefined;
91
+ return {
92
+ action: action,
93
+ requestId,
94
+ payload,
95
+ };
96
+ };
97
+ const ok = (requestId, result) => ({
98
+ ok: true,
99
+ requestId,
100
+ result,
101
+ error: null,
102
+ });
103
+ const fail = (requestId, code, message, details) => ({
104
+ ok: false,
105
+ requestId,
106
+ result: null,
107
+ error: { code, message, details },
108
+ });
109
+ const listSchedules = async () => {
110
+ const rows = await SchedulerRuntime.listWithState();
111
+ return rows.map(({ schedule, state }) => ({
112
+ name: schedule.name,
113
+ intervalMs: schedule.intervalMs,
114
+ cron: schedule.cron,
115
+ timezone: schedule.timezone,
116
+ enabled: schedule.enabled,
117
+ runOnStart: schedule.runOnStart,
118
+ state,
119
+ }));
120
+ };
121
+ const verifyRequest = async (req, bodyText, settings) => {
122
+ if (settings.keyId.trim() === '' || settings.secret.trim() === '') {
123
+ return {
124
+ ok: false,
125
+ status: 500,
126
+ code: 'CONFIG_ERROR',
127
+ message: 'Schedule HTTP gateway signing credentials are not configured',
128
+ };
129
+ }
130
+ const url = new URL(req.getPath(), 'http://localhost');
131
+ const verifyResult = await SignedRequest.verify({
132
+ method: req.getMethod(),
133
+ url,
134
+ body: bodyText,
135
+ headers: toIncomingHeaders(req),
136
+ nowMs: nowMs(),
137
+ windowMs: settings.signingWindowMs,
138
+ verifyNonce: async (keyId, nonce) => storeNonce(keyId, nonce, settings.nonceTtlMs),
139
+ getSecretForKeyId: (keyId) => {
140
+ if (keyId === settings.keyId)
141
+ return settings.secret;
142
+ return undefined;
143
+ },
144
+ });
145
+ if (verifyResult.ok === true)
146
+ return { ok: true };
147
+ const errorCode = 'code' in verifyResult ? verifyResult.code : 'INVALID_SIGNATURE';
148
+ const errorMessage = 'message' in verifyResult ? verifyResult.message : 'Invalid signature';
149
+ const status = errorCode === 'EXPIRED' || errorCode === 'REPLAYED' ? 401 : 403;
150
+ return { ok: false, status, code: errorCode, message: errorMessage };
151
+ };
152
+ const handleRpc = async (req, res) => {
153
+ const settings = readSettings();
154
+ const rawBody = getRawBody(req);
155
+ const body = getBodyRecord(req);
156
+ const requestId = typeof body['requestId'] === 'string' && String(body['requestId']).trim() !== ''
157
+ ? String(body['requestId'])
158
+ : 'unknown';
159
+ const auth = await verifyRequest(req, rawBody, settings);
160
+ if (auth.ok === false) {
161
+ res.status(auth.status).json(fail(requestId, auth.code, auth.message));
162
+ return;
163
+ }
164
+ const parsed = parseRequest(req);
165
+ try {
166
+ if (parsed.action === 'list') {
167
+ res.json(ok(parsed.requestId, await listSchedules()));
168
+ return;
169
+ }
170
+ const name = String(parsed.payload?.name ?? '').trim();
171
+ if (name.length === 0) {
172
+ res.status(400).json(fail(parsed.requestId, 'VALIDATION_ERROR', 'payload.name is required'));
173
+ return;
174
+ }
175
+ await SchedulerRuntime.runOnce(name);
176
+ res.json(ok(parsed.requestId, { ran: true, name }));
177
+ }
178
+ catch (error) {
179
+ Logger.error('Schedule RPC failed', error);
180
+ res.status(500).json(fail(parsed.requestId, 'INTERNAL_ERROR', 'Schedule RPC failed', {
181
+ message: error instanceof Error ? error.message : String(error),
182
+ }));
183
+ }
184
+ };
185
+ export const ScheduleHttpGateway = Object.freeze({
186
+ create() {
187
+ const settings = readSettings();
188
+ const options = settings.middleware.length > 0 ? { middleware: settings.middleware } : undefined;
189
+ return Object.freeze({
190
+ registerRoutes(router) {
191
+ Router.post(router, settings.basePath, handleRpc, options);
192
+ },
193
+ });
194
+ },
195
+ });
196
+ export default ScheduleHttpGateway;
@@ -2,6 +2,7 @@
2
2
  * ScheduleRunner
3
3
  * Lightweight, zero-dependency schedule runner for long-running runtimes
4
4
  */
5
+ import { type ScheduleRunState } from './state/ScheduleStateStore';
5
6
  import type { ISchedule, IScheduleKernel } from './types';
6
7
  type ScheduleRunner = {
7
8
  register: (schedule: ISchedule) => void;
@@ -9,6 +10,11 @@ type ScheduleRunner = {
9
10
  stop: (timeoutMs?: number) => Promise<void>;
10
11
  list: () => ISchedule[];
11
12
  runOnce: (name: string, kernel?: IScheduleKernel) => Promise<void>;
13
+ getState: (name: string) => Promise<ScheduleRunState | null>;
14
+ listStates: () => Promise<Array<{
15
+ name: string;
16
+ state: ScheduleRunState;
17
+ }>>;
12
18
  };
13
19
  export declare const create: () => Readonly<ScheduleRunner>;
14
20
  declare const _default: {
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleRunner.d.ts","sourceRoot":"","sources":["../../../src/scheduler/ScheduleRunner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAgBnE,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,SAAS,EAAE,CAAC;IACxB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE,CAAC;AAoKF,eAAO,MAAM,MAAM,QAAO,QAAQ,CAAC,cAAc,CAuBhD,CAAC;;kBAvBwB,QAAQ,CAAC,cAAc,CAAC;;AAyBlD,wBAA0B"}
1
+ {"version":3,"file":"ScheduleRunner.d.ts","sourceRoot":"","sources":["../../../src/scheduler/ScheduleRunner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAkBnE,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,SAAS,EAAE,CAAC;IACxB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC7D,UAAU,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC,CAAC;CAC7E,CAAC;AA6VF,eAAO,MAAM,MAAM,QAAO,QAAQ,CAAC,cAAc,CA6BhD,CAAC;;kBA7BwB,QAAQ,CAAC,cAAc,CAAC;;AA+BlD,wBAA0B"}