@reventlessdev/online-shop-hybrid-seed 1.0.0-alpha.2
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/CHANGELOG.md +10 -0
- package/LICENSE +202 -0
- package/lib/bs/.compiler.log +2 -0
- package/lib/bs/OnlineShopHybridSeed.cmi +0 -0
- package/lib/bs/OnlineShopHybridSeed.cmj +0 -0
- package/lib/bs/OnlineShopHybridSeed.cmt +0 -0
- package/lib/bs/OnlineShopHybridSeed.mlmap +4 -0
- package/lib/bs/build.ninja +0 -0
- package/lib/bs/compiler-info.json +8 -0
- package/lib/bs/src/DemoCommands-OnlineShopHybridSeed.cmi +0 -0
- package/lib/bs/src/DemoCommands-OnlineShopHybridSeed.cmj +0 -0
- package/lib/bs/src/DemoCommands-OnlineShopHybridSeed.cmt +0 -0
- package/lib/bs/src/DemoCommands.ast +0 -0
- package/lib/bs/src/DemoCommands.res +154 -0
- package/lib/bs/src/DemoCommands.res.mjs +388 -0
- package/lib/bs/src/DemoData-OnlineShopHybridSeed.cmi +0 -0
- package/lib/bs/src/DemoData-OnlineShopHybridSeed.cmj +0 -0
- package/lib/bs/src/DemoData-OnlineShopHybridSeed.cmt +0 -0
- package/lib/bs/src/DemoData.ast +0 -0
- package/lib/bs/src/DemoData.res +307 -0
- package/lib/bs/src/DemoData.res.mjs +481 -0
- package/lib/bs/src/HybridSeedData-OnlineShopHybridSeed.cmi +0 -0
- package/lib/bs/src/HybridSeedData-OnlineShopHybridSeed.cmj +0 -0
- package/lib/bs/src/HybridSeedData-OnlineShopHybridSeed.cmt +0 -0
- package/lib/bs/src/HybridSeedData.ast +0 -0
- package/lib/bs/src/HybridSeedData.res +418 -0
- package/lib/bs/src/HybridSeedData.res.mjs +317 -0
- package/lib/ocaml/.compiler.log +2 -0
- package/lib/ocaml/DemoCommands-OnlineShopHybridSeed.cmi +0 -0
- package/lib/ocaml/DemoCommands-OnlineShopHybridSeed.cmj +0 -0
- package/lib/ocaml/DemoCommands-OnlineShopHybridSeed.cmt +0 -0
- package/lib/ocaml/DemoCommands.ast +0 -0
- package/lib/ocaml/DemoCommands.res +154 -0
- package/lib/ocaml/DemoData-OnlineShopHybridSeed.cmi +0 -0
- package/lib/ocaml/DemoData-OnlineShopHybridSeed.cmj +0 -0
- package/lib/ocaml/DemoData-OnlineShopHybridSeed.cmt +0 -0
- package/lib/ocaml/DemoData.ast +0 -0
- package/lib/ocaml/DemoData.res +307 -0
- package/lib/ocaml/HybridSeedData-OnlineShopHybridSeed.cmi +0 -0
- package/lib/ocaml/HybridSeedData-OnlineShopHybridSeed.cmj +0 -0
- package/lib/ocaml/HybridSeedData-OnlineShopHybridSeed.cmt +0 -0
- package/lib/ocaml/HybridSeedData.ast +0 -0
- package/lib/ocaml/HybridSeedData.res +418 -0
- package/lib/ocaml/OnlineShopHybridSeed.cmi +0 -0
- package/lib/ocaml/OnlineShopHybridSeed.cmj +0 -0
- package/lib/ocaml/OnlineShopHybridSeed.cmt +0 -0
- package/lib/ocaml/OnlineShopHybridSeed.mlmap +4 -0
- package/package.json +34 -0
- package/rescript.json +27 -0
- package/src/DemoCommands.res +154 -0
- package/src/DemoCommands.res.mjs +388 -0
- package/src/DemoData.res +307 -0
- package/src/DemoData.res.mjs +481 -0
- package/src/HybridSeedData.res +418 -0
- package/src/HybridSeedData.res.mjs +317 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
4
|
+
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
7
|
+
import * as Seed$ReventlessSeed from "@reventlessdev/reventless-seed/src/Seed.res.mjs";
|
|
8
|
+
import * as Seed_Client$ReventlessSeed from "@reventlessdev/reventless-seed/src/Seed_Client.res.mjs";
|
|
9
|
+
import * as Seed_Runner$ReventlessSeed from "@reventlessdev/reventless-seed/src/Seed_Runner.res.mjs";
|
|
10
|
+
import * as Seed_Upload$ReventlessSeed from "@reventlessdev/reventless-seed/src/Seed_Upload.res.mjs";
|
|
11
|
+
import * as DemoData$OnlineShopHybridSeed from "./DemoData.res.mjs";
|
|
12
|
+
import * as DemoCommands$OnlineShopHybridSeed from "./DemoCommands.res.mjs";
|
|
13
|
+
|
|
14
|
+
let views = [
|
|
15
|
+
{
|
|
16
|
+
TAG: "Seeded",
|
|
17
|
+
_0: "Catalog_Categories"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
TAG: "Seeded",
|
|
21
|
+
_0: "Catalog_Products"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
TAG: "Seeded",
|
|
25
|
+
_0: "Catalog_ProductDemands"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
TAG: "Seeded",
|
|
29
|
+
_0: "Catalog_ImportProductAudits"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
TAG: "Seeded",
|
|
33
|
+
_0: "Ordering_AvailableProducts"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
TAG: "Seeded",
|
|
37
|
+
_0: "Ordering_Orders"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
TAG: "Seeded",
|
|
41
|
+
_0: "Ordering_Customers"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
TAG: "Seeded",
|
|
45
|
+
_0: "Ordering_AutoShipOrderTodos"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
TAG: "Seeded",
|
|
49
|
+
_0: "Ordering_SendOrderConfirmationTodos"
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
async function seedCategories(client) {
|
|
54
|
+
await Seed_Client$ReventlessSeed.sendAll(client, DemoData$OnlineShopHybridSeed.categories.map(c => DemoCommands$OnlineShopHybridSeed.addCategory({
|
|
55
|
+
TAG: "AddCategory",
|
|
56
|
+
categoryId: c.id,
|
|
57
|
+
name: c.name
|
|
58
|
+
})));
|
|
59
|
+
return Seed_Runner$ReventlessSeed.report(`categories: ` + DemoData$OnlineShopHybridSeed.categories.length.toString() + ` added`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function uploadProductImages(products, client, uploadEndpoint) {
|
|
63
|
+
let out = [];
|
|
64
|
+
for (let i = 0, i_finish = products.length; i < i_finish; ++i) {
|
|
65
|
+
let p = products[i];
|
|
66
|
+
if (p !== undefined) {
|
|
67
|
+
let svg = DemoData$OnlineShopHybridSeed.productSvg(p.name, i);
|
|
68
|
+
let servedRef = await Seed_Upload$ReventlessSeed.uploadAsset(uploadEndpoint, svg, p.id + `.svg`, "image/svg+xml", Seed_Client$ReventlessSeed.currentToken(client));
|
|
69
|
+
if (servedRef.TAG === "Ok") {
|
|
70
|
+
out.push({
|
|
71
|
+
id: p.id,
|
|
72
|
+
name: p.name,
|
|
73
|
+
description: p.description,
|
|
74
|
+
price: p.price,
|
|
75
|
+
imageUrl: servedRef._0,
|
|
76
|
+
categoryId: p.categoryId
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
throw {
|
|
80
|
+
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
81
|
+
_1: `product image upload for ` + p.id + ` failed: ` + servedRef._0,
|
|
82
|
+
Error: new Error()
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
Seed_Runner$ReventlessSeed.report(`product images: ` + out.length.toString() + ` uploaded to the served bucket`);
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function seedProducts(products, client) {
|
|
92
|
+
await Seed_Client$ReventlessSeed.sendAll(client, products.map(p => DemoCommands$OnlineShopHybridSeed.addProduct({
|
|
93
|
+
TAG: "AddProduct",
|
|
94
|
+
productId: p.id,
|
|
95
|
+
name: p.name,
|
|
96
|
+
description: p.description,
|
|
97
|
+
price: p.price,
|
|
98
|
+
imageUrl: p.imageUrl,
|
|
99
|
+
categoryId: p.categoryId
|
|
100
|
+
})));
|
|
101
|
+
return Seed_Runner$ReventlessSeed.report(`products: ` + products.length.toString() + ` added`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function seedCatalogEdits(products, client) {
|
|
105
|
+
let repriced = DemoData$OnlineShopHybridSeed.repricedProducts(products);
|
|
106
|
+
await Seed_Client$ReventlessSeed.sendAll(client, repriced.map(p => DemoCommands$OnlineShopHybridSeed.changeProductPrice({
|
|
107
|
+
TAG: "ChangeProductPrice",
|
|
108
|
+
productId: p.id,
|
|
109
|
+
price: DemoData$OnlineShopHybridSeed.discountedPrice(p)
|
|
110
|
+
})));
|
|
111
|
+
let redescribed = DemoData$OnlineShopHybridSeed.redescribedProducts(products);
|
|
112
|
+
await Seed_Client$ReventlessSeed.sendAll(client, redescribed.map(p => DemoCommands$OnlineShopHybridSeed.changeProductDescription({
|
|
113
|
+
TAG: "ChangeProductDescription",
|
|
114
|
+
productId: p.id,
|
|
115
|
+
description: p.description + ` Updated listing copy.`
|
|
116
|
+
})));
|
|
117
|
+
await Seed_Client$ReventlessSeed.sendAll(client, [DemoCommands$OnlineShopHybridSeed.renameCategory({
|
|
118
|
+
TAG: "RenameCategory",
|
|
119
|
+
categoryId: DemoData$OnlineShopHybridSeed.renamedCategoryId,
|
|
120
|
+
name: DemoData$OnlineShopHybridSeed.renamedCategoryName
|
|
121
|
+
})]);
|
|
122
|
+
let archived = DemoData$OnlineShopHybridSeed.categories.filter(c => c.archive);
|
|
123
|
+
await Seed_Client$ReventlessSeed.sendAll(client, archived.map(c => DemoCommands$OnlineShopHybridSeed.archiveCategory({
|
|
124
|
+
TAG: "ArchiveCategory",
|
|
125
|
+
categoryId: c.id
|
|
126
|
+
})));
|
|
127
|
+
return Seed_Runner$ReventlessSeed.report(`catalog edits: ` + repriced.length.toString() + ` repriced, ` + redescribed.length.toString() + ` redescribed, 1 renamed, ` + archived.length.toString() + ` archived`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function seedSupplierFeed(client) {
|
|
131
|
+
for (let i = 0, i_finish = DemoData$OnlineShopHybridSeed.supplierFeed.length; i < i_finish; ++i) {
|
|
132
|
+
let row = DemoData$OnlineShopHybridSeed.supplierFeed[i];
|
|
133
|
+
if (row !== undefined) {
|
|
134
|
+
await Seed_Client$ReventlessSeed.send(client, DemoCommands$OnlineShopHybridSeed.importProduct(row), ["TranslationFailed"]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
let audits = await Seed_Client$ReventlessSeed.queryAllNodes(client, "Catalog_ImportProductAudits", "status");
|
|
138
|
+
let countWith = status => audits.filter(a => Primitive_object.equal(Seed_Client$ReventlessSeed.nodeString(a, "status"), status)).length;
|
|
139
|
+
let successes = countWith("Success");
|
|
140
|
+
let failures = countWith("Failure");
|
|
141
|
+
if (successes !== DemoData$OnlineShopHybridSeed.expectedImportSuccesses || failures !== DemoData$OnlineShopHybridSeed.expectedImportFailures) {
|
|
142
|
+
throw {
|
|
143
|
+
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
144
|
+
_1: `supplier feed: expected ` + DemoData$OnlineShopHybridSeed.expectedImportSuccesses.toString() + ` Success / ` + DemoData$OnlineShopHybridSeed.expectedImportFailures.toString() + ` Failure audit rows, got ` + successes.toString() + `/` + failures.toString(),
|
|
145
|
+
Error: new Error()
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return Seed_Runner$ReventlessSeed.report(`supplier feed: ` + successes.toString() + ` imported, ` + failures.toString() + ` rejected (both shown in the audit view)`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function seedCustomers(customers, client) {
|
|
152
|
+
await Seed_Client$ReventlessSeed.sendAll(client, customers.map(c => DemoCommands$OnlineShopHybridSeed.customer(c.id, {
|
|
153
|
+
TAG: "Register",
|
|
154
|
+
email: c.email,
|
|
155
|
+
address: c.address
|
|
156
|
+
})));
|
|
157
|
+
await Seed_Client$ReventlessSeed.sendAll(client, customers.map(c => DemoCommands$OnlineShopHybridSeed.customer(c.id, {
|
|
158
|
+
TAG: "SetLocation",
|
|
159
|
+
location: {
|
|
160
|
+
lat: c.lat,
|
|
161
|
+
lng: c.lng
|
|
162
|
+
}
|
|
163
|
+
})));
|
|
164
|
+
let moved = DemoData$OnlineShopHybridSeed.movedCustomers(customers);
|
|
165
|
+
await Seed_Client$ReventlessSeed.sendAll(client, moved.map(c => DemoCommands$OnlineShopHybridSeed.customer(c.id, {
|
|
166
|
+
TAG: "UpdateAddress",
|
|
167
|
+
address: DemoData$OnlineShopHybridSeed.newAddress()
|
|
168
|
+
})));
|
|
169
|
+
return Seed_Runner$ReventlessSeed.report(`customers: ` + customers.length.toString() + ` registered, ` + moved.length.toString() + ` moved`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function seedOrders(orders, client) {
|
|
173
|
+
for (let i = 0, i_finish = orders.length; i < i_finish; ++i) {
|
|
174
|
+
let order = orders[i];
|
|
175
|
+
if (order !== undefined) {
|
|
176
|
+
await Seed_Client$ReventlessSeed.send(client, DemoCommands$OnlineShopHybridSeed.placeOrder({
|
|
177
|
+
TAG: "PlaceOrder",
|
|
178
|
+
orderId: order.id,
|
|
179
|
+
customerId: order.customerId,
|
|
180
|
+
productIds: order.productIds,
|
|
181
|
+
shippingMethod: order.shippingMethod
|
|
182
|
+
}), undefined);
|
|
183
|
+
if ((i + 1 | 0) % 50 === 0) {
|
|
184
|
+
Seed_Runner$ReventlessSeed.report(`orders: ` + (i + 1 | 0).toString() + `/` + orders.length.toString() + ` placed`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
let countMethod = method => orders.filter(o => o.shippingMethod === method).length;
|
|
189
|
+
return Seed_Runner$ReventlessSeed.report(`orders: ` + orders.length.toString() + ` placed (Standard ` + countMethod("Standard").toString() + `, Express ` + countMethod("Express").toString() + `, Pickup ` + countMethod("Pickup").toString() + `) — Express placements were auto-shipped on arrival`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function dispatchStandardBatch(orders, client) {
|
|
193
|
+
let dispatched = DemoData$OnlineShopHybridSeed.batchDispatched(orders);
|
|
194
|
+
await Seed_Client$ReventlessSeed.sendAll(client, dispatched.map(o => DemoCommands$OnlineShopHybridSeed.shipOrder({
|
|
195
|
+
TAG: "ShipOrder",
|
|
196
|
+
orderId: o.id
|
|
197
|
+
})));
|
|
198
|
+
let standardTotal = orders.filter(o => o.shippingMethod === "Standard").length;
|
|
199
|
+
Seed_Runner$ReventlessSeed.report(`batch dispatch: ` + dispatched.length.toString() + `/` + standardTotal.toString() + ` Standard orders shipped, ` + (standardTotal - dispatched.length | 0).toString() + ` left pending`);
|
|
200
|
+
return dispatched.map(o => o.id);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function seedCancellations(orders, client, dispatched) {
|
|
204
|
+
let cancellable = DemoData$OnlineShopHybridSeed.cancellable(orders, dispatched);
|
|
205
|
+
let targets = DemoData$OnlineShopHybridSeed.cancelled(cancellable);
|
|
206
|
+
await Seed_Client$ReventlessSeed.sendAll(client, targets.map(o => DemoCommands$OnlineShopHybridSeed.cancelOrder({
|
|
207
|
+
TAG: "CancelOrder",
|
|
208
|
+
orderId: o.id
|
|
209
|
+
})));
|
|
210
|
+
return Seed_Runner$ReventlessSeed.report(`cancellations: ` + targets.length.toString() + ` of ` + cancellable.length.toString() + ` cancellable orders cancelled`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function seedDeactivations(customers, client) {
|
|
214
|
+
let targets = DemoData$OnlineShopHybridSeed.deactivatedCustomers(customers);
|
|
215
|
+
await Seed_Client$ReventlessSeed.sendAll(client, targets.map(c => DemoCommands$OnlineShopHybridSeed.customer(c.id, "Deactivate")));
|
|
216
|
+
return Seed_Runner$ReventlessSeed.report(`customers: ` + targets.length.toString() + ` deactivated`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function summarise(client, counts) {
|
|
220
|
+
let orders = await Seed_Client$ReventlessSeed.queryAllNodes(client, "Ordering_Orders", "status shippingMethod");
|
|
221
|
+
let statuses = [
|
|
222
|
+
"Placed",
|
|
223
|
+
"Shipped",
|
|
224
|
+
"Cancelled"
|
|
225
|
+
];
|
|
226
|
+
let methods = [
|
|
227
|
+
"Standard",
|
|
228
|
+
"Express",
|
|
229
|
+
"Pickup"
|
|
230
|
+
];
|
|
231
|
+
let countCell = (status, method) => orders.filter(o => {
|
|
232
|
+
if (Primitive_object.equal(Seed_Client$ReventlessSeed.nodeString(o, "status"), status)) {
|
|
233
|
+
return Primitive_object.equal(Seed_Client$ReventlessSeed.nodeString(o, "shippingMethod"), method);
|
|
234
|
+
} else {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
}).length;
|
|
238
|
+
let countStatus = status => orders.filter(o => Primitive_object.equal(Seed_Client$ReventlessSeed.nodeString(o, "status"), status)).length;
|
|
239
|
+
let demand = await Seed_Client$ReventlessSeed.queryAllNodes(client, "Catalog_ProductDemands", "name orderCount");
|
|
240
|
+
let orderCountOf = node => {
|
|
241
|
+
let match = Seed_Client$ReventlessSeed.field(node, "orderCount");
|
|
242
|
+
if (typeof match === "number") {
|
|
243
|
+
return match | 0;
|
|
244
|
+
} else {
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
let ranked = demand.toSorted((a, b) => Primitive_int.compare(orderCountOf(b), orderCountOf(a)));
|
|
249
|
+
let withDemand = ranked.filter(n => orderCountOf(n) > 0);
|
|
250
|
+
let head = ranked.slice(0, 3).map(n => Stdlib_Option.getOr(Seed_Client$ReventlessSeed.nodeString(n, "name"), "?") + ` (` + orderCountOf(n).toString() + `)`).join(", ");
|
|
251
|
+
Seed_Runner$ReventlessSeed.heading("Seeded:");
|
|
252
|
+
console.log(` order status: ` + statuses.map(s => s + ` ` + countStatus(s).toString()).join(", "));
|
|
253
|
+
console.log(` demand head: ` + head);
|
|
254
|
+
console.log(` demand spread: ` + withDemand.length.toString() + `/` + ranked.length.toString() + ` products ordered, tail min ` + Stdlib_Option.mapOr(Stdlib_Array.last(withDemand), 0, orderCountOf).toString());
|
|
255
|
+
console.log("");
|
|
256
|
+
console.log(" status × shippingMethod:");
|
|
257
|
+
console.log(` ` + " ".padEnd(10, " ") + methods.map(m => m.padStart(10, " ")).join(""));
|
|
258
|
+
statuses.forEach(status => {
|
|
259
|
+
console.log(` ` + status.padEnd(10, " ") + methods.map(m => countCell(status, m).toString().padStart(10, " ")).join(""));
|
|
260
|
+
});
|
|
261
|
+
let observedStatuses = statuses.filter(s => countStatus(s) > 0);
|
|
262
|
+
let spreadWarning = observedStatuses.length < 3 ? [`the board shows only ` + observedStatuses.length.toString() + ` of the 3 order statuses (` + observedStatuses.join(", ") + `) — the shipping-method mix or the batch-dispatch share needs adjusting.`] : [];
|
|
263
|
+
return Seed_Runner$ReventlessSeed.warn(spreadWarning.concat(Seed_Runner$ReventlessSeed.unfillableWarnings(views, counts)));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async function run(connection, productCount, customerCount, orderCount) {
|
|
267
|
+
let client = connection.client;
|
|
268
|
+
let built = DemoData$OnlineShopHybridSeed.buildProducts(productCount, undefined);
|
|
269
|
+
let products = connection.uploadEndpoint === "" ? (Seed_Runner$ReventlessSeed.report("product images: skipped (no upload endpoint / SEED_SKIP_UPLOADS) — imageUrl left empty"), built) : await uploadProductImages(built, client, connection.uploadEndpoint);
|
|
270
|
+
let customers = DemoData$OnlineShopHybridSeed.buildCustomers(customerCount, undefined);
|
|
271
|
+
let orders = DemoData$OnlineShopHybridSeed.buildOrders(products, customers, orderCount, undefined);
|
|
272
|
+
await seedCategories(client);
|
|
273
|
+
await seedProducts(products, client);
|
|
274
|
+
await seedCatalogEdits(products, client);
|
|
275
|
+
await seedSupplierFeed(client);
|
|
276
|
+
await seedCustomers(customers, client);
|
|
277
|
+
let expected = products.map(p => p.id).concat(DemoData$OnlineShopHybridSeed.importedSkus);
|
|
278
|
+
let available = await Seed_Client$ReventlessSeed.waitForIds(client, "Ordering_AvailableProductsByIds", expected, undefined);
|
|
279
|
+
Seed_Runner$ReventlessSeed.report(`ordering: ` + available.toString() + ` products available`);
|
|
280
|
+
await seedOrders(orders, client);
|
|
281
|
+
let dispatched = await dispatchStandardBatch(orders, client);
|
|
282
|
+
await seedCancellations(orders, client, dispatched);
|
|
283
|
+
await seedDeactivations(customers, client);
|
|
284
|
+
let counts = await Seed_Runner$ReventlessSeed.verifyViews(client, views);
|
|
285
|
+
return await summarise(client, counts);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
let dataSets = [
|
|
289
|
+
{
|
|
290
|
+
name: "full",
|
|
291
|
+
label: `full — ` + DemoData$OnlineShopHybridSeed.productCount.toString() + ` products, ` + DemoData$OnlineShopHybridSeed.customerCount.toString() + ` customers, ` + DemoData$OnlineShopHybridSeed.orderCount.toString() + ` orders`,
|
|
292
|
+
seed: connection => run(connection, DemoData$OnlineShopHybridSeed.productCount, DemoData$OnlineShopHybridSeed.customerCount, DemoData$OnlineShopHybridSeed.orderCount)
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "sample",
|
|
296
|
+
label: "sample — 16 products, 8 customers, 40 orders",
|
|
297
|
+
seed: connection => run(connection, 16, 8, 40)
|
|
298
|
+
}
|
|
299
|
+
];
|
|
300
|
+
|
|
301
|
+
export {
|
|
302
|
+
views,
|
|
303
|
+
seedCategories,
|
|
304
|
+
uploadProductImages,
|
|
305
|
+
seedProducts,
|
|
306
|
+
seedCatalogEdits,
|
|
307
|
+
seedSupplierFeed,
|
|
308
|
+
seedCustomers,
|
|
309
|
+
seedOrders,
|
|
310
|
+
dispatchStandardBatch,
|
|
311
|
+
seedCancellations,
|
|
312
|
+
seedDeactivations,
|
|
313
|
+
summarise,
|
|
314
|
+
run,
|
|
315
|
+
dataSets,
|
|
316
|
+
}
|
|
317
|
+
/* dataSets Not a pure module */
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Adapter: online-shop-hybrid command values → GraphQL mutations.
|
|
2
|
+
//
|
|
3
|
+
// This is the only place that knows how this example's commands are exposed on
|
|
4
|
+
// the API — the mutation field names and how each variant's payload maps onto
|
|
5
|
+
// arguments. Everything above it works in plugin command types; everything
|
|
6
|
+
// below it (`ReventlessSeed`) works in generic mutations.
|
|
7
|
+
//
|
|
8
|
+
// Each encoder pattern-matches the real command variant, so a renamed field or
|
|
9
|
+
// a new payload member is a compile error here rather than a rejected mutation
|
|
10
|
+
// at seed time. That is the whole point of routing the seed through typed
|
|
11
|
+
// commands instead of hand-written GraphQL strings.
|
|
12
|
+
|
|
13
|
+
open ReventlessSeed
|
|
14
|
+
|
|
15
|
+
// Mutation fields are `<PluginName>_<CommandVariant>`; aggregates additionally
|
|
16
|
+
// carry the entity id as a separate `id` argument.
|
|
17
|
+
let catalog = (name: string): string => `Catalog_${name}`
|
|
18
|
+
let ordering = (name: string): string => `Ordering_${name}`
|
|
19
|
+
|
|
20
|
+
// ── Catalog ─────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
let addCategory = (command: CatalogPlugin.AddCategory.command): Seed.mutation =>
|
|
23
|
+
switch command {
|
|
24
|
+
| AddCategory({categoryId, name}) =>
|
|
25
|
+
Seed.mutation(catalog("AddCategory"), [("categoryId", Id(categoryId)), ("name", String(name))])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let renameCategory = (command: CatalogPlugin.RenameCategory.command): Seed.mutation =>
|
|
29
|
+
switch command {
|
|
30
|
+
| RenameCategory({categoryId, name}) =>
|
|
31
|
+
Seed.mutation(
|
|
32
|
+
catalog("RenameCategory"),
|
|
33
|
+
[("categoryId", Id(categoryId)), ("name", String(name))],
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let archiveCategory = (command: CatalogPlugin.ArchiveCategory.command): Seed.mutation =>
|
|
38
|
+
switch command {
|
|
39
|
+
| ArchiveCategory({categoryId}) =>
|
|
40
|
+
Seed.mutation(catalog("ArchiveCategory"), [("categoryId", Id(categoryId))])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let addProduct = (command: CatalogPlugin.AddProduct.command): Seed.mutation =>
|
|
44
|
+
switch command {
|
|
45
|
+
| AddProduct({productId, name, description, price, imageUrl, categoryId}) =>
|
|
46
|
+
Seed.mutation(
|
|
47
|
+
catalog("AddProduct"),
|
|
48
|
+
[
|
|
49
|
+
("productId", Id(productId)),
|
|
50
|
+
("name", String(name)),
|
|
51
|
+
("description", String(description)),
|
|
52
|
+
("price", Float(price)),
|
|
53
|
+
("imageUrl", String(imageUrl)),
|
|
54
|
+
("categoryId", Id(categoryId)),
|
|
55
|
+
],
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let changeProductPrice = (command: CatalogPlugin.ChangeProductPrice.command): Seed.mutation =>
|
|
60
|
+
switch command {
|
|
61
|
+
| ChangeProductPrice({productId, price}) =>
|
|
62
|
+
Seed.mutation(
|
|
63
|
+
catalog("ChangeProductPrice"),
|
|
64
|
+
[("productId", Id(productId)), ("price", Float(price))],
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let changeProductDescription = (
|
|
69
|
+
command: CatalogPlugin.ChangeProductDescription.command,
|
|
70
|
+
): Seed.mutation =>
|
|
71
|
+
switch command {
|
|
72
|
+
| ChangeProductDescription({productId, description}) =>
|
|
73
|
+
Seed.mutation(
|
|
74
|
+
catalog("ChangeProductDescription"),
|
|
75
|
+
[("productId", Id(productId)), ("description", String(description))],
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** InboundTranslationSlice: the mutation arguments are the external input's
|
|
80
|
+
fields, not a command payload — the slice translates them itself. */
|
|
81
|
+
let importProduct = (input: CatalogPlugin.ImportProduct.externalInput): Seed.mutation =>
|
|
82
|
+
Seed.mutation(
|
|
83
|
+
catalog("ImportProduct"),
|
|
84
|
+
[
|
|
85
|
+
("sku", String(input.sku)),
|
|
86
|
+
("title", String(input.title)),
|
|
87
|
+
("desc", String(input.desc)),
|
|
88
|
+
("unitPrice", Int(input.unitPrice)),
|
|
89
|
+
("currency", String(input.currency)),
|
|
90
|
+
("category", Id(input.category)),
|
|
91
|
+
],
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
// ── Ordering ────────────────────────────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
let shippingMethod = (method: OrderingPlugin.PlaceOrder.shippingMethod): Seed.value =>
|
|
97
|
+
switch method {
|
|
98
|
+
| Standard => Enum("Standard")
|
|
99
|
+
| Express => Enum("Express")
|
|
100
|
+
| Pickup => Enum("Pickup")
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let placeOrder = (command: OrderingPlugin.PlaceOrder.command): Seed.mutation =>
|
|
104
|
+
switch command {
|
|
105
|
+
| PlaceOrder({orderId, customerId, productIds, shippingMethod: method}) =>
|
|
106
|
+
Seed.mutation(
|
|
107
|
+
ordering("PlaceOrder"),
|
|
108
|
+
[
|
|
109
|
+
("orderId", Id(orderId)),
|
|
110
|
+
("customerId", Id(customerId)),
|
|
111
|
+
("productIds", Seed.ids(productIds)),
|
|
112
|
+
("shippingMethod", shippingMethod(method)),
|
|
113
|
+
],
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let shipOrder = (command: OrderingPlugin.ShipOrder.command): Seed.mutation =>
|
|
118
|
+
switch command {
|
|
119
|
+
| ShipOrder({orderId}) => Seed.mutation(ordering("ShipOrder"), [("orderId", Id(orderId))])
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** CancelOrder's ReopenOrder variant is `@noApi`, so it has no mutation field to
|
|
123
|
+
encode to — reaching it here means the seed tried to drive an internal-only
|
|
124
|
+
command through the public API. */
|
|
125
|
+
let cancelOrder = (command: OrderingPlugin.CancelOrder.command): Seed.mutation =>
|
|
126
|
+
switch command {
|
|
127
|
+
| CancelOrder({orderId}) => Seed.mutation(ordering("CancelOrder"), [("orderId", Id(orderId))])
|
|
128
|
+
| ReopenOrder(_) =>
|
|
129
|
+
throw(Seed.Failed("ReopenOrder is @noApi — it cannot be seeded through the GraphQL API"))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Aggregate commands are exposed as `<Plugin>_<Aggregate>_<Variant>` and take
|
|
133
|
+
the aggregate id alongside the payload. */
|
|
134
|
+
let customer = (~id: string, command: OrderingPlugin.Customer.command): Seed.mutation =>
|
|
135
|
+
switch command {
|
|
136
|
+
| Register({email, address}) =>
|
|
137
|
+
Seed.mutation(
|
|
138
|
+
ordering("Customer_Register"),
|
|
139
|
+
[("id", Id(id)), ("email", String(email)), ("address", String(address))],
|
|
140
|
+
)
|
|
141
|
+
| UpdateEmail({email}) =>
|
|
142
|
+
Seed.mutation(ordering("Customer_UpdateEmail"), [("id", Id(id)), ("email", String(email))])
|
|
143
|
+
| UpdateAddress({address}) =>
|
|
144
|
+
Seed.mutation(
|
|
145
|
+
ordering("Customer_UpdateAddress"),
|
|
146
|
+
[("id", Id(id)), ("address", String(address))],
|
|
147
|
+
)
|
|
148
|
+
| SetLocation({location}) =>
|
|
149
|
+
Seed.mutation(
|
|
150
|
+
ordering("Customer_SetLocation"),
|
|
151
|
+
[("id", Id(id)), ("location", Object([("lat", Float(location.lat)), ("lng", Float(location.lng))]))],
|
|
152
|
+
)
|
|
153
|
+
| Deactivate => Seed.mutation(ordering("Customer_Deactivate"), [("id", Id(id))])
|
|
154
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|