@naisys/erp-shared 3.0.0-beta.23 → 3.0.0-beta.25

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,5 +1,6 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionSchema, HateoasLinkSchema } from "./hateoas-types.js";
3
+ import { paginationQuery } from "./pagination-types.js";
3
4
  export const AdminInfoResponseSchema = z.object({
4
5
  erpVersion: z.string(),
5
6
  erpDbPath: z.string(),
@@ -17,8 +18,7 @@ export const AdminAttachmentItemSchema = z.object({
17
18
  createdAt: z.string(),
18
19
  });
19
20
  export const AdminAttachmentListRequestSchema = z.object({
20
- page: z.coerce.number().optional().default(1),
21
- pageSize: z.coerce.number().optional().default(50),
21
+ ...paginationQuery(50),
22
22
  });
23
23
  export const AdminAttachmentListResponseSchema = z.object({
24
24
  attachments: z.array(AdminAttachmentItemSchema),
@@ -3,4 +3,10 @@ export const ErrorResponseSchema = z.object({
3
3
  statusCode: z.number().int(),
4
4
  error: z.string(),
5
5
  message: z.string(),
6
+ /**
7
+ * For 403 responses raised by a permission check, the name of the
8
+ * missing permission. Lets clients react structurally without having
9
+ * to parse the human-readable `message`.
10
+ */
11
+ missingPermission: z.string().optional(),
6
12
  });
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ export * from "./operation-types.js";
18
18
  export * from "./order-revision-types.js";
19
19
  export * from "./order-run-types.js";
20
20
  export * from "./order-types.js";
21
+ export * from "./pagination-types.js";
21
22
  export * from "./revision-diff-types.js";
22
23
  export * from "./step-run-types.js";
23
24
  export * from "./step-types.js";
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionTemplateSchema, HateoasLinkSchema, } from "./hateoas-types.js";
3
+ import { paginationQuery } from "./pagination-types.js";
3
4
  // Query params for inventory list (all item instances across all items)
4
5
  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),
6
+ ...paginationQuery(),
7
7
  search: z.string().optional(),
8
8
  });
9
9
  // Flattened inventory item for the list
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ import { paginationQuery } from "./pagination-types.js";
3
4
  import { FieldValueEntrySchema } from "./step-run-types.js";
4
5
  // Full item instance response shape
5
6
  export const ItemInstanceSchema = z.object({
@@ -36,8 +37,7 @@ export const UpdateItemInstanceSchema = z
36
37
  .strict();
37
38
  // Query params for listing item instances
38
39
  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),
40
+ ...paginationQuery(),
41
41
  search: z.string().optional(),
42
42
  });
43
43
  // List response
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod/v4";
2
2
  import { FieldListResponseSchema } from "./field-types.js";
3
3
  import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
4
+ import { paginationQuery } from "./pagination-types.js";
4
5
  // Full item response shape
5
6
  export const ItemSchema = z.object({
6
7
  id: z.number(),
@@ -39,8 +40,7 @@ export const UpdateItemSchema = z
39
40
  .strict();
40
41
  // Query params for listing items
41
42
  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),
43
+ ...paginationQuery(),
44
44
  search: z.string().optional(),
45
45
  });
46
46
  // List response
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ import { paginationQuery } from "./pagination-types.js";
3
4
  // Operation summary embedded in revision GET responses
