@shipfox/api-triggers 4.0.0 → 6.0.0

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 (86) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +65 -0
  3. package/README.md +23 -3
  4. package/dist/core/dispatch-integration-event.d.ts +2 -0
  5. package/dist/core/dispatch-integration-event.d.ts.map +1 -1
  6. package/dist/core/dispatch-integration-event.js +9 -5
  7. package/dist/core/dispatch-integration-event.js.map +1 -1
  8. package/dist/core/drain-cron-schedules.d.ts +2 -0
  9. package/dist/core/drain-cron-schedules.d.ts.map +1 -1
  10. package/dist/core/drain-cron-schedules.js +1 -0
  11. package/dist/core/drain-cron-schedules.js.map +1 -1
  12. package/dist/core/fire-cron.d.ts +6 -2
  13. package/dist/core/fire-cron.d.ts.map +1 -1
  14. package/dist/core/fire-cron.js +8 -5
  15. package/dist/core/fire-cron.js.map +1 -1
  16. package/dist/core/fire-manual.d.ts +6 -2
  17. package/dist/core/fire-manual.d.ts.map +1 -1
  18. package/dist/core/fire-manual.js +8 -4
  19. package/dist/core/fire-manual.js.map +1 -1
  20. package/dist/core/route-event-to-job-listeners.d.ts +2 -0
  21. package/dist/core/route-event-to-job-listeners.d.ts.map +1 -1
  22. package/dist/core/route-event-to-job-listeners.js +2 -3
  23. package/dist/core/route-event-to-job-listeners.js.map +1 -1
  24. package/dist/core/workflows-client.d.ts +69 -0
  25. package/dist/core/workflows-client.d.ts.map +1 -0
  26. package/dist/core/workflows-client.js +20 -0
  27. package/dist/core/workflows-client.js.map +1 -0
  28. package/dist/index.d.ts +5 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +52 -50
  31. package/dist/index.js.map +1 -1
  32. package/dist/presentation/index.d.ts +2 -2
  33. package/dist/presentation/index.d.ts.map +1 -1
  34. package/dist/presentation/index.js +2 -2
  35. package/dist/presentation/index.js.map +1 -1
  36. package/dist/presentation/routes/fire-manual.d.ts +2 -1
  37. package/dist/presentation/routes/fire-manual.d.ts.map +1 -1
  38. package/dist/presentation/routes/fire-manual.js +61 -58
  39. package/dist/presentation/routes/fire-manual.js.map +1 -1
  40. package/dist/presentation/routes/index.d.ts +2 -1
  41. package/dist/presentation/routes/index.d.ts.map +1 -1
  42. package/dist/presentation/routes/index.js +23 -21
  43. package/dist/presentation/routes/index.js.map +1 -1
  44. package/dist/presentation/subscribers/index.d.ts +1 -1
  45. package/dist/presentation/subscribers/index.d.ts.map +1 -1
  46. package/dist/presentation/subscribers/index.js +1 -1
  47. package/dist/presentation/subscribers/index.js.map +1 -1
  48. package/dist/presentation/subscribers/on-integration-event-received.d.ts +2 -1
  49. package/dist/presentation/subscribers/on-integration-event-received.d.ts.map +1 -1
  50. package/dist/presentation/subscribers/on-integration-event-received.js +16 -13
  51. package/dist/presentation/subscribers/on-integration-event-received.js.map +1 -1
  52. package/dist/temporal/activities/drain-cron-batch.d.ts +2 -1
  53. package/dist/temporal/activities/drain-cron-batch.d.ts.map +1 -1
  54. package/dist/temporal/activities/drain-cron-batch.js +2 -1
  55. package/dist/temporal/activities/drain-cron-batch.js.map +1 -1
  56. package/dist/temporal/activities/index.d.ts +4 -3
  57. package/dist/temporal/activities/index.d.ts.map +1 -1
  58. package/dist/temporal/activities/index.js +2 -2
  59. package/dist/temporal/activities/index.js.map +1 -1
  60. package/dist/tsconfig.test.tsbuildinfo +1 -1
  61. package/package.json +27 -35
  62. package/src/core/dispatch-integration-event.history-failure.test.ts +11 -6
  63. package/src/core/dispatch-integration-event.test.ts +50 -36
  64. package/src/core/dispatch-integration-event.ts +8 -5
  65. package/src/core/drain-cron-schedules.test.ts +30 -29
  66. package/src/core/drain-cron-schedules.ts +3 -0
  67. package/src/core/fire-cron.test.ts +35 -24
  68. package/src/core/fire-cron.ts +9 -7
  69. package/src/core/fire-manual.test.ts +19 -22
  70. package/src/core/fire-manual.ts +9 -6
  71. package/src/core/record-trigger-history.test.ts +3 -5
  72. package/src/core/route-event-to-job-listeners.test.ts +5 -4
  73. package/src/core/route-event-to-job-listeners.ts +5 -4
  74. package/src/core/workflows-client.test.ts +73 -0
  75. package/src/core/workflows-client.ts +32 -0
  76. package/src/index.ts +49 -42
  77. package/src/presentation/index.ts +2 -2
  78. package/src/presentation/routes/fire-manual.test.ts +14 -30
  79. package/src/presentation/routes/fire-manual.ts +62 -54
  80. package/src/presentation/routes/index.ts +18 -15
  81. package/src/presentation/subscribers/index.ts +1 -1
  82. package/src/presentation/subscribers/on-integration-event-received.test.ts +6 -3
  83. package/src/presentation/subscribers/on-integration-event-received.ts +20 -16
  84. package/src/temporal/activities/drain-cron-batch.ts +5 -1
  85. package/src/temporal/activities/index.ts +3 -2
  86. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/route-event-to-job-listeners.ts"],"sourcesContent":["import {deliverEventToListener, type JobListenerEventDisposition} from '@shipfox/api-workflows';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {findMatchingJobListenerSubscriptions} from '#db/job-listener-subscriptions.js';\nimport {evaluateStoredFilter, type StoredFilterEvaluation} from './config.js';\nimport type {JobListenerSubscription} from './entities/job-listener-subscription.js';\nimport {type TriggerHistoryRecorder, toReason} from './record-trigger-history.js';\n\nexport interface RouteEventToJobListenersParams {\n history: TriggerHistoryRecorder;\n eventRef: string;\n workspaceId: string;\n provider: string;\n source: string;\n event: string;\n deliveryId: string;\n payload: unknown;\n receivedAt: Date;\n}\n\nexport interface RouteEventToJobListenersResult {\n /**\n * Listener outcomes that should contribute to received_event.matched_count:\n * filter errors, accepted deliveries, and dispatch errors. Stale skipped jobs\n * are intentionally excluded because they did not produce an auditable decision.\n */\n engagedCount: number;\n /**\n * Jobs with an effective matcher after source/event/filter checks, including\n * stale skipped jobs.\n */\n matchedJobCount: number;\n acceptedJobCount: number;\n deliveredCount: number;\n transientErrored: boolean;\n transientError: unknown;\n}\n\nexport async function routeEventToJobListeners(\n params: RouteEventToJobListenersParams,\n): Promise<RouteEventToJobListenersResult> {\n const subscriptions = await findMatchingJobListenerSubscriptions({\n workspaceId: params.workspaceId,\n source: params.source,\n event: params.event,\n });\n\n let filterErrorCount = 0;\n const effectiveMatchByJobId = new Map<string, JobListenerSubscription>();\n for (const subscription of subscriptions) {\n const filterResult = evaluateListenerFilter({subscription, payload: params.payload});\n if (filterResult.kind === 'filtered') continue;\n if (filterResult.kind === 'filter-error') {\n filterErrorCount += 1;\n await params.history.listenerFilterErrored(subscription, filterResult.reason);\n continue;\n }\n\n const previous = effectiveMatchByJobId.get(subscription.jobId);\n if (!previous || shouldReplaceEffectiveMatcher(previous, subscription)) {\n effectiveMatchByJobId.set(subscription.jobId, subscription);\n }\n }\n\n let acceptedJobCount = 0;\n let deliveredCount = 0;\n let sawTransientError = false;\n let dispatchErrorCount = 0;\n let firstTransientError: unknown;\n\n for (const subscription of effectiveMatchByJobId.values()) {\n const disposition = listenerDisposition(subscription);\n try {\n const result = await deliverEventToListener({\n jobId: subscription.jobId,\n disposition,\n eventRef: params.eventRef,\n deliveryId: params.deliveryId,\n source: params.source,\n event: params.event,\n provider: params.provider,\n payload: params.payload,\n receivedAt: params.receivedAt,\n });\n if (!result.skipped) {\n acceptedJobCount += 1;\n await params.history.listenerTriggered(subscription);\n }\n if (result.buffered) deliveredCount += 1;\n } catch (error) {\n dispatchErrorCount += 1;\n await params.history.listenerDispatchErrored(subscription, toReason(error));\n if (!sawTransientError) {\n sawTransientError = true;\n firstTransientError = error;\n }\n }\n }\n\n return {\n engagedCount: filterErrorCount + acceptedJobCount + dispatchErrorCount,\n matchedJobCount: effectiveMatchByJobId.size,\n acceptedJobCount,\n deliveredCount,\n transientErrored: sawTransientError,\n transientError: sawTransientError ? firstTransientError : undefined,\n };\n}\n\ninterface EvaluateListenerFilterParams {\n subscription: JobListenerSubscription;\n payload: unknown;\n}\n\nfunction evaluateListenerFilter(params: EvaluateListenerFilterParams): StoredFilterEvaluation {\n const filter = params.subscription.config.filter;\n if (filter === null || filter === undefined) return {kind: 'matched'};\n if (typeof filter !== 'string' || filter.trim() === '') {\n return evaluateStoredFilter({\n value: filter,\n context: {event: params.payload},\n invalidReason: 'Listener subscription filter must be a non-empty string when set',\n evaluationFailedReason: 'Listener filter evaluation failed',\n });\n }\n\n const snapshot = readFilterSnapshot(params.subscription);\n if (snapshot.kind === 'invalid') return snapshot.result;\n\n return evaluateStoredFilter({\n value: filter,\n context: {...snapshot.value, event: params.payload},\n invalidReason: 'Listener subscription filter must be a non-empty string when set',\n evaluationFailedReason: 'Listener filter evaluation failed',\n });\n}\n\nfunction readFilterSnapshot(\n subscription: JobListenerSubscription,\n):\n | {kind: 'valid'; value: Record<string, unknown>}\n | {kind: 'invalid'; result: Extract<StoredFilterEvaluation, {kind: 'filter-error'}>} {\n const value = subscription.config.filter_snapshot;\n if (value === undefined) return {kind: 'valid', value: {}};\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n return {kind: 'valid', value: value as Record<string, unknown>};\n }\n return {\n kind: 'invalid',\n result: {\n kind: 'filter-error',\n reason: 'Listener filter snapshot must be an object when set',\n },\n };\n}\n\nfunction listenerDisposition(subscription: JobListenerSubscription): JobListenerEventDisposition {\n return subscription.kind === 'until' ? 'resolve' : 'fire';\n}\n\nfunction listenerMatcherSortKey(subscription: JobListenerSubscription): string {\n const kindRank = subscription.kind === 'until' ? '0' : '1';\n return `${kindRank}:${subscription.matcherOrdinal.toString().padStart(10, '0')}`;\n}\n\nfunction shouldReplaceEffectiveMatcher(\n previous: JobListenerSubscription,\n candidate: JobListenerSubscription,\n): boolean {\n const previousKey = listenerMatcherSortKey(previous);\n const candidateKey = listenerMatcherSortKey(candidate);\n if (candidateKey !== previousKey) return candidateKey < previousKey;\n\n logger().warn(\n {\n jobId: candidate.jobId,\n keptSubscriptionId: previous.id,\n candidateSubscriptionId: candidate.id,\n matcherKind: candidate.kind,\n matcherOrdinal: candidate.matcherOrdinal,\n },\n 'duplicate job listener matcher key encountered; choosing deterministic subscription id order',\n );\n return candidate.id < previous.id;\n}\n"],"names":["deliverEventToListener","logger","findMatchingJobListenerSubscriptions","evaluateStoredFilter","toReason","routeEventToJobListeners","params","subscriptions","workspaceId","source","event","filterErrorCount","effectiveMatchByJobId","Map","subscription","filterResult","evaluateListenerFilter","payload","kind","history","listenerFilterErrored","reason","previous","get","jobId","shouldReplaceEffectiveMatcher","set","acceptedJobCount","deliveredCount","sawTransientError","dispatchErrorCount","firstTransientError","values","disposition","listenerDisposition","result","eventRef","deliveryId","provider","receivedAt","skipped","listenerTriggered","buffered","error","listenerDispatchErrored","engagedCount","matchedJobCount","size","transientErrored","transientError","undefined","filter","config","trim","value","context","invalidReason","evaluationFailedReason","snapshot","readFilterSnapshot","filter_snapshot","Array","isArray","listenerMatcherSortKey","kindRank","matcherOrdinal","toString","padStart","candidate","previousKey","candidateKey","warn","keptSubscriptionId","id","candidateSubscriptionId","matcherKind"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/route-event-to-job-listeners.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\nimport {findMatchingJobListenerSubscriptions} from '#db/job-listener-subscriptions.js';\nimport {evaluateStoredFilter, type StoredFilterEvaluation} from './config.js';\nimport type {JobListenerSubscription} from './entities/job-listener-subscription.js';\nimport {type TriggerHistoryRecorder, toReason} from './record-trigger-history.js';\nimport type {WorkflowsModuleClient} from './workflows-client.js';\n\nexport interface RouteEventToJobListenersParams {\n workflows: WorkflowsModuleClient;\n history: TriggerHistoryRecorder;\n eventRef: string;\n workspaceId: string;\n provider: string;\n source: string;\n event: string;\n deliveryId: string;\n payload: unknown;\n receivedAt: Date;\n}\n\nexport interface RouteEventToJobListenersResult {\n /**\n * Listener outcomes that should contribute to received_event.matched_count:\n * filter errors, accepted deliveries, and dispatch errors. Stale skipped jobs\n * are intentionally excluded because they did not produce an auditable decision.\n */\n engagedCount: number;\n /**\n * Jobs with an effective matcher after source/event/filter checks, including\n * stale skipped jobs.\n */\n matchedJobCount: number;\n acceptedJobCount: number;\n deliveredCount: number;\n transientErrored: boolean;\n transientError: unknown;\n}\n\nexport async function routeEventToJobListeners(\n params: RouteEventToJobListenersParams,\n): Promise<RouteEventToJobListenersResult> {\n const subscriptions = await findMatchingJobListenerSubscriptions({\n workspaceId: params.workspaceId,\n source: params.source,\n event: params.event,\n });\n\n let filterErrorCount = 0;\n const effectiveMatchByJobId = new Map<string, JobListenerSubscription>();\n for (const subscription of subscriptions) {\n const filterResult = evaluateListenerFilter({subscription, payload: params.payload});\n if (filterResult.kind === 'filtered') continue;\n if (filterResult.kind === 'filter-error') {\n filterErrorCount += 1;\n await params.history.listenerFilterErrored(subscription, filterResult.reason);\n continue;\n }\n\n const previous = effectiveMatchByJobId.get(subscription.jobId);\n if (!previous || shouldReplaceEffectiveMatcher(previous, subscription)) {\n effectiveMatchByJobId.set(subscription.jobId, subscription);\n }\n }\n\n let acceptedJobCount = 0;\n let deliveredCount = 0;\n let sawTransientError = false;\n let dispatchErrorCount = 0;\n let firstTransientError: unknown;\n\n for (const subscription of effectiveMatchByJobId.values()) {\n const disposition = listenerDisposition(subscription);\n try {\n const result = await params.workflows.deliverEventToJobListener({\n jobId: subscription.jobId,\n disposition,\n eventRef: params.eventRef,\n deliveryId: params.deliveryId,\n source: params.source,\n event: params.event,\n provider: params.provider,\n payload: params.payload,\n receivedAt: params.receivedAt.toISOString(),\n });\n if (!result.skipped) {\n acceptedJobCount += 1;\n await params.history.listenerTriggered(subscription);\n }\n if (result.buffered) deliveredCount += 1;\n } catch (error) {\n dispatchErrorCount += 1;\n await params.history.listenerDispatchErrored(subscription, toReason(error));\n if (!sawTransientError) {\n sawTransientError = true;\n firstTransientError = error;\n }\n }\n }\n\n return {\n engagedCount: filterErrorCount + acceptedJobCount + dispatchErrorCount,\n matchedJobCount: effectiveMatchByJobId.size,\n acceptedJobCount,\n deliveredCount,\n transientErrored: sawTransientError,\n transientError: sawTransientError ? firstTransientError : undefined,\n };\n}\n\ninterface EvaluateListenerFilterParams {\n subscription: JobListenerSubscription;\n payload: unknown;\n}\n\nfunction evaluateListenerFilter(params: EvaluateListenerFilterParams): StoredFilterEvaluation {\n const filter = params.subscription.config.filter;\n if (filter === null || filter === undefined) return {kind: 'matched'};\n if (typeof filter !== 'string' || filter.trim() === '') {\n return evaluateStoredFilter({\n value: filter,\n context: {event: params.payload},\n invalidReason: 'Listener subscription filter must be a non-empty string when set',\n evaluationFailedReason: 'Listener filter evaluation failed',\n });\n }\n\n const snapshot = readFilterSnapshot(params.subscription);\n if (snapshot.kind === 'invalid') return snapshot.result;\n\n return evaluateStoredFilter({\n value: filter,\n context: {...snapshot.value, event: params.payload},\n invalidReason: 'Listener subscription filter must be a non-empty string when set',\n evaluationFailedReason: 'Listener filter evaluation failed',\n });\n}\n\nfunction readFilterSnapshot(\n subscription: JobListenerSubscription,\n):\n | {kind: 'valid'; value: Record<string, unknown>}\n | {kind: 'invalid'; result: Extract<StoredFilterEvaluation, {kind: 'filter-error'}>} {\n const value = subscription.config.filter_snapshot;\n if (value === undefined) return {kind: 'valid', value: {}};\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n return {kind: 'valid', value: value as Record<string, unknown>};\n }\n return {\n kind: 'invalid',\n result: {\n kind: 'filter-error',\n reason: 'Listener filter snapshot must be an object when set',\n },\n };\n}\n\nfunction listenerDisposition(subscription: JobListenerSubscription): 'fire' | 'resolve' {\n return subscription.kind === 'until' ? 'resolve' : 'fire';\n}\n\nfunction listenerMatcherSortKey(subscription: JobListenerSubscription): string {\n const kindRank = subscription.kind === 'until' ? '0' : '1';\n return `${kindRank}:${subscription.matcherOrdinal.toString().padStart(10, '0')}`;\n}\n\nfunction shouldReplaceEffectiveMatcher(\n previous: JobListenerSubscription,\n candidate: JobListenerSubscription,\n): boolean {\n const previousKey = listenerMatcherSortKey(previous);\n const candidateKey = listenerMatcherSortKey(candidate);\n if (candidateKey !== previousKey) return candidateKey < previousKey;\n\n logger().warn(\n {\n jobId: candidate.jobId,\n keptSubscriptionId: previous.id,\n candidateSubscriptionId: candidate.id,\n matcherKind: candidate.kind,\n matcherOrdinal: candidate.matcherOrdinal,\n },\n 'duplicate job listener matcher key encountered; choosing deterministic subscription id order',\n );\n return candidate.id < previous.id;\n}\n"],"names":["logger","findMatchingJobListenerSubscriptions","evaluateStoredFilter","toReason","routeEventToJobListeners","params","subscriptions","workspaceId","source","event","filterErrorCount","effectiveMatchByJobId","Map","subscription","filterResult","evaluateListenerFilter","payload","kind","history","listenerFilterErrored","reason","previous","get","jobId","shouldReplaceEffectiveMatcher","set","acceptedJobCount","deliveredCount","sawTransientError","dispatchErrorCount","firstTransientError","values","disposition","listenerDisposition","result","workflows","deliverEventToJobListener","eventRef","deliveryId","provider","receivedAt","toISOString","skipped","listenerTriggered","buffered","error","listenerDispatchErrored","engagedCount","matchedJobCount","size","transientErrored","transientError","undefined","filter","config","trim","value","context","invalidReason","evaluationFailedReason","snapshot","readFilterSnapshot","filter_snapshot","Array","isArray","listenerMatcherSortKey","kindRank","matcherOrdinal","toString","padStart","candidate","previousKey","candidateKey","warn","keptSubscriptionId","id","candidateSubscriptionId","matcherKind"],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { type WorkflowsModuleClient } from '@shipfox/api-workflows-dto/inter-module';
