@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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +65 -0
- package/README.md +23 -3
- package/dist/core/dispatch-integration-event.d.ts +2 -0
- package/dist/core/dispatch-integration-event.d.ts.map +1 -1
- package/dist/core/dispatch-integration-event.js +9 -5
- package/dist/core/dispatch-integration-event.js.map +1 -1
- package/dist/core/drain-cron-schedules.d.ts +2 -0
- package/dist/core/drain-cron-schedules.d.ts.map +1 -1
- package/dist/core/drain-cron-schedules.js +1 -0
- package/dist/core/drain-cron-schedules.js.map +1 -1
- package/dist/core/fire-cron.d.ts +6 -2
- package/dist/core/fire-cron.d.ts.map +1 -1
- package/dist/core/fire-cron.js +8 -5
- package/dist/core/fire-cron.js.map +1 -1
- package/dist/core/fire-manual.d.ts +6 -2
- package/dist/core/fire-manual.d.ts.map +1 -1
- package/dist/core/fire-manual.js +8 -4
- package/dist/core/fire-manual.js.map +1 -1
- package/dist/core/route-event-to-job-listeners.d.ts +2 -0
- package/dist/core/route-event-to-job-listeners.d.ts.map +1 -1
- package/dist/core/route-event-to-job-listeners.js +2 -3
- package/dist/core/route-event-to-job-listeners.js.map +1 -1
- package/dist/core/workflows-client.d.ts +69 -0
- package/dist/core/workflows-client.d.ts.map +1 -0
- package/dist/core/workflows-client.js +20 -0
- package/dist/core/workflows-client.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -50
- package/dist/index.js.map +1 -1
- package/dist/presentation/index.d.ts +2 -2
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +2 -2
- package/dist/presentation/index.js.map +1 -1
- package/dist/presentation/routes/fire-manual.d.ts +2 -1
- package/dist/presentation/routes/fire-manual.d.ts.map +1 -1
- package/dist/presentation/routes/fire-manual.js +61 -58
- package/dist/presentation/routes/fire-manual.js.map +1 -1
- package/dist/presentation/routes/index.d.ts +2 -1
- package/dist/presentation/routes/index.d.ts.map +1 -1
- package/dist/presentation/routes/index.js +23 -21
- package/dist/presentation/routes/index.js.map +1 -1
- package/dist/presentation/subscribers/index.d.ts +1 -1
- package/dist/presentation/subscribers/index.d.ts.map +1 -1
- package/dist/presentation/subscribers/index.js +1 -1
- package/dist/presentation/subscribers/index.js.map +1 -1
- package/dist/presentation/subscribers/on-integration-event-received.d.ts +2 -1
- package/dist/presentation/subscribers/on-integration-event-received.d.ts.map +1 -1
- package/dist/presentation/subscribers/on-integration-event-received.js +16 -13
- package/dist/presentation/subscribers/on-integration-event-received.js.map +1 -1
- package/dist/temporal/activities/drain-cron-batch.d.ts +2 -1
- package/dist/temporal/activities/drain-cron-batch.d.ts.map +1 -1
- package/dist/temporal/activities/drain-cron-batch.js +2 -1
- package/dist/temporal/activities/drain-cron-batch.js.map +1 -1
- package/dist/temporal/activities/index.d.ts +4 -3
- package/dist/temporal/activities/index.d.ts.map +1 -1
- package/dist/temporal/activities/index.js +2 -2
- package/dist/temporal/activities/index.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +27 -35
- package/src/core/dispatch-integration-event.history-failure.test.ts +11 -6
- package/src/core/dispatch-integration-event.test.ts +50 -36
- package/src/core/dispatch-integration-event.ts +8 -5
- package/src/core/drain-cron-schedules.test.ts +30 -29
- package/src/core/drain-cron-schedules.ts +3 -0
- package/src/core/fire-cron.test.ts +35 -24
- package/src/core/fire-cron.ts +9 -7
- package/src/core/fire-manual.test.ts +19 -22
- package/src/core/fire-manual.ts +9 -6
- package/src/core/record-trigger-history.test.ts +3 -5
- package/src/core/route-event-to-job-listeners.test.ts +5 -4
- package/src/core/route-event-to-job-listeners.ts +5 -4
- package/src/core/workflows-client.test.ts +73 -0
- package/src/core/workflows-client.ts +32 -0
- package/src/index.ts +49 -42
- package/src/presentation/index.ts +2 -2
- package/src/presentation/routes/fire-manual.test.ts +14 -30
- package/src/presentation/routes/fire-manual.ts +62 -54
- package/src/presentation/routes/index.ts +18 -15
- package/src/presentation/subscribers/index.ts +1 -1
- package/src/presentation/subscribers/on-integration-event-received.test.ts +6 -3
- package/src/presentation/subscribers/on-integration-event-received.ts +20 -16
- package/src/temporal/activities/drain-cron-batch.ts +5 -1
- package/src/temporal/activities/index.ts +3 -2
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -3,68 +3,76 @@ import {
|
|
|
3
3
|
fireManualTriggerBodySchema,
|
|
4
4
|
fireManualTriggerResponseSchema,
|
|
5
5
|
} from '@shipfox/api-triggers-dto';
|
|
6
|
-
import {
|
|
6
|
+
import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';
|
|
7
7
|
import {ClientError, defineRoute} from '@shipfox/node-fastify';
|
|
8
8
|
import {z} from 'zod';
|
|
9
9
|
import {ManualTriggerNotFoundError} from '#core/errors.js';
|
|
10
10
|
import {fireManualSubscription} from '#core/fire-manual.js';
|
|
11
|
+
import {isInterpolationUnresolvableError} from '#core/workflows-client.js';
|
|
11
12
|
import {getManualSubscriptionByDefinitionId} from '#db/subscriptions.js';
|
|
12
13
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
body: fireManualTriggerBodySchema,
|
|
22
|
-
response: {
|
|
23
|
-
201: fireManualTriggerResponseSchema,
|
|
24
|
-
422: z.object({
|
|
25
|
-
code: z.string(),
|
|
26
|
-
details: z.object({
|
|
27
|
-
field: z.string(),
|
|
28
|
-
source: z.string(),
|
|
29
|
-
env_key: z.string().optional(),
|
|
30
|
-
}),
|
|
14
|
+
export function createFireManualTriggerRoute(workflows: WorkflowsModuleClient) {
|
|
15
|
+
return defineRoute({
|
|
16
|
+
method: 'POST',
|
|
17
|
+
path: '/:definitionId/fire-manual',
|
|
18
|
+
description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',
|
|
19
|
+
schema: {
|
|
20
|
+
params: z.object({
|
|
21
|
+
definitionId: z.string().uuid(),
|
|
31
22
|
}),
|
|
23
|
+
body: fireManualTriggerBodySchema,
|
|
24
|
+
response: {
|
|
25
|
+
201: fireManualTriggerResponseSchema,
|
|
26
|
+
422: z.object({
|
|
27
|
+
code: z.string(),
|
|
28
|
+
details: z.object({
|
|
29
|
+
field: z.string(),
|
|
30
|
+
source: z.string(),
|
|
31
|
+
env_key: z.string().optional(),
|
|
32
|
+
}),
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
32
35
|
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
errorHandler: (error) => {
|
|
37
|
+
if (error instanceof ManualTriggerNotFoundError) {
|
|
38
|
+
throw new ClientError(error.message, 'manual-trigger-not-found', {status: 404});
|
|
39
|
+
}
|
|
40
|
+
if (isInterpolationUnresolvableError(error)) {
|
|
41
|
+
throw new ClientError(
|
|
42
|
+
'Workflow interpolation cannot be resolved',
|
|
43
|
+
'workflow-interpolation-unresolvable',
|
|
44
|
+
{
|
|
45
|
+
status: 422,
|
|
46
|
+
details: {
|
|
47
|
+
field: error.details.field,
|
|
48
|
+
source: error.details.source,
|
|
49
|
+
...(error.details.envKey === undefined ? {} : {env_key: error.details.envKey}),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
},
|
|
56
|
+
handler: async (request, reply) => {
|
|
57
|
+
const {definitionId} = request.params;
|
|
58
|
+
const userContext = requireUserContext(request);
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
const subscription = await getManualSubscriptionByDefinitionId(definitionId);
|
|
61
|
+
// 404 covers both "no such manual trigger" and "not your workspace" to avoid leaking existence.
|
|
62
|
+
if (!subscription || !userContext.canAccess(subscription.workspaceId)) {
|
|
63
|
+
throw new ManualTriggerNotFoundError(definitionId);
|
|
64
|
+
}
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
const run = await fireManualSubscription({
|
|
67
|
+
workflows,
|
|
68
|
+
subscriptionId: subscription.id,
|
|
69
|
+
callerWorkspaceId: subscription.workspaceId,
|
|
70
|
+
userId: userContext.userId,
|
|
71
|
+
inputs: request.body.inputs,
|
|
72
|
+
});
|
|
66
73
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
});
|
|
74
|
+
reply.status(201);
|
|
75
|
+
return {workflow_run_id: run.id};
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import {AUTH_USER} from '@shipfox/api-auth-context';
|
|
2
|
+
import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';
|
|
2
3
|
import type {RouteGroup} from '@shipfox/node-fastify';
|
|
3
|
-
import {
|
|
4
|
+
import {createFireManualTriggerRoute} from './fire-manual.js';
|
|
4
5
|
import {getTriggerEventRoute} from './get-trigger-event.js';
|
|
5
6
|
import {listTriggerEventFacetsRoute} from './list-trigger-event-facets.js';
|
|
6
7
|
import {listTriggerEventsRoute} from './list-trigger-events.js';
|
|
7
8
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
export function createTriggerRoutes(workflows: WorkflowsModuleClient): RouteGroup[] {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
prefix: '/workflow-definitions',
|
|
13
|
+
auth: AUTH_USER,
|
|
14
|
+
routes: [createFireManualTriggerRoute(workflows)],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
// The static /facets path is matched ahead of the /:id detail route by Fastify's
|
|
18
|
+
// radix router, so registration order does not affect resolution.
|
|
19
|
+
prefix: '/trigger-events',
|
|
20
|
+
auth: AUTH_USER,
|
|
21
|
+
routes: [listTriggerEventFacetsRoute, listTriggerEventsRoute, getTriggerEventRoute],
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export {onDefinitionDeleted} from './on-definition-deleted.js';
|
|
2
2
|
export {onDefinitionResolved} from './on-definition-resolved.js';
|
|
3
|
-
export {
|
|
3
|
+
export {createOnIntegrationEventReceived} from './on-integration-event-received.js';
|
|
4
4
|
export {onJobActivated} from './on-job-activated.js';
|
|
5
5
|
export {onJobTerminated} from './on-job-terminated.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {IntegrationEventReceivedEvent} from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';
|
|
2
3
|
import type {DomainEvent} from '@shipfox/node-outbox';
|
|
3
4
|
|
|
4
5
|
const dispatchIntegrationEvent = vi.fn();
|
|
@@ -7,8 +8,9 @@ vi.mock('#core/dispatch-integration-event.js', () => ({
|
|
|
7
8
|
dispatchIntegrationEvent: (...args: unknown[]) => dispatchIntegrationEvent(...args),
|
|
8
9
|
}));
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const {createOnIntegrationEventReceived} = await import('./on-integration-event-received.js');
|
|
12
|
+
|
|
13
|
+
const workflows = {} as WorkflowsModuleClient;
|
|
12
14
|
|
|
13
15
|
describe('onIntegrationEventReceived', () => {
|
|
14
16
|
beforeEach(() => {
|
|
@@ -35,9 +37,10 @@ describe('onIntegrationEventReceived', () => {
|
|
|
35
37
|
payload: envelope,
|
|
36
38
|
};
|
|
37
39
|
|
|
38
|
-
await
|
|
40
|
+
await createOnIntegrationEventReceived(workflows)(envelope, event);
|
|
39
41
|
|
|
40
42
|
expect(dispatchIntegrationEvent).toHaveBeenCalledWith({
|
|
43
|
+
workflows,
|
|
41
44
|
eventRef: event.id,
|
|
42
45
|
workspaceId: envelope.workspaceId,
|
|
43
46
|
provider: envelope.provider,
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import type {IntegrationEventReceivedEvent} from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';
|
|
2
3
|
import type {DomainEvent} from '@shipfox/node-outbox';
|
|
3
4
|
import {dispatchIntegrationEvent} from '#core/dispatch-integration-event.js';
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
export function createOnIntegrationEventReceived(workflows: WorkflowsModuleClient) {
|
|
7
|
+
return async function onIntegrationEventReceived(
|
|
8
|
+
envelope: IntegrationEventReceivedEvent,
|
|
9
|
+
event: DomainEvent<IntegrationEventReceivedEvent>,
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
await dispatchIntegrationEvent({
|
|
12
|
+
workflows,
|
|
13
|
+
eventRef: event.id,
|
|
14
|
+
workspaceId: envelope.workspaceId,
|
|
15
|
+
provider: envelope.provider,
|
|
16
|
+
source: envelope.source,
|
|
17
|
+
event: envelope.event,
|
|
18
|
+
deliveryId: envelope.deliveryId,
|
|
19
|
+
connectionId: envelope.connectionId,
|
|
20
|
+
connectionName: envelope.connectionName ?? null,
|
|
21
|
+
payload: envelope.payload,
|
|
22
|
+
receivedAt: new Date(envelope.receivedAt),
|
|
23
|
+
});
|
|
24
|
+
};
|
|
21
25
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';
|
|
1
2
|
import {Context} from '@temporalio/activity';
|
|
2
3
|
import {config} from '#config.js';
|
|
3
4
|
import {type CronDrainSummary, drainDueCronSchedules} from '#core/drain-cron-schedules.js';
|
|
4
5
|
|
|
5
|
-
export async function drainCronBatchActivity(
|
|
6
|
+
export async function drainCronBatchActivity(
|
|
7
|
+
workflows: WorkflowsModuleClient,
|
|
8
|
+
): Promise<CronDrainSummary> {
|
|
6
9
|
const ctx = Context.current();
|
|
7
10
|
return await drainDueCronSchedules({
|
|
11
|
+
workflows,
|
|
8
12
|
batchSize: config.TRIGGER_CRON_CLAIM_BATCH,
|
|
9
13
|
jitterWindowSeconds: config.TRIGGER_CRON_JITTER_WINDOW_SECONDS,
|
|
10
14
|
onScheduleProcessed: () => ctx.heartbeat(),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';
|
|
1
2
|
import {drainCronBatchActivity, readCronFanoutActivity} from './drain-cron-batch.js';
|
|
2
3
|
import {pruneTriggerEventsActivity} from './prune-trigger-events.js';
|
|
3
4
|
|
|
@@ -7,9 +8,9 @@ export function createTriggersMaintenanceActivities() {
|
|
|
7
8
|
};
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
export function createTriggersCronActivities() {
|
|
11
|
+
export function createTriggersCronActivities(workflows: WorkflowsModuleClient) {
|
|
11
12
|
return {
|
|
12
|
-
drainCronBatchActivity,
|
|
13
|
+
drainCronBatchActivity: () => drainCronBatchActivity(workflows),
|
|
13
14
|
readCronFanoutActivity,
|
|
14
15
|
};
|
|
15
16
|
}
|