@shipfox/api-definitions 13.1.0 → 14.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 (223) hide show
  1. package/.turbo/turbo-build.log +11 -11
  2. package/CHANGELOG.md +35 -0
  3. package/dist/core/entities/index.d.ts +1 -1
  4. package/dist/core/entities/index.d.ts.map +1 -1
  5. package/dist/core/entities/index.js +1 -1
  6. package/dist/core/entities/index.js.map +1 -1
  7. package/dist/core/entities/integration-context.d.ts +4 -0
  8. package/dist/core/entities/integration-context.d.ts.map +1 -1
  9. package/dist/core/entities/integration-context.js.map +1 -1
  10. package/dist/core/entities/sync-state.d.ts +10 -4
  11. package/dist/core/entities/sync-state.d.ts.map +1 -1
  12. package/dist/core/entities/sync-state.js +26 -7
  13. package/dist/core/entities/sync-state.js.map +1 -1
  14. package/dist/core/entities/validation-diagnostic.d.ts +8 -0
  15. package/dist/core/entities/validation-diagnostic.d.ts.map +1 -0
  16. package/dist/core/entities/validation-diagnostic.js +3 -0
  17. package/dist/core/entities/validation-diagnostic.js.map +1 -0
  18. package/dist/core/entities/workflow-definition.d.ts +2 -0
  19. package/dist/core/entities/workflow-definition.d.ts.map +1 -1
  20. package/dist/core/entities/workflow-definition.js.map +1 -1
  21. package/dist/core/errors.d.ts +10 -0
  22. package/dist/core/errors.d.ts.map +1 -1
  23. package/dist/core/errors.js +9 -0
  24. package/dist/core/errors.js.map +1 -1
  25. package/dist/core/index.d.ts +2 -1
  26. package/dist/core/index.d.ts.map +1 -1
  27. package/dist/core/index.js +2 -1
  28. package/dist/core/index.js.map +1 -1
  29. package/dist/core/integrations.d.ts +3 -1
  30. package/dist/core/integrations.d.ts.map +1 -1
  31. package/dist/core/integrations.js +10 -2
  32. package/dist/core/integrations.js.map +1 -1
  33. package/dist/core/parse-definition.d.ts +4 -4
  34. package/dist/core/parse-definition.d.ts.map +1 -1
  35. package/dist/core/parse-definition.js +5 -5
  36. package/dist/core/parse-definition.js.map +1 -1
  37. package/dist/core/resolve-definition-at-ref.d.ts +66 -0
  38. package/dist/core/resolve-definition-at-ref.d.ts.map +1 -0
  39. package/dist/core/resolve-definition-at-ref.js +374 -0
  40. package/dist/core/resolve-definition-at-ref.js.map +1 -0
  41. package/dist/core/sync-definitions.d.ts +2 -2
  42. package/dist/core/sync-definitions.d.ts.map +1 -1
  43. package/dist/core/sync-definitions.js +5 -5
  44. package/dist/core/sync-definitions.js.map +1 -1
  45. package/dist/core/validate-definition.d.ts +3 -3
  46. package/dist/core/validate-definition.d.ts.map +1 -1
  47. package/dist/core/validate-definition.js +17 -12
  48. package/dist/core/validate-definition.js.map +1 -1
  49. package/dist/core/workflow-model/cron-trigger.d.ts +1 -1
  50. package/dist/core/workflow-model/cron-trigger.d.ts.map +1 -1
  51. package/dist/core/workflow-model/cron-trigger.js +9 -5
  52. package/dist/core/workflow-model/cron-trigger.js.map +1 -1
  53. package/dist/core/workflow-model/index.d.ts +1 -1
  54. package/dist/core/workflow-model/index.d.ts.map +1 -1
  55. package/dist/core/workflow-model/index.js.map +1 -1
  56. package/dist/core/workflow-model/invalid-workflow-model-error.d.ts +4 -2
  57. package/dist/core/workflow-model/invalid-workflow-model-error.d.ts.map +1 -1
  58. package/dist/core/workflow-model/invalid-workflow-model-error.js.map +1 -1
  59. package/dist/core/workflow-model/normalize-job-listening.d.ts.map +1 -1
  60. package/dist/core/workflow-model/normalize-job-listening.js +51 -30
  61. package/dist/core/workflow-model/normalize-job-listening.js.map +1 -1
  62. package/dist/core/workflow-model/normalize-triggers.d.ts +1 -1
  63. package/dist/core/workflow-model/normalize-triggers.d.ts.map +1 -1
  64. package/dist/core/workflow-model/normalize-triggers.js +48 -18
  65. package/dist/core/workflow-model/normalize-triggers.js.map +1 -1
  66. package/dist/core/workflow-model/normalize-workflow-document.d.ts +1 -1
  67. package/dist/core/workflow-model/normalize-workflow-document.d.ts.map +1 -1
  68. package/dist/core/workflow-model/normalize-workflow-document.js +3 -3
  69. package/dist/core/workflow-model/normalize-workflow-document.js.map +1 -1
  70. package/dist/core/workflow-model/parse-interpolation-field.d.ts.map +1 -1
  71. package/dist/core/workflow-model/parse-interpolation-field.js +1 -15
  72. package/dist/core/workflow-model/parse-interpolation-field.js.map +1 -1
  73. package/dist/core/workflow-model/validate-predicate-expression.d.ts +3 -1
  74. package/dist/core/workflow-model/validate-predicate-expression.d.ts.map +1 -1
  75. package/dist/core/workflow-model/validate-predicate-expression.js +3 -0
  76. package/dist/core/workflow-model/validate-predicate-expression.js.map +1 -1
  77. package/dist/core/workflow-model/validation-issue.d.ts +2 -1
  78. package/dist/core/workflow-model/validation-issue.d.ts.map +1 -1
  79. package/dist/core/workflow-model/validation-issue.js +12 -15
  80. package/dist/core/workflow-model/validation-issue.js.map +1 -1
  81. package/dist/db/db.d.ts +196 -4
  82. package/dist/db/db.d.ts.map +1 -1
  83. package/dist/db/db.js +3 -1
  84. package/dist/db/db.js.map +1 -1
  85. package/dist/db/definition-triggers.js +3 -1
  86. package/dist/db/definition-triggers.js.map +1 -1
  87. package/dist/db/definitions.d.ts +17 -0
  88. package/dist/db/definitions.d.ts.map +1 -1
  89. package/dist/db/definitions.js +190 -23
  90. package/dist/db/definitions.js.map +1 -1
  91. package/dist/db/index.d.ts +2 -1
  92. package/dist/db/index.d.ts.map +1 -1
  93. package/dist/db/index.js +2 -1
  94. package/dist/db/index.js.map +1 -1
  95. package/dist/db/schema/definitions.d.ts +17 -0
  96. package/dist/db/schema/definitions.d.ts.map +1 -1
  97. package/dist/db/schema/definitions.js +8 -0
  98. package/dist/db/schema/definitions.js.map +1 -1
  99. package/dist/db/schema/sync-states.d.ts +7 -3
  100. package/dist/db/schema/sync-states.d.ts.map +1 -1
  101. package/dist/db/schema/sync-states.js +5 -1
  102. package/dist/db/schema/sync-states.js.map +1 -1
  103. package/dist/db/schema/workflows.d.ts +78 -0
  104. package/dist/db/schema/workflows.d.ts.map +1 -0
  105. package/dist/db/schema/workflows.js +17 -0
  106. package/dist/db/schema/workflows.js.map +1 -0
  107. package/dist/db/sync-states.d.ts +2 -2
  108. package/dist/db/sync-states.d.ts.map +1 -1
  109. package/dist/db/sync-states.js +4 -4
  110. package/dist/db/sync-states.js.map +1 -1
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +5 -1
  113. package/dist/index.js.map +1 -1
  114. package/dist/metrics/index.d.ts +2 -0
  115. package/dist/metrics/index.d.ts.map +1 -0
  116. package/dist/metrics/index.js +3 -0
  117. package/dist/metrics/index.js.map +1 -0
  118. package/dist/metrics/instance.d.ts +4 -0
  119. package/dist/metrics/instance.d.ts.map +1 -0
  120. package/dist/metrics/instance.js +19 -0
  121. package/dist/metrics/instance.js.map +1 -0
  122. package/dist/presentation/dto/definition.d.ts.map +1 -1
  123. package/dist/presentation/dto/definition.js +11 -4
  124. package/dist/presentation/dto/definition.js.map +1 -1
  125. package/dist/presentation/inter-module.d.ts +9 -1
  126. package/dist/presentation/inter-module.d.ts.map +1 -1
  127. package/dist/presentation/inter-module.js +66 -2
  128. package/dist/presentation/inter-module.js.map +1 -1
  129. package/dist/presentation/routes/create-definition.d.ts.map +1 -1
  130. package/dist/presentation/routes/create-definition.js +16 -3
  131. package/dist/presentation/routes/create-definition.js.map +1 -1
  132. package/dist/presentation/routes/get-definition.d.ts.map +1 -1
  133. package/dist/presentation/routes/get-definition.js +18 -4
  134. package/dist/presentation/routes/get-definition.js.map +1 -1
  135. package/dist/presentation/routes/project-access.d.ts +1 -0
  136. package/dist/presentation/routes/project-access.d.ts.map +1 -1
  137. package/dist/presentation/routes/validate-definition.js +3 -3
  138. package/dist/presentation/routes/validate-definition.js.map +1 -1
  139. package/dist/temporal/activities/sync-activities.d.ts +3 -3
  140. package/dist/temporal/activities/sync-activities.d.ts.map +1 -1
  141. package/dist/temporal/activities/sync-activities.js +7 -4
  142. package/dist/temporal/activities/sync-activities.js.map +1 -1
  143. package/dist/temporal/workflows/definition-sync.js +1 -1
  144. package/dist/temporal/workflows/definition-sync.js.map +1 -1
  145. package/dist/temporal/workflows/index.bundle.js +50 -22
  146. package/dist/tsconfig.test.tsbuildinfo +1 -1
  147. package/drizzle/0003_nebulous_nemesis.sql +11 -0
  148. package/drizzle/0004_workflow_ref_lookup.sql +1 -0
  149. package/drizzle/meta/0003_snapshot.json +627 -0
  150. package/drizzle/meta/0004_snapshot.json +649 -0
  151. package/drizzle/meta/_journal.json +14 -0
  152. package/drizzle.config.ts +1 -0
  153. package/package.json +7 -7
  154. package/src/core/entities/index.ts +1 -1
  155. package/src/core/entities/integration-context.ts +4 -0
  156. package/src/core/entities/sync-state.test.ts +49 -0
  157. package/src/core/entities/sync-state.ts +35 -12
  158. package/src/core/entities/validation-diagnostic.ts +8 -0
  159. package/src/core/entities/workflow-definition.ts +2 -0
  160. package/src/core/errors.ts +26 -0
  161. package/src/core/index.ts +12 -0
  162. package/src/core/integrations.test.ts +38 -0
  163. package/src/core/integrations.ts +10 -1
  164. package/src/core/parse-definition-diagnostics.test.ts +47 -0
  165. package/src/core/parse-definition.test.ts +29 -5
  166. package/src/core/parse-definition.ts +7 -7
  167. package/src/core/resolve-definition-at-ref.test.ts +792 -0
  168. package/src/core/resolve-definition-at-ref.ts +551 -0
  169. package/src/core/sync-definitions.test.ts +61 -2
  170. package/src/core/sync-definitions.ts +7 -7
  171. package/src/core/validate-definition.test.ts +31 -22
  172. package/src/core/validate-definition.ts +21 -13
  173. package/src/core/workflow-model/cron-trigger.ts +6 -2
  174. package/src/core/workflow-model/index.ts +1 -0
  175. package/src/core/workflow-model/invalid-workflow-model-error.ts +5 -1
  176. package/src/core/workflow-model/normalize-job-listening.ts +55 -23
  177. package/src/core/workflow-model/normalize-triggers.ts +44 -15
  178. package/src/core/workflow-model/normalize-workflow-document.test.ts +444 -36
  179. package/src/core/workflow-model/normalize-workflow-document.ts +8 -4
  180. package/src/core/workflow-model/parse-interpolation-field.ts +1 -23
  181. package/src/core/workflow-model/validate-predicate-expression.ts +6 -0
  182. package/src/core/workflow-model/validation-issue.ts +8 -13
  183. package/src/db/db.ts +7 -1
  184. package/src/db/definition-triggers.test.ts +44 -0
  185. package/src/db/definition-triggers.ts +1 -1
  186. package/src/db/definitions.test.ts +300 -1
  187. package/src/db/definitions.ts +282 -28
  188. package/src/db/index.ts +2 -0
  189. package/src/db/schema/definitions.test.ts +1 -0
  190. package/src/db/schema/definitions.ts +11 -0
  191. package/src/db/schema/sync-states.ts +12 -3
  192. package/src/db/schema/workflows.ts +23 -0
  193. package/src/db/sync-states.test.ts +87 -18
  194. package/src/db/sync-states.ts +6 -6
  195. package/src/db/workflow-lineage-migration.test.ts +158 -0
  196. package/src/index.ts +3 -1
  197. package/src/metrics/index.ts +1 -0
  198. package/src/metrics/instance.test.ts +50 -0
  199. package/src/metrics/instance.ts +23 -0
  200. package/src/presentation/dto/definition.test.ts +89 -1
  201. package/src/presentation/dto/definition.ts +8 -5
  202. package/src/presentation/inter-module.test.ts +177 -0
  203. package/src/presentation/inter-module.ts +77 -4
  204. package/src/presentation/routes/create-definition.test.ts +38 -0
  205. package/src/presentation/routes/create-definition.ts +20 -3
  206. package/src/presentation/routes/get-definition.test.ts +125 -11
  207. package/src/presentation/routes/get-definition.ts +21 -4
  208. package/src/presentation/routes/list-definitions.test.ts +1 -1
  209. package/src/presentation/routes/validate-definition.test.ts +1 -1
  210. package/src/presentation/routes/validate-definition.ts +3 -3
  211. package/src/presentation/subscribers/on-integration-connection-available.test.ts +3 -0
  212. package/src/temporal/activities/sync-activities.test.ts +46 -2
  213. package/src/temporal/activities/sync-activities.ts +9 -7
  214. package/src/temporal/workflows/definition-sync.ts +1 -1
  215. package/test/factories/definition.ts +1 -0
  216. package/test/globalSetup.ts +2 -0
  217. package/tsconfig.build.tsbuildinfo +1 -1
  218. package/dist/core/entities/validation-warning.d.ts +0 -6
  219. package/dist/core/entities/validation-warning.d.ts.map +0 -1
  220. package/dist/core/entities/validation-warning.js +0 -3
  221. package/dist/core/entities/validation-warning.js.map +0 -1
  222. package/src/core/entities/validation-warning.ts +0 -5
  223. package/src/core/parse-definition-warnings.test.ts +0 -33
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-definitions",
3
3
  "license": "MIT",
