@shipfox/annotations 2.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 (109) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +67 -0
  5. package/LICENSE +21 -0
  6. package/dist/config.d.ts +6 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +26 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/core/entities/annotation.d.ts +21 -0
  11. package/dist/core/entities/annotation.d.ts.map +1 -0
  12. package/dist/core/entities/annotation.js +3 -0
  13. package/dist/core/entities/annotation.js.map +1 -0
  14. package/dist/core/entities/index.d.ts +2 -0
  15. package/dist/core/entities/index.d.ts.map +1 -0
  16. package/dist/core/entities/index.js +3 -0
  17. package/dist/core/entities/index.js.map +1 -0
  18. package/dist/core/errors.d.ts +13 -0
  19. package/dist/core/errors.d.ts.map +1 -0
  20. package/dist/core/errors.js +20 -0
  21. package/dist/core/errors.js.map +1 -0
  22. package/dist/core/write-annotations.d.ts +25 -0
  23. package/dist/core/write-annotations.d.ts.map +1 -0
  24. package/dist/core/write-annotations.js +105 -0
  25. package/dist/core/write-annotations.js.map +1 -0
  26. package/dist/db/annotations.d.ts +63 -0
  27. package/dist/db/annotations.d.ts.map +1 -0
  28. package/dist/db/annotations.js +96 -0
  29. package/dist/db/annotations.js.map +1 -0
  30. package/dist/db/db.d.ts +304 -0
  31. package/dist/db/db.d.ts.map +1 -0
  32. package/dist/db/db.js +18 -0
  33. package/dist/db/db.js.map +1 -0
  34. package/dist/db/index.d.ts +4 -0
  35. package/dist/db/index.d.ts.map +1 -0
  36. package/dist/db/index.js +6 -0
  37. package/dist/db/index.js.map +1 -0
  38. package/dist/db/schema/annotations.d.ts +302 -0
  39. package/dist/db/schema/annotations.d.ts.map +1 -0
  40. package/dist/db/schema/annotations.js +67 -0
  41. package/dist/db/schema/annotations.js.map +1 -0
  42. package/dist/db/schema/common.d.ts +2 -0
  43. package/dist/db/schema/common.d.ts.map +1 -0
  44. package/dist/db/schema/common.js +4 -0
  45. package/dist/db/schema/common.js.map +1 -0
  46. package/dist/index.d.ts +5 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +15 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/presentation/dto/annotation.d.ts +4 -0
  51. package/dist/presentation/dto/annotation.d.ts.map +1 -0
  52. package/dist/presentation/dto/annotation.js +15 -0
  53. package/dist/presentation/dto/annotation.js.map +1 -0
  54. package/dist/presentation/dto/index.d.ts +2 -0
  55. package/dist/presentation/dto/index.d.ts.map +1 -0
  56. package/dist/presentation/dto/index.js +3 -0
  57. package/dist/presentation/dto/index.js.map +1 -0
  58. package/dist/presentation/routes/index.d.ts +3 -0
  59. package/dist/presentation/routes/index.d.ts.map +1 -0
  60. package/dist/presentation/routes/index.js +21 -0
  61. package/dist/presentation/routes/index.js.map +1 -0
  62. package/dist/presentation/routes/read-annotations.d.ts +2 -0
  63. package/dist/presentation/routes/read-annotations.d.ts.map +1 -0
  64. package/dist/presentation/routes/read-annotations.js +49 -0
  65. package/dist/presentation/routes/read-annotations.js.map +1 -0
  66. package/dist/presentation/routes/write-annotations.d.ts +2 -0
  67. package/dist/presentation/routes/write-annotations.d.ts.map +1 -0
  68. package/dist/presentation/routes/write-annotations.js +73 -0
  69. package/dist/presentation/routes/write-annotations.js.map +1 -0
  70. package/dist/tsconfig.test.tsbuildinfo +1 -0
  71. package/drizzle/0000_initial.sql +32 -0
  72. package/drizzle/meta/0000_snapshot.json +247 -0
  73. package/drizzle/meta/_journal.json +13 -0
  74. package/drizzle.config.ts +7 -0
  75. package/package.json +69 -0
  76. package/src/config.test.ts +45 -0
  77. package/src/config.ts +26 -0
  78. package/src/core/entities/annotation.ts +21 -0
  79. package/src/core/entities/index.ts +1 -0
  80. package/src/core/errors.ts +20 -0
  81. package/src/core/write-annotations.test.ts +261 -0
  82. package/src/core/write-annotations.ts +142 -0
  83. package/src/db/annotations.test.ts +261 -0
  84. package/src/db/annotations.ts +180 -0
  85. package/src/db/db.ts +19 -0
  86. package/src/db/index.ts +7 -0
  87. package/src/db/schema/annotations.test.ts +50 -0
  88. package/src/db/schema/annotations.ts +96 -0
  89. package/src/db/schema/common.ts +3 -0
  90. package/src/index.ts +17 -0
  91. package/src/presentation/dto/annotation.test.ts +42 -0
  92. package/src/presentation/dto/annotation.ts +16 -0
  93. package/src/presentation/dto/index.ts +1 -0
  94. package/src/presentation/routes/index.ts +17 -0
  95. package/src/presentation/routes/read-annotations.test.ts +279 -0
  96. package/src/presentation/routes/read-annotations.ts +50 -0
  97. package/src/presentation/routes/write-annotations.test.ts +188 -0
  98. package/src/presentation/routes/write-annotations.ts +76 -0
  99. package/test/env.ts +5 -0
  100. package/test/factories/annotation.ts +57 -0
  101. package/test/fixtures/lease-token.ts +43 -0
  102. package/test/globalSetup.ts +20 -0
  103. package/test/index.ts +2 -0
  104. package/test/setup.ts +17 -0
  105. package/tsconfig.build.json +9 -0
  106. package/tsconfig.build.tsbuildinfo +1 -0
  107. package/tsconfig.json +3 -0
  108. package/tsconfig.test.json +8 -0
  109. package/vitest.config.ts +13 -0
