@sixtyninecommerce/admin 0.10.0 → 0.12.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 +5772 -118
- package/dist/auth/index.d.ts +7 -1
- package/dist/auth/index.js +8 -1
- package/dist/catalog/assets.d.ts +120 -8
- package/dist/catalog/assets.js +98 -12
- package/dist/catalog/collections.d.ts +279 -14
- package/dist/catalog/collections.js +246 -15
- package/dist/catalog/documents.d.ts +142 -0
- package/dist/catalog/documents.js +114 -0
- package/dist/catalog/index.d.ts +54 -6
- package/dist/catalog/index.js +10 -1
- package/dist/catalog/metadata.d.ts +244 -0
- package/dist/catalog/metadata.js +220 -0
- package/dist/catalog/products.d.ts +159 -19
- package/dist/catalog/products.js +88 -13
- package/dist/catalog/properties.d.ts +140 -14
- package/dist/catalog/properties.js +65 -1
- package/dist/catalog/recommendations.d.ts +288 -0
- package/dist/catalog/recommendations.js +237 -0
- package/dist/catalog/reviews.d.ts +381 -0
- package/dist/catalog/reviews.js +325 -0
- package/dist/catalog/types.d.ts +17 -1
- package/dist/catalog/types.js +10 -0
- package/dist/catalog/variant-find.d.ts +136 -0
- package/dist/catalog/variant-find.js +239 -0
- package/dist/catalog/variants.d.ts +293 -26
- package/dist/catalog/variants.js +164 -7
- package/dist/catalog/visibility.d.ts +38 -7
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +121 -9
- package/dist/client.js +53 -14
- package/dist/content/assets.d.ts +285 -0
- package/dist/content/assets.js +181 -0
- package/dist/content/forms.d.ts +332 -1
- package/dist/content/forms.js +140 -4
- package/dist/content/items.d.ts +292 -0
- package/dist/content/items.js +170 -0
- package/dist/content/menus.d.ts +254 -0
- package/dist/content/menus.js +70 -0
- package/dist/content/strings.d.ts +137 -0
- package/dist/content/strings.js +82 -0
- package/dist/content/types.d.ts +282 -0
- package/dist/content/types.js +100 -0
- package/dist/customers/age-verification.d.ts +66 -0
- package/dist/customers/age-verification.js +79 -0
- package/dist/customers/credit.d.ts +263 -0
- package/dist/customers/credit.js +244 -0
- package/dist/customers/delivery-preferences.d.ts +120 -0
- package/dist/customers/delivery-preferences.js +97 -0
- package/dist/customers/delivery-terms.d.ts +44 -0
- package/dist/customers/delivery-terms.js +32 -0
- package/dist/customers/groups.d.ts +207 -0
- package/dist/customers/groups.js +438 -0
- package/dist/customers/index.d.ts +462 -37
- package/dist/customers/index.js +317 -40
- package/dist/customers/invitation-status.d.ts +57 -0
- package/dist/customers/invitation-status.js +21 -0
- package/dist/customers/notes.d.ts +67 -0
- package/dist/customers/notes.js +51 -0
- package/dist/customers/notification-recipients.d.ts +97 -0
- package/dist/customers/notification-recipients.js +84 -0
- package/dist/customers/saved-lists.d.ts +42 -0
- package/dist/customers/saved-lists.js +61 -0
- package/dist/customers/vat.d.ts +83 -0
- package/dist/customers/vat.js +46 -0
- package/dist/customers/wire.d.ts +20 -0
- package/dist/customers/wire.js +35 -0
- package/dist/documents/ar.d.ts +307 -0
- package/dist/documents/ar.js +254 -0
- package/dist/documents/emails.d.ts +150 -0
- package/dist/documents/emails.js +220 -0
- package/dist/documents/index.d.ts +744 -21
- package/dist/documents/index.js +438 -24
- package/dist/documents/pdf.d.ts +2 -0
- package/dist/documents/pdf.js +11 -0
- package/dist/fulfillments/create.d.ts +167 -0
- package/dist/fulfillments/create.js +216 -0
- package/dist/fulfillments/index.d.ts +163 -11
- package/dist/fulfillments/index.js +135 -6
- package/dist/fulfillments/payment-policy.d.ts +64 -0
- package/dist/fulfillments/payment-policy.js +140 -0
- package/dist/fulfillments/warehouse.d.ts +724 -0
- package/dist/fulfillments/warehouse.js +914 -0
- package/dist/geo/index.d.ts +119 -0
- package/dist/geo/index.js +107 -0
- package/dist/index.d.ts +147 -39
- package/dist/index.js +51 -12
- package/dist/integrations/afas-actions.d.ts +234 -0
- package/dist/integrations/afas-actions.js +310 -0
- package/dist/integrations/afas-types.d.ts +483 -0
- package/dist/integrations/afas-types.js +5 -0
- package/dist/integrations/afas.d.ts +234 -0
- package/dist/integrations/afas.js +290 -0
- package/dist/integrations/connections.d.ts +103 -0
- package/dist/integrations/connections.js +55 -0
- package/dist/integrations/esp.d.ts +313 -0
- package/dist/integrations/esp.js +169 -0
- package/dist/integrations/exact-online-types.d.ts +965 -0
- package/dist/integrations/exact-online-types.js +6 -0
- package/dist/integrations/exact-online.d.ts +784 -0
- package/dist/integrations/exact-online.js +1089 -0
- package/dist/integrations/index.d.ts +44 -3
- package/dist/integrations/index.js +23 -3
- package/dist/integrations/pipeline-discoveries.d.ts +65 -0
- package/dist/integrations/pipeline-discoveries.js +65 -0
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipeline-runs.d.ts +119 -0
- package/dist/integrations/pipeline-runs.js +87 -0
- package/dist/integrations/pipelines.d.ts +87 -15
- package/dist/integrations/pipelines.js +41 -22
- package/dist/integrations/price-import.d.ts +223 -0
- package/dist/integrations/price-import.js +124 -0
- package/dist/integrations/types.d.ts +367 -3
- package/dist/integrations/types.js +4 -3
- package/dist/locations/index.d.ts +66 -0
- package/dist/locations/index.js +31 -0
- package/dist/meta/index.d.ts +172 -0
- package/dist/metafields/index.d.ts +8 -1
- package/dist/metafields/index.js +10 -0
- package/dist/orders/cancel-with-money.d.ts +237 -0
- package/dist/orders/cancel-with-money.js +155 -0
- package/dist/orders/commit-edit.d.ts +23 -1
- package/dist/orders/commit-edit.js +19 -2
- package/dist/orders/deposit-policy.d.ts +3 -1
- package/dist/orders/drafts.d.ts +800 -0
- package/dist/orders/drafts.js +771 -0
- package/dist/orders/fields.d.ts +245 -0
- package/dist/orders/fields.js +188 -0
- package/dist/orders/get.d.ts +29 -19
- package/dist/orders/get.js +17 -8
- package/dist/orders/index.d.ts +66 -15
- package/dist/orders/index.js +25 -2
- package/dist/orders/lifecycle.d.ts +128 -0
- package/dist/orders/lifecycle.js +158 -0
- package/dist/orders/line-price-preview.d.ts +7 -2
- package/dist/orders/list.d.ts +243 -0
- package/dist/orders/list.js +487 -0
- package/dist/orders/manual-discounts.d.ts +13 -5
- package/dist/orders/manual-pricing.d.ts +5 -0
- package/dist/orders/money-view.d.ts +149 -0
- package/dist/orders/money-view.js +99 -0
- package/dist/orders/order-entry.d.ts +20 -7
- package/dist/orders/plan-edit.d.ts +34 -2
- package/dist/orders/plan-edit.js +112 -11
- package/dist/orders/settings.d.ts +201 -0
- package/dist/orders/settings.js +325 -0
- package/dist/orders/status.d.ts +159 -13
- package/dist/orders/status.js +21 -0
- package/dist/orders/surcharges.d.ts +20 -1
- package/dist/orders/surcharges.js +37 -11
- package/dist/payments/account-credit.d.ts +46 -0
- package/dist/payments/account-credit.js +42 -0
- package/dist/payments/ar.d.ts +292 -0
- package/dist/payments/ar.js +223 -0
- package/dist/payments/connected-account.d.ts +47 -0
- package/dist/payments/connected-account.js +61 -0
- package/dist/payments/credit-noted-fields.d.ts +19 -0
- package/dist/payments/credit-noted-fields.js +69 -0
- package/dist/payments/customer-consent.d.ts +30 -0
- package/dist/payments/customer-consent.js +49 -0
- package/dist/payments/index.d.ts +340 -19
- package/dist/payments/index.js +151 -1
- package/dist/payments/methods.d.ts +303 -8
- package/dist/payments/methods.js +337 -7
- package/dist/payments/mollie-methods.d.ts +159 -0
- package/dist/payments/mollie-methods.js +141 -0
- package/dist/payments/payment-links.d.ts +180 -0
- package/dist/payments/payment-links.js +97 -0
- package/dist/payments/provider-keys.d.ts +150 -0
- package/dist/payments/provider-keys.js +118 -0
- package/dist/payments/providers.d.ts +86 -11
- package/dist/payments/providers.js +29 -0
- package/dist/payments/requests.d.ts +147 -0
- package/dist/payments/requests.js +93 -0
- package/dist/payments/store-credit-fields.d.ts +15 -0
- package/dist/payments/store-credit-fields.js +51 -0
- package/dist/pickups/index.d.ts +106 -0
- package/dist/pickups/index.js +108 -0
- package/dist/platform/channels.d.ts +132 -0
- package/dist/platform/channels.js +128 -0
- package/dist/platform/email-gateways.d.ts +165 -0
- package/dist/platform/email-gateways.js +78 -0
- package/dist/platform/geo.d.ts +123 -0
- package/dist/platform/geo.js +144 -0
- package/dist/platform/tax.d.ts +162 -0
- package/dist/platform/tax.js +169 -0
- package/dist/pos/anomalies.d.ts +158 -0
- package/dist/pos/anomalies.js +64 -0
- package/dist/pos/assisted-selling.d.ts +79 -0
- package/dist/pos/assisted-selling.js +38 -0
- package/dist/pos/exchanges.d.ts +108 -0
- package/dist/pos/exchanges.js +22 -0
- package/dist/pos/gift-cards.d.ts +135 -0
- package/dist/pos/gift-cards.js +47 -0
- package/dist/pos/index.d.ts +2370 -58
- package/dist/pos/index.js +854 -7
- package/dist/pos/no-receipt.d.ts +94 -0
- package/dist/pos/no-receipt.js +25 -0
- package/dist/pos/offline-sales.d.ts +228 -0
- package/dist/pos/offline-sales.js +170 -0
- package/dist/pos/pay-by-link.d.ts +143 -0
- package/dist/pos/pay-by-link.js +57 -0
- package/dist/pos/quick-keys.d.ts +103 -0
- package/dist/pos/quick-keys.js +45 -0
- package/dist/pos/reports.d.ts +360 -0
- package/dist/pos/reports.js +62 -0
- package/dist/pos/returns.d.ts +244 -0
- package/dist/pos/returns.js +83 -0
- package/dist/pricing/bulk-coupons.d.ts +139 -0
- package/dist/pricing/bulk-coupons.js +112 -0
- package/dist/pricing/index.d.ts +174 -4
- package/dist/pricing/index.js +174 -1
- package/dist/pricing/price-lists.d.ts +606 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/purchasing/alerts.d.ts +104 -0
- package/dist/purchasing/alerts.js +88 -0
- package/dist/purchasing/backorders.d.ts +61 -0
- package/dist/purchasing/backorders.js +92 -0
- package/dist/purchasing/cost.d.ts +110 -0
- package/dist/purchasing/cost.js +86 -0
- package/dist/purchasing/index.d.ts +54 -0
- package/dist/purchasing/index.js +24 -0
- package/dist/purchasing/links.d.ts +263 -0
- package/dist/purchasing/links.js +192 -0
- package/dist/purchasing/purchase-orders.d.ts +551 -0
- package/dist/purchasing/purchase-orders.js +491 -0
- package/dist/purchasing/receipts.d.ts +396 -0
- package/dist/purchasing/receipts.js +287 -0
- package/dist/purchasing/replenishment.d.ts +281 -0
- package/dist/purchasing/replenishment.js +240 -0
- package/dist/purchasing/returns.d.ts +273 -0
- package/dist/purchasing/returns.js +229 -0
- package/dist/purchasing/settings.d.ts +152 -0
- package/dist/purchasing/settings.js +181 -0
- package/dist/purchasing/suppliers.d.ts +476 -0
- package/dist/purchasing/suppliers.js +438 -0
- package/dist/quotes/index.d.ts +518 -0
- package/dist/quotes/index.js +439 -0
- package/dist/reports/index.d.ts +71 -8
- package/dist/reports/index.js +74 -11
- package/dist/returns/index.d.ts +675 -21
- package/dist/returns/index.js +756 -11
- package/dist/search/index.d.ts +76 -1
- package/dist/search/index.js +63 -0
- package/dist/seo/config.d.ts +128 -0
- package/dist/seo/config.js +95 -0
- package/dist/seo/redirects.d.ts +125 -0
- package/dist/seo/redirects.js +60 -1
- package/dist/seo/settings.d.ts +147 -0
- package/dist/seo/settings.js +209 -0
- package/dist/shipping/definitions.d.ts +29 -0
- package/dist/shipping/definitions.js +47 -0
- package/dist/shipping/fulfillment-profiles.d.ts +174 -0
- package/dist/shipping/fulfillment-profiles.js +104 -0
- package/dist/shipping/hendriks.d.ts +97 -0
- package/dist/shipping/hendriks.js +50 -0
- package/dist/shipping/index.d.ts +54 -0
- package/dist/shipping/index.js +27 -0
- package/dist/shipping/methods.d.ts +205 -0
- package/dist/shipping/methods.js +240 -0
- package/dist/shipping/myparcel.d.ts +668 -0
- package/dist/shipping/myparcel.js +466 -0
- package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
- package/dist/shipping/parcel-rule.d.ts +6 -5
- package/dist/shipping/parcel-rule.js +21 -23
- package/dist/shipping/rate-tables.d.ts +324 -0
- package/dist/shipping/rate-tables.js +390 -0
- package/dist/shipping/ship-to-countries.d.ts +75 -0
- package/dist/shipping/ship-to-countries.js +47 -0
- package/dist/stock/by-location.d.ts +86 -0
- package/dist/stock/by-location.js +94 -0
- package/dist/stock/index.d.ts +18 -4
- package/dist/stock/index.js +7 -0
- package/dist/stock/locations.d.ts +144 -0
- package/dist/stock/locations.js +168 -0
- package/dist/stock/settings.d.ts +106 -0
- package/dist/stock/settings.js +103 -0
- package/dist/stock/transfers.d.ts +386 -52
- package/dist/stock/transfers.js +222 -17
- package/dist/stored-value/index.d.ts +312 -11
- package/dist/stored-value/index.js +223 -4
- package/dist/subscriptions/index.d.ts +682 -0
- package/dist/subscriptions/index.js +815 -0
- package/dist/tax/display-policy.d.ts +105 -0
- package/dist/tax/display-policy.js +84 -0
- package/dist/tax/index.d.ts +79 -1
- package/dist/tax/index.js +52 -0
- package/dist/tenant/email-style.d.ts +102 -0
- package/dist/tenant/email-style.js +72 -0
- package/dist/tenant/email-templates.d.ts +287 -0
- package/dist/tenant/email-templates.js +271 -0
- package/dist/tenant/notifications.d.ts +23 -17
- package/dist/tenant/settings-sources.d.ts +1 -1
- package/dist/tenant/time-zone.d.ts +17 -0
- package/dist/tenant/time-zone.js +11 -0
- package/dist/types.d.ts +50 -3
- package/dist/users/index.d.ts +3 -0
- package/dist/users/index.js +2 -0
- package/dist/users/warehouses.d.ts +50 -0
- package/dist/users/warehouses.js +51 -0
- package/package.json +2 -2
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { ValidationError } from '@sixtyninecommerce/core';
|
|
2
|
+
import { createSearchModule, escapeSearchFilterValue } from '../search/index.js';
|
|
3
|
+
import { fieldOf } from './types.js';
|
|
4
|
+
/** The most variants one `variants.find` answers. */
|
|
5
|
+
export const MAX_VARIANT_FIND_TAKE = 500;
|
|
6
|
+
/** The most products one `variants.find` search reads (`take / perProduct`, rounded up). */
|
|
7
|
+
export const MAX_VARIANT_FIND_PRODUCTS = 100;
|
|
8
|
+
const FOUND_VARIANT_PRODUCT_FIELDS = /* GraphQL */ `
|
|
9
|
+
id
|
|
10
|
+
name
|
|
11
|
+
slug
|
|
12
|
+
featuredAsset {
|
|
13
|
+
id
|
|
14
|
+
preview
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
/**
|
|
18
|
+
* What a picker reads of a variant. `storePrice`, never core's `price` / `priceWithTax`: those
|
|
19
|
+
* throw for a variant the store has no price for, and one such variant would empty the answer.
|
|
20
|
+
*/
|
|
21
|
+
export const FOUND_VARIANT_FIELDS = /* GraphQL */ `
|
|
22
|
+
id
|
|
23
|
+
name
|
|
24
|
+
sku
|
|
25
|
+
enabled
|
|
26
|
+
storePrice {
|
|
27
|
+
price
|
|
28
|
+
priceWithTax
|
|
29
|
+
currencyCode
|
|
30
|
+
}
|
|
31
|
+
trackInventory
|
|
32
|
+
outOfStockThreshold
|
|
33
|
+
useGlobalOutOfStockThreshold
|
|
34
|
+
stockOnHand
|
|
35
|
+
stockAllocated
|
|
36
|
+
stockLevels {
|
|
37
|
+
stockLocationId
|
|
38
|
+
stockOnHand
|
|
39
|
+
stockAllocated
|
|
40
|
+
stockLocation {
|
|
41
|
+
id
|
|
42
|
+
name
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
/** A found variant with its product: the selection of every list that answers variants flat. */
|
|
47
|
+
export const FOUND_VARIANT_WITH_PRODUCT_FIELDS = /* GraphQL */ `
|
|
48
|
+
${FOUND_VARIANT_FIELDS}
|
|
49
|
+
product {
|
|
50
|
+
${FOUND_VARIANT_PRODUCT_FIELDS}
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
export const FIND_VARIANTS_BY_IDS_QUERY = /* GraphQL */ `
|
|
54
|
+
query CatalogFindVariantsByIds($options: ProductVariantListOptions) {
|
|
55
|
+
productVariants(options: $options) {
|
|
56
|
+
items {
|
|
57
|
+
${FOUND_VARIANT_WITH_PRODUCT_FIELDS}
|
|
58
|
+
}
|
|
59
|
+
totalItems
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
/**
|
|
64
|
+
* The variants of some products, bounded PER PRODUCT (`variantList`, never `variants`, which the
|
|
65
|
+
* engine answers whole and then cuts at 1,000 without saying so).
|
|
66
|
+
*/
|
|
67
|
+
export const FIND_VARIANTS_OF_PRODUCTS_QUERY = /* GraphQL */ `
|
|
68
|
+
query CatalogFindVariantsOfProducts(
|
|
69
|
+
$options: ProductListOptions
|
|
70
|
+
$variantOptions: ProductVariantListOptions
|
|
71
|
+
) {
|
|
72
|
+
products(options: $options) {
|
|
73
|
+
items {
|
|
74
|
+
${FOUND_VARIANT_PRODUCT_FIELDS}
|
|
75
|
+
variantList(options: $variantOptions) {
|
|
76
|
+
items {
|
|
77
|
+
${FOUND_VARIANT_FIELDS}
|
|
78
|
+
}
|
|
79
|
+
totalItems
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
totalItems
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
export function toFoundVariant(wire) {
|
|
87
|
+
const { stockLevels, product, ...rest } = wire;
|
|
88
|
+
return {
|
|
89
|
+
...rest,
|
|
90
|
+
stockLevels: stockLevels.map((level) => ({
|
|
91
|
+
stockLocationId: level.stockLocationId,
|
|
92
|
+
stockLocationName: level.stockLocation?.name ?? '',
|
|
93
|
+
stockOnHand: level.stockOnHand,
|
|
94
|
+
stockAllocated: level.stockAllocated,
|
|
95
|
+
})),
|
|
96
|
+
product: {
|
|
97
|
+
id: product.id,
|
|
98
|
+
name: product.name,
|
|
99
|
+
slug: product.slug,
|
|
100
|
+
featuredAsset: product.featuredAsset,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function invalid(message) {
|
|
105
|
+
return new ValidationError({
|
|
106
|
+
code: 'VARIANT_FIND_INPUT_INVALID',
|
|
107
|
+
message,
|
|
108
|
+
status: 400,
|
|
109
|
+
service: 'vendure',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function wholeNumber(value, low, high) {
|
|
113
|
+
return typeof value === 'number' && Number.isInteger(value) && value >= low && value <= high;
|
|
114
|
+
}
|
|
115
|
+
/** A literal inside a regular expression the engine evaluates (Postgres `~*`). */
|
|
116
|
+
function escapeRegex(value) {
|
|
117
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
118
|
+
}
|
|
119
|
+
function criterionOf(input) {
|
|
120
|
+
const given = ['ids', 'term', 'skuPrefix'].filter((key) => input[key] !== undefined);
|
|
121
|
+
if (given.length !== 1) {
|
|
122
|
+
throw invalid(`Say which variants with exactly one of ids, term and skuPrefix; got ${given.length === 0 ? 'none' : given.join(' and ')}.`);
|
|
123
|
+
}
|
|
124
|
+
if (input.ids !== undefined) {
|
|
125
|
+
if (!Array.isArray(input.ids) || input.ids.some((id) => typeof id !== 'string' || id === '')) {
|
|
126
|
+
throw invalid('ids must be a list of variant ids.');
|
|
127
|
+
}
|
|
128
|
+
return { kind: 'ids', ids: [...new Set(input.ids)] };
|
|
129
|
+
}
|
|
130
|
+
const key = input.term !== undefined ? 'term' : 'skuPrefix';
|
|
131
|
+
const text = input[key];
|
|
132
|
+
if (typeof text !== 'string' || text.trim() === '') {
|
|
133
|
+
throw invalid(`${key} must be text to search for; an empty one finds nothing.`);
|
|
134
|
+
}
|
|
135
|
+
return key === 'term'
|
|
136
|
+
? { kind: 'term', term: text.trim() }
|
|
137
|
+
: { kind: 'skuPrefix', prefix: text.trim() };
|
|
138
|
+
}
|
|
139
|
+
/** The call's options with the currency the prices are asked in. */
|
|
140
|
+
function pricedIn(options, currencyCode) {
|
|
141
|
+
if (currencyCode === undefined)
|
|
142
|
+
return options;
|
|
143
|
+
if (typeof currencyCode !== 'string' || currencyCode.trim() === '') {
|
|
144
|
+
throw invalid('currencyCode must be an ISO 4217 code, or left out for the store default.');
|
|
145
|
+
}
|
|
146
|
+
return { ...options, tenant: { ...options?.tenant, currency: currencyCode } };
|
|
147
|
+
}
|
|
148
|
+
async function findByIds(transport, ids, take, options) {
|
|
149
|
+
if (ids.length > take) {
|
|
150
|
+
throw invalid(`ids names ${String(ids.length)} variants and take is ${String(take)}. Raise take, or ask for fewer.`);
|
|
151
|
+
}
|
|
152
|
+
if (ids.length === 0)
|
|
153
|
+
return { items: [], products: [] };
|
|
154
|
+
const list = await fieldOf(transport, FIND_VARIANTS_BY_IDS_QUERY, 'productVariants',
|
|
155
|
+
// Sorted so the engine's page is one total order; the answer is re-ordered below.
|
|
156
|
+
{ options: { filter: { id: { in: ids } }, take: ids.length, sort: { id: 'ASC' } } }, options);
|
|
157
|
+
const found = new Map(list.items.map((row) => [row.id, row]));
|
|
158
|
+
return {
|
|
159
|
+
items: ids.flatMap((id) => {
|
|
160
|
+
const row = found.get(id);
|
|
161
|
+
return row ? [toFoundVariant(row)] : [];
|
|
162
|
+
}),
|
|
163
|
+
products: [],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async function findBySearch(transport, criterion, take, perProduct, options, pricedOptions) {
|
|
167
|
+
const productCount = Math.ceil(take / perProduct);
|
|
168
|
+
if (productCount > MAX_VARIANT_FIND_PRODUCTS) {
|
|
169
|
+
throw invalid(`take ${String(take)} at ${String(perProduct)} per product reads ${String(productCount)} products; at most ${String(MAX_VARIANT_FIND_PRODUCTS)}. Raise perProduct or lower take.`);
|
|
170
|
+
}
|
|
171
|
+
// Which products, and in what order, is the index's answer (`search.index`, never a copy of
|
|
172
|
+
// it): relevance for a term, the product's name for a SKU prefix.
|
|
173
|
+
const hits = await createSearchModule(transport).index('products', criterion.kind === 'term'
|
|
174
|
+
? { term: criterion.term, take: productCount }
|
|
175
|
+
: {
|
|
176
|
+
term: '',
|
|
177
|
+
filters: [`skus STARTS WITH "${escapeSearchFilterValue(criterion.prefix)}"`],
|
|
178
|
+
sort: 'name',
|
|
179
|
+
take: productCount,
|
|
180
|
+
}, options);
|
|
181
|
+
const productIds = hits.items.map((hit) => hit.id);
|
|
182
|
+
if (productIds.length === 0)
|
|
183
|
+
return { items: [], products: [] };
|
|
184
|
+
const list = await fieldOf(transport, FIND_VARIANTS_OF_PRODUCTS_QUERY, 'products', {
|
|
185
|
+
options: { filter: { id: { in: productIds } }, take: productIds.length, sort: { id: 'ASC' } },
|
|
186
|
+
variantOptions: {
|
|
187
|
+
take: perProduct,
|
|
188
|
+
// A total order, so a bounded page is the same page on every read. By id alone: the
|
|
189
|
+
// engine applies the keys of a sort in the order its schema declares them, where `id`
|
|
190
|
+
// precedes `position`, so the `position, id` the pickers used to send was this order.
|
|
191
|
+
sort: { id: 'ASC' },
|
|
192
|
+
// Only a SKU search narrows the variants. A term matches the PRODUCT (its name, its
|
|
193
|
+
// description), and a variant's name is its options, so filtering variants by it would
|
|
194
|
+
// answer a product with nothing to pick.
|
|
195
|
+
...(criterion.kind === 'skuPrefix'
|
|
196
|
+
? { filter: { sku: { regex: `^${escapeRegex(criterion.prefix)}` } } }
|
|
197
|
+
: {}),
|
|
198
|
+
},
|
|
199
|
+
}, pricedOptions);
|
|
200
|
+
const read = new Map(list.items.map((product) => [product.id, product]));
|
|
201
|
+
const items = [];
|
|
202
|
+
const products = [];
|
|
203
|
+
for (const id of productIds) {
|
|
204
|
+
const room = take - items.length;
|
|
205
|
+
if (room <= 0)
|
|
206
|
+
break;
|
|
207
|
+
// The index can name a product the store no longer holds: it is updated after each change.
|
|
208
|
+
const product = read.get(id);
|
|
209
|
+
if (!product)
|
|
210
|
+
continue;
|
|
211
|
+
const rows = product.variantList.items.slice(0, room);
|
|
212
|
+
if (rows.length === 0)
|
|
213
|
+
continue;
|
|
214
|
+
for (const row of rows)
|
|
215
|
+
items.push(toFoundVariant({ ...row, product }));
|
|
216
|
+
products.push({ id: product.id, shown: rows.length, total: product.variantList.totalItems });
|
|
217
|
+
}
|
|
218
|
+
return { items, products };
|
|
219
|
+
}
|
|
220
|
+
/** `catalog.variants.find`; its contract is on `VariantsModule.find`. */
|
|
221
|
+
export async function findVariants(transport, input, options) {
|
|
222
|
+
if (typeof input !== 'object' || input === null)
|
|
223
|
+
throw invalid('find takes an input object.');
|
|
224
|
+
const criterion = criterionOf(input);
|
|
225
|
+
const { take, perProduct } = input;
|
|
226
|
+
if (!wholeNumber(take, 1, MAX_VARIANT_FIND_TAKE)) {
|
|
227
|
+
throw invalid(`take must be a whole number from 1 to ${String(MAX_VARIANT_FIND_TAKE)}.`);
|
|
228
|
+
}
|
|
229
|
+
const pricedOptions = pricedIn(options, input.currencyCode);
|
|
230
|
+
if (criterion.kind === 'ids') {
|
|
231
|
+
if (perProduct !== undefined)
|
|
232
|
+
throw invalid('perProduct bounds a search; ids takes none.');
|
|
233
|
+
return findByIds(transport, criterion.ids, take, pricedOptions);
|
|
234
|
+
}
|
|
235
|
+
if (perProduct !== undefined && !wholeNumber(perProduct, 1, take)) {
|
|
236
|
+
throw invalid(`perProduct must be a whole number from 1 to take (${String(take)}).`);
|
|
237
|
+
}
|
|
238
|
+
return findBySearch(transport, criterion, take, perProduct ?? Math.ceil(take / 10), options, pricedOptions);
|
|
239
|
+
}
|