4
- "version": "13.1.0",
4
+ "version": "14.0.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -26,14 +26,14 @@
26
26
  "js-yaml": "^4.1.0",
27
27
  "yaml": "^2.8.3",
28
28
  "zod": "^4.4.3",
29
- "@shipfox/api-agent-dto": "13.1.0",
29
+ "@shipfox/api-agent-dto": "14.0.0",
30
30
  "@shipfox/api-auth-context": "12.2.0",
31
- "@shipfox/api-definitions-dto": "12.3.0",
32
- "@shipfox/api-integration-core-dto": "12.2.0",
33
- "@shipfox/api-projects-dto": "12.2.0",
31
+ "@shipfox/api-definitions-dto": "14.0.0",
32
+ "@shipfox/api-integration-core-dto": "14.0.0",
33
+ "@shipfox/api-projects-dto": "14.0.0",
34
34
  "@shipfox/api-secrets-dto": "12.0.0",
35
35
  "@shipfox/config": "1.2.4",
36
- "@shipfox/expression": "2.2.0",
36
+ "@shipfox/expression": "2.2.1",
37
37
  "@shipfox/inter-module": "0.2.3",
38
38
  "@shipfox/node-drizzle": "0.3.5",
39
39
  "@shipfox/node-fastify": "0.4.2",
