@misiki/gocommerce-connector 0.27.0 → 0.29.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/README.md +5 -0
- package/dist/{index-BY0qUnNO.d.cts → index-DOlNI60Y.d.cts} +14 -22
- package/dist/{index-BY0qUnNO.d.ts → index-DOlNI60Y.d.ts} +14 -22
- package/dist/index.cjs +28 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +28 -4
- package/dist/index.js.map +1 -1
- package/dist/services/index.cjs +28 -4
- package/dist/services/index.cjs.map +1 -1
- package/dist/services/index.d.cts +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +28 -4
- package/dist/services/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -127,6 +127,7 @@ down stays best-effort: the storefront renders from its static record.
|
|
|
127
127
|
| --- | --- |
|
|
128
128
|
| product page, listings, search | `/api/products`, `/api/products/slug/{slug}` (an id or SKU also works) |
|
|
129
129
|
| category pages and tree | `/api/categories`, `/api/categories/{slug}` — a category sells its descendants |
|
|
130
|
+
| the filter rail's categories | the counts from `/api/products?facets=1`, each with its ancestors from `/api/categories?flat=1`, in tree order and with its `depth`. A parent counts its whole subtree |
|
|
130
131
|
| collections | `/api/collections`, `/api/collections/{slug}` |
|
|
131
132
|
| featured / trending shelves | the collection with slug `featured` / `trending`; newest products when there is none |
|
|
132
133
|
| product page extras | on the product from `/api/products/slug/{slug}` (D134): `highlights` and `freeGift` from the product's own metadata, `soldAtLeast` when the shop shows sold counts (null otherwise, never zero), and the product's videos after its pictures in `images` (and alone in `videos`), so the gallery plays them |
|
|
@@ -241,6 +242,10 @@ Each of these is a real gap, listed so nobody has to find it in production.
|
|
|
241
242
|
vendor, product type, category attributes, price) need an engine that counts
|
|
242
243
|
them (`GET /api/products?facets=1`, D130). Against an older one the filter
|
|
243
244
|
rail is empty and a category page's attribute filters are not applied.
|
|
245
|
+
- **Category counts in a large shop.** The engine counts a listing's products
|
|
246
|
+
in at most 100 categories, the ones with the most products. The connector adds
|
|
247
|
+
those counts up to each parent, so in a shop with more categories a parent's
|
|
248
|
+
count misses the products of the categories the engine left out.
|
|
244
249
|
- **Tax in the bag.** The engine's cart carries no tax or total; tax is computed
|
|
245
250
|
when the order is placed. The bag shows subtotal − discount + delivery, and the
|
|
246
251
|
order shows the real figures.
|
|
@@ -1536,7 +1536,9 @@ declare class BaseService {
|
|
|
1536
1536
|
* Prices a cart at the signed-in shopper's customer-group prices. The
|
|
1537
1537
|
* engine does this only for an account whose email is confirmed (403
|
|
1538
1538
|
* otherwise), and the cart stays the shopper's either way — so a refusal
|
|
1539
|
-
* is not an error, and neither is a build without ext/identity.
|
|
1539
|
+
* is not an error, and neither is a build without ext/identity. A refused
|
|
1540
|
+
* claim still gives the cart the account's email, which the claim would
|
|
1541
|
+
* have set, or the checkout asks the shopper for it again.
|
|
1540
1542
|
*/
|
|
1541
1543
|
protected claimCartForAccount(cartId: string): Promise<void>;
|
|
1542
1544
|
/**
|
|
@@ -2467,13 +2469,19 @@ declare class ProductService extends CatalogService {
|
|
|
2467
2469
|
}
|
|
2468
2470
|
declare const productService: ProductService;
|
|
2469
2471
|
|
|
2472
|
+
type RailCategory = {
|
|
2473
|
+
name: string;
|
|
2474
|
+
slug: string;
|
|
2475
|
+
count: number;
|
|
2476
|
+
depth: number;
|
|
2477
|
+
};
|
|
2470
2478
|
/**
|
|
2471
2479
|
* The engine's counts in the shape the storefront's filter rail reads. Each
|
|
2472
2480
|
* `allFilters` key is also the URL parameter the rail writes when a value is
|
|
2473
2481
|
* ticked, and `searchWithUrl` reads it back: `vendor`, `product_type` and
|
|
2474
2482
|
* `attributes.<handle>`. Tags go to the rail's own tag group, written as `tags`.
|
|
2475
2483
|
*/
|
|
2476
|
-
declare function toStorefrontFacets(f?: ProductFacets | null): {
|
|
2484
|
+
declare function toStorefrontFacets(f?: ProductFacets | null, tree?: Category[]): {
|
|
2477
2485
|
priceStat: {
|
|
2478
2486
|
min: number;
|
|
2479
2487
|
max: number;
|
|
@@ -2481,11 +2489,7 @@ declare function toStorefrontFacets(f?: ProductFacets | null): {
|
|
|
2481
2489
|
min?: undefined;
|
|
2482
2490
|
max?: undefined;
|
|
2483
2491
|
};
|
|
2484
|
-
categories:
|
|
2485
|
-
name: string;
|
|
2486
|
-
slug: string;
|
|
2487
|
-
count: number;
|
|
2488
|
-
}[];
|
|
2492
|
+
categories: RailCategory[];
|
|
2489
2493
|
tags: {
|
|
2490
2494
|
name: string;
|
|
2491
2495
|
count: number;
|
|
@@ -2518,11 +2522,7 @@ declare class SearchService extends CatalogService {
|
|
|
2518
2522
|
min?: undefined;
|
|
2519
2523
|
max?: undefined;
|
|
2520
2524
|
};
|
|
2521
|
-
categories:
|
|
2522
|
-
name: string;
|
|
2523
|
-
slug: string;
|
|
2524
|
-
count: number;
|
|
2525
|
-
}[];
|
|
2525
|
+
categories: RailCategory[];
|
|
2526
2526
|
tags: {
|
|
2527
2527
|
name: string;
|
|
2528
2528
|
count: number;
|
|
@@ -2546,11 +2546,7 @@ declare class SearchService extends CatalogService {
|
|
|
2546
2546
|
min?: undefined;
|
|
2547
2547
|
max?: undefined;
|
|
2548
2548
|
};
|
|
2549
|
-
categories:
|
|
2550
|
-
name: string;
|
|
2551
|
-
slug: string;
|
|
2552
|
-
count: number;
|
|
2553
|
-
}[];
|
|
2549
|
+
categories: RailCategory[];
|
|
2554
2550
|
tags: {
|
|
2555
2551
|
name: string;
|
|
2556
2552
|
count: number;
|
|
@@ -2717,11 +2713,7 @@ declare class SearchService extends CatalogService {
|
|
|
2717
2713
|
min?: undefined;
|
|
2718
2714
|
max?: undefined;
|
|
2719
2715
|
};
|
|
2720
|
-
categories:
|
|
2721
|
-
name: string;
|
|
2722
|
-
slug: string;
|
|
2723
|
-
count: number;
|
|
2724
|
-
}[];
|
|
2716
|
+
categories: RailCategory[];
|
|
2725
2717
|
tags: {
|
|
2726
2718
|
name: string;
|
|
2727
2719
|
count: number;
|
|
@@ -1536,7 +1536,9 @@ declare class BaseService {
|
|
|
1536
1536
|
* Prices a cart at the signed-in shopper's customer-group prices. The
|
|
1537
1537
|
* engine does this only for an account whose email is confirmed (403
|
|
1538
1538
|
* otherwise), and the cart stays the shopper's either way — so a refusal
|
|
1539
|
-
* is not an error, and neither is a build without ext/identity.
|
|
1539
|
+
* is not an error, and neither is a build without ext/identity. A refused
|
|
1540
|
+
* claim still gives the cart the account's email, which the claim would
|
|
1541
|
+
* have set, or the checkout asks the shopper for it again.
|
|
1540
1542
|
*/
|
|
1541
1543
|
protected claimCartForAccount(cartId: string): Promise<void>;
|
|
1542
1544
|
/**
|
|
@@ -2467,13 +2469,19 @@ declare class ProductService extends CatalogService {
|
|
|
2467
2469
|
}
|
|
2468
2470
|
declare const productService: ProductService;
|
|
2469
2471
|
|
|
2472
|
+
type RailCategory = {
|
|
2473
|
+
name: string;
|
|
2474
|
+
slug: string;
|
|
2475
|
+
count: number;
|
|
2476
|
+
depth: number;
|
|
2477
|
+
};
|
|
2470
2478
|
/**
|
|
2471
2479
|
* The engine's counts in the shape the storefront's filter rail reads. Each
|
|
2472
2480
|
* `allFilters` key is also the URL parameter the rail writes when a value is
|
|
2473
2481
|
* ticked, and `searchWithUrl` reads it back: `vendor`, `product_type` and
|
|
2474
2482
|
* `attributes.<handle>`. Tags go to the rail's own tag group, written as `tags`.
|
|
2475
2483
|
*/
|
|
2476
|
-
declare function toStorefrontFacets(f?: ProductFacets | null): {
|
|
2484
|
+
declare function toStorefrontFacets(f?: ProductFacets | null, tree?: Category[]): {
|
|
2477
2485
|
priceStat: {
|
|
2478
2486
|
min: number;
|
|
2479
2487
|
max: number;
|
|
@@ -2481,11 +2489,7 @@ declare function toStorefrontFacets(f?: ProductFacets | null): {
|
|
|
2481
2489
|
min?: undefined;
|
|
2482
2490
|
max?: undefined;
|
|
2483
2491
|
};
|
|
2484
|
-
categories:
|
|
2485
|
-
name: string;
|
|
2486
|
-
slug: string;
|
|
2487
|
-
count: number;
|
|
2488
|
-
}[];
|
|
2492
|
+
categories: RailCategory[];
|
|
2489
2493
|
tags: {
|
|
2490
2494
|
name: string;
|
|
2491
2495
|
count: number;
|
|
@@ -2518,11 +2522,7 @@ declare class SearchService extends CatalogService {
|
|
|
2518
2522
|
min?: undefined;
|
|
2519
2523
|
max?: undefined;
|
|
2520
2524
|
};
|
|
2521
|
-
categories:
|
|
2522
|
-
name: string;
|
|
2523
|
-
slug: string;
|
|
2524
|
-
count: number;
|
|
2525
|
-
}[];
|
|
2525
|
+
categories: RailCategory[];
|
|
2526
2526
|
tags: {
|
|
2527
2527
|
name: string;
|
|
2528
2528
|
count: number;
|
|
@@ -2546,11 +2546,7 @@ declare class SearchService extends CatalogService {
|
|
|
2546
2546
|
min?: undefined;
|
|
2547
2547
|
max?: undefined;
|
|
2548
2548
|
};
|
|
2549
|
-
categories:
|
|
2550
|
-
name: string;
|
|
2551
|
-
slug: string;
|
|
2552
|
-
count: number;
|
|
2553
|
-
}[];
|
|
2549
|
+
categories: RailCategory[];
|
|
2554
2550
|
tags: {
|
|
2555
2551
|
name: string;
|
|
2556
2552
|
count: number;
|
|
@@ -2717,11 +2713,7 @@ declare class SearchService extends CatalogService {
|
|
|
2717
2713
|
min?: undefined;
|
|
2718
2714
|
max?: undefined;
|
|
2719
2715
|
};
|
|
2720
|
-
categories:
|
|
2721
|
-
name: string;
|
|
2722
|
-
slug: string;
|
|
2723
|
-
count: number;
|
|
2724
|
-
}[];
|
|
2716
|
+
categories: RailCategory[];
|
|
2725
2717
|
tags: {
|
|
2726
2718
|
name: string;
|
|
2727
2719
|
count: number;
|
package/dist/index.cjs
CHANGED
|
@@ -440,12 +440,19 @@ var BaseService = class _BaseService {
|
|
|
440
440
|
* Prices a cart at the signed-in shopper's customer-group prices. The
|
|
441
441
|
* engine does this only for an account whose email is confirmed (403
|
|
442
442
|
* otherwise), and the cart stays the shopper's either way — so a refusal
|
|
443
|
-
* is not an error, and neither is a build without ext/identity.
|
|
443
|
+
* is not an error, and neither is a build without ext/identity. A refused
|
|
444
|
+
* claim still gives the cart the account's email, which the claim would
|
|
445
|
+
* have set, or the checkout asks the shopper for it again.
|
|
444
446
|
*/
|
|
445
447
|
async claimCartForAccount(cartId) {
|
|
446
448
|
try {
|
|
447
449
|
await this.engine("/x/identity/me/carts", { method: "POST", body: { cart_id: cartId }, auth: true });
|
|
448
450
|
} catch {
|
|
451
|
+
const email = currentMe()?.email;
|
|
452
|
+
if (email)
|
|
453
|
+
await this.engine(`/api/carts/${encodeURIComponent(cartId)}/email`, { method: "PUT", body: { email } }).catch(
|
|
454
|
+
() => void 0
|
|
455
|
+
);
|
|
449
456
|
}
|
|
450
457
|
}
|
|
451
458
|
// ------------------------------------------------------------ Litekart verbs
|
|
@@ -1586,7 +1593,23 @@ function attributesFrom(p) {
|
|
|
1586
1593
|
return Object.keys(out).length ? out : void 0;
|
|
1587
1594
|
}
|
|
1588
1595
|
var counts = (values) => Object.fromEntries((values ?? []).map((v) => [v.value, v.count]));
|
|
1589
|
-
function
|
|
1596
|
+
function categoryFacets(counted, tree) {
|
|
1597
|
+
const byId = new Map(tree.map((c) => [c.id, c]));
|
|
1598
|
+
const totals = /* @__PURE__ */ new Map();
|
|
1599
|
+
for (const { id: id2, count } of counted) {
|
|
1600
|
+
for (let c = byId.get(id2); c; c = c.parent_id === null ? void 0 : byId.get(c.parent_id)) {
|
|
1601
|
+
totals.set(c.id, (totals.get(c.id) ?? 0) + count);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
const kept = tree.filter((c) => totals.has(c.id)).sort((a, b) => a.position - b.position || a.id - b.id);
|
|
1605
|
+
const parentOf = (c) => c.parent_id !== null && byId.has(c.parent_id) ? c.parent_id : null;
|
|
1606
|
+
const under = (parent) => kept.filter((c) => parentOf(c) === parent).flatMap((c) => [{ name: c.title, slug: c.slug, count: totals.get(c.id), depth: c.depth }, ...under(c.id)]);
|
|
1607
|
+
return [
|
|
1608
|
+
...under(null),
|
|
1609
|
+
...counted.filter((c) => !byId.has(c.id)).map((c) => ({ name: c.title, slug: c.slug, count: c.count, depth: 0 }))
|
|
1610
|
+
];
|
|
1611
|
+
}
|
|
1612
|
+
function toStorefrontFacets(f, tree = []) {
|
|
1590
1613
|
if (!f) return { priceStat: {}, categories: [], tags: [], allFilters: {} };
|
|
1591
1614
|
const allFilters = {};
|
|
1592
1615
|
const group = (key, values) => {
|
|
@@ -1597,7 +1620,7 @@ function toStorefrontFacets(f) {
|
|
|
1597
1620
|
for (const [handle, values] of Object.entries(f.attributes ?? {})) group(`attributes.${handle}`, values);
|
|
1598
1621
|
return {
|
|
1599
1622
|
priceStat: f.price ? { min: toMajor(f.price.min), max: toMajor(f.price.max) } : {},
|
|
1600
|
-
categories: (f.categories ?? []
|
|
1623
|
+
categories: categoryFacets(f.categories ?? [], tree),
|
|
1601
1624
|
tags: (f.tags ?? []).map((t) => ({ name: t.value, count: t.count })),
|
|
1602
1625
|
allFilters
|
|
1603
1626
|
};
|
|
@@ -1630,13 +1653,14 @@ var SearchService = class extends CatalogService {
|
|
|
1630
1653
|
productTypes: listParam(p, "product_type"),
|
|
1631
1654
|
facets: true
|
|
1632
1655
|
});
|
|
1656
|
+
const tree = res.facets?.categories?.length ? await this.facts.categories().catch(() => []) : [];
|
|
1633
1657
|
return {
|
|
1634
1658
|
data: res.data,
|
|
1635
1659
|
count: res.count,
|
|
1636
1660
|
totalPages: res.noOfPage,
|
|
1637
1661
|
page: res.page,
|
|
1638
1662
|
categoryHierarchy: res.categoryHierarchy,
|
|
1639
|
-
facets: toStorefrontFacets(res.facets)
|
|
1663
|
+
facets: toStorefrontFacets(res.facets, tree)
|
|
1640
1664
|
};
|
|
1641
1665
|
} catch (err) {
|
|
1642
1666
|
if (err?.status === 404) return this.emptyResult();
|