@zintrust/core 0.4.76 → 0.4.79

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 (45) hide show
  1. package/bin/zintrust-main.d.ts +12 -0
  2. package/bin/zintrust-main.d.ts.map +1 -1
  3. package/bin/zintrust-main.js +149 -54
  4. package/package.json +1 -1
  5. package/src/boot/registry/runtime.d.ts.map +1 -1
  6. package/src/boot/registry/runtime.js +38 -4
  7. package/src/cli/commands/ProxyScaffoldUtils.d.ts +2 -0
  8. package/src/cli/commands/ProxyScaffoldUtils.d.ts.map +1 -1
  9. package/src/cli/commands/ProxyScaffoldUtils.js +147 -4
  10. package/src/cli/commands/TraceCommands.d.ts.map +1 -1
  11. package/src/cli/commands/TraceCommands.js +43 -51
  12. package/src/cli/commands/WranglerProxyCommandUtils.d.ts.map +1 -1
  13. package/src/cli/commands/WranglerProxyCommandUtils.js +14 -2
  14. package/src/config/logging/KvLogger.d.ts.map +1 -1
  15. package/src/config/logging/KvLogger.js +18 -6
  16. package/src/config/workers.d.ts.map +1 -1
  17. package/src/config/workers.js +52 -12
  18. package/src/functions/cloudflare.d.ts.map +1 -1
  19. package/src/functions/cloudflare.js +8 -0
  20. package/src/http/RequestContext.d.ts.map +1 -1
  21. package/src/http/RequestContext.js +5 -6
  22. package/src/index.d.ts +1 -0
  23. package/src/index.d.ts.map +1 -1
  24. package/src/index.js +4 -3
  25. package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -1
  26. package/src/middleware/ErrorHandlerMiddleware.js +14 -0
  27. package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
  28. package/src/orm/adapters/SQLiteAdapter.js +2 -1
  29. package/src/orm/migrations/MigrationStore.d.ts.map +1 -1
  30. package/src/orm/migrations/MigrationStore.js +383 -16
  31. package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
  32. package/src/proxy/d1/ZintrustD1Proxy.js +16 -9
  33. package/src/runtime/StartupConfigFileRegistry.d.ts +2 -1
  34. package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -1
  35. package/src/runtime/StartupConfigFileRegistry.js +1 -0
  36. package/src/runtime/plugins/trace-runtime.d.ts +10 -0
  37. package/src/runtime/plugins/trace-runtime.d.ts.map +1 -1
  38. package/src/runtime/plugins/trace-runtime.js +51 -7
  39. package/src/templates/project/basic/tsconfig.json.tpl +11 -12
  40. package/src/tools/queue/Queue.d.ts +1 -2
  41. package/src/tools/queue/Queue.d.ts.map +1 -1
  42. package/src/tools/queue/Queue.js +1 -2
  43. package/src/trace/SystemTraceBridge.js +1 -1
  44. package/src/zintrust.plugins.js +2 -2
  45. package/src/zintrust.plugins.wg.js +2 -2
@@ -1,6 +1,17 @@
1
1
  import { Env } from '../../config/env.js';
2
2
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
3
3
  import { QueryBuilder } from '../QueryBuilder.js';