2
+ export type { WorkflowsModuleClient };
3
+ /**
4
+ * Workflows declares only failures that can never succeed on retry for trigger
5
+ * run creation. Every other outcome is opaque and must remain retryable because
6
+ * it may have committed before the caller stopped waiting.
7
+ */
8
+ export declare function isPermanentStartRunError(error: unknown): boolean;
9
+ export declare function isInterpolationUnresolvableError(error: unknown): error is Extract<ReturnType<typeof startRunKnownError>, {
10
+ code: 'interpolation-unresolvable';
11
+ }>;
12
+ declare function startRunKnownError(error: unknown): import("@shipfox/inter-module").InterModuleKnownErrorFor<import("@shipfox/inter-module").InterModuleMethodContract<import("zod").ZodObject<{
13
+ workspaceId: import("zod").ZodString;
14
+ projectId: import("zod").ZodString;
15
+ definitionId: import("zod").ZodString;
16
+ triggerPayload: import("zod").ZodUnion<readonly [import("zod").ZodObject<{
17
+ provider: import("zod").ZodOptional<import("zod").ZodLiteral<"manual">>;
18
+ source: import("zod").ZodLiteral<"manual">;
19
+ event: import("zod").ZodLiteral<"fire">;
20
+ subscriptionId: import("zod").ZodString;
21
+ userId: import("zod").ZodString;
22
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
23
+ provider: import("zod").ZodOptional<import("zod").ZodLiteral<"cron">>;
24
+ source: import("zod").ZodLiteral<"cron">;
25
+ event: import("zod").ZodLiteral<"tick">;
26
+ scheduleId: import("zod").ZodString;
27
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
28
+ provider: import("zod").ZodString;
29
+ source: import("zod").ZodString;
30
+ event: import("zod").ZodString;
31
+ deliveryId: import("zod").ZodString;
32
+ data: import("zod").ZodUnknown;
33
+ }, import("zod/v4/core").$strip>]>;
34
+ inputs: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
35
+ idempotencyKey: import("zod").ZodString;
36
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
37
+ id: import("zod").ZodString;
38
+ name: import("zod").ZodString;
39
+ }, import("zod/v4/core").$strip>, {
40
+ readonly 'definition-not-found': import("zod").ZodObject<{
41
+ definitionId: import("zod").ZodString;
42
+ }, import("zod/v4/core").$strip>;
43
+ readonly 'project-mismatch': import("zod").ZodObject<{}, import("zod/v4/core").$strip>;
44
+ readonly 'agent-config-unresolvable': import("zod").ZodObject<{
45
+ definitionId: import("zod").ZodString;
46
+ }, import("zod/v4/core").$strip>;
47
+ readonly 'agent-integration-materialization-failed': import("zod").ZodObject<{}, import("zod/v4/core").$strip>;
48
+ readonly 'interpolation-unresolvable': import("zod").ZodObject<{
49
+ definitionId: import("zod").ZodString;
50
+ field: import("zod").ZodEnum<{
51
+ run: "run";
52
+ env: "env";
53
+ "agent.prompt": "agent.prompt";
54
+ "agent.model": "agent.model";
55
+ "agent.provider": "agent.provider";
56
+ "job.runner": "job.runner";
57
+ "job.outputs": "job.outputs";
58
+ "job.name": "job.name";
59
+ "step.name": "step.name";
60
+ "step.feedback": "step.feedback";
61
+ }>;
62
+ source: import("zod").ZodString;
63
+ envKey: import("zod").ZodOptional<import("zod").ZodString>;
64
+ }, import("zod/v4/core").$strip>;
65
+ readonly 'invalid-job-runner-labels': import("zod").ZodObject<{
66
+ labels: import("zod").ZodArray<import("zod").ZodString>;
67
+ }, import("zod/v4/core").$strip>;
68
+ }>> | undefined;
69
+ //# sourceMappingURL=workflows-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows-client.d.ts","sourceRoot":"","sources":["../../src/core/workflows-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,yCAAyC,CAAC;AAGjD,YAAY,EAAC,qBAAqB,EAAC,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEhE;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAAE;IAAC,IAAI,EAAE,4BAA4B,CAAA;CAAC,CAAC,CAK/F;AAED,iBAAS,kBAAkB,CAAC,KAAK,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAKzC"}
@@ -0,0 +1,20 @@
1
+ import { workflowsInterModuleContract } from '@shipfox/api-workflows-dto/inter-module';
2
+ import { isInterModuleKnownError } from '@shipfox/inter-module';
3
+ /**
4
+ * Workflows declares only failures that can never succeed on retry for trigger
5
+ * run creation. Every other outcome is opaque and must remain retryable because
6
+ * it may have committed before the caller stopped waiting.
7
+ */ export function isPermanentStartRunError(error) {
8
+ return isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, error);
9
+ }
10
+ export function isInterpolationUnresolvableError(error) {
11
+ return isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, error) && error.code === 'interpolation-unresolvable';
12
+ }
13
+ function startRunKnownError(error) {
14
+ if (!isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, error)) {
15
+ return undefined;
16
+ }
17
+ return error;
18
+ }
19
+
20
+ //# sourceMappingURL=workflows-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/workflows-client.ts"],"sourcesContent":["import {\n type WorkflowsModuleClient,\n workflowsInterModuleContract,\n} from '@shipfox/api-workflows-dto/inter-module';\nimport {isInterModuleKnownError} from '@shipfox/inter-module';\n\nexport type {WorkflowsModuleClient};\n\n/**\n * Workflows declares only failures that can never succeed on retry for trigger\n * run creation. Every other outcome is opaque and must remain retryable because\n * it may have committed before the caller stopped waiting.\n */\nexport function isPermanentStartRunError(error: unknown): boolean {\n return isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, error);\n}\n\nexport function isInterpolationUnresolvableError(\n error: unknown,\n): error is Extract<ReturnType<typeof startRunKnownError>, {code: 'interpolation-unresolvable'}> {\n return (\n isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, error) &&\n error.code === 'interpolation-unresolvable'\n );\n}\n\nfunction startRunKnownError(error: unknown) {\n if (!isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, error)) {\n return undefined;\n }\n return error;\n}\n"],"names":["workflowsInterModuleContract","isInterModuleKnownError","isPermanentStartRunError","error","methods","startRunFromTrigger","isInterpolationUnresolvableError","code","startRunKnownError","undefined"],"mappings":"AAAA,SAEEA,4BAA4B,QACvB,0CAA0C;AACjD,SAAQC,uBAAuB,QAAO,wBAAwB;AAI9D;;;;CAIC,GACD,OAAO,SAASC,yBAAyBC,KAAc;IACrD,OAAOF,wBAAwBD,6BAA6BI,OAAO,CAACC,mBAAmB,EAAEF;AAC3F;AAEA,OAAO,SAASG,iCACdH,KAAc;IAEd,OACEF,wBAAwBD,6BAA6BI,OAAO,CAACC,mBAAmB,EAAEF,UAClFA,MAAMI,IAAI,KAAK;AAEnB;AAEA,SAASC,mBAAmBL,KAAc;IACxC,IAAI,CAACF,wBAAwBD,6BAA6BI,OAAO,CAACC,mBAAmB,EAAEF,QAAQ;QAC7F,OAAOM;IACT;IACA,OAAON;AACT"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,11 @@
1
+ import type { WorkflowsModuleClient } from '@shipfox/api-workflows-dto/inter-module';
1
2
  import { type ShipfoxModule } from '@shipfox/node-module';
