@shipfox/annotations 17.0.0 → 19.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.
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 18 files with swc (364.53ms)
2
+ Successfully compiled: 18 files with swc (333.55ms)
@@ -1,2 +1 @@
1
1
  $ shipfox-tsc-check
2
- context canceled
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @shipfox/annotations
2
2
 
3
+ ## 19.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 34ebe6a: Expose workspace-scoped workflow execution and annotation read contracts.
8
+
9
+ ### Patch Changes
10
+
11
+ - b416c4c: Preserves existing package behavior while simplifying internal control flow.
12
+ - Updated dependencies [34ebe6a]
13
+ - Updated dependencies [b416c4c]
14
+ - @shipfox/annotations-dto@19.0.0
15
+ - @shipfox/api-auth-context@19.0.0
16
+ - @shipfox/node-module@1.0.8
17
+ - @shipfox/config@1.2.4
18
+ - @shipfox/inter-module@0.2.3
19
+ - @shipfox/node-drizzle@0.3.5
20
+ - @shipfox/node-fastify@0.4.3
21
+ - @shipfox/node-postgres@0.5.1
22
+
23
+ ## 18.0.0
24
+
25
+ ### Patch Changes
26
+
27
+ - @shipfox/api-auth-context@18.0.0
28
+
3
29
  ## 17.0.0
4
30
 
