@kizlo/woocommerce 0.1.9 → 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.
- package/dist/index.d.ts +6 -6
- package/dist/index.js +239 -179
- package/dist/test.js +38 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1329,7 +1329,7 @@ declare function woocommerce(): kizlo0.Extension<"woocommerce", {
|
|
|
1329
1329
|
attributes: {
|
|
1330
1330
|
id: number;
|
|
1331
1331
|
name: string;
|
|
1332
|
-
taxonomy: string;
|
|
1332
|
+
taxonomy: string | null;
|
|
1333
1333
|
hasVariations: boolean;
|
|
1334
1334
|
terms: {
|
|
1335
1335
|
id: number;
|
|
@@ -1537,7 +1537,7 @@ declare function woocommerce(): kizlo0.Extension<"woocommerce", {
|
|
|
1537
1537
|
attributes: {
|
|
1538
1538
|
id: number;
|
|
1539
1539
|
name: string;
|
|
1540
|
-
taxonomy: string;
|
|
1540
|
+
taxonomy: string | null;
|
|
1541
1541
|
hasVariations: boolean;
|
|
1542
1542
|
terms: {
|
|
1543
1543
|
id: number;
|
|
@@ -1719,7 +1719,7 @@ declare function woocommerce(): kizlo0.Extension<"woocommerce", {
|
|
|
1719
1719
|
taxonomy: string;
|
|
1720
1720
|
description: string;
|
|
1721
1721
|
count: number;
|
|
1722
|
-
type: "
|
|
1722
|
+
type: "image" | "text" | "color";
|
|
1723
1723
|
swatch: string | null;
|
|
1724
1724
|
}[];
|
|
1725
1725
|
taxonomyTerms: {
|
|
@@ -2424,8 +2424,7 @@ declare function woocommerce(): kizlo0.Extension<"woocommerce", {
|
|
|
2424
2424
|
retry: kizlo0.Procedure<"api", {
|
|
2425
2425
|
body: {
|
|
2426
2426
|
key: string;
|
|
2427
|
-
|
|
2428
|
-
billingAddress?: {
|
|
2427
|
+
billingAddress: {
|
|
2429
2428
|
firstName: string;
|
|
2430
2429
|
lastName: string;
|
|
2431
2430
|
phone: string;
|
|
@@ -2437,7 +2436,8 @@ declare function woocommerce(): kizlo0.Extension<"woocommerce", {
|
|
|
2437
2436
|
email: string;
|
|
2438
2437
|
company?: string | undefined;
|
|
2439
2438
|
address2?: string | undefined;
|
|
2440
|
-
}
|
|
2439
|
+
};
|
|
2440
|
+
paymentMethod: string;
|
|
2441
2441
|
shippingAddress?: {
|
|
2442
2442
|
firstName: string;
|
|
2443
2443
|
lastName: string;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { CurrencyFormat, IdentifierInput, KizloError, ListMetadata, Seo,
|
|
1
|
+
import { CurrencyFormat, IdentifierInput, KizloError, ListMetadata, Seo, createExtension, createMiddleware, createProcedure, defineErrorMap, deserializeCurrencyFormat, deserializeListMetadata } from "kizlo";
|
|
2
2
|
import { BooleanLike, Media, Metadata, NumberLike, arrayable, normalizeArrayableValue, random, seconds, timestampSec, toPublicMetadata, tryCatch } from "@kizlo/shared";
|
|
3
3
|
import { SignJWT, jwtVerify } from "jose";
|
|
4
4
|
import z$1, { z } from "zod/v4";
|
|
5
5
|
import z$2 from "zod";
|
|
6
6
|
|
|
7
7
|
//#region src/session.ts
|
|
8
|
+
const GUEST_COOKIE_OPTIONS = {
|
|
9
|
+
httpOnly: true,
|
|
10
|
+
path: "/",
|
|
11
|
+
sameSite: "lax"
|
|
12
|
+
};
|
|
8
13
|
async function mintGuestToken(secret, ttlSeconds) {
|
|
9
14
|
const sub = random({
|
|
10
15
|
length: 32,
|
|
@@ -49,10 +54,7 @@ function sessionMiddleware(options) {
|
|
|
49
54
|
await context.cookies.set({
|
|
50
55
|
name: cookieName,
|
|
51
56
|
value: jwt,
|
|
52
|
-
options:
|
|
53
|
-
httpOnly: true,
|
|
54
|
-
sameSite: "lax"
|
|
55
|
-
}
|
|
57
|
+
options: GUEST_COOKIE_OPTIONS
|
|
56
58
|
});
|
|
57
59
|
return next({ context: { sessionHeaders: getCartHeaders({
|
|
58
60
|
token: sub,
|
|
@@ -65,10 +67,7 @@ function sessionMiddleware(options) {
|
|
|
65
67
|
await context.cookies.set({
|
|
66
68
|
name: cookieName,
|
|
67
69
|
value: jwt,
|
|
68
|
-
options:
|
|
69
|
-
httpOnly: true,
|
|
70
|
-
sameSite: "lax"
|
|
71
|
-
}
|
|
70
|
+
options: GUEST_COOKIE_OPTIONS
|
|
72
71
|
});
|
|
73
72
|
throw new KizloError("CART_SESSION_EXPIRED");
|
|
74
73
|
}
|
|
@@ -80,17 +79,14 @@ function sessionMiddleware(options) {
|
|
|
80
79
|
if (foundToken) {
|
|
81
80
|
const [err, data] = await tryCatch(verifyToken(foundToken, context.config.siteSecret));
|
|
82
81
|
if (!err) {
|
|
83
|
-
const response = await context.wordpress.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
connInfo
|
|
89
|
-
})
|
|
90
|
-
});
|
|
82
|
+
const response = await context.wordpress.woocommerce.kizlo.cart.merge({}, { headers: getCartHeaders({
|
|
83
|
+
userId: auth.id,
|
|
84
|
+
token: data.sub,
|
|
85
|
+
connInfo
|
|
86
|
+
}) });
|
|
91
87
|
if (response.error) context.logger.error("CART_MERGE_FAILED", response.error);
|
|
92
88
|
}
|
|
93
|
-
await context.cookies.delete(cookieName);
|
|
89
|
+
await context.cookies.delete(cookieName, GUEST_COOKIE_OPTIONS);
|
|
94
90
|
}
|
|
95
91
|
return next({ context: { sessionHeaders: getCartHeaders({
|
|
96
92
|
userId: auth.id,
|
|
@@ -228,7 +224,7 @@ const ProductAttributeTermRef = z.object({
|
|
|
228
224
|
const ProductAttributeRef = z.object({
|
|
229
225
|
id: z.number(),
|
|
230
226
|
name: z.string(),
|
|
231
|
-
taxonomy: z.string(),
|
|
227
|
+
taxonomy: z.string().nullable(),
|
|
232
228
|
hasVariations: z.boolean(),
|
|
233
229
|
terms: z.array(ProductAttributeTermRef)
|
|
234
230
|
});
|
|
@@ -753,10 +749,7 @@ const CART_ROUTER = {
|
|
|
753
749
|
errors: GET_CART_ERROR_MAP,
|
|
754
750
|
middlewares: [sessionMiddleware()]
|
|
755
751
|
}, async ({ context, errors }) => {
|
|
756
|
-
const response = await context.wordpress.get(
|
|
757
|
-
base: WC_STORE_BASE,
|
|
758
|
-
headers: context.sessionHeaders
|
|
759
|
-
});
|
|
752
|
+
const response = await context.wordpress.woocommerce.store.cart.get({}, { headers: context.sessionHeaders });
|
|
760
753
|
if (response.error) switch (response.error.code) {
|
|
761
754
|
default:
|
|
762
755
|
context.logger.error("Get cart unhandled error", response.error, { code: response.error.code });
|
|
@@ -774,45 +767,41 @@ const CART_ROUTER = {
|
|
|
774
767
|
middlewares: [sessionMiddleware()]
|
|
775
768
|
}, async ({ context, input: { body: input }, errors }) => {
|
|
776
769
|
const connInfo = await context.getConnInfo();
|
|
777
|
-
const
|
|
770
|
+
const billing = input.billing ?? {
|
|
778
771
|
...input.shipping,
|
|
779
772
|
email: void 0
|
|
780
773
|
};
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
country: defaultBilling?.country ?? connInfo?.country ?? void 0,
|
|
793
|
-
postcode: defaultBilling?.postcode ?? connInfo?.postcode ?? ""
|
|
794
|
-
} : {},
|
|
795
|
-
shipping_address: input.shipping !== void 0 ? {
|
|
796
|
-
first_name: input.shipping?.firstName ?? "",
|
|
797
|
-
last_name: input.shipping?.lastName ?? "",
|
|
798
|
-
address_1: input.shipping?.address1 ?? "",
|
|
799
|
-
address_2: input.shipping?.address2 ?? "",
|
|
800
|
-
company: input.shipping?.company ?? "",
|
|
801
|
-
phone: input.shipping?.phone ?? "",
|
|
802
|
-
city: input.shipping?.city ?? "",
|
|
803
|
-
state: input.shipping?.state ?? connInfo?.state ?? void 0,
|
|
804
|
-
country: input.shipping?.country ?? connInfo?.country ?? void 0,
|
|
805
|
-
postcode: input.shipping?.postcode ?? connInfo?.postcode ?? ""
|
|
806
|
-
} : {}
|
|
774
|
+
const address = {
|
|
775
|
+
first_name: billing.firstName ?? "",
|
|
776
|
+
last_name: billing.lastName ?? "",
|
|
777
|
+
address_1: billing.address1 ?? "",
|
|
778
|
+
address_2: billing.address2 ?? "",
|
|
779
|
+
company: billing.company ?? "",
|
|
780
|
+
phone: billing.phone ?? "",
|
|
781
|
+
city: billing.city ?? "",
|
|
782
|
+
state: billing.state ?? connInfo?.state ?? "",
|
|
783
|
+
country: billing.country ?? connInfo?.country ?? "",
|
|
784
|
+
postcode: billing.postcode ?? connInfo?.postcode ?? ""
|
|
807
785
|
};
|
|
808
|
-
const response = await context.wordpress.
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
shipping_address: updateData.shipping_address
|
|
786
|
+
const response = await context.wordpress.woocommerce.store.cart.updateCustomer({
|
|
787
|
+
billing_address: {
|
|
788
|
+
...address,
|
|
789
|
+
email: billing.email ?? ""
|
|
813
790
|
},
|
|
814
|
-
|
|
815
|
-
|
|
791
|
+
...input.shipping && { shipping_address: {
|
|
792
|
+
...address,
|
|
793
|
+
first_name: input.shipping.firstName ?? "",
|
|
794
|
+
last_name: input.shipping.lastName ?? "",
|
|
795
|
+
address_1: input.shipping.address1 ?? "",
|
|
796
|
+
address_2: input.shipping.address2 ?? "",
|
|
797
|
+
company: input.shipping.company ?? "",
|
|
798
|
+
phone: input.shipping.phone ?? "",
|
|
799
|
+
city: input.shipping.city ?? "",
|
|
800
|
+
state: input.shipping.state ?? connInfo?.state ?? "",
|
|
801
|
+
country: input.shipping.country ?? connInfo?.country ?? "",
|
|
802
|
+
postcode: input.shipping.postcode ?? connInfo?.postcode ?? ""
|
|
803
|
+
} }
|
|
804
|
+
}, { headers: context.sessionHeaders });
|
|
816
805
|
if (response.error) switch (response.error.code) {
|
|
817
806
|
default:
|
|
818
807
|
context.logger.error("Update cart customer unhandled error", response.error, { code: response.error.code });
|
|
@@ -829,14 +818,10 @@ const CART_ROUTER = {
|
|
|
829
818
|
errors: SELECT_SHIPPING_RATE_ERROR_MAP,
|
|
830
819
|
middlewares: [sessionMiddleware()]
|
|
831
820
|
}, async ({ context, input: { body }, errors }) => {
|
|
832
|
-
const response = await context.wordpress.
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
rate_id: body.rateId,
|
|
837
|
-
package_id: body.packageId
|
|
838
|
-
}
|
|
839
|
-
});
|
|
821
|
+
const response = await context.wordpress.woocommerce.store.cart.selectShippingRate({
|
|
822
|
+
rate_id: body.rateId,
|
|
823
|
+
package_id: body.packageId
|
|
824
|
+
}, { headers: context.sessionHeaders });
|
|
840
825
|
if (response.error) switch (response.error.code) {
|
|
841
826
|
case "woocommerce_rest_cart_shipping_rate_not_found": throw errors.CART_SHIPPING_RATE_NOT_FOUND({ message: response.error.message });
|
|
842
827
|
case "woocommerce_rest_shipping_disabled": throw errors.CART_SHIPPING_DISABLED({ message: response.error.message });
|
|
@@ -856,15 +841,11 @@ const CART_ROUTER = {
|
|
|
856
841
|
errors: ADD_CART_ITEM_ERROR_MAP,
|
|
857
842
|
middlewares: [sessionMiddleware()]
|
|
858
843
|
}, async ({ context, input: { body: input }, errors }) => {
|
|
859
|
-
const response = await context.wordpress.
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
},
|
|
865
|
-
base: WC_STORE_BASE,
|
|
866
|
-
headers: context.sessionHeaders
|
|
867
|
-
});
|
|
844
|
+
const response = await context.wordpress.woocommerce.store.cart.addItem({
|
|
845
|
+
id: input.productId,
|
|
846
|
+
quantity: input.quantity,
|
|
847
|
+
variation: input.variations ?? []
|
|
848
|
+
}, { headers: context.sessionHeaders });
|
|
868
849
|
if (response.error) switch (response.error.code) {
|
|
869
850
|
case "woocommerce_rest_product_out_of_stock": throw errors.CART_ITEM_OUT_OF_STOCK({ message: response.error.message });
|
|
870
851
|
case "woocommerce_rest_product_partially_out_of_stock": throw errors.CART_ITEM_INSUFFICIENT_STOCK({ message: response.error.message });
|
|
@@ -893,14 +874,10 @@ const CART_ROUTER = {
|
|
|
893
874
|
errors: UPDATE_CART_ITEM_ERROR_MAP,
|
|
894
875
|
middlewares: [sessionMiddleware()]
|
|
895
876
|
}, async ({ context, input: { params, body }, errors }) => {
|
|
896
|
-
const response = await context.wordpress.
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
},
|
|
901
|
-
base: WC_STORE_BASE,
|
|
902
|
-
headers: context.sessionHeaders
|
|
903
|
-
});
|
|
877
|
+
const response = await context.wordpress.woocommerce.store.cart.updateItem({
|
|
878
|
+
key: params.key,
|
|
879
|
+
quantity: body.quantity
|
|
880
|
+
}, { headers: context.sessionHeaders });
|
|
904
881
|
if (response.error) switch (response.error.code) {
|
|
905
882
|
case "woocommerce_rest_cart_invalid_key": throw errors.CART_ITEM_NOT_FOUND({ message: response.error.message });
|
|
906
883
|
case "woocommerce_rest_cart_invalid_product": throw errors.CART_PRODUCT_INVALID({ message: response.error.message });
|
|
@@ -922,11 +899,7 @@ const CART_ROUTER = {
|
|
|
922
899
|
errors: REMOVE_CART_ITEM_ERROR_MAP,
|
|
923
900
|
middlewares: [sessionMiddleware()]
|
|
924
901
|
}, async ({ context, input: { params }, errors }) => {
|
|
925
|
-
const response = await context.wordpress.
|
|
926
|
-
body: { key: params.key },
|
|
927
|
-
base: WC_STORE_BASE,
|
|
928
|
-
headers: context.sessionHeaders
|
|
929
|
-
});
|
|
902
|
+
const response = await context.wordpress.woocommerce.store.cart.removeItem({ key: params.key }, { headers: context.sessionHeaders });
|
|
930
903
|
if (response.error) switch (response.error.code) {
|
|
931
904
|
case "woocommerce_rest_cart_invalid_key": throw errors.CART_ITEM_NOT_FOUND({ message: response.error.message });
|
|
932
905
|
default:
|
|
@@ -946,11 +919,7 @@ const CART_ROUTER = {
|
|
|
946
919
|
errors: APPLY_COUPON_ERROR_MAP,
|
|
947
920
|
middlewares: [sessionMiddleware()]
|
|
948
921
|
}, async ({ context, input: { body }, errors }) => {
|
|
949
|
-
const response = await context.wordpress.
|
|
950
|
-
body: { code: body.code },
|
|
951
|
-
base: WC_STORE_BASE,
|
|
952
|
-
headers: context.sessionHeaders
|
|
953
|
-
});
|
|
922
|
+
const response = await context.wordpress.woocommerce.store.cart.applyCoupon({ code: body.code }, { headers: context.sessionHeaders });
|
|
954
923
|
if (response.error) switch (response.error.code) {
|
|
955
924
|
case "woocommerce_rest_cart_coupon_error": throw errors.CART_COUPON_INVALID({ message: response.error.message });
|
|
956
925
|
case "woocommerce_rest_cart_coupon_disabled": throw errors.CART_COUPON_DISABLED({ message: response.error.message });
|
|
@@ -969,11 +938,7 @@ const CART_ROUTER = {
|
|
|
969
938
|
errors: REMOVE_COUPON_ERROR_MAP,
|
|
970
939
|
middlewares: [sessionMiddleware()]
|
|
971
940
|
}, async ({ context, input, errors }) => {
|
|
972
|
-
const response = await context.wordpress.
|
|
973
|
-
body: { code: input.params.code },
|
|
974
|
-
base: WC_STORE_BASE,
|
|
975
|
-
headers: context.sessionHeaders
|
|
976
|
-
});
|
|
941
|
+
const response = await context.wordpress.woocommerce.store.cart.removeCoupon({ code: input.params.code }, { headers: context.sessionHeaders });
|
|
977
942
|
if (response.error) switch (response.error.code) {
|
|
978
943
|
case "woocommerce_rest_cart_coupon_error": throw errors.CART_COUPON_INVALID({ message: response.error.message });
|
|
979
944
|
case "woocommerce_rest_cart_coupon_disabled": throw errors.CART_COUPON_DISABLED({ message: response.error.message });
|
|
@@ -1175,13 +1140,61 @@ const RetryCheckoutInput = z$2.object({
|
|
|
1175
1140
|
orderId: NumberLike,
|
|
1176
1141
|
paymentMethod: z$2.string(),
|
|
1177
1142
|
billingEmail: z$2.email().optional(),
|
|
1178
|
-
billingAddress: BillingAddress
|
|
1143
|
+
billingAddress: BillingAddress,
|
|
1179
1144
|
paymentData: CheckoutPaymentData.optional(),
|
|
1180
1145
|
shippingAddress: ShippingAddress.optional()
|
|
1181
1146
|
});
|
|
1182
1147
|
|
|
1183
1148
|
//#endregion
|
|
1184
1149
|
//#region src/checkout/utils.ts
|
|
1150
|
+
/**
|
|
1151
|
+
* A payment method the caller named, passed to WooCommerce as one.
|
|
1152
|
+
*
|
|
1153
|
+
* WooCommerce builds this argument's enum from `get_payment_gateway_ids()`, so the contract
|
|
1154
|
+
* enumerates the gateways enabled on the WordPress the client was generated against. That is true of
|
|
1155
|
+
* that install and says nothing about the one a build actually talks to, and WooCommerce agrees: its
|
|
1156
|
+
* own comment on the enum is that further validation happens during the request.
|
|
1157
|
+
*
|
|
1158
|
+
* So the enum is documentation here rather than a constraint, and the gateway a shopper chose is
|
|
1159
|
+
* sent whatever it is. WooCommerce rejects an unknown one with
|
|
1160
|
+
* `woocommerce_rest_checkout_payment_method_disabled`, which both callers already map.
|
|
1161
|
+
*/
|
|
1162
|
+
function gateway(method) {
|
|
1163
|
+
return method;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* A Kizlo address in the shape WooCommerce registered its argument in.
|
|
1167
|
+
*
|
|
1168
|
+
* Kizlo's addresses are camelCase and WooCommerce's are snake_case, and until the contract described
|
|
1169
|
+
* the route nothing said so: the retry call passed a Kizlo address straight through as
|
|
1170
|
+
* `billing_address`, where every key missed and WooCommerce kept the address already on the order.
|
|
1171
|
+
*
|
|
1172
|
+
* Every field is required there, so an address given in part is sent filled out. An address that was
|
|
1173
|
+
* not given at all is a different thing and never reaches here: WooCommerce reads an absent
|
|
1174
|
+
* `shipping_address` as "use the billing address", and a blank one as an address, so a caller who
|
|
1175
|
+
* omitted it must leave the argument off the call rather than send this filled with empty strings.
|
|
1176
|
+
*/
|
|
1177
|
+
function serializeAddress(address) {
|
|
1178
|
+
return {
|
|
1179
|
+
first_name: address.firstName,
|
|
1180
|
+
last_name: address.lastName,
|
|
1181
|
+
address_1: address.address1,
|
|
1182
|
+
address_2: address.address2 ?? "",
|
|
1183
|
+
company: address.company ?? "",
|
|
1184
|
+
city: address.city,
|
|
1185
|
+
state: address.state,
|
|
1186
|
+
country: address.country,
|
|
1187
|
+
postcode: address.postcode,
|
|
1188
|
+
phone: address.phone
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
/** The same, plus the email WooCommerce carries on the billing address alone. */
|
|
1192
|
+
function serializeBillingAddress(address) {
|
|
1193
|
+
return {
|
|
1194
|
+
...serializeAddress(address),
|
|
1195
|
+
email: address.email
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1185
1198
|
function deserializeCheckout(data) {
|
|
1186
1199
|
return {
|
|
1187
1200
|
cart: data.__experimentalCart ? deserializeCart(data.__experimentalCart) : null,
|
|
@@ -1210,16 +1223,40 @@ function deserializeCheckout(data) {
|
|
|
1210
1223
|
postcode: data.billing_address.postcode,
|
|
1211
1224
|
state: data.billing_address.state
|
|
1212
1225
|
},
|
|
1213
|
-
additionalFields: data.additional_fields,
|
|
1226
|
+
additionalFields: additionalFields(data.additional_fields),
|
|
1214
1227
|
customerNote: data.customer_note,
|
|
1215
1228
|
paymentMethod: data.payment_method,
|
|
1216
1229
|
paymentResult: data.payment_result?.payment_status ? {
|
|
1217
|
-
status: data.payment_result.payment_status,
|
|
1230
|
+
status: paymentStatus(data.payment_result.payment_status),
|
|
1218
1231
|
redirectUrl: data.payment_result.redirect_url,
|
|
1219
1232
|
data: data.payment_result.payment_details
|
|
1220
1233
|
} : null
|
|
1221
1234
|
};
|
|
1222
1235
|
}
|
|
1236
|
+
/**
|
|
1237
|
+
* WooCommerce registers `additional_fields` as a bare object, so the contract describes it as one
|
|
1238
|
+
* with undescribed contents: what a site's checkout fields are is a per-site question that no schema
|
|
1239
|
+
* can answer ahead of time. The values are scalars in practice, and anything else is dropped rather
|
|
1240
|
+
* than passed on to fail the procedure's own output validation with a less useful message.
|
|
1241
|
+
*/
|
|
1242
|
+
function additionalFields(fields) {
|
|
1243
|
+
const kept = {};
|
|
1244
|
+
for (const [key, value] of Object.entries(fields ?? {})) if (typeof value === "string" || typeof value === "boolean") kept[key] = value;
|
|
1245
|
+
return kept;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* WooCommerce names the four statuses in the field's description and declares the field a plain
|
|
1249
|
+
* string, so the contract cannot narrow it. `error` is the safe reading of anything unrecognized: a
|
|
1250
|
+
* gateway that answered with something new has not taken payment as far as this checkout knows.
|
|
1251
|
+
*/
|
|
1252
|
+
function paymentStatus(status) {
|
|
1253
|
+
switch (status) {
|
|
1254
|
+
case "success":
|
|
1255
|
+
case "pending":
|
|
1256
|
+
case "failure": return status;
|
|
1257
|
+
default: return "error";
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1223
1260
|
|
|
1224
1261
|
//#endregion
|
|
1225
1262
|
//#region src/checkout/index.ts
|
|
@@ -1232,10 +1269,7 @@ const CHECKOUT_ROUTER = {
|
|
|
1232
1269
|
errors: GET_CHECKOUT_ERROR_MAP,
|
|
1233
1270
|
middlewares: [sessionMiddleware()]
|
|
1234
1271
|
}, async ({ context, errors }) => {
|
|
1235
|
-
const response = await context.wordpress.get(
|
|
1236
|
-
base: WC_STORE_BASE,
|
|
1237
|
-
headers: context.sessionHeaders
|
|
1238
|
-
});
|
|
1272
|
+
const response = await context.wordpress.woocommerce.store.checkout.get({}, { headers: context.sessionHeaders });
|
|
1239
1273
|
if (response.error) switch (response.error.code) {
|
|
1240
1274
|
case "woocommerce_rest_checkout_missing_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: response.error.message });
|
|
1241
1275
|
default:
|
|
@@ -1253,16 +1287,12 @@ const CHECKOUT_ROUTER = {
|
|
|
1253
1287
|
errors: UPDATE_CHECKOUT_ERROR_MAP,
|
|
1254
1288
|
middlewares: [sessionMiddleware()]
|
|
1255
1289
|
}, async ({ context, input, errors }) => {
|
|
1256
|
-
const response = await context.wordpress.
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
__experimental_calc_totals: input.body.recalculateTotals
|
|
1263
|
-
},
|
|
1264
|
-
headers: context.sessionHeaders
|
|
1265
|
-
});
|
|
1290
|
+
const response = await context.wordpress.woocommerce.store.checkout.update({
|
|
1291
|
+
order_notes: input.body.customerNote,
|
|
1292
|
+
payment_method: gateway(input.body.paymentMethod),
|
|
1293
|
+
additional_fields: input.body.additionalFields,
|
|
1294
|
+
__experimental_calc_totals: input.body.recalculateTotals
|
|
1295
|
+
}, { headers: context.sessionHeaders });
|
|
1266
1296
|
if (response.error) switch (response.error.code) {
|
|
1267
1297
|
case "woocommerce_rest_cart_coupon_error": throw errors.CHECKOUT_COUPON_INVALID({ message: response.error.message });
|
|
1268
1298
|
case "woocommerce_rest_checkout_payment_method_disabled": throw errors.CHECKOUT_PAYMENT_METHOD_DISABLED({ message: response.error.message });
|
|
@@ -1287,30 +1317,23 @@ const CHECKOUT_ROUTER = {
|
|
|
1287
1317
|
errors: CONFIRM_CHECKOUT_ERROR_MAP,
|
|
1288
1318
|
middlewares: [sessionMiddleware()]
|
|
1289
1319
|
}, async ({ context, input, errors }) => {
|
|
1290
|
-
const checkoutResponse = await context.wordpress.get(
|
|
1291
|
-
base: WC_STORE_BASE,
|
|
1292
|
-
headers: context.sessionHeaders
|
|
1293
|
-
});
|
|
1320
|
+
const checkoutResponse = await context.wordpress.woocommerce.store.checkout.get({}, { headers: context.sessionHeaders });
|
|
1294
1321
|
if (checkoutResponse.error) switch (checkoutResponse.error.code) {
|
|
1295
1322
|
case "woocommerce_rest_checkout_missing_order": throw errors.CHECKOUT_ORDER_NOT_FOUND({ message: checkoutResponse.error.message });
|
|
1296
1323
|
default:
|
|
1297
1324
|
context.logger.error("Get checkout for confirm unhandled error", checkoutResponse.error, { code: checkoutResponse.error.code });
|
|
1298
1325
|
throw errors.INTERNAL_SERVER_ERROR();
|
|
1299
1326
|
}
|
|
1300
|
-
const confirmResponse = await context.wordpress.
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
additional_fields: checkoutResponse.data.additional_fields
|
|
1311
|
-
},
|
|
1312
|
-
headers: context.sessionHeaders
|
|
1313
|
-
});
|
|
1327
|
+
const confirmResponse = await context.wordpress.woocommerce.store.checkout.process({
|
|
1328
|
+
payment_data: input.body.paymentData,
|
|
1329
|
+
customer_password: input.body.customerPassword,
|
|
1330
|
+
customer_note: checkoutResponse.data.customer_note,
|
|
1331
|
+
payment_method: checkoutResponse.data.payment_method,
|
|
1332
|
+
create_account: !!input.body.customerPassword?.length,
|
|
1333
|
+
billing_address: checkoutResponse.data.billing_address,
|
|
1334
|
+
shipping_address: checkoutResponse.data.shipping_address,
|
|
1335
|
+
additional_fields: checkoutResponse.data.additional_fields
|
|
1336
|
+
}, { headers: context.sessionHeaders });
|
|
1314
1337
|
if (confirmResponse.error) switch (confirmResponse.error.code) {
|
|
1315
1338
|
case "woocommerce_rest_invalid_address": throw errors.CHECKOUT_ADDRESS_INVALID({ message: confirmResponse.error.message });
|
|
1316
1339
|
case "woocommerce_rest_invalid_address_country": throw errors.CHECKOUT_ADDRESS_COUNTRY_INVALID({ message: confirmResponse.error.message });
|
|
@@ -1346,19 +1369,15 @@ const CHECKOUT_ROUTER = {
|
|
|
1346
1369
|
errors: RETRY_CHECKOUT_ERROR_MAP,
|
|
1347
1370
|
middlewares: [sessionMiddleware()]
|
|
1348
1371
|
}, async ({ context, input, errors }) => {
|
|
1349
|
-
const response = await context.wordpress.
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
shipping_address: input.body.shippingAddress ?? {}
|
|
1359
|
-
},
|
|
1360
|
-
headers: context.sessionHeaders
|
|
1361
|
-
});
|
|
1372
|
+
const response = await context.wordpress.woocommerce.store.checkout.processOrder({
|
|
1373
|
+
key: input.body.key,
|
|
1374
|
+
id: input.params.orderId,
|
|
1375
|
+
payment_data: input.body.paymentData,
|
|
1376
|
+
billing_email: input.body.billingEmail,
|
|
1377
|
+
payment_method: gateway(input.body.paymentMethod),
|
|
1378
|
+
billing_address: serializeBillingAddress(input.body.billingAddress),
|
|
1379
|
+
shipping_address: input.body.shippingAddress ? serializeAddress(input.body.shippingAddress) : void 0
|
|
1380
|
+
}, { headers: context.sessionHeaders });
|
|
1362
1381
|
if (response.error) switch (response.error.code) {
|
|
1363
1382
|
case "woocommerce_rest_invalid_billing_email": throw errors.CHECKOUT_EMAIL_INVALID({ message: response.error.message });
|
|
1364
1383
|
case "woocommerce_rest_checkout_process_payment_error": throw errors.CHECKOUT_PAYMENT_FAILED({ message: response.error.message });
|
|
@@ -1447,8 +1466,17 @@ const CUSTOMER_ROUTER = { get: createProcedure({
|
|
|
1447
1466
|
}, async ({ context, errors }) => {
|
|
1448
1467
|
const auth = await context.getAuthUser();
|
|
1449
1468
|
if (!auth) throw errors.FORBIDDEN();
|
|
1450
|
-
const response = await context.wordpress.
|
|
1451
|
-
if (response.error)
|
|
1469
|
+
const response = await context.wordpress.woocommerce.customers.retrieve({ id: auth.id });
|
|
1470
|
+
if (response.error) switch (response.error.code) {
|
|
1471
|
+
case "wc_user_invalid_id": throw errors.NOT_FOUND();
|
|
1472
|
+
case "woocommerce_rest_cannot_view": throw errors.FORBIDDEN();
|
|
1473
|
+
default:
|
|
1474
|
+
context.logger.error("Get customer unhandled error", response.error, {
|
|
1475
|
+
userId: auth.id,
|
|
1476
|
+
code: response.error.code
|
|
1477
|
+
});
|
|
1478
|
+
throw errors.INTERNAL_SERVER_ERROR();
|
|
1479
|
+
}
|
|
1452
1480
|
return deserializeCustomer(response.data);
|
|
1453
1481
|
}) };
|
|
1454
1482
|
|
|
@@ -1472,13 +1500,13 @@ function deserializeProduct(data) {
|
|
|
1472
1500
|
description: data.description,
|
|
1473
1501
|
shortDescription: data.short_description,
|
|
1474
1502
|
prices: {
|
|
1475
|
-
price:
|
|
1476
|
-
salePrice:
|
|
1477
|
-
regularPrice:
|
|
1503
|
+
price: data.kizlo.prices.price,
|
|
1504
|
+
salePrice: data.kizlo.prices.sale_price,
|
|
1505
|
+
regularPrice: data.kizlo.prices.regular_price
|
|
1478
1506
|
},
|
|
1479
1507
|
isSoldIndividually: data.sold_individually,
|
|
1480
1508
|
onSaleFrom: data.date_on_sale_from ? toTimestamp(data.date_on_sale_from) : null,
|
|
1481
|
-
lowStockRemaining:
|
|
1509
|
+
lowStockRemaining: data.low_stock_amount,
|
|
1482
1510
|
onSaleTo: data.date_on_sale_to ? toTimestamp(data.date_on_sale_to) : null,
|
|
1483
1511
|
isInStock: data.stock_status === "instock",
|
|
1484
1512
|
stock: data.stock_quantity,
|
|
@@ -1508,9 +1536,15 @@ function deserializeProduct(data) {
|
|
|
1508
1536
|
};
|
|
1509
1537
|
}
|
|
1510
1538
|
function deserializeStoreProduct(data) {
|
|
1539
|
+
const kizlo = data.extensions.kizlo ?? {
|
|
1540
|
+
stock: null,
|
|
1541
|
+
on_sale_from: null,
|
|
1542
|
+
on_sale_to: null,
|
|
1543
|
+
hs_code: null
|
|
1544
|
+
};
|
|
1511
1545
|
return {
|
|
1512
1546
|
id: data.id,
|
|
1513
|
-
type: data.type,
|
|
1547
|
+
type: productType(data.type),
|
|
1514
1548
|
name: data.name,
|
|
1515
1549
|
slug: data.slug,
|
|
1516
1550
|
sku: data.sku,
|
|
@@ -1545,9 +1579,9 @@ function deserializeStoreProduct(data) {
|
|
|
1545
1579
|
isOnSale: data.on_sale,
|
|
1546
1580
|
parentId: data.parent,
|
|
1547
1581
|
variations: data.variations,
|
|
1548
|
-
stock:
|
|
1549
|
-
onSaleFrom:
|
|
1550
|
-
onSaleTo:
|
|
1582
|
+
stock: kizlo.stock,
|
|
1583
|
+
onSaleFrom: kizlo.on_sale_from ? toTimestamp(kizlo.on_sale_from) : null,
|
|
1584
|
+
onSaleTo: kizlo.on_sale_to ? toTimestamp(kizlo.on_sale_to) : null,
|
|
1551
1585
|
seo: null,
|
|
1552
1586
|
meta: {}
|
|
1553
1587
|
};
|
|
@@ -1557,7 +1591,13 @@ function deserializeProductFilters(data) {
|
|
|
1557
1591
|
const maxPrice = +data.price_range.max_price;
|
|
1558
1592
|
const minPrice = +data.price_range.min_price;
|
|
1559
1593
|
return {
|
|
1560
|
-
stockStatuses: data.stock_status_counts ?? []
|
|
1594
|
+
stockStatuses: (data.stock_status_counts ?? []).flatMap((entry) => {
|
|
1595
|
+
const status = stockStatus(entry.status);
|
|
1596
|
+
return status ? [{
|
|
1597
|
+
count: entry.count,
|
|
1598
|
+
status
|
|
1599
|
+
}] : [];
|
|
1600
|
+
}),
|
|
1561
1601
|
taxonomyTerms: data.kizlo.taxonomy_counts.map((item) => ({
|
|
1562
1602
|
id: item.id,
|
|
1563
1603
|
name: item.name,
|
|
@@ -1608,7 +1648,7 @@ function serializeProductListInput(data) {
|
|
|
1608
1648
|
orderby: data?.orderby,
|
|
1609
1649
|
parent: normalizeArrayableValue(data?.parent),
|
|
1610
1650
|
parent_exclude: normalizeArrayableValue(data?.parentExclude),
|
|
1611
|
-
rating: normalizeArrayableValue(data?.rating)?.map(Number),
|
|
1651
|
+
rating: normalizeArrayableValue(data?.rating)?.map((value) => Number(value)),
|
|
1612
1652
|
sku: data?.sku,
|
|
1613
1653
|
slug: data?.slug,
|
|
1614
1654
|
stock_status: normalizeArrayableValue(data?.stockStatus),
|
|
@@ -1631,6 +1671,20 @@ function serializeProductListInput(data) {
|
|
|
1631
1671
|
search: data?.search
|
|
1632
1672
|
};
|
|
1633
1673
|
}
|
|
1674
|
+
/**
|
|
1675
|
+
* WooCommerce declares both of these fields as plain strings, so the contract cannot narrow them and
|
|
1676
|
+
* neither can this without saying what it does with a value it does not recognize.
|
|
1677
|
+
*
|
|
1678
|
+
* A product type Kizlo has no name for reads as `simple`, which is what every gateway to a product
|
|
1679
|
+
* page needs it to behave like. An unrecognized stock status is dropped from the filter list
|
|
1680
|
+
* instead: a count nobody can label is not a filter anyone can offer.
|
|
1681
|
+
*/
|
|
1682
|
+
function productType(type) {
|
|
1683
|
+
return PRODUCT_TYPES.includes(type) ? type : "simple";
|
|
1684
|
+
}
|
|
1685
|
+
function stockStatus(status) {
|
|
1686
|
+
return PRODUCT_STOCK_STATUSES.includes(status) ? status : null;
|
|
1687
|
+
}
|
|
1634
1688
|
function deserializeImages(images) {
|
|
1635
1689
|
return images.map((item) => ({
|
|
1636
1690
|
id: item.id,
|
|
@@ -1665,7 +1719,7 @@ const PRODUCT_ROUTER = {
|
|
|
1665
1719
|
if (input.query?.previewToken) {
|
|
1666
1720
|
const result = await context.verifyPreviewToken(input.query.previewToken);
|
|
1667
1721
|
if (!result) throw errors.PRODUCT_NOT_FOUND();
|
|
1668
|
-
const response$1 = await context.wordpress.
|
|
1722
|
+
const response$1 = await context.wordpress.woocommerce.products.retrieve({ id: Number(result.id) });
|
|
1669
1723
|
if (response$1.error) switch (response$1.error.code) {
|
|
1670
1724
|
case "woocommerce_rest_product_invalid_id": throw errors.PRODUCT_NOT_FOUND({ message: response$1.error.message });
|
|
1671
1725
|
default:
|
|
@@ -1677,10 +1731,7 @@ const PRODUCT_ROUTER = {
|
|
|
1677
1731
|
}
|
|
1678
1732
|
return deserializeProduct(response$1.data);
|
|
1679
1733
|
}
|
|
1680
|
-
const response = await context.wordpress.
|
|
1681
|
-
searchParams: { slug: input.params.identifier },
|
|
1682
|
-
base: WC_CORE_BASE
|
|
1683
|
-
});
|
|
1734
|
+
const response = await context.wordpress.woocommerce.products.list({ slug: String(input.params.identifier) });
|
|
1684
1735
|
if (response.error) switch (response.error.code) {
|
|
1685
1736
|
default:
|
|
1686
1737
|
context.logger.error("Get product unhandled error", response.error, {
|
|
@@ -1702,10 +1753,7 @@ const PRODUCT_ROUTER = {
|
|
|
1702
1753
|
errors: LIST_PRODUCT_ERROR_MAP
|
|
1703
1754
|
}, async ({ context, input, errors }) => {
|
|
1704
1755
|
const searchParams = serializeProductListInput(input.query);
|
|
1705
|
-
const response = await context.wordpress.
|
|
1706
|
-
base: WC_STORE_BASE,
|
|
1707
|
-
searchParams: { ...searchParams }
|
|
1708
|
-
});
|
|
1756
|
+
const response = await context.wordpress.woocommerce.store.products.list(searchParams);
|
|
1709
1757
|
if (response.error) switch (response.error.code) {
|
|
1710
1758
|
default:
|
|
1711
1759
|
context.logger.error("List products unhandled error", response.error, { code: response.error.code });
|
|
@@ -1729,19 +1777,16 @@ const PRODUCT_ROUTER = {
|
|
|
1729
1777
|
output: ProductFilters.nullable()
|
|
1730
1778
|
}, async ({ context, errors, input }) => {
|
|
1731
1779
|
const searchParams = serializeProductListInput(input.query);
|
|
1732
|
-
const response = await context.wordpress.
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
query_type: item.queryType
|
|
1743
|
-
}))
|
|
1744
|
-
}
|
|
1780
|
+
const response = await context.wordpress.woocommerce.store.products.collectionData({
|
|
1781
|
+
...searchParams,
|
|
1782
|
+
calculate_price_range: true,
|
|
1783
|
+
calculate_rating_counts: input.query?.ratingFilters,
|
|
1784
|
+
calculate_taxonomy_counts: input.query?.taxonomyFilters,
|
|
1785
|
+
calculate_stock_status_counts: input.query?.stockStatusFilters,
|
|
1786
|
+
calculate_attribute_counts: input.query?.attributeFilters?.map((item) => ({
|
|
1787
|
+
taxonomy: item.taxonomy,
|
|
1788
|
+
query_type: item.queryType
|
|
1789
|
+
}))
|
|
1745
1790
|
});
|
|
1746
1791
|
if (response.error) switch (response.error.code) {
|
|
1747
1792
|
default:
|
|
@@ -1757,6 +1802,21 @@ const PRODUCT_ROUTER = {
|
|
|
1757
1802
|
function woocommerce() {
|
|
1758
1803
|
return createExtension({
|
|
1759
1804
|
id: "woocommerce",
|
|
1805
|
+
requires: {
|
|
1806
|
+
plugin: {
|
|
1807
|
+
slug: "kizlo-woocommerce",
|
|
1808
|
+
name: "Kizlo WooCommerce",
|
|
1809
|
+
version: "0.2.0"
|
|
1810
|
+
},
|
|
1811
|
+
endpoints: [
|
|
1812
|
+
"woocommerce.customers",
|
|
1813
|
+
"woocommerce.products",
|
|
1814
|
+
"woocommerce.kizlo.cart",
|
|
1815
|
+
"woocommerce.store.cart",
|
|
1816
|
+
"woocommerce.store.checkout",
|
|
1817
|
+
"woocommerce.store.products"
|
|
1818
|
+
]
|
|
1819
|
+
},
|
|
1760
1820
|
init: () => {
|
|
1761
1821
|
return { router: {
|
|
1762
1822
|
cart: CART_ROUTER,
|
package/dist/test.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import { WC_CORE_BASE, WC_STORE_BASE } from "kizlo";
|
|
2
1
|
import { defineFixture, kizloRelease } from "kizlo/test";
|
|
3
2
|
|
|
3
|
+
//#region src/constants.ts
|
|
4
|
+
/**
|
|
5
|
+
* Base paths for the two WooCommerce APIs, used only where this package seeds or inspects a store
|
|
6
|
+
* directly. Everything a router or service reaches goes through a generated endpoint, which derives
|
|
7
|
+
* its own prefix from the namespace the plugin declares.
|
|
8
|
+
*/
|
|
9
|
+
const WC_CORE_BASE = "/wp-json/wc/v3";
|
|
10
|
+
const WC_STORE_BASE = "/wp-json/wc/store/v1";
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
4
13
|
//#region src/test/index.ts
|
|
5
14
|
const PRODUCTS = [
|
|
6
15
|
{
|
|
@@ -51,6 +60,30 @@ async function upsertCoupon(service, coupon) {
|
|
|
51
60
|
if (created.error) throw created.error;
|
|
52
61
|
}
|
|
53
62
|
/**
|
|
63
|
+
* WooCommerce ships every gateway disabled, and paying an order needs an available one, so the
|
|
64
|
+
* checkout tests have nothing to reach without this. Bank transfer is the gateway with no shipping
|
|
65
|
+
* method or country conditions attached to it, so enabling it says the least about the rest.
|
|
66
|
+
*/
|
|
67
|
+
async function enableBankTransfer(service) {
|
|
68
|
+
const updated = await service.put(`${WC_CORE_BASE}/payment_gateways/bacs`, { body: { enabled: true } });
|
|
69
|
+
if (updated.error) throw updated.error;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* WooCommerce bundles Action Scheduler, which keeps its actions in the posts table until it
|
|
73
|
+
* migrates to its own tables, and registers two global post statuses (`in-progress`, `failed`)
|
|
74
|
+
* for as long as that legacy store is live. The migration is scheduled a minute after activation
|
|
75
|
+
* and left to cron, so a WordPress reports those two statuses for roughly its first minute and
|
|
76
|
+
* never again. Every post type's status enum is built from the global list, so a client generated
|
|
77
|
+
* inside that window carries two statuses that one generated outside it does not.
|
|
78
|
+
*
|
|
79
|
+
* Firing Action Scheduler's own migration callback settles it: the runner finds nothing to move
|
|
80
|
+
* on a fresh install and marks the migration complete itself, so this is its cron path run now
|
|
81
|
+
* rather than its bookkeeping written by hand.
|
|
82
|
+
*/
|
|
83
|
+
async function settleActionScheduler(wpEval) {
|
|
84
|
+
await wpEval("if (class_exists(\"ActionScheduler_DataController\") && !ActionScheduler_DataController::is_migration_complete()) { do_action(\"action_scheduler/migration_hook\"); }");
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
54
87
|
* WooCommerce test fixture: installs WooCommerce + the kizlo-woocommerce plugin, seeds
|
|
55
88
|
* products/coupons. Pass `plugins` to override the defaults — e.g. bind-mount your local
|
|
56
89
|
* source with `{ path: "plugins/kizlo-woocommerce" }` to develop/test against live files.
|
|
@@ -62,6 +95,9 @@ function woocommerce(opts = {}) {
|
|
|
62
95
|
name: "kizlo-woocommerce",
|
|
63
96
|
source: kizloRelease("kizlo-woocommerce")
|
|
64
97
|
}],
|
|
98
|
+
async settle({ wpEval }) {
|
|
99
|
+
await settleActionScheduler(wpEval);
|
|
100
|
+
},
|
|
65
101
|
async seed({ service }) {
|
|
66
102
|
let productId = 0;
|
|
67
103
|
for (const product of PRODUCTS) {
|
|
@@ -69,6 +105,7 @@ function woocommerce(opts = {}) {
|
|
|
69
105
|
if (!productId) productId = id;
|
|
70
106
|
}
|
|
71
107
|
for (const coupon of COUPONS) await upsertCoupon(service, coupon);
|
|
108
|
+
await enableBankTransfer(service);
|
|
72
109
|
return { productId };
|
|
73
110
|
},
|
|
74
111
|
async cleanup({ service, userId }) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kizlo/woocommerce",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "WooCommerce extension for Kizlo.",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"access": "public"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@kizlo/shared": "0.
|
|
52
|
+
"@kizlo/shared": "0.7.0",
|
|
53
53
|
"jose": "6.1.0",
|
|
54
54
|
"zod": "^4.3.6"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"kizlo": ">=0.
|
|
57
|
+
"kizlo": ">=0.15.0"
|
|
58
58
|
}
|
|
59
59
|
}
|