4
+ const DEFAULT_LAYOUT = Object.freeze({
5
+ hasAppliedAt: true,
6
+ hasCreatedAt: true,
7
+ hasMigration: false,
8
+ hasName: true,
9
+ hasScope: true,
10
+ hasService: true,
11
+ hasStatus: true,
12
+ requiresCompatibilityMode: false,
13
+ });
14
+ const tableLayoutCache = new WeakMap();
4
15
  function nowIso() {
5
16
  // MySQL/MariaDB DATETIME does not accept ISO8601 with timezone (e.g. trailing 'Z').
6
17
  // Use a portable UTC datetime string.
@@ -11,6 +22,261 @@ const toSafeService = (service) => {
11
22
  return '';
12
23
  return service.length > 0 ? service : '';
13
24
  };
25
+ const isDefaultTrackingTarget = (scope, service) => {
26
+ return scope === 'global' && service === '';
27
+ };
28
+ const queryExists = async (db, sql, parameters) => {
29
+ const rows = await db.query(sql, parameters, true);
30
+ return rows.length > 0;
31
+ };
32
+ const schemaHasTable = async (db, tableName) => {
33
+ const driver = db.getType();
34
+ if (driver === 'sqlite' || driver === 'd1' || driver === 'd1-remote') {
35
+ return queryExists(db, "SELECT 1 FROM sqlite_master WHERE type='table' AND name=? LIMIT 1", [
36
+ tableName,
37
+ ]);
38
+ }
39
+ if (driver === 'postgresql') {
40
+ return queryExists(db, "SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name=? LIMIT 1", [tableName]);
41
+ }
42
+ if (driver === 'mysql') {
43
+ return queryExists(db, 'SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name=? LIMIT 1', [tableName]);
44
+ }
45
+ if (driver === 'sqlserver') {
46
+ return queryExists(db, 'SELECT 1 FROM sys.tables WHERE name=? LIMIT 1', [tableName]);
47
+ }
48
+ throw ErrorFactory.createCliError(`Unsupported DB driver: ${driver}`);
49
+ };
50
+ const schemaHasColumn = async (db, tableName, columnName) => {
51
+ const driver = db.getType();
52
+ if (driver === 'sqlite' || driver === 'd1' || driver === 'd1-remote') {
53
+ const rows = await db.query(`PRAGMA table_info("${tableName}")`, [], true);
54
+ return rows.some((row) => {
55
+ const record = row;
56
+ return typeof record.name === 'string' && record.name === columnName;
57
+ });
58
+ }
59
+ if (driver === 'postgresql') {
60
+ return queryExists(db, "SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name=? AND column_name=? LIMIT 1", [tableName, columnName]);
61
+ }
62
+ if (driver === 'mysql') {
63
+ return queryExists(db, 'SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name=? AND column_name=? LIMIT 1', [tableName, columnName]);
64
+ }
65
+ if (driver === 'sqlserver') {
66
+ return queryExists(db, 'SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(?) AND name=?', [
67
+ tableName,
68
+ columnName,
69
+ ]);
70
+ }
71
+ throw ErrorFactory.createCliError(`Unsupported DB driver: ${driver}`);
72
+ };
73
+ const clearTableLayoutCache = (db) => {
74
+ tableLayoutCache.delete(db);
75
+ };
76
+ const ensureTrackingTable = async (db) => {
77
+ assertDbSupportsMigrations(db);
78
+ const adapter = db.getAdapterInstance(false);
79
+ const ensure = requireMigrationsTableSupport(adapter);
80
+ // getAdapterInstance(false) returns a raw adapter without going through Database.query()
81
+ // which auto-connects; ensure we're connected before creating the migrations table.
82
+ if (typeof db.connect === 'function') {
83
+ await db.connect();
84
+ }
85
+ else if (typeof adapter.connect === 'function') {
86
+ await adapter.connect();
87
+ }
88
+ clearTableLayoutCache(db);
89
+ await ensure();
90
+ clearTableLayoutCache(db);
91
+ };
92
+ const probeTableLayout = async (db) => {
93
+ const [hasTable, hasName, hasMigration, hasScope, hasService, hasStatus, hasAppliedAt, hasCreatedAt,] = await Promise.all([
94
+ schemaHasTable(db, 'migrations'),
95
+ schemaHasColumn(db, 'migrations', 'name'),
96
+ schemaHasColumn(db, 'migrations', 'migration'),
97
+ schemaHasColumn(db, 'migrations', 'scope'),
98
+ schemaHasColumn(db, 'migrations', 'service'),
99
+ schemaHasColumn(db, 'migrations', 'status'),
100
+ schemaHasColumn(db, 'migrations', 'applied_at'),
101
+ schemaHasColumn(db, 'migrations', 'created_at'),
102
+ ]);
103
+ return {
104
+ hasAppliedAt,
105
+ hasCreatedAt,
106
+ hasMigration,
107
+ hasName,
108
+ hasScope,
109
+ hasService,
110
+ hasStatus,
111
+ hasTable,
112
+ };
113
+ };
114
+ const ensureProbeTableExists = async (db, probe, allowEnsure) => {
115
+ if (probe.hasTable || !allowEnsure)
116
+ return null;
117
+ await ensureTrackingTable(db);
118
+ return resolveTableLayout(db, false);
119
+ };
120
+ const assertProbeHasIdentityColumns = (probe) => {
121
+ if (probe.hasName || probe.hasMigration)
122
+ return;
123
+ throw ErrorFactory.createCliError('The migrations table is missing both `name` and `migration` columns. Update the tracking table before running migrations.');
124
+ };
125
+ const toTableLayout = (probe) => {
126
+ return {
127
+ hasAppliedAt: probe.hasAppliedAt,
128
+ hasCreatedAt: probe.hasCreatedAt,
129
+ hasMigration: probe.hasMigration,
130
+ hasName: probe.hasName,
131
+ hasScope: probe.hasScope,
132
+ hasService: probe.hasService,
133
+ hasStatus: probe.hasStatus,
134
+ requiresCompatibilityMode: probe.hasMigration ||
135
+ !probe.hasName ||
136
+ !probe.hasScope ||
137
+ !probe.hasService ||
138
+ !probe.hasStatus,
139
+ };
140
+ };
141
+ const loadTableLayout = async (db, allowEnsure) => {
142
+ if (typeof db.query !== 'function')
143
+ return DEFAULT_LAYOUT;
144
+ const probe = await probeTableLayout(db);
145
+ const ensuredLayout = await ensureProbeTableExists(db, probe, allowEnsure);
146
+ if (ensuredLayout !== null)
147
+ return ensuredLayout;
148
+ assertProbeHasIdentityColumns(probe);
149
+ return toTableLayout(probe);
150
+ };
151
+ const resolveTableLayout = async (db, allowEnsure = true) => {
152
+ const cached = tableLayoutCache.get(db);
153
+ if (cached !== undefined)
154
+ return cached;
155
+ const layoutPromise = loadTableLayout(db, allowEnsure);
156
+ tableLayoutCache.set(db, layoutPromise);
157
+ return layoutPromise.catch((error) => {
158
+ if (tableLayoutCache.get(db) === layoutPromise) {
159
+ clearTableLayoutCache(db);
160
+ }
161
+ throw error;
162
+ });
163
+ };
164
+ const assertCompatibleTrackingTarget = (layout, scope, service) => {
165
+ if ((layout.hasScope && layout.hasService) || isDefaultTrackingTarget(scope, service))
166
+ return;
167
+ throw ErrorFactory.createCliError('The existing migrations table uses the legacy schema and does not support scoped/service-specific migration tracking yet.');
168
+ };
169
+ const buildLegacyIdentity = (layout, name, scope, service) => {
170
+ const conditions = [];
171
+ const params = [];
172
+ if (layout.hasName && layout.hasMigration) {
173
+ conditions.push('(name = ? OR migration = ?)');
174
+ params.push(name, name);
175
+ }
176
+ else if (layout.hasName) {
177
+ conditions.push('name = ?');
178
+ params.push(name);
179
+ }
180
+ else {
181
+ conditions.push('migration = ?');
182
+ params.push(name);
183
+ }
184
+ if (layout.hasScope) {
185
+ conditions.push('scope = ?');
186
+ params.push(scope);
187
+ }
188
+ if (layout.hasService) {
189
+ conditions.push('service = ?');
190
+ params.push(service);
191
+ }
192
+ return { params, sql: conditions.join(' AND ') };
193
+ };
194
+ const normalizeLegacyName = (row) => {
195
+ if (typeof row['name'] === 'string' && row['name'].length > 0)
196
+ return row['name'];
197
+ if (typeof row['migration'] === 'string' && row['migration'].length > 0)
198
+ return row['migration'];
199
+ return '';
200
+ };
201
+ const getLegacyBatch = (row) => {
202
+ const value = row['batch'];
203
+ return typeof value === 'number' ? value : Number(value);
204
+ };
205
+ const getLegacyAppliedAt = (row) => {
206
+ return typeof row['applied_at'] === 'string' ? row['applied_at'] : null;
207
+ };
208
+ const getLegacyAppliedRows = async (db, layout, scope, service) => {
209
+ const normalizedService = toSafeService(service);
210
+ assertCompatibleTrackingTarget(layout, scope, normalizedService);
211
+ const selectColumns = [
212
+ ...(layout.hasName ? ['name'] : []),
213
+ ...(layout.hasMigration ? ['migration'] : []),
214
+ 'batch',
215
+ ...(layout.hasAppliedAt ? ['applied_at'] : []),
216
+ ];
217
+ const conditions = [];
218
+ const params = [];
219
+ if (layout.hasStatus) {
220
+ conditions.push('status = ?');
221
+ params.push('completed');
222
+ }
223
+ if (layout.hasScope) {
224
+ conditions.push('scope = ?');
225
+ params.push(scope);
226
+ }
227
+ if (layout.hasService) {
228
+ conditions.push('service = ?');
229
+ params.push(normalizedService);
230
+ }
231
+ const whereClause = conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : '';
232
+ return (await db.query(`SELECT ${selectColumns.join(', ')} FROM migrations${whereClause}`, params, true));
233
+ };
234
+ const findLegacyMigrationRecord = async (db, layout, params) => {
235
+ const identity = buildLegacyIdentity(layout, params.name, params.scope, params.service);
236
+ const existing = (await db.query(`SELECT id FROM migrations WHERE ${identity.sql} LIMIT 1`, identity.params, true));
237
+ return existing.length > 0;
238
+ };
239
+ const updateLegacyRunningRecord = async (db, layout, params) => {
240
+ const identity = buildLegacyIdentity(layout, params.name, params.scope, params.service);
241
+ const assignments = ['batch = ?'];
242
+ const updateParams = [params.batch];
243
+ if (layout.hasAppliedAt) {
244
+ assignments.push('applied_at = ?');
245
+ updateParams.push(null);
246
+ }
247
+ await db.execute(`UPDATE migrations SET ${assignments.join(', ')} WHERE ${identity.sql}`, [
248
+ ...updateParams,
249
+ ...identity.params,
250
+ ]);
251
+ };
252
+ const buildLegacyInsertRunningPayload = (layout, params) => {
253
+ return {
254
+ columns: [
255
+ ...(layout.hasName ? ['name'] : []),
256
+ ...(layout.hasMigration ? ['migration'] : []),
257
+ ...(layout.hasScope ? ['scope'] : []),
258
+ ...(layout.hasService ? ['service'] : []),
259
+ 'batch',
260
+ ...(layout.hasStatus ? ['status'] : []),
261
+ ...(layout.hasAppliedAt ? ['applied_at'] : []),
262
+ ...(layout.hasCreatedAt ? ['created_at'] : []),
263
+ ],
264
+ values: [
265
+ ...(layout.hasName ? [params.name] : []),
266
+ ...(layout.hasMigration ? [params.name] : []),
267
+ ...(layout.hasScope ? [params.scope] : []),
268
+ ...(layout.hasService ? [params.service] : []),
269
+ params.batch,
270
+ ...(layout.hasStatus ? ['running'] : []),
271
+ ...(layout.hasAppliedAt ? [null] : []),
272
+ ...(layout.hasCreatedAt ? [nowIso()] : []),
273
+ ],
274
+ };
275
+ };
276
+ const insertLegacyRunningRecord = async (db, layout, params) => {
277
+ const payload = buildLegacyInsertRunningPayload(layout, params);
278
+ await db.execute(`INSERT INTO migrations (${payload.columns.join(', ')}) VALUES (${payload.columns.map(() => '?').join(', ')})`, payload.values);
279
+ };
14
280
  const assertDbSupportsMigrations = (db) => {
15
281
  const t = db.getType();
16
282
  if (t === 'd1') {
@@ -42,22 +308,22 @@ const requireMigrationsTableSupport = (adapter) => {
42
308
  };
43
309
  export const MigrationStore = Object.freeze({
44
310
  async ensureTable(db) {
45
- assertDbSupportsMigrations(db);
46
- const adapter = db.getAdapterInstance(false);
47
- const ensure = requireMigrationsTableSupport(adapter);
48
- // getAdapterInstance(false) returns a raw adapter without going through Database.query()
49
- // which auto-connects; ensure we're connected before creating the migrations table.
50
- if (typeof db.connect === 'function') {
51
- await db.connect();
52
- }
53
- else if (typeof adapter.connect === 'function') {
54
- await adapter.connect();
55
- }
56
- await ensure();
311
+ await ensureTrackingTable(db);
57
312
  },
58
313
  async getLastCompletedBatch(db, scope = 'global', service = '') {
59
314
  assertDbSupportsMigrations(db);
315
+ const layout = await resolveTableLayout(db);
60
316
  const normalizedService = toSafeService(service);
317
+ if (layout.requiresCompatibilityMode) {
318
+ const rows = await getLegacyAppliedRows(db, layout, scope, normalizedService);
319
+ let maxBatch = 0;
320
+ for (const row of rows) {
321
+ const batch = getLegacyBatch(row);
322
+ if (Number.isFinite(batch) && batch > maxBatch)
323
+ maxBatch = batch;
324
+ }
325
+ return maxBatch;
326
+ }
61
327
  const row = await QueryBuilder.create('migrations', db)
62
328
  .max('batch', 'max_batch')
63
329
  .where('status', '=', 'completed')
@@ -70,6 +336,28 @@ export const MigrationStore = Object.freeze({
70
336
  async getAppliedMap(db, scope, service) {
71
337
  assertDbSupportsMigrations(db);
72
338
  const normalizedService = toSafeService(service);
339
+ const layout = await resolveTableLayout(db);
340
+ if (layout.requiresCompatibilityMode) {
341
+ const rows = await getLegacyAppliedRows(db, layout, scope, normalizedService);
342
+ const map = new Map();
343
+ for (const row of rows) {
344
+ const name = normalizeLegacyName(row);
345
+ const batch = getLegacyBatch(row);
346
+ if (name === '' || !Number.isFinite(batch))
347
+ continue;
348
+ map.set(name, {
349
+ name,
350
+ scope: layout.hasScope ? scope : 'global',
351
+ service: layout.hasService ? normalizedService : '',
352
+ batch,
353
+ status: typeof row['status'] === 'string'
354
+ ? row['status']
355
+ : 'completed',
356
+ appliedAt: getLegacyAppliedAt(row),
357
+ });
358
+ }
359
+ return map;
360
+ }
73
361
  const rows = await QueryBuilder.create('migrations', db)
74
362
  .select('name', 'scope', 'service', 'batch', 'status')
75
363
  .selectAs('applied_at', 'appliedAt')
@@ -90,6 +378,22 @@ export const MigrationStore = Object.freeze({
90
378
  async insertRunning(db, params) {
91
379
  assertDbSupportsMigrations(db);
92
380
  const normalizedService = toSafeService(params.service);
381
+ const layout = await resolveTableLayout(db);
382
+ if (layout.requiresCompatibilityMode) {
383
+ assertCompatibleTrackingTarget(layout, params.scope, normalizedService);
384
+ const legacyParams = {
385
+ name: params.name,
386
+ scope: params.scope,
387
+ service: normalizedService,
388
+ batch: params.batch,
389
+ };
390
+ if (await findLegacyMigrationRecord(db, layout, legacyParams)) {
391
+ await updateLegacyRunningRecord(db, layout, legacyParams);
392
+ return;
393
+ }
394
+ await insertLegacyRunningRecord(db, layout, legacyParams);
395
+ return;
396
+ }
93
397
  const existing = await QueryBuilder.create('migrations', db)
94
398
  .select('id')
95
399
  .where('name', '=', params.name)
@@ -122,10 +426,37 @@ export const MigrationStore = Object.freeze({
122
426
  },
123
427
  async markStatus(db, params) {
124
428
  assertDbSupportsMigrations(db);
429
+ const normalizedService = toSafeService(params.service);
430
+ const layout = await resolveTableLayout(db);
431
+ if (layout.requiresCompatibilityMode) {
432
+ assertCompatibleTrackingTarget(layout, params.scope, normalizedService);
433
+ const identity = buildLegacyIdentity(layout, params.name, params.scope, normalizedService);
434
+ if (!layout.hasStatus && params.status === 'failed') {
435
+ await db.execute(`DELETE FROM migrations WHERE ${identity.sql}`, identity.params);
436
+ return;
437
+ }
438
+ const assignments = [];
439
+ const updateParams = [];
440
+ if (layout.hasStatus) {
441
+ assignments.push('status = ?');
442
+ updateParams.push(params.status);
443
+ }
444
+ if (params.appliedAt !== undefined && layout.hasAppliedAt) {
445
+ assignments.push('applied_at = ?');
446
+ updateParams.push(params.appliedAt);
447
+ }
448
+ if (assignments.length === 0)
449
+ return;
450
+ await db.execute(`UPDATE migrations SET ${assignments.join(', ')} WHERE ${identity.sql}`, [
451
+ ...updateParams,
452
+ ...identity.params,
453
+ ]);
454
+ return;
455
+ }
125
456
  const builder = QueryBuilder.create('migrations', db)
126
457
  .where('name', '=', params.name)
127
458
  .andWhere('scope', '=', params.scope)
128
- .andWhere('service', '=', toSafeService(params.service));
459
+ .andWhere('service', '=', normalizedService);
129
460
  if (params.appliedAt !== undefined) {
130
461
  await builder.update({ status: params.status, applied_at: params.appliedAt });
131
462
  return;
@@ -134,11 +465,30 @@ export const MigrationStore = Object.freeze({
134
465
  },
135
466
  async listCompletedInBatchesGte(db, params) {
136
467
  assertDbSupportsMigrations(db);
468
+ const normalizedService = toSafeService(params.service);
469
+ const layout = await resolveTableLayout(db);
470
+ if (layout.requiresCompatibilityMode) {
471
+ const rows = await getLegacyAppliedRows(db, layout, params.scope, normalizedService);
472
+ const out = [];
473
+ for (const row of rows) {
474
+ const name = normalizeLegacyName(row);
475
+ const batch = getLegacyBatch(row);
476
+ if (name === '' || !Number.isFinite(batch) || batch < params.minBatch)
477
+ continue;
478
+ out.push({ name, batch });
479
+ }
480
+ out.sort((left, right) => {
481
+ if (left.batch !== right.batch)
482
+ return right.batch - left.batch;
483
+ return right.name.localeCompare(left.name);
484
+ });
485
+ return out;
486
+ }
137
487
  const rows = await QueryBuilder.create('migrations', db)
138
488
  .select('name', 'batch')
139
489
  .where('status', '=', 'completed')
140
490
  .andWhere('scope', '=', params.scope)
141
- .andWhere('service', '=', toSafeService(params.service))
491
+ .andWhere('service', '=', normalizedService)
142
492
  .andWhere('batch', '>=', params.minBatch)
143
493
  .orderBy('batch', 'DESC')
144
494
  .orderBy('id', 'DESC')
@@ -157,11 +507,20 @@ export const MigrationStore = Object.freeze({
157
507
  },
158
508
  async listAllCompletedNames(db, params) {
159
509
  assertDbSupportsMigrations(db);
510
+ const normalizedService = toSafeService(params.service);
511
+ const layout = await resolveTableLayout(db);
512
+ if (layout.requiresCompatibilityMode) {
513
+ const rows = await getLegacyAppliedRows(db, layout, params.scope, normalizedService);
514
+ return rows
515
+ .map(normalizeLegacyName)
516
+ .filter((name) => name.length > 0)
517
+ .sort((left, right) => right.localeCompare(left));
518
+ }
160
519
  const rows = await QueryBuilder.create('migrations', db)
161
520
  .select('name')
162
521
  .where('status', '=', 'completed')
163
522
  .andWhere('scope', '=', params.scope)
164
- .andWhere('service', '=', toSafeService(params.service))
523
+ .andWhere('service', '=', normalizedService)
165
524
  .orderBy('batch', 'DESC')
166
525
  .orderBy('id', 'DESC')
167
526
  .get();
@@ -169,10 +528,18 @@ export const MigrationStore = Object.freeze({
169
528
  },
170
529
  async deleteRecord(db, params) {
171
530
  assertDbSupportsMigrations(db);
531
+ const normalizedService = toSafeService(params.service);
532
+ const layout = await resolveTableLayout(db);
533
+ if (layout.requiresCompatibilityMode) {
534
+ assertCompatibleTrackingTarget(layout, params.scope, normalizedService);
535
+ const identity = buildLegacyIdentity(layout, params.name, params.scope, normalizedService);
536
+ await db.execute(`DELETE FROM migrations WHERE ${identity.sql}`, identity.params);
537
+ return;
538
+ }
172
539
  await QueryBuilder.create('migrations', db)
173
540
  .where('name', '=', params.name)
174
541
  .andWhere('scope', '=', params.scope)
175
- .andWhere('service', '=', toSafeService(params.service))
542
+ .andWhere('service', '=', normalizedService)
176
543
  .delete();
177
544
  },
178
545
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ZintrustD1Proxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/d1/ZintrustD1Proxy.ts"],"names":[],"mappings":"AAWA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;CACf,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,mBAAmB,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5C,GAAG,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAC/C,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AA6QF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ZintrustD1Proxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/d1/ZintrustD1Proxy.ts"],"names":[],"mappings":"AASA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;CACf,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,mBAAmB,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5C,GAAG,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAC/C,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAyRF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -1,11 +1,12 @@
1
- import { Logger } from '../../config/logger.js';
2
- import { isArray, isObject, isString } from '../../helper/index.js';
3
1
  import { getEnvInt, json, normalizeBindingName, readAndVerifyJson, toErrorResponse, } from '../CloudflareProxyShared.js';
4
2
  import { RequestValidator } from '../RequestValidator.js';
5
3
  const DEFAULT_SIGNING_WINDOW_MS = 60_000;
6
4
  const DEFAULT_MAX_BODY_BYTES = 128 * 1024;
7
5
  const DEFAULT_MAX_SQL_BYTES = 32 * 1024;
8
6
  const DEFAULT_MAX_PARAMS = 256;
7
+ const isRecord = (value) => typeof value === 'object' && value !== null;
8
+ const isString = (value) => typeof value === 'string';
9
+ const isArray = (value) => Array.isArray(value);
9
10
  const isDebugEnabled = (env) => {
10
11
  const raw = env.ZT_PROXY_DEBUG;
11
12
  if (!isString(raw))
@@ -28,10 +29,16 @@ const safeErrorMessage = (error) => {
28
29
  const logProxyError = (env, context, error) => {
29
30
  if (!isDebugEnabled(env))
30
31
  return;
31
- Logger.error('[ZintrustD1Proxy] error', {
32
- ...context,
33
- message: safeErrorMessage(error).slice(0, 800),
34
- });
32
+ try {
33
+ // eslint-disable-next-line no-console
34
+ console.error('[ZintrustD1Proxy] error', {
35
+ ...context,
36
+ message: safeErrorMessage(error).slice(0, 800),
37
+ });
38
+ }
39
+ catch {
40
+ // ignore logging failures in Workers proxy mode
41
+ }
35
42
  };
36
43
  const resolveD1Binding = (env) => {
37
44
  const candidates = ['DB', 'zintrust_db', normalizeBindingName(env.D1_BINDING)].filter((value, index, values) => isString(value) && value.trim() !== '' && values.indexOf(value) === index);
@@ -50,7 +57,7 @@ const loadStatements = (env) => {
50
57
  return null;
51
58
  try {
52
59
  const parsed = JSON.parse(raw);
53
- if (!isObject(parsed))
60
+ if (!isRecord(parsed))
54
61
  return null;
55
62
  return parsed;
56
63
  }
@@ -80,7 +87,7 @@ const toD1ExceptionResponse = (error) => {
80
87
  return toErrorResponse(500, 'D1_ERROR', message);
81
88
  };
82
89
  const parseSqlPayload = (payload) => {
83
- if (!isObject(payload)) {
90
+ if (!isRecord(payload)) {
84
91
  return { ok: false, response: toErrorResponse(400, 'VALIDATION_ERROR', 'Invalid body') };
85
92
  }
86
93
  const sql = payload['sql'];
@@ -181,7 +188,7 @@ const handleExec = async (request, env) => {
181
188
  }
182
189
  };
183
190
  const parseStatementPayload = (payload) => {
184
- if (!isObject(payload)) {
191
+ if (!isRecord(payload)) {
185
192
  return { ok: false, response: toErrorResponse(400, 'VALIDATION_ERROR', 'Invalid body') };
186
193
  }
187
194
  const statementId = payload['statementId'];
@@ -3,13 +3,14 @@ export declare const StartupConfigFile: {
3
3
  readonly Cache: "config/cache.ts";
4
4
  readonly Database: "config/database.ts";
5
5
  readonly Mail: "config/mail.ts";
6
+ readonly Trace: "config/trace.ts";
6
7
  readonly Middleware: "config/middleware.ts";
7
8
  readonly Notification: "config/notification.ts";
8
9
  readonly Queue: "config/queue.ts";
9
10
  readonly Storage: "config/storage.ts";
10
11
  readonly Workers: "config/workers.ts";
11
12
  };
12
- export type StartupConfigFileTypes = typeof StartupConfigFile.Broadcast | typeof StartupConfigFile.Cache | typeof StartupConfigFile.Database | typeof StartupConfigFile.Mail | typeof StartupConfigFile.Middleware | typeof StartupConfigFile.Notification | typeof StartupConfigFile.Queue | typeof StartupConfigFile.Storage | typeof StartupConfigFile.Workers;
13
+ export type StartupConfigFileTypes = typeof StartupConfigFile.Broadcast | typeof StartupConfigFile.Cache | typeof StartupConfigFile.Database | typeof StartupConfigFile.Mail | typeof StartupConfigFile.Trace | typeof StartupConfigFile.Middleware | typeof StartupConfigFile.Notification | typeof StartupConfigFile.Queue | typeof StartupConfigFile.Storage | typeof StartupConfigFile.Workers;
13
14
  export declare const StartupConfigFileRegistry: Readonly<{
14
15
  preload(files: readonly StartupConfigFileTypes[]): Promise<void>;
15
16
  isPreloaded(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"StartupConfigFileRegistry.d.ts","sourceRoot":"","sources":["../../../src/runtime/StartupConfigFileRegistry.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB;;;;;;;;;;CAUpB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAC9B,OAAO,iBAAiB,CAAC,SAAS,GAClC,OAAO,iBAAiB,CAAC,KAAK,GAC9B,OAAO,iBAAiB,CAAC,QAAQ,GACjC,OAAO,iBAAiB,CAAC,IAAI,GAC7B,OAAO,iBAAiB,CAAC,UAAU,GACnC,OAAO,iBAAiB,CAAC,YAAY,GACrC,OAAO,iBAAiB,CAAC,KAAK,GAC9B,OAAO,iBAAiB,CAAC,OAAO,GAChC,OAAO,iBAAiB,CAAC,OAAO,CAAC;AAiDrC,eAAO,MAAM,yBAAyB;mBACf,SAAS,sBAAsB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;mBAcvD,OAAO;QAIlB,CAAC,QAAQ,sBAAsB,GAAG,CAAC,GAAG,SAAS;cAIzC,sBAAsB,GAAG,OAAO;IAI1C,+BAA+B;aACtB,IAAI;EAIb,CAAC;AAEH,eAAe,yBAAyB,CAAC"}
1
+ {"version":3,"file":"StartupConfigFileRegistry.d.ts","sourceRoot":"","sources":["../../../src/runtime/StartupConfigFileRegistry.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB;;;;;;;;;;;CAWpB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAC9B,OAAO,iBAAiB,CAAC,SAAS,GAClC,OAAO,iBAAiB,CAAC,KAAK,GAC9B,OAAO,iBAAiB,CAAC,QAAQ,GACjC,OAAO,iBAAiB,CAAC,IAAI,GAC7B,OAAO,iBAAiB,CAAC,KAAK,GAC9B,OAAO,iBAAiB,CAAC,UAAU,GACnC,OAAO,iBAAiB,CAAC,YAAY,GACrC,OAAO,iBAAiB,CAAC,KAAK,GAC9B,OAAO,iBAAiB,CAAC,OAAO,GAChC,OAAO,iBAAiB,CAAC,OAAO,CAAC;AAiDrC,eAAO,MAAM,yBAAyB;mBACf,SAAS,sBAAsB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;mBAcvD,OAAO;QAIlB,CAAC,QAAQ,sBAAsB,GAAG,CAAC,GAAG,SAAS;cAIzC,sBAAsB,GAAG,OAAO;IAI1C,+BAA+B;aACtB,IAAI;EAIb,CAAC;AAEH,eAAe,yBAAyB,CAAC"}
@@ -8,6 +8,7 @@ export const StartupConfigFile = {
8
8
  Cache: 'config/cache.ts',
9
9
  Database: 'config/database.ts',
10
10
  Mail: 'config/mail.ts',
11
+ Trace: 'config/trace.ts',
11
12
  Middleware: 'config/middleware.ts',
12
13
  Notification: 'config/notification.ts',
13
14
  Queue: 'config/queue.ts',
@@ -10,10 +10,20 @@ type TraceStorageApi = {
10
10
  export declare const isAvailable: () => boolean;
11
11
  export declare const TraceConfig: TraceConfigApi;
12
12
  export declare const TraceStorage: TraceStorageApi;
13
+ export declare const registerTraceDashboard: (router: unknown, options?: {
14
+ basePath?: string;
15
+ middleware?: ReadonlyArray<string>;
16
+ }) => void;
13
17
  export declare const registerTraceRoutes: (router: unknown, storage: unknown, options?: {
14
18
  basePath?: string;
15
19
  middleware?: ReadonlyArray<string>;
16
20
  }) => void;
21
+ export declare const captureTraceException: (error: unknown, context?: {
22
+ batchId?: string;
23
+ hostname?: string;
24
+ path?: string;
25
+ userId?: string;
26
+ }) => void;
17
27
  export declare const ensureSystemTraceRegistered: () => Promise<void>;
18
28
  export {};
19
29
  //# sourceMappingURL=trace-runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trace-runtime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/plugins/trace-runtime.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC;CACtC,CAAC;AA8BF,eAAO,MAAM,WAAW,QAAO,OAA0C,CAAC;AAE1E,eAAO,MAAM,WAAW,EAAE,cAAsE,CAAC;AAEjG,eAAO,MAAM,YAAY,EAAE,eAC8B,CAAC;AAE1D,eAAO,MAAM,mBAAmB,WA/BpB,OAAO,WACN,OAAO,YACN;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,KAChE,IA6BgE,CAAC;AAExE,eAAO,MAAM,2BAA2B,QAAa,OAAO,CAAC,IAAI,CAGhE,CAAC"}
1
+ {"version":3,"file":"trace-runtime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/plugins/trace-runtime.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC;CACtC,CAAC;AAwEF,eAAO,MAAM,WAAW,QAAO,OAA0C,CAAC;AAE1E,eAAO,MAAM,WAAW,EAAE,cAIxB,CAAC;AAEH,eAAO,MAAM,YAAY,EAAE,eAIzB,CAAC;AAEH,eAAO,MAAM,sBAAsB,GACjC,QAAQ,OAAO,EACf,UAAU;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,KAClE,IAEF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,OAAO,EACf,SAAS,OAAO,EAChB,UAAU;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,KAClE,IAEF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,UAAU;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAChF,IASF,CAAC;AAEF,eAAO,MAAM,2BAA2B,QAAa,OAAO,CAAC,IAAI,CAIhE,CAAC"}