@@ -0,0 +1,67 @@
1
+ import { ANNOTATION_CONTEXT_MAX_LENGTH, ANNOTATION_CONTEXT_TRIM_CODE_POINTS, ANNOTATION_STYLES } from '@shipfox/annotations-dto';
2
+ import { uuidv7PrimaryKey } from '@shipfox/node-drizzle';
3
+ import { sql } from 'drizzle-orm';
4
+ import { check, index, integer, pgEnum, text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
5
+ import { pgTable } from './common.js';
6
+ export const annotationStyleEnum = pgEnum('annotations_style', [
7
+ ...ANNOTATION_STYLES
8
+ ]);
9
+ const annotationContextTrimCharactersSql = sql`concat(${sql.join(ANNOTATION_CONTEXT_TRIM_CODE_POINTS.map((codePoint)=>sql.raw(`chr(${codePoint})`)), sql`, `)})`;
10
+ export const annotations = pgTable('annotations', {
11
+ id: uuidv7PrimaryKey(),
12
+ workspaceId: uuid('workspace_id').notNull(),
13
+ projectId: uuid('project_id').notNull(),
14
+ workflowRunId: uuid('workflow_run_id').notNull(),
15
+ workflowRunAttempt: integer('workflow_run_attempt').notNull(),
16
+ workflowRunAttemptId: uuid('workflow_run_attempt_id').notNull(),
17
+ jobId: uuid('job_id').notNull(),
18
+ jobExecutionId: uuid('job_execution_id').notNull(),
19
+ originStepId: uuid('origin_step_id').notNull(),
20
+ originStepAttempt: integer('origin_step_attempt').notNull(),
21
+ context: text('context').notNull(),
22
+ style: annotationStyleEnum('style').notNull().default('default'),
23
+ body: text('body').notNull(),
24
+ bodyBytes: integer('body_bytes').notNull(),
25
+ sequence: integer('sequence').notNull(),
26
+ createdAt: timestamp('created_at', {
27
+ withTimezone: true
28
+ }).notNull().defaultNow(),
29
+ updatedAt: timestamp('updated_at', {
30
+ withTimezone: true
31
+ }).notNull().defaultNow()
32
+ }, (table)=>[
33
+ uniqueIndex('annotations_job_execution_context_unique').on(table.jobExecutionId, table.context),
34
+ index('annotations_workflow_run_attempt_idx').on(table.workflowRunId, table.workflowRunAttempt),
35
+ index('annotations_workflow_run_attempt_id_idx').on(table.workflowRunAttemptId),
36
+ index('annotations_job_execution_id_idx').on(table.jobExecutionId),
37
+ check('annotations_workflow_run_attempt_positive_ck', sql`${table.workflowRunAttempt} > 0`),
38
+ check('annotations_origin_step_attempt_positive_ck', sql`${table.originStepAttempt} > 0`),
39
+ check('annotations_body_bytes_matches_body_ck', sql`${table.bodyBytes} = octet_length(${table.body})`),
40
+ check('annotations_sequence_positive_ck', sql`${table.sequence} > 0`),
41
+ check('annotations_context_not_empty_ck', sql`length(${table.context}) > 0`),
42
+ check('annotations_context_trimmed_ck', sql`${table.context} = btrim(${table.context}, ${annotationContextTrimCharactersSql})`),
43
+ check('annotations_context_max_length_ck', sql`length(${table.context}) <= ${ANNOTATION_CONTEXT_MAX_LENGTH}`)
44
+ ]);
45
+ export function toAnnotation(row) {
46
+ return {
47
+ id: row.id,
48
+ workspaceId: row.workspaceId,
49
+ projectId: row.projectId,
50
+ workflowRunId: row.workflowRunId,
51
+ workflowRunAttempt: row.workflowRunAttempt,
52
+ workflowRunAttemptId: row.workflowRunAttemptId,
53
+ jobId: row.jobId,
54
+ jobExecutionId: row.jobExecutionId,
55
+ originStepId: row.originStepId,
56
+ originStepAttempt: row.originStepAttempt,
57
+ context: row.context,
58
+ style: row.style,
59
+ body: row.body,
60
+ bodyBytes: row.bodyBytes,
61
+ sequence: row.sequence,
62
+ createdAt: row.createdAt,
63
+ updatedAt: row.updatedAt
64
+ };
65
+ }
66
+
67
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/db/schema/annotations.ts"],"sourcesContent":["import {\n ANNOTATION_CONTEXT_MAX_LENGTH,\n ANNOTATION_CONTEXT_TRIM_CODE_POINTS,\n ANNOTATION_STYLES,\n} from '@shipfox/annotations-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {\n check,\n index,\n integer,\n pgEnum,\n text,\n timestamp,\n uniqueIndex,\n uuid,\n} from 'drizzle-orm/pg-core';\nimport type {Annotation} from '#core/entities/annotation.js';\nimport {pgTable} from './common.js';\n\nexport const annotationStyleEnum = pgEnum('annotations_style', [...ANNOTATION_STYLES]);\n\nconst annotationContextTrimCharactersSql = sql`concat(${sql.join(\n ANNOTATION_CONTEXT_TRIM_CODE_POINTS.map((codePoint) => sql.raw(`chr(${codePoint})`)),\n sql`, `,\n)})`;\n\nexport const annotations = pgTable(\n 'annotations',\n {\n id: uuidv7PrimaryKey(),\n workspaceId: uuid('workspace_id').notNull(),\n projectId: uuid('project_id').notNull(),\n workflowRunId: uuid('workflow_run_id').notNull(),\n workflowRunAttempt: integer('workflow_run_attempt').notNull(),\n workflowRunAttemptId: uuid('workflow_run_attempt_id').notNull(),\n jobId: uuid('job_id').notNull(),\n jobExecutionId: uuid('job_execution_id').notNull(),\n originStepId: uuid('origin_step_id').notNull(),\n originStepAttempt: integer('origin_step_attempt').notNull(),\n context: text('context').notNull(),\n style: annotationStyleEnum('style').notNull().default('default'),\n body: text('body').notNull(),\n bodyBytes: integer('body_bytes').notNull(),\n sequence: integer('sequence').notNull(),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('annotations_job_execution_context_unique').on(table.jobExecutionId, table.context),\n index('annotations_workflow_run_attempt_idx').on(table.workflowRunId, table.workflowRunAttempt),\n index('annotations_workflow_run_attempt_id_idx').on(table.workflowRunAttemptId),\n index('annotations_job_execution_id_idx').on(table.jobExecutionId),\n check('annotations_workflow_run_attempt_positive_ck', sql`${table.workflowRunAttempt} > 0`),\n check('annotations_origin_step_attempt_positive_ck', sql`${table.originStepAttempt} > 0`),\n check(\n 'annotations_body_bytes_matches_body_ck',\n sql`${table.bodyBytes} = octet_length(${table.body})`,\n ),\n check('annotations_sequence_positive_ck', sql`${table.sequence} > 0`),\n check('annotations_context_not_empty_ck', sql`length(${table.context}) > 0`),\n check(\n 'annotations_context_trimmed_ck',\n sql`${table.context} = btrim(${table.context}, ${annotationContextTrimCharactersSql})`,\n ),\n check(\n 'annotations_context_max_length_ck',\n sql`length(${table.context}) <= ${ANNOTATION_CONTEXT_MAX_LENGTH}`,\n ),\n ],\n);\n\nexport type AnnotationDb = typeof annotations.$inferSelect;\nexport type AnnotationCreateDb = typeof annotations.$inferInsert;\n\nexport function toAnnotation(row: AnnotationDb): Annotation {\n return {\n id: row.id,\n workspaceId: row.workspaceId,\n projectId: row.projectId,\n workflowRunId: row.workflowRunId,\n workflowRunAttempt: row.workflowRunAttempt,\n workflowRunAttemptId: row.workflowRunAttemptId,\n jobId: row.jobId,\n jobExecutionId: row.jobExecutionId,\n originStepId: row.originStepId,\n originStepAttempt: row.originStepAttempt,\n context: row.context,\n style: row.style,\n body: row.body,\n bodyBytes: row.bodyBytes,\n sequence: row.sequence,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["ANNOTATION_CONTEXT_MAX_LENGTH","ANNOTATION_CONTEXT_TRIM_CODE_POINTS","ANNOTATION_STYLES","uuidv7PrimaryKey","sql","check","index","integer","pgEnum","text","timestamp","uniqueIndex","uuid","pgTable","annotationStyleEnum","annotationContextTrimCharactersSql","join","map","codePoint","raw","annotations","id","workspaceId","notNull","projectId","workflowRunId","workflowRunAttempt","workflowRunAttemptId","jobId","jobExecutionId","originStepId","originStepAttempt","context","style","default","body","bodyBytes","sequence","createdAt","withTimezone","defaultNow","updatedAt","table","on","toAnnotation","row"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const pgTable: import("drizzle-orm/pg-core").PgTableFn<undefined>;
2
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/db/schema/common.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,oDAAkD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { pgTableCreator } from 'drizzle-orm/pg-core';
2
+ export const pgTable = pgTableCreator((name)=>`annotations_${name}`);
3
+
4
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/db/schema/common.ts"],"sourcesContent":["import {pgTableCreator} from 'drizzle-orm/pg-core';\n\nexport const pgTable = pgTableCreator((name) => `annotations_${name}`);\n"],"names":["pgTableCreator","pgTable","name"],"mappings":"AAAA,SAAQA,cAAc,QAAO,sBAAsB;AAEnD,OAAO,MAAMC,UAAUD,eAAe,CAACE,OAAS,CAAC,YAAY,EAAEA,MAAM,EAAE"}
@@ -0,0 +1,5 @@
1
+ import type { ShipfoxModule } from '@shipfox/node-module';
2
+ export { AnnotationBodyTooLargeError, AnnotationCountLimitExceededError, AnnotationTotalBytesLimitExceededError, } from '#core/errors.js';
3
+ export { type WriteAnnotationsParams, writeAnnotations } from '#core/write-annotations.js';
4
+ export declare const annotationsModule: ShipfoxModule;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAKxD,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,sCAAsC,GACvC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,KAAK,sBAAsB,EAAE,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AAEzF,eAAO,MAAM,iBAAiB,EAAE,aAI/B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ import { db } from '#db/db.js';
2
+ import { migrationsPath } from '#db/index.js';
3
+ import { annotationsRoutes } from '#presentation/routes/index.js';
4
+ export { AnnotationBodyTooLargeError, AnnotationCountLimitExceededError, AnnotationTotalBytesLimitExceededError } from '#core/errors.js';
5
+ export { writeAnnotations } from '#core/write-annotations.js';
6
+ export const annotationsModule = {
7
+ name: 'annotations',
8
+ database: {
9
+ db,
10
+ migrationsPath
11
+ },
12
+ routes: annotationsRoutes
13
+ };
14
+
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {ShipfoxModule} from '@shipfox/node-module';\nimport {db} from '#db/db.js';\nimport {migrationsPath} from '#db/index.js';\nimport {annotationsRoutes} from '#presentation/routes/index.js';\n\nexport {\n AnnotationBodyTooLargeError,\n AnnotationCountLimitExceededError,\n AnnotationTotalBytesLimitExceededError,\n} from '#core/errors.js';\nexport {type WriteAnnotationsParams, writeAnnotations} from '#core/write-annotations.js';\n\nexport const annotationsModule: ShipfoxModule = {\n name: 'annotations',\n database: {db, migrationsPath},\n routes: annotationsRoutes,\n};\n"],"names":["db","migrationsPath","annotationsRoutes","AnnotationBodyTooLargeError","AnnotationCountLimitExceededError","AnnotationTotalBytesLimitExceededError","writeAnnotations","annotationsModule","name","database","routes"],"mappings":"AACA,SAAQA,EAAE,QAAO,YAAY;AAC7B,SAAQC,cAAc,QAAO,eAAe;AAC5C,SAAQC,iBAAiB,QAAO,gCAAgC;AAEhE,SACEC,2BAA2B,EAC3BC,iCAAiC,EACjCC,sCAAsC,QACjC,kBAAkB;AACzB,SAAqCC,gBAAgB,QAAO,6BAA6B;AAEzF,OAAO,MAAMC,oBAAmC;IAC9CC,MAAM;IACNC,UAAU;QAACT;QAAIC;IAAc;IAC7BS,QAAQR;AACV,EAAE"}
@@ -0,0 +1,4 @@
1
+ import type { AnnotationDto } from '@shipfox/annotations-dto';
2
+ import type { Annotation } from '#core/entities/annotation.js';
3
+ export declare function toAnnotationDto(annotation: Annotation): AnnotationDto;
4
+ //# sourceMappingURL=annotation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/annotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAE7D,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,CAYrE"}
@@ -0,0 +1,15 @@
1
+ export function toAnnotationDto(annotation) {
2
+ return {
3
+ id: annotation.id,
4
+ job_id: annotation.jobId,
5
+ job_execution_id: annotation.jobExecutionId,
6
+ origin_step_id: annotation.originStepId,
7
+ origin_step_attempt: annotation.originStepAttempt,
8
+ context: annotation.context,
9
+ style: annotation.style,
10
+ sequence: annotation.sequence,
11
+ body: annotation.body
12
+ };
13
+ }
14
+
15
+ //# sourceMappingURL=annotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/dto/annotation.ts"],"sourcesContent":["import type {AnnotationDto} from '@shipfox/annotations-dto';\nimport type {Annotation} from '#core/entities/annotation.js';\n\nexport function toAnnotationDto(annotation: Annotation): AnnotationDto {\n return {\n id: annotation.id,\n job_id: annotation.jobId,\n job_execution_id: annotation.jobExecutionId,\n origin_step_id: annotation.originStepId,\n origin_step_attempt: annotation.originStepAttempt,\n context: annotation.context,\n style: annotation.style,\n sequence: annotation.sequence,\n body: annotation.body,\n };\n}\n"],"names":["toAnnotationDto","annotation","id","job_id","jobId","job_execution_id","jobExecutionId","origin_step_id","originStepId","origin_step_attempt","originStepAttempt","context","style","sequence","body"],"mappings":"AAGA,OAAO,SAASA,gBAAgBC,UAAsB;IACpD,OAAO;QACLC,IAAID,WAAWC,EAAE;QACjBC,QAAQF,WAAWG,KAAK;QACxBC,kBAAkBJ,WAAWK,cAAc;QAC3CC,gBAAgBN,WAAWO,YAAY;QACvCC,qBAAqBR,WAAWS,iBAAiB;QACjDC,SAASV,WAAWU,OAAO;QAC3BC,OAAOX,WAAWW,KAAK;QACvBC,UAAUZ,WAAWY,QAAQ;QAC7BC,MAAMb,WAAWa,IAAI;IACvB;AACF"}
@@ -0,0 +1,2 @@
1
+ export { toAnnotationDto } from './annotation.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { toAnnotationDto } from './annotation.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/dto/index.ts"],"sourcesContent":["export {toAnnotationDto} from './annotation.js';\n"],"names":["toAnnotationDto"],"mappings":"AAAA,SAAQA,eAAe,QAAO,kBAAkB"}
@@ -0,0 +1,3 @@
1
+ import type { RouteGroup } from '@shipfox/node-fastify';
2
+ export declare const annotationsRoutes: RouteGroup[];
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAItD,eAAO,MAAM,iBAAiB,EAAE,UAAU,EAWzC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { AUTH_LEASED_JOB, AUTH_USER } from '@shipfox/api-auth-context';
2
+ import { readAnnotationsRoute } from './read-annotations.js';
3
+ import { writeAnnotationsRoute } from './write-annotations.js';
4
+ export const annotationsRoutes = [
5
+ {
6
+ prefix: '/annotations',
7
+ auth: AUTH_USER,
8
+ routes: [
9
+ readAnnotationsRoute
10
+ ]
11
+ },
12
+ {
13
+ prefix: '/runs/jobs/current',
14
+ auth: AUTH_LEASED_JOB,
15
+ routes: [
16
+ writeAnnotationsRoute
17
+ ]
18
+ }
19
+ ];
20
+
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/index.ts"],"sourcesContent":["import {AUTH_LEASED_JOB, AUTH_USER} from '@shipfox/api-auth-context';\nimport type {RouteGroup} from '@shipfox/node-fastify';\nimport {readAnnotationsRoute} from './read-annotations.js';\nimport {writeAnnotationsRoute} from './write-annotations.js';\n\nexport const annotationsRoutes: RouteGroup[] = [\n {\n prefix: '/annotations',\n auth: AUTH_USER,\n routes: [readAnnotationsRoute],\n },\n {\n prefix: '/runs/jobs/current',\n auth: AUTH_LEASED_JOB,\n routes: [writeAnnotationsRoute],\n },\n];\n"],"names":["AUTH_LEASED_JOB","AUTH_USER","readAnnotationsRoute","writeAnnotationsRoute","annotationsRoutes","prefix","auth","routes"],"mappings":"AAAA,SAAQA,eAAe,EAAEC,SAAS,QAAO,4BAA4B;AAErE,SAAQC,oBAAoB,QAAO,wBAAwB;AAC3D,SAAQC,qBAAqB,QAAO,yBAAyB;AAE7D,OAAO,MAAMC,oBAAkC;IAC7C;QACEC,QAAQ;QACRC,MAAML;QACNM,QAAQ;YAACL;SAAqB;IAChC;IACA;QACEG,QAAQ;QACRC,MAAMN;QACNO,QAAQ;YAACJ;SAAsB;IACjC;CACD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const readAnnotationsRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=read-annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-annotations.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/read-annotations.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,iDA0C/B,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { readAnnotationsQuerySchema, readAnnotationsResponseSchema } from '@shipfox/annotations-dto';
2
+ import { requireUserContext } from '@shipfox/api-auth-context';
3
+ import { decodeNumberIdCursor, encodeNumberIdCursor } from '@shipfox/node-drizzle';
4
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
5
+ import { listAnnotationsForRunAttempt } from '#db/index.js';
6
+ import { toAnnotationDto } from '#presentation/dto/index.js';
7
+ export const readAnnotationsRoute = defineRoute({
8
+ method: 'GET',
9
+ path: '/',
10
+ description: 'Read annotations for a workflow run attempt.',
11
+ schema: {
12
+ querystring: readAnnotationsQuerySchema,
13
+ response: {
14
+ 200: readAnnotationsResponseSchema
15
+ }
16
+ },
17
+ handler: async (request)=>{
18
+ const user = requireUserContext(request);
19
+ const { workflow_run_id: workflowRunId, attempt, job_execution_id: jobExecutionId, cursor, limit } = request.query;
20
+ const decodedCursor = decodeNumberIdCursor(cursor);
21
+ if (cursor !== undefined && !decodedCursor) {
22
+ throw new ClientError('Invalid cursor', 'invalid-cursor', {
23
+ status: 400
24
+ });
25
+ }
26
+ const workspaceIds = user.memberships.map((membership)=>membership.workspaceId);
27
+ const result = await listAnnotationsForRunAttempt({
28
+ workflowRunId,
29
+ workflowRunAttempt: attempt,
30
+ workspaceIds,
31
+ jobExecutionId,
32
+ after: decodedCursor ? {
33
+ sequence: decodedCursor.value,
34
+ id: decodedCursor.id
35
+ } : undefined,
36
+ limit
37
+ });
38
+ return {
39
+ annotations: result.annotations.map(toAnnotationDto),
40
+ has_more: result.hasMore,
41
+ next_cursor: result.nextCursor ? encodeNumberIdCursor({
42
+ value: result.nextCursor.sequence,
43
+ id: result.nextCursor.id
44
+ }) : null
45
+ };
46
+ }
47
+ });
48
+
49
+ //# sourceMappingURL=read-annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/read-annotations.ts"],"sourcesContent":["import {readAnnotationsQuerySchema, readAnnotationsResponseSchema} from '@shipfox/annotations-dto';\nimport {requireUserContext} from '@shipfox/api-auth-context';\nimport {decodeNumberIdCursor, encodeNumberIdCursor} from '@shipfox/node-drizzle';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {listAnnotationsForRunAttempt} from '#db/index.js';\nimport {toAnnotationDto} from '#presentation/dto/index.js';\n\nexport const readAnnotationsRoute = defineRoute({\n method: 'GET',\n path: '/',\n description: 'Read annotations for a workflow run attempt.',\n schema: {\n querystring: readAnnotationsQuerySchema,\n response: {\n 200: readAnnotationsResponseSchema,\n },\n },\n handler: async (request) => {\n const user = requireUserContext(request);\n const {\n workflow_run_id: workflowRunId,\n attempt,\n job_execution_id: jobExecutionId,\n cursor,\n limit,\n } = request.query;\n const decodedCursor = decodeNumberIdCursor(cursor);\n if (cursor !== undefined && !decodedCursor) {\n throw new ClientError('Invalid cursor', 'invalid-cursor', {status: 400});\n }\n\n const workspaceIds = user.memberships.map((membership) => membership.workspaceId);\n const result = await listAnnotationsForRunAttempt({\n workflowRunId,\n workflowRunAttempt: attempt,\n workspaceIds,\n jobExecutionId,\n after: decodedCursor ? {sequence: decodedCursor.value, id: decodedCursor.id} : undefined,\n limit,\n });\n\n return {\n annotations: result.annotations.map(toAnnotationDto),\n has_more: result.hasMore,\n next_cursor: result.nextCursor\n ? encodeNumberIdCursor({value: result.nextCursor.sequence, id: result.nextCursor.id})\n : null,\n };\n },\n});\n"],"names":["readAnnotationsQuerySchema","readAnnotationsResponseSchema","requireUserContext","decodeNumberIdCursor","encodeNumberIdCursor","ClientError","defineRoute","listAnnotationsForRunAttempt","toAnnotationDto","readAnnotationsRoute","method","path","description","schema","querystring","response","handler","request","user","workflow_run_id","workflowRunId","attempt","job_execution_id","jobExecutionId","cursor","limit","query","decodedCursor","undefined","status","workspaceIds","memberships","map","membership","workspaceId","result","workflowRunAttempt","after","sequence","value","id","annotations","has_more","hasMore","next_cursor","nextCursor"],"mappings":"AAAA,SAAQA,0BAA0B,EAAEC,6BAA6B,QAAO,2BAA2B;AACnG,SAAQC,kBAAkB,QAAO,4BAA4B;AAC7D,SAAQC,oBAAoB,EAAEC,oBAAoB,QAAO,wBAAwB;AACjF,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,4BAA4B,QAAO,eAAe;AAC1D,SAAQC,eAAe,QAAO,6BAA6B;AAE3D,OAAO,MAAMC,uBAAuBH,YAAY;IAC9CI,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,aAAad;QACbe,UAAU;YACR,KAAKd;QACP;IACF;IACAe,SAAS,OAAOC;QACd,MAAMC,OAAOhB,mBAAmBe;QAChC,MAAM,EACJE,iBAAiBC,aAAa,EAC9BC,OAAO,EACPC,kBAAkBC,cAAc,EAChCC,MAAM,EACNC,KAAK,EACN,GAAGR,QAAQS,KAAK;QACjB,MAAMC,gBAAgBxB,qBAAqBqB;QAC3C,IAAIA,WAAWI,aAAa,CAACD,eAAe;YAC1C,MAAM,IAAItB,YAAY,kBAAkB,kBAAkB;gBAACwB,QAAQ;YAAG;QACxE;QAEA,MAAMC,eAAeZ,KAAKa,WAAW,CAACC,GAAG,CAAC,CAACC,aAAeA,WAAWC,WAAW;QAChF,MAAMC,SAAS,MAAM5B,6BAA6B;YAChDa;YACAgB,oBAAoBf;YACpBS;YACAP;YACAc,OAAOV,gBAAgB;gBAACW,UAAUX,cAAcY,KAAK;gBAAEC,IAAIb,cAAca,EAAE;YAAA,IAAIZ;YAC/EH;QACF;QAEA,OAAO;YACLgB,aAAaN,OAAOM,WAAW,CAACT,GAAG,CAACxB;YACpCkC,UAAUP,OAAOQ,OAAO;YACxBC,aAAaT,OAAOU,UAAU,GAC1BzC,qBAAqB;gBAACmC,OAAOJ,OAAOU,UAAU,CAACP,QAAQ;gBAAEE,IAAIL,OAAOU,UAAU,CAACL,EAAE;YAAA,KACjF;QACN;IACF;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const writeAnnotationsRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=write-annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-annotations.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/write-annotations.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,qBAAqB,iDA8DhC,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { leasedWriteAnnotationsBodySchema, leasedWriteAnnotationsResponseSchema } from '@shipfox/annotations-dto';
2
+ import { requireLeasedJobContext } from '@shipfox/api-auth-context';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { AnnotationBodyTooLargeError, AnnotationCountLimitExceededError, AnnotationTotalBytesLimitExceededError } from '#core/errors.js';
5
+ import { writeAnnotations } from '#core/write-annotations.js';
6
+ export const writeAnnotationsRoute = defineRoute({
7
+ method: 'POST',
8
+ path: '/annotations',
9
+ description: 'Creates, updates, or removes annotations for the current leased job execution.',
10
+ schema: {
11
+ body: leasedWriteAnnotationsBodySchema,
12
+ response: {
13
+ 200: leasedWriteAnnotationsResponseSchema
14
+ }
15
+ },
16
+ errorHandler: (error)=>{
17
+ if (error instanceof AnnotationBodyTooLargeError) {
18
+ throw new ClientError(error.message, 'annotation-body-too-large', {
19
+ status: 413,
20
+ details: {
21
+ max_body_bytes: error.maxBytes
22
+ }
23
+ });
24
+ }
25
+ if (error instanceof AnnotationCountLimitExceededError) {
26
+ throw new ClientError(error.message, 'annotation-count-limit-exceeded', {
27
+ status: 413,
28
+ details: {
29
+ max_annotations: error.maxAnnotations
30
+ }
31
+ });
32
+ }
33
+ if (error instanceof AnnotationTotalBytesLimitExceededError) {
34
+ throw new ClientError(error.message, 'annotation-total-bytes-limit-exceeded', {
35
+ status: 413,
36
+ details: {
37
+ max_total_body_bytes: error.maxBytes
38
+ }
39
+ });
40
+ }
41
+ throw error;
42
+ },
43
+ handler: async (request)=>{
44
+ const leasedJob = requireLeasedJobContext(request);
45
+ const { step_id: stepId, attempt, annotations } = request.body;
46
+ if (leasedJob.currentStepId !== stepId || leasedJob.currentStepAttempt !== attempt) {
47
+ throw new ClientError('Step not found for leased job execution', 'step-not-found', {
48
+ status: 404
49
+ });
50
+ }
51
+ const result = await writeAnnotations({
52
+ workspaceId: leasedJob.workspaceId,
53
+ projectId: leasedJob.projectId,
54
+ workflowRunId: leasedJob.workflowRunId,
55
+ workflowRunAttempt: leasedJob.workflowRunAttempt ?? 1,
56
+ workflowRunAttemptId: leasedJob.workflowRunAttemptId,
57
+ jobId: leasedJob.jobId,
58
+ jobExecutionId: leasedJob.jobExecutionId,
59
+ originStepId: stepId,
60
+ originStepAttempt: attempt,
61
+ operations: annotations
62
+ });
63
+ return {
64
+ annotations: result.annotations,
65
+ accounting: {
66
+ annotation_count: result.accounting.annotationCount,
67
+ total_body_bytes: result.accounting.totalBodyBytes
68
+ }
69
+ };
70
+ }
71
+ });
72
+
73
+ //# sourceMappingURL=write-annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/write-annotations.ts"],"sourcesContent":["import {\n leasedWriteAnnotationsBodySchema,\n leasedWriteAnnotationsResponseSchema,\n} from '@shipfox/annotations-dto';\nimport {requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {\n AnnotationBodyTooLargeError,\n AnnotationCountLimitExceededError,\n AnnotationTotalBytesLimitExceededError,\n} from '#core/errors.js';\nimport {writeAnnotations} from '#core/write-annotations.js';\n\nexport const writeAnnotationsRoute = defineRoute({\n method: 'POST',\n path: '/annotations',\n description: 'Creates, updates, or removes annotations for the current leased job execution.',\n schema: {\n body: leasedWriteAnnotationsBodySchema,\n response: {\n 200: leasedWriteAnnotationsResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof AnnotationBodyTooLargeError) {\n throw new ClientError(error.message, 'annotation-body-too-large', {\n status: 413,\n details: {max_body_bytes: error.maxBytes},\n });\n }\n if (error instanceof AnnotationCountLimitExceededError) {\n throw new ClientError(error.message, 'annotation-count-limit-exceeded', {\n status: 413,\n details: {max_annotations: error.maxAnnotations},\n });\n }\n if (error instanceof AnnotationTotalBytesLimitExceededError) {\n throw new ClientError(error.message, 'annotation-total-bytes-limit-exceeded', {\n status: 413,\n details: {max_total_body_bytes: error.maxBytes},\n });\n }\n throw error;\n },\n handler: async (request) => {\n const leasedJob = requireLeasedJobContext(request);\n const {step_id: stepId, attempt, annotations} = request.body;\n\n if (leasedJob.currentStepId !== stepId || leasedJob.currentStepAttempt !== attempt) {\n throw new ClientError('Step not found for leased job execution', 'step-not-found', {\n status: 404,\n });\n }\n\n const result = await writeAnnotations({\n workspaceId: leasedJob.workspaceId,\n projectId: leasedJob.projectId,\n workflowRunId: leasedJob.workflowRunId,\n workflowRunAttempt: leasedJob.workflowRunAttempt ?? 1,\n workflowRunAttemptId: leasedJob.workflowRunAttemptId,\n jobId: leasedJob.jobId,\n jobExecutionId: leasedJob.jobExecutionId,\n originStepId: stepId,\n originStepAttempt: attempt,\n operations: annotations,\n });\n\n return {\n annotations: result.annotations,\n accounting: {\n annotation_count: result.accounting.annotationCount,\n total_body_bytes: result.accounting.totalBodyBytes,\n },\n };\n },\n});\n"],"names":["leasedWriteAnnotationsBodySchema","leasedWriteAnnotationsResponseSchema","requireLeasedJobContext","ClientError","defineRoute","AnnotationBodyTooLargeError","AnnotationCountLimitExceededError","AnnotationTotalBytesLimitExceededError","writeAnnotations","writeAnnotationsRoute","method","path","description","schema","body","response","errorHandler","error","message","status","details","max_body_bytes","maxBytes","max_annotations","maxAnnotations","max_total_body_bytes","handler","request","leasedJob","step_id","stepId","attempt","annotations","currentStepId","currentStepAttempt","result","workspaceId","projectId","workflowRunId","workflowRunAttempt","workflowRunAttemptId","jobId","jobExecutionId","originStepId","originStepAttempt","operations","accounting","annotation_count","annotationCount","total_body_bytes","totalBodyBytes"],"mappings":"AAAA,SACEA,gCAAgC,EAChCC,oCAAoC,QAC/B,2BAA2B;AAClC,SAAQC,uBAAuB,QAAO,4BAA4B;AAClE,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SACEC,2BAA2B,EAC3BC,iCAAiC,EACjCC,sCAAsC,QACjC,kBAAkB;AACzB,SAAQC,gBAAgB,QAAO,6BAA6B;AAE5D,OAAO,MAAMC,wBAAwBL,YAAY;IAC/CM,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMd;QACNe,UAAU;YACR,KAAKd;QACP;IACF;IACAe,cAAc,CAACC;QACb,IAAIA,iBAAiBZ,6BAA6B;YAChD,MAAM,IAAIF,YAAYc,MAAMC,OAAO,EAAE,6BAA6B;gBAChEC,QAAQ;gBACRC,SAAS;oBAACC,gBAAgBJ,MAAMK,QAAQ;gBAAA;YAC1C;QACF;QACA,IAAIL,iBAAiBX,mCAAmC;YACtD,MAAM,IAAIH,YAAYc,MAAMC,OAAO,EAAE,mCAAmC;gBACtEC,QAAQ;gBACRC,SAAS;oBAACG,iBAAiBN,MAAMO,cAAc;gBAAA;YACjD;QACF;QACA,IAAIP,iBAAiBV,wCAAwC;YAC3D,MAAM,IAAIJ,YAAYc,MAAMC,OAAO,EAAE,yCAAyC;gBAC5EC,QAAQ;gBACRC,SAAS;oBAACK,sBAAsBR,MAAMK,QAAQ;gBAAA;YAChD;QACF;QACA,MAAML;IACR;IACAS,SAAS,OAAOC;QACd,MAAMC,YAAY1B,wBAAwByB;QAC1C,MAAM,EAACE,SAASC,MAAM,EAAEC,OAAO,EAAEC,WAAW,EAAC,GAAGL,QAAQb,IAAI;QAE5D,IAAIc,UAAUK,aAAa,KAAKH,UAAUF,UAAUM,kBAAkB,KAAKH,SAAS;YAClF,MAAM,IAAI5B,YAAY,2CAA2C,kBAAkB;gBACjFgB,QAAQ;YACV;QACF;QAEA,MAAMgB,SAAS,MAAM3B,iBAAiB;YACpC4B,aAAaR,UAAUQ,WAAW;YAClCC,WAAWT,UAAUS,SAAS;YAC9BC,eAAeV,UAAUU,aAAa;YACtCC,oBAAoBX,UAAUW,kBAAkB,IAAI;YACpDC,sBAAsBZ,UAAUY,oBAAoB;YACpDC,OAAOb,UAAUa,KAAK;YACtBC,gBAAgBd,UAAUc,cAAc;YACxCC,cAAcb;YACdc,mBAAmBb;YACnBc,YAAYb;QACd;QAEA,OAAO;YACLA,aAAaG,OAAOH,WAAW;YAC/Bc,YAAY;gBACVC,kBAAkBZ,OAAOW,UAAU,CAACE,eAAe;gBACnDC,kBAAkBd,OAAOW,UAAU,CAACI,cAAc;YACpD;QACF;IACF;AACF,GAAG"}