@@ -44,7 +44,7 @@
44
44
  "@shipfox/node-postgres": "0.5.0",
45
45
  "@shipfox/node-temporal": "0.4.5",
46
46
  "@shipfox/runner-labels": "0.2.0",
47
- "@shipfox/workflow-document": "3.0.1"
47
+ "@shipfox/workflow-document": "3.1.0"
48
48
  },
49
49
  "imports": {
50
50
  "#*": "./dist/*"
@@ -1,5 +1,5 @@
1
1
  export * from './integration-context.js';
2
2
  export * from './sync-state.js';
3
- export * from './validation-warning.js';
3
+ export * from './validation-diagnostic.js';
4
4
  export * from './workflow-definition.js';
5
5
  export * from './workflow-model.js';
@@ -25,5 +25,9 @@ export interface IntegrationValidationContext {
25
25
  readonly capabilities: readonly IntegrationCapability[];
26
26
  }
27
27
  >;
28
+ /** Documented event names per provider; provider-minted names are never a closed set. */
29
+ readonly eventCatalogs: ReadonlyMap<IntegrationProviderKind, ReadonlySet<string>>;
30
+ /** Providers whose single event name is Shipfox-minted (`webhook` today). */
31
+ readonly fixedEventProviders: ReadonlySet<IntegrationProviderKind>;
28
32
  readonly defaultConnectionSlug?: string | undefined;
29
33
  }
