@salixcommerce/core 0.1.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.
- package/README.md +5 -0
- package/dist/admin.d.ts +70 -0
- package/dist/admin.d.ts.map +1 -0
- package/dist/admin.js +76 -0
- package/dist/admin.js.map +1 -0
- package/dist/cart.d.ts +107 -0
- package/dist/cart.d.ts.map +1 -0
- package/dist/cart.js +87 -0
- package/dist/cart.js.map +1 -0
- package/dist/catalog.d.ts +89 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +89 -0
- package/dist/catalog.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/invariant-error.d.ts +6 -0
- package/dist/invariant-error.d.ts.map +1 -0
- package/dist/invariant-error.js +9 -0
- package/dist/invariant-error.js.map +1 -0
- package/dist/inventory.d.ts +27 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +95 -0
- package/dist/inventory.js.map +1 -0
- package/dist/lifecycle.d.ts +30 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +76 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/money.d.ts +13 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/money.js +67 -0
- package/dist/money.js.map +1 -0
- package/dist/order.d.ts +119 -0
- package/dist/order.d.ts.map +1 -0
- package/dist/order.js +132 -0
- package/dist/order.js.map +1 -0
- package/dist/payment.d.ts +253 -0
- package/dist/payment.d.ts.map +1 -0
- package/dist/payment.js +230 -0
- package/dist/payment.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const inventoryStateSchema: z.ZodObject<{
|
|
3
|
+
mode: z.ZodEnum<{
|
|
4
|
+
tracked: "tracked";
|
|
5
|
+
untracked: "untracked";
|
|
6
|
+
}>;
|
|
7
|
+
onHand: z.ZodNumber;
|
|
8
|
+
reserved: z.ZodDefault<z.ZodNumber>;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export declare const inventoryMovementSchema: z.ZodObject<{
|
|
11
|
+
delta: z.ZodNumber;
|
|
12
|
+
idempotencyKey: z.ZodString;
|
|
13
|
+
reason: z.ZodString;
|
|
14
|
+
}, z.core.$strict>;
|
|
15
|
+
export declare const inventoryAvailabilitySchema: z.ZodEnum<{
|
|
16
|
+
untracked: "untracked";
|
|
17
|
+
backorder: "backorder";
|
|
18
|
+
in_stock: "in_stock";
|
|
19
|
+
out_of_stock: "out_of_stock";
|
|
20
|
+
}>;
|
|
21
|
+
export type InventoryState = z.output<typeof inventoryStateSchema>;
|
|
22
|
+
export type InventoryMovement = z.output<typeof inventoryMovementSchema>;
|
|
23
|
+
export type InventoryAvailability = z.output<typeof inventoryAvailabilitySchema>;
|
|
24
|
+
export declare function resolveInventoryAvailability(state: InventoryState, allowBackorders: boolean): InventoryAvailability;
|
|
25
|
+
export declare function applyInventoryReservation(state: InventoryState, delta: number): InventoryState;
|
|
26
|
+
export declare function applyInventoryMovement(state: InventoryState, movement: InventoryMovement): InventoryState;
|
|
27
|
+
//# sourceMappingURL=inventory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,oBAAoB;;;;;;;kBAqB7B,CAAC;AAEL,eAAO,MAAM,uBAAuB;;;;kBAalC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;EAKtC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACnE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACzE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEjF,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,cAAc,EACrB,eAAe,EAAE,OAAO,GACvB,qBAAqB,CAKvB;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAmC9F;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,cAAc,CA8BhB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DomainInvariantError } from "./invariant-error.js";
|
|
3
|
+
const inventoryQuantitySchema = z.number().int().safe().nonnegative();
|
|
4
|
+
export const inventoryStateSchema = z
|
|
5
|
+
.strictObject({
|
|
6
|
+
mode: z.enum(["tracked", "untracked"]),
|
|
7
|
+
onHand: inventoryQuantitySchema,
|
|
8
|
+
reserved: inventoryQuantitySchema.default(0),
|
|
9
|
+
})
|
|
10
|
+
.superRefine((value, context) => {
|
|
11
|
+
if (value.mode === "untracked" && (value.onHand !== 0 || value.reserved !== 0)) {
|
|
12
|
+
context.addIssue({
|
|
13
|
+
code: "custom",
|
|
14
|
+
message: "Untracked inventory must use zero on-hand and reserved placeholders.",
|
|
15
|
+
path: ["onHand"],
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (value.mode === "tracked" && value.reserved > value.onHand) {
|
|
19
|
+
context.addIssue({
|
|
20
|
+
code: "custom",
|
|
21
|
+
message: "Reserved inventory cannot exceed physical on-hand inventory.",
|
|
22
|
+
path: ["reserved"],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
export const inventoryMovementSchema = z.strictObject({
|
|
27
|
+
delta: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.safe()
|
|
31
|
+
.refine((value) => value !== 0, "Movement delta cannot be zero."),
|
|
32
|
+
idempotencyKey: z
|
|
33
|
+
.string()
|
|
34
|
+
.trim()
|
|
35
|
+
.min(8)
|
|
36
|
+
.max(160)
|
|
37
|
+
.regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/u, "Invalid inventory idempotency key."),
|
|
38
|
+
reason: z.string().trim().min(1).max(240),
|
|
39
|
+
});
|
|
40
|
+
export const inventoryAvailabilitySchema = z.enum([
|
|
41
|
+
"backorder",
|
|
42
|
+
"in_stock",
|
|
43
|
+
"out_of_stock",
|
|
44
|
+
"untracked",
|
|
45
|
+
]);
|
|
46
|
+
export function resolveInventoryAvailability(state, allowBackorders) {
|
|
47
|
+
const parsed = inventoryStateSchema.parse(state);
|
|
48
|
+
if (parsed.mode === "untracked")
|
|
49
|
+
return "untracked";
|
|
50
|
+
if (parsed.onHand - parsed.reserved > 0)
|
|
51
|
+
return "in_stock";
|
|
52
|
+
return allowBackorders ? "backorder" : "out_of_stock";
|
|
53
|
+
}
|
|
54
|
+
export function applyInventoryReservation(state, delta) {
|
|
55
|
+
const parsedState = inventoryStateSchema.parse(state);
|
|
56
|
+
const parsedDelta = z
|
|
57
|
+
.number()
|
|
58
|
+
.int()
|
|
59
|
+
.safe()
|
|
60
|
+
.refine((value) => value !== 0)
|
|
61
|
+
.parse(delta);
|
|
62
|
+
if (parsedState.mode === "untracked") {
|
|
63
|
+
throw new DomainInvariantError("INVENTORY_UNTRACKED_MOVEMENT", "Inventory reservations require tracked inventory.");
|
|
64
|
+
}
|
|
65
|
+
const nextReserved = parsedState.reserved + parsedDelta;
|
|
66
|
+
if (!Number.isSafeInteger(nextReserved)) {
|
|
67
|
+
throw new DomainInvariantError("INVENTORY_ARITHMETIC_OVERFLOW", "Inventory reservation exceeds the safe-integer range.");
|
|
68
|
+
}
|
|
69
|
+
if (nextReserved < 0) {
|
|
70
|
+
throw new DomainInvariantError("INVENTORY_RESERVATION_NEGATIVE", "Inventory reservation cannot create a negative reserved balance.");
|
|
71
|
+
}
|
|
72
|
+
if (nextReserved > parsedState.onHand) {
|
|
73
|
+
throw new DomainInvariantError("INVENTORY_RESERVATION_EXCEEDS_ON_HAND", "Inventory reservation cannot exceed physical on-hand inventory.");
|
|
74
|
+
}
|
|
75
|
+
return { ...parsedState, reserved: nextReserved };
|
|
76
|
+
}
|
|
77
|
+
export function applyInventoryMovement(state, movement) {
|
|
78
|
+
const parsedState = inventoryStateSchema.parse(state);
|
|
79
|
+
const parsedMovement = inventoryMovementSchema.parse(movement);
|
|
80
|
+
if (parsedState.mode === "untracked") {
|
|
81
|
+
throw new DomainInvariantError("INVENTORY_UNTRACKED_MOVEMENT", "Inventory movements require tracked inventory.");
|
|
82
|
+
}
|
|
83
|
+
const nextOnHand = parsedState.onHand + parsedMovement.delta;
|
|
84
|
+
if (!Number.isSafeInteger(nextOnHand)) {
|
|
85
|
+
throw new DomainInvariantError("INVENTORY_ARITHMETIC_OVERFLOW", "Inventory movement exceeds safe integer range.");
|
|
86
|
+
}
|
|
87
|
+
if (nextOnHand < 0) {
|
|
88
|
+
throw new DomainInvariantError("INVENTORY_NEGATIVE_BALANCE", "Inventory movement cannot create a negative physical balance.");
|
|
89
|
+
}
|
|
90
|
+
if (nextOnHand < parsedState.reserved) {
|
|
91
|
+
throw new DomainInvariantError("INVENTORY_MOVEMENT_BELOW_RESERVED", "Inventory movement cannot reduce physical stock below the reserved balance.");
|
|
92
|
+
}
|
|
93
|
+
return { ...parsedState, onHand: nextOnHand };
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface LifecycleTransition<TState extends string, TCapability extends string> {
|
|
2
|
+
readonly capability: TCapability;
|
|
3
|
+
readonly from: TState;
|
|
4
|
+
readonly to: TState;
|
|
5
|
+
}
|
|
6
|
+
export interface LifecycleTableDefect {
|
|
7
|
+
readonly detail: string;
|
|
8
|
+
readonly kind: "CONTRADICTORY_TRANSITION" | "DEAD_NON_TERMINAL" | "DUPLICATE_EDGE" | "UNREACHABLE_STATE";
|
|
9
|
+
}
|
|
10
|
+
export type LifecycleGuardResult<TState extends string, TCapability extends string> = {
|
|
11
|
+
readonly ok: true;
|
|
12
|
+
readonly transition: LifecycleTransition<TState, TCapability>;
|
|
13
|
+
} | {
|
|
14
|
+
readonly error: {
|
|
15
|
+
readonly code: "ILLEGAL_TRANSITION";
|
|
16
|
+
readonly from: TState;
|
|
17
|
+
readonly to: TState;
|
|
18
|
+
} | {
|
|
19
|
+
readonly capability: TCapability;
|
|
20
|
+
readonly code: "UNAUTHORIZED_ACTOR";
|
|
21
|
+
};
|
|
22
|
+
readonly ok: false;
|
|
23
|
+
};
|
|
24
|
+
export declare function guardLifecycleTransition<TState extends string, TCapability extends string>(table: readonly LifecycleTransition<TState, TCapability>[], request: Readonly<{
|
|
25
|
+
capabilities: readonly TCapability[];
|
|
26
|
+
from: TState;
|
|
27
|
+
to: TState;
|
|
28
|
+
}>): LifecycleGuardResult<TState, TCapability>;
|
|
29
|
+
export declare function validateLifecycleTransitionTable<TState extends string, TCapability extends string>(table: readonly LifecycleTransition<TState, TCapability>[], initial: TState, declaredTerminal: readonly TState[]): LifecycleTableDefect[];
|
|
30
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB,CAAC,MAAM,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM;IACpF,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EACX,0BAA0B,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;CAC7F;AAED,MAAM,MAAM,oBAAoB,CAAC,MAAM,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM,IAC9E;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC/D,GACD;IACE,QAAQ,CAAC,KAAK,EACV;QACE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;QACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;KACrB,GACD;QACE,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;QACjC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;KACrC,CAAC;IACN,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;CACpB,CAAC;AAEN,wBAAgB,wBAAwB,CAAC,MAAM,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM,EACxF,KAAK,EAAE,SAAS,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAC1D,OAAO,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC,GACD,oBAAoB,CAAC,MAAM,EAAE,WAAW,CAAC,CAiB3C;AAED,wBAAgB,gCAAgC,CAAC,MAAM,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM,EAChG,KAAK,EAAE,SAAS,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAC1D,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAClC,oBAAoB,EAAE,CA2DxB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export function guardLifecycleTransition(table, request) {
|
|
2
|
+
const transition = table.find((candidate) => candidate.from === request.from && candidate.to === request.to);
|
|
3
|
+
if (transition === undefined) {
|
|
4
|
+
return {
|
|
5
|
+
error: { code: "ILLEGAL_TRANSITION", from: request.from, to: request.to },
|
|
6
|
+
ok: false,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
if (!request.capabilities.includes(transition.capability)) {
|
|
10
|
+
return {
|
|
11
|
+
error: { capability: transition.capability, code: "UNAUTHORIZED_ACTOR" },
|
|
12
|
+
ok: false,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return { ok: true, transition };
|
|
16
|
+
}
|
|
17
|
+
export function validateLifecycleTransitionTable(table, initial, declaredTerminal) {
|
|
18
|
+
const defects = [];
|
|
19
|
+
const states = new Set([initial]);
|
|
20
|
+
const edges = new Map();
|
|
21
|
+
const edgeCounts = new Map();
|
|
22
|
+
const adjacency = new Map();
|
|
23
|
+
for (const transition of table) {
|
|
24
|
+
states.add(transition.from);
|
|
25
|
+
states.add(transition.to);
|
|
26
|
+
const key = `${transition.from}->${transition.to}`;
|
|
27
|
+
const capabilities = edges.get(key) ?? new Set();
|
|
28
|
+
capabilities.add(transition.capability);
|
|
29
|
+
edges.set(key, capabilities);
|
|
30
|
+
edgeCounts.set(key, (edgeCounts.get(key) ?? 0) + 1);
|
|
31
|
+
adjacency.set(transition.from, [...(adjacency.get(transition.from) ?? []), transition.to]);
|
|
32
|
+
}
|
|
33
|
+
for (const [key, capabilities] of edges) {
|
|
34
|
+
if (capabilities.size > 1) {
|
|
35
|
+
defects.push({
|
|
36
|
+
detail: `${key} has conflicting capabilities: ${[...capabilities].join(", ")}`,
|
|
37
|
+
kind: "CONTRADICTORY_TRANSITION",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else if ((edgeCounts.get(key) ?? 0) > 1) {
|
|
41
|
+
defects.push({ detail: `${key} is declared more than once.`, kind: "DUPLICATE_EDGE" });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const seen = new Set([initial]);
|
|
45
|
+
const queue = [initial];
|
|
46
|
+
while (queue.length > 0) {
|
|
47
|
+
const state = queue.shift();
|
|
48
|
+
if (state === undefined)
|
|
49
|
+
break;
|
|
50
|
+
for (const next of adjacency.get(state) ?? []) {
|
|
51
|
+
if (seen.has(next))
|
|
52
|
+
continue;
|
|
53
|
+
seen.add(next);
|
|
54
|
+
queue.push(next);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const state of states) {
|
|
58
|
+
if (!seen.has(state)) {
|
|
59
|
+
defects.push({
|
|
60
|
+
detail: `'${state}' is unreachable from '${initial}'.`,
|
|
61
|
+
kind: "UNREACHABLE_STATE",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const terminal = new Set(declaredTerminal);
|
|
66
|
+
for (const state of states) {
|
|
67
|
+
if (!adjacency.has(state) && !terminal.has(state)) {
|
|
68
|
+
defects.push({
|
|
69
|
+
detail: `'${state}' has no outgoing edge and is not declared terminal.`,
|
|
70
|
+
kind: "DEAD_NON_TERMINAL",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return defects;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"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"}
|
package/dist/money.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const currencyCodeSchema: z.ZodString;
|
|
3
|
+
export declare const nonNegativeMinorUnitSchema: z.ZodNumber;
|
|
4
|
+
export declare const moneySchema: z.ZodObject<{
|
|
5
|
+
amountMinor: z.ZodNumber;
|
|
6
|
+
currency: z.ZodString;
|
|
7
|
+
}, z.core.$strict>;
|
|
8
|
+
export type Money = z.output<typeof moneySchema>;
|
|
9
|
+
export declare function createMoney(amountMinor: number, currency: string): Money;
|
|
10
|
+
export declare function addMoney(left: Money, right: Money): Money;
|
|
11
|
+
export declare function multiplyMoney(money: Money, multiplier: number): Money;
|
|
12
|
+
export declare function formatMoney(money: Money, locale: string): string;
|
|
13
|
+
//# sourceMappingURL=money.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,kBAAkB,aAIsD,CAAC;AAEtF,eAAO,MAAM,0BAA0B,aAIgC,CAAC;AAExE,eAAO,MAAM,WAAW;;;kBAGtB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAEjD,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,CAExE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAQzD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,KAAK,CAOrE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAWhE"}
|
package/dist/money.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DomainInvariantError } from "./invariant-error.js";
|
|
3
|
+
export const currencyCodeSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.trim()
|
|
6
|
+
.regex(/^[A-Z]{3}$/u, "Currency must be an uppercase ISO 4217 code.")
|
|
7
|
+
.refine(isRuntimeCurrency, "Currency must be supported by the JavaScript runtime.");
|
|
8
|
+
export const nonNegativeMinorUnitSchema = z
|
|
9
|
+
.number()
|
|
10
|
+
.int()
|
|
11
|
+
.safe()
|
|
12
|
+
.nonnegative("Money amount must be nonnegative integer minor units.");
|
|
13
|
+
export const moneySchema = z.strictObject({
|
|
14
|
+
amountMinor: nonNegativeMinorUnitSchema,
|
|
15
|
+
currency: currencyCodeSchema,
|
|
16
|
+
});
|
|
17
|
+
export function createMoney(amountMinor, currency) {
|
|
18
|
+
return moneySchema.parse({ amountMinor, currency });
|
|
19
|
+
}
|
|
20
|
+
export function addMoney(left, right) {
|
|
21
|
+
const parsedLeft = moneySchema.parse(left);
|
|
22
|
+
const parsedRight = moneySchema.parse(right);
|
|
23
|
+
assertMatchingCurrency(parsedLeft, parsedRight);
|
|
24
|
+
return createMoney(safeMoneyArithmetic(parsedLeft.amountMinor + parsedRight.amountMinor), parsedLeft.currency);
|
|
25
|
+
}
|
|
26
|
+
export function multiplyMoney(money, multiplier) {
|
|
27
|
+
const parsedMoney = moneySchema.parse(money);
|
|
28
|
+
const parsedMultiplier = z.number().int().safe().nonnegative().parse(multiplier);
|
|
29
|
+
return createMoney(safeMoneyArithmetic(parsedMoney.amountMinor * parsedMultiplier), parsedMoney.currency);
|
|
30
|
+
}
|
|
31
|
+
export function formatMoney(money, locale) {
|
|
32
|
+
const parsed = moneySchema.parse(money);
|
|
33
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
34
|
+
currency: parsed.currency,
|
|
35
|
+
style: "currency",
|
|
36
|
+
});
|
|
37
|
+
const fractionDigits = formatter.resolvedOptions().maximumFractionDigits;
|
|
38
|
+
if (fractionDigits === undefined) {
|
|
39
|
+
throw new RangeError(`No minor-unit exponent is available for ${parsed.currency}.`);
|
|
40
|
+
}
|
|
41
|
+
return formatter.format(parsed.amountMinor / 10 ** fractionDigits);
|
|
42
|
+
}
|
|
43
|
+
function isRuntimeCurrency(value) {
|
|
44
|
+
const supportedValuesOf = Intl.supportedValuesOf;
|
|
45
|
+
if (supportedValuesOf) {
|
|
46
|
+
return supportedValuesOf("currency").includes(value);
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
new Intl.NumberFormat("en", { currency: value, style: "currency" }).format(0);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function assertMatchingCurrency(left, right) {
|
|
57
|
+
if (left.currency !== right.currency) {
|
|
58
|
+
throw new DomainInvariantError("MONEY_CURRENCY_MISMATCH", `Cannot combine ${left.currency} and ${right.currency}.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function safeMoneyArithmetic(value) {
|
|
62
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
63
|
+
throw new DomainInvariantError("MONEY_ARITHMETIC_OVERFLOW", "Money calculation exceeds the nonnegative safe-integer range.");
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=money.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"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"}
|
package/dist/order.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type PricedCartLine } from "./cart.js";
|
|
3
|
+
import { type LifecycleGuardResult } from "./lifecycle.js";
|
|
4
|
+
import { type Money } from "./money.js";
|
|
5
|
+
export declare const orderStatusSchema: z.ZodEnum<{
|
|
6
|
+
fulfilled: "fulfilled";
|
|
7
|
+
processing: "processing";
|
|
8
|
+
pending_payment: "pending_payment";
|
|
9
|
+
paid: "paid";
|
|
10
|
+
cancelled: "cancelled";
|
|
11
|
+
}>;
|
|
12
|
+
export declare const orderCapabilitySchema: z.ZodEnum<{
|
|
13
|
+
"order.cancel": "order.cancel";
|
|
14
|
+
"order.process": "order.process";
|
|
15
|
+
"order.fulfill": "order.fulfill";
|
|
16
|
+
"payment.succeed": "payment.succeed";
|
|
17
|
+
}>;
|
|
18
|
+
export declare const orderReferenceSchema: z.ZodString;
|
|
19
|
+
export declare const contactEmailSchema: z.ZodString;
|
|
20
|
+
export declare const orderCreateCommandSchema: z.ZodObject<{
|
|
21
|
+
contactEmail: z.ZodString;
|
|
22
|
+
idempotencyKey: z.ZodString;
|
|
23
|
+
}, z.core.$strict>;
|
|
24
|
+
export declare const orderCancelCommandSchema: z.ZodObject<{
|
|
25
|
+
idempotencyKey: z.ZodString;
|
|
26
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
27
|
+
}, z.core.$strict>;
|
|
28
|
+
export declare const orderItemSnapshotSchema: z.ZodObject<{
|
|
29
|
+
backorderedQuantity: z.ZodNumber;
|
|
30
|
+
inventoryMode: z.ZodEnum<{
|
|
31
|
+
tracked: "tracked";
|
|
32
|
+
untracked: "untracked";
|
|
33
|
+
}>;
|
|
34
|
+
lineTotal: z.ZodObject<{
|
|
35
|
+
amountMinor: z.ZodNumber;
|
|
36
|
+
currency: z.ZodString;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
productName: z.ZodString;
|
|
39
|
+
productSlug: z.ZodString;
|
|
40
|
+
quantity: z.ZodNumber;
|
|
41
|
+
reservedQuantity: z.ZodNumber;
|
|
42
|
+
sku: z.ZodNullable<z.ZodString>;
|
|
43
|
+
sourceVariantId: z.ZodString;
|
|
44
|
+
unitPrice: z.ZodObject<{
|
|
45
|
+
amountMinor: z.ZodNumber;
|
|
46
|
+
currency: z.ZodString;
|
|
47
|
+
}, z.core.$strict>;
|
|
48
|
+
variantName: z.ZodString;
|
|
49
|
+
}, z.core.$strict>;
|
|
50
|
+
export declare const orderSnapshotSchema: z.ZodObject<{
|
|
51
|
+
contactEmail: z.ZodString;
|
|
52
|
+
createdAt: z.ZodString;
|
|
53
|
+
currency: z.ZodString;
|
|
54
|
+
id: z.ZodString;
|
|
55
|
+
items: z.ZodArray<z.ZodObject<{
|
|
56
|
+
backorderedQuantity: z.ZodNumber;
|
|
57
|
+
inventoryMode: z.ZodEnum<{
|
|
58
|
+
tracked: "tracked";
|
|
59
|
+
untracked: "untracked";
|
|
60
|
+
}>;
|
|
61
|
+
lineTotal: z.ZodObject<{
|
|
62
|
+
amountMinor: z.ZodNumber;
|
|
63
|
+
currency: z.ZodString;
|
|
64
|
+
}, z.core.$strict>;
|
|
65
|
+
productName: z.ZodString;
|
|
66
|
+
productSlug: z.ZodString;
|
|
67
|
+
quantity: z.ZodNumber;
|
|
68
|
+
reservedQuantity: z.ZodNumber;
|
|
69
|
+
sku: z.ZodNullable<z.ZodString>;
|
|
70
|
+
sourceVariantId: z.ZodString;
|
|
71
|
+
unitPrice: z.ZodObject<{
|
|
72
|
+
amountMinor: z.ZodNumber;
|
|
73
|
+
currency: z.ZodString;
|
|
74
|
+
}, z.core.$strict>;
|
|
75
|
+
variantName: z.ZodString;
|
|
76
|
+
}, z.core.$strict>>;
|
|
77
|
+
merchandiseSubtotal: z.ZodObject<{
|
|
78
|
+
amountMinor: z.ZodNumber;
|
|
79
|
+
currency: z.ZodString;
|
|
80
|
+
}, z.core.$strict>;
|
|
81
|
+
reference: z.ZodString;
|
|
82
|
+
status: z.ZodEnum<{
|
|
83
|
+
fulfilled: "fulfilled";
|
|
84
|
+
processing: "processing";
|
|
85
|
+
pending_payment: "pending_payment";
|
|
86
|
+
paid: "paid";
|
|
87
|
+
cancelled: "cancelled";
|
|
88
|
+
}>;
|
|
89
|
+
}, z.core.$strict>;
|
|
90
|
+
export type OrderStatus = z.output<typeof orderStatusSchema>;
|
|
91
|
+
export type OrderCapability = z.output<typeof orderCapabilitySchema>;
|
|
92
|
+
export type OrderItemSnapshot = z.output<typeof orderItemSnapshotSchema>;
|
|
93
|
+
export type OrderSnapshot = z.output<typeof orderSnapshotSchema>;
|
|
94
|
+
export declare const ORDER_TRANSITIONS: readonly [{
|
|
95
|
+
readonly capability: "order.cancel";
|
|
96
|
+
readonly from: "pending_payment";
|
|
97
|
+
readonly to: "cancelled";
|
|
98
|
+
}, {
|
|
99
|
+
readonly capability: "payment.succeed";
|
|
100
|
+
readonly from: "pending_payment";
|
|
101
|
+
readonly to: "paid";
|
|
102
|
+
}, {
|
|
103
|
+
readonly capability: "order.process";
|
|
104
|
+
readonly from: "paid";
|
|
105
|
+
readonly to: "processing";
|
|
106
|
+
}, {
|
|
107
|
+
readonly capability: "order.fulfill";
|
|
108
|
+
readonly from: "processing";
|
|
109
|
+
readonly to: "fulfilled";
|
|
110
|
+
}];
|
|
111
|
+
export declare function guardOrderTransition(from: OrderStatus, to: OrderStatus, capabilities: readonly OrderCapability[]): LifecycleGuardResult<OrderStatus, OrderCapability>;
|
|
112
|
+
export declare function validateOrderTransitionTable(): import("./lifecycle.js").LifecycleTableDefect[];
|
|
113
|
+
export declare function createOrderItemSnapshot(line: PricedCartLine, allocation: Readonly<{
|
|
114
|
+
backorderedQuantity: number;
|
|
115
|
+
inventoryMode: "tracked" | "untracked";
|
|
116
|
+
reservedQuantity: number;
|
|
117
|
+
}>): OrderItemSnapshot;
|
|
118
|
+
export declare function verifyOrderLineTotal(item: OrderItemSnapshot): Money;
|
|
119
|
+
//# sourceMappingURL=order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../src/order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA8C,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAE5F,OAAO,EAGL,KAAK,oBAAoB,EAE1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA4D,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAElG,eAAO,MAAM,iBAAiB;;;;;;EAM5B,CAAC;AACH,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAC;AACH,eAAO,MAAM,oBAAoB,aAAuC,CAAC;AACzE,eAAO,MAAM,kBAAkB,aAAmD,CAAC;AAEnF,eAAO,MAAM,wBAAwB;;;kBAGnC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;kBAGnC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;kBAwChC,CAAC;AAEL,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6B5B,CAAC;AAEL,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACzE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;EAKoD,CAAC;AAEnF,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,WAAW,EACf,YAAY,EAAE,SAAS,eAAe,EAAE,GACvC,oBAAoB,CAAC,WAAW,EAAE,eAAe,CAAC,CAEpD;AAED,wBAAgB,4BAA4B,oDAK3C;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,QAAQ,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,SAAS,GAAG,WAAW,CAAC;IACvC,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC,GACD,iBAAiB,CAenB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,KAAK,CAGnE"}
|
package/dist/order.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { idempotencyKeySchema, pricedCartLineSchema } from "./cart.js";
|
|
3
|
+
import { positiveIdentifierSchema, productSlugSchema } from "./catalog.js";
|
|
4
|
+
import { guardLifecycleTransition, validateLifecycleTransitionTable, } from "./lifecycle.js";
|
|
5
|
+
import { addMoney, currencyCodeSchema, moneySchema, multiplyMoney } from "./money.js";
|
|
6
|
+
export const orderStatusSchema = z.enum([
|
|
7
|
+
"pending_payment",
|
|
8
|
+
"paid",
|
|
9
|
+
"processing",
|
|
10
|
+
"fulfilled",
|
|
11
|
+
"cancelled",
|
|
12
|
+
]);
|
|
13
|
+
export const orderCapabilitySchema = z.enum([
|
|
14
|
+
"order.cancel",
|
|
15
|
+
"order.process",
|
|
16
|
+
"order.fulfill",
|
|
17
|
+
"payment.succeed",
|
|
18
|
+
]);
|
|
19
|
+
export const orderReferenceSchema = z.string().regex(/^ORD-[0-9]{12}$/u);
|
|
20
|
+
export const contactEmailSchema = z.string().trim().max(320).email().toLowerCase();
|
|
21
|
+
export const orderCreateCommandSchema = z.strictObject({
|
|
22
|
+
contactEmail: contactEmailSchema,
|
|
23
|
+
idempotencyKey: idempotencyKeySchema,
|
|
24
|
+
});
|
|
25
|
+
export const orderCancelCommandSchema = z.strictObject({
|
|
26
|
+
idempotencyKey: idempotencyKeySchema,
|
|
27
|
+
reason: z.string().trim().min(1).max(240).default("Customer cancelled before payment."),
|
|
28
|
+
});
|
|
29
|
+
export const orderItemSnapshotSchema = z
|
|
30
|
+
.strictObject({
|
|
31
|
+
backorderedQuantity: z.number().int().safe().nonnegative(),
|
|
32
|
+
inventoryMode: z.enum(["tracked", "untracked"]),
|
|
33
|
+
lineTotal: moneySchema,
|
|
34
|
+
productName: z.string().trim().min(1).max(240),
|
|
35
|
+
productSlug: productSlugSchema,
|
|
36
|
+
quantity: z.number().int().safe().min(1).max(99),
|
|
37
|
+
reservedQuantity: z.number().int().safe().nonnegative(),
|
|
38
|
+
sku: z.string().trim().min(1).max(120).nullable(),
|
|
39
|
+
sourceVariantId: positiveIdentifierSchema,
|
|
40
|
+
unitPrice: moneySchema,
|
|
41
|
+
variantName: z.string().trim().min(1).max(160),
|
|
42
|
+
})
|
|
43
|
+
.superRefine((item, context) => {
|
|
44
|
+
const allocatedQuantity = item.reservedQuantity + item.backorderedQuantity;
|
|
45
|
+
const invalidTrackedAllocation = item.inventoryMode === "tracked" &&
|
|
46
|
+
(!Number.isSafeInteger(allocatedQuantity) || allocatedQuantity !== item.quantity);
|
|
47
|
+
const invalidUntrackedAllocation = item.inventoryMode === "untracked" &&
|
|
48
|
+
(item.reservedQuantity !== 0 || item.backorderedQuantity !== 0);
|
|
49
|
+
if (invalidTrackedAllocation || invalidUntrackedAllocation) {
|
|
50
|
+
context.addIssue({ code: "custom", message: "Order allocation must equal item quantity." });
|
|
51
|
+
}
|
|
52
|
+
let expectedLineTotal;
|
|
53
|
+
try {
|
|
54
|
+
expectedLineTotal = multiplyMoney(item.unitPrice, item.quantity);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
expectedLineTotal = undefined;
|
|
58
|
+
}
|
|
59
|
+
if (expectedLineTotal?.currency !== item.lineTotal.currency ||
|
|
60
|
+
expectedLineTotal.amountMinor !== item.lineTotal.amountMinor) {
|
|
61
|
+
context.addIssue({
|
|
62
|
+
code: "custom",
|
|
63
|
+
message: "Order line total must match its price snapshot.",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
export const orderSnapshotSchema = z
|
|
68
|
+
.strictObject({
|
|
69
|
+
contactEmail: contactEmailSchema,
|
|
70
|
+
createdAt: z.string().datetime({ offset: true }),
|
|
71
|
+
currency: currencyCodeSchema,
|
|
72
|
+
id: positiveIdentifierSchema,
|
|
73
|
+
items: z.array(orderItemSnapshotSchema).min(1).max(100),
|
|
74
|
+
merchandiseSubtotal: moneySchema,
|
|
75
|
+
reference: orderReferenceSchema,
|
|
76
|
+
status: orderStatusSchema,
|
|
77
|
+
})
|
|
78
|
+
.superRefine((order, context) => {
|
|
79
|
+
if (order.merchandiseSubtotal.currency !== order.currency) {
|
|
80
|
+
context.addIssue({ code: "custom", message: "Order currency and subtotal must match." });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
let total = { amountMinor: 0, currency: order.currency };
|
|
84
|
+
try {
|
|
85
|
+
for (const item of order.items)
|
|
86
|
+
total = addMoney(total, item.lineTotal);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
context.addIssue({ code: "custom", message: "Order item currencies must match." });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (total.amountMinor !== order.merchandiseSubtotal.amountMinor) {
|
|
93
|
+
context.addIssue({
|
|
94
|
+
code: "custom",
|
|
95
|
+
message: "Order subtotal must equal its item snapshots.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
export const ORDER_TRANSITIONS = Object.freeze([
|
|
100
|
+
{ capability: "order.cancel", from: "pending_payment", to: "cancelled" },
|
|
101
|
+
{ capability: "payment.succeed", from: "pending_payment", to: "paid" },
|
|
102
|
+
{ capability: "order.process", from: "paid", to: "processing" },
|
|
103
|
+
{ capability: "order.fulfill", from: "processing", to: "fulfilled" },
|
|
104
|
+
]);
|
|
105
|
+
export function guardOrderTransition(from, to, capabilities) {
|
|
106
|
+
return guardLifecycleTransition(ORDER_TRANSITIONS, { capabilities, from, to });
|
|
107
|
+
}
|
|
108
|
+
export function validateOrderTransitionTable() {
|
|
109
|
+
return validateLifecycleTransitionTable(ORDER_TRANSITIONS, "pending_payment", [
|
|
110
|
+
"cancelled",
|
|
111
|
+
"fulfilled",
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
export function createOrderItemSnapshot(line, allocation) {
|
|
115
|
+
const parsedLine = pricedCartLineSchema.parse(line);
|
|
116
|
+
return Object.freeze(orderItemSnapshotSchema.parse({
|
|
117
|
+
...allocation,
|
|
118
|
+
lineTotal: parsedLine.lineTotal,
|
|
119
|
+
productName: parsedLine.productName,
|
|
120
|
+
productSlug: parsedLine.productSlug,
|
|
121
|
+
quantity: parsedLine.quantity,
|
|
122
|
+
sku: parsedLine.sku,
|
|
123
|
+
sourceVariantId: parsedLine.variantId,
|
|
124
|
+
unitPrice: parsedLine.unitPrice,
|
|
125
|
+
variantName: parsedLine.variantName,
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
export function verifyOrderLineTotal(item) {
|
|
129
|
+
const parsed = orderItemSnapshotSchema.parse(item);
|
|
130
|
+
return multiplyMoney(parsed.unitPrice, parsed.quantity);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.js","sourceRoot":"","sources":["../src/order.ts"],"names":[],"mappings":"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"}
|