@juo/blocks 2.0.0-alpha.5 → 2.0.0-alpha.7
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/{ExtensionRoot-DRpD5EcC.js → ExtensionRoot-CG9dH98z.js} +1 -1
- package/dist/core.js +473 -13
- package/dist/{css-runtime-B7tZrBIp.js → css-runtime-CjZl0K48.js} +23 -17
- package/dist/editor/handler.d.ts.map +1 -1
- package/dist/editor.js +4 -1
- package/dist/{gridstack-adapter-BGKGC-eO.js → gridstack-adapter-C1Q8gbsH.js} +2 -2
- package/dist/languages.d.ts +51 -0
- package/dist/languages.d.ts.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/{project-gridstack-PxN_DIfP.js → project-gridstack-CRZ_7HoT.js} +1 -1
- package/dist/services/customer/adapter.d.ts +12 -0
- package/dist/services/customer/adapter.d.ts.map +1 -1
- package/dist/services/customer/adapter.test.d.ts +2 -0
- package/dist/services/customer/adapter.test.d.ts.map +1 -0
- package/dist/services/customer/customerService.d.ts.map +1 -1
- package/dist/services/customer/index.d.ts +1 -1
- package/dist/services/customer/index.d.ts.map +1 -1
- package/dist/services/customer/types.d.ts +13 -0
- package/dist/services/customer/types.d.ts.map +1 -1
- package/dist/services/login/adapter.d.ts.map +1 -1
- package/dist/services/login/loginService.d.ts +1 -0
- package/dist/services/login/loginService.d.ts.map +1 -1
- package/dist/services/login/loginService.test.d.ts +2 -0
- package/dist/services/login/loginService.test.d.ts.map +1 -0
- package/dist/services/order/adapter.d.ts +11 -1
- package/dist/services/order/adapter.d.ts.map +1 -1
- package/dist/services/order/adapter.test.d.ts +2 -0
- package/dist/services/order/adapter.test.d.ts.map +1 -0
- package/dist/services/order/index.d.ts +2 -2
- package/dist/services/order/index.d.ts.map +1 -1
- package/dist/services/order/types.d.ts +56 -6
- package/dist/services/order/types.d.ts.map +1 -1
- package/dist/services/subscription/adapter.d.ts +10 -1
- package/dist/services/subscription/adapter.d.ts.map +1 -1
- package/dist/services/subscription/index.d.ts +2 -0
- package/dist/services/subscription/index.d.ts.map +1 -1
- package/dist/services/subscription/instantOrderErrors.d.ts +66 -0
- package/dist/services/subscription/instantOrderErrors.d.ts.map +1 -0
- package/dist/services/subscription/lineRemoval.d.ts +56 -0
- package/dist/services/subscription/lineRemoval.d.ts.map +1 -0
- package/dist/services/subscription/lineRemoval.test.d.ts +2 -0
- package/dist/services/subscription/lineRemoval.test.d.ts.map +1 -0
- package/dist/services/subscription/paymentInstrument.d.ts +8 -1
- package/dist/services/subscription/paymentInstrument.d.ts.map +1 -1
- package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
- package/dist/services/subscription/types.d.ts +87 -1
- package/dist/services/subscription/types.d.ts.map +1 -1
- package/dist/theme-state.d.ts +10 -1
- package/dist/theme-state.d.ts.map +1 -1
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/vue/context.d.ts +25 -1
- package/dist/vue/context.d.ts.map +1 -1
- package/dist/vue/useTranslatedProp.test.d.ts +2 -0
- package/dist/vue/useTranslatedProp.test.d.ts.map +1 -0
- package/dist/vue.js +36 -2
- package/dist/web-components/editor/InlineText.d.ts +1 -0
- package/dist/web-components/editor/InlineText.d.ts.map +1 -1
- package/dist/web-components-editor.js +13 -5
- package/dist/web-components-runtime.js +2 -2
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4
4
|
import { signal, effect, createBlockInstance, layoutSystemEnabled, untracked } from "@juo/blocks";
|
|
5
5
|
import { reportBlockWarning, reportBlockError } from "./observability.js";
|
|
6
6
|
import { b as isStubDefinition, w as withWrapper, s as subscribeContext, c as backfillInstanceDefaults, d as __clearDevtoolsBlockState, o as onRegisterBlock } from "./block-BjJztStr.js";
|
|
7
|
-
import { L as LAYOUT_SCOPE_ATTR, b as buildGridLayout, a as ThemeStateContext } from "./css-runtime-
|
|
7
|
+
import { L as LAYOUT_SCOPE_ATTR, b as buildGridLayout, a as ThemeStateContext } from "./css-runtime-CjZl0K48.js";
|
|
8
8
|
import { getHook } from "./devtools.js";
|
|
9
9
|
class Block extends HTMLElement {
|
|
10
10
|
constructor() {
|
package/dist/core.js
CHANGED
|
@@ -3,12 +3,33 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { e as createContext, f as d, m as w, n as defineBlock, h as createBlockInstance, j as getDefinedBlocks, p as registerBlock, E, u, s as subscribeContext } from "./block-BjJztStr.js";
|
|
5
5
|
import { B, q, t, S, v, _, x, c, y, g, z, A, D, F, G, i, H, b, I, o, J, k, K, l, L, w as w2 } from "./block-BjJztStr.js";
|
|
6
|
-
import { G as GRID_V1_ENGINE_ID, d as clampRect, e as applyFillExpansion, f as compactItems, g as findFreeRect, D as DEFAULT_GRID } from "./css-runtime-
|
|
7
|
-
import { h, i as i2, L as L2, P, a, T, b as b2, j, k as k2, l as l2, m, n, o as o2, p, q as q2, s, t as t2, u as u2, v as v2, c as c2, w as w3, r } from "./css-runtime-
|
|
6
|
+
import { G as GRID_V1_ENGINE_ID, d as clampRect, e as applyFillExpansion, f as compactItems, g as findFreeRect, D as DEFAULT_GRID } from "./css-runtime-CjZl0K48.js";
|
|
7
|
+
import { h, i as i2, L as L2, P, a, T, b as b2, j, k as k2, l as l2, m, n, o as o2, p, q as q2, s, t as t2, u as u2, v as v2, c as c2, w as w3, r } from "./css-runtime-CjZl0K48.js";
|
|
8
8
|
import { reportBlockWarning, reportBlockError } from "./observability.js";
|
|
9
9
|
import { a as createEditorBridge, E as createSelectBlockMessage } from "./bridge-Mz0CqG6E.js";
|
|
10
|
-
import { p as p2 } from "./project-gridstack-
|
|
10
|
+
import { p as p2 } from "./project-gridstack-CRZ_7HoT.js";
|
|
11
11
|
import { clearLayoutModeAdapter, getLayoutModeAdapter, registerLayoutModeAdapter } from "./layout-mode-adapter-BBd4JRQd.js";
|
|
12
|
+
const SUPPORTED_UI_LANGUAGES = [
|
|
13
|
+
{ code: "cs", label: "Czech" },
|
|
14
|
+
{ code: "da", label: "Danish" },
|
|
15
|
+
{ code: "nl", label: "Dutch" },
|
|
16
|
+
{ code: "en", label: "English" },
|
|
17
|
+
{ code: "fr", label: "French" },
|
|
18
|
+
{ code: "de", label: "German" },
|
|
19
|
+
{ code: "el", label: "Greek" },
|
|
20
|
+
{ code: "hu", label: "Hungarian" },
|
|
21
|
+
{ code: "pl", label: "Polish" },
|
|
22
|
+
{ code: "pt", label: "Portuguese" },
|
|
23
|
+
{ code: "sk", label: "Slovak" },
|
|
24
|
+
{ code: "sl", label: "Slovenian" },
|
|
25
|
+
{ code: "es", label: "Spanish" }
|
|
26
|
+
];
|
|
27
|
+
function toLanguageSelectOptions(languages) {
|
|
28
|
+
return languages.map(({ code, label }) => ({ label, value: code }));
|
|
29
|
+
}
|
|
30
|
+
const SUPPORTED_UI_LANGUAGE_OPTIONS = toLanguageSelectOptions(
|
|
31
|
+
SUPPORTED_UI_LANGUAGES
|
|
32
|
+
);
|
|
12
33
|
function createState() {
|
|
13
34
|
const discountCode = d(null);
|
|
14
35
|
const products = d([]);
|
|
@@ -276,6 +297,13 @@ function createCustomerService(options) {
|
|
|
276
297
|
},
|
|
277
298
|
createPaymentMethod(params) {
|
|
278
299
|
return options.adapter.createPaymentMethod(params);
|
|
300
|
+
},
|
|
301
|
+
async updateAttributes(attributes) {
|
|
302
|
+
var _a;
|
|
303
|
+
const merged = { ...(_a = current.value) == null ? void 0 : _a.attributes, ...attributes };
|
|
304
|
+
const result = await options.adapter.updateAttributes(merged);
|
|
305
|
+
if (result._tag === "Success") current.value = result.data;
|
|
306
|
+
return result;
|
|
279
307
|
}
|
|
280
308
|
};
|
|
281
309
|
}
|
|
@@ -287,7 +315,8 @@ const PAYMENT_INSTRUMENT_TYPES = [
|
|
|
287
315
|
"sepa_direct_debit",
|
|
288
316
|
"blik",
|
|
289
317
|
"mbway",
|
|
290
|
-
"bacs"
|
|
318
|
+
"bacs",
|
|
319
|
+
"manual"
|
|
291
320
|
];
|
|
292
321
|
const INSTRUMENT_TYPE_TO_NAME = {
|
|
293
322
|
credit_card: null,
|
|
@@ -296,7 +325,8 @@ const INSTRUMENT_TYPE_TO_NAME = {
|
|
|
296
325
|
sepa_direct_debit: "SEPA",
|
|
297
326
|
mbway: "MB WAY",
|
|
298
327
|
shop_pay: "Shop Pay",
|
|
299
|
-
bacs: "Bacs"
|
|
328
|
+
bacs: "Bacs",
|
|
329
|
+
manual: "Shopify Checkout"
|
|
300
330
|
};
|
|
301
331
|
function getPaymentInstrumentName(instrument) {
|
|
302
332
|
const name = INSTRUMENT_TYPE_TO_NAME[instrument.type] ?? null;
|
|
@@ -378,16 +408,23 @@ function serializeV1PaymentInstrument(raw) {
|
|
|
378
408
|
return { type: "mbway", ...r2.phone != null ? { phone: r2.phone } : {} };
|
|
379
409
|
case "bacs":
|
|
380
410
|
return { type: "bacs", maskedNumber: r2.maskedNumber ?? "" };
|
|
411
|
+
case "manual":
|
|
412
|
+
return { type: "manual" };
|
|
381
413
|
default:
|
|
382
414
|
return null;
|
|
383
415
|
}
|
|
384
416
|
}
|
|
385
417
|
function createMockCustomerAdapter() {
|
|
386
|
-
|
|
418
|
+
let customer = { id: "customer-1", name: "Customer 1", attributes: {} };
|
|
387
419
|
return {
|
|
388
420
|
async getCurrent() {
|
|
389
421
|
return { _tag: "Success", data: customer };
|
|
390
422
|
},
|
|
423
|
+
async updateAttributes(attributes) {
|
|
424
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
425
|
+
customer = { ...customer, attributes: { ...attributes } };
|
|
426
|
+
return { _tag: "Success", data: customer };
|
|
427
|
+
},
|
|
391
428
|
async createPaymentMethod(params) {
|
|
392
429
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
393
430
|
if (params.provider === "shopify") {
|
|
@@ -410,17 +447,41 @@ function createMockCustomerAdapter() {
|
|
|
410
447
|
}
|
|
411
448
|
};
|
|
412
449
|
}
|
|
450
|
+
function fromV1Customer(body) {
|
|
451
|
+
return {
|
|
452
|
+
id: body.id,
|
|
453
|
+
name: body.displayName,
|
|
454
|
+
email: body.email ?? void 0,
|
|
455
|
+
attributes: Object.fromEntries(
|
|
456
|
+
body.customAttributes.map(({ key, value }) => [key, value])
|
|
457
|
+
)
|
|
458
|
+
};
|
|
459
|
+
}
|
|
413
460
|
function createApiCustomerAdapter(fetcher) {
|
|
414
461
|
return {
|
|
415
462
|
async getCurrent() {
|
|
416
463
|
try {
|
|
417
|
-
const res = await fetcher("/customer/
|
|
464
|
+
const res = await fetcher("/customer/v1/customer");
|
|
465
|
+
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
466
|
+
return {
|
|
467
|
+
_tag: "Success",
|
|
468
|
+
data: fromV1Customer(await res.json())
|
|
469
|
+
};
|
|
470
|
+
} catch (e) {
|
|
471
|
+
return { _tag: "Failure", error: e };
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
async updateAttributes(attributes) {
|
|
475
|
+
try {
|
|
476
|
+
const res = await fetcher("/customer/v1/customer", {
|
|
477
|
+
method: "PATCH",
|
|
478
|
+
headers: { "Content-Type": "application/json" },
|
|
479
|
+
body: JSON.stringify({ customAttributes: attributes })
|
|
480
|
+
});
|
|
418
481
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
419
|
-
const data = await res.json();
|
|
420
|
-
const name = [data.firstName, data.lastName].filter(Boolean).join(" ") || data.email || "";
|
|
421
482
|
return {
|
|
422
483
|
_tag: "Success",
|
|
423
|
-
data:
|
|
484
|
+
data: fromV1Customer(await res.json())
|
|
424
485
|
};
|
|
425
486
|
} catch (e) {
|
|
426
487
|
return { _tag: "Failure", error: e };
|
|
@@ -578,6 +639,12 @@ function createApiLoginAdapter(fetcher, opts) {
|
|
|
578
639
|
});
|
|
579
640
|
}
|
|
580
641
|
}
|
|
642
|
+
if (res.status === 401) {
|
|
643
|
+
const data = await res.json().catch(() => null);
|
|
644
|
+
if (data != null && typeof data === "object" && "message" in data && data.message === "Customer not found") {
|
|
645
|
+
throw new AuthenticationError(AuthenticationErrorReason.Missing);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
581
648
|
if (!res.ok) {
|
|
582
649
|
throw new Error(`Unexpected response: ${res.statusText}`);
|
|
583
650
|
}
|
|
@@ -851,7 +918,10 @@ function createMockOrderAdapter() {
|
|
|
851
918
|
currencyCode: "USD",
|
|
852
919
|
totalPrice: 89.97,
|
|
853
920
|
financialStatus: "PAID",
|
|
921
|
+
paymentStatus: "paid",
|
|
922
|
+
paidAt: "2024-10-15T09:31:00Z",
|
|
854
923
|
fulfillmentStatus: "FULFILLED",
|
|
924
|
+
subscriptionIds: ["subscription_1"],
|
|
855
925
|
lines: [
|
|
856
926
|
{
|
|
857
927
|
id: "line_1",
|
|
@@ -876,7 +946,10 @@ function createMockOrderAdapter() {
|
|
|
876
946
|
currencyCode: "USD",
|
|
877
947
|
totalPrice: 45.99,
|
|
878
948
|
financialStatus: "PAID",
|
|
949
|
+
paymentStatus: "paid",
|
|
950
|
+
paidAt: "2024-09-20T14:16:00Z",
|
|
879
951
|
fulfillmentStatus: "PARTIALLY_FULFILLED",
|
|
952
|
+
subscriptionIds: [],
|
|
880
953
|
lines: [
|
|
881
954
|
{
|
|
882
955
|
id: "line_2",
|
|
@@ -921,11 +994,28 @@ function mapOrder(order) {
|
|
|
921
994
|
currencyCode: order.currencyCode,
|
|
922
995
|
totalPrice: order.totalPrice,
|
|
923
996
|
financialStatus: order.financialStatus,
|
|
997
|
+
// Defaulted rather than required so an older backend (which returns neither
|
|
998
|
+
// field) degrades to "settled, time unknown" instead of producing an Order
|
|
999
|
+
// with holes in it. Matches the endpoint's own fallback for an order it
|
|
1000
|
+
// never tracked.
|
|
1001
|
+
paymentStatus: order.paymentStatus ?? "paid",
|
|
1002
|
+
paidAt: order.paidAt ?? null,
|
|
924
1003
|
fulfillmentStatus: order.fulfillmentStatus,
|
|
925
1004
|
lines: order.items.map(mapOrderLine),
|
|
926
|
-
customAttributes: order.customAttributes
|
|
1005
|
+
customAttributes: order.customAttributes,
|
|
1006
|
+
subscriptionIds: order.subscriptionIds ?? []
|
|
927
1007
|
};
|
|
928
1008
|
}
|
|
1009
|
+
function quoteSearchValue(value) {
|
|
1010
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
1011
|
+
}
|
|
1012
|
+
function buildOrdersQuery(params) {
|
|
1013
|
+
const callerQuery = (params == null ? void 0 : params.query) != null && params.query.trim() !== "" ? params.query : null;
|
|
1014
|
+
const subscriptionTerm = (params == null ? void 0 : params.subscriptionId) != null ? `subscriptionId:${quoteSearchValue(params.subscriptionId)}` : null;
|
|
1015
|
+
if (callerQuery == null) return subscriptionTerm;
|
|
1016
|
+
if (subscriptionTerm == null) return callerQuery;
|
|
1017
|
+
return `(${callerQuery}) AND ${subscriptionTerm}`;
|
|
1018
|
+
}
|
|
929
1019
|
function createApiOrderAdapter(fetcher) {
|
|
930
1020
|
return {
|
|
931
1021
|
async getOrders(params) {
|
|
@@ -933,9 +1023,10 @@ function createApiOrderAdapter(fetcher) {
|
|
|
933
1023
|
if ((params == null ? void 0 : params.limit) != null) query.set("limit", String(params.limit));
|
|
934
1024
|
if ((params == null ? void 0 : params.after) != null) query.set("after", params.after);
|
|
935
1025
|
if ((params == null ? void 0 : params.before) != null) query.set("before", params.before);
|
|
936
|
-
if ((params == null ? void 0 : params.query) != null) query.set("query", params.query);
|
|
937
1026
|
if ((params == null ? void 0 : params.includeOneTime) != null) query.set("includeOneTime", String(params.includeOneTime));
|
|
938
1027
|
if ((params == null ? void 0 : params.sort) != null) query.set("sort", params.sort);
|
|
1028
|
+
const searchQuery = buildOrdersQuery(params);
|
|
1029
|
+
if (searchQuery != null) query.set("query", searchQuery);
|
|
939
1030
|
const qs = query.toString();
|
|
940
1031
|
const res = await fetcher(`/customer/v1/orders${qs ? `?${qs}` : ""}`);
|
|
941
1032
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
@@ -1520,6 +1611,10 @@ function toNonEmptyAttributeArray(next) {
|
|
|
1520
1611
|
({ key, value }) => key !== "" && value !== ""
|
|
1521
1612
|
);
|
|
1522
1613
|
}
|
|
1614
|
+
const MOCK_INSTANT_ORDER_MIN_ITEMS = 1;
|
|
1615
|
+
const MOCK_INSTANT_ORDER_MAX_ITEMS = 20;
|
|
1616
|
+
const MOCK_INSTANT_ORDER_MIN_QUANTITY = 1;
|
|
1617
|
+
const MOCK_INSTANT_ORDER_MAX_QUANTITY = 10;
|
|
1523
1618
|
function createMockSubscriptionAdapter(options = {}) {
|
|
1524
1619
|
const richBase = (id, itemId, renewalId) => ({
|
|
1525
1620
|
id,
|
|
@@ -1804,6 +1899,60 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1804
1899
|
description: "Lightweight daily sun protection"
|
|
1805
1900
|
}
|
|
1806
1901
|
];
|
|
1902
|
+
const mockInstantOrderImages = {
|
|
1903
|
+
"io-product-1": "https://images.unsplash.com/photo-1447933601403-0c6688de566e?w=200",
|
|
1904
|
+
"io-product-2": "https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?w=200"
|
|
1905
|
+
};
|
|
1906
|
+
const mockInstantOrderProducts = [
|
|
1907
|
+
{
|
|
1908
|
+
id: "io-product-1",
|
|
1909
|
+
title: "Single-Origin Espresso",
|
|
1910
|
+
hasOnlyDefaultVariant: false,
|
|
1911
|
+
featuredImage: {
|
|
1912
|
+
url: mockInstantOrderImages["io-product-1"],
|
|
1913
|
+
altText: "Single-Origin Espresso"
|
|
1914
|
+
},
|
|
1915
|
+
variants: {
|
|
1916
|
+
items: [
|
|
1917
|
+
{
|
|
1918
|
+
id: "io-variant-1",
|
|
1919
|
+
title: "250 g",
|
|
1920
|
+
image: { url: mockInstantOrderImages["io-product-1"] },
|
|
1921
|
+
price: { amount: "12.00", currencyCode: "USD" },
|
|
1922
|
+
availableForSale: true
|
|
1923
|
+
},
|
|
1924
|
+
{
|
|
1925
|
+
id: "io-variant-2",
|
|
1926
|
+
title: "1 kg",
|
|
1927
|
+
image: { url: mockInstantOrderImages["io-product-1"] },
|
|
1928
|
+
price: { amount: "38.00", currencyCode: "USD" },
|
|
1929
|
+
availableForSale: true
|
|
1930
|
+
}
|
|
1931
|
+
]
|
|
1932
|
+
}
|
|
1933
|
+
},
|
|
1934
|
+
{
|
|
1935
|
+
id: "io-product-2",
|
|
1936
|
+
title: "Ceramic Pour-Over Dripper",
|
|
1937
|
+
hasOnlyDefaultVariant: true,
|
|
1938
|
+
featuredImage: {
|
|
1939
|
+
url: mockInstantOrderImages["io-product-2"],
|
|
1940
|
+
altText: "Ceramic Pour-Over Dripper"
|
|
1941
|
+
},
|
|
1942
|
+
variants: {
|
|
1943
|
+
items: [
|
|
1944
|
+
{
|
|
1945
|
+
id: "io-variant-3",
|
|
1946
|
+
title: "Default Title",
|
|
1947
|
+
image: { url: mockInstantOrderImages["io-product-2"] },
|
|
1948
|
+
price: { amount: "24.50", currencyCode: "USD" },
|
|
1949
|
+
availableForSale: true
|
|
1950
|
+
}
|
|
1951
|
+
]
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
];
|
|
1955
|
+
let placedInstantOrders = 0;
|
|
1807
1956
|
return {
|
|
1808
1957
|
async getById(id) {
|
|
1809
1958
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -2210,6 +2359,75 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
2210
2359
|
async addUpsellProduct() {
|
|
2211
2360
|
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
2212
2361
|
return { _tag: "Success", data: void 0 };
|
|
2362
|
+
},
|
|
2363
|
+
async getInstantOrderProducts({
|
|
2364
|
+
query
|
|
2365
|
+
}) {
|
|
2366
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
2367
|
+
const term = query == null ? void 0 : query.trim().toLowerCase();
|
|
2368
|
+
const products = term ? mockInstantOrderProducts.filter(
|
|
2369
|
+
(product) => product.title.toLowerCase().includes(term)
|
|
2370
|
+
) : [...mockInstantOrderProducts];
|
|
2371
|
+
return {
|
|
2372
|
+
_tag: "Success",
|
|
2373
|
+
data: {
|
|
2374
|
+
// Deliberately independent of `query`, mirroring the endpoint: a search
|
|
2375
|
+
// that matches nothing must not read as "the feature is unavailable"
|
|
2376
|
+
// and make a consumer hide its entry point mid-interaction.
|
|
2377
|
+
available: mockInstantOrderProducts.length > 0,
|
|
2378
|
+
requiresCheckout: false,
|
|
2379
|
+
products,
|
|
2380
|
+
hasNextPage: false,
|
|
2381
|
+
endCursor: null
|
|
2382
|
+
}
|
|
2383
|
+
};
|
|
2384
|
+
},
|
|
2385
|
+
async placeInstantOrder({
|
|
2386
|
+
items
|
|
2387
|
+
}) {
|
|
2388
|
+
var _a;
|
|
2389
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
2390
|
+
const malformed = items.length < MOCK_INSTANT_ORDER_MIN_ITEMS || items.length > MOCK_INSTANT_ORDER_MAX_ITEMS || items.some(
|
|
2391
|
+
(item) => !Number.isInteger(item.quantity) || item.quantity < MOCK_INSTANT_ORDER_MIN_QUANTITY || item.quantity > MOCK_INSTANT_ORDER_MAX_QUANTITY
|
|
2392
|
+
);
|
|
2393
|
+
if (malformed) {
|
|
2394
|
+
return {
|
|
2395
|
+
_tag: "Failure",
|
|
2396
|
+
error: {
|
|
2397
|
+
kind: "INVALID_REQUEST",
|
|
2398
|
+
message: "Malformed item list"
|
|
2399
|
+
}
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2402
|
+
const variants = mockInstantOrderProducts.flatMap(
|
|
2403
|
+
(product) => product.variants.items
|
|
2404
|
+
);
|
|
2405
|
+
const unknown = items.find(
|
|
2406
|
+
(item) => !variants.some((variant) => variant.id === item.variantId)
|
|
2407
|
+
);
|
|
2408
|
+
if (unknown) {
|
|
2409
|
+
return {
|
|
2410
|
+
_tag: "Failure",
|
|
2411
|
+
error: {
|
|
2412
|
+
kind: "INVALID_REQUEST",
|
|
2413
|
+
message: `Unknown variant ${unknown.variantId}`
|
|
2414
|
+
}
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
const total = items.reduce((sum, item) => {
|
|
2418
|
+
const variant = variants.find((v3) => v3.id === item.variantId);
|
|
2419
|
+
return sum + Number((variant == null ? void 0 : variant.price.amount) ?? 0) * item.quantity;
|
|
2420
|
+
}, 0);
|
|
2421
|
+
placedInstantOrders += 1;
|
|
2422
|
+
return {
|
|
2423
|
+
_tag: "Success",
|
|
2424
|
+
data: {
|
|
2425
|
+
orderId: `io-order-${placedInstantOrders}`,
|
|
2426
|
+
totalPrice: total.toFixed(2),
|
|
2427
|
+
currencyCode: ((_a = variants[0]) == null ? void 0 : _a.price.currencyCode) ?? "USD",
|
|
2428
|
+
status: "paid"
|
|
2429
|
+
}
|
|
2430
|
+
};
|
|
2213
2431
|
}
|
|
2214
2432
|
};
|
|
2215
2433
|
}
|
|
@@ -2352,6 +2570,51 @@ async function readErrorBody(res) {
|
|
|
2352
2570
|
return {};
|
|
2353
2571
|
}
|
|
2354
2572
|
}
|
|
2573
|
+
async function readErrorMessage(res) {
|
|
2574
|
+
const body = await readErrorBody(res);
|
|
2575
|
+
return typeof body.message === "string" ? body.message : void 0;
|
|
2576
|
+
}
|
|
2577
|
+
const PLACE_INSTANT_ORDER_ERROR_KINDS = {
|
|
2578
|
+
400: "INVALID_REQUEST",
|
|
2579
|
+
403: "REFUSED",
|
|
2580
|
+
409: "DUPLICATE_REQUEST",
|
|
2581
|
+
429: "RATE_LIMITED"
|
|
2582
|
+
};
|
|
2583
|
+
function mapInstantOrderProducts(body) {
|
|
2584
|
+
const currencyCode = body.currencyCode;
|
|
2585
|
+
const products = (body.products ?? []).map(
|
|
2586
|
+
(product) => {
|
|
2587
|
+
const image = product.featuredImage ? {
|
|
2588
|
+
url: product.featuredImage.url,
|
|
2589
|
+
...product.featuredImage.altText != null ? { altText: product.featuredImage.altText } : {}
|
|
2590
|
+
} : null;
|
|
2591
|
+
return {
|
|
2592
|
+
id: product.productId,
|
|
2593
|
+
title: product.title,
|
|
2594
|
+
// Shopify's own flag, not a count of the variants this response happens
|
|
2595
|
+
// to carry — the two differ whenever some are filtered.
|
|
2596
|
+
hasOnlyDefaultVariant: product.hasOnlyDefaultVariant,
|
|
2597
|
+
featuredImage: image,
|
|
2598
|
+
variants: {
|
|
2599
|
+
items: (product.variants ?? []).map((variant) => ({
|
|
2600
|
+
id: variant.id,
|
|
2601
|
+
title: variant.title,
|
|
2602
|
+
image,
|
|
2603
|
+
price: { amount: variant.price, currencyCode },
|
|
2604
|
+
availableForSale: variant.availableForSale
|
|
2605
|
+
}))
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
}
|
|
2609
|
+
);
|
|
2610
|
+
return {
|
|
2611
|
+
available: body.available,
|
|
2612
|
+
requiresCheckout: body.requiresCheckout,
|
|
2613
|
+
products,
|
|
2614
|
+
hasNextPage: body.hasNextPage,
|
|
2615
|
+
endCursor: body.endCursor ?? null
|
|
2616
|
+
};
|
|
2617
|
+
}
|
|
2355
2618
|
function createApiSubscriptionAdapter(fetcher) {
|
|
2356
2619
|
const adapter = {
|
|
2357
2620
|
async search(options) {
|
|
@@ -2882,6 +3145,108 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
2882
3145
|
}
|
|
2883
3146
|
},
|
|
2884
3147
|
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
3148
|
+
async getInstantOrderProducts({ subscriptionId, query, after, limit }) {
|
|
3149
|
+
try {
|
|
3150
|
+
const params = new URLSearchParams();
|
|
3151
|
+
if (query) params.set("q", query);
|
|
3152
|
+
if (after != null) params.set("after", after);
|
|
3153
|
+
if (limit != null) params.set("limit", String(limit));
|
|
3154
|
+
const search = params.toString() ? `?${params.toString()}` : "";
|
|
3155
|
+
const res = await fetcher(
|
|
3156
|
+
`/customer/subscriptions/${subscriptionId}/instant-orders/products${search}`
|
|
3157
|
+
);
|
|
3158
|
+
if (!res.ok) {
|
|
3159
|
+
if (res.status === 404) {
|
|
3160
|
+
return { _tag: "Failure", error: { kind: "SUBSCRIPTION_NOT_FOUND" } };
|
|
3161
|
+
}
|
|
3162
|
+
const message = await readErrorMessage(res);
|
|
3163
|
+
return {
|
|
3164
|
+
_tag: "Failure",
|
|
3165
|
+
error: { kind: "UNKNOWN", message: message ?? `HTTP ${res.status}` }
|
|
3166
|
+
};
|
|
3167
|
+
}
|
|
3168
|
+
const body = await res.json().catch(() => null);
|
|
3169
|
+
if (body == null) {
|
|
3170
|
+
return {
|
|
3171
|
+
_tag: "Failure",
|
|
3172
|
+
error: { kind: "UNKNOWN", message: "Malformed response" }
|
|
3173
|
+
};
|
|
3174
|
+
}
|
|
3175
|
+
return { _tag: "Success", data: mapInstantOrderProducts(body) };
|
|
3176
|
+
} catch (e) {
|
|
3177
|
+
return {
|
|
3178
|
+
_tag: "Failure",
|
|
3179
|
+
error: {
|
|
3180
|
+
kind: "NETWORK",
|
|
3181
|
+
message: e instanceof Error ? e.message : void 0
|
|
3182
|
+
}
|
|
3183
|
+
};
|
|
3184
|
+
}
|
|
3185
|
+
},
|
|
3186
|
+
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
3187
|
+
//
|
|
3188
|
+
// No X-Last-Updated-At header: an instant order never mutates the
|
|
3189
|
+
// subscription, so the optimistic-lock preValidation (which only fires when
|
|
3190
|
+
// the header is present) has nothing to guard here.
|
|
3191
|
+
async placeInstantOrder({ subscriptionId, requestKey, items }) {
|
|
3192
|
+
try {
|
|
3193
|
+
const res = await fetcher(
|
|
3194
|
+
`/customer/subscriptions/${subscriptionId}/instant-orders`,
|
|
3195
|
+
{
|
|
3196
|
+
method: "POST",
|
|
3197
|
+
headers: { "Content-Type": "application/json" },
|
|
3198
|
+
body: JSON.stringify({
|
|
3199
|
+
requestKey,
|
|
3200
|
+
// Narrowed to what the endpoint accepts: the rest of
|
|
3201
|
+
// PostableSubscriptionItem describes a subscription line (its
|
|
3202
|
+
// billing policy, its cycle limit), and an instant order is not one.
|
|
3203
|
+
items: items.map(({ variantId, quantity }) => ({
|
|
3204
|
+
variantId,
|
|
3205
|
+
quantity
|
|
3206
|
+
}))
|
|
3207
|
+
})
|
|
3208
|
+
}
|
|
3209
|
+
);
|
|
3210
|
+
if (!res.ok) {
|
|
3211
|
+
if (res.status === 404) {
|
|
3212
|
+
return { _tag: "Failure", error: { kind: "SUBSCRIPTION_NOT_FOUND" } };
|
|
3213
|
+
}
|
|
3214
|
+
const message = await readErrorMessage(res);
|
|
3215
|
+
const kind = PLACE_INSTANT_ORDER_ERROR_KINDS[res.status] ?? "UNKNOWN";
|
|
3216
|
+
return {
|
|
3217
|
+
_tag: "Failure",
|
|
3218
|
+
error: { kind, message: message ?? `HTTP ${res.status}` }
|
|
3219
|
+
};
|
|
3220
|
+
}
|
|
3221
|
+
const body = await res.json().catch(() => null);
|
|
3222
|
+
if (body == null) {
|
|
3223
|
+
return {
|
|
3224
|
+
_tag: "Failure",
|
|
3225
|
+
error: { kind: "UNKNOWN", message: "Malformed response" }
|
|
3226
|
+
};
|
|
3227
|
+
}
|
|
3228
|
+
return {
|
|
3229
|
+
_tag: "Success",
|
|
3230
|
+
data: {
|
|
3231
|
+
orderId: body.orderId,
|
|
3232
|
+
totalPrice: body.totalPrice ?? null,
|
|
3233
|
+
currencyCode: body.currencyCode,
|
|
3234
|
+
status: body.status,
|
|
3235
|
+
...body.paymentUrl != null ? { paymentUrl: body.paymentUrl } : {},
|
|
3236
|
+
...body.reason != null ? { reason: body.reason } : {}
|
|
3237
|
+
}
|
|
3238
|
+
};
|
|
3239
|
+
} catch (e) {
|
|
3240
|
+
return {
|
|
3241
|
+
_tag: "Failure",
|
|
3242
|
+
error: {
|
|
3243
|
+
kind: "NETWORK",
|
|
3244
|
+
message: e instanceof Error ? e.message : void 0
|
|
3245
|
+
}
|
|
3246
|
+
};
|
|
3247
|
+
}
|
|
3248
|
+
},
|
|
3249
|
+
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
2885
3250
|
async getLastOrder({ subscriptionId }) {
|
|
2886
3251
|
try {
|
|
2887
3252
|
const res = await fetcher(
|
|
@@ -3816,10 +4181,98 @@ function createSubscriptionService(adapter) {
|
|
|
3816
4181
|
getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
|
|
3817
4182
|
getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
|
|
3818
4183
|
getUpsellProducts: (params) => adapter.getUpsellProducts ? adapter.getUpsellProducts(params) : Promise.resolve({ _tag: "Success", data: [] }),
|
|
3819
|
-
addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 })
|
|
4184
|
+
addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 }),
|
|
4185
|
+
getInstantOrderProducts: (subscriptionId, params) => adapter.getInstantOrderProducts ? adapter.getInstantOrderProducts({ subscriptionId, ...params }) : Promise.resolve({
|
|
4186
|
+
_tag: "Success",
|
|
4187
|
+
data: {
|
|
4188
|
+
available: false,
|
|
4189
|
+
requiresCheckout: false,
|
|
4190
|
+
products: [],
|
|
4191
|
+
hasNextPage: false,
|
|
4192
|
+
endCursor: null
|
|
4193
|
+
}
|
|
4194
|
+
}),
|
|
4195
|
+
placeInstantOrder: (subscriptionId, requestKey, items) => adapter.placeInstantOrder ? adapter.placeInstantOrder({ subscriptionId, requestKey, items }) : (
|
|
4196
|
+
// Distinguishable from every server-side refusal, so a consumer can
|
|
4197
|
+
// treat "this host cannot do instant orders" as a missing capability
|
|
4198
|
+
// rather than telling the customer their order was declined.
|
|
4199
|
+
Promise.resolve({
|
|
4200
|
+
_tag: "Failure",
|
|
4201
|
+
error: { kind: "UNSUPPORTED" }
|
|
4202
|
+
})
|
|
4203
|
+
)
|
|
3820
4204
|
};
|
|
3821
4205
|
return service;
|
|
3822
4206
|
}
|
|
4207
|
+
function isOneTimeLine(line) {
|
|
4208
|
+
return line.isOneTime === true || line.recurringCycleLimit === 1;
|
|
4209
|
+
}
|
|
4210
|
+
function hasValue(value) {
|
|
4211
|
+
return typeof value === "string" && value.length > 0;
|
|
4212
|
+
}
|
|
4213
|
+
function hasIdentity(line) {
|
|
4214
|
+
return hasValue(line.subscriptionId) && hasValue(line.subscriptionLineId);
|
|
4215
|
+
}
|
|
4216
|
+
function isSameLine(a2, b3) {
|
|
4217
|
+
return hasValue(a2.subscriptionLineId) && a2.subscriptionLineId === b3.subscriptionLineId;
|
|
4218
|
+
}
|
|
4219
|
+
function belongsToSameSubscription(a2, b3) {
|
|
4220
|
+
return hasValue(a2.subscriptionId) && a2.subscriptionId === b3.subscriptionId;
|
|
4221
|
+
}
|
|
4222
|
+
function parentLineFor(child, lines) {
|
|
4223
|
+
if (!hasValue(child.parentLineId)) {
|
|
4224
|
+
return void 0;
|
|
4225
|
+
}
|
|
4226
|
+
return lines.find(
|
|
4227
|
+
(candidate) => belongsToSameSubscription(candidate, child) && (candidate.subscriptionLineId === child.parentLineId || candidate.id === child.parentLineId)
|
|
4228
|
+
);
|
|
4229
|
+
}
|
|
4230
|
+
function productKey(line, lines) {
|
|
4231
|
+
if (hasValue(line.parentProductId)) {
|
|
4232
|
+
return `product:${line.parentProductId}`;
|
|
4233
|
+
}
|
|
4234
|
+
if (hasValue(line.parentLineId)) {
|
|
4235
|
+
const parent = parentLineFor(line, lines);
|
|
4236
|
+
if (hasValue(parent == null ? void 0 : parent.productId)) {
|
|
4237
|
+
return `product:${parent.productId}`;
|
|
4238
|
+
}
|
|
4239
|
+
return `line:${line.parentLineId}`;
|
|
4240
|
+
}
|
|
4241
|
+
const lineIdentity = hasValue(line.subscriptionLineId) ? line.subscriptionLineId : line.id;
|
|
4242
|
+
if (!hasValue(lineIdentity)) {
|
|
4243
|
+
return null;
|
|
4244
|
+
}
|
|
4245
|
+
const isReferencedAsParent = lines.some(
|
|
4246
|
+
(candidate) => belongsToSameSubscription(candidate, line) && (hasValue(line.productId) && candidate.parentProductId === line.productId || hasValue(candidate.parentLineId) && (candidate.parentLineId === line.subscriptionLineId || candidate.parentLineId === line.id))
|
|
4247
|
+
);
|
|
4248
|
+
if (isReferencedAsParent && hasValue(line.productId)) {
|
|
4249
|
+
return `product:${line.productId}`;
|
|
4250
|
+
}
|
|
4251
|
+
return `line:${lineIdentity}`;
|
|
4252
|
+
}
|
|
4253
|
+
function remainingRecurringProductKeys(line, lines) {
|
|
4254
|
+
const removedProductKey = productKey(line, lines);
|
|
4255
|
+
return new Set(
|
|
4256
|
+
lines.filter(
|
|
4257
|
+
(item) => belongsToSameSubscription(item, line) && !isOneTimeLine(item)
|
|
4258
|
+
).map((item) => productKey(item, lines)).filter((key) => key != null && key !== removedProductKey)
|
|
4259
|
+
);
|
|
4260
|
+
}
|
|
4261
|
+
function canRemoveLine(line, lines) {
|
|
4262
|
+
if (!hasIdentity(line)) {
|
|
4263
|
+
return false;
|
|
4264
|
+
}
|
|
4265
|
+
const targetExists = lines.some(
|
|
4266
|
+
(item) => belongsToSameSubscription(item, line) && isSameLine(item, line)
|
|
4267
|
+
);
|
|
4268
|
+
if (!targetExists) {
|
|
4269
|
+
return false;
|
|
4270
|
+
}
|
|
4271
|
+
if (isOneTimeLine(line)) {
|
|
4272
|
+
return true;
|
|
4273
|
+
}
|
|
4274
|
+
return remainingRecurringProductKeys(line, lines).size > 0;
|
|
4275
|
+
}
|
|
3823
4276
|
function getDefaultBlockForAction(actionType, actionConfig, blockId) {
|
|
3824
4277
|
const blockName = `action:${actionType}`;
|
|
3825
4278
|
const definedBlocks = getDefinedBlocks();
|
|
@@ -4798,6 +5251,8 @@ export {
|
|
|
4798
5251
|
PAYMENT_INSTRUMENT_TYPES,
|
|
4799
5252
|
ProductServiceContext,
|
|
4800
5253
|
RouterServiceContext,
|
|
5254
|
+
SUPPORTED_UI_LANGUAGES,
|
|
5255
|
+
SUPPORTED_UI_LANGUAGE_OPTIONS,
|
|
4801
5256
|
SchedulesServiceContext,
|
|
4802
5257
|
S as SelectedBlockContext,
|
|
4803
5258
|
SettingsServiceContext,
|
|
@@ -4814,6 +5269,8 @@ export {
|
|
|
4814
5269
|
c as backfillInstanceDefaults,
|
|
4815
5270
|
b2 as buildGridLayout,
|
|
4816
5271
|
j as buildLayoutCss,
|
|
5272
|
+
buildOrdersQuery,
|
|
5273
|
+
canRemoveLine,
|
|
4817
5274
|
canvasMode,
|
|
4818
5275
|
clampRect,
|
|
4819
5276
|
k2 as classifyRowDividers,
|
|
@@ -4867,6 +5324,7 @@ export {
|
|
|
4867
5324
|
emitLayoutSetRects,
|
|
4868
5325
|
q2 as expandFillLayoutDocument,
|
|
4869
5326
|
findFreeRect,
|
|
5327
|
+
fromV1Customer,
|
|
4870
5328
|
getActiveSurfaceContext,
|
|
4871
5329
|
getDefaultBlockForAction,
|
|
4872
5330
|
getDefinedBlocks,
|
|
@@ -4884,6 +5342,7 @@ export {
|
|
|
4884
5342
|
insertRectRelative,
|
|
4885
5343
|
H as isEditorPreview,
|
|
4886
5344
|
isFilterQuery,
|
|
5345
|
+
isOneTimeLine,
|
|
4887
5346
|
isStaleSubscriptionMessage,
|
|
4888
5347
|
b as isStubDefinition,
|
|
4889
5348
|
t2 as layoutScopeSelector,
|
|
@@ -4910,6 +5369,7 @@ export {
|
|
|
4910
5369
|
l as setLayoutSystemEnabled,
|
|
4911
5370
|
d as signal,
|
|
4912
5371
|
subscribeContext,
|
|
5372
|
+
toLanguageSelectOptions,
|
|
4913
5373
|
L as untracked,
|
|
4914
5374
|
waitForDevBlocksUrl,
|
|
4915
5375
|
w2 as withWrapper
|