@@ -0,0 +1,49 @@
1
+ import {DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT} from '@shipfox/api-definitions-dto';
2
+ import {type DefinitionSyncDiagnostic, limitDefinitionSyncDiagnostics} from './sync-state.js';
3
+
4
+ describe('limitDefinitionSyncDiagnostics', () => {
5
+ it('orders errors before warnings while keeping the order within each severity', () => {
6
+ const diagnostics: DefinitionSyncDiagnostic[] = [
7
+ {code: 'warning-a', message: 'first warning', severity: 'warning'},
8
+ {code: 'error-a', message: 'first error', severity: 'error'},
9
+ {code: 'warning-b', message: 'second warning', severity: 'warning'},
10
+ {code: 'error-b', message: 'second error', severity: 'error'},
11
+ ];
12
+
13
+ expect(limitDefinitionSyncDiagnostics(diagnostics).map((entry) => entry.code)).toEqual([
14
+ 'error-a',
15
+ 'error-b',
16
+ 'warning-a',
17
+ 'warning-b',
18
+ ]);
19
+ });
20
+
21
+ it('drops warnings first when the list exceeds the maximum count', () => {
22
+ const diagnostics: DefinitionSyncDiagnostic[] = [
23
+ ...Array.from({length: DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT}, (_, index) => ({
24
+ code: `warning-${index}`,
25
+ message: `warning ${index}`,
26
+ severity: 'warning' as const,
27
+ })),
28
+ {code: 'error-last', message: 'error persisted', severity: 'error'},
29
+ ];
30
+
31
+ const limited = limitDefinitionSyncDiagnostics(diagnostics);
32
+
33
+ expect(limited).toHaveLength(DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT);
34
+ expect(limited[0]?.code).toBe('error-last');
35
+ expect(limited.filter((entry) => entry.severity === 'error')).toHaveLength(1);
36
+ expect(limited.some((entry) => entry.code === 'warning-0')).toBe(true);
37
+ expect(
38
+ limited.some(
39
+ (entry) => entry.code === `warning-${DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT - 1}`,
40
+ ),
41
+ ).toBe(false);
42
+ });
43
+
44
+ it('preserves severity and an absent path', () => {
45
+ expect(
46
+ limitDefinitionSyncDiagnostics([{code: 'code', message: 'message', severity: 'warning'}]),
47
+ ).toEqual([{code: 'code', message: 'message', severity: 'warning'}]);
48
+ });
49
+ });
@@ -1,24 +1,47 @@
1
1
  import {
2
+ DEFINITION_SYNC_DIAGNOSTIC_FILE_PATH_MAX_LENGTH,
3
+ DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT,
2
4
  DEFINITION_SYNC_WARNING_CODE_MAX_LENGTH,
3
5
  DEFINITION_SYNC_WARNING_MESSAGE_MAX_LENGTH,
4
6
  DEFINITION_SYNC_WARNING_PATH_MAX_LENGTH,
5
- DEFINITION_SYNC_WARNINGS_MAX_COUNT,
6
7
  } from '@shipfox/api-definitions-dto';
