@useairfoil/producer-shopify 0.2.0 → 0.2.1

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.
Files changed (60) hide show
  1. package/README.md +85 -248
  2. package/dist/index.d.mts +6993 -0
  3. package/dist/index.mjs +3 -0
  4. package/dist/main.d.mts +1 -0
  5. package/dist/main.mjs +698 -0
  6. package/dist/main.mjs.map +1 -0
  7. package/dist/manifest.d.mts +32 -0
  8. package/dist/manifest.mjs +51 -0
  9. package/dist/manifest.mjs.map +1 -0
  10. package/dist/{chunk-Bp6m_JJh.js → rolldown-runtime-D7D4PA-g.mjs} +4 -4
  11. package/dist/src-Bgvuhcfk.mjs +2473 -0
  12. package/dist/src-Bgvuhcfk.mjs.map +1 -0
  13. package/package.json +19 -19
  14. package/src/{auth.ts → api/auth.ts} +15 -35
  15. package/src/api/client.ts +429 -0
  16. package/src/api/graphql.ts +221 -0
  17. package/src/api/http.ts +25 -0
  18. package/src/connector.ts +266 -163
  19. package/src/create-table.ts +5 -0
  20. package/src/demo/customers.ts +412 -0
  21. package/src/demo/index.ts +31 -0
  22. package/src/demo/setup.ts +63 -0
  23. package/src/demo/shared.ts +114 -0
  24. package/src/index.ts +35 -21
  25. package/src/main.ts +8 -8
  26. package/src/manifest.ts +4 -55
  27. package/src/resources/carts/row.ts +58 -0
  28. package/src/resources/carts/webhook.ts +98 -0
  29. package/src/resources/customers/graphql.ts +175 -0
  30. package/src/resources/customers/row.ts +112 -0
  31. package/src/resources/customers/webhook.ts +30 -0
  32. package/src/resources/orders/graphql.ts +419 -0
  33. package/src/resources/orders/row.ts +180 -0
  34. package/src/resources/orders/webhook.ts +248 -0
  35. package/src/resources/products/graphql.ts +142 -0
  36. package/src/resources/products/row.ts +92 -0
  37. package/src/resources/products/webhook.ts +130 -0
  38. package/src/resources/refunds/graphql.ts +196 -0
  39. package/src/resources/refunds/row.ts +97 -0
  40. package/src/resources/refunds/webhook.ts +123 -0
  41. package/src/resources/shared.ts +293 -0
  42. package/src/sandbox.ts +3 -3
  43. package/src/start.ts +3 -5
  44. package/src/tables.ts +15 -0
  45. package/dist/index.d.ts +0 -965
  46. package/dist/index.js +0 -4
  47. package/dist/main.d.ts +0 -1
  48. package/dist/main.js +0 -49
  49. package/dist/main.js.map +0 -1
  50. package/dist/manifest-BFfx2LkS.js +0 -91
  51. package/dist/manifest-BFfx2LkS.js.map +0 -1
  52. package/dist/manifest-CPOEExQU.d.ts +0 -34
  53. package/dist/manifest.d.ts +0 -2
  54. package/dist/manifest.js +0 -3
  55. package/dist/src-DqmiLrYS.js +0 -984
  56. package/dist/src-DqmiLrYS.js.map +0 -1
  57. package/src/api.ts +0 -636
  58. package/src/schemas.ts +0 -319
  59. package/src/throttle.ts +0 -89
  60. package/src/transient-retry.ts +0 -74
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import { C as CartWebhookPayloadSchema, S as ProductVariantSchema, _ as ProductWebhookPayloadSchema, a as RefundWebhookPayloadSchema, b as ProductStatusSchema, c as OrderWebhookPayloadSchema, d as CartSchema, f as client_exports, g as ProductDeleteWebhookPayloadSchema, h as CustomerSchema, l as fromOrderWebhook, m as OrderSchema, o as fromRefundWebhook, p as RefundSchema, r as connector_exports, s as OrderDeleteWebhookPayloadSchema, t as ShopifyNormalize, u as CartLineItemSchema, v as ProductOptionSchema, w as PageInfoSchema, x as ProductVariantInventoryPolicySchema, y as ProductSchema } from "./src-Bgvuhcfk.mjs";
2
+ import { manifest } from "./manifest.mjs";
3
+ export { CartLineItemSchema, CartSchema, CartWebhookPayloadSchema, CustomerSchema, OrderDeleteWebhookPayloadSchema, OrderSchema, OrderWebhookPayloadSchema, PageInfoSchema, ProductDeleteWebhookPayloadSchema, ProductOptionSchema, ProductSchema, ProductStatusSchema, ProductVariantInventoryPolicySchema, ProductVariantSchema, ProductWebhookPayloadSchema, RefundSchema, RefundWebhookPayloadSchema, client_exports as ShopifyApiClient, connector_exports as ShopifyConnector, ShopifyNormalize, fromOrderWebhook, fromRefundWebhook, manifest };
@@ -0,0 +1 @@
1
+ export {}
package/dist/main.mjs ADDED
@@ -0,0 +1,698 @@
1
+ import { E as normalizeAmount, T as gid, d as CartSchema, h as CustomerSchema, i as layerConfig, m as OrderSchema, n as ShopifyConnector, p as RefundSchema, y as ProductSchema } from "./src-Bgvuhcfk.mjs";
2
+ import { ShopifyConfigDef } from "./manifest.mjs";
3
+ import "effect/Schema";
4
+ import { ConnectorApp, Demo, Ingestor, RuntimeConfig, StateStore, Telemetry } from "@useairfoil/connector-kit";
5
+ import { Config, Duration, Effect, Layer, Logger, Schema } from "effect";
6
+ import { FetchHttpClient } from "effect/http";
7
+ import { NodeRuntime, NodeServices } from "@effect/platform-node";
8
+ import { Command } from "effect/cli";
9
+ import { PgClient } from "@effect/sql-pg";
10
+ //#region package.json
11
+ var version = "0.2.0";
12
+ //#endregion
13
+ //#region src/tables.ts
14
+ const tableSchemas = {
15
+ products: ProductSchema,
16
+ carts: CartSchema,
17
+ customers: CustomerSchema,
18
+ orders: OrderSchema,
19
+ refunds: RefundSchema
20
+ };
21
+ //#endregion
22
+ //#region src/create-table.ts
23
+ const createTableCommand = ConnectorApp.makeCreateTableCommand(tableSchemas);
24
+ //#endregion
25
+ //#region src/demo/shared.ts
26
+ const hour = Duration.toMillis(Duration.hours(1));
27
+ const day = Duration.toMillis(Duration.days(1));
28
+ const vendor = "Northwind Goods";
29
+ const taxRate = .08;
30
+ const welcomeCode = "WELCOME10";
31
+ const catalog = [
32
+ {
33
+ title: "Classic Cotton Tee",
34
+ type: "T-Shirts",
35
+ price: 2800,
36
+ grams: 180,
37
+ option: {
38
+ name: "Size",
39
+ values: [
40
+ "S",
41
+ "M",
42
+ "L",
43
+ "XL"
44
+ ]
45
+ }
46
+ },
47
+ {
48
+ title: "Everyday Hoodie",
49
+ type: "Sweatshirts",
50
+ price: 6400,
51
+ grams: 520,
52
+ option: {
53
+ name: "Size",
54
+ values: [
55
+ "S",
56
+ "M",
57
+ "L",
58
+ "XL"
59
+ ]
60
+ }
61
+ },
62
+ {
63
+ title: "Linen Button Shirt",
64
+ type: "Shirts",
65
+ price: 7200,
66
+ grams: 260,
67
+ option: {
68
+ name: "Size",
69
+ values: [
70
+ "S",
71
+ "M",
72
+ "L"
73
+ ]
74
+ }
75
+ },
76
+ {
77
+ title: "Wool Beanie",
78
+ type: "Hats",
79
+ price: 2600,
80
+ grams: 90,
81
+ option: {
82
+ name: "Color",
83
+ values: [
84
+ "Charcoal",
85
+ "Navy",
86
+ "Rust"
87
+ ]
88
+ }
89
+ },
90
+ {
91
+ title: "Canvas Tote Bag",
92
+ type: "Bags",
93
+ price: 2200,
94
+ grams: 300,
95
+ option: null
96
+ },
97
+ {
98
+ title: "Leather Card Wallet",
99
+ type: "Accessories",
100
+ price: 5400,
101
+ grams: 80,
102
+ option: {
103
+ name: "Color",
104
+ values: ["Black", "Tan"]
105
+ }
106
+ },
107
+ {
108
+ title: "Stoneware Mug",
109
+ type: "Home",
110
+ price: 1800,
111
+ grams: 400,
112
+ option: {
113
+ name: "Color",
114
+ values: ["Cream", "Sage"]
115
+ }
116
+ },
117
+ {
118
+ title: "Insulated Water Bottle",
119
+ type: "Home",
120
+ price: 3200,
121
+ grams: 450,
122
+ option: {
123
+ name: "Color",
124
+ values: [
125
+ "Black",
126
+ "White",
127
+ "Sky"
128
+ ]
129
+ }
130
+ },
131
+ {
132
+ title: "Merino Running Socks",
133
+ type: "Socks",
134
+ price: 1600,
135
+ grams: 60,
136
+ option: {
137
+ name: "Size",
138
+ values: ["S/M", "L/XL"]
139
+ }
140
+ },
141
+ {
142
+ title: "Gift Card",
143
+ type: "Gift Cards",
144
+ price: 5e3,
145
+ grams: 0,
146
+ option: null
147
+ }
148
+ ];
149
+ const productNumber = (p) => 81e11 + p;
150
+ const variantNumber = (p, v) => 44e12 + p * 10 + v;
151
+ const handleOf = (item) => item.title.toLowerCase().replaceAll(" ", "-");
152
+ const isGiftCard = (item) => item.type === "Gift Cards";
153
+ const valuesOf = (item) => item.option?.values ?? ["Default Title"];
154
+ const money = (cents) => {
155
+ const amount = normalizeAmount((cents / 100).toFixed(2));
156
+ return {
157
+ shopMoney: {
158
+ amount,
159
+ currencyCode: "USD"
160
+ },
161
+ presentmentMoney: {
162
+ amount,
163
+ currencyCode: "USD"
164
+ }
165
+ };
166
+ };
167
+ const amount = (cents) => normalizeAmount((cents / 100).toFixed(2));
168
+ /** Date helpers for one run. `at` keeps a time from going past now. */
169
+ const clock = ({ now }) => {
170
+ const at = (time) => new Date(Math.min(time, now.getTime()));
171
+ return { at };
172
+ };
173
+ //#endregion
174
+ //#region src/demo/customers.ts
175
+ /** One group is one customer with their orders, refunds, and sometimes an open cart. */
176
+ const customerRows = (index, context) => {
177
+ const { faker, now } = context;
178
+ const { at } = clock(context);
179
+ const rows = {
180
+ customers: [],
181
+ orders: [],
182
+ refunds: [],
183
+ carts: []
184
+ };
185
+ const customerNumber = 72e11 + index;
186
+ const customerId = gid("Customer", customerNumber);
187
+ const addressId = gid("MailingAddress", 93e11 + index);
188
+ const firstName = faker.person.firstName();
189
+ const lastName = faker.person.lastName();
190
+ const email = faker.internet.exampleEmail({
191
+ firstName,
192
+ lastName
193
+ }).toLowerCase();
194
+ const phone = faker.phone.number({ style: "international" });
195
+ const address = {
196
+ firstName,
197
+ lastName,
198
+ name: `${firstName} ${lastName}`,
199
+ company: null,
200
+ address1: faker.location.streetAddress(),
201
+ address2: null,
202
+ city: faker.location.city(),
203
+ province: faker.location.state(),
204
+ provinceCode: faker.location.state({ abbreviated: true }),
205
+ country: "United States",
206
+ countryCode: "US",
207
+ zip: faker.location.zipCode("#####"),
208
+ phone,
209
+ latitude: faker.location.latitude(),
210
+ longitude: faker.location.longitude()
211
+ };
212
+ const subscribed = faker.datatype.boolean({ probability: .4 });
213
+ const created = at(now.getTime() - faker.number.int({
214
+ min: 10 * day,
215
+ max: 700 * day
216
+ }));
217
+ const orderCount = faker.helpers.weightedArrayElement([
218
+ {
219
+ weight: 20,
220
+ value: 0
221
+ },
222
+ {
223
+ weight: 40,
224
+ value: 1
225
+ },
226
+ {
227
+ weight: 20,
228
+ value: 2
229
+ },
230
+ {
231
+ weight: 10,
232
+ value: 3
233
+ },
234
+ {
235
+ weight: 10,
236
+ value: faker.number.int({
237
+ min: 4,
238
+ max: 6
239
+ })
240
+ }
241
+ ]);
242
+ const orderTimes = Array.from({ length: orderCount }, () => faker.date.between({
243
+ from: created,
244
+ to: now
245
+ })).toSorted((a, b) => a.getTime() - b.getTime());
246
+ let spent = 0;
247
+ let lastChange = created;
248
+ orderTimes.forEach((orderCreated, n) => {
249
+ const orderNumber = 56e11 + index * 10 + n;
250
+ const orderId = gid("Order", orderNumber);
251
+ const saleId = gid("OrderTransaction", 67e11 + (index * 10 + n) * 2);
252
+ const discounted = n === 0 && faker.datatype.boolean({ probability: .25 });
253
+ const lines = faker.helpers.arrayElements(catalog.map((item, p) => ({
254
+ item,
255
+ p
256
+ })), {
257
+ min: 1,
258
+ max: 3
259
+ }).map(({ item, p }, k) => {
260
+ const v = faker.number.int({ max: valuesOf(item).length - 1 });
261
+ const quantity = isGiftCard(item) ? 1 : faker.number.int({
262
+ min: 1,
263
+ max: 2
264
+ });
265
+ const gross = item.price * quantity;
266
+ const discount = discounted ? Math.round(gross * .1) : 0;
267
+ return {
268
+ item,
269
+ p,
270
+ v,
271
+ k,
272
+ quantity,
273
+ gross,
274
+ discount,
275
+ tax: isGiftCard(item) ? 0 : Math.round((gross - discount) * taxRate)
276
+ };
277
+ });
278
+ const discountTotal = lines.reduce((sum, line) => sum + line.discount, 0);
279
+ const subtotal = lines.reduce((sum, line) => sum + line.gross - line.discount, 0);
280
+ const tax = lines.reduce((sum, line) => sum + line.tax, 0);
281
+ const shipping = lines.every((line) => isGiftCard(line.item)) || subtotal >= 7500 ? 0 : 600;
282
+ const total = subtotal + shipping + tax;
283
+ const grams = lines.reduce((sum, line) => sum + line.item.grams * line.quantity, 0);
284
+ const cancelled = faker.datatype.boolean({ probability: .03 });
285
+ const refund = cancelled ? null : faker.helpers.maybe(() => faker.helpers.arrayElement(["full", "partial"]), { probability: .06 });
286
+ const refundedLines = refund === "full" ? lines : refund === "partial" ? lines.slice(0, 1) : [];
287
+ const refundShipping = refund === "full" ? shipping : 0;
288
+ const refundedSubtotal = refundedLines.reduce((sum, line) => sum + line.gross - line.discount, 0);
289
+ const refundedTax = refundedLines.reduce((sum, line) => sum + line.tax, 0);
290
+ const refundedTotal = refundedSubtotal + refundedTax + refundShipping;
291
+ const cancelledAt = cancelled ? at(orderCreated.getTime() + faker.number.int({
292
+ min: 6e4,
293
+ max: day
294
+ })) : null;
295
+ const refundAt = refund ? at(orderCreated.getTime() + faker.number.int({
296
+ min: 3 * day,
297
+ max: 20 * day
298
+ })) : null;
299
+ const fulfilled = orderCreated.getTime() < now.getTime() - 5 * day;
300
+ const closedAt = cancelledAt ?? (fulfilled ? at(orderCreated.getTime() + faker.number.int({
301
+ min: 2 * day,
302
+ max: 5 * day
303
+ })) : null);
304
+ const updatedAt = new Date(Math.max(orderCreated.getTime(), closedAt?.getTime() ?? 0, refundAt?.getTime() ?? 0));
305
+ const current = cancelled ? 0 : 1;
306
+ const currentSubtotal = (subtotal - refundedSubtotal) * current;
307
+ const currentTax = (tax - refundedTax) * current;
308
+ const currentShipping = (shipping - refundShipping) * current;
309
+ const currentTotal = currentSubtotal + currentTax + currentShipping;
310
+ spent += currentTotal;
311
+ lastChange = updatedAt > lastChange ? updatedAt : lastChange;
312
+ const shippingLineId = gid("ShippingLine", 45e11 + index * 10 + n);
313
+ rows.orders.push({
314
+ id: orderId,
315
+ legacyResourceId: String(orderNumber),
316
+ name: `#${1001 + index * 10 + n}`,
317
+ email,
318
+ phone,
319
+ customerId,
320
+ customerLocale: "en",
321
+ customerAcceptsMarketing: subscribed,
322
+ billingAddress: address,
323
+ shippingAddress: lines.every((line) => isGiftCard(line.item)) ? null : address,
324
+ note: "",
325
+ customAttributes: [],
326
+ tags: [],
327
+ confirmationNumber: faker.string.alphanumeric({
328
+ length: 9,
329
+ casing: "upper"
330
+ }),
331
+ poNumber: "",
332
+ sourceName: "web",
333
+ sourceIdentifier: "",
334
+ appId: gid("App", 580111),
335
+ paymentGatewayNames: ["shopify_payments"],
336
+ test: false,
337
+ taxesIncluded: false,
338
+ taxExempt: false,
339
+ dutiesIncluded: false,
340
+ estimatedTaxes: false,
341
+ totalWeight: grams,
342
+ displayFinancialStatus: cancelled ? "VOIDED" : refund === "full" ? "REFUNDED" : refund === "partial" ? "PARTIALLY_REFUNDED" : "PAID",
343
+ cancelReason: cancelled ? "CUSTOMER" : null,
344
+ cancelledAt,
345
+ closedAt,
346
+ processedAt: orderCreated,
347
+ createdAt: orderCreated,
348
+ updatedAt,
349
+ currencyCode: "USD",
350
+ presentmentCurrencyCode: "USD",
351
+ discountCodes: discounted ? [welcomeCode] : [],
352
+ discountApplications: discounted ? [{
353
+ index: 0,
354
+ type: "DISCOUNT_CODE",
355
+ code: welcomeCode,
356
+ title: null,
357
+ description: null,
358
+ allocationMethod: "ACROSS",
359
+ targetSelection: "ALL",
360
+ targetType: "LINE_ITEM",
361
+ valueType: "PERCENTAGE",
362
+ value: "10"
363
+ }] : [],
364
+ subtotalPriceSet: money(subtotal),
365
+ currentSubtotalPriceSet: money(currentSubtotal),
366
+ totalDiscountsSet: money(discountTotal),
367
+ currentTotalDiscountsSet: money(discountTotal * current),
368
+ totalShippingPriceSet: money(shipping),
369
+ currentShippingPriceSet: money(currentShipping),
370
+ totalTaxSet: money(tax),
371
+ currentTotalTaxSet: money(currentTax),
372
+ originalTotalDutiesSet: null,
373
+ currentTotalDutiesSet: null,
374
+ totalPriceSet: money(total),
375
+ currentTotalPriceSet: money(currentTotal),
376
+ taxLines: tax > 0 ? [{
377
+ title: "Sales Tax",
378
+ rate: taxRate,
379
+ priceSet: money(tax)
380
+ }] : [],
381
+ shippingLines: shipping === 0 && lines.every((line) => isGiftCard(line.item)) ? [] : [{
382
+ id: shippingLineId,
383
+ title: shipping === 0 ? "Free Shipping" : "Standard Shipping",
384
+ code: shipping === 0 ? "Free Shipping" : "Standard Shipping",
385
+ source: "shopify",
386
+ carrierIdentifier: null,
387
+ phone: null,
388
+ isRemoved: false,
389
+ originalPriceSet: money(shipping),
390
+ discountedPriceSet: money(shipping),
391
+ currentDiscountedPriceSet: money(currentShipping),
392
+ taxLines: [],
393
+ discountAllocations: []
394
+ }],
395
+ lineItems: lines.map((line) => {
396
+ const value = valuesOf(line.item)[line.v] ?? "Default Title";
397
+ const refundedQuantity = refundedLines.includes(line) ? line.quantity : 0;
398
+ return {
399
+ id: gid("LineItem", 0xcbba106e000 + (index * 10 + n) * 10 + line.k),
400
+ name: line.item.option ? `${line.item.title} - ${value}` : line.item.title,
401
+ title: line.item.title,
402
+ variantTitle: line.item.option ? value : null,
403
+ sku: `NW-${handleOf(line.item).toUpperCase()}-${value.replace("/", "").toUpperCase()}`,
404
+ vendor,
405
+ productId: gid("Product", productNumber(line.p)),
406
+ variantId: gid("ProductVariant", variantNumber(line.p, line.v)),
407
+ quantity: line.quantity,
408
+ currentQuantity: (line.quantity - refundedQuantity) * current,
409
+ taxable: !isGiftCard(line.item),
410
+ requiresShipping: !isGiftCard(line.item),
411
+ isGiftCard: isGiftCard(line.item),
412
+ originalUnitPriceSet: money(line.item.price),
413
+ totalDiscountSet: money(line.discount),
414
+ taxLines: line.tax > 0 ? [{
415
+ title: "Sales Tax",
416
+ rate: taxRate,
417
+ priceSet: money(line.tax)
418
+ }] : [],
419
+ discountAllocations: discounted ? [{
420
+ discountApplicationIndex: 0,
421
+ amountSet: money(line.discount)
422
+ }] : [],
423
+ customAttributes: []
424
+ };
425
+ })
426
+ });
427
+ if (refund && refundAt) {
428
+ const refundNumber = 0xe8d4a51000 + index * 10 + n;
429
+ rows.refunds.push({
430
+ id: gid("Refund", refundNumber),
431
+ legacyResourceId: String(refundNumber),
432
+ orderId,
433
+ note: refund === "full" ? "Returned by customer" : "",
434
+ createdAt: refundAt,
435
+ processedAt: refundAt,
436
+ transactions: [{
437
+ id: gid("OrderTransaction", 67e11 + (index * 10 + n) * 2 + 1),
438
+ kind: "REFUND",
439
+ status: "SUCCESS",
440
+ amount: amount(refundedTotal),
441
+ currencyCode: "USD",
442
+ gateway: "shopify_payments",
443
+ test: false,
444
+ errorCode: null,
445
+ parentTransactionId: saleId,
446
+ createdAt: refundAt,
447
+ processedAt: refundAt
448
+ }],
449
+ refundLineItems: refundedLines.map((line) => ({
450
+ id: gid("RefundLineItem", 2e12 + (index * 10 + n) * 10 + line.k),
451
+ lineItemId: gid("LineItem", 0xcbba106e000 + (index * 10 + n) * 10 + line.k),
452
+ quantity: line.quantity,
453
+ restockType: "RETURN",
454
+ locationId: gid("Location", 64000000001),
455
+ subtotalSet: money(line.gross - line.discount),
456
+ totalTaxSet: money(line.tax)
457
+ })),
458
+ refundShippingLines: refundShipping > 0 ? [{
459
+ id: gid("RefundShippingLine", 3e12 + index * 10 + n),
460
+ shippingLineId,
461
+ subtotalAmountSet: money(refundShipping)
462
+ }] : [],
463
+ orderAdjustments: [],
464
+ duties: []
465
+ });
466
+ }
467
+ });
468
+ if (faker.datatype.boolean({ probability: .25 })) {
469
+ const token = `c1-${index.toString(16).padStart(8, "0")}${faker.string.hexadecimal({
470
+ length: 24,
471
+ casing: "lower",
472
+ prefix: ""
473
+ })}`;
474
+ const cartCreated = at(now.getTime() - faker.number.int({
475
+ min: hour,
476
+ max: 7 * day
477
+ }));
478
+ rows.carts.push({
479
+ id: token,
480
+ token,
481
+ topic: "carts/update",
482
+ lineItems: faker.helpers.arrayElements(catalog.map((item, p) => ({
483
+ item,
484
+ p
485
+ })), {
486
+ min: 1,
487
+ max: 2
488
+ }).map(({ item, p }) => {
489
+ const v = faker.number.int({ max: valuesOf(item).length - 1 });
490
+ const quantity = faker.number.int({
491
+ min: 1,
492
+ max: 2
493
+ });
494
+ const variant = variantNumber(p, v);
495
+ return {
496
+ id: String(variant),
497
+ properties: null,
498
+ quantity,
499
+ variantId: gid("ProductVariant", variant),
500
+ key: `${variant}:${faker.string.hexadecimal({
501
+ length: 32,
502
+ casing: "lower",
503
+ prefix: ""
504
+ })}`,
505
+ discountedPrice: amount(item.price),
506
+ discounts: "[]",
507
+ giftCard: isGiftCard(item),
508
+ grams: item.grams,
509
+ linePrice: amount(item.price * quantity),
510
+ originalLinePrice: amount(item.price * quantity),
511
+ originalPrice: amount(item.price),
512
+ price: amount(item.price),
513
+ productId: gid("Product", productNumber(p)),
514
+ sku: `NW-${handleOf(item).toUpperCase()}-${(valuesOf(item)[v] ?? "").replace("/", "").toUpperCase()}`,
515
+ taxable: !isGiftCard(item),
516
+ title: item.title,
517
+ totalDiscount: "0",
518
+ vendor,
519
+ discountedPriceSet: money(item.price),
520
+ linePriceSet: money(item.price * quantity),
521
+ originalLinePriceSet: money(item.price * quantity),
522
+ priceSet: money(item.price),
523
+ totalDiscountSet: money(0),
524
+ parentRelationship: null
525
+ };
526
+ }),
527
+ note: "",
528
+ updatedAt: at(cartCreated.getTime() + faker.number.int({
529
+ min: 0,
530
+ max: hour
531
+ })),
532
+ createdAt: cartCreated
533
+ });
534
+ }
535
+ const subscribedAt = subscribed ? created : null;
536
+ rows.customers.push({
537
+ id: customerId,
538
+ legacyResourceId: String(customerNumber),
539
+ firstName,
540
+ lastName,
541
+ displayName: `${firstName} ${lastName}`,
542
+ email,
543
+ emailMarketingState: subscribed ? "SUBSCRIBED" : "NOT_SUBSCRIBED",
544
+ emailMarketingOptInLevel: subscribed ? "SINGLE_OPT_IN" : null,
545
+ emailMarketingUpdatedAt: subscribedAt,
546
+ phone,
547
+ smsMarketingState: "NOT_SUBSCRIBED",
548
+ smsMarketingOptInLevel: null,
549
+ smsMarketingUpdatedAt: null,
550
+ smsMarketingCollectedFrom: null,
551
+ note: "",
552
+ state: orderCount > 0 ? "ENABLED" : "DISABLED",
553
+ verifiedEmail: true,
554
+ taxExempt: false,
555
+ taxExemptions: [],
556
+ tags: orderCount >= 3 ? ["repeat"] : [],
557
+ locale: "en",
558
+ numberOfOrders: orderCount,
559
+ amountSpent: {
560
+ amount: amount(spent),
561
+ currencyCode: "USD"
562
+ },
563
+ lastOrderId: orderCount > 0 ? gid("Order", 56e11 + index * 10 + orderCount - 1) : "",
564
+ productSubscriberStatus: "NEVER_SUBSCRIBED",
565
+ dataSaleOptOut: false,
566
+ defaultAddressId: addressId,
567
+ addresses: [{
568
+ id: addressId,
569
+ ...address
570
+ }],
571
+ createdAt: created,
572
+ updatedAt: lastChange
573
+ });
574
+ return rows;
575
+ };
576
+ //#endregion
577
+ //#region src/demo/setup.ts
578
+ /** The product catalog, written once before any customer. */
579
+ const setupRows = ({ now }) => {
580
+ const created = /* @__PURE__ */ new Date(now.getTime() - 800 * day);
581
+ return { products: catalog.map((item, p) => ({
582
+ id: gid("Product", productNumber(p)),
583
+ legacyResourceId: String(productNumber(p)),
584
+ title: item.title,
585
+ handle: handleOf(item),
586
+ descriptionHtml: `<p>The ${item.title.toLowerCase()} from ${vendor}.</p>`,
587
+ productType: item.type,
588
+ vendor,
589
+ status: "ACTIVE",
590
+ tags: [item.type.toLowerCase()],
591
+ createdAt: created,
592
+ updatedAt: created,
593
+ publishedAt: created,
594
+ templateSuffix: "",
595
+ featuredMedia: { image: {
596
+ url: `https://demo.example.com/images/${handleOf(item)}.jpg`,
597
+ altText: item.title
598
+ } },
599
+ options: [{
600
+ id: gid("ProductOption", productNumber(p)),
601
+ name: item.option?.name ?? "Title",
602
+ position: 1,
603
+ values: valuesOf(item)
604
+ }],
605
+ variants: valuesOf(item).map((value, v) => ({
606
+ id: gid("ProductVariant", variantNumber(p, v)),
607
+ legacyResourceId: String(variantNumber(p, v)),
608
+ title: value,
609
+ sku: `NW-${handleOf(item).toUpperCase()}-${value.replace("/", "").toUpperCase()}`,
610
+ barcode: null,
611
+ price: amount(item.price),
612
+ compareAtPrice: null,
613
+ inventoryPolicy: "DENY",
614
+ taxable: !isGiftCard(item),
615
+ createdAt: created,
616
+ updatedAt: created
617
+ }))
618
+ })) };
619
+ };
620
+ //#endregion
621
+ //#region src/demo/index.ts
622
+ const demo = Demo.define({
623
+ name: "producer-shopify",
624
+ setup: {
625
+ tables: [Demo.table({
626
+ name: "products",
627
+ rowSchema: ProductSchema,
628
+ version: "updatedAt"
629
+ })],
630
+ rows: setupRows
631
+ },
632
+ group: {
633
+ tables: [
634
+ Demo.table({
635
+ name: "customers",
636
+ rowSchema: CustomerSchema,
637
+ version: "updatedAt"
638
+ }),
639
+ Demo.table({
640
+ name: "orders",
641
+ rowSchema: OrderSchema,
642
+ version: "updatedAt"
643
+ }),
644
+ Demo.table({
645
+ name: "refunds",
646
+ rowSchema: RefundSchema,
647
+ version: "processedAt"
648
+ }),
649
+ Demo.table({
650
+ name: "carts",
651
+ rowSchema: CartSchema,
652
+ version: "updatedAt"
653
+ })
654
+ ],
655
+ rows: customerRows
656
+ }
657
+ });
658
+ const demoCommand = ConnectorApp.makeDemoCommand(demo).pipe(Command.provide(RuntimeConfig.layerHosted()));
659
+ //#endregion
660
+ //#region src/sandbox.ts
661
+ const ConnectorLayer$1 = layerConfig(ShopifyConfigDef.config);
662
+ const TelemetryLayer$1 = Layer.mergeAll(Telemetry.layerOtlp({ redactedHeaders: ["x-shopify-access-token"] }), Telemetry.layerMetricsConsoleDump());
663
+ const sandboxCommand = Command.make("sandbox", {}, () => Effect.gen(function* () {
664
+ const port = yield* RuntimeConfig.httpPort;
665
+ const entrypoint = yield* ShopifyConnector;
666
+ return yield* ConnectorApp.start(entrypoint, { port });
667
+ }).pipe(Effect.annotateLogs({ component: "producer-shopify" }), Effect.provide(Layer.mergeAll(StateStore.layerMemory, Ingestor.layerConsole, ConnectorLayer$1, Logger.layer([Logger.consolePretty()]), TelemetryLayer$1)))).pipe(Command.withDescription("Run the connector locally and log ingested data"));
668
+ //#endregion
669
+ //#region src/start.ts
670
+ const ConnectorLayer = layerConfig(ShopifyConfigDef.config);
671
+ const TelemetryLayer = Telemetry.layerOtlp({ redactedHeaders: ["x-shopify-access-token"] });
672
+ const PostgresLayer = PgClient.layerConfig({
673
+ url: Config.schema(Schema.Redacted(Schema.NonEmptyString), RuntimeConfig.PlatformRuntimeKey.postgresConnectionString),
674
+ maxConnections: Config.succeed(2),
675
+ connectTimeout: Config.succeed("5 seconds"),
676
+ applicationName: Config.succeed("airfoil-producer-shopify")
677
+ });
678
+ const StateStoreLayer = StateStore.layerSql().pipe(Layer.provide(PostgresLayer));
679
+ const startCommand = Command.make("start", {}, () => Effect.gen(function* () {
680
+ const port = yield* RuntimeConfig.httpPort;
681
+ const entrypoint = yield* ShopifyConnector;
682
+ return yield* ConnectorApp.start(entrypoint, { port }).pipe(Effect.provide(Ingestor.layerWingsConfig(entrypoint)));
683
+ }).pipe(Effect.annotateLogs({ component: "producer-shopify" }), Effect.provide(Layer.mergeAll(StateStoreLayer, ConnectorLayer, Logger.layer([Logger.consolePretty()]), TelemetryLayer)), Effect.provide(RuntimeConfig.layerHosted()))).pipe(Command.withDescription("Run the production connector against Wings"));
684
+ //#endregion
685
+ //#region src/main.ts
686
+ const BootstrapLayer = Layer.mergeAll(FetchHttpClient.layer, NodeServices.layer);
687
+ const program = Command.make("producer-shopify", {}, () => Effect.void).pipe(Command.withSubcommands([
688
+ startCommand,
689
+ sandboxCommand,
690
+ createTableCommand,
691
+ demoCommand
692
+ ]));
693
+ const cli = Command.run(program, { version });
694
+ NodeRuntime.runMain(cli.pipe(Effect.provide(BootstrapLayer), Effect.scoped));
695
+ //#endregion
696
+ export {};
697
+
698
+ //# sourceMappingURL=main.mjs.map