2
3
  export type { JobListenerMatcherKind, JobListenerSubscription, } from '#core/entities/job-listener-subscription.js';
3
4
  export type { TriggerSubscription } from '#core/entities/subscription.js';
4
5
  export { fireCronSubscription, fireManualSubscription, ManualTriggerNotFoundError, TriggerSubscriptionNotCronError, TriggerSubscriptionNotFoundError, TriggerSubscriptionNotManualError, TriggerWorkspaceMismatchError, } from '#core/index.js';
5
6
  export { db, findMatchingJobListenerSubscriptions, findMatchingSubscriptions, getManualSubscriptionByDefinitionId, getTriggerSubscriptionById, jobListenerSubscriptions, listSubscriptionsByWorkflowDefinitionIds, migrationsPath, projectJobListenerSubscriptions, removeJobListenerSubscriptionsForJob, triggersOutbox, } from '#db/index.js';
6
- export declare const triggersModule: ShipfoxModule;
7
+ export interface CreateTriggersModuleOptions {
8
+ workflows: WorkflowsModuleClient;
9
+ }
10
+ export declare function createTriggersModule({ workflows }: CreateTriggersModuleOptions): ShipfoxModule;
7
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,KAAK,aAAa,EAAoB,MAAM,sBAAsB,CAAC;AAiB3E,YAAY,EACV,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,6CAA6C,CAAC;AACrD,YAAY,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,+BAA+B,EAC/B,gCAAgC,EAChC,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,EAAE,EACF,oCAAoC,EACpC,yBAAyB,EACzB,mCAAmC,EACnC,0BAA0B,EAC1B,wBAAwB,EACxB,wCAAwC,EACxC,cAAc,EACd,+BAA+B,EAC/B,oCAAoC,EACpC,cAAc,GACf,MAAM,cAAc,CAAC;AAStB,eAAO,MAAM,cAAc,EAAE,aAuC5B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AACnF,OAAO,EAAC,KAAK,aAAa,EAAoB,MAAM,sBAAsB,CAAC;AAiB3E,YAAY,EACV,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,6CAA6C,CAAC;AACrD,YAAY,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,+BAA+B,EAC/B,gCAAgC,EAChC,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,EAAE,EACF,oCAAoC,EACpC,yBAAyB,EACzB,mCAAmC,EACnC,0BAA0B,EAC1B,wBAAwB,EACxB,wCAAwC,EACxC,cAAc,EACd,+BAA+B,EAC/B,oCAAoC,EACpC,cAAc,GACf,MAAM,cAAc,CAAC;AAStB,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,oBAAoB,CAAC,EAAC,SAAS,EAAC,EAAE,2BAA2B,GAAG,aAAa,CAyC5F"}
package/dist/index.js CHANGED
@@ -6,8 +6,8 @@ import { WORKFLOWS_JOB_ACTIVATED, WORKFLOWS_JOB_TERMINATED } from '@shipfox/api-
6
6
  import { subscriberFactory } from '@shipfox/node-module';
