@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.
- package/dist/admin-types.js +41 -0
- package/dist/api-types.js +4 -0
- package/dist/audit-types.js +19 -0
- package/dist/auth-types.js +15 -0
- package/dist/error-types.js +6 -0
- package/dist/field-ref-types.js +55 -0
- package/dist/field-types.js +61 -0
- package/dist/hateoas-types.js +1 -0
- package/dist/index.js +25 -0
- package/dist/inventory-types.js +26 -0
- package/dist/item-instance-types.js +52 -0
- package/dist/item-types.js +55 -0
- package/dist/labor-ticket-types.js +31 -0
- package/dist/mutation-types.js +97 -0
- package/dist/operation-dependency-types.js +24 -0
- package/dist/operation-run-comment-types.js +30 -0
- package/dist/operation-run-types.js +82 -0
- package/dist/operation-types.js +58 -0
- package/dist/order-revision-types.js +61 -0
- package/dist/order-run-types.js +141 -0
- package/dist/order-types.js +61 -0
- package/dist/revision-diff-types.js +55 -0
- package/dist/step-run-types.js +148 -0
- package/dist/step-types.js +51 -0
- package/dist/user-types.js +79 -0
- package/dist/work-center-types.js +79 -0
- package/package.json +32 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
|
|
3
|
+
// Predecessor summary (included in list responses)
|
|
4
|
+
export const OperationPredecessorSchema = z.object({
|
|
5
|
+
seqNo: z.number(),
|
|
6
|
+
title: z.string(),
|
|
7
|
+
});
|
|
8
|
+
// Step summary (included in single operation GET responses)
|
|
9
|
+
export const StepSummarySchema = z.object({
|
|
10
|
+
seqNo: z.number(),
|
|
11
|
+
title: z.string(),
|
|
12
|
+
});
|
|
13
|
+
// Full operation response shape
|
|
14
|
+
export const OperationSchema = z.object({
|
|
15
|
+
id: z.number(),
|
|
16
|
+
orderRevId: z.number(),
|
|
17
|
+
seqNo: z.number(),
|
|
18
|
+
title: z.string(),
|
|
19
|
+
description: z.string(),
|
|
20
|
+
workCenterKey: z.string().nullable(),
|
|
21
|
+
stepCount: z.number().optional(),
|
|
22
|
+
stepSummary: z.array(StepSummarySchema).optional(),
|
|
23
|
+
predecessors: z.array(OperationPredecessorSchema).optional(),
|
|
24
|
+
createdAt: z.iso.datetime(),
|
|
25
|
+
createdBy: z.string(),
|
|
26
|
+
updatedAt: z.iso.datetime(),
|
|
27
|
+
updatedBy: z.string(),
|
|
28
|
+
_links: z.array(HateoasLinkSchema).optional(),
|
|
29
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
30
|
+
});
|
|
31
|
+
// Input for creating an operation
|
|
32
|
+
export const CreateOperationSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
seqNo: z.number().int().min(1).optional(),
|
|
35
|
+
title: z.string().min(1).max(200),
|
|
36
|
+
description: z.string().max(2000).optional(),
|
|
37
|
+
workCenterKey: z.string().max(100).nullable().optional(),
|
|
38
|
+
predecessorSeqNos: z.array(z.number().int().min(1)).optional(),
|
|
39
|
+
})
|
|
40
|
+
.strict();
|
|
41
|
+
// Input for updating an operation
|
|
42
|
+
export const UpdateOperationSchema = z
|
|
43
|
+
.object({
|
|
44
|
+
title: z.string().min(1).max(200).optional(),
|
|
45
|
+
description: z.string().max(2000).optional(),
|
|
46
|
+
workCenterKey: z.string().max(100).nullable().optional(),
|
|
47
|
+
seqNo: z.number().int().min(1).optional(),
|
|
48
|
+
})
|
|
49
|
+
.strict();
|
|
50
|
+
// List response
|
|
51
|
+
export const OperationListResponseSchema = z.object({
|
|
52
|
+
items: z.array(OperationSchema),
|
|
53
|
+
total: z.number(),
|
|
54
|
+
nextSeqNo: z.number(),
|
|
55
|
+
_links: z.array(HateoasLinkSchema),
|
|
56
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
57
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
58
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
|
|
3
|
+
// Operation summary embedded in revision GET responses
|
|
4
|
+
export const RevisionOperationSummarySchema = z.object({
|
|
5
|
+
seqNo: z.number(),
|
|
6
|
+
title: z.string(),
|
|
7
|
+
});
|
|
8
|
+
export const RevisionStatusEnum = z.enum(["draft", "approved", "obsolete"]);
|
|
9
|
+
export const RevisionStatus = RevisionStatusEnum.enum;
|
|
10
|
+
// Full revision response shape
|
|
11
|
+
export const OrderRevisionSchema = z.object({
|
|
12
|
+
id: z.number(),
|
|
13
|
+
orderId: z.number(),
|
|
14
|
+
revNo: z.number(),
|
|
15
|
+
status: RevisionStatusEnum,
|
|
16
|
+
description: z.string(),
|
|
17
|
+
changeSummary: z.string().nullable(),
|
|
18
|
+
itemKey: z.string().nullable(),
|
|
19
|
+
operationSummary: z.array(RevisionOperationSummarySchema).optional(),
|
|
20
|
+
createdAt: z.iso.datetime(),
|
|
21
|
+
createdBy: z.string(),
|
|
22
|
+
updatedAt: z.iso.datetime(),
|
|
23
|
+
updatedBy: z.string(),
|
|
24
|
+
_links: z.array(HateoasLinkSchema).optional(),
|
|
25
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
26
|
+
});
|
|
27
|
+
// Input for creating a revision
|
|
28
|
+
export const CreateOrderRevisionSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
description: z.string().max(2000).optional(),
|
|
31
|
+
changeSummary: z.string().max(2000).optional(),
|
|
32
|
+
})
|
|
33
|
+
.strict();
|
|
34
|
+
// Input for updating a revision
|
|
35
|
+
export const UpdateOrderRevisionSchema = z
|
|
36
|
+
.object({
|
|
37
|
+
description: z.string().max(2000).optional(),
|
|
38
|
+
changeSummary: z.string().max(2000).optional(),
|
|
39
|
+
})
|
|
40
|
+
.strict();
|
|
41
|
+
// Query params for listing revisions
|
|
42
|
+
export const OrderRevisionListQuerySchema = z.object({
|
|
43
|
+
page: z.coerce.number().int().min(1).optional().default(1),
|
|
44
|
+
pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
|
|
45
|
+
status: RevisionStatusEnum.optional(),
|
|
46
|
+
includeObsolete: z
|
|
47
|
+
.enum(["true", "false"])
|
|
48
|
+
.transform((v) => v === "true")
|
|
49
|
+
.optional()
|
|
50
|
+
.default(false),
|
|
51
|
+
});
|
|
52
|
+
// List response
|
|
53
|
+
export const OrderRevisionListResponseSchema = z.object({
|
|
54
|
+
items: z.array(OrderRevisionSchema),
|
|
55
|
+
total: z.number(),
|
|
56
|
+
page: z.number(),
|
|
57
|
+
pageSize: z.number(),
|
|
58
|
+
_links: z.array(HateoasLinkSchema),
|
|
59
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
60
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
61
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
|
|
3
|
+
import { OperationRunStatusEnum } from "./operation-run-types.js";
|
|
4
|
+
// Operation summary embedded in order run GET responses
|
|
5
|
+
export const OperationRunSummarySchema = z.object({
|
|
6
|
+
seqNo: z.number(),
|
|
7
|
+
title: z.string(),
|
|
8
|
+
status: OperationRunStatusEnum,
|
|
9
|
+
});
|
|
10
|
+
export const OrderRunStatusEnum = z.enum([
|
|
11
|
+
"released",
|
|
12
|
+
"started",
|
|
13
|
+
"closed",
|
|
14
|
+
"cancelled",
|
|
15
|
+
]);
|
|
16
|
+
export const OrderRunStatus = OrderRunStatusEnum.enum;
|
|
17
|
+
export const OrderRunPriorityEnum = z.enum([
|
|
18
|
+
"low",
|
|
19
|
+
"medium",
|
|
20
|
+
"high",
|
|
21
|
+
"critical",
|
|
22
|
+
]);
|
|
23
|
+
export const OrderRunPriority = OrderRunPriorityEnum.enum;
|
|
24
|
+
// Full order run response shape
|
|
25
|
+
export const OrderRunSchema = z.object({
|
|
26
|
+
id: z.number(),
|
|
27
|
+
runNo: z.number(),
|
|
28
|
+
orderId: z.number(),
|
|
29
|
+
orderKey: z.string(),
|
|
30
|
+
revNo: z.number(),
|
|
31
|
+
itemKey: z.string().nullable(),
|
|
32
|
+
instanceId: z.number().nullable(),
|
|
33
|
+
instanceKey: z.string().nullable(),
|
|
34
|
+
status: OrderRunStatusEnum,
|
|
35
|
+
priority: OrderRunPriorityEnum,
|
|
36
|
+
cost: z.number().nullable(),
|
|
37
|
+
dueAt: z.string().nullable(),
|
|
38
|
+
releaseNote: z.string().nullable(),
|
|
39
|
+
operationSummary: z.array(OperationRunSummarySchema).optional(),
|
|
40
|
+
createdAt: z.iso.datetime(),
|
|
41
|
+
createdBy: z.string(),
|
|
42
|
+
updatedAt: z.iso.datetime(),
|
|
43
|
+
updatedBy: z.string(),
|
|
44
|
+
_links: z.array(HateoasLinkSchema).optional(),
|
|
45
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
46
|
+
});
|
|
47
|
+
// Input for creating an order run
|
|
48
|
+
export const CreateOrderRunSchema = z
|
|
49
|
+
.object({
|
|
50
|
+
revNo: z.number().int().min(1).optional(),
|
|
51
|
+
priority: OrderRunPriorityEnum.optional().default("medium"),
|
|
52
|
+
dueAt: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Must be YYYY-MM-DD"),
|
|
53
|
+
releaseNote: z.string().max(2000).optional(),
|
|
54
|
+
})
|
|
55
|
+
.strict();
|
|
56
|
+
// Input for updating an order run
|
|
57
|
+
export const UpdateOrderRunSchema = z
|
|
58
|
+
.object({
|
|
59
|
+
priority: OrderRunPriorityEnum.optional(),
|
|
60
|
+
dueAt: z
|
|
61
|
+
.string()
|
|
62
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, "Must be YYYY-MM-DD")
|
|
63
|
+
.nullable()
|
|
64
|
+
.optional(),
|
|
65
|
+
releaseNote: z.string().max(2000).nullable().optional(),
|
|
66
|
+
})
|
|
67
|
+
.strict();
|
|
68
|
+
// Input for completing an order run (creates item instance + closes run)
|
|
69
|
+
export const CompleteOrderRunSchema = z
|
|
70
|
+
.object({
|
|
71
|
+
instanceKey: z.string().max(200).optional(),
|
|
72
|
+
quantity: z.number().nullable().optional(),
|
|
73
|
+
fieldValues: z
|
|
74
|
+
.array(z.object({
|
|
75
|
+
fieldId: z.number().int(),
|
|
76
|
+
value: z.string().max(2000),
|
|
77
|
+
setIndex: z.number().int().min(0).optional(),
|
|
78
|
+
}))
|
|
79
|
+
.optional(),
|
|
80
|
+
})
|
|
81
|
+
.strict();
|
|
82
|
+
// Query params for listing order runs
|
|
83
|
+
export const OrderRunListQuerySchema = z.object({
|
|
84
|
+
page: z.coerce.number().int().min(1).optional().default(1),
|
|
85
|
+
pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
|
|
86
|
+
status: OrderRunStatusEnum.optional(),
|
|
87
|
+
priority: OrderRunPriorityEnum.optional(),
|
|
88
|
+
search: z.string().optional(),
|
|
89
|
+
});
|
|
90
|
+
// List response
|
|
91
|
+
export const OrderRunListResponseSchema = z.object({
|
|
92
|
+
items: z.array(OrderRunSchema),
|
|
93
|
+
total: z.number(),
|
|
94
|
+
page: z.number(),
|
|
95
|
+
pageSize: z.number(),
|
|
96
|
+
_links: z.array(HateoasLinkSchema),
|
|
97
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
98
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
99
|
+
});
|
|
100
|
+
// Query params for dispatch view (operation runs across open orders)
|
|
101
|
+
export const DispatchListQuerySchema = z.object({
|
|
102
|
+
page: z.coerce.number().int().min(1).optional().default(1),
|
|
103
|
+
pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
|
|
104
|
+
status: OperationRunStatusEnum.optional(),
|
|
105
|
+
priority: OrderRunPriorityEnum.optional(),
|
|
106
|
+
search: z.string().optional(),
|
|
107
|
+
viewAs: z.string().optional(),
|
|
108
|
+
canWork: z
|
|
109
|
+
.union([z.literal("true"), z.literal("false")])
|
|
110
|
+
.transform((v) => v === "true")
|
|
111
|
+
.optional(),
|
|
112
|
+
clockedIn: z
|
|
113
|
+
.union([z.literal("true"), z.literal("false")])
|
|
114
|
+
.transform((v) => v === "true")
|
|
115
|
+
.optional(),
|
|
116
|
+
});
|
|
117
|
+
// Dispatch item = operation run with parent order/run context
|
|
118
|
+
export const DispatchItemSchema = z.object({
|
|
119
|
+
id: z.number(),
|
|
120
|
+
orderKey: z.string(),
|
|
121
|
+
revNo: z.number(),
|
|
122
|
+
runNo: z.number(),
|
|
123
|
+
seqNo: z.number(),
|
|
124
|
+
title: z.string(),
|
|
125
|
+
workCenterKey: z.string().nullable(),
|
|
126
|
+
canWork: z.boolean(),
|
|
127
|
+
status: OperationRunStatusEnum,
|
|
128
|
+
priority: OrderRunPriorityEnum,
|
|
129
|
+
assignedTo: z.string().nullable(),
|
|
130
|
+
dueAt: z.string().nullable(),
|
|
131
|
+
createdAt: z.iso.datetime(),
|
|
132
|
+
});
|
|
133
|
+
export const DispatchListResponseSchema = z.object({
|
|
134
|
+
items: z.array(DispatchItemSchema),
|
|
135
|
+
total: z.number(),
|
|
136
|
+
page: z.number(),
|
|
137
|
+
pageSize: z.number(),
|
|
138
|
+
_links: z.array(HateoasLinkSchema),
|
|
139
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
140
|
+
_actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
|
|
141
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
|
|
3
|
+
export const OrderStatusEnum = z.enum(["active", "archived"]);
|
|
4
|
+
export const OrderStatus = OrderStatusEnum.enum;
|
|
5
|
+
// Full order response shape
|
|
6
|
+
export const OrderSchema = z.object({
|
|
7
|
+
id: z.number(),
|
|
8
|
+
key: z.string(),
|
|
9
|
+
description: z.string(),
|
|
10
|
+
status: OrderStatusEnum,
|
|
11
|
+
itemKey: z.string().nullable(),
|
|
12
|
+
createdBy: z.string(),
|
|
13
|
+
createdAt: z.iso.datetime(),
|
|
14
|
+
updatedBy: z.string(),
|
|
15
|
+
updatedAt: z.iso.datetime(),
|
|
16
|
+
_links: z.array(HateoasLinkSchema).optional(),
|
|
17
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
18
|
+
});
|
|
19
|
+
// Input for creating an order
|
|
20
|
+
export const CreateOrderSchema = z
|
|
21
|
+
.object({
|
|
22
|
+
key: z
|
|
23
|
+
.string()
|
|
24
|
+
.min(1)
|
|
25
|
+
.max(100)
|
|
26
|
+
.regex(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/, "Key must be alphanumeric with hyphens"),
|
|
27
|
+
description: z.string().max(2000).optional().default(""),
|
|
28
|
+
itemKey: z.string().max(100).optional(),
|
|
29
|
+
})
|
|
30
|
+
.strict();
|
|
31
|
+
// Input for updating an order
|
|
32
|
+
export const UpdateOrderSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
key: z
|
|
35
|
+
.string()
|
|
36
|
+
.min(1)
|
|
37
|
+
.max(100)
|
|
38
|
+
.regex(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/, "Key must be alphanumeric with hyphens")
|
|
39
|
+
.optional(),
|
|
40
|
+
description: z.string().max(2000).optional(),
|
|
41
|
+
status: OrderStatusEnum.optional(),
|
|
42
|
+
itemKey: z.string().max(100).nullable().optional(),
|
|
43
|
+
})
|
|
44
|
+
.strict();
|
|
45
|
+
// Query params for listing orders
|
|
46
|
+
export const OrderListQuerySchema = z.object({
|
|
47
|
+
page: z.coerce.number().int().min(1).optional().default(1),
|
|
48
|
+
pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
|
|
49
|
+
status: z.enum(["active", "archived"]).optional(),
|
|
50
|
+
search: z.string().optional(),
|
|
51
|
+
});
|
|
52
|
+
// List response
|
|
53
|
+
export const OrderListResponseSchema = z.object({
|
|
54
|
+
items: z.array(OrderSchema),
|
|
55
|
+
total: z.number(),
|
|
56
|
+
page: z.number(),
|
|
57
|
+
pageSize: z.number(),
|
|
58
|
+
_links: z.array(HateoasLinkSchema),
|
|
59
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
60
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
61
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
// A single changed property
|
|
3
|
+
export const PropertyChangeSchema = z.object({
|
|
4
|
+
field: z.string(),
|
|
5
|
+
from: z.union([z.string(), z.number(), z.boolean(), z.null()]),
|
|
6
|
+
to: z.union([z.string(), z.number(), z.boolean(), z.null()]),
|
|
7
|
+
});
|
|
8
|
+
export const DiffStatusEnum = z.enum([
|
|
9
|
+
"added",
|
|
10
|
+
"removed",
|
|
11
|
+
"modified",
|
|
12
|
+
"unchanged",
|
|
13
|
+
]);
|
|
14
|
+
// Field-level diff
|
|
15
|
+
export const FieldDiffSchema = z.object({
|
|
16
|
+
seqNo: z.number(),
|
|
17
|
+
label: z.string(),
|
|
18
|
+
status: DiffStatusEnum,
|
|
19
|
+
changes: z.array(PropertyChangeSchema).optional(),
|
|
20
|
+
});
|
|
21
|
+
// Step-level diff
|
|
22
|
+
export const StepDiffSchema = z.object({
|
|
23
|
+
seqNo: z.number(),
|
|
24
|
+
title: z.string(),
|
|
25
|
+
status: DiffStatusEnum,
|
|
26
|
+
changes: z.array(PropertyChangeSchema).optional(),
|
|
27
|
+
fields: z.array(FieldDiffSchema).optional(),
|
|
28
|
+
});
|
|
29
|
+
// Dependency diff
|
|
30
|
+
export const DependencyDiffSchema = z.object({
|
|
31
|
+
predecessorSeqNo: z.number(),
|
|
32
|
+
predecessorTitle: z.string(),
|
|
33
|
+
status: z.enum(["added", "removed", "unchanged"]),
|
|
34
|
+
});
|
|
35
|
+
// Operation-level diff
|
|
36
|
+
export const OperationDiffSchema = z.object({
|
|
37
|
+
seqNo: z.number(),
|
|
38
|
+
title: z.string(),
|
|
39
|
+
status: DiffStatusEnum,
|
|
40
|
+
changes: z.array(PropertyChangeSchema).optional(),
|
|
41
|
+
steps: z.array(StepDiffSchema).optional(),
|
|
42
|
+
dependencies: z.array(DependencyDiffSchema).optional(),
|
|
43
|
+
});
|
|
44
|
+
// Top-level diff response
|
|
45
|
+
export const RevisionDiffResponseSchema = z.object({
|
|
46
|
+
fromRevNo: z.number(),
|
|
47
|
+
toRevNo: z.number(),
|
|
48
|
+
revisionChanges: z.array(PropertyChangeSchema),
|
|
49
|
+
operations: z.array(OperationDiffSchema),
|
|
50
|
+
});
|
|
51
|
+
// Query params
|
|
52
|
+
export const RevisionDiffQuerySchema = z.object({
|
|
53
|
+
from: z.coerce.number().int().min(1),
|
|
54
|
+
to: z.coerce.number().int().min(1),
|
|
55
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
|
|
3
|
+
// Validation result for a field value
|
|
4
|
+
export const FieldValidationSchema = z.object({
|
|
5
|
+
valid: z.boolean(),
|
|
6
|
+
error: z.string().optional(),
|
|
7
|
+
});
|
|
8
|
+
// Attachment metadata within a field value
|
|
9
|
+
export const FieldAttachmentSchema = z.object({
|
|
10
|
+
id: z.string(),
|
|
11
|
+
filename: z.string(),
|
|
12
|
+
fileSize: z.number(),
|
|
13
|
+
downloadHref: z.string().optional(),
|
|
14
|
+
});
|
|
15
|
+
// Field value: string for scalar fields, string[] for array fields (type ends with "[]")
|
|
16
|
+
// Coerce non-strings (e.g. numbers, booleans) to strings so callers don't
|
|
17
|
+
// get an opaque "Invalid input" error when they send 2024 instead of "2024".
|
|
18
|
+
const coercedString = z.coerce.string();
|
|
19
|
+
export const FieldValueSchema = z.union([
|
|
20
|
+
z.array(coercedString),
|
|
21
|
+
coercedString,
|
|
22
|
+
]);
|
|
23
|
+
/** Human/AI-readable hint for the expected value format per field type. */
|
|
24
|
+
export const VALUE_FORMAT_HINTS = {
|
|
25
|
+
string: "any text",
|
|
26
|
+
number: 'numeric string, e.g. "42" or "3.14"',
|
|
27
|
+
date: 'YYYY-MM-DD, e.g. "2024-06-15"',
|
|
28
|
+
datetime: 'YYYY-MM-DDTHH:mm, e.g. "2024-06-15T09:30"',
|
|
29
|
+
yesNo: '"Yes" or "No"',
|
|
30
|
+
checkbox: '"checked" or "" (empty string to uncheck)',
|
|
31
|
+
attachment: "managed by file upload endpoints, not set directly",
|
|
32
|
+
};
|
|
33
|
+
/** Return the API-facing type string, appending "[]" for array fields. */
|
|
34
|
+
export function fieldTypeString(type, isArray) {
|
|
35
|
+
return isArray ? `${type}[]` : type;
|
|
36
|
+
}
|
|
37
|
+
/** Look up the valueFormat hint for a given field type (handles "[]" suffix). */
|
|
38
|
+
export function getValueFormatHint(type) {
|
|
39
|
+
const isArray = type.endsWith("[]");
|
|
40
|
+
const baseType = isArray ? type.slice(0, -2) : type;
|
|
41
|
+
const hint = VALUE_FORMAT_HINTS[baseType] ?? "any text";
|
|
42
|
+
if (isArray) {
|
|
43
|
+
return `value must be a native JSON array (not a string), e.g. ["value1", "value2"]. Each element: ${hint}`;
|
|
44
|
+
}
|
|
45
|
+
return hint;
|
|
46
|
+
}
|
|
47
|
+
// A single field value entry (API response shape)
|
|
48
|
+
export const FieldValueEntrySchema = z.object({
|
|
49
|
+
fieldId: z.number(),
|
|
50
|
+
fieldSeqNo: z.number(),
|
|
51
|
+
label: z.string(),
|
|
52
|
+
type: z.string(),
|
|
53
|
+
valueFormat: z.string(),
|
|
54
|
+
required: z.boolean(),
|
|
55
|
+
setIndex: z.number(),
|
|
56
|
+
value: FieldValueSchema,
|
|
57
|
+
attachments: z.array(FieldAttachmentSchema).optional(),
|
|
58
|
+
validation: FieldValidationSchema,
|
|
59
|
+
});
|
|
60
|
+
// Upload attachment response
|
|
61
|
+
export const UploadAttachmentResponseSchema = z.object({
|
|
62
|
+
attachmentId: z.string(),
|
|
63
|
+
filename: z.string(),
|
|
64
|
+
fileSize: z.number(),
|
|
65
|
+
});
|
|
66
|
+
// Full step run response shape
|
|
67
|
+
export const StepRunSchema = z.object({
|
|
68
|
+
id: z.number(),
|
|
69
|
+
operationRunId: z.number(),
|
|
70
|
+
stepId: z.number(),
|
|
71
|
+
seqNo: z.number(),
|
|
72
|
+
title: z.string(),
|
|
73
|
+
instructions: z.string(),
|
|
74
|
+
multiSet: z.boolean(),
|
|
75
|
+
completed: z.boolean(),
|
|
76
|
+
note: z.string().nullable(),
|
|
77
|
+
fieldCount: z.number().optional(),
|
|
78
|
+
fieldValues: z.array(FieldValueEntrySchema).optional(),
|
|
79
|
+
createdAt: z.iso.datetime(),
|
|
80
|
+
createdBy: z.string(),
|
|
81
|
+
updatedAt: z.iso.datetime(),
|
|
82
|
+
updatedBy: z.string(),
|
|
83
|
+
_links: z.array(HateoasLinkSchema).optional(),
|
|
84
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
85
|
+
_actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
|
|
86
|
+
});
|
|
87
|
+
// Single field value update (setIndex is specified via URL path, not body)
|
|
88
|
+
const coercedStringMax = z.coerce.string().max(2000);
|
|
89
|
+
export const UpdateFieldValueSchema = z
|
|
90
|
+
.object({
|
|
91
|
+
value: z.union([z.array(coercedStringMax), coercedStringMax]),
|
|
92
|
+
})
|
|
93
|
+
.strict();
|
|
94
|
+
// Batch field value update (setIndex is specified via URL path, not body)
|
|
95
|
+
export const BatchUpdateFieldValuesSchema = z
|
|
96
|
+
.object({
|
|
97
|
+
fieldValues: z.array(z.object({
|
|
98
|
+
fieldSeqNo: z.number().int(),
|
|
99
|
+
value: z.union([z.array(coercedStringMax), coercedStringMax]),
|
|
100
|
+
})),
|
|
101
|
+
})
|
|
102
|
+
.strict();
|
|
103
|
+
// Batch field value response
|
|
104
|
+
export const BatchFieldValueResponseSchema = z.object({
|
|
105
|
+
items: z.array(FieldValueEntrySchema),
|
|
106
|
+
total: z.number(),
|
|
107
|
+
});
|
|
108
|
+
// Response for single field value update — field entry + step-level actions
|
|
109
|
+
export const FieldValueUpdateResponseSchema = FieldValueEntrySchema.extend({
|
|
110
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
111
|
+
_actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
|
|
112
|
+
});
|
|
113
|
+
// Response for batch field value update — field entries + step-level actions
|
|
114
|
+
export const BatchFieldValueUpdateResponseSchema = BatchFieldValueResponseSchema.extend({
|
|
115
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
116
|
+
_actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
|
|
117
|
+
});
|
|
118
|
+
// Response for deleting a field value set
|
|
119
|
+
export const DeleteSetResponseSchema = z.object({
|
|
120
|
+
setCount: z.number(),
|
|
121
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
122
|
+
_actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
|
|
123
|
+
});
|
|
124
|
+
// Slim transition response (complete/reopen)
|
|
125
|
+
export const StepRunTransitionSchema = z.object({
|
|
126
|
+
id: z.number(),
|
|
127
|
+
completed: z.boolean(),
|
|
128
|
+
note: z.string().nullable(),
|
|
129
|
+
updatedAt: z.iso.datetime(),
|
|
130
|
+
updatedBy: z.string(),
|
|
131
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
132
|
+
_actionTemplates: z.array(HateoasActionTemplateSchema).optional(),
|
|
133
|
+
});
|
|
134
|
+
// Query params for listing step runs
|
|
135
|
+
export const StepRunListQuerySchema = z.object({
|
|
136
|
+
includeFields: z
|
|
137
|
+
.union([z.literal("true"), z.literal("false")])
|
|
138
|
+
.transform((v) => v === "true")
|
|
139
|
+
.optional(),
|
|
140
|
+
});
|
|
141
|
+
// List response
|
|
142
|
+
export const StepRunListResponseSchema = z.object({
|
|
143
|
+
items: z.array(StepRunSchema),
|
|
144
|
+
total: z.number(),
|
|
145
|
+
_links: z.array(HateoasLinkSchema),
|
|
146
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
147
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
148
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { FieldListResponseSchema } from "./field-types.js";
|
|
3
|
+
import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
|
|
4
|
+
// Full step response shape
|
|
5
|
+
export const StepSchema = z.object({
|
|
6
|
+
id: z.number(),
|
|
7
|
+
operationId: z.number(),
|
|
8
|
+
seqNo: z.number(),
|
|
9
|
+
title: z.string(),
|
|
10
|
+
instructions: z.string(),
|
|
11
|
+
multiSet: z.boolean(),
|
|
12
|
+
fieldCount: z.number().optional(),
|
|
13
|
+
createdAt: z.iso.datetime(),
|
|
14
|
+
createdBy: z.string(),
|
|
15
|
+
updatedAt: z.iso.datetime(),
|
|
16
|
+
updatedBy: z.string(),
|
|
17
|
+
fields: FieldListResponseSchema,
|
|
18
|
+
_links: z.array(HateoasLinkSchema).optional(),
|
|
19
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
20
|
+
});
|
|
21
|
+
// Input for creating a step
|
|
22
|
+
export const CreateStepSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
seqNo: z.number().int().min(1).optional(),
|
|
25
|
+
title: z.string().max(200).optional(),
|
|
26
|
+
instructions: z.string().max(10000).optional(),
|
|
27
|
+
multiSet: z.boolean().optional(),
|
|
28
|
+
})
|
|
29
|
+
.strict();
|
|
30
|
+
// Input for batch creating steps
|
|
31
|
+
export const BatchCreateStepSchema = z.object({
|
|
32
|
+
items: z.array(CreateStepSchema).min(1).max(100),
|
|
33
|
+
});
|
|
34
|
+
// Input for updating a step
|
|
35
|
+
export const UpdateStepSchema = z
|
|
36
|
+
.object({
|
|
37
|
+
seqNo: z.number().int().min(1).optional(),
|
|
38
|
+
title: z.string().max(200).optional(),
|
|
39
|
+
instructions: z.string().max(10000).optional(),
|
|
40
|
+
multiSet: z.boolean().optional(),
|
|
41
|
+
})
|
|
42
|
+
.strict();
|
|
43
|
+
// List response
|
|
44
|
+
export const StepListResponseSchema = z.object({
|
|
45
|
+
items: z.array(StepSchema),
|
|
46
|
+
total: z.number(),
|
|
47
|
+
nextSeqNo: z.number(),
|
|
48
|
+
_links: z.array(HateoasLinkSchema),
|
|
49
|
+
_linkTemplates: z.array(HateoasLinkTemplateSchema).optional(),
|
|
50
|
+
_actions: z.array(HateoasActionSchema).optional(),
|
|
51
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
export const ErpPermissionEnum = z.enum([
|
|
3
|
+
"erp_admin",
|
|
4
|
+
"order_planner",
|
|
5
|
+
"order_executor",
|
|
6
|
+
"order_manager",
|
|
7
|
+
"item_manager",
|
|
8
|
+
]);
|
|
9
|
+
export const ErpPermission = ErpPermissionEnum.enum;
|
|
10
|
+
const urlSafeUsername = z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.max(64)
|
|
14
|
+
.regex(/^[a-zA-Z0-9_-]+$/, "Must contain only letters, numbers, hyphens, and underscores");
|
|
15
|
+
export const CreateUserSchema = z
|
|
16
|
+
.object({
|
|
17
|
+
username: urlSafeUsername,
|
|
18
|
+
password: z.string().min(6),
|
|
19
|
+
})
|
|
20
|
+
.strict();
|
|
21
|
+
export const UpdateUserSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
username: urlSafeUsername.optional(),
|
|
24
|
+
password: z.string().min(6).optional(),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
27
|
+
export const GrantPermissionSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
permission: ErpPermissionEnum,
|
|
30
|
+
})
|
|
31
|
+
.strict();
|
|
32
|
+
export const CreateAgentUserSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
agentId: z.number().int(),
|
|
35
|
+
})
|
|
36
|
+
.strict();
|
|
37
|
+
export const ChangePasswordSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
password: z.string().min(6),
|
|
40
|
+
})
|
|
41
|
+
.strict();
|
|
42
|
+
export const UserPermissionSchema = z.object({
|
|
43
|
+
permission: ErpPermissionEnum,
|
|
44
|
+
grantedAt: z.string(),
|
|
45
|
+
grantedBy: z.number().nullable(),
|
|
46
|
+
_actions: z.array(z.any()).optional(),
|
|
47
|
+
});
|
|
48
|
+
export const UserSchema = z.object({
|
|
49
|
+
id: z.number(),
|
|
50
|
+
username: z.string(),
|
|
51
|
+
isAgent: z.boolean(),
|
|
52
|
+
createdAt: z.string(),
|
|
53
|
+
updatedAt: z.string(),
|
|
54
|
+
apiKey: z.string().nullable().optional(),
|
|
55
|
+
permissions: z.array(UserPermissionSchema),
|
|
56
|
+
_links: z.array(z.any()).optional(),
|
|
57
|
+
_actions: z.array(z.any()).optional(),
|
|
58
|
+
});
|
|
59
|
+
export const UserListItemSchema = z.object({
|
|
60
|
+
id: z.number(),
|
|
61
|
+
username: z.string(),
|
|
62
|
+
isAgent: z.boolean(),
|
|
63
|
+
createdAt: z.string(),
|
|
64
|
+
permissionCount: z.number(),
|
|
65
|
+
});
|
|
66
|
+
export const UserListResponseSchema = z.object({
|
|
67
|
+
items: z.array(UserListItemSchema),
|
|
68
|
+
total: z.number(),
|
|
69
|
+
page: z.number(),
|
|
70
|
+
pageSize: z.number(),
|
|
71
|
+
_links: z.array(z.any()).optional(),
|
|
72
|
+
_linkTemplates: z.array(z.any()).optional(),
|
|
73
|
+
_actions: z.array(z.any()).optional(),
|
|
74
|
+
});
|
|
75
|
+
export const UserListQuerySchema = z.object({
|
|
76
|
+
page: z.coerce.number().int().min(1).default(1),
|
|
77
|
+
pageSize: z.coerce.number().int().min(1).max(100).default(20),
|
|
78
|
+
search: z.string().optional(),
|
|
79
|
+
});
|