@naisys/erp-shared 3.0.0-beta.10

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.
@@ -0,0 +1,41 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionSchema, HateoasLinkSchema } from "./hateoas-types.js";
3
+ export const AdminInfoResponseSchema = z.object({
4
+ erpDbPath: z.string(),
5
+ erpDbSize: z.number().optional(),
6
+ _actions: z.array(HateoasActionSchema).optional(),
7
+ });
8
+ export const AdminAttachmentItemSchema = z.object({
9
+ id: z.string(),
10
+ filename: z.string(),
11
+ fileSize: z.number(),
12
+ fileHash: z.string(),
13
+ uploadedBy: z.string(),
14
+ createdAt: z.string(),
15
+ });
16
+ export const AdminAttachmentListRequestSchema = z.object({
17
+ page: z.coerce.number().optional().default(1),
18
+ pageSize: z.coerce.number().optional().default(50),
19
+ });
20
+ export const AdminAttachmentListResponseSchema = z.object({
21
+ attachments: z.array(AdminAttachmentItemSchema),
22
+ total: z.number(),
23
+ page: z.number(),
24
+ pageSize: z.number(),
25
+ _links: z.array(HateoasLinkSchema),
26
+ });
27
+ export const PinoLogEntrySchema = z.object({
28
+ level: z.number(),
29
+ time: z.number(),
30
+ msg: z.string(),
31
+ detail: z.string().optional(),
32
+ });
33
+ export const ServerLogRequestSchema = z.object({
34
+ lines: z.coerce.number().optional().default(200),
35
+ minLevel: z.coerce.number().optional(),
36
+ });
37
+ export const ServerLogResponseSchema = z.object({
38
+ entries: z.array(PinoLogEntrySchema),
39
+ fileName: z.string(),
40
+ fileSize: z.number().optional(),
41
+ });
@@ -0,0 +1,4 @@
1
+ import { z } from "zod/v4";
2
+ export const HelloResponseSchema = z.object({
3
+ message: z.string(),
4
+ });
@@ -0,0 +1,19 @@
1
+ import { z } from "zod/v4";
2
+ export const AuditEntrySchema = z.object({
3
+ id: z.number(),
4
+ entityType: z.string(),
5
+ entityId: z.number(),
6
+ action: z.string(),
7
+ field: z.string(),
8
+ oldValue: z.string().nullable(),
9
+ newValue: z.string().nullable(),
10
+ userId: z.number(),
11
+ createdAt: z.iso.datetime(),
12
+ });
13
+ export const AuditListResponseSchema = z.object({
14
+ items: z.array(AuditEntrySchema),
15
+ });
16
+ export const AuditQuerySchema = z.object({
17
+ entityType: z.string(),
18
+ entityId: z.coerce.number().int(),
19
+ });
@@ -0,0 +1,15 @@
1
+ import { z } from "zod/v4";
2
+ export const LoginRequestSchema = z
3
+ .object({
4
+ username: z.string().min(1),
5
+ password: z.string().min(1),
6
+ })
7
+ .strict();
8
+ export const AuthUserSchema = z.object({
9
+ id: z.number(),
10
+ username: z.string(),
11
+ permissions: z.array(z.string()).optional(),
12
+ });
13
+ export const LoginResponseSchema = z.object({
14
+ user: AuthUserSchema,
15
+ });
@@ -0,0 +1,6 @@
1
+ import { z } from "zod/v4";
2
+ export const ErrorResponseSchema = z.object({
3
+ statusCode: z.number().int(),
4
+ error: z.string(),
5
+ message: z.string(),
6
+ });
@@ -0,0 +1,55 @@
1
+ import { z } from "zod/v4";
2
+ import { FieldTypeEnum } from "./field-types.js";
3
+ import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
4
+ // Field definition summary within a field ref
5
+ export const FieldRefFieldSchema = z.object({
6
+ seqNo: z.number(),
7
+ label: z.string(),
8
+ type: FieldTypeEnum,
9
+ });
10
+ // Full field ref response shape (plan level)
11
+ export const FieldRefSchema = z.object({
12
+ id: z.number(),
13
+ seqNo: z.number(),
14
+ title: z.string(),
15
+ sourceOpSeqNo: z.number(),
16
+ sourceOpTitle: z.string(),
17
+ sourceStepSeqNo: z.number(),
18
+ sourceStepTitle: z.string(),
19
+ fields: z.array(FieldRefFieldSchema),
20
+ createdAt: z.iso.datetime(),
21
+ createdBy: z.string(),
22
+ _links: z.array(HateoasLinkSchema).optional(),
23
+ _actions: z.array(HateoasActionSchema).optional(),
24
+ });
25
+ // Input for creating a field ref
26
+ export const CreateFieldRefSchema = z
27
+ .object({
28
+ seqNo: z.number().int().min(1).optional(),
29
+ title: z.string().min(1).max(200),
30
+ sourceOpSeqNo: z.number().int().min(1),
31
+ sourceStepSeqNo: z.number().int().min(1),
32
+ })
33
+ .strict();
34
+ // List response
35
+ export const FieldRefListResponseSchema = z.object({
36
+ items: z.array(FieldRefSchema),
37
+ total: z.number(),
38
+ nextSeqNo: z.number(),
39
+ _links: z.array(HateoasLinkSchema),
40
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
41
+ _actions: z.array(HateoasActionSchema).optional(),
42
+ });
43
+ // Field ref value summary embedded in OperationRun GET response
44
+ // Uses FieldValueEntry from step-run-types for compatibility with FieldValueRunList
45
+ import { FieldValueEntrySchema } from "./step-run-types.js";
46
+ export const FieldRefValueSummarySchema = z.object({
47
+ seqNo: z.number(),
48
+ title: z.string(),
49
+ sourceOpSeqNo: z.number(),
50
+ sourceOpTitle: z.string(),
51
+ sourceStepSeqNo: z.number(),
52
+ sourceStepTitle: z.string(),
53
+ multiSet: z.boolean(),
54
+ fieldValues: z.array(FieldValueEntrySchema),
55
+ });
@@ -0,0 +1,61 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ export const FieldTypeEnum = z.enum([
4
+ "string",
5
+ "number",
6
+ "date",
7
+ "datetime",
8
+ "yesNo",
9
+ "checkbox",
10
+ "attachment",
11
+ ]);
12
+ export const FieldType = FieldTypeEnum.enum;
13
+ // Full field response shape
14
+ export const FieldSchema = z.object({
15
+ id: z.number(),
16
+ fieldSetId: z.number(),
17
+ seqNo: z.number(),
18
+ label: z.string(),
19
+ type: FieldTypeEnum,
20
+ isArray: z.boolean(),
21
+ required: z.boolean(),
22
+ createdAt: z.iso.datetime(),
23
+ createdBy: z.string(),
24
+ updatedAt: z.iso.datetime(),
25
+ updatedBy: z.string(),
26
+ _links: z.array(HateoasLinkSchema).optional(),
27
+ _actions: z.array(HateoasActionSchema).optional(),
28
+ });
29
+ // Input for creating a field
30
+ export const CreateFieldSchema = z
31
+ .object({
32
+ seqNo: z.number().int().min(1).optional(),
33
+ label: z.string().min(1).max(200),
34
+ type: FieldTypeEnum.optional(),
35
+ isArray: z.boolean().optional(),
36
+ required: z.boolean().optional(),
37
+ })
38
+ .strict();
39
+ // Input for batch creating fields
40
+ export const BatchCreateFieldSchema = z.object({
41
+ items: z.array(CreateFieldSchema).min(1).max(100),
42
+ });
43
+ // Input for updating a field
44
+ export const UpdateFieldSchema = z
45
+ .object({
46
+ seqNo: z.number().int().min(1).optional(),
47
+ label: z.string().min(1).max(200).optional(),
48
+ type: FieldTypeEnum.optional(),
49
+ isArray: z.boolean().optional(),
50
+ required: z.boolean().optional(),
51
+ })
52
+ .strict();
53
+ // List response
54
+ export const FieldListResponseSchema = z.object({
55
+ items: z.array(FieldSchema),
56
+ total: z.number(),
57
+ nextSeqNo: z.number(),
58
+ _links: z.array(HateoasLinkSchema),
59
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
60
+ _actions: z.array(HateoasActionSchema).optional(),
61
+ });
@@ -0,0 +1 @@
1
+ export { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinksSchema, HateoasLinkTemplateSchema, } from "@naisys/common";
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ export * from "./admin-types.js";
2
+ export * from "./api-types.js";
3
+ export * from "./audit-types.js";
4
+ export * from "./auth-types.js";
5
+ export * from "./error-types.js";
6
+ export * from "./field-ref-types.js";
7
+ export * from "./field-types.js";
8
+ export * from "./hateoas-types.js";
9
+ export * from "./inventory-types.js";
10
+ export * from "./item-instance-types.js";
11
+ export * from "./item-types.js";
12
+ export * from "./labor-ticket-types.js";
13
+ export * from "./mutation-types.js";
14
+ export * from "./operation-dependency-types.js";
15
+ export * from "./operation-run-comment-types.js";
16
+ export * from "./operation-run-types.js";
17
+ export * from "./operation-types.js";
18
+ export * from "./order-revision-types.js";
19
+ export * from "./order-run-types.js";
20
+ export * from "./order-types.js";
21
+ export * from "./revision-diff-types.js";
22
+ export * from "./step-run-types.js";
23
+ export * from "./step-types.js";
24
+ export * from "./user-types.js";
25
+ export * from "./work-center-types.js";
@@ -0,0 +1,26 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionTemplateSchema, HateoasLinkSchema, } from "./hateoas-types.js";
3
+ // Query params for inventory list (all item instances across all items)
4
+ export const InventoryListQuerySchema = z.object({
5
+ page: z.coerce.number().int().min(1).optional().default(1),
6
+ pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
7
+ search: z.string().optional(),
8
+ });
9
+ // Flattened inventory item for the list
10
+ export const InventoryItemSchema = z.object({
11
+ id: z.number(),
12
+ itemKey: z.string(),
13
+ key: z.string(),
14
+ quantity: z.number().nullable(),
15
+ orderKey: z.string().nullable(),
16
+ orderRunNo: z.number().nullable(),
17
+ createdAt: z.iso.datetime(),
18
+ });
19
+ export const InventoryListResponseSchema = z.object({
20
+ items: z.array(InventoryItemSchema),
21
+ total: z.number(),
22
+ page: z.number(),
23
+ pageSize: z.number(),
24
+ _links: z.array(HateoasLinkSchema),
25
+ _actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
26
+ });
@@ -0,0 +1,52 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ import { FieldValueEntrySchema } from "./step-run-types.js";
4
+ // Full item instance response shape
5
+ export const ItemInstanceSchema = z.object({
6
+ id: z.number(),
7
+ itemKey: z.string(),
8
+ orderKey: z.string().nullable(),
9
+ orderRunNo: z.number().nullable(),
10
+ key: z.string(),
11
+ quantity: z.number().nullable(),
12
+ fieldValues: z.array(FieldValueEntrySchema),
13
+ createdBy: z.string(),
14
+ createdAt: z.iso.datetime(),
15
+ updatedBy: z.string(),
16
+ updatedAt: z.iso.datetime(),
17
+ _links: z.array(HateoasLinkSchema).optional(),
18
+ _actions: z.array(HateoasActionSchema).optional(),
19
+ _actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
20
+ });
21
+ // Input for creating an item instance
22
+ export const CreateItemInstanceSchema = z
23
+ .object({
24
+ key: z.string().min(1).max(200),
25
+ quantity: z.number().nullable().optional(),
26
+ orderRunId: z.number().nullable().optional(),
27
+ })
28
+ .strict();
29
+ // Input for updating an item instance
30
+ export const UpdateItemInstanceSchema = z
31
+ .object({
32
+ key: z.string().min(1).max(200).optional(),
33
+ quantity: z.number().nullable().optional(),
34
+ orderRunId: z.number().nullable().optional(),
35
+ })
36
+ .strict();
37
+ // Query params for listing item instances
38
+ export const ItemInstanceListQuerySchema = z.object({
39
+ page: z.coerce.number().int().min(1).optional().default(1),
40
+ pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
41
+ search: z.string().optional(),
42
+ });
43
+ // List response
44
+ export const ItemInstanceListResponseSchema = z.object({
45
+ items: z.array(ItemInstanceSchema),
46
+ total: z.number(),
47
+ page: z.number(),
48
+ pageSize: z.number(),
49
+ _links: z.array(HateoasLinkSchema),
50
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
51
+ _actions: z.array(HateoasActionSchema).optional(),
52
+ });
@@ -0,0 +1,55 @@
1
+ import { z } from "zod/v4";
2
+ import { FieldListResponseSchema } from "./field-types.js";
3
+ import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
4
+ // Full item response shape
5
+ export const ItemSchema = z.object({
6
+ id: z.number(),
7
+ key: z.string(),
8
+ description: z.string(),
9
+ fields: FieldListResponseSchema,
10
+ createdBy: z.string(),
11
+ createdAt: z.iso.datetime(),
12
+ updatedBy: z.string(),
13
+ updatedAt: z.iso.datetime(),
14
+ _links: z.array(HateoasLinkSchema).optional(),
15
+ _actions: z.array(HateoasActionSchema).optional(),
16
+ });
17
+ // Input for creating an item
18
+ export const CreateItemSchema = z
19
+ .object({
20
+ key: z
21
+ .string()
22
+ .min(1)
23
+ .max(100)
24
+ .regex(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/, "Key must be alphanumeric with hyphens"),
25
+ description: z.string().max(2000).optional().default(""),
26
+ })
27
+ .strict();
28
+ // Input for updating an item
29
+ export const UpdateItemSchema = z
30
+ .object({
31
+ key: z
32
+ .string()
33
+ .min(1)
34
+ .max(100)
35
+ .regex(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/, "Key must be alphanumeric with hyphens")
36
+ .optional(),
37
+ description: z.string().max(2000).optional(),
38
+ })
39
+ .strict();
40
+ // Query params for listing items
41
+ export const ItemListQuerySchema = z.object({
42
+ page: z.coerce.number().int().min(1).optional().default(1),
43
+ pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
44
+ search: z.string().optional(),
45
+ });
46
+ // List response
47
+ export const ItemListResponseSchema = z.object({
48
+ items: z.array(ItemSchema),
49
+ total: z.number(),
50
+ page: z.number(),
51
+ pageSize: z.number(),
52
+ _links: z.array(HateoasLinkSchema),
53
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
54
+ _actions: z.array(HateoasActionSchema).optional(),
55
+ });
@@ -0,0 +1,31 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ export const LaborTicketSchema = z.object({
4
+ id: z.number(),
5
+ operationRunId: z.number(),
6
+ userId: z.number(),
7
+ username: z.string(),
8
+ runId: z.number().nullable(),
9
+ clockIn: z.iso.datetime(),
10
+ clockOut: z.iso.datetime().nullable(),
11
+ cost: z.number().nullable(),
12
+ createdAt: z.iso.datetime(),
13
+ createdBy: z.string(),
14
+ updatedAt: z.iso.datetime(),
15
+ updatedBy: z.string(),
16
+ _links: z.array(HateoasLinkSchema).optional(),
17
+ });
18
+ export const ClockOutLaborTicketSchema = z
19
+ .object({
20
+ userId: z.number().int().optional(),
21
+ ticketId: z.number().int().optional(),
22
+ })
23
+ .strict();
24
+ export const LaborTicketListResponseSchema = z.object({
25
+ items: z.array(LaborTicketSchema),
26
+ total: z.number(),
27
+ _links: z.array(HateoasLinkSchema),
28
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
29
+ _actions: z.array(HateoasActionSchema).optional(),
30
+ _actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
31
+ });
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Slim response schemas for POST/PUT/DELETE mutations.
3
+ *
4
+ * By default, mutations return a slim response (identifiers + _actions).
5
+ * Callers can send `Prefer: return=representation` to get the full entity
6
+ * response instead (useful for UI clients that patch state in place).
7
+ */
8
+ import { z } from "zod/v4";
9
+ import { HateoasActionSchema, HateoasLinkSchema } from "./hateoas-types.js";
10
+ import { OperationRunStatusEnum } from "./operation-run-types.js";
11
+ import { RevisionStatusEnum } from "./order-revision-types.js";
12
+ import { OrderRunStatusEnum } from "./order-run-types.js";
13
+ import { FieldValidationSchema, FieldValueSchema } from "./step-run-types.js";
14
+ // ── Base mutation responses ─────────────────────────────────────────
15
+ /** PUT / generic mutation — just updated actions */
16
+ export const MutateResponseSchema = z.object({
17
+ _actions: z.array(HateoasActionSchema).optional(),
18
+ });
19
+ /** POST create — server-generated id + self link + actions */
20
+ export const CreateResponseSchema = MutateResponseSchema.extend({
21
+ id: z.number(),
22
+ _links: z.array(HateoasLinkSchema).optional(),
23
+ });
24
+ // ── Entity create variants ──────────────────────────────────────────
25
+ /** Orders, items, work centers, item instances (key-based) */
26
+ export const KeyCreateResponseSchema = CreateResponseSchema.extend({
27
+ key: z.string(),
28
+ });
29
+ /** Operations, steps, fields, field refs (seqNo-based) */
30
+ export const SeqNoCreateResponseSchema = CreateResponseSchema.extend({
31
+ seqNo: z.number(),
32
+ });
33
+ /** Batch create (steps, fields) */
34
+ export const BatchSeqNoCreateResponseSchema = z.object({
35
+ items: z.array(z.object({ id: z.number(), seqNo: z.number() })),
36
+ total: z.number(),
37
+ _actions: z.array(HateoasActionSchema).optional(),
38
+ });
39
+ /** Order revision create */
40
+ export const RevisionCreateResponseSchema = CreateResponseSchema.extend({
41
+ revNo: z.number(),
42
+ });
43
+ /** Order run create */
44
+ export const RunCreateResponseSchema = CreateResponseSchema.extend({
45
+ runNo: z.number(),
46
+ });
47
+ /** User create (ERP) */
48
+ export const UserCreateResponseSchema = z.object({
49
+ id: z.number(),
50
+ username: z.string(),
51
+ apiKey: z.string().nullable().optional(),
52
+ _links: z.array(HateoasLinkSchema).optional(),
53
+ _actions: z.array(HateoasActionSchema).optional(),
54
+ });
55
+ // ── Transition responses ────────────────────────────────────────────
56
+ /** Order run transition (start / close / complete / cancel / reopen) */
57
+ export const OrderRunTransitionSchema = z.object({
58
+ status: OrderRunStatusEnum,
59
+ _actions: z.array(HateoasActionSchema).optional(),
60
+ });
61
+ /** Operation run transition (start / complete / skip / fail / reopen) */
62
+ export const OperationRunTransitionSlimSchema = z.object({
63
+ status: OperationRunStatusEnum,
64
+ _actions: z.array(HateoasActionSchema).optional(),
65
+ });
66
+ /** Step run transition (complete / reopen) */
67
+ export const StepRunTransitionSlimSchema = z.object({
68
+ completed: z.boolean(),
69
+ _actions: z.array(HateoasActionSchema).optional(),
70
+ });
71
+ /** Order revision transition (approve / obsolete) */
72
+ export const OrderRevisionTransitionSchema = z.object({
73
+ status: RevisionStatusEnum,
74
+ _actions: z.array(HateoasActionSchema).optional(),
75
+ });
76
+ // ── Field value mutation responses ──────────────────────────────────
77
+ /** Single field value PUT — echo value + validation + actions */
78
+ export const FieldValueMutateResponseSchema = z.object({
79
+ value: FieldValueSchema,
80
+ validation: FieldValidationSchema,
81
+ _actions: z.array(HateoasActionSchema).optional(),
82
+ });
83
+ /** Batch field value PUT */
84
+ export const BatchFieldValueMutateResponseSchema = z.object({
85
+ items: z.array(z.object({
86
+ fieldSeqNo: z.number(),
87
+ value: FieldValueSchema,
88
+ validation: FieldValidationSchema,
89
+ })),
90
+ total: z.number(),
91
+ _actions: z.array(HateoasActionSchema).optional(),
92
+ });
93
+ /** Delete field value set */
94
+ export const DeleteSetMutateResponseSchema = z.object({
95
+ setCount: z.number(),
96
+ _actions: z.array(HateoasActionSchema).optional(),
97
+ });
@@ -0,0 +1,24 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, } from "./hateoas-types.js";
3
+ // Full dependency response shape
4
+ export const OperationDependencySchema = z.object({
5
+ id: z.number(),
6
+ predecessorSeqNo: z.number(),
7
+ predecessorTitle: z.string(),
8
+ createdAt: z.iso.datetime(),
9
+ createdBy: z.string(),
10
+ });
11
+ // Input for creating a dependency
12
+ export const CreateOperationDependencySchema = z
13
+ .object({
14
+ predecessorSeqNo: z.number().int().min(1),
15
+ })
16
+ .strict();
17
+ // List response
18
+ export const OperationDependencyListResponseSchema = z.object({
19
+ items: z.array(OperationDependencySchema),
20
+ total: z.number(),
21
+ _links: z.array(HateoasLinkSchema),
22
+ _actions: z.array(HateoasActionSchema).optional(),
23
+ _actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
24
+ });
@@ -0,0 +1,30 @@
1
+ import { z } from "zod/v4";
2
+ import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ export const OperationRunCommentTypeEnum = z.enum([
4
+ "note",
5
+ "issue",
6
+ "feedback",
7
+ ]);
8
+ export const OperationRunCommentType = OperationRunCommentTypeEnum.enum;
9
+ export const OperationRunCommentSchema = z.object({
10
+ id: z.number(),
11
+ operationRunId: z.number(),
12
+ type: OperationRunCommentTypeEnum,
13
+ body: z.string(),
14
+ createdAt: z.iso.datetime(),
15
+ createdBy: z.string(),
16
+ _links: z.array(HateoasLinkSchema).optional(),
17
+ });
18
+ export const CreateOperationRunCommentSchema = z
19
+ .object({
20
+ type: OperationRunCommentTypeEnum.optional(),
21
+ body: z.string().min(1).max(5000),
22
+ })
23
+ .strict();
24
+ export const OperationRunCommentListResponseSchema = z.object({
25
+ items: z.array(OperationRunCommentSchema),
26
+ total: z.number(),
27
+ _links: z.array(HateoasLinkSchema),
28
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
29
+ _actions: z.array(HateoasActionSchema).optional(),
30
+ });
@@ -0,0 +1,82 @@
1
+ import { z } from "zod/v4";
2
+ import { FieldRefValueSummarySchema } from "./field-ref-types.js";
3
+ import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
4
+ import { OperationPredecessorSchema } from "./operation-types.js";
5
+ // Step summary embedded in operation run GET responses
6
+ export const StepRunSummarySchema = z.object({
7
+ seqNo: z.number(),
8
+ title: z.string(),
9
+ completed: z.boolean(),
10
+ });
11
+ export const OperationRunStatusEnum = z.enum([
12
+ "blocked",
13
+ "pending",
14
+ "in_progress",
15
+ "completed",
16
+ "skipped",
17
+ "failed",
18
+ ]);
19
+ export const OperationRunStatus = OperationRunStatusEnum.enum;
20
+ // Full operation run response shape
21
+ export const OperationRunSchema = z.object({
22
+ id: z.number(),
23
+ orderRunId: z.number(),
24
+ operationId: z.number(),
25
+ seqNo: z.number(),
26
+ title: z.string(),
27
+ description: z.string(),
28
+ workCenterKey: z.string().nullable(),
29
+ stepCount: z.number().optional(),
30
+ predecessors: z.array(OperationPredecessorSchema).optional(),
31
+ status: OperationRunStatusEnum,
32
+ assignedTo: z.string().nullable(),
33
+ cost: z.number().nullable(),
34
+ note: z.string().nullable(),
35
+ completedAt: z.iso.datetime().nullable(),
36
+ stepSummary: z.array(StepRunSummarySchema).optional(),
37
+ fieldRefSummary: z.array(FieldRefValueSummarySchema).optional(),
38
+ createdAt: z.iso.datetime(),
39
+ createdBy: z.string(),
40
+ updatedAt: z.iso.datetime(),
41
+ updatedBy: z.string(),
42
+ _links: z.array(HateoasLinkSchema).optional(),
43
+ _actions: z.array(HateoasActionSchema).optional(),
44
+ });
45
+ // Input for updating an operation run
46
+ export const UpdateOperationRunSchema = z
47
+ .object({
48
+ assignedToId: z.number().int().nullable().optional(),
49
+ })
50
+ .strict();
51
+ // Body for any status transition that accepts an optional note
52
+ // Accept null/undefined so callers don't need to send -d '{}' on POST
53
+ // endpoints where the body is entirely optional. A simpler
54
+ // .nullable().default({}) doesn't narrow the output type in zod v4,
55
+ // so we use a union + transform instead.
56
+ export const TransitionNoteSchema = z
57
+ .union([
58
+ z.object({ note: z.string().max(2000).optional() }).strict(),
59
+ z.null(),
60
+ z.undefined(),
61
+ ])
62
+ .transform((v) => v ?? {});
63
+ // Slim transition response (start/complete/skip/fail/reopen)
64
+ export const OperationRunTransitionSchema = z.object({
65
+ id: z.number(),
66
+ status: OperationRunStatusEnum,
67
+ assignedTo: z.string().nullable(),
68
+ cost: z.number().nullable(),
69
+ note: z.string().nullable(),
70
+ completedAt: z.iso.datetime().nullable(),
71
+ updatedAt: z.iso.datetime(),
72
+ updatedBy: z.string(),
73
+ _actions: z.array(HateoasActionSchema).optional(),
74
+ });
75
+ // List response
76
+ export const OperationRunListResponseSchema = z.object({
77
+ items: z.array(OperationRunSchema),
78
+ total: z.number(),
79
+ _links: z.array(HateoasLinkSchema),
80
+ _linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
81
+ _actions: z.array(HateoasActionSchema).optional(),
82
+ });