@kizlo/woocommerce 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/dist/index.js ADDED
@@ -0,0 +1,1796 @@
1
+ import { CurrencyFormat, IdentifierInput, KizloError, ListMetadata, Media, Seo, WC_CORE_BASE, WC_STORE_BASE, WP_KIZLO_BASE, createExtension, createMiddleware, createProcedure, defineErrorMap, deserializeCurrencyFormat, deserializeListMetadata } from "kizlo";
2
+ import { BooleanLike, Metadata, NumberLike, arrayable, normalizeArrayableValue, random, seconds, timestampSec, toPublicMetadata, tryCatch } from "@kizlo/shared";
3
+ import { SignJWT, jwtVerify } from "jose";
4
+ import z$1, { z } from "zod/v4";
5
+ import z$2 from "zod";
6
+
7
+ //#region src/session.ts
8
+ async function mintGuestToken(secret, ttlSeconds) {
9
+ const sub = random({
10
+ length: 32,
11
+ prefix: "t"
12
+ });
13
+ return {
14
+ jwt: await new SignJWT().setProtectedHeader({
15
+ alg: "HS256",
16
+ typ: "JWT"
17
+ }).setSubject(sub).setIssuedAt().setExpirationTime(timestampSec() + ttlSeconds).sign(encodeSecret(secret)),
18
+ sub
19
+ };
20
+ }
21
+ async function verifyToken(token, secret) {
22
+ const { payload } = await jwtVerify(token, encodeSecret(secret));
23
+ return payload;
24
+ }
25
+ function encodeSecret(secret) {
26
+ return new TextEncoder().encode(secret);
27
+ }
28
+ function getCartHeaders(options) {
29
+ const { connInfo, userId, token } = options;
30
+ const headers = {};
31
+ if (token) headers["X-Kizlo-Guest-Token"] = token;
32
+ if (userId) headers["X-Kizlo-User-Id"] = String(userId);
33
+ if (connInfo?.city) headers["X-Kizlo-Geo-City"] = connInfo.city;
34
+ if (connInfo?.state) headers["X-Kizlo-Geo-State"] = connInfo.state;
35
+ if (connInfo?.country) headers["X-Kizlo-Geo-Country"] = connInfo.country;
36
+ if (connInfo?.postcode) headers["X-Kizlo-Geo-Postcode"] = connInfo.postcode;
37
+ return headers;
38
+ }
39
+ function sessionMiddleware(options) {
40
+ const cookieName = options?.cookieName ?? "guest-session";
41
+ const ttlSeconds = seconds(options?.ttl ?? "48 hours");
42
+ return createMiddleware(async ({ context, next }) => {
43
+ const connInfo = await context.getConnInfo();
44
+ const auth = await context.getAuthUser();
45
+ const foundToken = await context.cookies.get(cookieName);
46
+ if (!auth) {
47
+ if (!foundToken) {
48
+ const { jwt, sub } = await mintGuestToken(context.config.siteSecret, ttlSeconds);
49
+ await context.cookies.set({
50
+ name: cookieName,
51
+ value: jwt,
52
+ options: {
53
+ httpOnly: true,
54
+ sameSite: "lax"
55
+ }
56
+ });
57
+ return next({ context: { sessionHeaders: getCartHeaders({
58
+ token: sub,
59
+ connInfo
60
+ }) } });
61
+ }
62
+ const [err, data] = await tryCatch(verifyToken(foundToken, context.config.siteSecret));
63
+ if (err) {
64
+ const { jwt } = await mintGuestToken(context.config.siteSecret, ttlSeconds);
65
+ await context.cookies.set({
66
+ name: cookieName,
67
+ value: jwt,
68
+ options: {
69
+ httpOnly: true,
70
+ sameSite: "lax"
71
+ }
72
+ });
73
+ throw new KizloError("CART_SESSION_EXPIRED");
74
+ }
75
+ return next({ context: { sessionHeaders: getCartHeaders({
76
+ token: data.sub,
77
+ connInfo
78
+ }) } });
79
+ }
80
+ if (foundToken) {
81
+ const [err, data] = await tryCatch(verifyToken(foundToken, context.config.siteSecret));
82
+ if (!err) {
83
+ const response = await context.service.wordpress.post("/cart/merge", {
84
+ base: WP_KIZLO_BASE,
85
+ headers: getCartHeaders({
86
+ userId: auth.id,
87
+ token: data.sub,
88
+ connInfo
89
+ })
90
+ });
91
+ if (response.error) context.logger.error("CART_MERGE_FAILED", response.error);
92
+ }
93
+ await context.cookies.delete(cookieName);
94
+ }
95
+ return next({ context: { sessionHeaders: getCartHeaders({
96
+ userId: auth.id,
97
+ connInfo
98
+ }) } });
99
+ });
100
+ }
101
+
102
+ //#endregion
103
+ //#region src/cart/error.ts
104
+ const GET_CART_ERROR_MAP = defineErrorMap({});
105
+ const UPDATE_CART_ERROR_MAP = defineErrorMap({});
106
+ const ADD_CART_ITEM_ERROR_MAP = defineErrorMap({
107
+ CART_ITEM_OUT_OF_STOCK: {
108
+ status: 409,
109
+ message: "Product is out of stock."
110
+ },
111
+ CART_ITEM_INSUFFICIENT_STOCK: {
112
+ status: 409,
113
+ message: "Not enough stock for the requested quantity."
114
+ },
115
+ CART_ITEM_NOT_PURCHASABLE: {
116
+ status: 400,
117
+ message: "Product is not purchasable."
118
+ },
119
+ CART_ITEM_INVALID_QUANTITY: {
120
+ status: 400,
121
+ message: "Invalid quantity for the cart item."
122
+ },
123
+ CART_ITEM_EXISTS: {
124
+ status: 409,
125
+ message: "Item already exists in the cart."
126
+ },
127
+ CART_PRODUCT_INVALID: {
128
+ status: 404,
129
+ message: "The requested product is invalid."
130
+ },
131
+ CART_VARIATION_INVALID: {
132
+ status: 400,
133
+ message: "Variation data is invalid or missing."
134
+ }
135
+ });
136
+ const UPDATE_CART_ITEM_ERROR_MAP = defineErrorMap({
137
+ CART_ITEM_NOT_FOUND: {
138
+ status: 404,
139
+ message: "Cart item not found."
140
+ },
141
+ CART_PRODUCT_INVALID: {
142
+ status: 404,
143
+ message: "The requested product is invalid."
144
+ },
145
+ CART_ITEM_OUT_OF_STOCK: {
146
+ status: 409,
147
+ message: "Product is out of stock."
148
+ },
149
+ CART_ITEM_INSUFFICIENT_STOCK: {
150
+ status: 409,
151
+ message: "Not enough stock for the requested quantity."
152
+ },
153
+ CART_ITEM_INVALID_QUANTITY: {
154
+ status: 400,
155
+ message: "Invalid quantity for the cart item."
156
+ }
157
+ });
158
+ const REMOVE_CART_ITEM_ERROR_MAP = defineErrorMap({ CART_ITEM_NOT_FOUND: {
159
+ status: 404,
160
+ message: "Cart item not found."
161
+ } });
162
+ const SELECT_SHIPPING_RATE_ERROR_MAP = defineErrorMap({
163
+ CART_SHIPPING_RATE_NOT_FOUND: {
164
+ status: 404,
165
+ message: "The selected shipping rate is no longer available."
166
+ },
167
+ CART_SHIPPING_DISABLED: {
168
+ status: 400,
169
+ message: "Shipping is not available for this cart."
170
+ }
171
+ });
172
+ const APPLY_COUPON_ERROR_MAP = defineErrorMap({
173
+ CART_COUPON_INVALID: {
174
+ status: 400,
175
+ message: "The coupon could not be applied to the cart."
176
+ },
177
+ CART_COUPON_DISABLED: {
178
+ status: 400,
179
+ message: "Coupons are disabled."
180
+ }
181
+ });
182
+ const REMOVE_COUPON_ERROR_MAP = defineErrorMap({
183
+ CART_COUPON_INVALID: {
184
+ status: 400,
185
+ message: "The coupon could not be removed from the cart."
186
+ },
187
+ CART_COUPON_DISABLED: {
188
+ status: 400,
189
+ message: "Coupons are disabled."
190
+ },
191
+ CART_COUPON_NOT_FOUND: {
192
+ status: 404,
193
+ message: "Coupon was not applied to the cart."
194
+ }
195
+ });
196
+
197
+ //#endregion
198
+ //#region src/product/schema.ts
199
+ const SWATCH_TYPES = [
200
+ "text",
201
+ "color",
202
+ "image"
203
+ ];
204
+ const SwatchType = z.enum(SWATCH_TYPES);
205
+ const PRODUCT_TYPES = [
206
+ "simple",
207
+ "grouped",
208
+ "external",
209
+ "variable",
210
+ "variation"
211
+ ];
212
+ const ProductType = z.enum(PRODUCT_TYPES);
213
+ const ProductTagRef = z.object({
214
+ id: z.number(),
215
+ name: z.string(),
216
+ slug: z.string()
217
+ });
218
+ const ProductBrandRef = z.object({
219
+ id: z.number(),
220
+ name: z.string(),
221
+ slug: z.string()
222
+ });
223
+ const ProductAttributeTermRef = z.object({
224
+ id: z.number(),
225
+ name: z.string(),
226
+ slug: z.string()
227
+ });
228
+ const ProductAttributeRef = z.object({
229
+ id: z.number(),
230
+ name: z.string(),
231
+ taxonomy: z.string(),
232
+ hasVariations: z.boolean(),
233
+ terms: z.array(ProductAttributeTermRef)
234
+ });
235
+ const ProductCategoryRef = z.object({
236
+ id: z.number(),
237
+ name: z.string(),
238
+ slug: z.string()
239
+ });
240
+ const ProductVariationAttributeRef = z.object({
241
+ name: z.string(),
242
+ value: z.string()
243
+ });
244
+ const ProductVariationRef = z.object({
245
+ id: z.number(),
246
+ attributes: z.array(ProductVariationAttributeRef)
247
+ });
248
+ const ProductPrices = z.object({
249
+ price: z.number(),
250
+ salePrice: z.number().nullable(),
251
+ regularPrice: z.number()
252
+ });
253
+ const Product = z.object({
254
+ id: z.number(),
255
+ parentId: z.number(),
256
+ type: ProductType,
257
+ name: z.string(),
258
+ slug: z.string(),
259
+ sku: z.string().nullable(),
260
+ shortDescription: z.string(),
261
+ description: z.string(),
262
+ onSaleFrom: z.number().nullable(),
263
+ onSaleTo: z.number().nullable(),
264
+ isOnSale: z.boolean(),
265
+ prices: ProductPrices,
266
+ averageRating: z.string(),
267
+ reviewCount: z.number(),
268
+ images: z.array(Media),
269
+ categories: z.array(ProductCategoryRef),
270
+ tags: z.array(ProductTagRef),
271
+ brands: z.array(ProductBrandRef),
272
+ attributes: z.array(ProductAttributeRef),
273
+ variations: z.array(ProductVariationRef),
274
+ groupedProducts: z.array(z.number()),
275
+ isSoldIndividually: z.boolean(),
276
+ hasOptions: z.boolean(),
277
+ isPurchasable: z.boolean(),
278
+ isInStock: z.boolean(),
279
+ isOnBackorder: z.boolean(),
280
+ stock: z.number().nullable(),
281
+ lowStockRemaining: z.number().nullable(),
282
+ seo: Seo.nullable(),
283
+ currencyFormat: CurrencyFormat,
284
+ meta: Metadata
285
+ });
286
+ const ProductList = z.object({
287
+ items: z.array(Product),
288
+ meta: ListMetadata
289
+ });
290
+ const RetrieveProductInput = z.object({
291
+ identifier: IdentifierInput,
292
+ previewToken: z.string().optional()
293
+ });
294
+ const PRODUCTS_ORDER_BYS = [
295
+ "date",
296
+ "id",
297
+ "include",
298
+ "title",
299
+ "slug",
300
+ "price",
301
+ "popularity",
302
+ "rating",
303
+ "menu_order",
304
+ "comment_count"
305
+ ];
306
+ const ProductOrderBy = z.enum(PRODUCTS_ORDER_BYS);
307
+ const PRODUCT_TAXONOMY_OPERATORS = [
308
+ "in",
309
+ "not_in",
310
+ "and"
311
+ ];
312
+ const ProductTaxonomyOperator = z.enum(PRODUCT_TAXONOMY_OPERATORS);
313
+ const PRODUCT_ATTRIBUTE_RELATIONS = ["in", "and"];
314
+ const ProductAttributeRelation = z.enum(PRODUCT_ATTRIBUTE_RELATIONS);
315
+ const PRODUCT_STOCK_STATUSES = [
316
+ "instock",
317
+ "outofstock",
318
+ "onbackorder"
319
+ ];
320
+ const ProductStockStatus = z.enum(PRODUCT_STOCK_STATUSES);
321
+ const PRODUCT_CATALOG_VISIBILITIES = [
322
+ "any",
323
+ "visible",
324
+ "catalog",
325
+ "search",
326
+ "hidden"
327
+ ];
328
+ const ProductCatalogVisibility = z.enum(PRODUCT_CATALOG_VISIBILITIES);
329
+ const PRODUCT_RATINGS = [
330
+ "1",
331
+ "2",
332
+ "3",
333
+ "4",
334
+ "5"
335
+ ];
336
+ const ProductRating = z.enum(PRODUCT_RATINGS);
337
+ const ProductAttributeFilter = z.object({
338
+ attribute: z.string().optional(),
339
+ slug: arrayable(z.string()).optional(),
340
+ termId: arrayable(NumberLike).optional(),
341
+ operator: ProductTaxonomyOperator.optional()
342
+ });
343
+ const ListProductInput = z.object({
344
+ page: NumberLike.optional(),
345
+ perPage: NumberLike.optional(),
346
+ search: z.string().optional(),
347
+ slug: z.string().optional(),
348
+ after: z.string().optional(),
349
+ before: z.string().optional(),
350
+ exclude: arrayable(NumberLike).optional(),
351
+ include: arrayable(NumberLike).optional(),
352
+ offset: NumberLike.optional(),
353
+ order: z.enum(["asc", "desc"]).optional(),
354
+ orderby: ProductOrderBy.optional(),
355
+ parent: arrayable(NumberLike).optional(),
356
+ parentExclude: arrayable(NumberLike).optional(),
357
+ type: ProductType.optional(),
358
+ sku: z.string().optional(),
359
+ featured: BooleanLike.optional(),
360
+ category: z.string().optional(),
361
+ categoryOperator: ProductTaxonomyOperator.optional(),
362
+ brand: z.string().optional(),
363
+ brandOperator: ProductTaxonomyOperator.optional(),
364
+ tag: z.string().optional(),
365
+ tagOperator: ProductTaxonomyOperator.optional(),
366
+ onSale: BooleanLike.optional(),
367
+ minPrice: z.string().optional(),
368
+ maxPrice: z.string().optional(),
369
+ stockStatus: arrayable(ProductStockStatus).optional(),
370
+ attributes: z.array(ProductAttributeFilter).optional(),
371
+ attributeRelation: ProductAttributeRelation.optional(),
372
+ catalogVisibility: ProductCatalogVisibility.optional(),
373
+ rating: arrayable(ProductRating).optional(),
374
+ related: NumberLike.optional()
375
+ });
376
+ const ProductFiltersPriceRange = z.object({
377
+ minPrice: z.number(),
378
+ maxPrice: z.number()
379
+ });
380
+ const ProductFiltersStockStatus = z.object({
381
+ count: z.number(),
382
+ status: ProductStockStatus
383
+ });
384
+ const ProductFiltersTerm = z.object({
385
+ id: z.number(),
386
+ parentId: z.number().nullable(),
387
+ name: z.string(),
388
+ slug: z.string(),
389
+ taxonomy: z.string(),
390
+ description: z.string(),
391
+ count: z.number()
392
+ });
393
+ const ProductFiltersTaxonomyTerm = ProductFiltersTerm.extend({ image: Media.nullable() });
394
+ const ProductFiltersAttributeTerm = ProductFiltersTerm.extend({
395
+ type: SwatchType,
396
+ swatch: z.string().nullable()
397
+ });
398
+ const ProductFilters = z.object({
399
+ priceRange: ProductFiltersPriceRange,
400
+ stockStatuses: z.array(ProductFiltersStockStatus),
401
+ attributeTerms: z.array(ProductFiltersAttributeTerm),
402
+ taxonomyTerms: z.array(ProductFiltersTaxonomyTerm),
403
+ currencyFormat: CurrencyFormat
404
+ });
405
+ const CalculateAttributeFilter = z.object({
406
+ taxonomy: z.string(),
407
+ queryType: z.enum(["or", "and"]).optional()
408
+ });
409
+ const RetrieveProductFiltersInput = ListProductInput.extend({
410
+ ratingFilters: BooleanLike.optional(),
411
+ stockStatusFilters: BooleanLike.optional(),
412
+ taxonomyFilters: z.array(z.string()).optional(),
413
+ attributeFilters: z.array(CalculateAttributeFilter).optional()
414
+ });
415
+
416
+ //#endregion
417
+ //#region src/schema.ts
418
+ const Totals = z$1.object({
419
+ discountTotal: z$1.number(),
420
+ discountTaxTotal: z$1.number(),
421
+ shippingTotal: z$1.number(),
422
+ shippingTaxTotal: z$1.number(),
423
+ feeTotal: z$1.number(),
424
+ feeTaxTotal: z$1.number(),
425
+ taxTotal: z$1.number(),
426
+ total: z$1.number()
427
+ });
428
+ const ItemTotals = z$1.object({
429
+ unitPrice: z$1.number(),
430
+ grossAmount: z$1.number(),
431
+ discountAmount: z$1.number(),
432
+ discountTaxAmount: z$1.number(),
433
+ netAmount: z$1.number(),
434
+ taxAmount: z$1.number(),
435
+ total: z$1.number()
436
+ });
437
+ const ShippingAddress = z$1.object({
438
+ firstName: z$1.string(),
439
+ lastName: z$1.string(),
440
+ phone: z$1.string(),
441
+ company: z$1.string().optional(),
442
+ address1: z$1.string(),
443
+ address2: z$1.string().optional(),
444
+ city: z$1.string(),
445
+ postcode: z$1.string(),
446
+ state: z$1.string(),
447
+ country: z$1.string()
448
+ });
449
+ const BillingAddress = z$1.object({
450
+ firstName: z$1.string(),
451
+ lastName: z$1.string(),
452
+ phone: z$1.string(),
453
+ company: z$1.string().optional(),
454
+ address1: z$1.string(),
455
+ address2: z$1.string().optional(),
456
+ city: z$1.string(),
457
+ postcode: z$1.string(),
458
+ state: z$1.string(),
459
+ country: z$1.string(),
460
+ email: z$1.string()
461
+ });
462
+
463
+ //#endregion
464
+ //#region src/cart/schema.ts
465
+ const CART_ITEM_STATUSES = [
466
+ "insufficient_stock",
467
+ "low_stock",
468
+ "out_of_stock",
469
+ "unavailable",
470
+ "available"
471
+ ];
472
+ const CartLineItemStatus = z$1.enum(CART_ITEM_STATUSES);
473
+ const PackageAddress = z$1.object({
474
+ address1: z$1.string(),
475
+ address2: z$1.string(),
476
+ city: z$1.string(),
477
+ state: z$1.string(),
478
+ postcode: z$1.string(),
479
+ country: z$1.string()
480
+ });
481
+ const CartPackageItem = z$1.object({
482
+ key: z$1.string(),
483
+ name: z$1.string(),
484
+ quantity: z$1.number()
485
+ });
486
+ const CartPackageRate = z$1.object({
487
+ id: z$1.string(),
488
+ methodId: z$1.string(),
489
+ name: z$1.string(),
490
+ isSelected: z$1.boolean(),
491
+ description: z$1.string(),
492
+ deliveryTime: z$1.string(),
493
+ amount: z$1.number(),
494
+ taxAmount: z$1.number(),
495
+ total: z$1.number()
496
+ });
497
+ const CartPackageLine = z$1.object({
498
+ id: z$1.number(),
499
+ name: z$1.string(),
500
+ address: PackageAddress,
501
+ items: z$1.array(CartPackageItem),
502
+ rates: z$1.array(CartPackageRate)
503
+ });
504
+ const CartItemVariation = z$1.object({
505
+ name: z$1.string(),
506
+ attribute: z$1.string(),
507
+ value: z$1.string()
508
+ });
509
+ const CartItem = z$1.object({
510
+ key: z$1.string(),
511
+ type: z$1.string(),
512
+ status: CartLineItemStatus,
513
+ productId: z$1.number(),
514
+ variationId: z$1.number().nullable(),
515
+ name: z$1.string(),
516
+ description: z$1.string(),
517
+ shortDescription: z$1.string(),
518
+ sku: z$1.string(),
519
+ slug: z$1.string(),
520
+ lowStockCount: z$1.number().nullable(),
521
+ isSoldIndividually: z$1.boolean(),
522
+ images: z$1.array(Media),
523
+ variations: z$1.array(CartItemVariation),
524
+ prices: ProductPrices,
525
+ quantity: z$1.number(),
526
+ totals: ItemTotals
527
+ });
528
+ const AddCartItemInput = z$1.object({
529
+ productId: z$1.number(),
530
+ quantity: z$1.number(),
531
+ variations: z$1.array(z$1.object({
532
+ attribute: z$1.string(),
533
+ value: z$1.string()
534
+ })).optional()
535
+ });
536
+ const UpdateCartItemInput = z$1.object({
537
+ key: z$1.string(),
538
+ quantity: z$1.number()
539
+ });
540
+ const RemoveCartItemInput = z$1.object({ key: z$1.string() });
541
+ const CartCouponLine = z$1.object({
542
+ id: z$1.string(),
543
+ type: z$1.string(),
544
+ code: z$1.string(),
545
+ amount: z$1.number(),
546
+ taxAmount: z$1.number()
547
+ });
548
+ const ApplyCouponInput = z$1.object({ code: z$1.string() });
549
+ const RemoveCouponInput = z$1.object({ code: z$1.string() });
550
+ const CartShippingLine = z$1.object({
551
+ id: z$1.string(),
552
+ label: z$1.string(),
553
+ amount: z$1.number(),
554
+ taxAmount: z$1.number()
555
+ });
556
+ const CartShippingAddress = ShippingAddress.extend({ id: z$1.string().optional() });
557
+ const CartBillingAddress = BillingAddress.extend({ id: z$1.string().optional() });
558
+ const Cart = z$1.object({
559
+ totalItems: z$1.number(),
560
+ lineItems: z$1.array(CartItem),
561
+ billing: CartBillingAddress.nullable(),
562
+ shipping: CartShippingAddress.nullable(),
563
+ packageLines: z$1.array(CartPackageLine),
564
+ couponLines: z$1.array(CartCouponLine),
565
+ shippingLines: z$1.array(CartShippingLine),
566
+ currencyFormat: CurrencyFormat,
567
+ totals: Totals
568
+ });
569
+ const SelectCartShippingRateInput = z$1.object({
570
+ rateId: z$1.string(),
571
+ packageId: z$1.number()
572
+ });
573
+ const AddressInput = (schema) => {
574
+ return schema.extend({ id: z$1.string().optional() });
575
+ };
576
+ const UpdateCartInput = z$1.object({
577
+ shipping: AddressInput(ShippingAddress).nullable().optional(),
578
+ billing: AddressInput(BillingAddress).nullable().optional()
579
+ });
580
+
581
+ //#endregion
582
+ //#region src/cart/utils.ts
583
+ function deserializeCart(data) {
584
+ const lineItems = data.items.map((item) => {
585
+ const totals = calculateLineItemTotals({
586
+ quantity: item.quantity,
587
+ subtotal: Number(item.totals.line_subtotal),
588
+ subtotal_tax: Number(item.totals.line_subtotal_tax),
589
+ total: Number(item.totals.line_total),
590
+ total_tax: Number(item.totals.line_total_tax)
591
+ });
592
+ let itemStatus = "available";
593
+ const error = data.errors.find((e) => e.message.includes(item.name));
594
+ if (error) switch (error.code) {
595
+ case "woocommerce_rest_product_out_of_stock":
596
+ itemStatus = "out_of_stock";
597
+ break;
598
+ case "woocommerce_rest_cart_item_error":
599
+ itemStatus = "unavailable";
600
+ break;
601
+ }
602
+ if (item.low_stock_remaining) itemStatus = "low_stock";
603
+ const productSlug = new URL(item.permalink).pathname;
604
+ return {
605
+ key: item.key,
606
+ productId: item.id,
607
+ variationId: null,
608
+ type: item.type,
609
+ name: item.name,
610
+ sku: item.sku,
611
+ status: itemStatus,
612
+ quantity: item.quantity,
613
+ isSoldIndividually: item.sold_individually,
614
+ images: item.images.map((item$1) => ({
615
+ id: item$1.id,
616
+ name: item$1.name,
617
+ alt: item$1.alt,
618
+ src: item$1.src
619
+ })),
620
+ variations: item.variation.map((a) => ({
621
+ name: a.attribute,
622
+ attribute: a.raw_attribute,
623
+ value: a.value
624
+ })),
625
+ slug: productSlug,
626
+ description: item.description,
627
+ soldIndividually: item.sold_individually,
628
+ lowStockCount: item.low_stock_remaining,
629
+ prices: {
630
+ price: Number(item.prices.price),
631
+ salePrice: Number(item.prices.sale_price),
632
+ regularPrice: Number(item.prices.regular_price)
633
+ },
634
+ totals,
635
+ shortDescription: item.short_description
636
+ };
637
+ });
638
+ const couponLines = data.coupons.map((coupon) => {
639
+ return {
640
+ id: coupon.code,
641
+ code: coupon.code,
642
+ type: coupon.discount_type,
643
+ amount: Number(coupon.totals.total_discount),
644
+ taxAmount: Number(coupon.totals.total_discount_tax)
645
+ };
646
+ });
647
+ const packageLines = data.shipping_rates.map((pkg) => ({
648
+ id: Number(pkg.package_id),
649
+ name: pkg.name,
650
+ address: {
651
+ address1: pkg.destination.address_1,
652
+ address2: pkg.destination.address_2,
653
+ city: pkg.destination.city,
654
+ state: pkg.destination.state,
655
+ postcode: pkg.destination.postcode,
656
+ country: pkg.destination.country
657
+ },
658
+ items: pkg.items.map((item) => ({
659
+ key: item.key,
660
+ name: item.name,
661
+ quantity: item.quantity
662
+ })),
663
+ rates: pkg.shipping_rates.map((rate) => ({
664
+ id: rate.rate_id,
665
+ name: rate.name,
666
+ description: rate.description,
667
+ deliveryTime: rate.delivery_time,
668
+ amount: Number(rate.price),
669
+ taxAmount: Number(rate.taxes),
670
+ total: Number(rate.price) + Number(rate.taxes),
671
+ isSelected: rate.selected,
672
+ methodId: rate.method_id
673
+ }))
674
+ }));
675
+ const shippingLines = packageLines.reduce((acc, item) => {
676
+ const found = item.rates.find((a) => a.isSelected);
677
+ if (found) acc.push({
678
+ id: found.id,
679
+ label: found.name,
680
+ amount: found.amount,
681
+ taxAmount: found.taxAmount
682
+ });
683
+ return acc;
684
+ }, []);
685
+ const discountTotal = Number(data.totals.total_discount);
686
+ const discountTaxTotal = Number(data.totals.total_discount_tax);
687
+ const shippingTotal = Number(data.totals.total_shipping);
688
+ const shippingTaxTotal = Number(data.totals.total_shipping_tax);
689
+ const feeTotal = Number(data.totals.total_fees);
690
+ const feeTaxTotal = Number(data.totals.total_fees_tax);
691
+ const taxTotal = Number(data.totals.total_tax);
692
+ const total = Number(data.totals.total_price);
693
+ return {
694
+ lineItems,
695
+ couponLines,
696
+ packageLines,
697
+ shippingLines,
698
+ totalItems: data.items_count,
699
+ billing: data.billing_address.address_1.length ? deserializeCartBillingAddress(data) : null,
700
+ shipping: data.shipping_address.address_1.length ? deserializeCartShippingAddress(data) : null,
701
+ currencyFormat: deserializeCurrencyFormat(data.totals),
702
+ totals: {
703
+ discountTotal,
704
+ discountTaxTotal,
705
+ shippingTotal,
706
+ shippingTaxTotal,
707
+ feeTotal,
708
+ feeTaxTotal,
709
+ taxTotal,
710
+ total
711
+ }
712
+ };
713
+ }
714
+ function deserializeCartShippingAddress(cart) {
715
+ return {
716
+ address1: cart.shipping_address.address_1,
717
+ address2: cart.shipping_address.address_2,
718
+ city: cart.shipping_address.city,
719
+ company: cart.shipping_address.company,
720
+ country: cart.shipping_address.country,
721
+ firstName: cart.shipping_address.first_name,
722
+ lastName: cart.shipping_address.last_name,
723
+ phone: cart.shipping_address.phone,
724
+ postcode: cart.shipping_address.postcode,
725
+ state: cart.shipping_address.state
726
+ };
727
+ }
728
+ function deserializeCartBillingAddress(cart) {
729
+ return {
730
+ address1: cart.billing_address.address_1,
731
+ address2: cart.billing_address.address_2,
732
+ city: cart.billing_address.city,
733
+ company: cart.billing_address.company,
734
+ country: cart.billing_address.country,
735
+ firstName: cart.billing_address.first_name,
736
+ lastName: cart.billing_address.last_name,
737
+ phone: cart.billing_address.phone,
738
+ postcode: cart.billing_address.postcode,
739
+ state: cart.billing_address.state,
740
+ email: cart.billing_address.email
741
+ };
742
+ }
743
+ function calculateLineItemTotals(input) {
744
+ const unitPrice = input.subtotal / input.quantity;
745
+ const grossAmount = input.subtotal;
746
+ return {
747
+ unitPrice,
748
+ discountAmount: input.subtotal - input.total,
749
+ discountTaxAmount: input.subtotal_tax - input.total_tax,
750
+ grossAmount,
751
+ netAmount: input.total,
752
+ taxAmount: input.total_tax,
753
+ total: input.total + input.total_tax
754
+ };
755
+ }
756
+
757
+ //#endregion
758
+ //#region src/cart/index.ts
759
+ const CART_ROUTER = {
760
+ get: createProcedure({
761
+ scope: "api",
762
+ method: "GET",
763
+ path: "/cart",
764
+ output: Cart.nullable(),
765
+ errors: GET_CART_ERROR_MAP,
766
+ middlewares: [sessionMiddleware()]
767
+ }, async ({ context, errors }) => {
768
+ const response = await context.service.wordpress.get("/cart", {
769
+ base: WC_STORE_BASE,
770
+ headers: context.sessionHeaders
771
+ });
772
+ if (response.error) switch (response.error.code) {
773
+ default:
774
+ context.logger.error("Get cart unhandled error", response.error, { code: response.error.code });
775
+ throw errors.INTERNAL_SERVER_ERROR();
776
+ }
777
+ return deserializeCart(response.data);
778
+ }),
779
+ update: createProcedure({
780
+ scope: "api",
781
+ method: "PUT",
782
+ path: "/cart",
783
+ output: Cart,
784
+ body: UpdateCartInput,
785
+ errors: UPDATE_CART_ERROR_MAP,
786
+ middlewares: [sessionMiddleware()]
787
+ }, async ({ context, input: { body: input }, errors }) => {
788
+ const connInfo = await context.getConnInfo();
789
+ const defaultBilling = input.billing ?? {
790
+ ...input.shipping,
791
+ email: void 0
792
+ };
793
+ const updateData = {
794
+ billing_address: defaultBilling !== void 0 ? {
795
+ first_name: defaultBilling?.firstName ?? "",
796
+ last_name: defaultBilling?.lastName ?? "",
797
+ address_1: defaultBilling?.address1 ?? "",
798
+ address_2: defaultBilling?.address2 ?? "",
799
+ company: defaultBilling?.company ?? "",
800
+ email: defaultBilling?.email ?? "",
801
+ phone: defaultBilling?.phone ?? "",
802
+ city: defaultBilling?.city ?? "",
803
+ state: defaultBilling?.state ?? connInfo?.state ?? void 0,
804
+ country: defaultBilling?.country ?? connInfo?.country ?? void 0,
805
+ postcode: defaultBilling?.postcode ?? connInfo?.postcode ?? ""
806
+ } : {},
807
+ shipping_address: input.shipping !== void 0 ? {
808
+ first_name: input.shipping?.firstName ?? "",
809
+ last_name: input.shipping?.lastName ?? "",
810
+ address_1: input.shipping?.address1 ?? "",
811
+ address_2: input.shipping?.address2 ?? "",
812
+ company: input.shipping?.company ?? "",
813
+ phone: input.shipping?.phone ?? "",
814
+ city: input.shipping?.city ?? "",
815
+ state: input.shipping?.state ?? connInfo?.state ?? void 0,
816
+ country: input.shipping?.country ?? connInfo?.country ?? void 0,
817
+ postcode: input.shipping?.postcode ?? connInfo?.postcode ?? ""
818
+ } : {}
819
+ };
820
+ const response = await context.service.wordpress.post("/cart/update-customer", {
821
+ base: WC_STORE_BASE,
822
+ body: {
823
+ billing_address: updateData.billing_address,
824
+ shipping_address: updateData.shipping_address
825
+ },
826
+ headers: context.sessionHeaders
827
+ });
828
+ if (response.error) switch (response.error.code) {
829
+ default:
830
+ context.logger.error("Update cart customer unhandled error", response.error, { code: response.error.code });
831
+ throw errors.INTERNAL_SERVER_ERROR();
832
+ }
833
+ return deserializeCart(response.data);
834
+ }),
835
+ selectShippingRate: createProcedure({
836
+ scope: "api",
837
+ method: "PUT",
838
+ path: "/cart/shipping-rate",
839
+ body: SelectCartShippingRateInput,
840
+ output: Cart,
841
+ errors: SELECT_SHIPPING_RATE_ERROR_MAP,
842
+ middlewares: [sessionMiddleware()]
843
+ }, async ({ context, input: { body }, errors }) => {
844
+ const response = await context.service.wordpress.post("/cart/select-shipping-rate", {
845
+ base: WC_STORE_BASE,
846
+ headers: context.sessionHeaders,
847
+ body: {
848
+ rate_id: body.rateId,
849
+ package_id: body.packageId
850
+ }
851
+ });
852
+ if (response.error) switch (response.error.code) {
853
+ case "woocommerce_rest_cart_shipping_rate_not_found": throw errors.CART_SHIPPING_RATE_NOT_FOUND({ message: response.error.message });
854
+ case "woocommerce_rest_shipping_disabled": throw errors.CART_SHIPPING_DISABLED({ message: response.error.message });
855
+ default:
856
+ context.logger.error("Select shipping rate unhandled error", response.error, { code: response.error.code });
857
+ throw errors.INTERNAL_SERVER_ERROR();
858
+ }
859
+ return deserializeCart(response.data);
860
+ }),
861
+ items: {
862
+ add: createProcedure({
863
+ scope: "api",
864
+ method: "POST",
865
+ path: "/cart/items",
866
+ body: AddCartItemInput,
867
+ output: Cart,
868
+ errors: ADD_CART_ITEM_ERROR_MAP,
869
+ middlewares: [sessionMiddleware()]
870
+ }, async ({ context, input: { body: input }, errors }) => {
871
+ const response = await context.service.wordpress.post("/cart/add-item", {
872
+ body: {
873
+ id: input.productId,
874
+ quantity: input.quantity,
875
+ variation: input.variations ?? []
876
+ },
877
+ base: WC_STORE_BASE,
878
+ headers: context.sessionHeaders
879
+ });
880
+ if (response.error) switch (response.error.code) {
881
+ case "woocommerce_rest_product_out_of_stock": throw errors.CART_ITEM_OUT_OF_STOCK({ message: response.error.message });
882
+ case "woocommerce_rest_product_partially_out_of_stock": throw errors.CART_ITEM_INSUFFICIENT_STOCK({ message: response.error.message });
883
+ case "woocommerce_rest_product_not_purchasable": throw errors.CART_ITEM_NOT_PURCHASABLE({ message: response.error.message });
884
+ case "woocommerce_rest_product_invalid_quantity": throw errors.CART_ITEM_INVALID_QUANTITY({ message: response.error.message });
885
+ case "woocommerce_rest_cart_item_exists": throw errors.CART_ITEM_EXISTS({ message: response.error.message });
886
+ case "woocommerce_rest_cart_invalid_product":
887
+ case "woocommerce_rest_cart_invalid_parent_product": throw errors.CART_PRODUCT_INVALID({ message: response.error.message });
888
+ case "woocommerce_rest_invalid_variation_data":
889
+ case "woocommerce_rest_missing_attributes":
890
+ case "woocommerce_rest_missing_variation_data":
891
+ case "woocommerce_rest_variation_id_from_variation_data": throw errors.CART_VARIATION_INVALID({ message: response.error.message });
892
+ default:
893
+ context.logger.error("Add cart item unhandled error", response.error, { code: response.error.code });
894
+ throw errors.INTERNAL_SERVER_ERROR();
895
+ }
896
+ return deserializeCart(response.data);
897
+ }),
898
+ update: createProcedure({
899
+ scope: "api",
900
+ method: "PUT",
901
+ path: "/cart/items/{key}",
902
+ params: UpdateCartItemInput.pick({ key: true }),
903
+ body: UpdateCartItemInput.pick({ quantity: true }),
904
+ output: Cart,
905
+ errors: UPDATE_CART_ITEM_ERROR_MAP,
906
+ middlewares: [sessionMiddleware()]
907
+ }, async ({ context, input: { params, body }, errors }) => {
908
+ const response = await context.service.wordpress.post("/cart/update-item", {
909
+ body: {
910
+ key: params.key,
911
+ quantity: body.quantity
912
+ },
913
+ base: WC_STORE_BASE,
914
+ headers: context.sessionHeaders
915
+ });
916
+ if (response.error) switch (response.error.code) {
917
+ case "woocommerce_rest_cart_invalid_key": throw errors.CART_ITEM_NOT_FOUND({ message: response.error.message });
918
+ case "woocommerce_rest_cart_invalid_product": throw errors.CART_PRODUCT_INVALID({ message: response.error.message });
919
+ case "woocommerce_rest_product_out_of_stock": throw errors.CART_ITEM_OUT_OF_STOCK({ message: response.error.message });
920
+ case "woocommerce_rest_product_partially_out_of_stock": throw errors.CART_ITEM_INSUFFICIENT_STOCK({ message: response.error.message });
921
+ case "woocommerce_rest_product_invalid_quantity": throw errors.CART_ITEM_INVALID_QUANTITY({ message: response.error.message });
922
+ default:
923
+ context.logger.error("Update cart item unhandled error", response.error, { code: response.error.code });
924
+ throw errors.INTERNAL_SERVER_ERROR();
925
+ }
926
+ return deserializeCart(response.data);
927
+ }),
928
+ remove: createProcedure({
929
+ scope: "api",
930
+ method: "PATCH",
931
+ path: "/cart/items/{key}",
932
+ params: RemoveCartItemInput.pick({ key: true }),
933
+ output: Cart,
934
+ errors: REMOVE_CART_ITEM_ERROR_MAP,
935
+ middlewares: [sessionMiddleware()]
936
+ }, async ({ context, input: { params }, errors }) => {
937
+ const response = await context.service.wordpress.post("/cart/remove-item", {
938
+ body: { key: params.key },
939
+ base: WC_STORE_BASE,
940
+ headers: context.sessionHeaders
941
+ });
942
+ if (response.error) switch (response.error.code) {
943
+ case "woocommerce_rest_cart_invalid_key": throw errors.CART_ITEM_NOT_FOUND({ message: response.error.message });
944
+ default:
945
+ context.logger.error("Remove cart item unhandled error", response.error, { code: response.error.code });
946
+ throw errors.INTERNAL_SERVER_ERROR();
947
+ }
948
+ return deserializeCart(response.data);
949
+ })
950
+ },
951
+ coupons: {
952
+ apply: createProcedure({
953
+ scope: "api",
954
+ method: "POST",
955
+ path: "/cart/coupons",
956
+ body: ApplyCouponInput,
957
+ output: Cart,
958
+ errors: APPLY_COUPON_ERROR_MAP,
959
+ middlewares: [sessionMiddleware()]
960
+ }, async ({ context, input: { body }, errors }) => {
961
+ const response = await context.service.wordpress.post("/cart/apply-coupon", {
962
+ body: { code: body.code },
963
+ base: WC_STORE_BASE,
964
+ headers: context.sessionHeaders
965
+ });
966
+ if (response.error) switch (response.error.code) {
967
+ case "woocommerce_rest_cart_coupon_error": throw errors.CART_COUPON_INVALID({ message: response.error.message });
968
+ case "woocommerce_rest_cart_coupon_disabled": throw errors.CART_COUPON_DISABLED({ message: response.error.message });
969
+ default:
970
+ context.logger.error("Apply coupon unhandled error", response.error, { code: response.error.code });
971
+ throw errors.INTERNAL_SERVER_ERROR();
972
+ }
973
+ return deserializeCart(response.data);
974
+ }),
975
+ remove: createProcedure({
976
+ scope: "api",
977
+ method: "POST",
978
+ path: "/cart/coupons/{code}",
979
+ params: RemoveCouponInput.pick({ code: true }),
980
+ output: Cart,
981
+ errors: REMOVE_COUPON_ERROR_MAP,
982
+ middlewares: [sessionMiddleware()]
983
+ }, async ({ context, input, errors }) => {
984
+ const response = await context.service.wordpress.post("/cart/remove-coupon", {
985
+ body: { code: input.params.code },
986
+ base: WC_STORE_BASE,
987
+ headers: context.sessionHeaders
988
+ });
989
+ if (response.error) switch (response.error.code) {
990
+ case "woocommerce_rest_cart_coupon_error": throw errors.CART_COUPON_INVALID({ message: response.error.message });
991
+ case "woocommerce_rest_cart_coupon_disabled": throw errors.CART_COUPON_DISABLED({ message: response.error.message });
992
+ case "woocommerce_rest_cart_coupon_invalid_code": throw errors.CART_COUPON_NOT_FOUND({ message: response.error.message });
993
+ default:
994
+ context.logger.error("Remove coupon unhandled error", response.error, { code: response.error.code });
995
+ throw errors.INTERNAL_SERVER_ERROR();
996
+ }
997
+ return deserializeCart(response.data);
998
+ })
999
+ }
1000
+ };
1001
+
1002
+ //#endregion
1003
+ //#region src/checkout/error.ts
1004
+ const GET_CHECKOUT_ERROR_MAP = defineErrorMap({ CHECKOUT_ORDER_NOT_FOUND: {
1005
+ status: 404,
1006
+ message: "No checkout order found."
1007
+ } });
1008
+ const CONFIRM_CHECKOUT_ERROR_MAP = defineErrorMap({
1009
+ CHECKOUT_ADDRESS_COUNTRY_INVALID: {
1010
+ status: 400,
1011
+ message: "The address country is not supported."
1012
+ },
1013
+ CHECKOUT_ADDRESS_INVALID: {
1014
+ status: 400,
1015
+ message: "The provided address is invalid."
1016
+ },
1017
+ CHECKOUT_COUPON_INVALID: {
1018
+ status: 400,
1019
+ message: "A coupon on the cart is no longer valid."
1020
+ },
1021
+ CHECKOUT_EMAIL_INVALID: {
1022
+ status: 400,
1023
+ message: "The provided email address is invalid."
1024
+ },
1025
+ CHECKOUT_EMAIL_MISSING: {
1026
+ status: 400,
1027
+ message: "An email address is required."
1028
+ },
1029
+ CHECKOUT_PAYMENT_FAILED: {
1030
+ status: 400,
1031
+ message: "Payment could not be processed."
1032
+ },
1033
+ CHECKOUT_PAYMENT_METHOD_DISABLED: {
1034
+ status: 400,
1035
+ message: "The selected payment method is not available."
1036
+ },
1037
+ CHECKOUT_PAYMENT_METHOD_MISSING: {
1038
+ status: 400,
1039
+ message: "A payment method is required."
1040
+ },
1041
+ CHECKOUT_VALIDATION_FAILED: {
1042
+ status: 400,
1043
+ message: "Checkout validation failed."
1044
+ },
1045
+ CHECKOUT_GUEST_DISABLED: {
1046
+ status: 403,
1047
+ message: "Guest checkout is not allowed."
1048
+ },
1049
+ CHECKOUT_ORDER_NOT_FOUND: {
1050
+ status: 404,
1051
+ message: "No checkout order found."
1052
+ },
1053
+ CHECKOUT_CART_EMPTY: {
1054
+ status: 409,
1055
+ message: "The cart is empty."
1056
+ },
1057
+ CHECKOUT_CART_INVALID: {
1058
+ status: 409,
1059
+ message: "An item in the cart is no longer valid."
1060
+ },
1061
+ CHECKOUT_COUPONS_REMOVED: {
1062
+ status: 409,
1063
+ message: "One or more coupons were removed from the cart."
1064
+ },
1065
+ CHECKOUT_COUPON_RESERVATION_FAILED: {
1066
+ status: 409,
1067
+ message: "A coupon could not be reserved for this order."
1068
+ },
1069
+ CHECKOUT_PRODUCT_INSUFFICIENT_STOCK: {
1070
+ status: 409,
1071
+ message: "Not enough stock for one or more items in the cart."
1072
+ },
1073
+ CHECKOUT_PRODUCT_NOT_PURCHASABLE: {
1074
+ status: 409,
1075
+ message: "An item in the cart is no longer purchasable."
1076
+ },
1077
+ CHECKOUT_PRODUCT_OUT_OF_STOCK: {
1078
+ status: 409,
1079
+ message: "An item in the cart is out of stock."
1080
+ }
1081
+ });
1082
+ const RETRY_CHECKOUT_ERROR_MAP = defineErrorMap({
1083
+ CHECKOUT_EMAIL_INVALID: {
1084
+ status: 400,
1085
+ message: "The billing email is invalid."
1086
+ },
1087
+ CHECKOUT_PAYMENT_FAILED: {
1088
+ status: 400,
1089
+ message: "Payment could not be processed."
1090
+ },
1091
+ CHECKOUT_PAYMENT_METHOD_DISABLED: {
1092
+ status: 400,
1093
+ message: "The selected payment method is not available."
1094
+ },
1095
+ CHECKOUT_PAYMENT_METHOD_MISSING: {
1096
+ status: 400,
1097
+ message: "A payment method is required."
1098
+ },
1099
+ CHECKOUT_ORDER_FORBIDDEN: {
1100
+ status: 403,
1101
+ message: "You are not allowed to pay for this order."
1102
+ },
1103
+ CHECKOUT_ORDER_NOT_FOUND: {
1104
+ status: 404,
1105
+ message: "Order not found."
1106
+ },
1107
+ CHECKOUT_ORDER_STATUS_INVALID: {
1108
+ status: 409,
1109
+ message: "This order is not in a state that can be paid."
1110
+ }
1111
+ });
1112
+ const UPDATE_CHECKOUT_ERROR_MAP = defineErrorMap({
1113
+ CHECKOUT_COUPON_INVALID: {
1114
+ status: 400,
1115
+ message: "A coupon on the cart is no longer valid."
1116
+ },
1117
+ CHECKOUT_PAYMENT_METHOD_DISABLED: {
1118
+ status: 400,
1119
+ message: "The selected payment method is not available."
1120
+ },
1121
+ CHECKOUT_ORDER_NOT_FOUND: {
1122
+ status: 404,
1123
+ message: "No checkout order found."
1124
+ },
1125
+ CHECKOUT_CART_EMPTY: {
1126
+ status: 409,
1127
+ message: "The cart is empty."
1128
+ },
1129
+ CHECKOUT_CART_INVALID: {
1130
+ status: 409,
1131
+ message: "An item in the cart is no longer valid."
1132
+ },
1133
+ CHECKOUT_PRODUCT_INSUFFICIENT_STOCK: {
1134
+ status: 409,
1135
+ message: "Not enough stock for one or more items in the cart."
1136
+ },
1137
+ CHECKOUT_PRODUCT_NOT_PURCHASABLE: {
1138
+ status: 409,
1139
+ message: "An item in the cart is no longer purchasable."
1140
+ },
1141
+ CHECKOUT_PRODUCT_OUT_OF_STOCK: {
1142
+ status: 409,
1143
+ message: "An item in the cart is out of stock."
1144
+ }
1145
+ });
1146
+
1147
+ //#endregion
1148
+ //#region src/checkout/schema.ts
1149
+ const CheckoutAdditionalFields = z$2.record(z$2.string(), z$2.union([z$2.string(), z$2.boolean()]));
1150
+ const CheckoutPaymentData = z$2.array(z$2.object({
1151
+ key: z$2.string(),
1152
+ value: z$2.union([z$2.string(), z$2.boolean()])
1153
+ }));
1154
+ const Checkout = z$2.object({
1155
+ cart: Cart.nullable(),
1156
+ billingAddress: BillingAddress,
1157
+ shippingAddress: ShippingAddress,
1158
+ paymentMethod: z$2.string(),
1159
+ customerNote: z$2.string(),
1160
+ additionalFields: CheckoutAdditionalFields,
1161
+ paymentResult: z$2.object({
1162
+ status: z$2.enum([
1163
+ "success",
1164
+ "pending",
1165
+ "failure",
1166
+ "error"
1167
+ ]),
1168
+ data: z$2.array(z$2.object({
1169
+ key: z$2.string(),
1170
+ value: z$2.string()
1171
+ })).optional(),
1172
+ redirectUrl: z$2.string()
1173
+ }).nullable()
1174
+ });
1175
+ const UpdateCheckoutInput = z$2.object({
1176
+ paymentMethod: z$2.string().optional(),
1177
+ customerNote: z$2.string().optional(),
1178
+ recalculateTotals: z$2.boolean().optional(),
1179
+ additionalFields: CheckoutAdditionalFields.optional()
1180
+ });
1181
+ const ConfirmCheckoutInput = z$2.object({
1182
+ customerPassword: z$2.string().optional(),
1183
+ paymentData: CheckoutPaymentData.optional()
1184
+ });
1185
+ const RetryCheckoutInput = z$2.object({
1186
+ key: z$2.string(),
1187
+ orderId: NumberLike,
1188
+ paymentMethod: z$2.string(),
1189
+ billingEmail: z$2.email().optional(),
1190
+ billingAddress: BillingAddress.optional(),
1191
+ paymentData: CheckoutPaymentData.optional(),
1192
+ shippingAddress: ShippingAddress.optional()
1193
+ });
1194
+
1195
+ //#endregion
1196
+ //#region src/checkout/utils.ts
1197
+ function deserializeCheckout(data) {
1198
+ return {
1199
+ cart: data.__experimentalCart ? deserializeCart(data.__experimentalCart) : null,
1200
+ shippingAddress: {
1201
+ address1: data.shipping_address.address_1,
1202
+ address2: data.shipping_address.address_2,
1203
+ city: data.shipping_address.city,
1204
+ company: data.shipping_address.company,
1205
+ country: data.shipping_address.country,
1206
+ firstName: data.shipping_address.first_name,
1207
+ lastName: data.shipping_address.last_name,
1208
+ phone: data.shipping_address.phone,
1209
+ postcode: data.shipping_address.postcode,
1210
+ state: data.shipping_address.state
1211
+ },
1212
+ billingAddress: {
1213
+ address1: data.billing_address.address_1,
1214
+ address2: data.billing_address.address_2,
1215
+ city: data.billing_address.city,
1216
+ company: data.billing_address.company,
1217
+ country: data.billing_address.country,
1218
+ email: data.billing_address.email,
1219
+ firstName: data.billing_address.first_name,
1220
+ lastName: data.billing_address.last_name,
1221
+ phone: data.billing_address.phone,
1222
+ postcode: data.billing_address.postcode,
1223
+ state: data.billing_address.state
1224
+ },
1225
+ additionalFields: data.additional_fields,
1226
+ customerNote: data.customer_note,
1227
+ paymentMethod: data.payment_method,
1228
+ paymentResult: data.payment_result?.payment_status ? {
1229
+ status: data.payment_result.payment_status,
1230
+ redirectUrl: data.payment_result.redirect_url,
1231
+ data: data.payment_result.payment_details
1232
+ } : null
1233
+ };
1234
+ }
1235
+
1236
+ //#endregion
1237
+ //#region src/checkout/index.ts
1238
+ const CHECKOUT_ROUTER = {
1239
+ get: createProcedure({
1240
+ scope: "api",
1241
+ method: "GET",
1242
+ path: "/checkout",
1243
+ output: Checkout,
1244
+ errors: GET_CHECKOUT_ERROR_MAP,
1245
+ middlewares: [sessionMiddleware()]
1246
+ }, async ({ context, errors }) => {
1247
+ const response = await context.service.wordpress.get("/checkout", {
1248
+ base: WC_STORE_BASE,
1249
+ headers: context.sessionHeaders
1250
+ });
1251
+ if (response.error) switch (response.error.code) {
1252
+ case "woocommerce_rest_checkout_missing_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: response.error.message });
1253
+ default:
1254
+ context.logger.error("Get checkout unhandled error", response.error, { code: response.error.code });
1255
+ throw errors.INTERNAL_SERVER_ERROR();
1256
+ }
1257
+ return deserializeCheckout(response.data);
1258
+ }),
1259
+ update: createProcedure({
1260
+ scope: "api",
1261
+ method: "PUT",
1262
+ path: "/checkout",
1263
+ body: UpdateCheckoutInput,
1264
+ output: Checkout,
1265
+ errors: UPDATE_CHECKOUT_ERROR_MAP,
1266
+ middlewares: [sessionMiddleware()]
1267
+ }, async ({ context, input, errors }) => {
1268
+ const response = await context.service.wordpress.put("/checkout", {
1269
+ base: WC_STORE_BASE,
1270
+ body: {
1271
+ order_notes: input.body.customerNote,
1272
+ payment_method: input.body.paymentMethod,
1273
+ additional_fields: input.body.additionalFields,
1274
+ __experimental_calc_totals: input.body.recalculateTotals
1275
+ },
1276
+ headers: context.sessionHeaders
1277
+ });
1278
+ if (response.error) switch (response.error.code) {
1279
+ case "woocommerce_rest_cart_coupon_error": throw errors.CHECKOUT_COUPON_INVALID({ message: response.error.message });
1280
+ case "woocommerce_rest_checkout_payment_method_disabled": throw errors.CHECKOUT_PAYMENT_METHOD_DISABLED({ message: response.error.message });
1281
+ case "woocommerce_rest_checkout_missing_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: response.error.message });
1282
+ case "woocommerce_rest_cart_empty": throw errors.CHECKOUT_CART_EMPTY({ message: response.error.message });
1283
+ case "woocommerce_rest_cart_item_error": throw errors.CHECKOUT_CART_INVALID({ message: response.error.message });
1284
+ case "woocommerce_rest_product_partially_out_of_stock": throw errors.CHECKOUT_PRODUCT_INSUFFICIENT_STOCK({ message: response.error.message });
1285
+ case "woocommerce_rest_product_not_purchasable": throw errors.CHECKOUT_PRODUCT_NOT_PURCHASABLE({ message: response.error.message });
1286
+ case "woocommerce_rest_product_out_of_stock": throw errors.CHECKOUT_PRODUCT_OUT_OF_STOCK({ message: response.error.message });
1287
+ default:
1288
+ context.logger.error("Update checkout unhandled error", response.error, { code: response.error.code });
1289
+ throw errors.INTERNAL_SERVER_ERROR();
1290
+ }
1291
+ return deserializeCheckout(response.data);
1292
+ }),
1293
+ confirm: createProcedure({
1294
+ scope: "api",
1295
+ method: "POST",
1296
+ path: "/checkout",
1297
+ body: ConfirmCheckoutInput,
1298
+ output: Checkout,
1299
+ errors: CONFIRM_CHECKOUT_ERROR_MAP,
1300
+ middlewares: [sessionMiddleware()]
1301
+ }, async ({ context, input, errors }) => {
1302
+ const checkoutResponse = await context.service.wordpress.get("/checkout", {
1303
+ base: WC_STORE_BASE,
1304
+ headers: context.sessionHeaders
1305
+ });
1306
+ if (checkoutResponse.error) switch (checkoutResponse.error.code) {
1307
+ case "woocommerce_rest_checkout_missing_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: checkoutResponse.error.message });
1308
+ default:
1309
+ context.logger.error("Get checkout for confirm unhandled error", checkoutResponse.error, { code: checkoutResponse.error.code });
1310
+ throw errors.INTERNAL_SERVER_ERROR();
1311
+ }
1312
+ const confirmResponse = await context.service.wordpress.post("/checkout", {
1313
+ base: WC_STORE_BASE,
1314
+ body: {
1315
+ payment_data: input.body.paymentData,
1316
+ customer_password: input.body.customerPassword,
1317
+ customer_note: checkoutResponse.data.customer_note,
1318
+ payment_method: checkoutResponse.data.payment_method,
1319
+ create_account: !!input.body.customerPassword?.length,
1320
+ billing_address: checkoutResponse.data.billing_address,
1321
+ shipping_address: checkoutResponse.data.shipping_address,
1322
+ additional_fields: checkoutResponse.data.additional_fields
1323
+ },
1324
+ headers: context.sessionHeaders
1325
+ });
1326
+ if (confirmResponse.error) switch (confirmResponse.error.code) {
1327
+ case "woocommerce_rest_invalid_address": throw errors.CHECKOUT_ADDRESS_INVALID({ message: confirmResponse.error.message });
1328
+ case "woocommerce_rest_invalid_address_country": throw errors.CHECKOUT_ADDRESS_COUNTRY_INVALID({ message: confirmResponse.error.message });
1329
+ case "woocommerce_rest_cart_coupon_error": throw errors.CHECKOUT_COUPON_INVALID({ message: confirmResponse.error.message });
1330
+ case "woocommerce_rest_invalid_email_address": throw errors.CHECKOUT_EMAIL_INVALID({ message: confirmResponse.error.message });
1331
+ case "woocommerce_rest_missing_email_address": throw errors.CHECKOUT_EMAIL_MISSING({ message: confirmResponse.error.message });
1332
+ case "woocommerce_rest_checkout_process_payment_error": throw errors.CHECKOUT_PAYMENT_FAILED({ message: confirmResponse.error.message });
1333
+ case "woocommerce_rest_checkout_payment_method_disabled": throw errors.CHECKOUT_PAYMENT_METHOD_DISABLED({ message: confirmResponse.error.message });
1334
+ case "woocommerce_rest_checkout_missing_payment_method": throw errors.CHECKOUT_PAYMENT_METHOD_MISSING({ message: confirmResponse.error.message });
1335
+ case "woocommerce_rest_checkout_custom_validation_error": throw errors.CHECKOUT_VALIDATION_FAILED({ message: confirmResponse.error.message });
1336
+ case "woocommerce_rest_guest_checkout_disabled": throw errors.CHECKOUT_GUEST_DISABLED({ message: confirmResponse.error.message });
1337
+ case "woocommerce_rest_checkout_missing_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: confirmResponse.error.message });
1338
+ case "woocommerce_rest_cart_empty": throw errors.CHECKOUT_CART_EMPTY({ message: confirmResponse.error.message });
1339
+ case "woocommerce_rest_cart_item_error": throw errors.CHECKOUT_CART_INVALID({ message: confirmResponse.error.message });
1340
+ case "removed_coupons": throw errors.CHECKOUT_COUPONS_REMOVED({ message: confirmResponse.error.message });
1341
+ case "woocommerce_rest_coupon_reserve_failed": throw errors.CHECKOUT_COUPON_RESERVATION_FAILED({ message: confirmResponse.error.message });
1342
+ case "woocommerce_rest_product_partially_out_of_stock": throw errors.CHECKOUT_PRODUCT_INSUFFICIENT_STOCK({ message: confirmResponse.error.message });
1343
+ case "woocommerce_rest_product_not_purchasable": throw errors.CHECKOUT_PRODUCT_NOT_PURCHASABLE({ message: confirmResponse.error.message });
1344
+ case "woocommerce_rest_product_out_of_stock": throw errors.CHECKOUT_PRODUCT_OUT_OF_STOCK({ message: confirmResponse.error.message });
1345
+ default:
1346
+ context.logger.error("Confirm checkout unhandled error", confirmResponse.error, { code: confirmResponse.error.code });
1347
+ throw errors.INTERNAL_SERVER_ERROR();
1348
+ }
1349
+ return deserializeCheckout(confirmResponse.data);
1350
+ }),
1351
+ retry: createProcedure({
1352
+ scope: "api",
1353
+ method: "POST",
1354
+ path: "/checkout/{orderId}",
1355
+ params: RetryCheckoutInput.pick({ orderId: true }),
1356
+ body: RetryCheckoutInput.omit({ orderId: true }),
1357
+ output: Checkout,
1358
+ errors: RETRY_CHECKOUT_ERROR_MAP,
1359
+ middlewares: [sessionMiddleware()]
1360
+ }, async ({ context, input, errors }) => {
1361
+ const response = await context.service.wordpress.post(`/checkout/${input.params.orderId}`, {
1362
+ base: WC_STORE_BASE,
1363
+ body: {
1364
+ key: input.body.key,
1365
+ id: input.params.orderId,
1366
+ payment_data: input.body.paymentData,
1367
+ billing_email: input.body.billingEmail,
1368
+ payment_method: input.body.paymentMethod,
1369
+ billing_address: input.body.billingAddress ?? {},
1370
+ shipping_address: input.body.shippingAddress ?? {}
1371
+ },
1372
+ headers: context.sessionHeaders
1373
+ });
1374
+ if (response.error) switch (response.error.code) {
1375
+ case "woocommerce_rest_invalid_billing_email": throw errors.CHECKOUT_EMAIL_INVALID({ message: response.error.message });
1376
+ case "woocommerce_rest_checkout_process_payment_error": throw errors.CHECKOUT_PAYMENT_FAILED({ message: response.error.message });
1377
+ case "woocommerce_rest_checkout_payment_method_disabled": throw errors.CHECKOUT_PAYMENT_METHOD_DISABLED({ message: response.error.message });
1378
+ case "woocommerce_rest_checkout_missing_payment_method": throw errors.CHECKOUT_PAYMENT_METHOD_MISSING({ message: response.error.message });
1379
+ case "woocommerce_rest_invalid_user": throw errors.CHECKOUT_ORDER_FORBIDDEN({ message: response.error.message });
1380
+ case "woocommerce_rest_invalid_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: response.error.message });
1381
+ case "invalid_order_update_status": throw errors.CHECKOUT_ORDER_STATUS_INVALID({ message: response.error.message });
1382
+ default:
1383
+ context.logger.error("Retry checkout unhandled error", response.error, {
1384
+ orderId: input.params.orderId,
1385
+ code: response.error.code
1386
+ });
1387
+ throw errors.INTERNAL_SERVER_ERROR();
1388
+ }
1389
+ return deserializeCheckout(response.data);
1390
+ })
1391
+ };
1392
+
1393
+ //#endregion
1394
+ //#region src/customer/schema.ts
1395
+ const Customer = z$2.object({
1396
+ id: z$2.number(),
1397
+ email: z$2.string(),
1398
+ firstName: z$2.string(),
1399
+ lastName: z$2.string(),
1400
+ role: z$2.string(),
1401
+ username: z$2.string(),
1402
+ billing: BillingAddress,
1403
+ shipping: ShippingAddress,
1404
+ isPayingCustomer: z$2.boolean(),
1405
+ avatarUrl: z$2.string().nullable(),
1406
+ registeredAt: z$2.number(),
1407
+ meta: Metadata
1408
+ });
1409
+
1410
+ //#endregion
1411
+ //#region src/customer/utils.ts
1412
+ function deserializeCustomer(data) {
1413
+ return {
1414
+ id: data.id,
1415
+ avatarUrl: data.avatar_url.length ? data.avatar_url : null,
1416
+ billing: {
1417
+ firstName: data.billing.first_name,
1418
+ lastName: data.billing.last_name,
1419
+ address1: data.billing.address_1,
1420
+ city: data.billing.city,
1421
+ country: data.billing.country,
1422
+ email: data.billing.email,
1423
+ phone: data.billing.phone,
1424
+ postcode: data.billing.postcode,
1425
+ state: data.billing.state,
1426
+ address2: data.billing.address_2,
1427
+ company: data.billing.company
1428
+ },
1429
+ shipping: {
1430
+ firstName: data.shipping.first_name,
1431
+ lastName: data.shipping.last_name,
1432
+ address1: data.shipping.address_1,
1433
+ city: data.shipping.city,
1434
+ country: data.shipping.country,
1435
+ phone: data.shipping.phone,
1436
+ postcode: data.shipping.postcode,
1437
+ state: data.shipping.state,
1438
+ address2: data.shipping.address_2,
1439
+ company: data.shipping.company
1440
+ },
1441
+ email: data.email,
1442
+ firstName: data.first_name,
1443
+ lastName: data.last_name,
1444
+ isPayingCustomer: data.is_paying_customer,
1445
+ meta: toPublicMetadata(data.meta_data),
1446
+ registeredAt: new Date(data.date_created).getTime(),
1447
+ role: data.role,
1448
+ username: data.username
1449
+ };
1450
+ }
1451
+
1452
+ //#endregion
1453
+ //#region src/customer/index.ts
1454
+ const CUSTOMER_ROUTER = { get: createProcedure({
1455
+ scope: "api",
1456
+ method: "GET",
1457
+ path: "/customers",
1458
+ output: Customer
1459
+ }, async ({ context, errors }) => {
1460
+ const auth = await context.getAuthUser();
1461
+ if (!auth) throw errors.FORBIDDEN();
1462
+ const response = await context.service.wordpress.get(`/customers/${auth.id}`, { base: WC_CORE_BASE });
1463
+ if (response.error) throw response.error;
1464
+ return deserializeCustomer(response.data);
1465
+ }) };
1466
+
1467
+ //#endregion
1468
+ //#region src/product/error.ts
1469
+ const GET_PRODUCT_ERROR_MAP = defineErrorMap({ PRODUCT_NOT_FOUND: {
1470
+ status: 404,
1471
+ message: "Product not found."
1472
+ } });
1473
+ const LIST_PRODUCT_ERROR_MAP = defineErrorMap({});
1474
+ const FILTER_PRODUCT_ERROR_MAP = defineErrorMap({});
1475
+
1476
+ //#endregion
1477
+ //#region src/product/utils.ts
1478
+ function deserializeProduct(data) {
1479
+ return {
1480
+ id: data.id,
1481
+ type: data.type,
1482
+ slug: data.slug,
1483
+ name: data.name,
1484
+ sku: data.sku,
1485
+ description: data.description,
1486
+ shortDescription: data.short_description,
1487
+ prices: {
1488
+ price: +data.kizlo.prices.price,
1489
+ salePrice: +data.kizlo.prices.sale_price,
1490
+ regularPrice: +data.kizlo.prices.regular_price
1491
+ },
1492
+ isSoldIndividually: data.sold_individually,
1493
+ onSaleFrom: data.date_on_sale_from ? toTimestamp(data.date_on_sale_from) : null,
1494
+ lowStockRemaining: "data.low_stock_amount",
1495
+ onSaleTo: data.date_on_sale_to ? toTimestamp(data.date_on_sale_to) : null,
1496
+ isInStock: data.stock_status === "instock",
1497
+ stock: data.stock_quantity,
1498
+ images: data.images.map((item) => ({
1499
+ id: item.id,
1500
+ src: item.src,
1501
+ name: item.name,
1502
+ alt: item.alt
1503
+ })),
1504
+ categories: data.categories.map((category) => ({
1505
+ id: category.id,
1506
+ name: category.name,
1507
+ slug: category.slug
1508
+ })),
1509
+ tags: data.tags.map((tag) => ({
1510
+ id: tag.id,
1511
+ name: tag.name,
1512
+ slug: tag.slug
1513
+ })),
1514
+ averageRating: data.average_rating,
1515
+ reviewCount: data.rating_count,
1516
+ attributes: data.kizlo.attributes.map((item) => ({
1517
+ id: item.id,
1518
+ hasVariations: item.has_variations,
1519
+ name: item.name,
1520
+ taxonomy: item.taxonomy,
1521
+ terms: item.terms
1522
+ })),
1523
+ groupedProducts: data.grouped_products,
1524
+ isOnBackorder: data.backordered,
1525
+ isPurchasable: data.purchasable,
1526
+ isOnSale: data.on_sale,
1527
+ parentId: data.parent_id,
1528
+ brands: data.brands,
1529
+ variations: data.kizlo.variations,
1530
+ hasOptions: !!data.kizlo.variations.length,
1531
+ currencyFormat: deserializeCurrencyFormat(data.kizlo.currency_format),
1532
+ meta: toPublicMetadata(data.meta_data),
1533
+ seo: null
1534
+ };
1535
+ }
1536
+ function deserializeStoreProduct(data) {
1537
+ return {
1538
+ id: data.id,
1539
+ type: data.type,
1540
+ name: data.name,
1541
+ slug: data.slug,
1542
+ sku: data.sku,
1543
+ description: data.description,
1544
+ shortDescription: data.short_description,
1545
+ isInStock: data.is_in_stock,
1546
+ reviewCount: data.review_count,
1547
+ averageRating: data.average_rating,
1548
+ lowStockRemaining: data.low_stock_remaining,
1549
+ isSoldIndividually: data.sold_individually,
1550
+ prices: {
1551
+ price: +data.prices.price,
1552
+ salePrice: +data.prices.sale_price,
1553
+ regularPrice: +data.prices.regular_price
1554
+ },
1555
+ images: data.images.map((item) => ({
1556
+ id: item.id,
1557
+ src: item.src,
1558
+ name: item.name,
1559
+ alt: item.alt
1560
+ })),
1561
+ categories: data.categories.map((category) => ({
1562
+ id: category.id,
1563
+ name: category.name,
1564
+ slug: category.slug
1565
+ })),
1566
+ tags: data.tags.map((tag) => ({
1567
+ id: tag.id,
1568
+ name: tag.name,
1569
+ slug: tag.slug
1570
+ })),
1571
+ attributes: data.attributes.map((item) => ({
1572
+ id: item.id,
1573
+ name: item.name,
1574
+ terms: item.terms,
1575
+ taxonomy: item.taxonomy,
1576
+ hasVariations: item.has_variations
1577
+ })),
1578
+ currencyFormat: deserializeCurrencyFormat(data.prices),
1579
+ brands: data.brands,
1580
+ groupedProducts: data.grouped_products,
1581
+ hasOptions: data.has_options,
1582
+ isOnBackorder: data.is_on_backorder,
1583
+ isPurchasable: data.is_purchasable,
1584
+ isOnSale: data.on_sale,
1585
+ parentId: data.parent,
1586
+ variations: data.variations,
1587
+ stock: data.extensions.kizlo.stock,
1588
+ onSaleFrom: data.extensions.kizlo.on_sale_from ? toTimestamp(data.extensions.kizlo.on_sale_from) : null,
1589
+ onSaleTo: data.extensions.kizlo.on_sale_to ? toTimestamp(data.extensions.kizlo.on_sale_to) : null,
1590
+ seo: null,
1591
+ meta: {}
1592
+ };
1593
+ }
1594
+ function deserializeProductFilters(data) {
1595
+ if (!data.price_range) return null;
1596
+ const maxPrice = +data.price_range.max_price;
1597
+ const minPrice = +data.price_range.min_price;
1598
+ return {
1599
+ stockStatuses: data.stock_status_counts ?? [],
1600
+ taxonomyTerms: data.kizlo.taxonomy_counts.map((item) => ({
1601
+ id: item.id,
1602
+ name: item.name,
1603
+ count: item.count,
1604
+ description: item.description,
1605
+ parentId: item.parent,
1606
+ slug: item.slug,
1607
+ taxonomy: item.taxonomy,
1608
+ image: item.thumbnail ? {
1609
+ id: 0,
1610
+ alt: item.name,
1611
+ name: item.name,
1612
+ src: item.thumbnail
1613
+ } : null
1614
+ })),
1615
+ attributeTerms: data.kizlo.attribute_counts.map((item) => ({
1616
+ id: item.id,
1617
+ name: item.name,
1618
+ count: item.count,
1619
+ description: item.description,
1620
+ parentId: item.parent,
1621
+ slug: item.slug,
1622
+ swatch: item.swatch,
1623
+ type: item.swatch_type,
1624
+ taxonomy: item.taxonomy
1625
+ })),
1626
+ priceRange: {
1627
+ maxPrice,
1628
+ minPrice
1629
+ },
1630
+ currencyFormat: deserializeCurrencyFormat(data.price_range)
1631
+ };
1632
+ }
1633
+ function serializeProductListInput(data) {
1634
+ return {
1635
+ after: data?.after,
1636
+ attribute_relation: data?.attributeRelation,
1637
+ before: data?.before,
1638
+ brand: data?.brand,
1639
+ brand_operator: data?.brandOperator,
1640
+ catalog_visibility: data?.catalogVisibility,
1641
+ category: data?.category,
1642
+ category_operator: data?.categoryOperator,
1643
+ featured: data?.featured,
1644
+ max_price: data?.maxPrice ? String(data?.maxPrice) : void 0,
1645
+ min_price: data?.minPrice ? String(data?.minPrice) : void 0,
1646
+ on_sale: data?.onSale,
1647
+ orderby: data?.orderby,
1648
+ parent: normalizeArrayableValue(data?.parent),
1649
+ parent_exclude: normalizeArrayableValue(data?.parentExclude),
1650
+ rating: normalizeArrayableValue(data?.rating)?.map(Number),
1651
+ sku: data?.sku,
1652
+ slug: data?.slug,
1653
+ stock_status: normalizeArrayableValue(data?.stockStatus),
1654
+ tag: data?.tag,
1655
+ tag_operator: data?.tagOperator,
1656
+ type: data?.type,
1657
+ attributes: data?.attributes?.map((item) => ({
1658
+ operator: item.operator,
1659
+ attribute: item.attribute,
1660
+ slug: normalizeArrayableValue(item.slug),
1661
+ term_id: normalizeArrayableValue(item.termId)
1662
+ })),
1663
+ exclude: normalizeArrayableValue(data?.exclude),
1664
+ include: normalizeArrayableValue(data?.include),
1665
+ offset: data?.offset,
1666
+ order: data?.order,
1667
+ page: data?.page,
1668
+ per_page: data?.perPage,
1669
+ related: data?.related,
1670
+ search: data?.search
1671
+ };
1672
+ }
1673
+ function toTimestamp(date) {
1674
+ return new Date(date).getTime();
1675
+ }
1676
+
1677
+ //#endregion
1678
+ //#region src/product/index.ts
1679
+ const PRODUCT_ROUTER = {
1680
+ get: createProcedure({
1681
+ scope: "api",
1682
+ method: "GET",
1683
+ path: "/products/{identifier}",
1684
+ params: RetrieveProductInput.pick({ identifier: true }),
1685
+ query: RetrieveProductInput.pick({ previewToken: true }).optional(),
1686
+ output: Product,
1687
+ errors: GET_PRODUCT_ERROR_MAP
1688
+ }, async ({ context, input, errors }) => {
1689
+ if (input.query?.previewToken) {
1690
+ const result = await context.verifyPreviewToken(input.query.previewToken);
1691
+ if (!result) throw errors.PRODUCT_NOT_FOUND();
1692
+ const response$1 = await context.service.wordpress.get(`/products/${result.id}`, { base: WC_CORE_BASE });
1693
+ if (response$1.error) switch (response$1.error.code) {
1694
+ case "woocommerce_rest_product_invalid_id": throw errors.PRODUCT_NOT_FOUND({ message: response$1.error.message });
1695
+ default:
1696
+ context.logger.error("Get product preview unhandled error", response$1.error, {
1697
+ id: result.id,
1698
+ code: response$1.error.code
1699
+ });
1700
+ throw errors.INTERNAL_SERVER_ERROR();
1701
+ }
1702
+ return deserializeProduct(response$1.data);
1703
+ }
1704
+ const response = await context.service.wordpress.get("/products", {
1705
+ searchParams: { slug: input.params.identifier },
1706
+ base: WC_CORE_BASE
1707
+ });
1708
+ if (response.error) switch (response.error.code) {
1709
+ default:
1710
+ context.logger.error("Get product unhandled error", response.error, {
1711
+ identifier: input.params.identifier,
1712
+ code: response.error.code
1713
+ });
1714
+ throw errors.INTERNAL_SERVER_ERROR();
1715
+ }
1716
+ const data = response.data[0];
1717
+ if (!data) throw errors.PRODUCT_NOT_FOUND();
1718
+ return deserializeProduct(data);
1719
+ }),
1720
+ list: createProcedure({
1721
+ scope: "api",
1722
+ method: "GET",
1723
+ path: "/products",
1724
+ query: ListProductInput.optional(),
1725
+ output: ProductList,
1726
+ errors: LIST_PRODUCT_ERROR_MAP
1727
+ }, async ({ context, input, errors }) => {
1728
+ const searchParams = serializeProductListInput(input.query);
1729
+ const response = await context.service.wordpress.get("/products", {
1730
+ base: WC_STORE_BASE,
1731
+ searchParams: { ...searchParams }
1732
+ });
1733
+ if (response.error) switch (response.error.code) {
1734
+ default:
1735
+ context.logger.error("List products unhandled error", response.error, { code: response.error.code });
1736
+ throw errors.INTERNAL_SERVER_ERROR();
1737
+ }
1738
+ const list = context.service.wordpress.resolveList({
1739
+ data: response.data,
1740
+ headers: response.headers,
1741
+ searchParams: { ...searchParams }
1742
+ });
1743
+ return {
1744
+ items: list.items.map(deserializeStoreProduct),
1745
+ meta: deserializeListMetadata(list.meta)
1746
+ };
1747
+ }),
1748
+ filters: createProcedure({
1749
+ scope: "api",
1750
+ method: "GET",
1751
+ path: "/products/filters",
1752
+ query: RetrieveProductFiltersInput.optional(),
1753
+ output: ProductFilters.nullable()
1754
+ }, async ({ context, errors, input }) => {
1755
+ const searchParams = serializeProductListInput(input.query);
1756
+ const response = await context.service.wordpress.get("/products/collection-data", {
1757
+ base: WC_STORE_BASE,
1758
+ searchParams: {
1759
+ ...searchParams,
1760
+ calculate_price_range: true,
1761
+ calculate_rating_counts: input.query?.ratingFilters,
1762
+ calculate_taxonomy_counts: input.query?.taxonomyFilters,
1763
+ calculate_stock_status_counts: input.query?.stockStatusFilters,
1764
+ calculate_attribute_counts: input.query?.attributeFilters?.map((item) => ({
1765
+ taxonomy: item.taxonomy,
1766
+ query_type: item.queryType
1767
+ }))
1768
+ }
1769
+ });
1770
+ if (response.error) switch (response.error.code) {
1771
+ default:
1772
+ context.logger.error("Filter products unhandled error", response.error, { code: response.error.code });
1773
+ throw errors.INTERNAL_SERVER_ERROR();
1774
+ }
1775
+ return deserializeProductFilters(response.data);
1776
+ })
1777
+ };
1778
+
1779
+ //#endregion
1780
+ //#region src/index.ts
1781
+ function woocommerce() {
1782
+ return createExtension({
1783
+ id: "woocommerce",
1784
+ init: () => {
1785
+ return { router: {
1786
+ cart: CART_ROUTER,
1787
+ products: PRODUCT_ROUTER,
1788
+ checkout: CHECKOUT_ROUTER,
1789
+ customers: CUSTOMER_ROUTER
1790
+ } };
1791
+ }
1792
+ });
1793
+ }
1794
+
1795
+ //#endregion
1796
+ export { woocommerce };