@zintrust/core 0.7.0 → 0.7.2

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 (61) hide show
  1. package/package.json +7 -5
  2. package/src/auth/LoginFlow.d.ts +65 -0
  3. package/src/auth/LoginFlow.d.ts.map +1 -0
  4. package/src/auth/LoginFlow.js +352 -0
  5. package/src/cache/drivers/KVRemoteDriver.d.ts.map +1 -1
  6. package/src/cache/drivers/KVRemoteDriver.js +9 -3
  7. package/src/cli/commands/ScheduleListCommand.d.ts.map +1 -1
  8. package/src/cli/commands/ScheduleListCommand.js +3 -0
  9. package/src/cli/commands/ScheduleRunCommand.d.ts.map +1 -1
  10. package/src/cli/commands/ScheduleRunCommand.js +3 -0
  11. package/src/cli/commands/ScheduleStartCommand.d.ts.map +1 -1
  12. package/src/cli/commands/ScheduleStartCommand.js +3 -0
  13. package/src/cli/commands/schedule/ScheduleCliSupport.d.ts +1 -0
  14. package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -1
  15. package/src/cli/commands/schedule/ScheduleCliSupport.js +116 -6
  16. package/src/cli/scaffolding/GovernanceScaffolder.d.ts.map +1 -1
  17. package/src/cli/scaffolding/GovernanceScaffolder.js +22 -3
  18. package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
  19. package/src/cli/scaffolding/MigrationGenerator.js +2 -1
  20. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  21. package/src/cli/scaffolding/ProjectScaffolder.js +79 -8
  22. package/src/cli/scaffolding/ScaffoldingVersionUtils.js +1 -1
  23. package/src/common/ContextLoader.d.ts +27 -0
  24. package/src/common/ContextLoader.d.ts.map +1 -0
  25. package/src/common/ContextLoader.js +187 -0
  26. package/src/config/logger.d.ts +2 -0
  27. package/src/config/logger.d.ts.map +1 -1
  28. package/src/config/logger.js +12 -0
  29. package/src/index.d.ts +7 -0
  30. package/src/index.d.ts.map +1 -1
  31. package/src/index.js +7 -3
  32. package/src/orm/Model.d.ts.map +1 -1
  33. package/src/orm/Model.js +1 -1
  34. package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
  35. package/src/orm/adapters/D1Adapter.js +1 -1
  36. package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
  37. package/src/orm/adapters/MySQLAdapter.js +1 -1
  38. package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
  39. package/src/orm/adapters/MySQLProxyAdapter.js +11 -9
  40. package/src/orm/adapters/PostgreSQLAdapter.js +1 -1
  41. package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
  42. package/src/orm/adapters/SQLServerAdapter.js +1 -1
  43. package/src/orm/adapters/SQLiteAdapter.js +1 -1
  44. package/src/proxy/ProxyServerUtils.d.ts.map +1 -1
  45. package/src/proxy/ProxyServerUtils.js +15 -11
  46. package/src/security/SecurePayload.d.ts +38 -0
  47. package/src/security/SecurePayload.d.ts.map +1 -0
  48. package/src/security/SecurePayload.js +214 -0
  49. package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +132 -46
  50. package/src/templates/project/basic/package.json.tpl +5 -0
  51. package/src/tools/notification/Composer.d.ts +40 -0
  52. package/src/tools/notification/Composer.d.ts.map +1 -0
  53. package/src/tools/notification/Composer.js +140 -0
  54. package/src/tools/notification/Notification.d.ts +6 -0
  55. package/src/tools/notification/Notification.d.ts.map +1 -1
  56. package/src/tools/notification/Notification.js +7 -0
  57. package/src/tools/queue/AdvancedQueue.js +15 -0
  58. package/src/tools/queue/Queue.d.ts +1 -0
  59. package/src/tools/queue/Queue.d.ts.map +1 -1
  60. package/src/types/Queue.d.ts +1 -0
  61. package/src/types/Queue.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -57,19 +57,21 @@