7
7
  import { db, migrationsPath, triggersOutbox } from '#db/index.js';
8
8
  import { registerTriggersServiceMetrics } from '#metrics/index.js';
9
- import { routes } from '#presentation/index.js';
10
- import { onDefinitionDeleted, onDefinitionResolved, onIntegrationEventReceived, onJobActivated, onJobTerminated } from '#presentation/subscribers/index.js';
9
+ import { createTriggerRoutes } from '#presentation/index.js';
10
+ import { createOnIntegrationEventReceived, onDefinitionDeleted, onDefinitionResolved, onJobActivated, onJobTerminated } from '#presentation/subscribers/index.js';
11
11
  import { createTriggersCronActivities, createTriggersMaintenanceActivities } from '#temporal/activities/index.js';
12
12
  import { TRIGGERS_CRON_TASK_QUEUE, TRIGGERS_MAINTENANCE_TASK_QUEUE } from '#temporal/constants.js';
13
13
  export { fireCronSubscription, fireManualSubscription, ManualTriggerNotFoundError, TriggerSubscriptionNotCronError, TriggerSubscriptionNotFoundError, TriggerSubscriptionNotManualError, TriggerWorkspaceMismatchError } from '#core/index.js';
@@ -15,54 +15,56 @@ export { db, findMatchingJobListenerSubscriptions, findMatchingSubscriptions, ge
15
15
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
16
16
  const temporalWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');
17
17
  const subscriber = subscriberFactory();
18
- export const triggersModule = {
19
- name: 'triggers',
20
- database: {
21
- db,
22
- migrationsPath
23
- },
24
- routes,
25
- metrics: registerTriggersServiceMetrics,
26
- publishers: [
27
- {
28
- name: 'triggers',
29
- table: triggersOutbox,
30
- db
31
- }
32
- ],
33
- subscribers: [
34
- subscriber(DEFINITION_RESOLVED, onDefinitionResolved),
35
- subscriber(DEFINITION_DELETED, onDefinitionDeleted),
36
- subscriber(INTEGRATION_EVENT_RECEIVED, onIntegrationEventReceived),
37
- subscriber(WORKFLOWS_JOB_ACTIVATED, onJobActivated),
38
- subscriber(WORKFLOWS_JOB_TERMINATED, onJobTerminated)
39
- ],
40
- workers: [
41
- {
42
- taskQueue: TRIGGERS_MAINTENANCE_TASK_QUEUE,
43
- workflowsPath: temporalWorkflowsPath,
44
- activities: createTriggersMaintenanceActivities,
45
- workflows: [
46
- {
47
- name: 'pruneTriggerEventsCron',
48
- id: 'triggers-prune-trigger-events',
49
- cronSchedule: '0 * * * *'
50
- }
51
- ]
18
+ export function createTriggersModule({ workflows }) {
19
+ return {
20
+ name: 'triggers',
21
+ database: {
22
+ db,
23
+ migrationsPath
52
24
  },
53
- {
54
- taskQueue: TRIGGERS_CRON_TASK_QUEUE,
55
- workflowsPath: temporalWorkflowsPath,
56
- activities: createTriggersCronActivities,
57
- workflows: [
58
- {
59
- name: 'cronTickCron',
60
- id: 'triggers-cron-tick',
61
- cronSchedule: '* * * * *'
62
- }
63
- ]
64
- }
65
- ]
66
- };
25
+ routes: createTriggerRoutes(workflows),
26
+ metrics: registerTriggersServiceMetrics,
27
+ publishers: [
28
+ {
29
+ name: 'triggers',
30
+ table: triggersOutbox,
31
+ db
32
+ }
33
+ ],
34
+ subscribers: [
35
+ subscriber(DEFINITION_RESOLVED, onDefinitionResolved),
36
+ subscriber(DEFINITION_DELETED, onDefinitionDeleted),
37
+ subscriber(INTEGRATION_EVENT_RECEIVED, createOnIntegrationEventReceived(workflows)),
38
+ subscriber(WORKFLOWS_JOB_ACTIVATED, onJobActivated),
39
+ subscriber(WORKFLOWS_JOB_TERMINATED, onJobTerminated)
40
+ ],
41
+ workers: [
42
+ {
43
+ taskQueue: TRIGGERS_MAINTENANCE_TASK_QUEUE,
44
+ workflowsPath: temporalWorkflowsPath,
45
+ activities: createTriggersMaintenanceActivities,
46
+ workflows: [
47
+ {
48
+ name: 'pruneTriggerEventsCron',
49
+ id: 'triggers-prune-trigger-events',
50
+ cronSchedule: '0 * * * *'
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ taskQueue: TRIGGERS_CRON_TASK_QUEUE,
56
+ workflowsPath: temporalWorkflowsPath,
57
+ activities: ()=>createTriggersCronActivities(workflows),
58
+ workflows: [
59
+ {
60
+ name: 'cronTickCron',
61
+ id: 'triggers-cron-tick',
62
+ cronSchedule: '* * * * *'
63
+ }
64
+ ]
65
+ }
66
+ ]
67
+ };
68
+ }
67
69
 
68
70
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport {\n DEFINITION_DELETED,\n DEFINITION_RESOLVED,\n type DefinitionsEventMap,\n} from '@shipfox/api-definitions-dto';\nimport {\n INTEGRATION_EVENT_RECEIVED,\n type IntegrationsEventMap,\n} from '@shipfox/api-integration-core-dto';\nimport {\n WORKFLOWS_JOB_ACTIVATED,\n WORKFLOWS_JOB_TERMINATED,\n type WorkflowsEventMapDto,\n} from '@shipfox/api-workflows-dto';\nimport {type ShipfoxModule, subscriberFactory} from '@shipfox/node-module';\nimport {db, migrationsPath, triggersOutbox} from '#db/index.js';\nimport {registerTriggersServiceMetrics} from '#metrics/index.js';\nimport {routes} from '#presentation/index.js';\nimport {\n onDefinitionDeleted,\n onDefinitionResolved,\n onIntegrationEventReceived,\n onJobActivated,\n onJobTerminated,\n} from '#presentation/subscribers/index.js';\nimport {\n createTriggersCronActivities,\n createTriggersMaintenanceActivities,\n} from '#temporal/activities/index.js';\nimport {TRIGGERS_CRON_TASK_QUEUE, TRIGGERS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nexport type {\n JobListenerMatcherKind,\n JobListenerSubscription,\n} from '#core/entities/job-listener-subscription.js';\nexport type {TriggerSubscription} from '#core/entities/subscription.js';\nexport {\n fireCronSubscription,\n fireManualSubscription,\n ManualTriggerNotFoundError,\n TriggerSubscriptionNotCronError,\n TriggerSubscriptionNotFoundError,\n TriggerSubscriptionNotManualError,\n TriggerWorkspaceMismatchError,\n} from '#core/index.js';\nexport {\n db,\n findMatchingJobListenerSubscriptions,\n findMatchingSubscriptions,\n getManualSubscriptionByDefinitionId,\n getTriggerSubscriptionById,\n jobListenerSubscriptions,\n listSubscriptionsByWorkflowDefinitionIds,\n migrationsPath,\n projectJobListenerSubscriptions,\n removeJobListenerSubscriptionsForJob,\n triggersOutbox,\n} from '#db/index.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst temporalWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nconst subscriber = subscriberFactory<\n DefinitionsEventMap & IntegrationsEventMap & WorkflowsEventMapDto\n>();\n\nexport const triggersModule: ShipfoxModule = {\n name: 'triggers',\n database: {db, migrationsPath},\n routes,\n metrics: registerTriggersServiceMetrics,\n publishers: [{name: 'triggers', table: triggersOutbox, db}],\n subscribers: [\n subscriber(DEFINITION_RESOLVED, onDefinitionResolved),\n subscriber(DEFINITION_DELETED, onDefinitionDeleted),\n subscriber(INTEGRATION_EVENT_RECEIVED, onIntegrationEventReceived),\n subscriber(WORKFLOWS_JOB_ACTIVATED, onJobActivated),\n subscriber(WORKFLOWS_JOB_TERMINATED, onJobTerminated),\n ],\n workers: [\n {\n taskQueue: TRIGGERS_MAINTENANCE_TASK_QUEUE,\n workflowsPath: temporalWorkflowsPath,\n activities: createTriggersMaintenanceActivities,\n workflows: [\n {\n name: 'pruneTriggerEventsCron',\n id: 'triggers-prune-trigger-events',\n cronSchedule: '0 * * * *',\n },\n ],\n },\n {\n taskQueue: TRIGGERS_CRON_TASK_QUEUE,\n workflowsPath: temporalWorkflowsPath,\n activities: createTriggersCronActivities,\n workflows: [\n {\n name: 'cronTickCron',\n id: 'triggers-cron-tick',\n cronSchedule: '* * * * *',\n },\n ],\n },\n ],\n};\n"],"names":["dirname","resolve","fileURLToPath","DEFINITION_DELETED","DEFINITION_RESOLVED","INTEGRATION_EVENT_RECEIVED","WORKFLOWS_JOB_ACTIVATED","WORKFLOWS_JOB_TERMINATED","subscriberFactory","db","migrationsPath","triggersOutbox","registerTriggersServiceMetrics","routes","onDefinitionDeleted","onDefinitionResolved","onIntegrationEventReceived","onJobActivated","onJobTerminated","createTriggersCronActivities","createTriggersMaintenanceActivities","TRIGGERS_CRON_TASK_QUEUE","TRIGGERS_MAINTENANCE_TASK_QUEUE","fireCronSubscription","fireManualSubscription","ManualTriggerNotFoundError","TriggerSubscriptionNotCronError","TriggerSubscriptionNotFoundError","TriggerSubscriptionNotManualError","TriggerWorkspaceMismatchError","findMatchingJobListenerSubscriptions","findMatchingSubscriptions","getManualSubscriptionByDefinitionId","getTriggerSubscriptionById","jobListenerSubscriptions","listSubscriptionsByWorkflowDefinitionIds","projectJobListenerSubscriptions","removeJobListenerSubscriptionsForJob","packageRoot","url","temporalWorkflowsPath","subscriber","triggersModule","name","database","metrics","publishers","table","subscribers","workers","taskQueue","workflowsPath","activities","workflows","id","cronSchedule"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AACvC,SACEC,kBAAkB,EAClBC,mBAAmB,QAEd,+BAA+B;AACtC,SACEC,0BAA0B,QAErB,oCAAoC;AAC3C,SACEC,uBAAuB,EACvBC,wBAAwB,QAEnB,6BAA6B;AACpC,SAA4BC,iBAAiB,QAAO,uBAAuB;AAC3E,SAAQC,EAAE,EAAEC,cAAc,EAAEC,cAAc,QAAO,eAAe;AAChE,SAAQC,8BAA8B,QAAO,oBAAoB;AACjE,SAAQC,MAAM,QAAO,yBAAyB;AAC9C,SACEC,mBAAmB,EACnBC,oBAAoB,EACpBC,0BAA0B,EAC1BC,cAAc,EACdC,eAAe,QACV,qCAAqC;AAC5C,SACEC,4BAA4B,EAC5BC,mCAAmC,QAC9B,gCAAgC;AACvC,SAAQC,wBAAwB,EAAEC,+BAA+B,QAAO,yBAAyB;AAOjG,SACEC,oBAAoB,EACpBC,sBAAsB,EACtBC,0BAA0B,EAC1BC,+BAA+B,EAC/BC,gCAAgC,EAChCC,iCAAiC,EACjCC,6BAA6B,QACxB,iBAAiB;AACxB,SACEpB,EAAE,EACFqB,oCAAoC,EACpCC,yBAAyB,EACzBC,mCAAmC,EACnCC,0BAA0B,EAC1BC,wBAAwB,EACxBC,wCAAwC,EACxCzB,cAAc,EACd0B,+BAA+B,EAC/BC,oCAAoC,EACpC1B,cAAc,QACT,eAAe;AAEtB,MAAM2B,cAAcrC,QAAQD,QAAQE,cAAc,YAAYqC,GAAG,IAAI;AACrE,MAAMC,wBAAwBvC,QAAQqC,aAAa;AAEnD,MAAMG,aAAajC;AAInB,OAAO,MAAMkC,iBAAgC;IAC3CC,MAAM;IACNC,UAAU;QAACnC;QAAIC;IAAc;IAC7BG;IACAgC,SAASjC;IACTkC,YAAY;QAAC;YAACH,MAAM;YAAYI,OAAOpC;YAAgBF;QAAE;KAAE;IAC3DuC,aAAa;QACXP,WAAWrC,qBAAqBW;QAChC0B,WAAWtC,oBAAoBW;QAC/B2B,WAAWpC,4BAA4BW;QACvCyB,WAAWnC,yBAAyBW;QACpCwB,WAAWlC,0BAA0BW;KACtC;IACD+B,SAAS;QACP;YACEC,WAAW5B;YACX6B,eAAeX;YACfY,YAAYhC;YACZiC,WAAW;gBACT;oBACEV,MAAM;oBACNW,IAAI;oBACJC,cAAc;gBAChB;aACD;QACH;QACA;YACEL,WAAW7B;YACX8B,eAAeX;YACfY,YAAYjC;YACZkC,WAAW;gBACT;oBACEV,MAAM;oBACNW,IAAI;oBACJC,cAAc;gBAChB;aACD;QACH;KACD;AACH,EAAE"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport {\n DEFINITION_DELETED,\n DEFINITION_RESOLVED,\n type DefinitionsEventMap,\n} from '@shipfox/api-definitions-dto';\nimport {\n INTEGRATION_EVENT_RECEIVED,\n type IntegrationsEventMap,\n} from '@shipfox/api-integration-core-dto';\nimport {\n WORKFLOWS_JOB_ACTIVATED,\n WORKFLOWS_JOB_TERMINATED,\n type WorkflowsEventMapDto,\n} from '@shipfox/api-workflows-dto';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport {type ShipfoxModule, subscriberFactory} from '@shipfox/node-module';\nimport {db, migrationsPath, triggersOutbox} from '#db/index.js';\nimport {registerTriggersServiceMetrics} from '#metrics/index.js';\nimport {createTriggerRoutes} from '#presentation/index.js';\nimport {\n createOnIntegrationEventReceived,\n onDefinitionDeleted,\n onDefinitionResolved,\n onJobActivated,\n onJobTerminated,\n} from '#presentation/subscribers/index.js';\nimport {\n createTriggersCronActivities,\n createTriggersMaintenanceActivities,\n} from '#temporal/activities/index.js';\nimport {TRIGGERS_CRON_TASK_QUEUE, TRIGGERS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nexport type {\n JobListenerMatcherKind,\n JobListenerSubscription,\n} from '#core/entities/job-listener-subscription.js';\nexport type {TriggerSubscription} from '#core/entities/subscription.js';\nexport {\n fireCronSubscription,\n fireManualSubscription,\n ManualTriggerNotFoundError,\n TriggerSubscriptionNotCronError,\n TriggerSubscriptionNotFoundError,\n TriggerSubscriptionNotManualError,\n TriggerWorkspaceMismatchError,\n} from '#core/index.js';\nexport {\n db,\n findMatchingJobListenerSubscriptions,\n findMatchingSubscriptions,\n getManualSubscriptionByDefinitionId,\n getTriggerSubscriptionById,\n jobListenerSubscriptions,\n listSubscriptionsByWorkflowDefinitionIds,\n migrationsPath,\n projectJobListenerSubscriptions,\n removeJobListenerSubscriptionsForJob,\n triggersOutbox,\n} from '#db/index.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst temporalWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nconst subscriber = subscriberFactory<\n DefinitionsEventMap & IntegrationsEventMap & WorkflowsEventMapDto\n>();\n\nexport interface CreateTriggersModuleOptions {\n workflows: WorkflowsModuleClient;\n}\n\nexport function createTriggersModule({workflows}: CreateTriggersModuleOptions): ShipfoxModule {\n return {\n name: 'triggers',\n database: {db, migrationsPath},\n routes: createTriggerRoutes(workflows),\n metrics: registerTriggersServiceMetrics,\n publishers: [{name: 'triggers', table: triggersOutbox, db}],\n subscribers: [\n subscriber(DEFINITION_RESOLVED, onDefinitionResolved),\n subscriber(DEFINITION_DELETED, onDefinitionDeleted),\n subscriber(INTEGRATION_EVENT_RECEIVED, createOnIntegrationEventReceived(workflows)),\n subscriber(WORKFLOWS_JOB_ACTIVATED, onJobActivated),\n subscriber(WORKFLOWS_JOB_TERMINATED, onJobTerminated),\n ],\n workers: [\n {\n taskQueue: TRIGGERS_MAINTENANCE_TASK_QUEUE,\n workflowsPath: temporalWorkflowsPath,\n activities: createTriggersMaintenanceActivities,\n workflows: [\n {\n name: 'pruneTriggerEventsCron',\n id: 'triggers-prune-trigger-events',\n cronSchedule: '0 * * * *',\n },\n ],\n },\n {\n taskQueue: TRIGGERS_CRON_TASK_QUEUE,\n workflowsPath: temporalWorkflowsPath,\n activities: () => createTriggersCronActivities(workflows),\n workflows: [\n {\n name: 'cronTickCron',\n id: 'triggers-cron-tick',\n cronSchedule: '* * * * *',\n },\n ],\n },\n ],\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","DEFINITION_DELETED","DEFINITION_RESOLVED","INTEGRATION_EVENT_RECEIVED","WORKFLOWS_JOB_ACTIVATED","WORKFLOWS_JOB_TERMINATED","subscriberFactory","db","migrationsPath","triggersOutbox","registerTriggersServiceMetrics","createTriggerRoutes","createOnIntegrationEventReceived","onDefinitionDeleted","onDefinitionResolved","onJobActivated","onJobTerminated","createTriggersCronActivities","createTriggersMaintenanceActivities","TRIGGERS_CRON_TASK_QUEUE","TRIGGERS_MAINTENANCE_TASK_QUEUE","fireCronSubscription","fireManualSubscription","ManualTriggerNotFoundError","TriggerSubscriptionNotCronError","TriggerSubscriptionNotFoundError","TriggerSubscriptionNotManualError","TriggerWorkspaceMismatchError","findMatchingJobListenerSubscriptions","findMatchingSubscriptions","getManualSubscriptionByDefinitionId","getTriggerSubscriptionById","jobListenerSubscriptions","listSubscriptionsByWorkflowDefinitionIds","projectJobListenerSubscriptions","removeJobListenerSubscriptionsForJob","packageRoot","url","temporalWorkflowsPath","subscriber","createTriggersModule","workflows","name","database","routes","metrics","publishers","table","subscribers","workers","taskQueue","workflowsPath","activities","id","cronSchedule"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AACvC,SACEC,kBAAkB,EAClBC,mBAAmB,QAEd,+BAA+B;AACtC,SACEC,0BAA0B,QAErB,oCAAoC;AAC3C,SACEC,uBAAuB,EACvBC,wBAAwB,QAEnB,6BAA6B;AAEpC,SAA4BC,iBAAiB,QAAO,uBAAuB;AAC3E,SAAQC,EAAE,EAAEC,cAAc,EAAEC,cAAc,QAAO,eAAe;AAChE,SAAQC,8BAA8B,QAAO,oBAAoB;AACjE,SAAQC,mBAAmB,QAAO,yBAAyB;AAC3D,SACEC,gCAAgC,EAChCC,mBAAmB,EACnBC,oBAAoB,EACpBC,cAAc,EACdC,eAAe,QACV,qCAAqC;AAC5C,SACEC,4BAA4B,EAC5BC,mCAAmC,QAC9B,gCAAgC;AACvC,SAAQC,wBAAwB,EAAEC,+BAA+B,QAAO,yBAAyB;AAOjG,SACEC,oBAAoB,EACpBC,sBAAsB,EACtBC,0BAA0B,EAC1BC,+BAA+B,EAC/BC,gCAAgC,EAChCC,iCAAiC,EACjCC,6BAA6B,QACxB,iBAAiB;AACxB,SACEpB,EAAE,EACFqB,oCAAoC,EACpCC,yBAAyB,EACzBC,mCAAmC,EACnCC,0BAA0B,EAC1BC,wBAAwB,EACxBC,wCAAwC,EACxCzB,cAAc,EACd0B,+BAA+B,EAC/BC,oCAAoC,EACpC1B,cAAc,QACT,eAAe;AAEtB,MAAM2B,cAAcrC,QAAQD,QAAQE,cAAc,YAAYqC,GAAG,IAAI;AACrE,MAAMC,wBAAwBvC,QAAQqC,aAAa;AAEnD,MAAMG,aAAajC;AAQnB,OAAO,SAASkC,qBAAqB,EAACC,SAAS,EAA8B;IAC3E,OAAO;QACLC,MAAM;QACNC,UAAU;YAACpC;YAAIC;QAAc;QAC7BoC,QAAQjC,oBAAoB8B;QAC5BI,SAASnC;QACToC,YAAY;YAAC;gBAACJ,MAAM;gBAAYK,OAAOtC;gBAAgBF;YAAE;SAAE;QAC3DyC,aAAa;YACXT,WAAWrC,qBAAqBY;YAChCyB,WAAWtC,oBAAoBY;YAC/B0B,WAAWpC,4BAA4BS,iCAAiC6B;YACxEF,WAAWnC,yBAAyBW;YACpCwB,WAAWlC,0BAA0BW;SACtC;QACDiC,SAAS;YACP;gBACEC,WAAW9B;gBACX+B,eAAeb;gBACfc,YAAYlC;gBACZuB,WAAW;oBACT;wBACEC,MAAM;wBACNW,IAAI;wBACJC,cAAc;oBAChB;iBACD;YACH;YACA;gBACEJ,WAAW/B;gBACXgC,eAAeb;gBACfc,YAAY,IAAMnC,6BAA6BwB;gBAC/CA,WAAW;oBACT;wBACEC,MAAM;wBACNW,IAAI;wBACJC,cAAc;oBAChB;iBACD;YACH;SACD;IACH;AACF"}
@@ -1,3 +1,3 @@
1
- export { triggerRoutes as routes } from './routes/index.js';
2
- export { onDefinitionDeleted, onDefinitionResolved, onIntegrationEventReceived, } from './subscribers/index.js';
1
+ export { createTriggerRoutes } from './routes/index.js';
2
+ export { createOnIntegrationEventReceived, onDefinitionDeleted, onDefinitionResolved, } from './subscribers/index.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,IAAI,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,gCAAgC,EAChC,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC"}
@@ -1,4 +1,4 @@
1
- export { triggerRoutes as routes } from './routes/index.js';
2
- export { onDefinitionDeleted, onDefinitionResolved, onIntegrationEventReceived } from './subscribers/index.js';
1
+ export { createTriggerRoutes } from './routes/index.js';
2
+ export { createOnIntegrationEventReceived, onDefinitionDeleted, onDefinitionResolved } from './subscribers/index.js';
3
3
 
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/presentation/index.ts"],"sourcesContent":["export {triggerRoutes as routes} from './routes/index.js';\nexport {\n onDefinitionDeleted,\n onDefinitionResolved,\n onIntegrationEventReceived,\n} from './subscribers/index.js';\n"],"names":["triggerRoutes","routes","onDefinitionDeleted","onDefinitionResolved","onIntegrationEventReceived"],"mappings":"AAAA,SAAQA,iBAAiBC,MAAM,QAAO,oBAAoB;AAC1D,SACEC,mBAAmB,EACnBC,oBAAoB,EACpBC,0BAA0B,QACrB,yBAAyB"}
1
+ {"version":3,"sources":["../../src/presentation/index.ts"],"sourcesContent":["export {createTriggerRoutes} from './routes/index.js';\nexport {\n createOnIntegrationEventReceived,\n onDefinitionDeleted,\n onDefinitionResolved,\n} from './subscribers/index.js';\n"],"names":["createTriggerRoutes","createOnIntegrationEventReceived","onDefinitionDeleted","onDefinitionResolved"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,oBAAoB;AACtD,SACEC,gCAAgC,EAChCC,mBAAmB,EACnBC,oBAAoB,QACf,yBAAyB"}
@@ -1,2 +1,3 @@
1
- export declare const fireManualTriggerRoute: import("@shipfox/node-fastify").RouteDefinition;
1
+ import type { WorkflowsModuleClient } from '@shipfox/api-workflows-dto/inter-module';
2
+ export declare function createFireManualTriggerRoute(workflows: WorkflowsModuleClient): import("@shipfox/node-fastify").RouteDefinition;
2
3
  //# sourceMappingURL=fire-manual.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fire-manual.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/fire-manual.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,sBAAsB,iDAyDjC,CAAC"}
1
+ {"version":3,"file":"fire-manual.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/fire-manual.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAQnF,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,qBAAqB,mDAgE5E"}
@@ -1,71 +1,74 @@
1
1
  import { requireUserContext } from '@shipfox/api-auth-context';
2
2
  import { fireManualTriggerBodySchema, fireManualTriggerResponseSchema } from '@shipfox/api-triggers-dto';
3
- import { InterpolationUnresolvableError } from '@shipfox/api-workflows';
4
3
  import { ClientError, defineRoute } from '@shipfox/node-fastify';
5
4
  import { z } from 'zod';
6
5
  import { ManualTriggerNotFoundError } from '#core/errors.js';
7
6
  import { fireManualSubscription } from '#core/fire-manual.js';
7
+ import { isInterpolationUnresolvableError } from '#core/workflows-client.js';
8
8
  import { getManualSubscriptionByDefinitionId } from '#db/subscriptions.js';
9
- export const fireManualTriggerRoute = defineRoute({
10
- method: 'POST',
11
- path: '/:definitionId/fire-manual',
12
- description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',
13
- schema: {
14
- params: z.object({
15
- definitionId: z.string().uuid()
16
- }),
17
- body: fireManualTriggerBodySchema,
18
- response: {
19
- 201: fireManualTriggerResponseSchema,
20
- 422: z.object({
21
- code: z.string(),
22
- details: z.object({
23
- field: z.string(),
24
- source: z.string(),
25
- env_key: z.string().optional()
9
+ export function createFireManualTriggerRoute(workflows) {
10
+ return defineRoute({
11
+ method: 'POST',
12
+ path: '/:definitionId/fire-manual',
13
+ description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',
14
+ schema: {
15
+ params: z.object({
16
+ definitionId: z.string().uuid()
17
+ }),
18
+ body: fireManualTriggerBodySchema,
19
+ response: {
20
+ 201: fireManualTriggerResponseSchema,
21
+ 422: z.object({
22
+ code: z.string(),
23
+ details: z.object({
24
+ field: z.string(),
25
+ source: z.string(),
26
+ env_key: z.string().optional()
27
+ })
26
28
  })
27
- })
28
- }
29
- },
30
- errorHandler: (error)=>{
31
- if (error instanceof ManualTriggerNotFoundError) {
32
- throw new ClientError(error.message, 'manual-trigger-not-found', {
33
- status: 404
34
- });
35
- }
36
- if (error instanceof InterpolationUnresolvableError) {
37
- throw new ClientError(error.message, 'workflow-interpolation-unresolvable', {
38
- status: 422,
39
- details: {
40
- field: error.field,
41
- source: error.source,
42
- ...error.envKey === undefined ? {} : {
43
- env_key: error.envKey
29
+ }
30
+ },
31
+ errorHandler: (error)=>{
32
+ if (error instanceof ManualTriggerNotFoundError) {
33
+ throw new ClientError(error.message, 'manual-trigger-not-found', {
34
+ status: 404
35
+ });
36
+ }
37
+ if (isInterpolationUnresolvableError(error)) {
38
+ throw new ClientError('Workflow interpolation cannot be resolved', 'workflow-interpolation-unresolvable', {
39
+ status: 422,
40
+ details: {
41
+ field: error.details.field,
42
+ source: error.details.source,
43
+ ...error.details.envKey === undefined ? {} : {
44
+ env_key: error.details.envKey
45
+ }
44
46
  }
45
- }
47
+ });
48
+ }
49
+ throw error;
50
+ },
51
+ handler: async (request, reply)=>{
52
+ const { definitionId } = request.params;
53
+ const userContext = requireUserContext(request);
54
+ const subscription = await getManualSubscriptionByDefinitionId(definitionId);
55
+ // 404 covers both "no such manual trigger" and "not your workspace" to avoid leaking existence.
56
+ if (!subscription || !userContext.canAccess(subscription.workspaceId)) {
57
+ throw new ManualTriggerNotFoundError(definitionId);
58
+ }
59
+ const run = await fireManualSubscription({
60
+ workflows,
61
+ subscriptionId: subscription.id,
62
+ callerWorkspaceId: subscription.workspaceId,
63
+ userId: userContext.userId,
64
+ inputs: request.body.inputs
46
65
  });
66
+ reply.status(201);
67
+ return {
68
+ workflow_run_id: run.id
69
+ };
47
70
  }
48
- throw error;
49
- },
50
- handler: async (request, reply)=>{
51
- const { definitionId } = request.params;
52
- const userContext = requireUserContext(request);
53
- const subscription = await getManualSubscriptionByDefinitionId(definitionId);
54
- // 404 covers both "no such manual trigger" and "not your workspace" to avoid leaking existence.
55
- if (!subscription || !userContext.canAccess(subscription.workspaceId)) {
56
- throw new ManualTriggerNotFoundError(definitionId);
57
- }
58
- const run = await fireManualSubscription({
59
- subscriptionId: subscription.id,
60
- callerWorkspaceId: subscription.workspaceId,
61
- userId: userContext.userId,
62
- inputs: request.body.inputs
63
- });
64
- reply.status(201);
65
- return {
66
- workflow_run_id: run.id
67
- };
68
- }
69
- });
71
+ });
72
+ }
70
73
 
71
74
  //# sourceMappingURL=fire-manual.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/fire-manual.ts"],"sourcesContent":["import {requireUserContext} from '@shipfox/api-auth-context';\nimport {\n fireManualTriggerBodySchema,\n fireManualTriggerResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport {InterpolationUnresolvableError} from '@shipfox/api-workflows';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {ManualTriggerNotFoundError} from '#core/errors.js';\nimport {fireManualSubscription} from '#core/fire-manual.js';\nimport {getManualSubscriptionByDefinitionId} from '#db/subscriptions.js';\n\nexport const fireManualTriggerRoute = defineRoute({\n method: 'POST',\n path: '/:definitionId/fire-manual',\n description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',\n schema: {\n params: z.object({\n definitionId: z.string().uuid(),\n }),\n body: fireManualTriggerBodySchema,\n response: {\n 201: fireManualTriggerResponseSchema,\n 422: z.object({\n code: z.string(),\n details: z.object({\n field: z.string(),\n source: z.string(),\n env_key: z.string().optional(),\n }),\n }),\n },\n },\n errorHandler: (error) => {\n if (error instanceof ManualTriggerNotFoundError) {\n throw new ClientError(error.message, 'manual-trigger-not-found', {status: 404});\n }\n if (error instanceof InterpolationUnresolvableError) {\n throw new ClientError(error.message, 'workflow-interpolation-unresolvable', {\n status: 422,\n details: {\n field: error.field,\n source: error.source,\n ...(error.envKey === undefined ? {} : {env_key: error.envKey}),\n },\n });\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {definitionId} = request.params;\n const userContext = requireUserContext(request);\n\n const subscription = await getManualSubscriptionByDefinitionId(definitionId);\n // 404 covers both \"no such manual trigger\" and \"not your workspace\" to avoid leaking existence.\n if (!subscription || !userContext.canAccess(subscription.workspaceId)) {\n throw new ManualTriggerNotFoundError(definitionId);\n }\n\n const run = await fireManualSubscription({\n subscriptionId: subscription.id,\n callerWorkspaceId: subscription.workspaceId,\n userId: userContext.userId,\n inputs: request.body.inputs,\n });\n\n reply.status(201);\n return {workflow_run_id: run.id};\n },\n});\n"],"names":["requireUserContext","fireManualTriggerBodySchema","fireManualTriggerResponseSchema","InterpolationUnresolvableError","ClientError","defineRoute","z","ManualTriggerNotFoundError","fireManualSubscription","getManualSubscriptionByDefinitionId","fireManualTriggerRoute","method","path","description","schema","params","object","definitionId","string","uuid","body","response","code","details","field","source","env_key","optional","errorHandler","error","message","status","envKey","undefined","handler","request","reply","userContext","subscription","canAccess","workspaceId","run","subscriptionId","id","callerWorkspaceId","userId","inputs","workflow_run_id"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,4BAA4B;AAC7D,SACEC,2BAA2B,EAC3BC,+BAA+B,QAC1B,4BAA4B;AACnC,SAAQC,8BAA8B,QAAO,yBAAyB;AACtE,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,0BAA0B,QAAO,kBAAkB;AAC3D,SAAQC,sBAAsB,QAAO,uBAAuB;AAC5D,SAAQC,mCAAmC,QAAO,uBAAuB;AAEzE,OAAO,MAAMC,yBAAyBL,YAAY;IAChDM,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,QAAQT,EAAEU,MAAM,CAAC;YACfC,cAAcX,EAAEY,MAAM,GAAGC,IAAI;QAC/B;QACAC,MAAMnB;QACNoB,UAAU;YACR,KAAKnB;YACL,KAAKI,EAAEU,MAAM,CAAC;gBACZM,MAAMhB,EAAEY,MAAM;gBACdK,SAASjB,EAAEU,MAAM,CAAC;oBAChBQ,OAAOlB,EAAEY,MAAM;oBACfO,QAAQnB,EAAEY,MAAM;oBAChBQ,SAASpB,EAAEY,MAAM,GAAGS,QAAQ;gBAC9B;YACF;QACF;IACF;IACAC,cAAc,CAACC;QACb,IAAIA,iBAAiBtB,4BAA4B;YAC/C,MAAM,IAAIH,YAAYyB,MAAMC,OAAO,EAAE,4BAA4B;gBAACC,QAAQ;YAAG;QAC/E;QACA,IAAIF,iBAAiB1B,gCAAgC;YACnD,MAAM,IAAIC,YAAYyB,MAAMC,OAAO,EAAE,uCAAuC;gBAC1EC,QAAQ;gBACRR,SAAS;oBACPC,OAAOK,MAAML,KAAK;oBAClBC,QAAQI,MAAMJ,MAAM;oBACpB,GAAII,MAAMG,MAAM,KAAKC,YAAY,CAAC,IAAI;wBAACP,SAASG,MAAMG,MAAM;oBAAA,CAAC;gBAC/D;YACF;QACF;QACA,MAAMH;IACR;IACAK,SAAS,OAAOC,SAASC;QACvB,MAAM,EAACnB,YAAY,EAAC,GAAGkB,QAAQpB,MAAM;QACrC,MAAMsB,cAAcrC,mBAAmBmC;QAEvC,MAAMG,eAAe,MAAM7B,oCAAoCQ;QAC/D,gGAAgG;QAChG,IAAI,CAACqB,gBAAgB,CAACD,YAAYE,SAAS,CAACD,aAAaE,WAAW,GAAG;YACrE,MAAM,IAAIjC,2BAA2BU;QACvC;QAEA,MAAMwB,MAAM,MAAMjC,uBAAuB;YACvCkC,gBAAgBJ,aAAaK,EAAE;YAC/BC,mBAAmBN,aAAaE,WAAW;YAC3CK,QAAQR,YAAYQ,MAAM;YAC1BC,QAAQX,QAAQf,IAAI,CAAC0B,MAAM;QAC7B;QAEAV,MAAML,MAAM,CAAC;QACb,OAAO;YAACgB,iBAAiBN,IAAIE,EAAE;QAAA;IACjC;AACF,GAAG"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/fire-manual.ts"],"sourcesContent":["import {requireUserContext} from '@shipfox/api-auth-context';\nimport {\n fireManualTriggerBodySchema,\n fireManualTriggerResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {ManualTriggerNotFoundError} from '#core/errors.js';\nimport {fireManualSubscription} from '#core/fire-manual.js';\nimport {isInterpolationUnresolvableError} from '#core/workflows-client.js';\nimport {getManualSubscriptionByDefinitionId} from '#db/subscriptions.js';\n\nexport function createFireManualTriggerRoute(workflows: WorkflowsModuleClient) {\n return defineRoute({\n method: 'POST',\n path: '/:definitionId/fire-manual',\n description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',\n schema: {\n params: z.object({\n definitionId: z.string().uuid(),\n }),\n body: fireManualTriggerBodySchema,\n response: {\n 201: fireManualTriggerResponseSchema,\n 422: z.object({\n code: z.string(),\n details: z.object({\n field: z.string(),\n source: z.string(),\n env_key: z.string().optional(),\n }),\n }),\n },\n },\n errorHandler: (error) => {\n if (error instanceof ManualTriggerNotFoundError) {\n throw new ClientError(error.message, 'manual-trigger-not-found', {status: 404});\n }\n if (isInterpolationUnresolvableError(error)) {\n throw new ClientError(\n 'Workflow interpolation cannot be resolved',\n 'workflow-interpolation-unresolvable',\n {\n status: 422,\n details: {\n field: error.details.field,\n source: error.details.source,\n ...(error.details.envKey === undefined ? {} : {env_key: error.details.envKey}),\n },\n },\n );\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {definitionId} = request.params;\n const userContext = requireUserContext(request);\n\n const subscription = await getManualSubscriptionByDefinitionId(definitionId);\n // 404 covers both \"no such manual trigger\" and \"not your workspace\" to avoid leaking existence.\n if (!subscription || !userContext.canAccess(subscription.workspaceId)) {\n throw new ManualTriggerNotFoundError(definitionId);\n }\n\n const run = await fireManualSubscription({\n workflows,\n subscriptionId: subscription.id,\n callerWorkspaceId: subscription.workspaceId,\n userId: userContext.userId,\n inputs: request.body.inputs,\n });\n\n reply.status(201);\n return {workflow_run_id: run.id};\n },\n });\n}\n"],"names":["requireUserContext","fireManualTriggerBodySchema","fireManualTriggerResponseSchema","ClientError","defineRoute","z","ManualTriggerNotFoundError","fireManualSubscription","isInterpolationUnresolvableError","getManualSubscriptionByDefinitionId","createFireManualTriggerRoute","workflows","method","path","description","schema","params","object","definitionId","string","uuid","body","response","code","details","field","source","env_key","optional","errorHandler","error","message","status","envKey","undefined","handler","request","reply","userContext","subscription","canAccess","workspaceId","run","subscriptionId","id","callerWorkspaceId","userId","inputs","workflow_run_id"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,4BAA4B;AAC7D,SACEC,2BAA2B,EAC3BC,+BAA+B,QAC1B,4BAA4B;AAEnC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,0BAA0B,QAAO,kBAAkB;AAC3D,SAAQC,sBAAsB,QAAO,uBAAuB;AAC5D,SAAQC,gCAAgC,QAAO,4BAA4B;AAC3E,SAAQC,mCAAmC,QAAO,uBAAuB;AAEzE,OAAO,SAASC,6BAA6BC,SAAgC;IAC3E,OAAOP,YAAY;QACjBQ,QAAQ;QACRC,MAAM;QACNC,aAAa;QACbC,QAAQ;YACNC,QAAQX,EAAEY,MAAM,CAAC;gBACfC,cAAcb,EAAEc,MAAM,GAAGC,IAAI;YAC/B;YACAC,MAAMpB;YACNqB,UAAU;gBACR,KAAKpB;gBACL,KAAKG,EAAEY,MAAM,CAAC;oBACZM,MAAMlB,EAAEc,MAAM;oBACdK,SAASnB,EAAEY,MAAM,CAAC;wBAChBQ,OAAOpB,EAAEc,MAAM;wBACfO,QAAQrB,EAAEc,MAAM;wBAChBQ,SAAStB,EAAEc,MAAM,GAAGS,QAAQ;oBAC9B;gBACF;YACF;QACF;QACAC,cAAc,CAACC;YACb,IAAIA,iBAAiBxB,4BAA4B;gBAC/C,MAAM,IAAIH,YAAY2B,MAAMC,OAAO,EAAE,4BAA4B;oBAACC,QAAQ;gBAAG;YAC/E;YACA,IAAIxB,iCAAiCsB,QAAQ;gBAC3C,MAAM,IAAI3B,YACR,6CACA,uCACA;oBACE6B,QAAQ;oBACRR,SAAS;wBACPC,OAAOK,MAAMN,OAAO,CAACC,KAAK;wBAC1BC,QAAQI,MAAMN,OAAO,CAACE,MAAM;wBAC5B,GAAII,MAAMN,OAAO,CAACS,MAAM,KAAKC,YAAY,CAAC,IAAI;4BAACP,SAASG,MAAMN,OAAO,CAACS,MAAM;wBAAA,CAAC;oBAC/E;gBACF;YAEJ;YACA,MAAMH;QACR;QACAK,SAAS,OAAOC,SAASC;YACvB,MAAM,EAACnB,YAAY,EAAC,GAAGkB,QAAQpB,MAAM;YACrC,MAAMsB,cAActC,mBAAmBoC;YAEvC,MAAMG,eAAe,MAAM9B,oCAAoCS;YAC/D,gGAAgG;YAChG,IAAI,CAACqB,gBAAgB,CAACD,YAAYE,SAAS,CAACD,aAAaE,WAAW,GAAG;gBACrE,MAAM,IAAInC,2BAA2BY;YACvC;YAEA,MAAMwB,MAAM,MAAMnC,uBAAuB;gBACvCI;gBACAgC,gBAAgBJ,aAAaK,EAAE;gBAC/BC,mBAAmBN,aAAaE,WAAW;gBAC3CK,QAAQR,YAAYQ,MAAM;gBAC1BC,QAAQX,QAAQf,IAAI,CAAC0B,MAAM;YAC7B;YAEAV,MAAML,MAAM,CAAC;YACb,OAAO;gBAACgB,iBAAiBN,IAAIE,EAAE;YAAA;QACjC;IACF;AACF"}
@@ -1,3 +1,4 @@
1
+ import type { WorkflowsModuleClient } from '@shipfox/api-workflows-dto/inter-module';
1
2
  import type { RouteGroup } from '@shipfox/node-fastify';
2
- export declare const triggerRoutes: RouteGroup[];
3
+ export declare function createTriggerRoutes(workflows: WorkflowsModuleClient): RouteGroup[];
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAMtD,eAAO,MAAM,aAAa,EAAE,UAAU,EAarC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAMtD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,UAAU,EAAE,CAelF"}
@@ -1,27 +1,29 @@
1
1
  import { AUTH_USER } from '@shipfox/api-auth-context';
2
- import { fireManualTriggerRoute } from './fire-manual.js';
2
+ import { createFireManualTriggerRoute } from './fire-manual.js';
3
3
  import { getTriggerEventRoute } from './get-trigger-event.js';
4
4
  import { listTriggerEventFacetsRoute } from './list-trigger-event-facets.js';
5
5
  import { listTriggerEventsRoute } from './list-trigger-events.js';
6
- export const triggerRoutes = [
7
- {
8
- prefix: '/workflow-definitions',
9
- auth: AUTH_USER,
10
- routes: [
11
- fireManualTriggerRoute
12
- ]
13
- },
14
- {
15
- // The static /facets path is matched ahead of the /:id detail route by Fastify's
16
- // radix router, so registration order does not affect resolution.
17
- prefix: '/trigger-events',
18
- auth: AUTH_USER,
19
- routes: [
20
- listTriggerEventFacetsRoute,
21
- listTriggerEventsRoute,
22
- getTriggerEventRoute
23
- ]
24
- }
25
- ];
6
+ export function createTriggerRoutes(workflows) {
7
+ return [
8
+ {
9
+ prefix: '/workflow-definitions',
10
+ auth: AUTH_USER,
11
+ routes: [
12
+ createFireManualTriggerRoute(workflows)
13
+ ]
14
+ },
15
+ {
16
+ // The static /facets path is matched ahead of the /:id detail route by Fastify's
17
+ // radix router, so registration order does not affect resolution.
18
+ prefix: '/trigger-events',
19
+ auth: AUTH_USER,
20
+ routes: [
21
+ listTriggerEventFacetsRoute,
22
+ listTriggerEventsRoute,
23
+ getTriggerEventRoute
24
+ ]
25
+ }
26
+ ];
27
+ }
26
28
 
27
29
  //# sourceMappingURL=index.js.map