@shipfox/api-definitions 5.0.0 → 7.1.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 +11 -13
- package/CHANGELOG.md +49 -0
- package/dist/core/entities/workflow-definition.d.ts +2 -5
- package/dist/core/entities/workflow-definition.d.ts.map +1 -1
- package/dist/core/entities/workflow-definition.js.map +1 -1
- package/dist/core/entities/workflow-model.d.ts +1 -137
- package/dist/core/entities/workflow-model.d.ts.map +1 -1
- package/dist/core/entities/workflow-model.js.map +1 -1
- package/dist/core/integrations.d.ts +25 -0
- package/dist/core/integrations.d.ts.map +1 -0
- package/dist/core/integrations.js +30 -0
- package/dist/core/integrations.js.map +1 -0
- package/dist/core/sync-definitions.d.ts +2 -2
- package/dist/core/sync-definitions.d.ts.map +1 -1
- package/dist/core/sync-definitions.js +23 -14
- package/dist/core/sync-definitions.js.map +1 -1
- package/dist/core/workflow-model/constants.d.ts +1 -1
- package/dist/core/workflow-model/constants.d.ts.map +1 -1
- package/dist/core/workflow-model/constants.js +1 -1
- package/dist/core/workflow-model/constants.js.map +1 -1
- package/dist/core/workflow-model/normalize-job-checkout.d.ts +2 -2
- package/dist/core/workflow-model/normalize-job-checkout.d.ts.map +1 -1
- package/dist/core/workflow-model/normalize-job-checkout.js +2 -6
- package/dist/core/workflow-model/normalize-job-checkout.js.map +1 -1
- package/dist/core/workflow-model/normalize-job-success.d.ts +2 -1
- package/dist/core/workflow-model/normalize-job-success.d.ts.map +1 -1
- package/dist/core/workflow-model/normalize-job-success.js +2 -1
- package/dist/core/workflow-model/normalize-job-success.js.map +1 -1
- package/dist/db/db.d.ts +2 -2
- package/dist/db/schema/sync-states.d.ts +1 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -11
- package/dist/index.js.map +1 -1
- package/dist/presentation/index.d.ts +1 -1
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +1 -1
- package/dist/presentation/index.js.map +1 -1
- package/dist/presentation/inter-module.d.ts +4 -0
- package/dist/presentation/inter-module.d.ts.map +1 -0
- package/dist/presentation/inter-module.js +25 -0
- package/dist/presentation/inter-module.js.map +1 -0
- package/dist/presentation/routes/create-definition.d.ts +5 -6
- package/dist/presentation/routes/create-definition.d.ts.map +1 -1
- package/dist/presentation/routes/create-definition.js +7 -19
- package/dist/presentation/routes/create-definition.js.map +1 -1
- package/dist/presentation/routes/get-definition.d.ts +2 -1
- package/dist/presentation/routes/get-definition.d.ts.map +1 -1
- package/dist/presentation/routes/get-definition.js +26 -35
- package/dist/presentation/routes/get-definition.js.map +1 -1
- package/dist/presentation/routes/index.d.ts +1 -2
- package/dist/presentation/routes/index.d.ts.map +1 -1
- package/dist/presentation/routes/index.js +5 -6
- package/dist/presentation/routes/index.js.map +1 -1
- package/dist/presentation/routes/list-definitions.d.ts +2 -1
- package/dist/presentation/routes/list-definitions.d.ts.map +1 -1
- package/dist/presentation/routes/list-definitions.js +36 -45
- package/dist/presentation/routes/list-definitions.js.map +1 -1
- package/dist/presentation/routes/project-access.d.ts +10 -0
- package/dist/presentation/routes/project-access.d.ts.map +1 -0
- package/dist/presentation/routes/project-access.js +17 -0
- package/dist/presentation/routes/project-access.js.map +1 -0
- package/dist/temporal/activities/sync-activities.d.ts +3 -9
- package/dist/temporal/activities/sync-activities.d.ts.map +1 -1
- package/dist/temporal/activities/sync-activities.js +10 -14
- package/dist/temporal/activities/sync-activities.js.map +1 -1
- package/dist/temporal/workflows/index.bundle.js +17195 -3337
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +16 -32
- package/src/core/entities/workflow-definition.ts +3 -6
- package/src/core/entities/workflow-model.ts +1 -162
- package/src/core/integrations.ts +39 -0
- package/src/core/sync-definitions.test.ts +19 -17
- package/src/core/sync-definitions.ts +26 -20
- package/src/core/workflow-model/constants.ts +1 -1
- package/src/core/workflow-model/normalize-job-checkout.ts +2 -5
- package/src/core/workflow-model/normalize-job-success.ts +2 -1
- package/src/db/definitions.test.ts +68 -7
- package/src/index.ts +12 -31
- package/src/presentation/index.ts +1 -1
- package/src/presentation/inter-module.ts +25 -0
- package/src/presentation/routes/create-definition.test.ts +59 -63
- package/src/presentation/routes/create-definition.ts +15 -34
- package/src/presentation/routes/get-definition.test.ts +14 -8
- package/src/presentation/routes/get-definition.ts +25 -28
- package/src/presentation/routes/index.test.ts +8 -1
- package/src/presentation/routes/index.ts +5 -7
- package/src/presentation/routes/list-definitions.test.ts +8 -7
- package/src/presentation/routes/list-definitions.ts +33 -36
- package/src/presentation/routes/project-access.ts +16 -0
- package/src/temporal/activities/sync-activities.test.ts +14 -6
- package/src/temporal/activities/sync-activities.ts +20 -33
- package/tsconfig.build.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipfox/api-definitions",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "7.1.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/ShipfoxHQ/shipfox.git",
|
|
@@ -30,47 +30,31 @@
|
|
|
30
30
|
"js-yaml": "^4.1.0",
|
|
31
31
|
"yaml": "^2.8.3",
|
|
32
32
|
"zod": "^4.4.3",
|
|
33
|
-
"@shipfox/api-agent-dto": "
|
|
34
|
-
"@shipfox/api-auth-context": "
|
|
35
|
-
"@shipfox/api-definitions-dto": "
|
|
36
|
-
"@shipfox/api-integration-core": "
|
|
37
|
-
"@shipfox/api-
|
|
38
|
-
"@shipfox/api-
|
|
39
|
-
"@shipfox/api-projects-dto": "5.0.0",
|
|
40
|
-
"@shipfox/api-secrets-dto": "5.0.0",
|
|
33
|
+
"@shipfox/api-agent-dto": "6.0.0",
|
|
34
|
+
"@shipfox/api-auth-context": "7.1.0",
|
|
35
|
+
"@shipfox/api-definitions-dto": "6.0.0",
|
|
36
|
+
"@shipfox/api-integration-core-dto": "6.0.0",
|
|
37
|
+
"@shipfox/api-projects-dto": "6.0.0",
|
|
38
|
+
"@shipfox/api-secrets-dto": "6.0.0",
|
|
41
39
|
"@shipfox/config": "1.2.2",
|
|
42
40
|
"@shipfox/expression": "1.1.3",
|
|
43
|
-
"@shipfox/
|
|
44
|
-
"@shipfox/node-
|
|
45
|
-
"@shipfox/node-
|
|
46
|
-
"@shipfox/node-
|
|
47
|
-
"@shipfox/node-
|
|
41
|
+
"@shipfox/inter-module": "0.2.0",
|
|
42
|
+
"@shipfox/node-drizzle": "0.3.2",
|
|
43
|
+
"@shipfox/node-fastify": "0.3.0",
|
|
44
|
+
"@shipfox/node-error-monitoring": "0.2.0",
|
|
45
|
+
"@shipfox/node-module": "0.5.0",
|
|
46
|
+
"@shipfox/node-opentelemetry": "0.6.0",
|
|
47
|
+
"@shipfox/node-outbox": "0.2.4",
|
|
48
48
|
"@shipfox/node-postgres": "0.4.2",
|
|
49
|
-
"@shipfox/node-temporal": "0.
|
|
49
|
+
"@shipfox/node-temporal": "0.4.0",
|
|
50
50
|
"@shipfox/runner-labels": "0.1.1",
|
|
51
51
|
"@shipfox/workflow-document": "2.1.1"
|
|
52
52
|
},
|
|
53
|
-
"devDependencies": {
|
|
54
|
-
"@temporalio/client": "1.18.1",
|
|
55
|
-
"@temporalio/testing": "1.18.1",
|
|
56
|
-
"@temporalio/worker": "1.18.1",
|
|
57
|
-
"@types/js-yaml": "^4.0.9",
|
|
58
|
-
"@types/pg": "^8.15.5",
|
|
59
|
-
"drizzle-kit": "^0.31.10",
|
|
60
|
-
"fastify": "^5.3.3",
|
|
61
|
-
"fastify-type-provider-zod": "^6.0.0",
|
|
62
|
-
"fishery": "^2.4.0",
|
|
63
|
-
"@shipfox/biome": "1.8.2",
|
|
64
|
-
"@shipfox/regex": "0.2.2",
|
|
65
|
-
"@shipfox/swc": "1.2.6",
|
|
66
|
-
"@shipfox/ts-config": "1.3.8",
|
|
67
|
-
"@shipfox/typescript": "1.1.7",
|
|
68
|
-
"@shipfox/vitest": "1.2.3"
|
|
69
|
-
},
|
|
70
53
|
"scripts": {
|
|
71
54
|
"build": "shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js",
|
|
72
55
|
"check": "shipfox-biome-check",
|
|
73
56
|
"check:fix": "shipfox-biome-check --write",
|
|
57
|
+
"depcruise": "shipfox-depcruise",
|
|
74
58
|
"test": "shipfox-vitest-run",
|
|
75
59
|
"test:watch": "shipfox-vitest-watch",
|
|
76
60
|
"type": "shipfox-tsc-check",
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
+
import type {WorkflowModel, WorkflowSourceSnapshot} from '@shipfox/api-definitions-dto';
|
|
1
2
|
import type {WorkflowDocument} from '@shipfox/workflow-document';
|
|
2
|
-
import type {WorkflowModel} from './workflow-model.js';
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type {WorkflowSourceSnapshot};
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
content: string;
|
|
8
|
-
format: 'yaml';
|
|
9
|
-
}
|
|
6
|
+
export type WorkflowSpec = WorkflowDocument;
|
|
10
7
|
|
|
11
8
|
export interface WorkflowDefinitionPayload {
|
|
12
9
|
document: WorkflowDocument;
|
|
@@ -1,162 +1 @@
|
|
|
1
|
-
|
|
2
|
-
ExpressionType,
|
|
3
|
-
OutputDeclarations,
|
|
4
|
-
ResolvedFieldSegment,
|
|
5
|
-
WorkflowExpression,
|
|
6
|
-
} from '@shipfox/expression';
|
|
7
|
-
import type {AgentThinking, Harness} from '@shipfox/workflow-document';
|
|
8
|
-
|
|
9
|
-
export type WorkflowFieldTemplate = readonly ResolvedFieldSegment[];
|
|
10
|
-
export type WorkflowEnvTemplates = Readonly<Record<string, WorkflowFieldTemplate>>;
|
|
11
|
-
export type WorkflowOutputTemplates = Readonly<Record<string, WorkflowFieldTemplate>>;
|
|
12
|
-
|
|
13
|
-
export interface WorkflowModel {
|
|
14
|
-
readonly kind: 'workflow';
|
|
15
|
-
readonly name: string;
|
|
16
|
-
readonly env?: Readonly<Record<string, string>>;
|
|
17
|
-
readonly templates?: {
|
|
18
|
-
readonly env?: WorkflowEnvTemplates;
|
|
19
|
-
};
|
|
20
|
-
readonly triggers: readonly WorkflowModelTrigger[];
|
|
21
|
-
readonly jobs: readonly WorkflowModelJob[];
|
|
22
|
-
readonly dependencies: readonly WorkflowModelDependency[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface WorkflowModelTrigger {
|
|
26
|
-
readonly id: string;
|
|
27
|
-
readonly key: string;
|
|
28
|
-
readonly source: string;
|
|
29
|
-
readonly event: string;
|
|
30
|
-
readonly inputs?: Readonly<Record<string, unknown>>;
|
|
31
|
-
readonly filter?: string;
|
|
32
|
-
readonly config?: Readonly<Record<string, unknown>>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface WorkflowModelJob {
|
|
36
|
-
readonly id: string;
|
|
37
|
-
readonly key: string;
|
|
38
|
-
readonly mode: WorkflowModelJobMode;
|
|
39
|
-
readonly runner: readonly string[];
|
|
40
|
-
readonly runnerTemplates?: readonly WorkflowFieldTemplate[];
|
|
41
|
-
readonly checkout: WorkflowModelJobCheckout;
|
|
42
|
-
readonly if?: WorkflowExpression;
|
|
43
|
-
readonly success?: string;
|
|
44
|
-
readonly outputs?: WorkflowOutputTemplates;
|
|
45
|
-
readonly outputTypes?: Readonly<Record<string, ExpressionType>>;
|
|
46
|
-
readonly executionTimeoutMs?: number;
|
|
47
|
-
readonly listening?: WorkflowModelJobListening;
|
|
48
|
-
readonly name?: WorkflowFieldTemplate;
|
|
49
|
-
readonly env?: Readonly<Record<string, string>>;
|
|
50
|
-
readonly templates?: {
|
|
51
|
-
readonly env?: WorkflowEnvTemplates;
|
|
52
|
-
};
|
|
53
|
-
readonly dependencies: readonly string[];
|
|
54
|
-
readonly steps: readonly WorkflowModelStep[];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type WorkflowModelJobMode = 'one_shot' | 'listening';
|
|
58
|
-
|
|
59
|
-
export interface WorkflowModelJobListening {
|
|
60
|
-
readonly on: readonly WorkflowModelListeningTrigger[];
|
|
61
|
-
readonly until?: readonly WorkflowModelListeningTrigger[];
|
|
62
|
-
readonly timeoutMs?: number;
|
|
63
|
-
readonly maxExecutions?: number;
|
|
64
|
-
readonly batch?: WorkflowModelListeningBatch;
|
|
65
|
-
readonly onResolve: 'finish' | 'cancel';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface WorkflowModelListeningTrigger {
|
|
69
|
-
readonly source: string;
|
|
70
|
-
readonly event: string;
|
|
71
|
-
readonly inputs?: Readonly<Record<string, unknown>>;
|
|
72
|
-
readonly filter?: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface WorkflowModelListeningBatch {
|
|
76
|
-
readonly debounceMs?: number;
|
|
77
|
-
readonly maxSize?: number;
|
|
78
|
-
readonly maxWaitMs?: number;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface WorkflowModelJobCheckout {
|
|
82
|
-
readonly permissions: {readonly contents: 'read' | 'write'};
|
|
83
|
-
readonly persistCredentials: boolean;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export type WorkflowModelStep = WorkflowModelRunStep | WorkflowModelAgentStep;
|
|
87
|
-
|
|
88
|
-
interface WorkflowModelStepBase {
|
|
89
|
-
readonly id: string;
|
|
90
|
-
readonly key?: string;
|
|
91
|
-
readonly if?: WorkflowExpression;
|
|
92
|
-
readonly name?: string;
|
|
93
|
-
readonly outputs?: OutputDeclarations;
|
|
94
|
-
readonly gate?: WorkflowModelStepGate;
|
|
95
|
-
readonly sourceLocation?: WorkflowSourceLocation;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export interface WorkflowModelRunStep extends WorkflowModelStepBase {
|
|
99
|
-
readonly kind: 'run';
|
|
100
|
-
readonly command: WorkflowModelRunCommand;
|
|
101
|
-
readonly env?: Readonly<Record<string, string>>;
|
|
102
|
-
readonly templates?: {
|
|
103
|
-
readonly command?: WorkflowFieldTemplate;
|
|
104
|
-
readonly name?: WorkflowFieldTemplate;
|
|
105
|
-
readonly env?: WorkflowEnvTemplates;
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface WorkflowModelAgentStep extends WorkflowModelStepBase {
|
|
110
|
-
readonly kind: 'agent';
|
|
111
|
-
readonly harness?: Harness;
|
|
112
|
-
readonly model?: string;
|
|
113
|
-
readonly provider?: string;
|
|
114
|
-
readonly thinking?: AgentThinking;
|
|
115
|
-
readonly tools?: readonly string[];
|
|
116
|
-
readonly integrations?: readonly WorkflowModelStepIntegration[];
|
|
117
|
-
readonly prompt: string;
|
|
118
|
-
readonly templates?: {
|
|
119
|
-
readonly prompt?: WorkflowFieldTemplate;
|
|
120
|
-
readonly model?: WorkflowFieldTemplate;
|
|
121
|
-
readonly provider?: WorkflowFieldTemplate;
|
|
122
|
-
readonly name?: WorkflowFieldTemplate;
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export interface WorkflowModelStepIntegration {
|
|
127
|
-
readonly connection?: string;
|
|
128
|
-
readonly include: readonly string[];
|
|
129
|
-
readonly exclude?: readonly string[];
|
|
130
|
-
readonly allowWrite: boolean;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface WorkflowSourceLocation {
|
|
134
|
-
readonly startLine: number;
|
|
135
|
-
readonly endLine: number;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export type WorkflowStepSourceLocationMap = ReadonlyMap<
|
|
139
|
-
string,
|
|
140
|
-
ReadonlyMap<number, WorkflowSourceLocation>
|
|
141
|
-
>;
|
|
142
|
-
|
|
143
|
-
export interface WorkflowModelRunCommand {
|
|
144
|
-
readonly kind: 'shell';
|
|
145
|
-
readonly value: string;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export interface WorkflowModelStepGate {
|
|
149
|
-
readonly success?: WorkflowExpression;
|
|
150
|
-
readonly onFailure?: WorkflowModelStepFailureAction;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export interface WorkflowModelStepFailureAction {
|
|
154
|
-
readonly restartFrom: string;
|
|
155
|
-
readonly feedback?: string;
|
|
156
|
-
readonly feedbackTemplate?: WorkflowFieldTemplate;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export interface WorkflowModelDependency {
|
|
160
|
-
readonly from: string;
|
|
161
|
-
readonly to: string;
|
|
162
|
-
}
|
|
1
|
+
export type * from '@shipfox/api-definitions-dto';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type IntegrationsModuleClient,
|
|
3
|
+
integrationsInterModuleContract,
|
|
4
|
+
} from '@shipfox/api-integration-core-dto';
|
|
5
|
+
|
|
6
|
+
export type DefinitionsSourceControl = {
|
|
7
|
+
resolveRepository: IntegrationsModuleClient['resolveSourceRepository'];
|
|
8
|
+
listFiles: IntegrationsModuleClient['listSourceFiles'];
|
|
9
|
+
fetchFile: IntegrationsModuleClient['fetchSourceFile'];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function createDefinitionsSourceControl(
|
|
13
|
+
integrations: IntegrationsModuleClient,
|
|
14
|
+
): DefinitionsSourceControl {
|
|
15
|
+
return {
|
|
16
|
+
resolveRepository: integrations.resolveSourceRepository,
|
|
17
|
+
listFiles: integrations.listSourceFiles,
|
|
18
|
+
fetchFile: integrations.fetchSourceFile,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function loadIntegrationValidationContext(
|
|
23
|
+
integrations: IntegrationsModuleClient,
|
|
24
|
+
workspaceId: string,
|
|
25
|
+
defaultConnectionId: string,
|
|
26
|
+
) {
|
|
27
|
+
const context = await integrations.getAgentToolsContext({workspaceId, defaultConnectionId});
|
|
28
|
+
return {
|
|
29
|
+
agentToolSelectionCatalogs: new Map(
|
|
30
|
+
context.selectionCatalogs.map(({provider, selectors}) => [provider, {selectors}]),
|
|
31
|
+
),
|
|
32
|
+
workspaceConnectionSnapshot: new Map(
|
|
33
|
+
context.workspaceConnections.map(({slug, ...connection}) => [slug, connection]),
|
|
34
|
+
),
|
|
35
|
+
defaultConnectionSlug: context.defaultConnection?.slug,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {integrationsInterModuleContract};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
IntegrationConnectionWorkspaceMismatchError,
|
|
5
|
-
IntegrationProviderError,
|
|
6
|
-
type IntegrationSourceControlService,
|
|
7
|
-
} from '@shipfox/api-integration-core';
|
|
1
|
+
import type {IntegrationSourceControlService} from '@shipfox/api-integration-core';
|
|
2
|
+
import {integrationsInterModuleContract} from '@shipfox/api-integration-core-dto';
|
|
3
|
+
import {createInterModuleKnownError} from '@shipfox/inter-module';
|
|
8
4
|
import {LOWERCASE_SHA256_HEX_RE} from '@shipfox/regex';
|
|
9
5
|
import type {IntegrationValidationContext} from './entities/integration-context.js';
|
|
10
6
|
import {DefinitionSyncPermanentError} from './errors.js';
|
|
@@ -349,13 +345,15 @@ describe('classifySyncFailure', () => {
|
|
|
349
345
|
['malformed-provider-response', false, 'provider-malformed-response'],
|
|
350
346
|
['content-too-large', false, 'content-too-large'],
|
|
351
347
|
['too-many-files', false, 'too-many-files'],
|
|
352
|
-
])('maps
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
348
|
+
])('maps provider failures (%s) to retryable=%s code=%s', (reason, retryable, code) => {
|
|
349
|
+
const error = createInterModuleKnownError(
|
|
350
|
+
integrationsInterModuleContract.methods.resolveSourceRepository,
|
|
351
|
+
'provider-failure',
|
|
352
|
+
{reason},
|
|
356
353
|
);
|
|
354
|
+
const result = classifySyncFailure(error);
|
|
357
355
|
|
|
358
|
-
expect(result).toEqual({code, message:
|
|
356
|
+
expect(result).toEqual({code, message: error.message, retryable});
|
|
359
357
|
});
|
|
360
358
|
|
|
361
359
|
it('classifies DefinitionSyncPermanentError as non-retryable', () => {
|
|
@@ -367,11 +365,15 @@ describe('classifySyncFailure', () => {
|
|
|
367
365
|
});
|
|
368
366
|
|
|
369
367
|
it.each([
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
])('classifies
|
|
374
|
-
const error =
|
|
368
|
+
'connection-not-found',
|
|
369
|
+
'connection-inactive',
|
|
370
|
+
'connection-workspace-mismatch',
|
|
371
|
+
] as const)('classifies %s as non-retryable connection-unavailable', (code) => {
|
|
372
|
+
const error = createInterModuleKnownError(
|
|
373
|
+
integrationsInterModuleContract.methods.resolveSourceRepository,
|
|
374
|
+
code,
|
|
375
|
+
{connectionId: '00000000-0000-0000-0000-000000000000'},
|
|
376
|
+
);
|
|
375
377
|
|
|
376
378
|
const result = classifySyncFailure(error);
|
|
377
379
|
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import {createHash} from 'node:crypto';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
IntegrationConnectionNotFoundError,
|
|
5
|
-
IntegrationConnectionWorkspaceMismatchError,
|
|
6
|
-
IntegrationProviderError,
|
|
7
|
-
type IntegrationSourceControlService,
|
|
3
|
+
integrationsInterModuleContract,
|
|
8
4
|
MAX_REPOSITORY_FILE_BYTES,
|
|
9
|
-
} from '@shipfox/api-integration-core';
|
|
5
|
+
} from '@shipfox/api-integration-core-dto';
|
|
6
|
+
import {isInterModuleKnownError} from '@shipfox/inter-module';
|
|
10
7
|
import {boundedMap} from '@shipfox/node-module';
|
|
11
8
|
import type {IntegrationValidationContext} from './entities/integration-context.js';
|
|
12
9
|
import type {DefinitionSyncErrorCode} from './entities/sync-state.js';
|
|
13
10
|
import type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';
|
|
14
11
|
import {DefinitionParseError, DefinitionSyncPermanentError} from './errors.js';
|
|
15
12
|
import {hasAgentStepIntegrations} from './has-agent-step-integrations.js';
|
|
13
|
+
import type {DefinitionsSourceControl} from './integrations.js';
|
|
16
14
|
import {parseDefinition} from './parse-definition.js';
|
|
17
15
|
|
|
18
16
|
export const WORKFLOW_PREFIX = '.shipfox/workflows/';
|
|
@@ -24,7 +22,7 @@ export interface SyncSourceContext {
|
|
|
24
22
|
workspaceId: string;
|
|
25
23
|
sourceConnectionId: string;
|
|
26
24
|
sourceExternalRepositoryId: string;
|
|
27
|
-
sourceControl:
|
|
25
|
+
sourceControl: DefinitionsSourceControl;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
export interface ResolvedSyncSource {
|
|
@@ -173,19 +171,27 @@ export function classifySyncFailure(error: unknown): SyncFailureClassification {
|
|
|
173
171
|
if (error instanceof DefinitionSyncPermanentError) {
|
|
174
172
|
return {code: error.code, message: error.message, retryable: false};
|
|
175
173
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
code
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
174
|
+
const methods = [
|
|
175
|
+
integrationsInterModuleContract.methods.resolveSourceRepository,
|
|
176
|
+
integrationsInterModuleContract.methods.listSourceFiles,
|
|
177
|
+
integrationsInterModuleContract.methods.fetchSourceFile,
|
|
178
|
+
] as const;
|
|
179
|
+
for (const method of methods) {
|
|
180
|
+
if (!isInterModuleKnownError(method, error)) continue;
|
|
181
|
+
if (
|
|
182
|
+
error.code === 'connection-not-found' ||
|
|
183
|
+
error.code === 'connection-inactive' ||
|
|
184
|
+
error.code === 'connection-workspace-mismatch'
|
|
185
|
+
) {
|
|
186
|
+
return {code: 'connection-unavailable', message: error.message, retryable: false};
|
|
187
|
+
}
|
|
188
|
+
if (error.code === 'provider-failure') {
|
|
189
|
+
return {
|
|
190
|
+
code: providerErrorCode(error.details.reason),
|
|
191
|
+
message: error.message,
|
|
192
|
+
retryable: isProviderReasonRetryable(error.details.reason),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
189
195
|
}
|
|
190
196
|
return {
|
|
191
197
|
code: 'unknown',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {DEFAULT_RUN_TIMEOUT_MS} from '@shipfox/api-definitions-dto';
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
+
import {DEFAULT_JOB_CHECKOUT, type WorkflowModelJobCheckout} from '@shipfox/api-definitions-dto';
|
|
1
2
|
import type {WorkflowDocumentJobCheckout} from '@shipfox/workflow-document';
|
|
2
|
-
import type {WorkflowModelJobCheckout} from '../entities/workflow-model.js';
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
permissions: {contents: 'read'},
|
|
6
|
-
persistCredentials: true,
|
|
7
|
-
};
|
|
4
|
+
export {DEFAULT_JOB_CHECKOUT};
|
|
8
5
|
|
|
9
6
|
export function normalizeJobCheckout(
|
|
10
7
|
checkout: WorkflowDocumentJobCheckout | undefined,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import {DEFAULT_JOB_SUCCESS} from '@shipfox/api-definitions-dto';
|
|
1
2
|
import type {ExpressionTypeEnvironment} from '@shipfox/expression';
|
|
2
3
|
import type {WorkflowModelValidationIssue} from './invalid-workflow-model-error.js';
|
|
3
4
|
import {validatePredicateExpression} from './validate-predicate-expression.js';
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
+
export {DEFAULT_JOB_SUCCESS};
|
|
6
7
|
|
|
7
8
|
export function normalizeJobSuccess(params: {
|
|
8
9
|
source: string | undefined;
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import {DEFINITION_RESOLVED} from '@shipfox/api-definitions-dto';
|
|
2
2
|
import {
|
|
3
3
|
BATCH_SIZE,
|
|
4
|
+
countPendingOutboxRows as countPendingOutboxRowsFromRegistry,
|
|
5
|
+
createOutboxRegistry,
|
|
4
6
|
type DrainedEvent,
|
|
5
|
-
drainAll,
|
|
6
|
-
|
|
7
|
+
drainAll as drainFromRegistry,
|
|
8
|
+
type ModulePublisher,
|
|
9
|
+
markDispatched as markDispatchedFromRegistry,
|
|
10
|
+
type OutboxDispatchClaim,
|
|
7
11
|
type OutboxDispatchFailure,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
type PruneDispatchedOutboxRowsOptions,
|
|
13
|
+
pruneDispatchedOutboxRows as pruneFromRegistry,
|
|
14
|
+
recordDispatchFailure as recordFailureFromRegistry,
|
|
15
|
+
registerPublisher as registerInRegistry,
|
|
16
|
+
renewDispatchClaim as renewFromRegistry,
|
|
13
17
|
} from '@shipfox/node-module';
|
|
14
18
|
import {sql} from 'drizzle-orm';
|
|
15
19
|
import type {WorkflowDefinitionPayload} from '#core/entities/workflow-definition.js';
|
|
@@ -27,6 +31,44 @@ import {workflowDefinitions} from './schema/definitions.js';
|
|
|
27
31
|
import {definitionsOutbox} from './schema/outbox.js';
|
|
28
32
|
|
|
29
33
|
const MS_PER_DAY = 24 * 60 * 60 * 1_000;
|
|
34
|
+
let outboxRegistry = createOutboxRegistry();
|
|
35
|
+
|
|
36
|
+
function resetPublishers(): void {
|
|
37
|
+
outboxRegistry = createOutboxRegistry();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function registerPublisher(publisher: ModulePublisher): void {
|
|
41
|
+
registerInRegistry(outboxRegistry, publisher);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function drainAll(options?: {partition?: {workerIndex: number; workerCount: number}}) {
|
|
45
|
+
return drainFromRegistry(outboxRegistry, options);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function countPendingOutboxRows() {
|
|
49
|
+
return countPendingOutboxRowsFromRegistry(outboxRegistry);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function markDispatched(source: string, claims: string[] | OutboxDispatchClaim[]) {
|
|
53
|
+
return markDispatchedFromRegistry(outboxRegistry, source, claims);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function renewDispatchClaim(source: string, claim: OutboxDispatchClaim) {
|
|
57
|
+
return renewFromRegistry(outboxRegistry, source, claim);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function recordDispatchFailure(
|
|
61
|
+
source: string,
|
|
62
|
+
id: string,
|
|
63
|
+
failure: OutboxDispatchFailure,
|
|
64
|
+
claimExpiresAt?: Date,
|
|
65
|
+
) {
|
|
66
|
+
return recordFailureFromRegistry(outboxRegistry, source, id, failure, claimExpiresAt);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function pruneDispatchedOutboxRows(options: PruneDispatchedOutboxRowsOptions) {
|
|
70
|
+
return pruneFromRegistry(outboxRegistry, options);
|
|
71
|
+
}
|
|
30
72
|
|
|
31
73
|
function definitionFields(name = 'Test Workflow'): WorkflowDefinitionPayload {
|
|
32
74
|
const document = {
|
|
@@ -740,6 +782,25 @@ describe('definition queries', () => {
|
|
|
740
782
|
.where(sql`${definitionsOutbox.payload}->>'projectId' = ${projectId}`);
|
|
741
783
|
});
|
|
742
784
|
|
|
785
|
+
test('countPendingOutboxRows counts pending rows but excludes dispatched and dead-lettered rows', async () => {
|
|
786
|
+
await insertOutboxRow({projectId, marker: 'pending'});
|
|
787
|
+
await insertOutboxRow({projectId, marker: 'dispatched', dispatchedAt: new Date()});
|
|
788
|
+
await insertOutboxRow({projectId, marker: 'dead-lettered', deadLetteredAt: new Date()});
|
|
789
|
+
|
|
790
|
+
const pendingRows = await countPendingOutboxRows();
|
|
791
|
+
|
|
792
|
+
expect(pendingRows).toBe(1);
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
test('countPendingOutboxRows sums pending rows across every registered publisher', async () => {
|
|
796
|
+
registerPublisher({name: 'definitions-second', table: definitionsOutbox, db: () => db()});
|
|
797
|
+
await insertOutboxRow({projectId, marker: 'pending'});
|
|
798
|
+
|
|
799
|
+
const pendingRows = await countPendingOutboxRows();
|
|
800
|
+
|
|
801
|
+
expect(pendingRows).toBe(2);
|
|
802
|
+
});
|
|
803
|
+
|
|
743
804
|
test('drainAll returns undispatched outbox events', async () => {
|
|
744
805
|
await upsertDefinition({
|
|
745
806
|
projectId,
|
package/src/index.ts
CHANGED
|
@@ -5,12 +5,8 @@ import {
|
|
|
5
5
|
type DefinitionsEventMap,
|
|
6
6
|
definitionsEventSchemas,
|
|
7
7
|
} from '@shipfox/api-definitions-dto';
|
|
8
|
-
import type {
|
|
9
|
-
|
|
10
|
-
GetIntegrationConnectionByIdFn,
|
|
11
|
-
IntegrationSourceControlService,
|
|
12
|
-
LoadWorkspaceConnectionSnapshot,
|
|
13
|
-
} from '@shipfox/api-integration-core';
|
|
8
|
+
import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
|
|
9
|
+
import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
|
|
14
10
|
import {
|
|
15
11
|
PROJECT_SOURCE_BOUND,
|
|
16
12
|
PROJECT_SOURCE_COMMIT_OBSERVED,
|
|
@@ -18,8 +14,10 @@ import {
|
|
|
18
14
|
} from '@shipfox/api-projects-dto';
|
|
19
15
|
import {type ShipfoxModule, subscriberFactory} from '@shipfox/node-module';
|
|
20
16
|
import {logger} from '@shipfox/node-opentelemetry';
|
|
17
|
+
import {createDefinitionsSourceControl} from '#core/integrations.js';
|
|
21
18
|
import {db, definitionsOutbox, migrationsPath} from '#db/index.js';
|
|
22
19
|
import {createDefinitionRoutes} from '#presentation/index.js';
|
|
20
|
+
import {createDefinitionsInterModulePresentation} from '#presentation/inter-module.js';
|
|
23
21
|
import {
|
|
24
22
|
onProjectSourceBound,
|
|
25
23
|
onProjectSourceCommitObserved,
|
|
@@ -42,7 +40,6 @@ export {
|
|
|
42
40
|
normalizeWorkflowDocument,
|
|
43
41
|
} from '#core/index.js';
|
|
44
42
|
export {db, definitionsOutbox, getDefinitionById, migrationsPath} from '#db/index.js';
|
|
45
|
-
export {routes} from '#presentation/index.js';
|
|
46
43
|
|
|
47
44
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
48
45
|
const workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');
|
|
@@ -50,37 +47,20 @@ const workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');
|
|
|
50
47
|
const subscriber = subscriberFactory<DefinitionsEventMap & ProjectsEventMap>();
|
|
51
48
|
|
|
52
49
|
export interface CreateDefinitionsModuleOptions {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
loadWorkspaceConnectionSnapshot?: LoadWorkspaceConnectionSnapshot | undefined;
|
|
56
|
-
getIntegrationConnectionById?: GetIntegrationConnectionByIdFn | undefined;
|
|
50
|
+
projects: ProjectsModuleClient;
|
|
51
|
+
integrations: IntegrationsModuleClient;
|
|
57
52
|
}
|
|
58
53
|
|
|
59
54
|
export function createDefinitionsModule({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
loadWorkspaceConnectionSnapshot,
|
|
63
|
-
getIntegrationConnectionById,
|
|
55
|
+
projects,
|
|
56
|
+
integrations,
|
|
64
57
|
}: CreateDefinitionsModuleOptions): ShipfoxModule {
|
|
65
|
-
const
|
|
66
|
-
agentToolSelectionCatalogs === undefined ||
|
|
67
|
-
loadWorkspaceConnectionSnapshot === undefined ||
|
|
68
|
-
getIntegrationConnectionById === undefined
|
|
69
|
-
? undefined
|
|
70
|
-
: {
|
|
71
|
-
agentToolSelectionCatalogs,
|
|
72
|
-
loadWorkspaceConnectionSnapshot,
|
|
73
|
-
getIntegrationConnectionById,
|
|
74
|
-
};
|
|
58
|
+
const sourceControl = createDefinitionsSourceControl(integrations);
|
|
75
59
|
|
|
76
60
|
return {
|
|
77
61
|
name: 'definitions',
|
|
78
62
|
database: {db, migrationsPath},
|
|
79
|
-
routes: createDefinitionRoutes({
|
|
80
|
-
agentToolSelectionCatalogs,
|
|
81
|
-
loadWorkspaceConnectionSnapshot,
|
|
82
|
-
getIntegrationConnectionById,
|
|
83
|
-
}),
|
|
63
|
+
routes: createDefinitionRoutes({projects, integrations}),
|
|
84
64
|
publishers: [
|
|
85
65
|
{name: 'definitions', table: definitionsOutbox, db, eventSchemas: definitionsEventSchemas},
|
|
86
66
|
],
|
|
@@ -96,9 +76,10 @@ export function createDefinitionsModule({
|
|
|
96
76
|
{
|
|
97
77
|
taskQueue: DEFINITIONS_TASK_QUEUE,
|
|
98
78
|
workflowsPath,
|
|
99
|
-
activities: () => createDefinitionSyncActivities(sourceControl,
|
|
79
|
+
activities: () => createDefinitionSyncActivities(sourceControl, integrations),
|
|
100
80
|
workflows: [],
|
|
101
81
|
},
|
|
102
82
|
],
|
|
83
|
+
interModulePresentations: [createDefinitionsInterModulePresentation()],
|
|
103
84
|
};
|
|
104
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {createDefinitionRoutes
|
|
1
|
+
export {createDefinitionRoutes} from './routes/index.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {createWorkflowModelSnapshot} from '@shipfox/api-definitions-dto';
|
|
2
|
+
import {definitionsInterModuleContract} from '@shipfox/api-definitions-dto/inter-module';
|
|
3
|
+
import {defineInterModulePresentation, type InterModulePresentation} from '@shipfox/inter-module';
|
|
4
|
+
import {getDefinitionById} from '#db/definitions.js';
|
|
5
|
+
|
|
6
|
+
export function createDefinitionsInterModulePresentation(): InterModulePresentation<
|
|
7
|
+
typeof definitionsInterModuleContract
|
|
8
|
+
> {
|
|
9
|
+
return defineInterModulePresentation(definitionsInterModuleContract, {
|
|
10
|
+
getDefinitionForWorkflowRun: async ({definitionId}) => {
|
|
11
|
+
const definition = await getDefinitionById(definitionId);
|
|
12
|
+
if (!definition) return {definition: null};
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
definition: {
|
|
16
|
+
id: definition.id,
|
|
17
|
+
projectId: definition.projectId,
|
|
18
|
+
name: definition.name,
|
|
19
|
+
model: createWorkflowModelSnapshot(definition.model),
|
|
20
|
+
sourceSnapshot: definition.sourceSnapshot,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|