4
5
  export const RevisionOperationSummarySchema = z.object({
5
6
  seqNo: z.number(),
@@ -40,8 +41,7 @@ export const UpdateOrderRevisionSchema = z
40
41
  .strict();
41
42
  // Query params for listing revisions
42
43
  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),
44
+ ...paginationQuery(),
45
45
  status: RevisionStatusEnum.optional(),
46
46
  includeObsolete: z
47
47
  .enum(["true", "false"])
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionSchema, HateoasActionTemplateSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
3
  import { OperationRunStatusEnum } from "./operation-run-types.js";
4
+ import { paginationQuery } from "./pagination-types.js";
4
5
  // Operation summary embedded in order run GET responses
5
6
  export const OperationRunSummarySchema = z.object({
6
7
  seqNo: z.number(),
@@ -65,14 +66,18 @@ export const UpdateOrderRunSchema = z
65
66
  releaseNote: z.string().max(2000).nullable().optional(),
66
67
  })
67
68
  .strict();
68
- // Input for completing an order run (creates item instance + closes run)
69
+ // Input for completing an order run (creates item instance + closes run).
70
+ // `fieldValues[].fieldSeqNo` is the per-item field sequence number — matches
71
+ // the field-update endpoint at /items/{key}/instances/{instanceId}/fields/{fieldSeqNo}.
72
+ // If any required item field is empty, the endpoint returns 400 with the
73
+ // missing field labels rather than creating an invalid instance.
69
74
  export const CompleteOrderRunSchema = z
70
75
  .object({
71
76
  instanceKey: z.string().max(200).optional(),
72
77
  quantity: z.number().nullable().optional(),
73
78
  fieldValues: z
74
79
  .array(z.object({
75
- fieldId: z.number().int(),
80
+ fieldSeqNo: z.number().int(),
76
81
  value: z.string().max(2000),
77
82
  setIndex: z.number().int().min(0).optional(),
78
83
  }))
@@ -81,8 +86,7 @@ export const CompleteOrderRunSchema = z
81
86
  .strict();
82
87
  // Query params for listing order runs
83
88
  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),
89
+ ...paginationQuery(),
86
90
  status: OrderRunStatusEnum.optional(),
87
91
  priority: OrderRunPriorityEnum.optional(),
88
92
  search: z.string().optional(),
@@ -99,8 +103,7 @@ export const OrderRunListResponseSchema = z.object({
99
103
  });
100
104
  // Query params for dispatch view (operation runs across open orders)
101
105
  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),
106
+ ...paginationQuery(),
104
107
  status: OperationRunStatusEnum.optional(),
105
108
  priority: OrderRunPriorityEnum.optional(),
106
109
  search: z.string().optional(),
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ import { paginationQuery } from "./pagination-types.js";
3
4
  export const OrderStatusEnum = z.enum(["active", "archived"]);
4
5
  export const OrderStatus = OrderStatusEnum.enum;
5
6
  // Full order response shape
@@ -9,6 +10,7 @@ export const OrderSchema = z.object({
9
10
  description: z.string(),
10
11
  status: OrderStatusEnum,
11
12
  itemKey: z.string().nullable(),
13
+ latestApprovedRevNo: z.number().int().nullable().optional(),
12
14
  createdBy: z.string(),
13
15
  createdAt: z.iso.datetime(),
14
16
  updatedBy: z.string(),
@@ -44,8 +46,7 @@ export const UpdateOrderSchema = z
44
46
  .strict();
45
47
  // Query params for listing orders
46
48
  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
+ ...paginationQuery(),
49
50
  status: z.enum(["active", "archived"]).optional(),
50
51
  search: z.string().optional(),
51
52
  });
@@ -0,0 +1,52 @@
1
+ import { z } from "zod/v4";
2
+ /**
3
+ * Maximum allowed pageSize for any list endpoint.
4
+ *
5
+ * Callers may request a larger pageSize, but it will be silently clamped
6
+ * to this value. This is documented in the OpenAPI spec via the schema
7
+ * description so callers can discover the limit.
8
+ */
9
+ export const MAX_PAGE_SIZE = 100;
10
+ /**
11
+ * Build a `pageSize` query-param schema with a documented cap.
12
+ *
13
+ * Behaviour:
14
+ * - Coerces strings → numbers (querystrings are always strings).
15
+ * - Rejects values < 1 (floor of 1, then defaults).
16
+ * - Silently clamps oversized values to {@link MAX_PAGE_SIZE}.
17
+ * - Defaults to {@link defaultValue} when omitted.
18
+ *
19
+ * Apply via the shared {@link paginationQuery} helper rather than per-route.
20
+ */
21
+ export function pageSizeSchema(defaultValue = 20) {
22
+ return z.coerce
23
+ .number()
24
+ .int()
25
+ .min(1)
26
+ .optional()
27
+ .default(defaultValue)
28
+ .transform((n) => Math.min(n, MAX_PAGE_SIZE))
29
+ .describe(`Items per page. Values above ${MAX_PAGE_SIZE} are silently clamped to ${MAX_PAGE_SIZE}.`);
30
+ }
31
+ /**
32
+ * Page-number schema — coerced int >= 1, defaulting to 1.
33
+ */
34
+ export function pageSchema() {
35
+ return z.coerce.number().int().min(1).optional().default(1);
36
+ }
37
+ /**
38
+ * Standard pagination query fields. Spread into a list-query Zod object:
39
+ *
40
+ * ```ts
41
+ * export const InventoryListQuerySchema = z.object({
42
+ * ...paginationQuery(),
43
+ * search: z.string().optional(),
44
+ * });
45
+ * ```
46
+ */
47
+ export function paginationQuery(defaultPageSize = 20) {
48
+ return {
49
+ page: pageSchema(),
50
+ pageSize: pageSizeSchema(defaultPageSize),
51
+ };
52
+ }
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod/v4";
2
+ import { paginationQuery } from "./pagination-types.js";
2
3
  export const ErpPermissionEnum = z.enum([
3
4
  "erp_admin",
4
5
  "order_planner",
@@ -73,7 +74,6 @@ export const UserListResponseSchema = z.object({
73
74
  _actions: z.array(z.any()).optional(),
74
75
  });
75
76
  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),
77
+ ...paginationQuery(),
78
78
  search: z.string().optional(),
79
79
  });
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod/v4";
2
2
  import { HateoasActionSchema, HateoasLinkSchema, HateoasLinkTemplateSchema, } from "./hateoas-types.js";
3
+ import { paginationQuery } from "./pagination-types.js";
3
4
  // Work center user assignment (embedded in detail response)
4
5
  export const WorkCenterUserSchema = z.object({
5
6
  userId: z.number(),
@@ -52,8 +53,7 @@ export const AssignWorkCenterUserSchema = z
52
53
  .strict();
53
54
  // Query params for listing work centers
54
55
  export const WorkCenterListQuerySchema = z.object({
55
- page: z.coerce.number().int().min(1).optional().default(1),
56
- pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),
56
+ ...paginationQuery(),
57
57
  search: z.string().optional(),
58
58
  });
59
59
  // Work center list item (lighter response)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naisys/erp-shared",
3
- "version": "3.0.0-beta.23",
3
+ "version": "3.0.0-beta.25",
4
4
  "description": "[internal] NAISYS ERP shared types and validation schemas",
5
5
  "type": "module",
6
6
  "files": [
@@ -20,7 +20,7 @@
20
20
  "typescript": "^5.9.3"
21
21
  },
22
22
  "dependencies": {
23
- "@naisys/common": "3.0.0-beta.23",
23
+ "@naisys/common": "3.0.0-beta.25",
24
24
  "zod": "^4.3.6"
25
25
  },
26
26
  "exports": {