57
57
  "./package.json": "./package.json"
58
58
  },
59
59
  "dependencies": {
60
- "@cloudflare/containers": "^0.3.0",
60
+ "@cloudflare/containers": "^0.3.2",
61
61
  "bcryptjs": "^3.0.3",
62
- "bullmq": "^5.73.4",
62
+ "bullmq": "^5.74.1",
63
63
  "chalk": "^5.6.2",
64
64
  "commander": "^14.0.3",
65
65
  "inquirer": "^13.4.1",
66
66
  "jsonwebtoken": "^9.0.3",
67
- "mysql2": "^3.22.0",
68
- "pg": "^8.20.0"
67
+ "mysql2": "^3.22.1",
68
+ "pg": "^8.20.0",
69
+ "tsx": "^4.21.0"
69
70
  },
70
71
  "overrides": {
71
72
  "ajv": "^8.18.0",
72
73
  "axios": "^1.15.0",
74
+ "@eslint/plugin-kit": "^0.7.1",
73
75
  "follow-redirects": "^1.16.0",
74
76
  "@tootallnate/once": "^3.0.1",
75
77
  "node-forge": "^1.4.0",
@@ -0,0 +1,65 @@
1
+ import { type JwtPayload } from '../security/JwtManager';
2
+ export type LoginFlowStage = 'identify' | 'verify' | 'issue' | 'audit';
3
+ export type LoginFlowError = Error & {
4
+ stage: LoginFlowStage;
5
+ details?: unknown;
6
+ };
7
+ export type LoginFlowIdentity = Record<string, unknown> | null;
8
+ export type LoginFlowVerifiedRecord = {
9
+ user?: unknown;
10
+ subject?: string;
11
+ claims?: JwtPayload;
12
+ metadata?: Record<string, unknown>;
13
+ };
14
+ export type LoginFlowResult = {
15
+ identity: LoginFlowIdentity;
16
+ verified: LoginFlowVerifiedRecord;
17
+ issued?: unknown;
18
+ };
19
+ export type LoginFlowProvider<TContext = unknown> = {
20
+ identify: (input: unknown, context: TContext) => Promise<LoginFlowIdentity>;
21
+ verify: (identity: LoginFlowIdentity, input: unknown, context: TContext) => Promise<LoginFlowVerifiedRecord>;
22
+ };
23
+ export type LoginFlowIssuerInput<TContext = unknown> = {
24
+ verified: LoginFlowVerifiedRecord;
25
+ context: TContext;
26
+ };
27
+ export type LoginFlowIssuer<TContext = unknown> = (input: LoginFlowIssuerInput<TContext>) => Promise<unknown>;
28
+ export type LoginFlowAuditEvent<TContext = unknown> = {
29
+ status: 'success' | 'failed';
30
+ stage?: LoginFlowStage;
31
+ provider: string;
32
+ issuer?: string;
33
+ identity?: LoginFlowIdentity;
34
+ verified?: LoginFlowVerifiedRecord;
35
+ issued?: unknown;
36
+ error?: unknown;
37
+ context: TContext;
38
+ };
39
+ export type LoginFlowAuditor<TContext = unknown> = (event: LoginFlowAuditEvent<TContext>) => Promise<void>;
40
+ export type LoginFlowCreateOptions<TContext = unknown> = {
41
+ provider: string | LoginFlowProvider<TContext>;
42
+ context: TContext;
43
+ };
44
+ export type LoginFlowBuilder<TContext = unknown> = {
45
+ identify: (input: unknown) => LoginFlowBuilder<TContext>;
46
+ verify: (input: unknown) => LoginFlowBuilder<TContext>;
47
+ issue: (issuer: string | LoginFlowIssuer<TContext>) => LoginFlowBuilder<TContext>;
48
+ audit: (auditor?: string | LoginFlowAuditor<TContext>) => LoginFlowBuilder<TContext>;
49
+ run: () => Promise<LoginFlowResult>;
50
+ };
51
+ export type LoginFlowNamespace = {
52
+ create: <TContext = unknown>(options: LoginFlowCreateOptions<TContext>) => LoginFlowBuilder<TContext>;
53
+ registerProvider: <TContext = unknown>(name: string, provider: LoginFlowProvider<TContext>) => void;
54
+ unregisterProvider: (name: string) => void;
55
+ hasProvider: (name: string) => boolean;
56
+ registerIssuer: <TContext = unknown>(name: string, issuer: LoginFlowIssuer<TContext>) => void;
57
+ unregisterIssuer: (name: string) => void;
58
+ hasIssuer: (name: string) => boolean;
59
+ registerAuditor: <TContext = unknown>(name: string, auditor: LoginFlowAuditor<TContext>) => void;
60
+ unregisterAuditor: (name: string) => void;
61
+ hasAuditor: (name: string) => boolean;
62
+ clearRegistrations: () => void;
63
+ };
64
+ export declare const LoginFlow: LoginFlowNamespace;
65
+ //# sourceMappingURL=LoginFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginFlow.d.ts","sourceRoot":"","sources":["../../../src/auth/LoginFlow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,352 @@
1
+ import { SystemTraceBridge } from '../trace/SystemTraceBridge.js';
2
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
3
+ import { isFunction, isNonEmptyString, isObject } from '../helper/index.js';
4
+ import { JwtManager } from '../security/JwtManager.js';
5
+ const providerRegistry = new Map();
6
+ const issuerRegistry = new Map();
7
+ const auditorRegistry = new Map();
8
+ const createLoginFlowError = (stage, message, details) => {
9
+ return Object.assign(ErrorFactory.createValidationError(message, details), {
10
+ stage,
11
+ details,
12
+ });
13
+ };
14
+ const isLoginFlowError = (value) => {
15
+ if (!isObject(value)) {
16
+ return false;
17
+ }
18
+ return isNonEmptyString(value['stage']);
19
+ };
20
+ const getNamedProvider = (name) => {
21
+ const provider = providerRegistry.get(name);
22
+ if (!provider) {
23
+ throw createLoginFlowError('identify', `LoginFlow provider "${name}" is not registered`, {
24
+ provider: name,
25
+ });
26
+ }
27
+ return provider;
28
+ };
29
+ const getNamedIssuer = (name) => {
30
+ const issuer = issuerRegistry.get(name);
31
+ if (!issuer) {
32
+ throw createLoginFlowError('issue', `LoginFlow issuer "${name}" is not registered`, {
33
+ issuer: name,
34
+ });
35
+ }
36
+ return issuer;
37
+ };
38
+ const getNamedAuditor = (name) => {
39
+ const auditor = auditorRegistry.get(name);
40
+ if (!auditor) {
41
+ throw createLoginFlowError('audit', `LoginFlow auditor "${name}" is not registered`, {
42
+ auditor: name,
43
+ });
44
+ }
45
+ return auditor;
46
+ };
47
+ const resolveProvider = (provider) => {
48
+ if (typeof provider === 'string') {
49
+ return getNamedProvider(provider);
50
+ }
51
+ return provider;
52
+ };
53
+ const resolveProviderName = (provider) => {
54
+ if (typeof provider === 'string') {
55
+ return provider;
56
+ }
57
+ return 'inline';
58
+ };
59
+ const resolveIssuer = (issuer) => {
60
+ if (typeof issuer === 'string') {
61
+ return getNamedIssuer(issuer);
62
+ }
63
+ return issuer;
64
+ };
65
+ const resolveIssuerName = (issuer) => {
66
+ if (typeof issuer === 'string') {
67
+ return issuer;
68
+ }
69
+ return 'inline';
70
+ };
71
+ const resolveAuditor = (auditor) => {
72
+ if (typeof auditor === 'string') {
73
+ return getNamedAuditor(auditor);
74
+ }
75
+ return auditor;
76
+ };
77
+ const normalizeVerifiedRecord = (value) => {
78
+ if (!isObject(value)) {
79
+ throw createLoginFlowError('verify', 'LoginFlow verify() must return an object', { value });
80
+ }
81
+ const record = value;
82
+ if (record.subject !== undefined && !isNonEmptyString(record.subject)) {
83
+ throw createLoginFlowError('verify', 'LoginFlow verify() returned an invalid subject', {
84
+ subject: record.subject,
85
+ });
86
+ }
87
+ if (record.claims !== undefined && !isObject(record.claims)) {
88
+ throw createLoginFlowError('verify', 'LoginFlow verify() returned invalid claims', {
89
+ claims: record.claims,
90
+ });
91
+ }
92
+ return record;
93
+ };
94
+ const createJwtIssuer = async ({ verified, }) => {
95
+ const claims = isObject(verified.claims) ? { ...verified.claims } : {};
96
+ if (isNonEmptyString(verified.subject) && !isNonEmptyString(claims.sub)) {
97
+ claims.sub = verified.subject;
98
+ }
99
+ return JwtManager.signAccessToken(claims);
100
+ };
101
+ const createTraceAuditor = async (event) => {
102
+ const subject = typeof event.verified?.subject === 'string' && event.verified.subject.trim() !== ''
103
+ ? event.verified.subject
104
+ : undefined;
105
+ SystemTraceBridge.emitAuth(event.status === 'success' ? 'login' : 'failed', subject);
106
+ return Promise.resolve();
107
+ };
108
+ const ensureNamedRegistration = (kind, name) => {
109
+ if (!isNonEmptyString(name)) {
110
+ throw createLoginFlowError('identify', `LoginFlow ${kind} name must be a non-empty string`, {
111
+ name,
112
+ kind,
113
+ });
114
+ }
115
+ };
116
+ const ensureProvider = (provider) => {
117
+ if (!isObject(provider) || !isFunction(provider['identify']) || !isFunction(provider['verify'])) {
118
+ throw createLoginFlowError('identify', 'LoginFlow provider must expose identify() and verify()', {
119
+ provider,
120
+ });
121
+ }
122
+ };
123
+ const ensureHandler = (stage, kind, handler) => {
124
+ if (!isFunction(handler)) {
125
+ throw createLoginFlowError(stage, `LoginFlow ${kind} must be a function`, {
126
+ handler,
127
+ });
128
+ }
129
+ };
130
+ const auditFailureIfNeeded = async (auditorTarget, event) => {
131
+ if (auditorTarget === undefined) {
132
+ return;
133
+ }
134
+ const auditor = resolveAuditor(auditorTarget);
135
+ await auditor(event);
136
+ };
137
+ const ensureRequiredInputs = (state) => {
138
+ if (!state.identifySet) {
139
+ throw createLoginFlowError('identify', 'LoginFlow identify() must be called before run()', {
140
+ provider: state.providerName,
141
+ });
142
+ }
143
+ if (!state.verifySet) {
144
+ throw createLoginFlowError('verify', 'LoginFlow verify() must be called before run()', {
145
+ provider: state.providerName,
146
+ });
147
+ }
148
+ };
149
+ const resolveProviderWithAudit = async (state) => {
150
+ try {
151
+ return resolveProvider(state.options.provider);
152
+ }
153
+ catch (error) {
154
+ const wrapped = isLoginFlowError(error)
155
+ ? error
156
+ : createLoginFlowError('identify', 'LoginFlow identify() failed', {
157
+ provider: state.providerName,
158
+ error,
159
+ });
160
+ await auditFailureIfNeeded(state.auditorTarget, {
161
+ status: 'failed',
162
+ stage: 'identify',
163
+ provider: state.providerName,
164
+ context: state.options.context,
165
+ error: wrapped,
166
+ });
167
+ throw wrapped;
168
+ }
169
+ };
170
+ const identifyWithAudit = async (state, provider) => {
171
+ try {
172
+ return await provider.identify(state.identifyInput, state.options.context);
173
+ }
174
+ catch (error) {
175
+ const wrapped = createLoginFlowError('identify', 'LoginFlow identify() failed', {
176
+ provider: state.providerName,
177
+ error,
178
+ });
179
+ await auditFailureIfNeeded(state.auditorTarget, {
180
+ status: 'failed',
181
+ stage: 'identify',
182
+ provider: state.providerName,
183
+ context: state.options.context,
184
+ error: wrapped,
185
+ });
186
+ throw wrapped;
187
+ }
188
+ };
189
+ const verifyWithAudit = async (state, provider, identity) => {
190
+ try {
191
+ return normalizeVerifiedRecord(await provider.verify(identity, state.verifyInput, state.options.context));
192
+ }
193
+ catch (error) {
194
+ const wrapped = isLoginFlowError(error)
195
+ ? error
196
+ : createLoginFlowError('verify', 'LoginFlow verify() failed', {
197
+ provider: state.providerName,
198
+ error,
199
+ });
200
+ await auditFailureIfNeeded(state.auditorTarget, {
201
+ status: 'failed',
202
+ stage: 'verify',
203
+ provider: state.providerName,
204
+ identity,
205
+ context: state.options.context,
206
+ error: wrapped,
207
+ });
208
+ throw wrapped;
209
+ }
210
+ };
211
+ const issueWithAudit = async (state, identity, verified) => {
212
+ if (state.issueTarget === undefined) {
213
+ return undefined;
214
+ }
215
+ const issuer = resolveIssuer(state.issueTarget);
216
+ try {
217
+ return await issuer({ verified, context: state.options.context });
218
+ }
219
+ catch (error) {
220
+ const wrapped = createLoginFlowError('issue', 'LoginFlow issue() failed', {
221
+ provider: state.providerName,
222
+ issuer: state.issueName,
223
+ error,
224
+ });
225
+ await auditFailureIfNeeded(state.auditorTarget, {
226
+ status: 'failed',
227
+ stage: 'issue',
228
+ provider: state.providerName,
229
+ issuer: state.issueName,
230
+ identity,
231
+ verified,
232
+ context: state.options.context,
233
+ error: wrapped,
234
+ });
235
+ throw wrapped;
236
+ }
237
+ };
238
+ const auditSuccess = async (state, identity, verified, issued) => {
239
+ if (state.auditorTarget === undefined) {
240
+ return;
241
+ }
242
+ const auditor = resolveAuditor(state.auditorTarget);
243
+ await auditor({
244
+ status: 'success',
245
+ provider: state.providerName,
246
+ issuer: state.issueName,
247
+ identity,
248
+ verified,
249
+ issued,
250
+ context: state.options.context,
251
+ });
252
+ };
253
+ const runLoginFlow = async (state) => {
254
+ const provider = await resolveProviderWithAudit(state);
255
+ ensureRequiredInputs(state);
256
+ const identity = await identifyWithAudit(state, provider);
257
+ const verified = await verifyWithAudit(state, provider, identity);
258
+ const issued = await issueWithAudit(state, identity, verified);
259
+ await auditSuccess(state, identity, verified, issued);
260
+ return {
261
+ identity,
262
+ verified,
263
+ ...(issued === undefined ? {} : { issued }),
264
+ };
265
+ };
266
+ const createBuilder = (state) => {
267
+ return Object.freeze({
268
+ identify(input) {
269
+ state.identifyInput = input;
270
+ state.identifySet = true;
271
+ return this;
272
+ },
273
+ verify(input) {
274
+ state.verifyInput = input;
275
+ state.verifySet = true;
276
+ return this;
277
+ },
278
+ issue(issuer) {
279
+ state.issueTarget = issuer;
280
+ state.issueName = resolveIssuerName(issuer);
281
+ return this;
282
+ },
283
+ audit(auditor) {
284
+ state.auditorTarget = auditor ?? 'trace';
285
+ return this;
286
+ },
287
+ async run() {
288
+ return runLoginFlow(state);
289
+ },
290
+ });
291
+ };
292
+ const create = (options) => {
293
+ return createBuilder({
294
+ options,
295
+ providerName: resolveProviderName(options.provider),
296
+ identifyInput: undefined,
297
+ verifyInput: undefined,
298
+ issueTarget: undefined,
299
+ issueName: undefined,
300
+ auditorTarget: undefined,
301
+ identifySet: false,
302
+ verifySet: false,
303
+ });
304
+ };
305
+ const registerProvider = (name, provider) => {
306
+ ensureNamedRegistration('provider', name);
307
+ ensureProvider(provider);
308
+ providerRegistry.set(name, provider);
309
+ };
310
+ const unregisterProvider = (name) => {
311
+ providerRegistry.delete(name);
312
+ };
313
+ const hasProvider = (name) => providerRegistry.has(name);
314
+ const registerIssuer = (name, issuer) => {
315
+ ensureNamedRegistration('issuer', name);
316
+ ensureHandler('issue', 'issuer', issuer);
317
+ issuerRegistry.set(name, issuer);
318
+ };
319
+ const unregisterIssuer = (name) => {
320
+ issuerRegistry.delete(name);
321
+ };
322
+ const hasIssuer = (name) => issuerRegistry.has(name);
323
+ const registerAuditor = (name, auditor) => {
324
+ ensureNamedRegistration('auditor', name);
325
+ ensureHandler('audit', 'auditor', auditor);
326
+ auditorRegistry.set(name, auditor);
327
+ };
328
+ const unregisterAuditor = (name) => {
329
+ auditorRegistry.delete(name);
330
+ };
331
+ const hasAuditor = (name) => auditorRegistry.has(name);
332
+ const clearRegistrations = () => {
333
+ providerRegistry.clear();
334
+ issuerRegistry.clear();
335
+ auditorRegistry.clear();
336
+ issuerRegistry.set('jwt', createJwtIssuer);
337
+ auditorRegistry.set('trace', createTraceAuditor);
338
+ };
339
+ clearRegistrations();
340
+ export const LoginFlow = Object.freeze({
341
+ create,
342
+ registerProvider,
343
+ unregisterProvider,
344
+ hasProvider,
345
+ registerIssuer,
346
+ unregisterIssuer,
347
+ hasIssuer,
348
+ registerAuditor,
349
+ unregisterAuditor,
350
+ hasAuditor,
351
+ clearRegistrations,
352
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"KVRemoteDriver.d.ts","sourceRoot":"","sources":["../../../../src/cache/drivers/KVRemoteDriver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAqYtD,eAAO,MAAM,cAAc;kBAtFM,WAAW;EAwF1C,CAAC;AAEH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"KVRemoteDriver.d.ts","sourceRoot":"","sources":["../../../../src/cache/drivers/KVRemoteDriver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA2YtD,eAAO,MAAM,cAAc;kBA5FM,WAAW;EA8F1C,CAAC;AAEH,eAAe,cAAc,CAAC"}
@@ -227,7 +227,9 @@ const createKvRemoteDriver = () => {
227
227
  if (!hasCloudflareApiCreds())
228
228
  throw error;
229
229
  Logger.warn('KV remote proxy GET failed; falling back to Cloudflare KV API', {
230
- error: error instanceof Error ? error.message : String(error),
230
+ ...Logger.withTraceSkipContext({
231
+ error: error instanceof Error ? error.message : String(error),
232
+ }),
231
233
  });
232
234
  return cf.getJson(key);
233
235
  }
@@ -251,7 +253,9 @@ const createKvRemoteDriver = () => {
251
253
  if (!hasCloudflareApiCreds())
252
254
  throw error;
253
255
  Logger.warn('KV remote proxy PUT failed; falling back to Cloudflare KV API', {
254
- error: error instanceof Error ? error.message : String(error),
256
+ ...Logger.withTraceSkipContext({
257
+ error: error instanceof Error ? error.message : String(error),
258
+ }),
255
259
  });
256
260
  await cf.putJson(key, value, ttl);
257
261
  }
@@ -273,7 +277,9 @@ const createKvRemoteDriver = () => {
273
277
  if (!hasCloudflareApiCreds())
274
278
  throw error;
275
279
  Logger.warn('KV remote proxy DELETE failed; falling back to Cloudflare KV API', {
276
- error: error instanceof Error ? error.message : String(error),
280
+ ...Logger.withTraceSkipContext({
281
+ error: error instanceof Error ? error.message : String(error),
282
+ }),
277
283
  });
278
284
  await cf.deleteKey(key);
279
285
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleListCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleListCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA0ErE,eAAO,MAAM,mBAAmB;cACpB,YAAY;EAUtB,CAAC;AAEH,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"ScheduleListCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleListCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8ErE,eAAO,MAAM,mBAAmB;cACpB,YAAY;EAUtB,CAAC;AAEH,eAAe,mBAAmB,CAAC"}
@@ -3,6 +3,9 @@ import { ScheduleCliSupport } from '../commands/schedule/ScheduleCliSupport.js';
3
3
  import { Logger } from '../../config/logger.js';
4
4
  import { SchedulerRuntime } from '../../scheduler/SchedulerRuntime.js';
5
5
  const execute = async (options) => {
6
+ if (await ScheduleCliSupport.ensureProjectSourceContext()) {
7
+ return;
8
+ }
6
9
  try {
7
10
  await ScheduleCliSupport.registerAll();
8
11
  const toIso = (ms) => typeof ms === 'number' && Number.isFinite(ms) ? new Date(ms).toISOString() : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleRunCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleRunCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA0BrE,eAAO,MAAM,kBAAkB;cACnB,YAAY;EAUtB,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ScheduleRunCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleRunCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8BrE,eAAO,MAAM,kBAAkB;cACnB,YAAY;EAUtB,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
@@ -7,6 +7,9 @@ const execute = async (options) => {
7
7
  const name = (options.name ?? '').trim();
8
8
  if (name.length === 0)
9
9
  throw ErrorFactory.createConfigError('--name is required');
10
+ if (await ScheduleCliSupport.ensureProjectSourceContext()) {
11
+ return;
12
+ }
10
13
  try {
11
14
  await ScheduleCliSupport.registerAll();
12
15
  Logger.info('Running schedule once', { name });
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleStartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleStartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA6CrE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAOtB,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"ScheduleStartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleStartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAiDrE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAOtB,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
@@ -18,6 +18,9 @@ const execute = async (_options) => {
18
18
  Logger.info('Schedules are disabled (SCHEDULES_ENABLED=false); exiting');
19
19
  return;
20
20
  }
21
+ if (await ScheduleCliSupport.ensureProjectSourceContext()) {
22
+ return;
23
+ }
21
24
  await ScheduleCliSupport.registerAll();
22
25
  const registeredCount = SchedulerRuntime.list().length;
23
26
  Logger.info('Starting schedules daemon', { registeredCount });
@@ -1,4 +1,5 @@
1
1
  export declare const ScheduleCliSupport: Readonly<{
2
+ ensureProjectSourceContext: () => Promise<boolean>;
2
3
  registerAll(): Promise<void>;
3
4
  shutdownCliResources: () => Promise<void>;
4
5
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleCliSupport.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/schedule/ScheduleCliSupport.ts"],"names":[],"mappings":"AAwDA,eAAO,MAAM,kBAAkB;mBACR,OAAO,CAAC,IAAI,CAAC;gCA1BG,OAAO,CAAC,IAAI,CAAC;EAmClD,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ScheduleCliSupport.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/schedule/ScheduleCliSupport.ts"],"names":[],"mappings":"AAsMA,eAAO,MAAM,kBAAkB;sCA1Ec,OAAO,CAAC,OAAO,CAAC;mBA4EtC,OAAO,CAAC,IAAI,CAAC;gCA3BG,OAAO,CAAC,IAAI,CAAC;EAqClD,CAAC;AAEH,eAAe,kBAAkB,CAAC"}