@sixtyninecommerce/admin 0.8.0 → 0.10.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 +2739 -17
- package/dist/api-tokens/index.d.ts +15 -5
- package/dist/api-tokens/index.js +1 -0
- package/dist/apps/event-subscription.d.ts +59 -0
- package/dist/apps/event-subscription.js +32 -0
- package/dist/apps/hook-secret.d.ts +22 -0
- package/dist/apps/hook-secret.js +36 -0
- package/dist/apps/index.d.ts +54 -3
- package/dist/apps/index.js +17 -0
- package/dist/audit/index.d.ts +7 -0
- package/dist/auth/queries.d.ts +5 -1
- package/dist/auth/queries.js +6 -0
- package/dist/bulk/index.d.ts +323 -0
- package/dist/bulk/index.js +162 -0
- package/dist/catalog/assets.d.ts +147 -0
- package/dist/catalog/assets.js +164 -0
- package/dist/catalog/collections.d.ts +109 -0
- package/dist/catalog/collections.js +91 -0
- package/dist/catalog/facets.d.ts +103 -0
- package/dist/catalog/facets.js +100 -0
- package/dist/catalog/index.d.ts +115 -0
- package/dist/catalog/index.js +21 -0
- package/dist/catalog/options.d.ts +89 -0
- package/dist/catalog/options.js +88 -0
- package/dist/catalog/products-bulk.d.ts +21 -0
- package/dist/catalog/products-bulk.js +58 -0
- package/dist/catalog/products.d.ts +650 -0
- package/dist/catalog/products.js +458 -0
- package/dist/catalog/properties.d.ts +234 -0
- package/dist/catalog/properties.js +158 -0
- package/dist/catalog/types.d.ts +174 -0
- package/dist/catalog/types.js +141 -0
- package/dist/catalog/variants.d.ts +324 -0
- package/dist/catalog/variants.js +288 -0
- package/dist/catalog/visibility.d.ts +57 -0
- package/dist/catalog/visibility.js +59 -0
- package/dist/client.d.ts +192 -3
- package/dist/client.js +87 -12
- package/dist/compliance/index.d.ts +88 -0
- package/dist/compliance/index.js +88 -0
- package/dist/customer-data-redaction.d.ts +14 -0
- package/dist/customer-data-redaction.js +22 -0
- package/dist/customers/index.d.ts +428 -17
- package/dist/customers/index.js +322 -15
- package/dist/documents/index.d.ts +513 -16
- package/dist/documents/index.js +229 -3
- package/dist/events/index.d.ts +259 -0
- package/dist/events/index.js +147 -0
- package/dist/feeds/ai.d.ts +46 -0
- package/dist/feeds/ai.js +43 -0
- package/dist/feeds/categories.d.ts +50 -0
- package/dist/feeds/categories.js +56 -0
- package/dist/feeds/configs.d.ts +54 -0
- package/dist/feeds/configs.js +85 -0
- package/dist/feeds/identifier-fields.d.ts +25 -0
- package/dist/feeds/identifier-fields.js +29 -0
- package/dist/feeds/index.d.ts +54 -0
- package/dist/feeds/index.js +46 -0
- package/dist/feeds/preserve.d.ts +38 -0
- package/dist/feeds/preserve.js +74 -0
- package/dist/feeds/rules.d.ts +42 -0
- package/dist/feeds/rules.js +56 -0
- package/dist/feeds/types.d.ts +654 -0
- package/dist/feeds/types.js +135 -0
- package/dist/fulfillments/index.d.ts +437 -0
- package/dist/fulfillments/index.js +534 -0
- package/dist/heads/index.d.ts +60 -0
- package/dist/heads/index.js +45 -0
- package/dist/hooks/assignments.d.ts +90 -0
- package/dist/hooks/assignments.js +53 -0
- package/dist/hooks/index.d.ts +97 -0
- package/dist/hooks/index.js +76 -0
- package/dist/index.d.ts +95 -9
- package/dist/index.js +21 -1
- package/dist/integrations/index.d.ts +14 -0
- package/dist/integrations/index.js +9 -0
- package/dist/integrations/pipelines.d.ts +113 -0
- package/dist/integrations/pipelines.js +62 -0
- package/dist/integrations/types.d.ts +176 -0
- package/dist/integrations/types.js +8 -0
- package/dist/jobs/bulk-action-run.d.ts +74 -0
- package/dist/jobs/bulk-action-run.js +69 -0
- package/dist/locations/index.d.ts +6 -2
- package/dist/meta/index.d.ts +32 -0
- package/dist/orders/bulk.d.ts +75 -0
- package/dist/orders/bulk.js +150 -0
- package/dist/orders/commit-edit.d.ts +123 -0
- package/dist/orders/commit-edit.js +142 -0
- package/dist/orders/deposit-policy.d.ts +103 -0
- package/dist/orders/deposit-policy.js +202 -0
- package/dist/orders/get.d.ts +722 -0
- package/dist/orders/get.js +530 -0
- package/dist/orders/index.d.ts +186 -21
- package/dist/orders/index.js +57 -0
- package/dist/orders/line-price-preview.d.ts +297 -0
- package/dist/orders/line-price-preview.js +50 -0
- package/dist/orders/manual-discounts.d.ts +141 -0
- package/dist/orders/manual-discounts.js +97 -0
- package/dist/orders/manual-pricing.d.ts +192 -0
- package/dist/orders/manual-pricing.js +72 -0
- package/dist/orders/order-entry.d.ts +566 -0
- package/dist/orders/order-entry.js +129 -0
- package/dist/orders/parcel-charge.d.ts +45 -0
- package/dist/orders/parcel-charge.js +55 -0
- package/dist/orders/plan-edit.d.ts +489 -0
- package/dist/orders/plan-edit.js +93 -0
- package/dist/orders/status.d.ts +235 -0
- package/dist/orders/status.js +96 -0
- package/dist/orders/surcharges.d.ts +75 -2
- package/dist/orders/surcharges.js +110 -4
- package/dist/payments/account-credit.d.ts +171 -0
- package/dist/payments/account-credit.js +107 -0
- package/dist/payments/index.d.ts +241 -9
- package/dist/payments/index.js +92 -0
- package/dist/payments/methods.d.ts +37 -0
- package/dist/payments/methods.js +33 -0
- package/dist/platform/catalog.d.ts +148 -0
- package/dist/platform/catalog.js +74 -0
- package/dist/platform/entitlements.d.ts +111 -0
- package/dist/platform/entitlements.js +86 -0
- package/dist/platform/legal-entities.d.ts +139 -0
- package/dist/platform/legal-entities.js +126 -0
- package/dist/platform/legal-entity-numbering.d.ts +103 -0
- package/dist/platform/legal-entity-numbering.js +101 -0
- package/dist/platform/organization-membership.d.ts +80 -0
- package/dist/platform/organization-membership.js +71 -0
- package/dist/platform/organization-settings.d.ts +33 -0
- package/dist/platform/organization-settings.js +42 -0
- package/dist/platform/organization-sharing.d.ts +172 -0
- package/dist/platform/organization-sharing.js +120 -0
- package/dist/platform/organizations.d.ts +205 -0
- package/dist/platform/organizations.js +180 -0
- package/dist/platform/provision-store.d.ts +88 -8
- package/dist/platform/provision-store.js +12 -0
- package/dist/platform/reports.d.ts +46 -0
- package/dist/platform/reports.js +31 -0
- package/dist/platform/server-metrics.d.ts +58 -0
- package/dist/platform/server-metrics.js +11 -0
- package/dist/pos/index.d.ts +567 -0
- package/dist/pos/index.js +205 -0
- package/dist/pricing/index.d.ts +408 -0
- package/dist/pricing/index.js +353 -0
- package/dist/pricing/vouchers.d.ts +103 -0
- package/dist/pricing/vouchers.js +69 -0
- package/dist/provenance/index.d.ts +93 -0
- package/dist/provenance/index.js +53 -0
- package/dist/reports/index.d.ts +199 -0
- package/dist/reports/index.js +154 -0
- package/dist/returns/index.d.ts +225 -0
- package/dist/returns/index.js +160 -0
- package/dist/search/index.d.ts +99 -0
- package/dist/search/index.js +62 -0
- package/dist/shipping/parcel-count-suggestion.d.ts +52 -0
- package/dist/shipping/parcel-count-suggestion.js +73 -0
- package/dist/shipping/parcel-rule.d.ts +48 -0
- package/dist/shipping/parcel-rule.js +91 -0
- package/dist/stock/index.d.ts +166 -0
- package/dist/stock/index.js +115 -0
- package/dist/stock/transfers.d.ts +520 -0
- package/dist/stock/transfers.js +437 -0
- package/dist/stored-value/index.d.ts +154 -0
- package/dist/stored-value/index.js +130 -0
- package/dist/tenant/capabilities.d.ts +10 -0
- package/dist/tenant/entitlements.d.ts +35 -0
- package/dist/tenant/entitlements.js +15 -0
- package/dist/tenant/field-groups.d.ts +64 -0
- package/dist/tenant/field-groups.js +34 -0
- package/dist/tenant/legal-entity.d.ts +32 -0
- package/dist/tenant/legal-entity.js +41 -0
- package/dist/tenant/notifications.d.ts +148 -0
- package/dist/tenant/notifications.js +79 -0
- package/dist/tenant/retention.d.ts +10 -4
- package/dist/tenant/settings-sources.d.ts +103 -0
- package/dist/tenant/settings-sources.js +92 -0
- package/dist/types.d.ts +86 -11
- package/dist/uploads/index.d.ts +11 -7
- package/dist/users/index.d.ts +104 -0
- package/dist/users/index.js +80 -0
- package/package.json +3 -2
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
2
|
+
import type { JobHandle } from '../jobs/index.js';
|
|
3
|
+
import type { Call, ListOptions } from '../types.js';
|
|
4
|
+
import { type ProductBulkInput, type ProductBulkRun } from './products-bulk.js';
|
|
5
|
+
import { type AssetRef, type Availability, type AvailabilityInput, type CatalogueOwnership, type FacetValueRef, type LanguageCode, type PriceBasis, type ProductAvailabilityState, type TranslationInput, type VariantAvailabilityState } from './types.js';
|
|
6
|
+
import { type ParcelPacking, type VariantBackorderPolicy, type VariantPriceInput } from './variants.js';
|
|
7
|
+
export interface ProductOptionRef {
|
|
8
|
+
id: string;
|
|
9
|
+
code: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ProductOptionGroupRef {
|
|
13
|
+
id: string;
|
|
14
|
+
code: string;
|
|
15
|
+
name: string;
|
|
16
|
+
options: ProductOptionRef[];
|
|
17
|
+
}
|
|
18
|
+
export interface ProductTranslation {
|
|
19
|
+
id: string;
|
|
20
|
+
languageCode: LanguageCode;
|
|
21
|
+
name: string;
|
|
22
|
+
slug: string;
|
|
23
|
+
description: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A product, in the language the call asked for (`TenantContext.language`,
|
|
27
|
+
* else the store's default). Variants are read separately
|
|
28
|
+
* (`catalog.variants.list(productId)`); `variantCount` says how many there are.
|
|
29
|
+
*/
|
|
30
|
+
export interface Product extends Availability<ProductAvailabilityState> {
|
|
31
|
+
id: string;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
languageCode: LanguageCode;
|
|
35
|
+
name: string;
|
|
36
|
+
slug: string;
|
|
37
|
+
description: string;
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
featuredAsset: AssetRef | null;
|
|
40
|
+
assets: AssetRef[];
|
|
41
|
+
facetValues: FacetValueRef[];
|
|
42
|
+
optionGroups: ProductOptionGroupRef[];
|
|
43
|
+
translations: ProductTranslation[];
|
|
44
|
+
variantCount: number;
|
|
45
|
+
/** The store's own product, or its organization's; see {@link CatalogueOwnership}. */
|
|
46
|
+
catalogueOwnership: CatalogueOwnership;
|
|
47
|
+
/**
|
|
48
|
+
* The ACTIVE store excludes this product its organization shares with it
|
|
49
|
+
* ({@link ProductsModule.exclude}): it is off the store's storefront and out of its carts,
|
|
50
|
+
* while the store's orders, returns and invoices keep it. Always false for the store's own
|
|
51
|
+
* product and in an organization's workspace.
|
|
52
|
+
*/
|
|
53
|
+
excludedFromStore: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface ProductTranslationInput extends TranslationInput {
|
|
56
|
+
name?: string;
|
|
57
|
+
/** Vendure makes a slug unique within the store by suffixing it, rather than refusing a duplicate. */
|
|
58
|
+
slug?: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface CreateProductInput extends AvailabilityInput<ProductAvailabilityState> {
|
|
62
|
+
/** At least one; the store's default language is the one a shop falls back to. */
|
|
63
|
+
translations: ProductTranslationInput[];
|
|
64
|
+
/** Defaults to true on the engine. */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
featuredAssetId?: string | null;
|
|
67
|
+
/** The product's assets, in display order. Replaces the list on update. */
|
|
68
|
+
assetIds?: string[];
|
|
69
|
+
/** Replaces the product's facet values on update — send the whole set. */
|
|
70
|
+
facetValueIds?: string[];
|
|
71
|
+
/**
|
|
72
|
+
* The brand feeds name; at most 70 characters when new or changed (`FEED_IDENTIFIER_INVALID`
|
|
73
|
+
* otherwise). Null or blank clears it. A stored value sent back unchanged is never judged.
|
|
74
|
+
*/
|
|
75
|
+
brand?: string | null;
|
|
76
|
+
condition?: ProductCondition;
|
|
77
|
+
}
|
|
78
|
+
/** A product's condition, as feeds state it. */
|
|
79
|
+
export type ProductCondition = 'new' | 'refurbished' | 'used';
|
|
80
|
+
/** A PATCH: omitted fields are left alone. */
|
|
81
|
+
export interface UpdateProductInput extends Partial<CreateProductInput> {
|
|
82
|
+
id: string;
|
|
83
|
+
}
|
|
84
|
+
/** Every key narrows the list; several are combined with AND. */
|
|
85
|
+
export interface ProductListFilter {
|
|
86
|
+
ids?: string[];
|
|
87
|
+
/** Case-insensitive substring of the name in the requested language. */
|
|
88
|
+
name?: string;
|
|
89
|
+
/** Case-insensitive substring of any variant's SKU. */
|
|
90
|
+
sku?: string;
|
|
91
|
+
enabled?: boolean;
|
|
92
|
+
/** Products carrying ANY of these facet values. */
|
|
93
|
+
facetValueIds?: string[];
|
|
94
|
+
availabilityState?: ProductAvailabilityState;
|
|
95
|
+
}
|
|
96
|
+
export interface ProductListOptions extends ListOptions {
|
|
97
|
+
filter?: ProductListFilter;
|
|
98
|
+
sort?: {
|
|
99
|
+
field: 'name' | 'slug' | 'createdAt' | 'updatedAt';
|
|
100
|
+
direction: 'ASC' | 'DESC';
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** The engine's bound on one `exclude` or `include` call (`STORE_EXCLUSION_BATCH_LIMIT`). */
|
|
104
|
+
export declare const MAX_STORE_EXCLUSION_PRODUCTS = 500;
|
|
105
|
+
/**
|
|
106
|
+
* The engine's bounds on one `setAvailabilityInStores` or `availabilityInStores` call
|
|
107
|
+
* (`AVAILABILITY_*_LIMIT`).
|
|
108
|
+
*/
|
|
109
|
+
export declare const MAX_AVAILABILITY_PRODUCTS = 100;
|
|
110
|
+
export declare const MAX_AVAILABILITY_STORES = 50;
|
|
111
|
+
/**
|
|
112
|
+
* What {@link ProductsModule.setAvailabilityInStores} did to one product in one member store:
|
|
113
|
+
* `excluded` (off: kept by the store for its orders, off its storefront), `unlinked` (off, under
|
|
114
|
+
* the `selected` assortment, from a store that never sold or quoted it), `included` (on again)
|
|
115
|
+
* or `assigned` (on, in a store that did not hold it; its images and variants follow within
|
|
116
|
+
* moments). A string on the wire: a newer engine may add an action.
|
|
117
|
+
*/
|
|
118
|
+
export type OrganizationProductAvailabilityAction = 'excluded' | 'included' | 'unlinked' | 'assigned';
|
|
119
|
+
export interface OrganizationProductAvailabilityChange {
|
|
120
|
+
productId: string;
|
|
121
|
+
/** The member store's channel id. */
|
|
122
|
+
channelId: string;
|
|
123
|
+
action: OrganizationProductAvailabilityAction | (string & {});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* What a member store does with one of the workspace's products, as
|
|
127
|
+
* {@link ProductsModule.availabilityInStores} read it: `offered` (it holds the product and does
|
|
128
|
+
* not exclude it: the product's state, not a promise that a variant is buyable there), `excluded`
|
|
129
|
+
* (kept for its orders, off its storefront and carts; also a product excluded ahead of the
|
|
130
|
+
* organization's fan-out under the `all` assortment, not held yet) or `not-held` (never
|
|
131
|
+
* assigned, or unlinked). A string on the wire: a newer engine may add a state.
|
|
132
|
+
*/
|
|
133
|
+
export type OrganizationProductStoreState = 'offered' | 'excluded' | 'not-held';
|
|
134
|
+
export interface OrganizationProductStoreAvailability {
|
|
135
|
+
productId: string;
|
|
136
|
+
/** The member store's channel id. */
|
|
137
|
+
channelId: string;
|
|
138
|
+
state: OrganizationProductStoreState | (string & {});
|
|
139
|
+
/**
|
|
140
|
+
* The store's own live local copy of this product ({@link ProductsModule.makeLocalCopy}), if
|
|
141
|
+
* it has one; null otherwise.
|
|
142
|
+
*/
|
|
143
|
+
localCopyId: string | null;
|
|
144
|
+
}
|
|
145
|
+
export interface AvailabilityInStoresInput {
|
|
146
|
+
/** Products of the organization's workspace: 1 to {@link MAX_AVAILABILITY_PRODUCTS}. */
|
|
147
|
+
productIds: string[];
|
|
148
|
+
/** Member stores, by channel id: 1 to {@link MAX_AVAILABILITY_STORES}. */
|
|
149
|
+
channelIds: string[];
|
|
150
|
+
}
|
|
151
|
+
export interface SetAvailabilityInStoresInput {
|
|
152
|
+
/** Products of the organization's workspace: 1 to {@link MAX_AVAILABILITY_PRODUCTS}. */
|
|
153
|
+
productIds: string[];
|
|
154
|
+
/** Member stores, by channel id: 1 to {@link MAX_AVAILABILITY_STORES}. */
|
|
155
|
+
channelIds: string[];
|
|
156
|
+
/** True: offer the products in those stores; false: stop offering them there. */
|
|
157
|
+
available: boolean;
|
|
158
|
+
}
|
|
159
|
+
/** A SKU for the copy of one of the shared product's variants, taken as given or refused. */
|
|
160
|
+
export interface LocalCopySkuInput {
|
|
161
|
+
/** The shared product's variant, as the store holds it. */
|
|
162
|
+
productVariantId: string;
|
|
163
|
+
/** Trimmed by the engine; at most 255 characters. */
|
|
164
|
+
sku: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* What became of the organization's product in the store: `excluded` (the store sold or quoted
|
|
168
|
+
* it, or the organization offers every product: it keeps it for its orders, off its storefront)
|
|
169
|
+
* or `unlinked` (removed from the store). A string on the wire: a newer engine may add one.
|
|
170
|
+
*/
|
|
171
|
+
export type LocalCopyOriginalOutcome = 'excluded' | 'unlinked';
|
|
172
|
+
export interface LocalCopyResult {
|
|
173
|
+
/** The store's own copy, created DISABLED. */
|
|
174
|
+
product: Product;
|
|
175
|
+
/** The organization's product the copy was made from. */
|
|
176
|
+
originalProductId: string;
|
|
177
|
+
original: LocalCopyOriginalOutcome | (string & {});
|
|
178
|
+
/**
|
|
179
|
+
* How many of the organization's properties had a value on the original: the copy does not
|
|
180
|
+
* carry them (only the store's own property groups are copied), so say so before enabling it.
|
|
181
|
+
*/
|
|
182
|
+
droppedOrganizationPropertyCount: number;
|
|
183
|
+
}
|
|
184
|
+
/** The engine's bound on each list of one {@link ProductsModule.setCollections} call. */
|
|
185
|
+
export declare const MAX_PRODUCT_COLLECTION_IDS = 200;
|
|
186
|
+
/**
|
|
187
|
+
* Why a collection {@link ProductsModule.setCollections} was asked to take the product out of
|
|
188
|
+
* still holds it: `MEMBER_BY_FILTER`, the product is not on the collection's hand-picked list but
|
|
189
|
+
* matches its other filters (facet values, names), which the call never changes. A string on the
|
|
190
|
+
* wire: a newer engine may add a reason.
|
|
191
|
+
*/
|
|
192
|
+
export type ProductCollectionNotRemovedReason = 'MEMBER_BY_FILTER';
|
|
193
|
+
/** What {@link ProductsModule.setCollections} did, per collection id, each list in id order. */
|
|
194
|
+
export interface ProductCollectionsResult {
|
|
195
|
+
/** Collections whose hand-picked list now names the product. */
|
|
196
|
+
added: string[];
|
|
197
|
+
/** Collections whose hand-picked lists no longer name it. */
|
|
198
|
+
removed: string[];
|
|
199
|
+
/** Collections the call named (or, without `from`, found) that needed no write. */
|
|
200
|
+
unchanged: string[];
|
|
201
|
+
/** Collections the product was to leave but stays in. */
|
|
202
|
+
notRemoved: Array<{
|
|
203
|
+
collectionId: string;
|
|
204
|
+
reason: ProductCollectionNotRemovedReason | (string & {});
|
|
205
|
+
}>;
|
|
206
|
+
}
|
|
207
|
+
/** The product's own fields in a {@link ProductsModule.save}; a PATCH. */
|
|
208
|
+
export interface SaveProductFieldsInput extends AvailabilityInput<ProductAvailabilityState> {
|
|
209
|
+
/** In the save's `languageCode`. */
|
|
210
|
+
name?: string;
|
|
211
|
+
slug?: string;
|
|
212
|
+
description?: string;
|
|
213
|
+
enabled?: boolean;
|
|
214
|
+
/** Null: no featured image. */
|
|
215
|
+
featuredAssetId?: string | null;
|
|
216
|
+
/** The product's images, in display order; replaces the list. */
|
|
217
|
+
assetIds?: string[];
|
|
218
|
+
/** At most 70 characters when new or changed; null or blank clears it. */
|
|
219
|
+
brand?: string | null;
|
|
220
|
+
condition?: ProductCondition;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* One variant in a {@link ProductsModule.save}; a PATCH. A price (`price` or `prices`) travels
|
|
224
|
+
* with `priceBasis`, the store's basis, exactly as for `catalog.variants.update`.
|
|
225
|
+
*/
|
|
226
|
+
export interface SaveProductVariantInput extends AvailabilityInput<VariantAvailabilityState> {
|
|
227
|
+
id: string;
|
|
228
|
+
/** In the save's `languageCode`; trimmed. */
|
|
229
|
+
name?: string;
|
|
230
|
+
sku?: string;
|
|
231
|
+
enabled?: boolean;
|
|
232
|
+
/** Integer minor units of the store's default currency. */
|
|
233
|
+
price?: number;
|
|
234
|
+
/**
|
|
235
|
+
* The price in each named currency. A currency left out keeps its stored price (the list
|
|
236
|
+
* removes nothing), and one equal to what is stored is no change. Its default-currency entry
|
|
237
|
+
* must equal `price` when both are sent.
|
|
238
|
+
*/
|
|
239
|
+
prices?: VariantPriceInput[];
|
|
240
|
+
priceBasis?: PriceBasis;
|
|
241
|
+
taxCategoryId?: string;
|
|
242
|
+
/** Compared as a set. */
|
|
243
|
+
facetValueIds?: string[];
|
|
244
|
+
/** Null: no featured image. */
|
|
245
|
+
featuredAssetId?: string | null;
|
|
246
|
+
assetIds?: string[];
|
|
247
|
+
minOrderQuantity?: number | null;
|
|
248
|
+
salesUnit?: number | null;
|
|
249
|
+
/** Integer minor units of the store's default currency. */
|
|
250
|
+
cost?: number | null;
|
|
251
|
+
packageWeightGrams?: number | null;
|
|
252
|
+
packageLengthCm?: number | null;
|
|
253
|
+
packageWidthCm?: number | null;
|
|
254
|
+
packageHeightCm?: number | null;
|
|
255
|
+
/** 1 to 10,000; null: the store's items per parcel. */
|
|
256
|
+
parcelCapacity?: number | null;
|
|
257
|
+
/** Null: `shared`. */
|
|
258
|
+
parcelPacking?: ParcelPacking | null;
|
|
259
|
+
/** Null: `inherit`. */
|
|
260
|
+
backorderPolicy?: VariantBackorderPolicy | null;
|
|
261
|
+
backorderLimit?: number | null;
|
|
262
|
+
/** 8, 12, 13 or 14 digits when new or changed; null or blank clears it. */
|
|
263
|
+
gtin?: string | null;
|
|
264
|
+
mpn?: string | null;
|
|
265
|
+
}
|
|
266
|
+
/** One property value in a {@link ProductsModule.save}. */
|
|
267
|
+
export interface SaveProductPropertyValueInput {
|
|
268
|
+
propertyId: string;
|
|
269
|
+
/** A translatable property's language; the save's `languageCode` when left out. */
|
|
270
|
+
languageCode?: LanguageCode;
|
|
271
|
+
/** Null, `''` or `[]` clears it; a content-item or product property takes a list of ids. */
|
|
272
|
+
value: unknown;
|
|
273
|
+
}
|
|
274
|
+
/** A product page's whole change, for {@link ProductsModule.save}. */
|
|
275
|
+
export interface SaveProductInput {
|
|
276
|
+
id: string;
|
|
277
|
+
/** The editing language: names, slugs, descriptions and text values are written in it. */
|
|
278
|
+
languageCode: LanguageCode;
|
|
279
|
+
product?: SaveProductFieldsInput;
|
|
280
|
+
variants?: SaveProductVariantInput[];
|
|
281
|
+
/** The collections the product is in by hand: the whole wanted list. */
|
|
282
|
+
collectionIds?: string[];
|
|
283
|
+
/**
|
|
284
|
+
* The collections the caller last read the product in: only the difference is applied, so a
|
|
285
|
+
* change someone else made meanwhile stands (as `setCollections`' `from`). Needs `collectionIds`.
|
|
286
|
+
*/
|
|
287
|
+
fromCollectionIds?: string[];
|
|
288
|
+
/** An absent property keeps its value. */
|
|
289
|
+
propertyValues?: SaveProductPropertyValueInput[];
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Something a save did not do although everything it wrote is saved. A string on the wire: a
|
|
293
|
+
* newer engine may add a code.
|
|
294
|
+
* - `CONTENT_LABELS_NOT_SYNCED`: the content system did not answer, so the filter values of the
|
|
295
|
+
* properties in `propertyIds` were saved without their titles; run
|
|
296
|
+
* `catalog.syncContentFacets(propertyId)` on them once it is back.
|
|
297
|
+
*/
|
|
298
|
+
export interface SaveProductWarning {
|
|
299
|
+
code: 'CONTENT_LABELS_NOT_SYNCED' | (string & {});
|
|
300
|
+
message: string;
|
|
301
|
+
propertyIds: string[];
|
|
302
|
+
}
|
|
303
|
+
export interface SaveProductResult {
|
|
304
|
+
/** The product as saved. */
|
|
305
|
+
product: Product;
|
|
306
|
+
/** What the collection step did; null when the save changed no collection. */
|
|
307
|
+
collections: ProductCollectionsResult | null;
|
|
308
|
+
warnings: SaveProductWarning[];
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Product-level catalog writes. Reading needs `ReadCatalog` (or `ReadProduct`),
|
|
312
|
+
* creating `CreateCatalog`, updating `UpdateCatalog`, deleting `DeleteCatalog`.
|
|
313
|
+
*
|
|
314
|
+
* While an app or API token of the store owns a field group (`admin.tenant.fieldGroupOwners()`),
|
|
315
|
+
* an update that would change its Product details, or a delete while
|
|
316
|
+
* any group of the product or its variants is owned, by anyone else is refused `FIELD_GROUP_LOCKED`
|
|
317
|
+
* (`BusinessRuleError`, 422) and nothing is written; `error.details` names each refused field
|
|
318
|
+
* (`field` is a JSON pointer into the call, e.g. `/input/0/price`). A value equal to the stored
|
|
319
|
+
* one passes and is left out of the write. See the README, "Field groups: what an owned group
|
|
320
|
+
* refuses".
|
|
321
|
+
*/
|
|
322
|
+
export interface ProductsModule {
|
|
323
|
+
list(options?: ProductListOptions): Promise<Page<Product>>;
|
|
324
|
+
/** Null for an id this store does not have — the same answer another tenant's product gets. */
|
|
325
|
+
get(id: string, options?: Call): Promise<Product | null>;
|
|
326
|
+
create(input: CreateProductInput, options?: Call): Promise<Product>;
|
|
327
|
+
update(input: UpdateProductInput, options?: Call): Promise<Product>;
|
|
328
|
+
/**
|
|
329
|
+
* Soft-deletes the product and its variants. `PRODUCT_NOT_DELETED`
|
|
330
|
+
* (`ConflictError`) carries the engine's own reason when it refuses.
|
|
331
|
+
*/
|
|
332
|
+
delete(id: string, options?: Call): Promise<void>;
|
|
333
|
+
/**
|
|
334
|
+
* Duplicate a product (the platform's `cloneProduct`): variants, assets,
|
|
335
|
+
* facet values, prices, option groups, custom fields, properties, documents,
|
|
336
|
+
* visibility, SEO metadata, manual recommendations and manual collection
|
|
337
|
+
* membership. The copy is created DISABLED, named "<Name> (copy)", with SKU
|
|
338
|
+
* "<sku>-copy" (or the next free "<sku>-copy-N") and no stock. Answers the
|
|
339
|
+
* new product's id.
|
|
340
|
+
*
|
|
341
|
+
* Takes no input: the engine's mutation has none.
|
|
342
|
+
*/
|
|
343
|
+
clone(id: string, options?: Call): Promise<string>;
|
|
344
|
+
/** Attach an option group; its options then name the product's variants. */
|
|
345
|
+
addOptionGroup(productId: string, optionGroupId: string, options?: Call): Promise<Product>;
|
|
346
|
+
/**
|
|
347
|
+
* Detach an option group. Refused with `PRODUCT_OPTION_IN_USE_ERROR`
|
|
348
|
+
* (`BusinessRuleError`) — "Cannot remove ProductOptionGroup "{code}" as it is
|
|
349
|
+
* used by N ProductVariants. Use the `force` argument to remove it anyway" —
|
|
350
|
+
* unless `force` is set.
|
|
351
|
+
*/
|
|
352
|
+
removeOptionGroup(productId: string, optionGroupId: string, options?: Call & {
|
|
353
|
+
force?: boolean;
|
|
354
|
+
}): Promise<Product>;
|
|
355
|
+
/**
|
|
356
|
+
* Stop offering products the store's organization shares with it, in the ACTIVE store only
|
|
357
|
+
* (multi-region decision 58): they leave its storefront and its carts, while its orders,
|
|
358
|
+
* returns and invoices keep them; `excludedFromStore` reads true. Excluding an excluded
|
|
359
|
+
* product changes nothing. All or nothing, audited. Needs `UpdateCatalog` or `UpdateProduct`.
|
|
360
|
+
* Answers the products as the store sees them; no ids answers none, without a request. An
|
|
361
|
+
* Admin API mutation: an idempotency key deduplicates nothing.
|
|
362
|
+
*
|
|
363
|
+
* Refusals (nothing is written), GraphQL errors mapped by `core`:
|
|
364
|
+
* - `STORE_EXCLUSION_LOCAL_PRODUCT` → `BusinessRuleError` (422): a product of the store's own
|
|
365
|
+
* (or the store is in no organization), which it disables or deletes instead. The message
|
|
366
|
+
* says how many of the ids it was.
|
|
367
|
+
* - `STORE_EXCLUSION_INPUT_INVALID` → `ValidationError` (400): more than
|
|
368
|
+
* {@link MAX_STORE_EXCLUSION_PRODUCTS} distinct ids; refused before sending too.
|
|
369
|
+
* - `ORGANIZATION_WORKSPACE_NOT_A_STORE` → `BusinessRuleError` (422): called in an
|
|
370
|
+
* organization's workspace, which sells nothing.
|
|
371
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): an id this store does not hold.
|
|
372
|
+
*/
|
|
373
|
+
exclude(productIds: string[], options?: Call): Promise<Product[]>;
|
|
374
|
+
/**
|
|
375
|
+
* Offer excluded products in the ACTIVE store again. A product it holds and does not exclude
|
|
376
|
+
* is left as it is. Same permissions, answer and refusals as {@link exclude}, except
|
|
377
|
+
* `STORE_EXCLUSION_LOCAL_PRODUCT`; `ENTITY_NOT_FOUND` is a product the store neither holds
|
|
378
|
+
* nor excludes.
|
|
379
|
+
*/
|
|
380
|
+
include(productIds: string[], options?: Call): Promise<Product[]>;
|
|
381
|
+
/**
|
|
382
|
+
* The organization's Availability toggle (spec §7.2.3, decision 79), called with the
|
|
383
|
+
* organization's WORKSPACE as the tenant: offer workspace products in member stores, or stop
|
|
384
|
+
* offering them there. Off, under the `all` assortment: excluded from the store (its orders
|
|
385
|
+
* keep the product). Off, under `selected`: unlinked from a store that never sold or quoted
|
|
386
|
+
* it, else excluded. On: included again, or assigned to a store that lacks it. All or
|
|
387
|
+
* nothing, audited; answers what changed, sorted by store and product, and nothing for what
|
|
388
|
+
* already was so. Needs `ManageOrganization` (an organization admin) or SuperAdmin, and
|
|
389
|
+
* `UpdateCatalog` in each store named.
|
|
390
|
+
*
|
|
391
|
+
* Refusals (nothing is written), GraphQL errors mapped by `core`:
|
|
392
|
+
* - `ORGANIZATION_AVAILABILITY_INPUT_INVALID` → `ValidationError` (400): no products or no
|
|
393
|
+
* stores, more than {@link MAX_AVAILABILITY_PRODUCTS} distinct products or
|
|
394
|
+
* {@link MAX_AVAILABILITY_STORES} distinct stores, or `available` not a boolean; refused
|
|
395
|
+
* before sending too.
|
|
396
|
+
* - `ORGANIZATION_ACCESS_DENIED` → `PermissionDeniedError` (403): the tenant is not an
|
|
397
|
+
* organization's workspace.
|
|
398
|
+
* - `CHANNEL_ACCESS_DENIED` → `PermissionDeniedError` (403): a store the caller may not
|
|
399
|
+
* change the catalogue of.
|
|
400
|
+
* - `ORGANIZATION_CATALOG_NOT_SHARED` → `BusinessRuleError` (422): the organization does not
|
|
401
|
+
* share its products (`catalog` sharing is off).
|
|
402
|
+
* - `ORGANIZATION_PRICE_MISSING` → `BusinessRuleError` (422): a store would be offered a
|
|
403
|
+
* variant it has no price for in a currency it sells.
|
|
404
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): a product that is not the workspace's, or a
|
|
405
|
+
* store that is not a member.
|
|
406
|
+
*/
|
|
407
|
+
setAvailabilityInStores(input: SetAvailabilityInStoresInput, options?: Call): Promise<OrganizationProductAvailabilityChange[]>;
|
|
408
|
+
/**
|
|
409
|
+
* The read behind the organization's Availability toggle (decision 86), called with the
|
|
410
|
+
* organization's WORKSPACE as the tenant: whether each named member store offers, excludes or
|
|
411
|
+
* does not hold each named workspace product, one row per product and store, products first,
|
|
412
|
+
* in the order named (each distinct id once). Each row names the store's own local copy of the
|
|
413
|
+
* product, if it has one. It answers whether or not the organization shares its products.
|
|
414
|
+
* Needs `ManageOrganization` (an organization admin) or SuperAdmin, and `ReadCatalog`,
|
|
415
|
+
* `ReadProduct` or `UpdateCatalog` in each store named. Platform releases before this method
|
|
416
|
+
* do not have the query and refuse it as `ValidationError` `GRAPHQL_VALIDATION_FAILED` (400),
|
|
417
|
+
* told apart from a refused input by its code.
|
|
418
|
+
*
|
|
419
|
+
* Refusals, GraphQL errors mapped by `core`:
|
|
420
|
+
* - `ORGANIZATION_AVAILABILITY_INPUT_INVALID` → `ValidationError` (400): no products or no
|
|
421
|
+
* stores, or more than {@link MAX_AVAILABILITY_PRODUCTS} distinct products or
|
|
422
|
+
* {@link MAX_AVAILABILITY_STORES} distinct stores; refused before sending too.
|
|
423
|
+
* - `ORGANIZATION_ACCESS_DENIED` → `PermissionDeniedError` (403): the tenant is not an
|
|
424
|
+
* organization's workspace.
|
|
425
|
+
* - `CHANNEL_ACCESS_DENIED` → `PermissionDeniedError` (403): a store the caller may not read
|
|
426
|
+
* the catalogue of.
|
|
427
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): a product that is not the workspace's, or a
|
|
428
|
+
* store that is not a member.
|
|
429
|
+
*/
|
|
430
|
+
availabilityInStores(input: AvailabilityInStoresInput, options?: Call): Promise<OrganizationProductStoreAvailability[]>;
|
|
431
|
+
/**
|
|
432
|
+
* Make the ACTIVE member store's own copy of a product its organization shares with it, and
|
|
433
|
+
* stop offering the shared one, in one step (a local copy, or detach; spec §7.2.8). The copy
|
|
434
|
+
* is a clone created DISABLED (see {@link clone}), priced with the store's current prices,
|
|
435
|
+
* carrying the store's price-list entries and joined to the store's own collections only. Its
|
|
436
|
+
* product and variant rows, names, prices and properties are the store's own and no longer
|
|
437
|
+
* follow the organization's changes; the workspace's option groups, assets and facet values it
|
|
438
|
+
* still uses do (a workspace rename of an option shows on the copy, and the store cannot
|
|
439
|
+
* change them: `MANAGED_BY_ORGANIZATION`). Its variants' SKUs end in `-<store code>`
|
|
440
|
+
* (first free) unless `skus` names them, which are taken as given or refused. The shared
|
|
441
|
+
* product is excluded from the store when the store sold or quoted it, and always under the
|
|
442
|
+
* organization's `all` assortment; otherwise it is removed from the store (`original`).
|
|
443
|
+
*
|
|
444
|
+
* One transaction, audited. A repeat (a double submit, a retry) never makes a second copy: it
|
|
445
|
+
* is refused `LOCAL_COPY_ALREADY_EXISTS`, whether the first call excluded the original or
|
|
446
|
+
* unlinked it (a platform release older than that answers `ENTITY_NOT_FOUND` after an unlink,
|
|
447
|
+
* the store no longer holding the product). Needs `CreateCatalog` (or `CreateProduct`) AND
|
|
448
|
+
* `UpdateCatalog` in the store.
|
|
449
|
+
*
|
|
450
|
+
* Refusals (nothing is written), GraphQL errors mapped by `core`:
|
|
451
|
+
* - `LOCAL_COPY_PRODUCT_NOT_SHARED` → `BusinessRuleError` (422): the store's own product, or
|
|
452
|
+
* the store is in no organization; clone it instead.
|
|
453
|
+
* - `LOCAL_COPY_ALREADY_EXISTS` → `ConflictError` (409): the store already has a live copy.
|
|
454
|
+
* - `LOCAL_COPY_SKU_CONFLICT` → `ConflictError` (409): a SKU named in `skus` is another
|
|
455
|
+
* product's in the store. `error.details` names each one, its `field` the SKU's place in
|
|
456
|
+
* `skus` (`/skus/<index>/sku`), so a form can mark the inputs (an older platform release
|
|
457
|
+
* sends no details; its message names a single SKU and only counts several).
|
|
458
|
+
* - `LOCAL_COPY_INPUT_INVALID` → `ValidationError` (400): `skus` names a variant the store
|
|
459
|
+
* does not hold on that product, names one twice, repeats a SKU, or has a blank or overlong
|
|
460
|
+
* one.
|
|
461
|
+
* - `ORGANIZATION_WORKSPACE_NOT_A_STORE` → `BusinessRuleError` (422): called in the workspace.
|
|
462
|
+
* - `FORBIDDEN` → `PermissionDeniedError` (403): a permission above is missing.
|
|
463
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): a product this store does not hold.
|
|
464
|
+
*/
|
|
465
|
+
makeLocalCopy(productId: string, options?: Call & {
|
|
466
|
+
skus?: readonly LocalCopySkuInput[];
|
|
467
|
+
}): Promise<LocalCopyResult>;
|
|
468
|
+
/**
|
|
469
|
+
* Set the collections a product is in by hand (headless spec §7, part of `products.save`).
|
|
470
|
+
* Only MANUAL membership is written: the product is added to the hand-picked list (the
|
|
471
|
+
* `product-id-filter`, see `catalog.collections`) of each collection in `collectionIds` it is not
|
|
472
|
+
* in yet, and taken off the hand-picked lists of each collection it should leave. A collection
|
|
473
|
+
* the product is in only through its other filters (facet values, names) is never rewritten:
|
|
474
|
+
* those filters are the collection's, so it is reported in `notRemoved`
|
|
475
|
+
* (`MEMBER_BY_FILTER`) and stays.
|
|
476
|
+
*
|
|
477
|
+
* One transaction, and every collection it writes is row-locked first: two calls touching one
|
|
478
|
+
* collection (two products saved into it at once, a clone) both keep their change, which a
|
|
479
|
+
* client read-modify-write of the collection's filters (`catalog.collections.update`) cannot
|
|
480
|
+
* promise. All or nothing. Membership is DERIVED: each written collection re-runs its
|
|
481
|
+
* membership job, so the product shows in (or out of) it shortly after the call returns, not
|
|
482
|
+
* during it.
|
|
483
|
+
*
|
|
484
|
+
* `from`: where the product was, as far as this call is concerned. Given, only the difference
|
|
485
|
+
* between `from` and `collectionIds` is applied, and every collection in neither list (or in
|
|
486
|
+
* both) is left as it is. So a change needs no read: `setCollections(id, [x], { from: [] })`
|
|
487
|
+
* puts the product in `x` and touches nothing else, and `setCollections(id, [], { from: [x] })`
|
|
488
|
+
* takes it out of `x` only. A screen that shows the product's collections passes the ones it
|
|
489
|
+
* loaded, so a collection someone else changed since then keeps that change. Without `from`,
|
|
490
|
+
* `collectionIds` is the WHOLE new hand-picked membership, compared with the product's
|
|
491
|
+
* membership now: every other collection that lists the product by hand loses it. A repeat of
|
|
492
|
+
* a call that went through writes nothing: each collection answers `unchanged`, except one the
|
|
493
|
+
* product stays in through other filters, which answers `notRemoved` again (while those filters
|
|
494
|
+
* hold it, and, for a collection with such filters, until its membership job has run). So
|
|
495
|
+
* `notRemoved` on a repeat does not mean the first call failed.
|
|
496
|
+
*
|
|
497
|
+
* Needs `UpdateCatalog` or `UpdateCollection`. Platform releases before this method do not
|
|
498
|
+
* have the mutation and refuse it as `ValidationError` `GRAPHQL_VALIDATION_FAILED` (400).
|
|
499
|
+
*
|
|
500
|
+
* Refusals (nothing is written), GraphQL errors mapped by `core`:
|
|
501
|
+
* - `PRODUCT_COLLECTIONS_INPUT_INVALID` → `ValidationError` (400): a list names a collection
|
|
502
|
+
* twice, or more than {@link MAX_PRODUCT_COLLECTION_IDS}; refused before sending too.
|
|
503
|
+
* `error.details` names each entry (`/collectionIds/<i>`, `/fromCollectionIds/<i>`).
|
|
504
|
+
* - `PRODUCT_COLLECTION_FILTER_INVALID` → `ValidationError` (400): a collection's hand-picked
|
|
505
|
+
* list cannot be read as product ids, so whether it names the product cannot be told. The
|
|
506
|
+
* message names the collection; save its product list again in the collection editor.
|
|
507
|
+
* - `SHARED_COLLECTION_NOT_ALLOWED` → `PermissionDeniedError` (403): a collection to write is
|
|
508
|
+
* also another store's (or one below it is), and you cannot change that store's catalogue.
|
|
509
|
+
* - `MANAGED_BY_ORGANIZATION` → `BusinessRuleError` (422): a collection to write is the store's
|
|
510
|
+
* organization's; change it in the organization's workspace.
|
|
511
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): a product or collection this store does not
|
|
512
|
+
* hold (or a deleted product).
|
|
513
|
+
* - `FORBIDDEN` → `PermissionDeniedError` (403): neither permission above.
|
|
514
|
+
*/
|
|
515
|
+
setCollections(productId: string, collectionIds: readonly string[], options?: Call & {
|
|
516
|
+
from?: readonly string[];
|
|
517
|
+
}): Promise<ProductCollectionsResult>;
|
|
518
|
+
/**
|
|
519
|
+
* Save a product page's whole change in ONE engine transaction: all of it, or none of it
|
|
520
|
+
* (headless spec §7 `products.save`). In this order: the variants, the hand-picked collections
|
|
521
|
+
* (as {@link setCollections}), the property values (and the filter-label sync of each
|
|
522
|
+
* filterable product property), the product. Every step's check runs before the first write.
|
|
523
|
+
*
|
|
524
|
+
* A PATCH with an echo rule: only what the input names is compared, and only what differs from
|
|
525
|
+
* what the store holds is written. A head may send the whole form: an unchanged value is not a
|
|
526
|
+
* write, so it never records a change of its field group, and a product the store's
|
|
527
|
+
* organization shares is not refused for a shared field sent back unchanged.
|
|
528
|
+
*
|
|
529
|
+
* Labels of content-item values are read from the content system before the transaction. When
|
|
530
|
+
* it does not answer, the save still goes through and `warnings` names the properties whose
|
|
531
|
+
* filter values were saved without their titles.
|
|
532
|
+
*
|
|
533
|
+
* Needs `UpdateCatalog` or `UpdateProduct`, plus `UpdateCatalog` or `UpdateCollection` when it
|
|
534
|
+
* changes collections and `UpdateCatalog` when it changes property values. `idempotencyKey`: a
|
|
535
|
+
* repeat answers the first call's result. Platform releases before this method do not have the
|
|
536
|
+
* mutation and refuse it as `ValidationError` `GRAPHQL_VALIDATION_FAILED` (400): deploy the
|
|
537
|
+
* engine first.
|
|
538
|
+
*
|
|
539
|
+
* Refusals (nothing is written), GraphQL errors mapped by `core`:
|
|
540
|
+
* - `PRICE_BASIS_REQUIRED` / `PRICE_BASIS_MISMATCH` / `INVALID_PRICE` → `ValidationError`
|
|
541
|
+
* (400): a variant price without the store's basis; refused before sending.
|
|
542
|
+
* - `PRODUCT_SAVE_INPUT_INVALID` → `ValidationError` (400): the input names nothing, names a
|
|
543
|
+
* variant, currency or property value twice, uses a language the store does not offer, gives
|
|
544
|
+
* a value outside its field's range, or `price` and the default-currency entry of `prices`
|
|
545
|
+
* differ. `error.details` names each (`field` is a pointer into the call).
|
|
546
|
+
* - `PRODUCT_COLLECTIONS_INPUT_INVALID` → `ValidationError` (400): a collection list names one
|
|
547
|
+
* twice, or more than {@link MAX_PRODUCT_COLLECTION_IDS}; refused before sending too.
|
|
548
|
+
* - `FEED_IDENTIFIER_INVALID` → `ValidationError` (400): a new or changed brand over 70
|
|
549
|
+
* characters, or a GTIN of another shape.
|
|
550
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): a product, variant (of another product
|
|
551
|
+
* included), collection or property this store does not hold.
|
|
552
|
+
* - `FORBIDDEN` → `PermissionDeniedError` (403): a step's permission above is missing.
|
|
553
|
+
* - `SHARED_PRODUCT_NOT_ALLOWED`, `SHARED_PRODUCT_VARIANT_NOT_ALLOWED`,
|
|
554
|
+
* `SHARED_COLLECTION_NOT_ALLOWED` → `PermissionDeniedError` (403): a row another store also
|
|
555
|
+
* holds, which you cannot change there.
|
|
556
|
+
* - `MANAGED_BY_ORGANIZATION` → `BusinessRuleError` (422): a CHANGED field of a product, variant,
|
|
557
|
+
* collection or property value the store's organization holds. The store's own price, its own
|
|
558
|
+
* facet values, its own collections and its own property values pass.
|
|
559
|
+
* - `FIELD_GROUP_LOCKED` → `BusinessRuleError` (422): a field group an app or API token owns.
|
|
560
|
+
* - `PRODUCT_COLLECTION_FILTER_INVALID` → `ValidationError` (400): a collection whose
|
|
561
|
+
* hand-picked list cannot be read.
|
|
562
|
+
* - `EXTERNAL_LINE_CARRIER_PROTECTED` → `BusinessRuleError` (422): the platform's carrier.
|
|
563
|
+
* - `INVALID_TAX_CATEGORY_FOR_CLASS` → `ValidationError` (400).
|
|
564
|
+
*/
|
|
565
|
+
save(input: SaveProductInput, options?: Call): Promise<SaveProductResult>;
|
|
566
|
+
/**
|
|
567
|
+
* Enable, disable, delete or clone up to `MAX_BULK_PRODUCTS` (50) products of the store in ONE
|
|
568
|
+
* call (headless spec §7 `products.bulkClone`; §6.11).
|
|
569
|
+
*
|
|
570
|
+
* **The run is a job.** The call answers a receipt (`runId`) as soon as the run is queued;
|
|
571
|
+
* `handle.wait()` polls it until it ends and resolves with the run, whatever the ending.
|
|
572
|
+
* `bulkRun(runId)` reads it again later, from any process. Each product's outcome is in
|
|
573
|
+
* `run.items`, in the order the ids were named: `OK` (with `newId`, the copy, for `CLONE`), or
|
|
574
|
+
* `FAILED` with the code the single door would have raised.
|
|
575
|
+
*
|
|
576
|
+
* **Each product succeeds or fails alone.** Every product goes through its own door
|
|
577
|
+
* (`update` with `enabled`, `delete`, `clone`) in a transaction of its own, so a refused product
|
|
578
|
+
* leaves the others done, and a `SUCCEEDED` run can hold `FAILED` items: read them. A product of
|
|
579
|
+
* another store answers `ENTITY_NOT_FOUND` on its item; a product another store also holds
|
|
580
|
+
* answers `SHARED_PRODUCT_NOT_ALLOWED` unless you may change that store's catalogue too; a
|
|
581
|
+
* product the store's organization holds answers `MANAGED_BY_ORGANIZATION` for every caller,
|
|
582
|
+
* SuperAdmin included; a group an app or API token owns answers `FIELD_GROUP_LOCKED` (a delete
|
|
583
|
+
* takes every group of the product; `enabled` is in no group); the external-line carrier
|
|
584
|
+
* answers `EXTERNAL_LINE_CARRIER_PROTECTED`; core declining a delete answers
|
|
585
|
+
* `PRODUCT_NOT_DELETED`.
|
|
586
|
+
*
|
|
587
|
+
* **Idempotency.** `options.idempotencyKey` (minted when omitted): the same key with the same
|
|
588
|
+
* action and ids answers the SAME run, so a resubmit never clones twice; the same key with
|
|
589
|
+
* another selection is refused `IDEMPOTENCY_CONFLICT` (409 `ConflictError`). Each product is
|
|
590
|
+
* keyed within the run as well, so a run the platform has to process again (a worker restart)
|
|
591
|
+
* answers each product it already did from that record.
|
|
592
|
+
*
|
|
593
|
+
* **No dry run.** The refusals that matter are the doors' own, made under the write (the
|
|
594
|
+
* field-group lock, the shared-product rule), so a rehearsal could answer "ok" for a product the
|
|
595
|
+
* real run refuses. Each product's outcome is reported when it runs instead.
|
|
596
|
+
*
|
|
597
|
+
* Needs the single door's permission for the action: `UpdateCatalog` or `UpdateProduct`
|
|
598
|
+
* (ENABLE, DISABLE), `DeleteCatalog` or `DeleteProduct` (DELETE), `CreateCatalog` or
|
|
599
|
+
* `CreateProduct` (CLONE). Reading the run needs `ReadCatalog` or `ReadProduct`. Search is
|
|
600
|
+
* reindexed for every product written.
|
|
601
|
+
*
|
|
602
|
+
* Refusals of the call itself (nothing is queued), GraphQL errors mapped by `core`:
|
|
603
|
+
* - `BULK_ACTION_INPUT_INVALID` → `ValidationError` (400): no products, more than
|
|
604
|
+
* `MAX_BULK_PRODUCTS`, a product named twice, an unknown action; refused before sending
|
|
605
|
+
* too. `error.details` names each entry (`/input/productIds/<index>`).
|
|
606
|
+
* - `BULK_ACTION_NOT_ALLOWED` → `PermissionDeniedError` (403): the action's permission is missing.
|
|
607
|
+
* - `IDEMPOTENCY_CONFLICT` → `ConflictError` (409): the key was used for another selection.
|
|
608
|
+
* - `ENTITY_NOT_FOUND` → `NotFoundError` (404): an id that is not an id at all.
|
|
609
|
+
*
|
|
610
|
+
* Platform releases before this method do not have the mutation and refuse it as
|
|
611
|
+
* `ValidationError` `GRAPHQL_VALIDATION_FAILED` (400).
|
|
612
|
+
*/
|
|
613
|
+
bulk(input: ProductBulkInput, options?: Call): Promise<JobHandle<ProductBulkRun>>;
|
|
614
|
+
/**
|
|
615
|
+
* One read of a bulk product run, by the `runId` `bulk()` answered. A run of another store, or
|
|
616
|
+
* one that does not exist, is `BULK_ACTION_RUN_NOT_FOUND` (`NotFoundError`, 404).
|
|
617
|
+
*/
|
|
618
|
+
bulkRun(runId: string, options?: Call): Promise<ProductBulkRun>;
|
|
619
|
+
}
|
|
620
|
+
export declare const PRODUCT_FIELDS = "\n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n";
|
|
621
|
+
export declare const PRODUCTS_QUERY = "\n query CatalogProducts($options: ProductListOptions) {\n products(options: $options) {\n items { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n totalItems\n }\n }\n";
|
|
622
|
+
export declare const PRODUCT_QUERY = "\n query CatalogProduct($id: ID!) {\n product(id: $id) { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n }\n";
|
|
623
|
+
export declare const CREATE_PRODUCT_MUTATION = "\n mutation CatalogCreateProduct($input: CreateProductInput!) {\n createProduct(input: $input) { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n }\n";
|
|
624
|
+
export declare const UPDATE_PRODUCT_MUTATION = "\n mutation CatalogUpdateProduct($input: UpdateProductInput!) {\n updateProduct(input: $input) { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n }\n";
|
|
625
|
+
export declare const DELETE_PRODUCT_MUTATION = "\n mutation CatalogDeleteProduct($id: ID!) {\n deleteProduct(id: $id) { \n result\n message\n }\n }\n";
|
|
626
|
+
export declare const CLONE_PRODUCT_MUTATION = "\n mutation CatalogCloneProduct($id: ID!) {\n cloneProduct(id: $id)\n }\n";
|
|
627
|
+
export declare const ADD_OPTION_GROUP_MUTATION = "\n mutation CatalogAddOptionGroup($productId: ID!, $optionGroupId: ID!) {\n addOptionGroupToProduct(productId: $productId, optionGroupId: $optionGroupId) { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n }\n";
|
|
628
|
+
export declare const REMOVE_OPTION_GROUP_MUTATION = "\n mutation CatalogRemoveOptionGroup($productId: ID!, $optionGroupId: ID!, $force: Boolean) {\n removeOptionGroupFromProduct(productId: $productId, optionGroupId: $optionGroupId, force: $force) {\n ... on Product { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n ... on ErrorResult {\n errorCode\n message\n }\n }\n }\n";
|
|
629
|
+
export declare const EXCLUDE_PRODUCTS_FROM_STORE_MUTATION = "\n mutation CatalogExcludeProductsFromStore($productIds: [ID!]!) {\n excludeProductsFromStore(productIds: $productIds) { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n }\n";
|
|
630
|
+
export declare const INCLUDE_PRODUCTS_IN_STORE_MUTATION = "\n mutation CatalogIncludeProductsInStore($productIds: [ID!]!) {\n includeProductsInStore(productIds: $productIds) { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n }\n";
|
|
631
|
+
export declare const SET_ORGANIZATION_PRODUCT_AVAILABILITY_MUTATION = "\n mutation CatalogSetOrganizationProductAvailability(\n $productIds: [ID!]!\n $channelIds: [ID!]!\n $available: Boolean!\n ) {\n setOrganizationProductAvailability(\n productIds: $productIds\n channelIds: $channelIds\n available: $available\n ) {\n productId\n channelId\n action\n }\n }\n";
|
|
632
|
+
export declare const ORGANIZATION_PRODUCT_AVAILABILITY_QUERY = "\n query CatalogOrganizationProductAvailability($productIds: [ID!]!, $channelIds: [ID!]!) {\n organizationProductAvailability(productIds: $productIds, channelIds: $channelIds) {\n productId\n channelId\n state\n localCopyId\n }\n }\n";
|
|
633
|
+
export declare const MAKE_LOCAL_COPY_MUTATION = "\n mutation CatalogMakeLocalCopy($productId: ID!, $skus: [LocalCopySkuInput!]) {\n makeLocalCopy(productId: $productId, skus: $skus) {\n product { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n originalProductId\n original\n droppedOrganizationPropertyCount\n }\n }\n";
|
|
634
|
+
export declare const SET_PRODUCT_COLLECTIONS_MUTATION = "\n mutation CatalogSetProductCollections(\n $productId: ID!\n $collectionIds: [ID!]!\n $fromCollectionIds: [ID!]\n ) {\n setProductCollections(\n productId: $productId\n collectionIds: $collectionIds\n fromCollectionIds: $fromCollectionIds\n ) {\n added\n removed\n unchanged\n notRemoved {\n collectionId\n reason\n }\n }\n }\n";
|
|
635
|
+
export declare const SAVE_PRODUCT_MUTATION = "\n mutation CatalogSaveProduct($input: SaveProductInput!, $idempotencyKey: String) {\n saveProduct(input: $input, idempotencyKey: $idempotencyKey) {\n product { \n id\n \n catalogueOwnership {\n state\n organizationName\n editableHere\n }\n\n createdAt\n updatedAt\n languageCode\n name\n slug\n description\n enabled\n featuredAsset { \n id\n name\n preview\n source\n }\n assets { \n id\n name\n preview\n source\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n optionGroups {\n id\n code\n name\n options {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n slug\n description\n }\n excludedFromStore\n variantList(options: { take: 1 }) {\n totalItems\n }\n customFields {\n availabilityState\n availableFrom\n preorderLimit\n }\n }\n collections {\n added\n removed\n unchanged\n notRemoved {\n collectionId\n reason\n }\n }\n warnings {\n code\n message\n propertyIds\n }\n }\n }\n";
|
|
636
|
+
/** The product as the Admin API answers it, before `toProduct`. */
|
|
637
|
+
export interface WireProduct extends Omit<Product, keyof Availability<string> | 'variantCount'> {
|
|
638
|
+
variantList: {
|
|
639
|
+
totalItems: number;
|
|
640
|
+
};
|
|
641
|
+
customFields: Partial<Availability<ProductAvailabilityState>> | null;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Lift the availability custom fields to first-class fields. A server older
|
|
645
|
+
* than the pre-order engine has no such fields and would refuse the document
|
|
646
|
+
* outright, so the defaults below only cover a NULL value, never an absent one.
|
|
647
|
+
*/
|
|
648
|
+
export declare function toProduct(wire: WireProduct): Product;
|
|
649
|
+
export declare function productFilter(filter: ProductListFilter | undefined): Record<string, unknown>;
|
|
650
|
+
export declare function createProductsModule(transport: Transport): ProductsModule;
|