5
31
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"write-annotations.d.ts","sourceRoot":"","sources":["../../src/core/write-annotations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iCAAiC,EAAC,MAAM,0BAA0B,CAAC;AAShF,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,SAAS,iCAAiC,EAAE,CAAC;CAC1D;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAC,CAAC;IACzD,UAAU,EAAE;QACV,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAqFhG"}
1
+ {"version":3,"file":"write-annotations.d.ts","sourceRoot":"","sources":["../../src/core/write-annotations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iCAAiC,EAAC,MAAM,0BAA0B,CAAC;AAahF,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,SAAS,iCAAiC,EAAE,CAAC;CAC1D;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAC,CAAC;IACzD,UAAU,EAAE;QACV,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AA6ED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAmBhG"}
@@ -1,82 +1,81 @@
1
1
  import { config } from '#config.js';
2
2
  import { withAnnotationLock } from '#db/annotations.js';
3
3
  import { AnnotationBodyTooLargeError, AnnotationCountLimitExceededError, AnnotationTotalBytesLimitExceededError } from './errors.js';
4
+ async function applyAnnotationOperation(repo, params, operation, state) {
5
+ if (operation.op === 'remove') {
6
+ await repo.removeAnnotation(params.jobExecutionId, operation.context);
7
+ state.current.delete(operation.context);
8
+ state.results.push({
9
+ context: operation.context,
10
+ id: null
11
+ });
12
+ return;
13
+ }
14
+ const existing = state.current.get(operation.context);
15
+ const body = operation.op === 'append' ? `${existing?.body ?? ''}${operation.body}` : operation.body;
16
+ const bodyBytes = Buffer.byteLength(body);
17
+ ensureBodyBudget(bodyBytes);
18
+ const unchanged = operation.op === 'replace' && existing !== undefined && existing.body === body && existing.style === operation.style;
19
+ if (unchanged) {
20
+ state.results.push({
21
+ context: operation.context,
22
+ id: existing.id
23
+ });
24
+ return;
25
+ }
26
+ const draft = new Map(state.current);
27
+ draft.set(operation.context, {
28
+ id: existing?.id ?? '',
29
+ context: operation.context,
30
+ style: operation.style,
31
+ body,
32
+ bodyBytes,
33
+ sequence: existing?.sequence ?? state.nextSequence
34
+ });
35
+ ensureExecutionBudgets(draft);
36
+ const row = existing ? await repo.updateAnnotation({
37
+ id: existing.id,
38
+ originStepId: params.originStepId,
39
+ originStepAttempt: params.originStepAttempt,
40
+ style: operation.style,
41
+ body,
42
+ bodyBytes
43
+ }) : await repo.createAnnotation({
44
+ workspaceId: params.workspaceId,
45
+ projectId: params.projectId,
46
+ workflowRunId: params.workflowRunId,
47
+ workflowRunAttempt: params.workflowRunAttempt,
48
+ workflowRunAttemptId: params.workflowRunAttemptId,
49
+ jobId: params.jobId,
50
+ jobExecutionId: params.jobExecutionId,
51
+ originStepId: params.originStepId,
52
+ originStepAttempt: params.originStepAttempt,
53
+ context: operation.context,
54
+ style: operation.style,
55
+ body,
56
+ bodyBytes,
57
+ sequence: state.nextSequence
58
+ });
59
+ state.current.set(operation.context, row);
60
+ if (!existing) state.nextSequence += 1;
61
+ state.results.push({
62
+ context: operation.context,
63
+ id: row.id
64
+ });
65
+ }
4
66
  export function writeAnnotations(params) {
5
67
  return withAnnotationLock(params.jobExecutionId, async (repo)=>{
6
68
  const current = await repo.loadCurrentAnnotations(params.jobExecutionId);
7
- let nextSequence = Math.max(0, ...Array.from(current.values()).map((annotation)=>annotation.sequence)) + 1;
8
- const results = [];
69
+ const state = {
70
+ current,
71
+ nextSequence: Math.max(0, ...Array.from(current.values()).map((annotation)=>annotation.sequence)) + 1,
72
+ results: []
73
+ };
9
74
  for (const operation of params.operations){
10
- if (operation.op === 'remove') {
11
- await repo.removeAnnotation(params.jobExecutionId, operation.context);
12
- current.delete(operation.context);
13
- results.push({
14
- context: operation.context,
15
- id: null
16
- });
17
- continue;
18
- }
19
- const existing = current.get(operation.context);
20
- const body = operation.op === 'append' ? `${existing?.body ?? ''}${operation.body}` : operation.body;
21
- const bodyBytes = Buffer.byteLength(body);
22
- ensureBodyBudget(bodyBytes);
23
- const isUnchangedReplace = operation.op === 'replace' && existing !== undefined && existing.body === body && existing.style === operation.style;
24
- if (isUnchangedReplace) {
25
- results.push({
26
- context: operation.context,
27
- id: existing.id
28
- });
29
- continue;
30
- }
31
- const draft = new Map(current);
32
- draft.set(operation.context, {
33
- id: existing?.id ?? '',
34
- context: operation.context,
35
- style: operation.style,
36
- body,
37
- bodyBytes,
38
- sequence: existing?.sequence ?? nextSequence
39
- });
40
- ensureExecutionBudgets(draft);
41
- const row = existing ? await repo.updateAnnotation({
42
- id: existing.id,
43
- originStepId: params.originStepId,
44
- originStepAttempt: params.originStepAttempt,
45
- style: operation.style,
46
- body,
47
- bodyBytes
48
- }) : await repo.createAnnotation({
49
- workspaceId: params.workspaceId,
50
- projectId: params.projectId,
51
- workflowRunId: params.workflowRunId,
52
- workflowRunAttempt: params.workflowRunAttempt,
53
- workflowRunAttemptId: params.workflowRunAttemptId,
54
- jobId: params.jobId,
55
- jobExecutionId: params.jobExecutionId,
56
- originStepId: params.originStepId,
57
- originStepAttempt: params.originStepAttempt,
58
- context: operation.context,
59
- style: operation.style,
60
- body,
61
- bodyBytes,
62
- sequence: nextSequence
63
- });
64
- current.set(operation.context, {
65
- id: row.id,
66
- context: row.context,
67
- style: row.style,
68
- body: row.body,
69
- bodyBytes: row.bodyBytes,
70
- sequence: row.sequence
71
- });
72
- if (!existing) nextSequence += 1;
73
- results.push({
74
- context: operation.context,
75
- id: row.id
76
- });
75
+ await applyAnnotationOperation(repo, params, operation, state);
77
76
  }
78
77
  return {
79
- annotations: results,
78
+ annotations: state.results,
80
79
  accounting: currentAccounting(current)
81
80
  };
82
81
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/write-annotations.ts"],"sourcesContent":["import type {LeasedWriteAnnotationOperationDto} from '@shipfox/annotations-dto';\nimport {config} from '#config.js';\nimport {type StoredAnnotation, withAnnotationLock} from '#db/annotations.js';\nimport {\n AnnotationBodyTooLargeError,\n AnnotationCountLimitExceededError,\n AnnotationTotalBytesLimitExceededError,\n} from './errors.js';\n\nexport interface WriteAnnotationsParams {\n workspaceId: string;\n projectId: string;\n workflowRunId: string;\n workflowRunAttempt: number;\n workflowRunAttemptId: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n operations: readonly LeasedWriteAnnotationOperationDto[];\n}\n\nexport interface WriteAnnotationsResult {\n annotations: Array<{context: string; id: string | null}>;\n accounting: {\n annotationCount: number;\n totalBodyBytes: number;\n };\n}\n\nexport function writeAnnotations(params: WriteAnnotationsParams): Promise<WriteAnnotationsResult> {\n return withAnnotationLock(params.jobExecutionId, async (repo) => {\n const current = await repo.loadCurrentAnnotations(params.jobExecutionId);\n let nextSequence =\n Math.max(0, ...Array.from(current.values()).map((annotation) => annotation.sequence)) + 1;\n const results: WriteAnnotationsResult['annotations'] = [];\n\n for (const operation of params.operations) {\n if (operation.op === 'remove') {\n await repo.removeAnnotation(params.jobExecutionId, operation.context);\n current.delete(operation.context);\n results.push({context: operation.context, id: null});\n continue;\n }\n\n const existing = current.get(operation.context);\n const body =\n operation.op === 'append' ? `${existing?.body ?? ''}${operation.body}` : operation.body;\n const bodyBytes = Buffer.byteLength(body);\n ensureBodyBudget(bodyBytes);\n\n const isUnchangedReplace =\n operation.op === 'replace' &&\n existing !== undefined &&\n existing.body === body &&\n existing.style === operation.style;\n if (isUnchangedReplace) {\n results.push({context: operation.context, id: existing.id});\n continue;\n }\n\n const draft = new Map(current);\n draft.set(operation.context, {\n id: existing?.id ?? '',\n context: operation.context,\n style: operation.style,\n body,\n bodyBytes,\n sequence: existing?.sequence ?? nextSequence,\n });\n ensureExecutionBudgets(draft);\n\n const row = existing\n ? await repo.updateAnnotation({\n id: existing.id,\n originStepId: params.originStepId,\n originStepAttempt: params.originStepAttempt,\n style: operation.style,\n body,\n bodyBytes,\n })\n : await repo.createAnnotation({\n workspaceId: params.workspaceId,\n projectId: params.projectId,\n workflowRunId: params.workflowRunId,\n workflowRunAttempt: params.workflowRunAttempt,\n workflowRunAttemptId: params.workflowRunAttemptId,\n jobId: params.jobId,\n jobExecutionId: params.jobExecutionId,\n originStepId: params.originStepId,\n originStepAttempt: params.originStepAttempt,\n context: operation.context,\n style: operation.style,\n body,\n bodyBytes,\n sequence: nextSequence,\n });\n\n current.set(operation.context, {\n id: row.id,\n context: row.context,\n style: row.style,\n body: row.body,\n bodyBytes: row.bodyBytes,\n sequence: row.sequence,\n });\n if (!existing) nextSequence += 1;\n results.push({context: operation.context, id: row.id});\n }\n\n return {\n annotations: results,\n accounting: currentAccounting(current),\n };\n });\n}\n\nfunction ensureBodyBudget(bodyBytes: number): void {\n if (bodyBytes > config.ANNOTATIONS_MAX_BODY_BYTES) {\n throw new AnnotationBodyTooLargeError(config.ANNOTATIONS_MAX_BODY_BYTES);\n }\n}\n\nfunction ensureExecutionBudgets(annotationsByContext: ReadonlyMap<string, StoredAnnotation>): void {\n const accounting = currentAccounting(annotationsByContext);\n if (accounting.annotationCount > config.ANNOTATIONS_MAX_PER_EXECUTION) {\n throw new AnnotationCountLimitExceededError(config.ANNOTATIONS_MAX_PER_EXECUTION);\n }\n if (accounting.totalBodyBytes > config.ANNOTATIONS_MAX_TOTAL_BYTES) {\n throw new AnnotationTotalBytesLimitExceededError(config.ANNOTATIONS_MAX_TOTAL_BYTES);\n }\n}\n\nfunction currentAccounting(annotationsByContext: ReadonlyMap<string, StoredAnnotation>) {\n return {\n annotationCount: annotationsByContext.size,\n totalBodyBytes: Array.from(annotationsByContext.values()).reduce(\n (total, annotation) => total + annotation.bodyBytes,\n 0,\n ),\n };\n}\n"],"names":["config","withAnnotationLock","AnnotationBodyTooLargeError","AnnotationCountLimitExceededError","AnnotationTotalBytesLimitExceededError","writeAnnotations","params","jobExecutionId","repo","current","loadCurrentAnnotations","nextSequence","Math","max","Array","from","values","map","annotation","sequence","results","operation","operations","op","removeAnnotation","context","delete","push","id","existing","get","body","bodyBytes","Buffer","byteLength","ensureBodyBudget","isUnchangedReplace","undefined","style","draft","Map","set","ensureExecutionBudgets","row","updateAnnotation","originStepId","originStepAttempt","createAnnotation","workspaceId","projectId","workflowRunId","workflowRunAttempt","workflowRunAttemptId","jobId","annotations","accounting","currentAccounting","ANNOTATIONS_MAX_BODY_BYTES","annotationsByContext","annotationCount","ANNOTATIONS_MAX_PER_EXECUTION","totalBodyBytes","ANNOTATIONS_MAX_TOTAL_BYTES","size","reduce","total"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/write-annotations.ts"],"sourcesContent":["import type {LeasedWriteAnnotationOperationDto} from '@shipfox/annotations-dto';\nimport {config} from '#config.js';\nimport {\n type AnnotationWriteRepository,\n type StoredAnnotation,\n withAnnotationLock,\n} from '#db/annotations.js';\nimport {\n AnnotationBodyTooLargeError,\n AnnotationCountLimitExceededError,\n AnnotationTotalBytesLimitExceededError,\n} from './errors.js';\n\nexport interface WriteAnnotationsParams {\n workspaceId: string;\n projectId: string;\n workflowRunId: string;\n workflowRunAttempt: number;\n workflowRunAttemptId: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n operations: readonly LeasedWriteAnnotationOperationDto[];\n}\n\nexport interface WriteAnnotationsResult {\n annotations: Array<{context: string; id: string | null}>;\n accounting: {\n annotationCount: number;\n totalBodyBytes: number;\n };\n}\n\ninterface AnnotationWriteState {\n current: Map<string, StoredAnnotation>;\n nextSequence: number;\n results: WriteAnnotationsResult['annotations'];\n}\n\nasync function applyAnnotationOperation(\n repo: AnnotationWriteRepository,\n params: WriteAnnotationsParams,\n operation: LeasedWriteAnnotationOperationDto,\n state: AnnotationWriteState,\n): Promise<void> {\n if (operation.op === 'remove') {\n await repo.removeAnnotation(params.jobExecutionId, operation.context);\n state.current.delete(operation.context);\n state.results.push({context: operation.context, id: null});\n return;\n }\n\n const existing = state.current.get(operation.context);\n const body =\n operation.op === 'append' ? `${existing?.body ?? ''}${operation.body}` : operation.body;\n const bodyBytes = Buffer.byteLength(body);\n ensureBodyBudget(bodyBytes);\n const unchanged =\n operation.op === 'replace' &&\n existing !== undefined &&\n existing.body === body &&\n existing.style === operation.style;\n if (unchanged) {\n state.results.push({context: operation.context, id: existing.id});\n return;\n }\n\n const draft = new Map(state.current);\n draft.set(operation.context, {\n id: existing?.id ?? '',\n context: operation.context,\n style: operation.style,\n body,\n bodyBytes,\n sequence: existing?.sequence ?? state.nextSequence,\n });\n ensureExecutionBudgets(draft);\n\n const row = existing\n ? await repo.updateAnnotation({\n id: existing.id,\n originStepId: params.originStepId,\n originStepAttempt: params.originStepAttempt,\n style: operation.style,\n body,\n bodyBytes,\n })\n : await repo.createAnnotation({\n workspaceId: params.workspaceId,\n projectId: params.projectId,\n workflowRunId: params.workflowRunId,\n workflowRunAttempt: params.workflowRunAttempt,\n workflowRunAttemptId: params.workflowRunAttemptId,\n jobId: params.jobId,\n jobExecutionId: params.jobExecutionId,\n originStepId: params.originStepId,\n originStepAttempt: params.originStepAttempt,\n context: operation.context,\n style: operation.style,\n body,\n bodyBytes,\n sequence: state.nextSequence,\n });\n state.current.set(operation.context, row);\n if (!existing) state.nextSequence += 1;\n state.results.push({context: operation.context, id: row.id});\n}\n\nexport function writeAnnotations(params: WriteAnnotationsParams): Promise<WriteAnnotationsResult> {\n return withAnnotationLock(params.jobExecutionId, async (repo) => {\n const current = await repo.loadCurrentAnnotations(params.jobExecutionId);\n const state: AnnotationWriteState = {\n current,\n nextSequence:\n Math.max(0, ...Array.from(current.values()).map((annotation) => annotation.sequence)) + 1,\n results: [],\n };\n\n for (const operation of params.operations) {\n await applyAnnotationOperation(repo, params, operation, state);\n }\n\n return {\n annotations: state.results,\n accounting: currentAccounting(current),\n };\n });\n}\n\nfunction ensureBodyBudget(bodyBytes: number): void {\n if (bodyBytes > config.ANNOTATIONS_MAX_BODY_BYTES) {\n throw new AnnotationBodyTooLargeError(config.ANNOTATIONS_MAX_BODY_BYTES);\n }\n}\n\nfunction ensureExecutionBudgets(annotationsByContext: ReadonlyMap<string, StoredAnnotation>): void {\n const accounting = currentAccounting(annotationsByContext);\n if (accounting.annotationCount > config.ANNOTATIONS_MAX_PER_EXECUTION) {\n throw new AnnotationCountLimitExceededError(config.ANNOTATIONS_MAX_PER_EXECUTION);\n }\n if (accounting.totalBodyBytes > config.ANNOTATIONS_MAX_TOTAL_BYTES) {\n throw new AnnotationTotalBytesLimitExceededError(config.ANNOTATIONS_MAX_TOTAL_BYTES);\n }\n}\n\nfunction currentAccounting(annotationsByContext: ReadonlyMap<string, StoredAnnotation>) {\n return {\n annotationCount: annotationsByContext.size,\n totalBodyBytes: Array.from(annotationsByContext.values()).reduce(\n (total, annotation) => total + annotation.bodyBytes,\n 0,\n ),\n };\n}\n"],"names":["config","withAnnotationLock","AnnotationBodyTooLargeError","AnnotationCountLimitExceededError","AnnotationTotalBytesLimitExceededError","applyAnnotationOperation","repo","params","operation","state","op","removeAnnotation","jobExecutionId","context","current","delete","results","push","id","existing","get","body","bodyBytes","Buffer","byteLength","ensureBodyBudget","unchanged","undefined","style","draft","Map","set","sequence","nextSequence","ensureExecutionBudgets","row","updateAnnotation","originStepId","originStepAttempt","createAnnotation","workspaceId","projectId","workflowRunId","workflowRunAttempt","workflowRunAttemptId","jobId","writeAnnotations","loadCurrentAnnotations","Math","max","Array","from","values","map","annotation","operations","annotations","accounting","currentAccounting","ANNOTATIONS_MAX_BODY_BYTES","annotationsByContext","annotationCount","ANNOTATIONS_MAX_PER_EXECUTION","totalBodyBytes","ANNOTATIONS_MAX_TOTAL_BYTES","size","reduce","total"],"mappings":"AACA,SAAQA,MAAM,QAAO,aAAa;AAClC,SAGEC,kBAAkB,QACb,qBAAqB;AAC5B,SACEC,2BAA2B,EAC3BC,iCAAiC,EACjCC,sCAAsC,QACjC,cAAc;AA6BrB,eAAeC,yBACbC,IAA+B,EAC/BC,MAA8B,EAC9BC,SAA4C,EAC5CC,KAA2B;IAE3B,IAAID,UAAUE,EAAE,KAAK,UAAU;QAC7B,MAAMJ,KAAKK,gBAAgB,CAACJ,OAAOK,cAAc,EAAEJ,UAAUK,OAAO;QACpEJ,MAAMK,OAAO,CAACC,MAAM,CAACP,UAAUK,OAAO;QACtCJ,MAAMO,OAAO,CAACC,IAAI,CAAC;YAACJ,SAASL,UAAUK,OAAO;YAAEK,IAAI;QAAI;QACxD;IACF;IAEA,MAAMC,WAAWV,MAAMK,OAAO,CAACM,GAAG,CAACZ,UAAUK,OAAO;IACpD,MAAMQ,OACJb,UAAUE,EAAE,KAAK,WAAW,GAAGS,UAAUE,QAAQ,KAAKb,UAAUa,IAAI,EAAE,GAAGb,UAAUa,IAAI;IACzF,MAAMC,YAAYC,OAAOC,UAAU,CAACH;IACpCI,iBAAiBH;IACjB,MAAMI,YACJlB,UAAUE,EAAE,KAAK,aACjBS,aAAaQ,aACbR,SAASE,IAAI,KAAKA,QAClBF,SAASS,KAAK,KAAKpB,UAAUoB,KAAK;IACpC,IAAIF,WAAW;QACbjB,MAAMO,OAAO,CAACC,IAAI,CAAC;YAACJ,SAASL,UAAUK,OAAO;YAAEK,IAAIC,SAASD,EAAE;QAAA;QAC/D;IACF;IAEA,MAAMW,QAAQ,IAAIC,IAAIrB,MAAMK,OAAO;IACnCe,MAAME,GAAG,CAACvB,UAAUK,OAAO,EAAE;QAC3BK,IAAIC,UAAUD,MAAM;QACpBL,SAASL,UAAUK,OAAO;QAC1Be,OAAOpB,UAAUoB,KAAK;QACtBP;QACAC;QACAU,UAAUb,UAAUa,YAAYvB,MAAMwB,YAAY;IACpD;IACAC,uBAAuBL;IAEvB,MAAMM,MAAMhB,WACR,MAAMb,KAAK8B,gBAAgB,CAAC;QAC1BlB,IAAIC,SAASD,EAAE;QACfmB,cAAc9B,OAAO8B,YAAY;QACjCC,mBAAmB/B,OAAO+B,iBAAiB;QAC3CV,OAAOpB,UAAUoB,KAAK;QACtBP;QACAC;IACF,KACA,MAAMhB,KAAKiC,gBAAgB,CAAC;QAC1BC,aAAajC,OAAOiC,WAAW;QAC/BC,WAAWlC,OAAOkC,SAAS;QAC3BC,eAAenC,OAAOmC,aAAa;QACnCC,oBAAoBpC,OAAOoC,kBAAkB;QAC7CC,sBAAsBrC,OAAOqC,oBAAoB;QACjDC,OAAOtC,OAAOsC,KAAK;QACnBjC,gBAAgBL,OAAOK,cAAc;QACrCyB,cAAc9B,OAAO8B,YAAY;QACjCC,mBAAmB/B,OAAO+B,iBAAiB;QAC3CzB,SAASL,UAAUK,OAAO;QAC1Be,OAAOpB,UAAUoB,KAAK;QACtBP;QACAC;QACAU,UAAUvB,MAAMwB,YAAY;IAC9B;IACJxB,MAAMK,OAAO,CAACiB,GAAG,CAACvB,UAAUK,OAAO,EAAEsB;IACrC,IAAI,CAAChB,UAAUV,MAAMwB,YAAY,IAAI;IACrCxB,MAAMO,OAAO,CAACC,IAAI,CAAC;QAACJ,SAASL,UAAUK,OAAO;QAAEK,IAAIiB,IAAIjB,EAAE;IAAA;AAC5D;AAEA,OAAO,SAAS4B,iBAAiBvC,MAA8B;IAC7D,OAAON,mBAAmBM,OAAOK,cAAc,EAAE,OAAON;QACtD,MAAMQ,UAAU,MAAMR,KAAKyC,sBAAsB,CAACxC,OAAOK,cAAc;QACvE,MAAMH,QAA8B;YAClCK;YACAmB,cACEe,KAAKC,GAAG,CAAC,MAAMC,MAAMC,IAAI,CAACrC,QAAQsC,MAAM,IAAIC,GAAG,CAAC,CAACC,aAAeA,WAAWtB,QAAQ,KAAK;YAC1FhB,SAAS,EAAE;QACb;QAEA,KAAK,MAAMR,aAAaD,OAAOgD,UAAU,CAAE;YACzC,MAAMlD,yBAAyBC,MAAMC,QAAQC,WAAWC;QAC1D;QAEA,OAAO;YACL+C,aAAa/C,MAAMO,OAAO;YAC1ByC,YAAYC,kBAAkB5C;QAChC;IACF;AACF;AAEA,SAASW,iBAAiBH,SAAiB;IACzC,IAAIA,YAAYtB,OAAO2D,0BAA0B,EAAE;QACjD,MAAM,IAAIzD,4BAA4BF,OAAO2D,0BAA0B;IACzE;AACF;AAEA,SAASzB,uBAAuB0B,oBAA2D;IACzF,MAAMH,aAAaC,kBAAkBE;IACrC,IAAIH,WAAWI,eAAe,GAAG7D,OAAO8D,6BAA6B,EAAE;QACrE,MAAM,IAAI3D,kCAAkCH,OAAO8D,6BAA6B;IAClF;IACA,IAAIL,WAAWM,cAAc,GAAG/D,OAAOgE,2BAA2B,EAAE;QAClE,MAAM,IAAI5D,uCAAuCJ,OAAOgE,2BAA2B;IACrF;AACF;AAEA,SAASN,kBAAkBE,oBAA2D;IACpF,OAAO;QACLC,iBAAiBD,qBAAqBK,IAAI;QAC1CF,gBAAgBb,MAAMC,IAAI,CAACS,qBAAqBR,MAAM,IAAIc,MAAM,CAC9D,CAACC,OAAOb,aAAea,QAAQb,WAAWhC,SAAS,EACnD;IAEJ;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"inter-module.d.ts","sourceRoot":"","sources":["../../src/presentation/inter-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,8BAA8B,EAAC,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAQ/B,wBAAgB,wCAAwC,IAAI,uBAAuB,CACjF,OAAO,8BAA8B,CACtC,CAmBA;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAkB7E"}
1
+ {"version":3,"file":"inter-module.d.ts","sourceRoot":"","sources":["../../src/presentation/inter-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,8BAA8B,EAAC,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAU/B,wBAAgB,wCAAwC,IAAI,uBAAuB,CACjF,OAAO,8BAA8B,CACtC,CAqCA;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAkB7E"}
@@ -2,6 +2,8 @@ import { annotationsInterModuleContract } from '@shipfox/annotations-dto/inter-m
2
2
  import { createInterModuleKnownError, defineInterModulePresentation } from '@shipfox/inter-module';
3
3
  import { AnnotationBodyTooLargeError, AnnotationCountLimitExceededError, AnnotationTotalBytesLimitExceededError } from '#core/errors.js';
4
4
  import { writeAnnotations } from '#core/write-annotations.js';
5
+ import { listAnnotationsForRunAttempt } from '#db/index.js';
6
+ import { toAnnotationDto } from './dto/annotation.js';
5
7
  export function createAnnotationsInterModulePresentation() {
6
8
  return defineInterModulePresentation(annotationsInterModuleContract, {
7
9
  replaceOrRemoveAnnotation: async (input)=>{
@@ -24,6 +26,29 @@ export function createAnnotationsInterModulePresentation() {
24
26
  } catch (error) {
25
27
  throw toReplaceOrRemoveAnnotationKnownError(error);
26
28
  }
29
+ },
30
+ listAnnotationsForRunAttempt: async (input)=>{
31
+ const result = await listAnnotationsForRunAttempt({
32
+ workflowRunId: input.workflowRunId,
33
+ workflowRunAttempt: input.workflowRunAttempt,
34
+ workspaceIds: [
35
+ input.workspaceId
36
+ ],
37
+ jobExecutionId: input.jobExecutionId,
38
+ after: input.cursor ? {
39
+ sequence: input.cursor.value,
40
+ id: input.cursor.id
41
+ } : undefined,
42
+ limit: input.limit
43
+ });
44
+ return {
45
+ annotations: result.annotations.map(toAnnotationDto),
46
+ hasMore: result.hasMore,
47
+ nextCursor: result.nextCursor ? {
48
+ value: result.nextCursor.sequence,
49
+ id: result.nextCursor.id
50
+ } : null
51
+ };
27
52
  }
28
53
  });
29
54
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {annotationsInterModuleContract} from '@shipfox/annotations-dto/inter-module';\nimport {\n createInterModuleKnownError,\n defineInterModulePresentation,\n type InterModulePresentation,\n} from '@shipfox/inter-module';\nimport {\n AnnotationBodyTooLargeError,\n AnnotationCountLimitExceededError,\n AnnotationTotalBytesLimitExceededError,\n} from '#core/errors.js';\nimport {writeAnnotations} from '#core/write-annotations.js';\n\nexport function createAnnotationsInterModulePresentation(): InterModulePresentation<\n typeof annotationsInterModuleContract\n> {\n return defineInterModulePresentation(annotationsInterModuleContract, {\n replaceOrRemoveAnnotation: async (input) => {\n try {\n const {annotation, context, ...target} = input;\n await writeAnnotations({\n ...target,\n operations: [\n annotation.op === 'remove'\n ? {context, style: 'warning', op: 'remove'}\n : {context, ...annotation},\n ],\n });\n return {};\n } catch (error) {\n throw toReplaceOrRemoveAnnotationKnownError(error);\n }\n },\n });\n}\n\nexport function toReplaceOrRemoveAnnotationKnownError(error: unknown): unknown {\n const method = annotationsInterModuleContract.methods.replaceOrRemoveAnnotation;\n if (error instanceof AnnotationBodyTooLargeError) {\n return createInterModuleKnownError(method, 'annotation-body-too-large', {\n maxBytes: error.maxBytes,\n });\n }\n if (error instanceof AnnotationCountLimitExceededError) {\n return createInterModuleKnownError(method, 'annotation-count-limit-exceeded', {\n maxAnnotations: error.maxAnnotations,\n });\n }\n if (error instanceof AnnotationTotalBytesLimitExceededError) {\n return createInterModuleKnownError(method, 'annotation-total-bytes-limit-exceeded', {\n maxBytes: error.maxBytes,\n });\n }\n return error;\n}\n"],"names":["annotationsInterModuleContract","createInterModuleKnownError","defineInterModulePresentation","AnnotationBodyTooLargeError","AnnotationCountLimitExceededError","AnnotationTotalBytesLimitExceededError","writeAnnotations","createAnnotationsInterModulePresentation","replaceOrRemoveAnnotation","input","annotation","context","target","operations","op","style","error","toReplaceOrRemoveAnnotationKnownError","method","methods","maxBytes","maxAnnotations"],"mappings":"AAAA,SAAQA,8BAA8B,QAAO,wCAAwC;AACrF,SACEC,2BAA2B,EAC3BC,6BAA6B,QAExB,wBAAwB;AAC/B,SACEC,2BAA2B,EAC3BC,iCAAiC,EACjCC,sCAAsC,QACjC,kBAAkB;AACzB,SAAQC,gBAAgB,QAAO,6BAA6B;AAE5D,OAAO,SAASC;IAGd,OAAOL,8BAA8BF,gCAAgC;QACnEQ,2BAA2B,OAAOC;YAChC,IAAI;gBACF,MAAM,EAACC,UAAU,EAAEC,OAAO,EAAE,GAAGC,QAAO,GAAGH;gBACzC,MAAMH,iBAAiB;oBACrB,GAAGM,MAAM;oBACTC,YAAY;wBACVH,WAAWI,EAAE,KAAK,WACd;4BAACH;4BAASI,OAAO;4BAAWD,IAAI;wBAAQ,IACxC;4BAACH;4BAAS,GAAGD,UAAU;wBAAA;qBAC5B;gBACH;gBACA,OAAO,CAAC;YACV,EAAE,OAAOM,OAAO;gBACd,MAAMC,sCAAsCD;YAC9C;QACF;IACF;AACF;AAEA,OAAO,SAASC,sCAAsCD,KAAc;IAClE,MAAME,SAASlB,+BAA+BmB,OAAO,CAACX,yBAAyB;IAC/E,IAAIQ,iBAAiBb,6BAA6B;QAChD,OAAOF,4BAA4BiB,QAAQ,6BAA6B;YACtEE,UAAUJ,MAAMI,QAAQ;QAC1B;IACF;IACA,IAAIJ,iBAAiBZ,mCAAmC;QACtD,OAAOH,4BAA4BiB,QAAQ,mCAAmC;YAC5EG,gBAAgBL,MAAMK,cAAc;QACtC;IACF;IACA,IAAIL,iBAAiBX,wCAAwC;QAC3D,OAAOJ,4BAA4BiB,QAAQ,yCAAyC;YAClFE,UAAUJ,MAAMI,QAAQ;QAC1B;IACF;IACA,OAAOJ;AACT"}
1
+ {"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {annotationsInterModuleContract} from '@shipfox/annotations-dto/inter-module';\nimport {\n createInterModuleKnownError,\n defineInterModulePresentation,\n type InterModulePresentation,\n} from '@shipfox/inter-module';\nimport {\n AnnotationBodyTooLargeError,\n AnnotationCountLimitExceededError,\n AnnotationTotalBytesLimitExceededError,\n} from '#core/errors.js';\nimport {writeAnnotations} from '#core/write-annotations.js';\nimport {listAnnotationsForRunAttempt} from '#db/index.js';\nimport {toAnnotationDto} from './dto/annotation.js';\n\nexport function createAnnotationsInterModulePresentation(): InterModulePresentation<\n typeof annotationsInterModuleContract\n> {\n return defineInterModulePresentation(annotationsInterModuleContract, {\n replaceOrRemoveAnnotation: async (input) => {\n try {\n const {annotation, context, ...target} = input;\n await writeAnnotations({\n ...target,\n operations: [\n annotation.op === 'remove'\n ? {context, style: 'warning', op: 'remove'}\n : {context, ...annotation},\n ],\n });\n return {};\n } catch (error) {\n throw toReplaceOrRemoveAnnotationKnownError(error);\n }\n },\n listAnnotationsForRunAttempt: async (input) => {\n const result = await listAnnotationsForRunAttempt({\n workflowRunId: input.workflowRunId,\n workflowRunAttempt: input.workflowRunAttempt,\n workspaceIds: [input.workspaceId],\n jobExecutionId: input.jobExecutionId,\n after: input.cursor ? {sequence: input.cursor.value, id: input.cursor.id} : undefined,\n limit: input.limit,\n });\n\n return {\n annotations: result.annotations.map(toAnnotationDto),\n hasMore: result.hasMore,\n nextCursor: result.nextCursor\n ? {value: result.nextCursor.sequence, id: result.nextCursor.id}\n : null,\n };\n },\n });\n}\n\nexport function toReplaceOrRemoveAnnotationKnownError(error: unknown): unknown {\n const method = annotationsInterModuleContract.methods.replaceOrRemoveAnnotation;\n if (error instanceof AnnotationBodyTooLargeError) {\n return createInterModuleKnownError(method, 'annotation-body-too-large', {\n maxBytes: error.maxBytes,\n });\n }\n if (error instanceof AnnotationCountLimitExceededError) {\n return createInterModuleKnownError(method, 'annotation-count-limit-exceeded', {\n maxAnnotations: error.maxAnnotations,\n });\n }\n if (error instanceof AnnotationTotalBytesLimitExceededError) {\n return createInterModuleKnownError(method, 'annotation-total-bytes-limit-exceeded', {\n maxBytes: error.maxBytes,\n });\n }\n return error;\n}\n"],"names":["annotationsInterModuleContract","createInterModuleKnownError","defineInterModulePresentation","AnnotationBodyTooLargeError","AnnotationCountLimitExceededError","AnnotationTotalBytesLimitExceededError","writeAnnotations","listAnnotationsForRunAttempt","toAnnotationDto","createAnnotationsInterModulePresentation","replaceOrRemoveAnnotation","input","annotation","context","target","operations","op","style","error","toReplaceOrRemoveAnnotationKnownError","result","workflowRunId","workflowRunAttempt","workspaceIds","workspaceId","jobExecutionId","after","cursor","sequence","value","id","undefined","limit","annotations","map","hasMore","nextCursor","method","methods","maxBytes","maxAnnotations"],"mappings":"AAAA,SAAQA,8BAA8B,QAAO,wCAAwC;AACrF,SACEC,2BAA2B,EAC3BC,6BAA6B,QAExB,wBAAwB;AAC/B,SACEC,2BAA2B,EAC3BC,iCAAiC,EACjCC,sCAAsC,QACjC,kBAAkB;AACzB,SAAQC,gBAAgB,QAAO,6BAA6B;AAC5D,SAAQC,4BAA4B,QAAO,eAAe;AAC1D,SAAQC,eAAe,QAAO,sBAAsB;AAEpD,OAAO,SAASC;IAGd,OAAOP,8BAA8BF,gCAAgC;QACnEU,2BAA2B,OAAOC;YAChC,IAAI;gBACF,MAAM,EAACC,UAAU,EAAEC,OAAO,EAAE,GAAGC,QAAO,GAAGH;gBACzC,MAAML,iBAAiB;oBACrB,GAAGQ,MAAM;oBACTC,YAAY;wBACVH,WAAWI,EAAE,KAAK,WACd;4BAACH;4BAASI,OAAO;4BAAWD,IAAI;wBAAQ,IACxC;4BAACH;4BAAS,GAAGD,UAAU;wBAAA;qBAC5B;gBACH;gBACA,OAAO,CAAC;YACV,EAAE,OAAOM,OAAO;gBACd,MAAMC,sCAAsCD;YAC9C;QACF;QACAX,8BAA8B,OAAOI;YACnC,MAAMS,SAAS,MAAMb,6BAA6B;gBAChDc,eAAeV,MAAMU,aAAa;gBAClCC,oBAAoBX,MAAMW,kBAAkB;gBAC5CC,cAAc;oBAACZ,MAAMa,WAAW;iBAAC;gBACjCC,gBAAgBd,MAAMc,cAAc;gBACpCC,OAAOf,MAAMgB,MAAM,GAAG;oBAACC,UAAUjB,MAAMgB,MAAM,CAACE,KAAK;oBAAEC,IAAInB,MAAMgB,MAAM,CAACG,EAAE;gBAAA,IAAIC;gBAC5EC,OAAOrB,MAAMqB,KAAK;YACpB;YAEA,OAAO;gBACLC,aAAab,OAAOa,WAAW,CAACC,GAAG,CAAC1B;gBACpC2B,SAASf,OAAOe,OAAO;gBACvBC,YAAYhB,OAAOgB,UAAU,GACzB;oBAACP,OAAOT,OAAOgB,UAAU,CAACR,QAAQ;oBAAEE,IAAIV,OAAOgB,UAAU,CAACN,EAAE;gBAAA,IAC5D;YACN;QACF;IACF;AACF;AAEA,OAAO,SAASX,sCAAsCD,KAAc;IAClE,MAAMmB,SAASrC,+BAA+BsC,OAAO,CAAC5B,yBAAyB;IAC/E,IAAIQ,iBAAiBf,6BAA6B;QAChD,OAAOF,4BAA4BoC,QAAQ,6BAA6B;YACtEE,UAAUrB,MAAMqB,QAAQ;QAC1B;IACF;IACA,IAAIrB,iBAAiBd,mCAAmC;QACtD,OAAOH,4BAA4BoC,QAAQ,mCAAmC;YAC5EG,gBAAgBtB,MAAMsB,cAAc;QACtC;IACF;IACA,IAAItB,iBAAiBb,wCAAwC;QAC3D,OAAOJ,4BAA4BoC,QAAQ,yCAAyC;YAClFE,UAAUrB,MAAMqB,QAAQ;QAC1B;IACF;IACA,OAAOrB;AACT"}