@tokenoftrust/storefront-runner 2.4.47 → 2.4.49
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/apps/storefront/migrations-apps/0016_scrappy_commerce_contract.sql +166 -0
- package/apps/storefront/src/lib/http/fetchTransport.ts +6 -1
- package/apps/storefront/src/lib/http/mcpServiceCall.ts +4 -1
- package/package.json +1 -1
- package/packages/public-runtime/fixtures/scrappy/orders-v1.json +847 -0
- package/packages/public-runtime/src/checkout-orders.ts +602 -16
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
-- Commerce orders, inbox/outbox, allocations, label purchases, and shipment audit.
|
|
2
|
+
-- Tenant and stage are on every row. Money is integer minor units.
|
|
3
|
+
-- The SQL directory is the apply set. One transaction per file.
|
|
4
|
+
CREATE TABLE `scrappy_commerce_orders` (
|
|
5
|
+
`tenant_id` text NOT NULL,
|
|
6
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
7
|
+
`order_id` text NOT NULL,
|
|
8
|
+
`source` text NOT NULL,
|
|
9
|
+
`source_order_id` text NOT NULL,
|
|
10
|
+
`currency` text NOT NULL,
|
|
11
|
+
`placed_at` text NOT NULL,
|
|
12
|
+
`payment_state` text NOT NULL CHECK (payment_state IN ('UNKNOWN', 'pending', 'authorized', 'captured', 'capture_unknown', 'voided', 'refund_requested', 'refunded', 'refund_unknown')),
|
|
13
|
+
`compliance_state` text NOT NULL CHECK (compliance_state IN ('UNKNOWN', 'pending', 'fresh', 'stale', 'unreadable', 'refused')),
|
|
14
|
+
`stock_state` text NOT NULL CHECK (stock_state IN ('UNKNOWN', 'unallocated', 'reserved', 'confirmed', 'released', 'expired')),
|
|
15
|
+
`fulfillment_state` text NOT NULL CHECK (fulfillment_state IN ('UNKNOWN', 'held', 'ready', 'handed_off', 'cancelled')),
|
|
16
|
+
`label_state` text NOT NULL CHECK (label_state IN ('UNKNOWN', 'none', 'intent', 'purchased', 'printed', 'void_requested', 'voided')),
|
|
17
|
+
`amount_minor` integer NOT NULL CHECK (amount_minor >= 0),
|
|
18
|
+
`event_version` integer NOT NULL CHECK (event_version >= 1),
|
|
19
|
+
PRIMARY KEY (`tenant_id`, `stage`, `order_id`)
|
|
20
|
+
);
|
|
21
|
+
--> statement-breakpoint
|
|
22
|
+
CREATE UNIQUE INDEX `uq_scrappy_commerce_source_order`
|
|
23
|
+
ON `scrappy_commerce_orders` (`tenant_id`, `stage`, `source`, `source_order_id`);
|
|
24
|
+
--> statement-breakpoint
|
|
25
|
+
CREATE TABLE `scrappy_order_addresses` (
|
|
26
|
+
`tenant_id` text NOT NULL,
|
|
27
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
28
|
+
`order_id` text NOT NULL,
|
|
29
|
+
`address_json` text NOT NULL,
|
|
30
|
+
PRIMARY KEY (`tenant_id`, `stage`, `order_id`),
|
|
31
|
+
FOREIGN KEY (`tenant_id`, `stage`, `order_id`) REFERENCES `scrappy_commerce_orders` (`tenant_id`, `stage`, `order_id`)
|
|
32
|
+
);
|
|
33
|
+
--> statement-breakpoint
|
|
34
|
+
CREATE TABLE `scrappy_commerce_inbox` (
|
|
35
|
+
`tenant_id` text NOT NULL,
|
|
36
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
37
|
+
`source` text NOT NULL,
|
|
38
|
+
`source_event_id` text NOT NULL,
|
|
39
|
+
`event_version` integer NOT NULL CHECK (event_version >= 1),
|
|
40
|
+
`idempotency_key` text NOT NULL,
|
|
41
|
+
`payload_digest` text NOT NULL,
|
|
42
|
+
`received_at` text NOT NULL,
|
|
43
|
+
PRIMARY KEY (`tenant_id`, `stage`, `source`, `source_event_id`)
|
|
44
|
+
);
|
|
45
|
+
--> statement-breakpoint
|
|
46
|
+
CREATE UNIQUE INDEX `uq_scrappy_inbox_idempotency`
|
|
47
|
+
ON `scrappy_commerce_inbox` (`tenant_id`, `stage`, `idempotency_key`);
|
|
48
|
+
--> statement-breakpoint
|
|
49
|
+
CREATE TABLE `scrappy_commerce_outbox` (
|
|
50
|
+
`outbox_id` text NOT NULL,
|
|
51
|
+
`tenant_id` text NOT NULL,
|
|
52
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
53
|
+
`order_id` text NOT NULL,
|
|
54
|
+
`source` text NOT NULL,
|
|
55
|
+
`source_event_id` text NOT NULL,
|
|
56
|
+
`event_version` integer NOT NULL CHECK (event_version >= 1),
|
|
57
|
+
`event_type` text NOT NULL,
|
|
58
|
+
`payload` text NOT NULL,
|
|
59
|
+
`available_at` text NOT NULL,
|
|
60
|
+
`attempt_count` integer NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
|
|
61
|
+
`state` text NOT NULL CHECK (state IN ('pending', 'delivered', 'dead')),
|
|
62
|
+
PRIMARY KEY (`outbox_id`),
|
|
63
|
+
UNIQUE (`tenant_id`, `stage`, `source`, `source_event_id`)
|
|
64
|
+
);
|
|
65
|
+
--> statement-breakpoint
|
|
66
|
+
CREATE INDEX `idx_scrappy_outbox_due`
|
|
67
|
+
ON `scrappy_commerce_outbox` (`state`, `available_at`);
|
|
68
|
+
--> statement-breakpoint
|
|
69
|
+
CREATE TABLE `scrappy_allocations` (
|
|
70
|
+
`tenant_id` text NOT NULL,
|
|
71
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
72
|
+
`order_id` text NOT NULL,
|
|
73
|
+
`sku` text NOT NULL,
|
|
74
|
+
`location_id` text NOT NULL,
|
|
75
|
+
`quantity` integer NOT NULL CHECK (quantity > 0),
|
|
76
|
+
`state` text NOT NULL CHECK (state IN ('reserved', 'confirmed', 'released', 'expired')),
|
|
77
|
+
PRIMARY KEY (`tenant_id`, `stage`, `order_id`, `sku`, `location_id`),
|
|
78
|
+
FOREIGN KEY (`tenant_id`, `stage`, `order_id`) REFERENCES `scrappy_commerce_orders` (`tenant_id`, `stage`, `order_id`)
|
|
79
|
+
);
|
|
80
|
+
--> statement-breakpoint
|
|
81
|
+
CREATE TABLE `scrappy_final_cart_authorizations` (
|
|
82
|
+
`tenant_id` text NOT NULL,
|
|
83
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
84
|
+
`authorization_id` text NOT NULL,
|
|
85
|
+
`cart_digest` text NOT NULL,
|
|
86
|
+
`expires_at` text NOT NULL,
|
|
87
|
+
`state` text NOT NULL CHECK (state IN ('active', 'consumed', 'expired', 'denied')),
|
|
88
|
+
PRIMARY KEY (`tenant_id`, `stage`, `authorization_id`)
|
|
89
|
+
);
|
|
90
|
+
--> statement-breakpoint
|
|
91
|
+
CREATE UNIQUE INDEX `uq_scrappy_active_final_cart`
|
|
92
|
+
ON `scrappy_final_cart_authorizations` (`tenant_id`, `stage`, `cart_digest`)
|
|
93
|
+
WHERE `state` = 'active';
|
|
94
|
+
--> statement-breakpoint
|
|
95
|
+
CREATE TABLE `scrappy_provider_operations` (
|
|
96
|
+
`tenant_id` text NOT NULL,
|
|
97
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
98
|
+
`provider` text NOT NULL,
|
|
99
|
+
`purchase_id` text NOT NULL,
|
|
100
|
+
`order_id` text NOT NULL,
|
|
101
|
+
`kind` text NOT NULL CHECK (kind IN ('label_purchase', 'payment_capture', 'refund')),
|
|
102
|
+
`outcome` text NOT NULL CHECK (outcome IN ('intent', 'accepted', 'unknown', 'voided', 'refunded')),
|
|
103
|
+
`amount_minor` integer NOT NULL CHECK (amount_minor >= 0),
|
|
104
|
+
PRIMARY KEY (`tenant_id`, `stage`, `provider`, `purchase_id`),
|
|
105
|
+
FOREIGN KEY (`tenant_id`, `stage`, `order_id`) REFERENCES `scrappy_commerce_orders` (`tenant_id`, `stage`, `order_id`)
|
|
106
|
+
);
|
|
107
|
+
--> statement-breakpoint
|
|
108
|
+
CREATE UNIQUE INDEX `uq_scrappy_open_label_purchase`
|
|
109
|
+
ON `scrappy_provider_operations` (`tenant_id`, `stage`, `order_id`)
|
|
110
|
+
WHERE `kind` = 'label_purchase' AND `outcome` IN ('intent', 'accepted', 'unknown');
|
|
111
|
+
--> statement-breakpoint
|
|
112
|
+
CREATE TABLE `scrappy_shipments` (
|
|
113
|
+
`tenant_id` text NOT NULL,
|
|
114
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
115
|
+
`order_id` text NOT NULL,
|
|
116
|
+
`scope` text NOT NULL CHECK (scope = 'whole-order'),
|
|
117
|
+
`label_purchase_state` text NOT NULL CHECK (label_purchase_state IN ('none', 'intent', 'purchased', 'void_requested', 'voided', 'unknown')),
|
|
118
|
+
`label_print_state` text NOT NULL CHECK (label_print_state IN ('none', 'printed')),
|
|
119
|
+
`handoff_state` text NOT NULL CHECK (handoff_state IN ('none', 'handed_off', 'unknown')),
|
|
120
|
+
CHECK (handoff_state = 'none' OR label_purchase_state = 'purchased'),
|
|
121
|
+
CHECK (label_print_state = 'none' OR label_purchase_state = 'purchased'),
|
|
122
|
+
PRIMARY KEY (`tenant_id`, `stage`, `order_id`),
|
|
123
|
+
FOREIGN KEY (`tenant_id`, `stage`, `order_id`) REFERENCES `scrappy_commerce_orders` (`tenant_id`, `stage`, `order_id`)
|
|
124
|
+
);
|
|
125
|
+
--> statement-breakpoint
|
|
126
|
+
CREATE TABLE `scrappy_shipment_audit` (
|
|
127
|
+
`audit_id` text NOT NULL,
|
|
128
|
+
`tenant_id` text NOT NULL,
|
|
129
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
130
|
+
`order_id` text NOT NULL,
|
|
131
|
+
`at` text NOT NULL,
|
|
132
|
+
`actor_id` text NOT NULL,
|
|
133
|
+
`kind` text NOT NULL,
|
|
134
|
+
`from_state` text NOT NULL,
|
|
135
|
+
`to_state` text NOT NULL,
|
|
136
|
+
PRIMARY KEY (`audit_id`),
|
|
137
|
+
FOREIGN KEY (`tenant_id`, `stage`, `order_id`) REFERENCES `scrappy_commerce_orders` (`tenant_id`, `stage`, `order_id`)
|
|
138
|
+
);
|
|
139
|
+
--> statement-breakpoint
|
|
140
|
+
CREATE TRIGGER `scrappy_shipment_audit_no_update`
|
|
141
|
+
BEFORE UPDATE ON `scrappy_shipment_audit`
|
|
142
|
+
BEGIN
|
|
143
|
+
SELECT RAISE(ABORT, 'append-only');
|
|
144
|
+
END;
|
|
145
|
+
--> statement-breakpoint
|
|
146
|
+
CREATE TRIGGER `scrappy_shipment_audit_no_delete`
|
|
147
|
+
BEFORE DELETE ON `scrappy_shipment_audit`
|
|
148
|
+
BEGIN
|
|
149
|
+
SELECT RAISE(ABORT, 'append-only');
|
|
150
|
+
END;
|
|
151
|
+
--> statement-breakpoint
|
|
152
|
+
CREATE TABLE `scrappy_caller_replay` (
|
|
153
|
+
`tenant_id` text NOT NULL,
|
|
154
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
155
|
+
`issuer` text NOT NULL,
|
|
156
|
+
`jti` text NOT NULL,
|
|
157
|
+
`seen_at` text NOT NULL,
|
|
158
|
+
PRIMARY KEY (`tenant_id`, `stage`, `issuer`, `jti`)
|
|
159
|
+
);
|
|
160
|
+
--> statement-breakpoint
|
|
161
|
+
CREATE TABLE `scrappy_sweep_cursor` (
|
|
162
|
+
`tenant_id` text NOT NULL,
|
|
163
|
+
`stage` text NOT NULL CHECK (stage IN ('preview', 'publication')),
|
|
164
|
+
`cursor` text NOT NULL,
|
|
165
|
+
PRIMARY KEY (`tenant_id`, `stage`)
|
|
166
|
+
);
|
|
@@ -45,7 +45,12 @@ export class FetchHttpTransport implements HttpTransport, HttpGetTransport {
|
|
|
45
45
|
async post(url: string, headers: Record<string, string>, body: unknown): Promise<HttpResponseLike> {
|
|
46
46
|
const res = await fetch(url, {
|
|
47
47
|
method: "POST",
|
|
48
|
-
|
|
48
|
+
// `post()` always JSON.stringify()s the body below, so every call sends JSON —
|
|
49
|
+
// declare it by default rather than leaving a caller that forgets its own
|
|
50
|
+
// `content-type` to silently send an unparseable body (the receiving server's
|
|
51
|
+
// JSON body-parser skips a request with no/wrong content-type and sees an empty
|
|
52
|
+
// body). A per-call or per-transport header of the same name still wins.
|
|
53
|
+
headers: { "content-type": "application/json", ...this.defaultHeaders, ...headers },
|
|
49
54
|
body: JSON.stringify(body),
|
|
50
55
|
signal: this.signal(),
|
|
51
56
|
});
|
|
@@ -80,6 +80,9 @@ export async function callMcpService(req: McpServiceRequest): Promise<McpService
|
|
|
80
80
|
);
|
|
81
81
|
return { kind: "misconfigured", status: res.status, reason };
|
|
82
82
|
}
|
|
83
|
-
if (res.status < 200 || res.status >= 300)
|
|
83
|
+
if (res.status < 200 || res.status >= 300) {
|
|
84
|
+
console.error(`[mcp-service-seam] ${req.method} ${req.path} answered ${res.status}`);
|
|
85
|
+
return { kind: "http-error", status: res.status };
|
|
86
|
+
}
|
|
84
87
|
return { kind: "ok", status: res.status, json: () => res.json() };
|
|
85
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.49",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|