7
- import type {ValidationWarning} from './validation-warning.js';
8
+ import type {ValidationDiagnostic} from './validation-diagnostic.js';
8
9
 
9
10
  export type DefinitionSyncStatus = 'pending' | 'syncing' | 'succeeded' | 'failed';
10
11
 
11
- export type DefinitionSyncWarning = ValidationWarning;
12
+ export interface DefinitionSyncDiagnostic extends ValidationDiagnostic {
13
+ filePath?: string | undefined;
14
+ }
15
+
16
+ /**
17
+ * Orders errors before warnings and bounds the list so truncation at
18
+ * `DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT` drops warnings first.
19
+ */
20
+ export function limitDefinitionSyncDiagnostics(
21
+ diagnostics: readonly DefinitionSyncDiagnostic[],
22
+ ): DefinitionSyncDiagnostic[] {
23
+ const ordered: DefinitionSyncDiagnostic[] = [];
24
+ for (const severity of ['error', 'warning'] as const) {
25
+ for (const diagnostic of diagnostics) {
26
+ if (diagnostic.severity !== severity) continue;
27
+ ordered.push(diagnostic);
28
+ if (ordered.length === DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT) break;
29
+ }
30
+ if (ordered.length === DEFINITION_SYNC_DIAGNOSTICS_MAX_COUNT) break;
31
+ }
12
32
 
13
- export function limitDefinitionSyncWarnings(
14
- warnings: readonly DefinitionSyncWarning[],
15
- ): DefinitionSyncWarning[] {
16
- return warnings.slice(0, DEFINITION_SYNC_WARNINGS_MAX_COUNT).map((warning) => ({
17
- code: warning.code.slice(0, DEFINITION_SYNC_WARNING_CODE_MAX_LENGTH),
18
- message: warning.message.slice(0, DEFINITION_SYNC_WARNING_MESSAGE_MAX_LENGTH),
19
- ...(warning.path === undefined
33
+ return ordered.map((diagnostic) => ({
34
+ code: diagnostic.code.slice(0, DEFINITION_SYNC_WARNING_CODE_MAX_LENGTH),
35
+ message: diagnostic.message.slice(0, DEFINITION_SYNC_WARNING_MESSAGE_MAX_LENGTH),
36
+ severity: diagnostic.severity,
37
+ ...(diagnostic.path === undefined
38
+ ? {}
39
+ : {path: diagnostic.path.slice(0, DEFINITION_SYNC_WARNING_PATH_MAX_LENGTH)}),
40
+ ...(diagnostic.filePath === undefined
20
41
  ? {}
21
- : {path: warning.path.slice(0, DEFINITION_SYNC_WARNING_PATH_MAX_LENGTH)}),
42
+ : {
43
+ filePath: diagnostic.filePath.slice(0, DEFINITION_SYNC_DIAGNOSTIC_FILE_PATH_MAX_LENGTH),
44
+ }),
22
45
  }));
23
46
  }
24
47
 
@@ -55,7 +78,7 @@ export interface DefinitionSyncState {
55
78
  status: DefinitionSyncStatus;
56
79
  lastErrorCode: DefinitionSyncErrorCode | null;
57
80
  lastErrorMessage: string | null;
58
- warnings: DefinitionSyncWarning[];
81
+ diagnostics: DefinitionSyncDiagnostic[];
59
82
  startedAt: Date | null;
60
83
  finishedAt: Date | null;
61
84
  createdAt: Date;
@@ -0,0 +1,8 @@
1
+ export type ValidationDiagnosticSeverity = 'error' | 'warning';
2
+
3
+ export interface ValidationDiagnostic {
4
+ code: string;
5
+ message: string;
6
+ path?: string | undefined;
7
+ severity: ValidationDiagnosticSeverity;
8
+ }
@@ -13,6 +13,8 @@ export interface WorkflowDefinitionPayload {
13
13
 
14
14
  export interface WorkflowDefinition {
15
15
  id: string;
16
+ /** Stable identity per project and config path; pathless manual rows share a project lineage. */
17
+ workflowId: string;
16
18
  projectId: string;
17
19
  configPath: string | null;
18
20
  source: 'manual' | 'vcs';
@@ -19,3 +19,29 @@ export class DefinitionSyncPermanentError extends Error {
19
19
  this.name = 'DefinitionSyncPermanentError';
20
20
  }
21
21
  }
22
+
23
+ export type DefinitionAtRefErrorCode =
24
+ | 'project-not-found'
25
+ | 'ref-not-found'
26
+ | 'ref-invalid'
27
+ | 'ref-moved'
28
+ | 'file-not-found'
29
+ | 'content-too-large'
30
+ | 'invalid-definition'
31
+ | 'too-many-files'
32
+ | 'source-unavailable';
33
+
34
+ /**
35
+ * Rejects a definition resolution or listing at a git ref. `details` carries
36
+ * the bounded context the presentation translates into known-error details.
37
+ */
38
+ export class DefinitionAtRefError extends Error {
39
+ constructor(
40
+ public readonly code: DefinitionAtRefErrorCode,
41
+ message: string,
42
+ public readonly details: Record<string, unknown> = {},
43
+ ) {
44
+ super(message);
45
+ this.name = 'DefinitionAtRefError';
46
+ }
47
+ }
package/src/core/index.ts CHANGED
@@ -1,9 +1,21 @@
1
1
  export type * from './entities/index.js';
2
2
  export {
3
+ DefinitionAtRefError,
4
+ type DefinitionAtRefErrorCode,
3
5
  DefinitionParseError,
4
6
  DefinitionSyncPermanentError,
5
7
  } from './errors.js';
6
8
  export {parseDefinition} from './parse-definition.js';
9
+ export {
10
+ type DefinitionAtRefFile,
11
+ type DefinitionsAtRefListing,
12
+ type ListDefinitionsAtRefParams,
13
+ listDefinitionsAtRef,
14
+ type ResolveDefinitionAtRefParams,
15
+ type ResolvedDefinitionAtRef,
16
+ resolveDefinitionAtRef,
17
+ type ValidationWarning,
18
+ } from './resolve-definition-at-ref.js';
7
19
  export {
8
20
  classifySyncFailure,
9
21
  DEFAULT_WORKFLOW_PATH,
@@ -0,0 +1,38 @@
1
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
2
+ import {loadIntegrationValidationContext} from './integrations.js';
3
+
4
+ describe('loadIntegrationValidationContext', () => {
5
+ it('materializes provider event catalogs and fixed-provider metadata', async () => {
6
+ const getAgentToolsContext = vi.fn<IntegrationsModuleClient['getAgentToolsContext']>(
7
+ async () => ({
8
+ selectionCatalogs: [],
9
+ catalogs: [],
10
+ workspaceConnections: [],
11
+ eventCatalogs: [
12
+ {provider: 'github', events: ['push', 'pull_request.opened']},
13
+ {provider: 'gitea', events: ['push']},
14
+ ],
15
+ fixedEventProviders: ['webhook'],
16
+ defaultConnection: null,
17
+ }),
18
+ );
19
+ const integrations = {getAgentToolsContext} as unknown as IntegrationsModuleClient;
20
+ const workspaceId = crypto.randomUUID();
21
+ const defaultConnectionId = crypto.randomUUID();
22
+
23
+ const context = await loadIntegrationValidationContext(
24
+ integrations,
25
+ workspaceId,
26
+ defaultConnectionId,
27
+ );
28
+
29
+ expect(getAgentToolsContext).toHaveBeenCalledWith({workspaceId, defaultConnectionId});
30
+ expect(context.eventCatalogs).toEqual(
31
+ new Map([
32
+ ['github', new Set(['push', 'pull_request.opened'])],
33
+ ['gitea', new Set(['push'])],
34
+ ]),
35
+ );
36
+ expect(context.fixedEventProviders).toEqual(new Set(['webhook']));
37
+ });
38
+ });
@@ -23,8 +23,13 @@ export async function loadIntegrationValidationContext(
23
23
  integrations: IntegrationsModuleClient,
24
24
  workspaceId: string,
25
25
  defaultConnectionId: string,
26
+ signal?: AbortSignal,
26
27
  ) {
27
- const context = await integrations.getAgentToolsContext({workspaceId, defaultConnectionId});
28
+ const input = {workspaceId, defaultConnectionId};
29
+ const context =
30
+ signal === undefined
31
+ ? await integrations.getAgentToolsContext(input)
32
+ : await integrations.getAgentToolsContext(input, {signal});
28
33
  return {
29
34
  agentToolSelectionCatalogs: new Map(
30
35
  context.selectionCatalogs.map(({provider, selectors}) => [provider, {selectors}]),
@@ -32,6 +37,10 @@ export async function loadIntegrationValidationContext(
32
37
  workspaceConnectionSnapshot: new Map(
33
38
  context.workspaceConnections.map(({slug, ...connection}) => [slug, connection]),
34
39
  ),
40
+ eventCatalogs: new Map(
41
+ context.eventCatalogs.map(({provider, events}) => [provider, new Set(events)]),
42
+ ),
43
+ fixedEventProviders: new Set(context.fixedEventProviders),
35
44
  defaultConnectionSlug: context.defaultConnection?.slug,
36
45
  };
37
46
  }
@@ -0,0 +1,47 @@
1
+ import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
2
+ import {parseDefinitionWithDiagnostics} from './parse-definition.js';
3
+ import {validateDefinition} from './validate-definition.js';
4
+
5
+ vi.mock('./validate-definition.js', () => ({
6
+ validateDefinition: vi.fn(),
7
+ }));
8
+
9
+ describe('parseDefinitionWithDiagnostics', () => {
10
+ it('returns diagnostics from successful validation', () => {
11
+ vi.mocked(validateDefinition).mockReturnValue({
12
+ valid: true,
13
+ definition: {document: {}, model: {}} as never,
14
+ diagnostics: [
15
+ {
16
+ code: 'synthetic-warning',
17
+ message: 'A non-fatal validation warning',
18
+ path: 'jobs.build.steps.0.run',
19
+ severity: 'warning',
20
+ },
21
+ {
22
+ code: 'synthetic-error',
23
+ message: 'A trigger-scoped validation error',
24
+ path: 'triggers.on_demand',
25
+ severity: 'error',
26
+ },
27
+ ],
28
+ });
29
+
30
+ const parsed = parseDefinitionWithDiagnostics('name: Workflow', {agentValidationCatalog});
31
+
32
+ expect(parsed.diagnostics).toEqual([
33
+ {
34
+ code: 'synthetic-warning',
35
+ message: 'A non-fatal validation warning',
36
+ path: 'jobs.build.steps.0.run',
37
+ severity: 'warning',
38
+ },
39
+ {
40
+ code: 'synthetic-error',
41
+ message: 'A trigger-scoped validation error',
42
+ path: 'triggers.on_demand',
43
+ severity: 'error',
44
+ },
45
+ ]);
46
+ });
47
+ });
@@ -3,7 +3,10 @@ import {dirname, resolve} from 'node:path';
3
3
  import {fileURLToPath} from 'node:url';
4
4
  import {agentValidationCatalog} from '#test/agent-validation-catalog.js';
5
5
  import {DefinitionParseError} from './errors.js';
6
- import {parseDefinition as parseDefinitionBase} from './parse-definition.js';
6
+ import {
7
+ parseDefinition as parseDefinitionBase,
8
+ parseDefinitionWithDiagnostics as parseDefinitionWithDiagnosticsBase,
9
+ } from './parse-definition.js';
7
10
 
8
11
  const fixturesDir = resolve(dirname(fileURLToPath(import.meta.url)), '../../test/fixtures');
9
12
 
@@ -11,6 +14,10 @@ function parseDefinition(yaml: string, options = {}) {
11
14
  return parseDefinitionBase(yaml, {agentValidationCatalog, ...options});
12
15
  }
13
16
 
17
+ function parseDefinitionWithDiagnostics(yaml: string, options = {}) {
18
+ return parseDefinitionWithDiagnosticsBase(yaml, {agentValidationCatalog, ...options});
19
+ }
20
+
14
21
  function readFixture(name: string): string {
15
22
  return readFileSync(resolve(fixturesDir, name), 'utf-8');
16
23
  }
@@ -177,7 +184,7 @@ jobs:
177
184
  expect(() => parseDefinition(yaml)).toThrow(DefinitionParseError);
178
185
  });
179
186
 
180
- test('manual trigger requires an explicit event', () => {
187
+ test('manual trigger without an explicit event parses and materializes fire', () => {
181
188
  const yaml = `name: Manual only
182
189
  runner: ubuntu-latest
183
190
  triggers:
@@ -189,10 +196,19 @@ jobs:
189
196
  - run: echo hello
190
197
  `;
191
198
 
192
- expect(() => parseDefinition(yaml)).toThrow(DefinitionParseError);
199
+ const definition = parseDefinition(yaml);
200
+
201
+ expect(definition.model.triggers).toEqual([
202
+ {
203
+ id: 'on-demand',
204
+ key: 'on_demand',
205
+ source: 'manual',
206
+ event: 'fire',
207
+ },
208
+ ]);
193
209
  });
194
210
 
195
- test('declaring more than one manual trigger throws DefinitionParseError', () => {
211
+ test('keeps the first manual trigger active and makes later ones inert', () => {
196
212
  const yaml = `name: Multi manual
197
213
  runner: ubuntu-latest
198
214
  triggers:
@@ -206,6 +222,14 @@ jobs:
206
222
  - run: echo hello
207
223
  `;
208
224
 
209
- expect(() => parseDefinition(yaml)).toThrow(DefinitionParseError);
225
+ const definition = parseDefinitionWithDiagnostics(yaml);
226
+
227
+ expect(definition.diagnostics).toEqual([
228
+ expect.objectContaining({
229
+ code: 'multiple-manual-triggers',
230
+ path: 'triggers.rollback',
231
+ }),
232
+ ]);
233
+ expect(definition.model.triggers.map((trigger) => trigger.key)).toEqual(['deploy']);
210
234
  });
211
235
  });
@@ -1,15 +1,15 @@
1
- import type {ValidationWarning} from './entities/validation-warning.js';
1
+ import type {ValidationDiagnostic} from './entities/validation-diagnostic.js';
2
2
  import type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';
3
3
  import {DefinitionParseError} from './errors.js';
4
4
  import {type DefinitionValidationOptions, validateDefinition} from './validate-definition.js';
5
5
 
6
6
  export interface ParsedDefinition extends WorkflowDefinitionPayload {
7
- warnings: ValidationWarning[];
7
+ diagnostics: ValidationDiagnostic[];
8
8
  }
9
9
 
10
10
  export type ParseDefinitionOptions = DefinitionValidationOptions;
11
11
 
12
- export function parseDefinitionWithWarnings(
12
+ export function parseDefinitionWithDiagnostics(
13
13
  yamlString: string,
14
14
  options: ParseDefinitionOptions,
15
15
  ): ParsedDefinition {
@@ -25,7 +25,7 @@ export function parseDefinitionWithWarnings(
25
25
  return {
26
26
  ...result.definition,
27
27
  sourceSnapshot: {content: yamlString, format: 'yaml'},
28
- warnings: result.warnings,
28
+ diagnostics: result.diagnostics,
29
29
  };
30
30
  }
31
31
 
@@ -33,11 +33,11 @@ export function parseDefinition(
33
33
  yamlString: string,
34
34
  options: ParseDefinitionOptions,
35
35
  ): WorkflowDefinitionPayload {
36
- const parsed = parseDefinitionWithWarnings(yamlString, options);
37
- return stripDefinitionWarnings(parsed);
36
+ const parsed = parseDefinitionWithDiagnostics(yamlString, options);
37
+ return stripDefinitionDiagnostics(parsed);
38
38
  }
39
39
 
40
- export function stripDefinitionWarnings(parsed: ParsedDefinition): WorkflowDefinitionPayload {
40
+ export function stripDefinitionDiagnostics(parsed: ParsedDefinition): WorkflowDefinitionPayload {
41
41
  return {
42
42
  document: parsed.document,
43
43
  model: parsed.model,