@endora-commerce/contracts 0.100.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/LICENSE +21 -0
- package/README.md +34 -0
- package/dist/actor.d.ts +79 -0
- package/dist/actor.d.ts.map +1 -0
- package/dist/actor.js +41 -0
- package/dist/actor.js.map +1 -0
- package/dist/addresses.d.ts +134 -0
- package/dist/addresses.d.ts.map +1 -0
- package/dist/addresses.js +16 -0
- package/dist/addresses.js.map +1 -0
- package/dist/admin-actions.d.ts +367 -0
- package/dist/admin-actions.d.ts.map +1 -0
- package/dist/admin-actions.js +287 -0
- package/dist/admin-actions.js.map +1 -0
- package/dist/admin-contributions.d.ts +518 -0
- package/dist/admin-contributions.d.ts.map +1 -0
- package/dist/admin-contributions.js +495 -0
- package/dist/admin-contributions.js.map +1 -0
- package/dist/admin-i18n.d.ts +135 -0
- package/dist/admin-i18n.d.ts.map +1 -0
- package/dist/admin-i18n.js +72 -0
- package/dist/admin-i18n.js.map +1 -0
- package/dist/admin-notifications.d.ts +55 -0
- package/dist/admin-notifications.d.ts.map +1 -0
- package/dist/admin-notifications.js +16 -0
- package/dist/admin-notifications.js.map +1 -0
- package/dist/admin-roles.d.ts +125 -0
- package/dist/admin-roles.d.ts.map +1 -0
- package/dist/admin-roles.js +2 -0
- package/dist/admin-roles.js.map +1 -0
- package/dist/admin-users.d.ts +178 -0
- package/dist/admin-users.d.ts.map +1 -0
- package/dist/admin-users.js +14 -0
- package/dist/admin-users.js.map +1 -0
- package/dist/admin.d.ts +243 -0
- package/dist/admin.d.ts.map +1 -0
- package/dist/admin.js +246 -0
- package/dist/admin.js.map +1 -0
- package/dist/analytics.d.ts +123 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +68 -0
- package/dist/analytics.js.map +1 -0
- package/dist/api-keys.d.ts +97 -0
- package/dist/api-keys.d.ts.map +1 -0
- package/dist/api-keys.js +64 -0
- package/dist/api-keys.js.map +1 -0
- package/dist/assets-library.d.ts +684 -0
- package/dist/assets-library.d.ts.map +1 -0
- package/dist/assets-library.js +181 -0
- package/dist/assets-library.js.map +1 -0
- package/dist/audit-logs.d.ts +141 -0
- package/dist/audit-logs.d.ts.map +1 -0
- package/dist/audit-logs.js +31 -0
- package/dist/audit-logs.js.map +1 -0
- package/dist/auth.d.ts +174 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +27 -0
- package/dist/auth.js.map +1 -0
- package/dist/blog.d.ts +669 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +360 -0
- package/dist/blog.js.map +1 -0
- package/dist/capabilities.d.ts +40 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +38 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/carts.d.ts +1367 -0
- package/dist/carts.d.ts.map +1 -0
- package/dist/carts.js +405 -0
- package/dist/carts.js.map +1 -0
- package/dist/catalog.d.ts +2855 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +1543 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cms.d.ts +872 -0
- package/dist/cms.d.ts.map +1 -0
- package/dist/cms.js +468 -0
- package/dist/cms.js.map +1 -0
- package/dist/common.d.ts +82 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +72 -0
- package/dist/common.js.map +1 -0
- package/dist/comparisons.d.ts +487 -0
- package/dist/comparisons.d.ts.map +1 -0
- package/dist/comparisons.js +221 -0
- package/dist/comparisons.js.map +1 -0
- package/dist/credentials.d.ts +292 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +142 -0
- package/dist/credentials.js.map +1 -0
- package/dist/credit-limits.d.ts +111 -0
- package/dist/credit-limits.d.ts.map +1 -0
- package/dist/credit-limits.js +35 -0
- package/dist/credit-limits.js.map +1 -0
- package/dist/currencies.d.ts +127 -0
- package/dist/currencies.d.ts.map +1 -0
- package/dist/currencies.js +20 -0
- package/dist/currencies.js.map +1 -0
- package/dist/custom-fields.d.ts +345 -0
- package/dist/custom-fields.d.ts.map +1 -0
- package/dist/custom-fields.js +185 -0
- package/dist/custom-fields.js.map +1 -0
- package/dist/customer-accounts.d.ts +690 -0
- package/dist/customer-accounts.d.ts.map +1 -0
- package/dist/customer-accounts.js +41 -0
- package/dist/customer-accounts.js.map +1 -0
- package/dist/customers.d.ts +305 -0
- package/dist/customers.d.ts.map +1 -0
- package/dist/customers.js +158 -0
- package/dist/customers.js.map +1 -0
- package/dist/dictionary.d.ts +580 -0
- package/dist/dictionary.d.ts.map +1 -0
- package/dist/dictionary.js +297 -0
- package/dist/dictionary.js.map +1 -0
- package/dist/email-address.d.ts +62 -0
- package/dist/email-address.d.ts.map +1 -0
- package/dist/email-address.js +64 -0
- package/dist/email-address.js.map +1 -0
- package/dist/email.d.ts +175 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +45 -0
- package/dist/email.js.map +1 -0
- package/dist/envelopes.d.ts +15 -0
- package/dist/envelopes.d.ts.map +1 -0
- package/dist/envelopes.js +16 -0
- package/dist/envelopes.js.map +1 -0
- package/dist/environment-inputs.d.ts +306 -0
- package/dist/environment-inputs.d.ts.map +1 -0
- package/dist/environment-inputs.js +277 -0
- package/dist/environment-inputs.js.map +1 -0
- package/dist/erp-connector.d.ts +52 -0
- package/dist/erp-connector.d.ts.map +1 -0
- package/dist/erp-connector.js +34 -0
- package/dist/erp-connector.js.map +1 -0
- package/dist/errors.d.ts +455 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +532 -0
- package/dist/errors.js.map +1 -0
- package/dist/google-analytics.d.ts +181 -0
- package/dist/google-analytics.d.ts.map +1 -0
- package/dist/google-analytics.js +176 -0
- package/dist/google-analytics.js.map +1 -0
- package/dist/google-tag-manager.d.ts +111 -0
- package/dist/google-tag-manager.d.ts.map +1 -0
- package/dist/google-tag-manager.js +129 -0
- package/dist/google-tag-manager.js.map +1 -0
- package/dist/i18n.d.ts +69 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +59 -0
- package/dist/i18n.js.map +1 -0
- package/dist/import-export.d.ts +63 -0
- package/dist/import-export.d.ts.map +1 -0
- package/dist/import-export.js +37 -0
- package/dist/import-export.js.map +1 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory.d.ts +673 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +412 -0
- package/dist/inventory.js.map +1 -0
- package/dist/invoice-ledger.d.ts +366 -0
- package/dist/invoice-ledger.d.ts.map +1 -0
- package/dist/invoice-ledger.js +114 -0
- package/dist/invoice-ledger.js.map +1 -0
- package/dist/invoices.d.ts +845 -0
- package/dist/invoices.d.ts.map +1 -0
- package/dist/invoices.js +314 -0
- package/dist/invoices.js.map +1 -0
- package/dist/kernel.d.ts +49 -0
- package/dist/kernel.d.ts.map +1 -0
- package/dist/kernel.js +19 -0
- package/dist/kernel.js.map +1 -0
- package/dist/languages.d.ts +122 -0
- package/dist/languages.d.ts.map +1 -0
- package/dist/languages.js +24 -0
- package/dist/languages.js.map +1 -0
- package/dist/linkedin-ads.d.ts +167 -0
- package/dist/linkedin-ads.d.ts.map +1 -0
- package/dist/linkedin-ads.js +156 -0
- package/dist/linkedin-ads.js.map +1 -0
- package/dist/megamenu.d.ts +556 -0
- package/dist/megamenu.d.ts.map +1 -0
- package/dist/megamenu.js +186 -0
- package/dist/megamenu.js.map +1 -0
- package/dist/meta-ads.d.ts +126 -0
- package/dist/meta-ads.d.ts.map +1 -0
- package/dist/meta-ads.js +112 -0
- package/dist/meta-ads.js.map +1 -0
- package/dist/mfa.d.ts +274 -0
- package/dist/mfa.d.ts.map +1 -0
- package/dist/mfa.js +187 -0
- package/dist/mfa.js.map +1 -0
- package/dist/modules.d.ts +1706 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +1390 -0
- package/dist/modules.js.map +1 -0
- package/dist/newsletter.d.ts +611 -0
- package/dist/newsletter.d.ts.map +1 -0
- package/dist/newsletter.js +345 -0
- package/dist/newsletter.js.map +1 -0
- package/dist/orders.d.ts +1175 -0
- package/dist/orders.d.ts.map +1 -0
- package/dist/orders.js +630 -0
- package/dist/orders.js.map +1 -0
- package/dist/organizations.d.ts +938 -0
- package/dist/organizations.d.ts.map +1 -0
- package/dist/organizations.js +418 -0
- package/dist/organizations.js.map +1 -0
- package/dist/pagination.d.ts +21 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +22 -0
- package/dist/pagination.js.map +1 -0
- package/dist/payment-methods.d.ts +472 -0
- package/dist/payment-methods.d.ts.map +1 -0
- package/dist/payment-methods.js +175 -0
- package/dist/payment-methods.js.map +1 -0
- package/dist/payment-return-url.d.ts +53 -0
- package/dist/payment-return-url.d.ts.map +1 -0
- package/dist/payment-return-url.js +35 -0
- package/dist/payment-return-url.js.map +1 -0
- package/dist/payments.d.ts +386 -0
- package/dist/payments.d.ts.map +1 -0
- package/dist/payments.js +84 -0
- package/dist/payments.js.map +1 -0
- package/dist/pim-connector.d.ts +60 -0
- package/dist/pim-connector.d.ts.map +1 -0
- package/dist/pim-connector.js +43 -0
- package/dist/pim-connector.js.map +1 -0
- package/dist/pim-field-path.d.ts +6 -0
- package/dist/pim-field-path.d.ts.map +1 -0
- package/dist/pim-field-path.js +101 -0
- package/dist/pim-field-path.js.map +1 -0
- package/dist/platform-language.d.ts +20 -0
- package/dist/platform-language.d.ts.map +1 -0
- package/dist/platform-language.js +22 -0
- package/dist/platform-language.js.map +1 -0
- package/dist/price-lists.d.ts +685 -0
- package/dist/price-lists.d.ts.map +1 -0
- package/dist/price-lists.js +330 -0
- package/dist/price-lists.js.map +1 -0
- package/dist/product-feeds.d.ts +2837 -0
- package/dist/product-feeds.d.ts.map +1 -0
- package/dist/product-feeds.js +1504 -0
- package/dist/product-feeds.js.map +1 -0
- package/dist/product-scope-overrides.d.ts +134 -0
- package/dist/product-scope-overrides.d.ts.map +1 -0
- package/dist/product-scope-overrides.js +82 -0
- package/dist/product-scope-overrides.js.map +1 -0
- package/dist/product-value-resolver.d.ts +88 -0
- package/dist/product-value-resolver.d.ts.map +1 -0
- package/dist/product-value-resolver.js +128 -0
- package/dist/product-value-resolver.js.map +1 -0
- package/dist/promotions.d.ts +678 -0
- package/dist/promotions.d.ts.map +1 -0
- package/dist/promotions.js +479 -0
- package/dist/promotions.js.map +1 -0
- package/dist/prompt-actions.d.ts +582 -0
- package/dist/prompt-actions.d.ts.map +1 -0
- package/dist/prompt-actions.js +221 -0
- package/dist/prompt-actions.js.map +1 -0
- package/dist/pwa.d.ts +293 -0
- package/dist/pwa.d.ts.map +1 -0
- package/dist/pwa.js +204 -0
- package/dist/pwa.js.map +1 -0
- package/dist/quick-order.d.ts +340 -0
- package/dist/quick-order.d.ts.map +1 -0
- package/dist/quick-order.js +177 -0
- package/dist/quick-order.js.map +1 -0
- package/dist/quote-requests.d.ts +538 -0
- package/dist/quote-requests.d.ts.map +1 -0
- package/dist/quote-requests.js +308 -0
- package/dist/quote-requests.js.map +1 -0
- package/dist/returns.d.ts +774 -0
- package/dist/returns.d.ts.map +1 -0
- package/dist/returns.js +389 -0
- package/dist/returns.js.map +1 -0
- package/dist/sales-channels.d.ts +392 -0
- package/dist/sales-channels.d.ts.map +1 -0
- package/dist/sales-channels.js +285 -0
- package/dist/sales-channels.js.map +1 -0
- package/dist/scope-notice.d.ts +60 -0
- package/dist/scope-notice.d.ts.map +1 -0
- package/dist/scope-notice.js +56 -0
- package/dist/scope-notice.js.map +1 -0
- package/dist/search.d.ts +321 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +160 -0
- package/dist/search.js.map +1 -0
- package/dist/seo.d.ts +113 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +63 -0
- package/dist/seo.js.map +1 -0
- package/dist/settings.d.ts +453 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +337 -0
- package/dist/settings.js.map +1 -0
- package/dist/shipments.d.ts +140 -0
- package/dist/shipments.d.ts.map +1 -0
- package/dist/shipments.js +14 -0
- package/dist/shipments.js.map +1 -0
- package/dist/shipping-methods.d.ts +350 -0
- package/dist/shipping-methods.d.ts.map +1 -0
- package/dist/shipping-methods.js +99 -0
- package/dist/shipping-methods.js.map +1 -0
- package/dist/shopping-lists.d.ts +122 -0
- package/dist/shopping-lists.d.ts.map +1 -0
- package/dist/shopping-lists.js +92 -0
- package/dist/shopping-lists.js.map +1 -0
- package/dist/taxes.d.ts +106 -0
- package/dist/taxes.d.ts.map +1 -0
- package/dist/taxes.js +80 -0
- package/dist/taxes.js.map +1 -0
- package/dist/text-normalization.d.ts +199 -0
- package/dist/text-normalization.d.ts.map +1 -0
- package/dist/text-normalization.js +205 -0
- package/dist/text-normalization.js.map +1 -0
- package/dist/transactional-emails.d.ts +459 -0
- package/dist/transactional-emails.d.ts.map +1 -0
- package/dist/transactional-emails.js +212 -0
- package/dist/transactional-emails.js.map +1 -0
- package/dist/webhooks.d.ts +69 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +53 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +46 -0
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type ProductAudience, type ProductListSort, type ProductSummary } from './catalog.js';
|
|
3
|
+
/**
|
|
4
|
+
* Maximum allowed phrase length, in characters. Mirrors the
|
|
5
|
+
* `phrase varchar(512)` upper bound in `data-model.md §1.1` so the wire
|
|
6
|
+
* contract refuses anything that the storage layer would refuse anyway.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SEARCH_PHRASE_MAX_LENGTH = 512;
|
|
9
|
+
/**
|
|
10
|
+
* Hard cap on `limit`; the per-channel `search.popup.suggestion_count`
|
|
11
|
+
* setting is what callers normally observe. The cap exists so a misbehaving
|
|
12
|
+
* client cannot ask for more than the popup UX could realistically render.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SEARCH_SUGGEST_LIMIT_MAX = 50;
|
|
15
|
+
export declare const SearchSuggestQuerySchema: z.ZodObject<{
|
|
16
|
+
q: z.ZodString;
|
|
17
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
export type SearchSuggestQuery = z.infer<typeof SearchSuggestQuerySchema>;
|
|
20
|
+
export declare const SearchSuggestMetaSchema: z.ZodObject<{
|
|
21
|
+
limit: z.ZodNumber;
|
|
22
|
+
minimumQueryLength: z.ZodNumber;
|
|
23
|
+
queryEcho: z.ZodString;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
export type SearchSuggestMeta = z.infer<typeof SearchSuggestMetaSchema>;
|
|
26
|
+
/**
|
|
27
|
+
* Money carried by an enriched suggestion. The amount is a decimal STRING
|
|
28
|
+
* (e.g. "199.00") to preserve trailing zeros across the wire, matching the
|
|
29
|
+
* `resolved-price` endpoint's shape (feature 011) rather than the foundation
|
|
30
|
+
* `moneySchema` (which uses a number for the legacy `ProductSummary.price`).
|
|
31
|
+
*/
|
|
32
|
+
export declare const searchSuggestMoneySchema: z.ZodObject<{
|
|
33
|
+
amount: z.ZodString;
|
|
34
|
+
currency: z.ZodString;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
export type SearchSuggestMoney = z.infer<typeof searchSuggestMoneySchema>;
|
|
37
|
+
/**
|
|
38
|
+
* A typeahead suggestion. Extends the foundation `ProductSummary` (id, sku,
|
|
39
|
+
* name, slug, `primaryAssetUrl`, legacy `price`) with the per-customer
|
|
40
|
+
* price-list resolution so the popup can render the SKU, image, and the
|
|
41
|
+
* price the searching user would actually pay — honouring their price list
|
|
42
|
+
* and price-visibility (`priceDisplayMode`, where `none` hides the price).
|
|
43
|
+
*
|
|
44
|
+
* The pricing fields are optional: when the search module runs without a
|
|
45
|
+
* pricing enricher wired (foundation tests, Meilisearch-only deployments)
|
|
46
|
+
* the response degrades to a plain `ProductSummary` and the storefront
|
|
47
|
+
* falls back to the legacy `price` projection.
|
|
48
|
+
*/
|
|
49
|
+
export declare const searchSuggestItemSchema: z.ZodObject<{
|
|
50
|
+
id: z.ZodString;
|
|
51
|
+
sku: z.ZodString;
|
|
52
|
+
type: z.ZodEnum<{
|
|
53
|
+
simple: "simple";
|
|
54
|
+
configurable: "configurable";
|
|
55
|
+
grouped: "grouped";
|
|
56
|
+
bundle: "bundle";
|
|
57
|
+
virtual: "virtual";
|
|
58
|
+
}>;
|
|
59
|
+
name: z.ZodString;
|
|
60
|
+
slug: z.ZodString;
|
|
61
|
+
categorySlugs: z.ZodArray<z.ZodString>;
|
|
62
|
+
primaryAssetUrl: z.ZodNullable<z.ZodString>;
|
|
63
|
+
price: z.ZodNullable<z.ZodObject<{
|
|
64
|
+
amount: z.ZodNumber;
|
|
65
|
+
currency: z.ZodString;
|
|
66
|
+
}, z.core.$strip>>;
|
|
67
|
+
stockIndicator: z.ZodNullable<z.ZodEnum<{
|
|
68
|
+
available: "available";
|
|
69
|
+
out_of_stock: "out_of_stock";
|
|
70
|
+
to_order: "to_order";
|
|
71
|
+
}>>;
|
|
72
|
+
stockLevel: z.ZodNullable<z.ZodNumber>;
|
|
73
|
+
priceUnavailable: z.ZodOptional<z.ZodBoolean>;
|
|
74
|
+
availability: z.ZodOptional<z.ZodObject<{
|
|
75
|
+
band: z.ZodEnum<{
|
|
76
|
+
available: "available";
|
|
77
|
+
out_of_stock: "out_of_stock";
|
|
78
|
+
high: "high";
|
|
79
|
+
medium: "medium";
|
|
80
|
+
low: "low";
|
|
81
|
+
}>;
|
|
82
|
+
inStock: z.ZodBoolean;
|
|
83
|
+
}, z.core.$strip>>;
|
|
84
|
+
basePrice: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
85
|
+
amount: z.ZodString;
|
|
86
|
+
currency: z.ZodString;
|
|
87
|
+
}, z.core.$strip>>>;
|
|
88
|
+
salePrice: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
89
|
+
amount: z.ZodString;
|
|
90
|
+
currency: z.ZodString;
|
|
91
|
+
}, z.core.$strip>>>;
|
|
92
|
+
priceDisplayMode: z.ZodOptional<z.ZodEnum<{
|
|
93
|
+
both: "both";
|
|
94
|
+
none: "none";
|
|
95
|
+
gross_only: "gross_only";
|
|
96
|
+
net_only: "net_only";
|
|
97
|
+
}>>;
|
|
98
|
+
}, z.core.$strip>;
|
|
99
|
+
export type SearchSuggestItem = z.infer<typeof searchSuggestItemSchema>;
|
|
100
|
+
export declare const SearchSuggestResponseSchema: z.ZodObject<{
|
|
101
|
+
data: z.ZodArray<z.ZodObject<{
|
|
102
|
+
id: z.ZodString;
|
|
103
|
+
sku: z.ZodString;
|
|
104
|
+
type: z.ZodEnum<{
|
|
105
|
+
simple: "simple";
|
|
106
|
+
configurable: "configurable";
|
|
107
|
+
grouped: "grouped";
|
|
108
|
+
bundle: "bundle";
|
|
109
|
+
virtual: "virtual";
|
|
110
|
+
}>;
|
|
111
|
+
name: z.ZodString;
|
|
112
|
+
slug: z.ZodString;
|
|
113
|
+
categorySlugs: z.ZodArray<z.ZodString>;
|
|
114
|
+
primaryAssetUrl: z.ZodNullable<z.ZodString>;
|
|
115
|
+
price: z.ZodNullable<z.ZodObject<{
|
|
116
|
+
amount: z.ZodNumber;
|
|
117
|
+
currency: z.ZodString;
|
|
118
|
+
}, z.core.$strip>>;
|
|
119
|
+
stockIndicator: z.ZodNullable<z.ZodEnum<{
|
|
120
|
+
available: "available";
|
|
121
|
+
out_of_stock: "out_of_stock";
|
|
122
|
+
to_order: "to_order";
|
|
123
|
+
}>>;
|
|
124
|
+
stockLevel: z.ZodNullable<z.ZodNumber>;
|
|
125
|
+
priceUnavailable: z.ZodOptional<z.ZodBoolean>;
|
|
126
|
+
availability: z.ZodOptional<z.ZodObject<{
|
|
127
|
+
band: z.ZodEnum<{
|
|
128
|
+
available: "available";
|
|
129
|
+
out_of_stock: "out_of_stock";
|
|
130
|
+
high: "high";
|
|
131
|
+
medium: "medium";
|
|
132
|
+
low: "low";
|
|
133
|
+
}>;
|
|
134
|
+
inStock: z.ZodBoolean;
|
|
135
|
+
}, z.core.$strip>>;
|
|
136
|
+
basePrice: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
137
|
+
amount: z.ZodString;
|
|
138
|
+
currency: z.ZodString;
|
|
139
|
+
}, z.core.$strip>>>;
|
|
140
|
+
salePrice: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
141
|
+
amount: z.ZodString;
|
|
142
|
+
currency: z.ZodString;
|
|
143
|
+
}, z.core.$strip>>>;
|
|
144
|
+
priceDisplayMode: z.ZodOptional<z.ZodEnum<{
|
|
145
|
+
both: "both";
|
|
146
|
+
none: "none";
|
|
147
|
+
gross_only: "gross_only";
|
|
148
|
+
net_only: "net_only";
|
|
149
|
+
}>>;
|
|
150
|
+
}, z.core.$strip>>;
|
|
151
|
+
meta: z.ZodObject<{
|
|
152
|
+
limit: z.ZodNumber;
|
|
153
|
+
minimumQueryLength: z.ZodNumber;
|
|
154
|
+
queryEcho: z.ZodString;
|
|
155
|
+
}, z.core.$strip>;
|
|
156
|
+
}, z.core.$strip>;
|
|
157
|
+
export type SearchSuggestResponse = z.infer<typeof SearchSuggestResponseSchema>;
|
|
158
|
+
/**
|
|
159
|
+
* The four `search.llm.*` settings whose values are inspected by the
|
|
160
|
+
* toggle wrapper. `enabled` must be present; the other three must be
|
|
161
|
+
* non-empty when `enabled=true`. The wrapper itself only writes the
|
|
162
|
+
* `enabled` setting — the embedder fields are written through the
|
|
163
|
+
* generic Settings admin route and read by the wrapper at validation
|
|
164
|
+
* time.
|
|
165
|
+
*/
|
|
166
|
+
export declare const LlmToggleRequestSchema: z.ZodObject<{
|
|
167
|
+
enabled: z.ZodBoolean;
|
|
168
|
+
salesChannelCodes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
169
|
+
expectedVersion: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
170
|
+
}, z.core.$strip>;
|
|
171
|
+
export type LlmToggleRequest = z.infer<typeof LlmToggleRequestSchema>;
|
|
172
|
+
export declare const LlmToggleResponseSchema: z.ZodObject<{
|
|
173
|
+
code: z.ZodLiteral<"search.llm.enabled">;
|
|
174
|
+
enabled: z.ZodBoolean;
|
|
175
|
+
newVersion: z.ZodString;
|
|
176
|
+
appliedChannelIds: z.ZodArray<z.ZodUUID>;
|
|
177
|
+
}, z.core.$strip>;
|
|
178
|
+
export type LlmToggleResponse = z.infer<typeof LlmToggleResponseSchema>;
|
|
179
|
+
/**
|
|
180
|
+
* Fire-and-forget analytics ingest. The storefront's `/search` page
|
|
181
|
+
* fires this on render, AFTER `listProducts` resolves so `resultCount`
|
|
182
|
+
* is meaningful. The endpoint always returns `202 { ok: true }` once
|
|
183
|
+
* the input passes shape validation; persistence failures degrade to a
|
|
184
|
+
* warn log (FR-015 — recording must never delay or fail the search
|
|
185
|
+
* response).
|
|
186
|
+
*/
|
|
187
|
+
export declare const RecordPhraseRequestSchema: z.ZodObject<{
|
|
188
|
+
phrase: z.ZodString;
|
|
189
|
+
resultCount: z.ZodOptional<z.ZodNumber>;
|
|
190
|
+
}, z.core.$strip>;
|
|
191
|
+
export type RecordPhraseRequest = z.infer<typeof RecordPhraseRequestSchema>;
|
|
192
|
+
export declare const RecordPhraseResponseSchema: z.ZodObject<{
|
|
193
|
+
ok: z.ZodLiteral<true>;
|
|
194
|
+
}, z.core.$strip>;
|
|
195
|
+
export type RecordPhraseResponse = z.infer<typeof RecordPhraseResponseSchema>;
|
|
196
|
+
/**
|
|
197
|
+
* Triggers an immediate, synchronous full reindex of every sales-channel
|
|
198
|
+
* Meilisearch index — the same work the periodic background sweep performs
|
|
199
|
+
* (`search.reindex_interval_minutes`). Body is empty; the response carries a
|
|
200
|
+
* per-run summary so the admin UI can confirm what was rebuilt.
|
|
201
|
+
*/
|
|
202
|
+
export declare const SearchReindexResponseSchema: z.ZodObject<{
|
|
203
|
+
channelsReindexed: z.ZodNumber;
|
|
204
|
+
documentCount: z.ZodNumber;
|
|
205
|
+
}, z.core.$strip>;
|
|
206
|
+
export type SearchReindexResponse = z.infer<typeof SearchReindexResponseSchema>;
|
|
207
|
+
/** The channel a search runs in, resolved before the query is built. */
|
|
208
|
+
export interface ResolvedSearchChannel {
|
|
209
|
+
id: string;
|
|
210
|
+
code: string;
|
|
211
|
+
isPublic: boolean;
|
|
212
|
+
defaultCurrency: string;
|
|
213
|
+
defaultLanguage: string;
|
|
214
|
+
}
|
|
215
|
+
export interface SearchQueryContext {
|
|
216
|
+
resolvedChannel: ResolvedSearchChannel;
|
|
217
|
+
/**
|
|
218
|
+
* Who is asking (issue #227). The index is not the authority on this: it
|
|
219
|
+
* carries `visibility` as a filterable attribute and has never carried
|
|
220
|
+
* `allowed_organization_ids` at all, so the answer is recomputed against the
|
|
221
|
+
* Postgres rows the hits hydrate from — the same place this path already
|
|
222
|
+
* insists the price comes from.
|
|
223
|
+
*/
|
|
224
|
+
audience: ProductAudience;
|
|
225
|
+
preferredLanguage?: string | undefined;
|
|
226
|
+
}
|
|
227
|
+
export interface SearchListProductsParams {
|
|
228
|
+
q?: string | undefined;
|
|
229
|
+
limit: number;
|
|
230
|
+
cursor?: string | undefined;
|
|
231
|
+
/**
|
|
232
|
+
* Feature 086 widened this to the catalogue's own sort union so the two
|
|
233
|
+
* backends keep sharing one input type. The two price members can never
|
|
234
|
+
* reach this backend — `catalog/routes.public.ts` routes a price ordering to
|
|
235
|
+
* Postgres before it chooses Meilisearch — and `buildSort` answers `[]` for
|
|
236
|
+
* them, because returning a sort expression for a field the document does not
|
|
237
|
+
* carry would be a trap for the next author.
|
|
238
|
+
*/
|
|
239
|
+
sort?: ProductListSort | undefined;
|
|
240
|
+
categorySlug?: string | undefined;
|
|
241
|
+
attributeFilters?: Record<string, string[]> | undefined;
|
|
242
|
+
}
|
|
243
|
+
export interface SearchListResult {
|
|
244
|
+
data: ProductSummary[];
|
|
245
|
+
pagination: {
|
|
246
|
+
cursor: string | null;
|
|
247
|
+
hasMore: boolean;
|
|
248
|
+
limit: number;
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* What a listing query answered: the page, or the fact that the index could
|
|
253
|
+
* not be reached.
|
|
254
|
+
*
|
|
255
|
+
* The second arm exists so the caller does not have to write a `catch` to
|
|
256
|
+
* learn it. `search` raises `SearchBackendUnavailable` internally when
|
|
257
|
+
* Meilisearch is unreachable; the port converts it here, on the owner's side,
|
|
258
|
+
* because a consumer catching it would be a `catch` around a port call — and
|
|
259
|
+
* that `catch` would swallow `ModuleDisabledError` too, turning "the operator
|
|
260
|
+
* switched `search` off" into "the index is slow today". Two different facts
|
|
261
|
+
* with two different right answers, fused by one `catch` clause.
|
|
262
|
+
*
|
|
263
|
+
* This is the `allowedIdsFor(): Promise<string[] | null>` shape AGENTS.md names
|
|
264
|
+
* as the worked example: where a degrade genuinely belongs, it goes inside the
|
|
265
|
+
* owner's implementation and is expressed in the return type.
|
|
266
|
+
*/
|
|
267
|
+
export type SearchListOutcome = {
|
|
268
|
+
status: 'ok';
|
|
269
|
+
result: SearchListResult;
|
|
270
|
+
}
|
|
271
|
+
/** Meilisearch refused or timed out. `reason` is for the caller's log line. */
|
|
272
|
+
| {
|
|
273
|
+
status: 'index-unavailable';
|
|
274
|
+
reason: string;
|
|
275
|
+
};
|
|
276
|
+
/**
|
|
277
|
+
* Container name: `searchQueryPort`. Owner: `search`.
|
|
278
|
+
*
|
|
279
|
+
* **The one port in the sweep whose consumer is right to degrade rather than
|
|
280
|
+
* fail**, and the degrade is already where it belongs: `catalog`'s listing
|
|
281
|
+
* route checks the backend setting and falls back to its own Postgres query.
|
|
282
|
+
* That is a `nonBindingDependencies` edge, declared, not a `catch` — a search
|
|
283
|
+
* index being unavailable must not take the catalogue down with it.
|
|
284
|
+
*
|
|
285
|
+
* Note what the fallback is *not* allowed to be: a `try`/`catch` around the
|
|
286
|
+
* call. Catching here would swallow `ModuleDisabledError` and make a
|
|
287
|
+
* switched-off `search` look like a slow one, which is the fail-open shape
|
|
288
|
+
* `check:port-catches` exists for. That is why `listProducts` answers a
|
|
289
|
+
* {@link SearchListOutcome} rather than throwing: the consumer distinguishes
|
|
290
|
+
* the two states by reading a field, and never by catching.
|
|
291
|
+
*/
|
|
292
|
+
export interface SearchQueryPort {
|
|
293
|
+
listProducts(params: SearchListProductsParams, ctx: SearchQueryContext): Promise<SearchListOutcome>;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Container name: `searchReindexPort`. Owner: `search`.
|
|
297
|
+
*
|
|
298
|
+
* A full rebuild of every channel's index, over the one indexer `searchModule`
|
|
299
|
+
* holds — so a composition has exactly one Meilisearch client whichever entry
|
|
300
|
+
* point triggers the reindex. `catalog` runs it as a `search_reindex` bulk
|
|
301
|
+
* operation when an attribute's `searchable` flag flips, and the `search:reindex`
|
|
302
|
+
* CLI command is the other caller.
|
|
303
|
+
*
|
|
304
|
+
* Published by `specs/117-instance-bring-up/` Phase 6, which is when it first
|
|
305
|
+
* had a consumer that resolves it **by name**: a composition root used to
|
|
306
|
+
* resolve it and hand `catalog` a closure, and a root's read is outside
|
|
307
|
+
* `check:port-shape`'s population, so the name went unpublished for as long as
|
|
308
|
+
* nothing inside a module asked for it.
|
|
309
|
+
*
|
|
310
|
+
* **Owner off:** `catalog` decides presence in front of the gate rather than
|
|
311
|
+
* catching behind it, and answers `{ documentCount: 0 }` — its manifest declares
|
|
312
|
+
* the edge `degrades-without`, because with `search` absent there is no index to
|
|
313
|
+
* rebuild and 503-ing an unrelated attribute edit would make an operator's
|
|
314
|
+
* supported off-switch fail a catalogue write.
|
|
315
|
+
*/
|
|
316
|
+
export interface SearchReindexPort {
|
|
317
|
+
reindexAll(): Promise<{
|
|
318
|
+
documentCount: number;
|
|
319
|
+
}>;
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Search module — feature 006 contract surface.
|
|
2
|
+
//
|
|
3
|
+
// Public API:
|
|
4
|
+
// - GET /api/v1/search/suggest (typeahead popup feed — US1)
|
|
5
|
+
// - POST /api/v1/search/record (analytics ingest — US3)
|
|
6
|
+
// - POST /api/v1/admin/search/llm/toggle (LLM-mode toggle wrapper — US2)
|
|
7
|
+
//
|
|
8
|
+
// Schemas live in three sections, populated by the user-story phases that
|
|
9
|
+
// own them. Foundation (T002) seeded the file empty; US1 (T009) adds the
|
|
10
|
+
// suggest contracts below. US2 / US3 schemas land later.
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { productSummarySchema, } from './catalog.js';
|
|
13
|
+
import { displayModeSchema } from './price-lists.js';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// (1) GET /api/v1/search/suggest — US1 / T009
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Maximum allowed phrase length, in characters. Mirrors the
|
|
19
|
+
* `phrase varchar(512)` upper bound in `data-model.md §1.1` so the wire
|
|
20
|
+
* contract refuses anything that the storage layer would refuse anyway.
|
|
21
|
+
*/
|
|
22
|
+
export const SEARCH_PHRASE_MAX_LENGTH = 512;
|
|
23
|
+
/**
|
|
24
|
+
* Hard cap on `limit`; the per-channel `search.popup.suggestion_count`
|
|
25
|
+
* setting is what callers normally observe. The cap exists so a misbehaving
|
|
26
|
+
* client cannot ask for more than the popup UX could realistically render.
|
|
27
|
+
*/
|
|
28
|
+
export const SEARCH_SUGGEST_LIMIT_MAX = 50;
|
|
29
|
+
export const SearchSuggestQuerySchema = z.object({
|
|
30
|
+
q: z
|
|
31
|
+
.string()
|
|
32
|
+
.min(1, 'phrase is required')
|
|
33
|
+
.max(SEARCH_PHRASE_MAX_LENGTH, 'phrase exceeds the maximum length'),
|
|
34
|
+
limit: z.coerce
|
|
35
|
+
.number()
|
|
36
|
+
.int()
|
|
37
|
+
.positive()
|
|
38
|
+
.max(SEARCH_SUGGEST_LIMIT_MAX)
|
|
39
|
+
.optional(),
|
|
40
|
+
});
|
|
41
|
+
export const SearchSuggestMetaSchema = z.object({
|
|
42
|
+
/** Effective limit applied to the response. */
|
|
43
|
+
limit: z.number().int().nonnegative(),
|
|
44
|
+
/** The channel's resolved minimum query length, echoed back so the
|
|
45
|
+
* client can self-correct without a separate round-trip. */
|
|
46
|
+
minimumQueryLength: z.number().int().positive(),
|
|
47
|
+
/** Echo of `q` after trimming, for client-side reconciliation when the
|
|
48
|
+
* popup is rendering stale state. */
|
|
49
|
+
queryEcho: z.string(),
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Money carried by an enriched suggestion. The amount is a decimal STRING
|
|
53
|
+
* (e.g. "199.00") to preserve trailing zeros across the wire, matching the
|
|
54
|
+
* `resolved-price` endpoint's shape (feature 011) rather than the foundation
|
|
55
|
+
* `moneySchema` (which uses a number for the legacy `ProductSummary.price`).
|
|
56
|
+
*/
|
|
57
|
+
export const searchSuggestMoneySchema = z.object({
|
|
58
|
+
amount: z.string(),
|
|
59
|
+
currency: z.string(),
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* A typeahead suggestion. Extends the foundation `ProductSummary` (id, sku,
|
|
63
|
+
* name, slug, `primaryAssetUrl`, legacy `price`) with the per-customer
|
|
64
|
+
* price-list resolution so the popup can render the SKU, image, and the
|
|
65
|
+
* price the searching user would actually pay — honouring their price list
|
|
66
|
+
* and price-visibility (`priceDisplayMode`, where `none` hides the price).
|
|
67
|
+
*
|
|
68
|
+
* The pricing fields are optional: when the search module runs without a
|
|
69
|
+
* pricing enricher wired (foundation tests, Meilisearch-only deployments)
|
|
70
|
+
* the response degrades to a plain `ProductSummary` and the storefront
|
|
71
|
+
* falls back to the legacy `price` projection.
|
|
72
|
+
*/
|
|
73
|
+
export const searchSuggestItemSchema = productSummarySchema.extend({
|
|
74
|
+
/** Resolved price-list Base price for this customer; `null` when no
|
|
75
|
+
* bracket applies or the price is hidden. */
|
|
76
|
+
basePrice: searchSuggestMoneySchema.nullable().optional(),
|
|
77
|
+
/** Resolved Sale price, when a sale list applies to this customer. */
|
|
78
|
+
salePrice: searchSuggestMoneySchema.nullable().optional(),
|
|
79
|
+
/** Resolved price-visibility mode. `none` ⇒ the storefront must hide the
|
|
80
|
+
* price and offer a quote affordance instead. */
|
|
81
|
+
priceDisplayMode: displayModeSchema.optional(),
|
|
82
|
+
});
|
|
83
|
+
export const SearchSuggestResponseSchema = z.object({
|
|
84
|
+
data: z.array(searchSuggestItemSchema),
|
|
85
|
+
meta: SearchSuggestMetaSchema,
|
|
86
|
+
});
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// (2) POST /api/v1/admin/search/llm/toggle — US2 / T021
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
/**
|
|
91
|
+
* The four `search.llm.*` settings whose values are inspected by the
|
|
92
|
+
* toggle wrapper. `enabled` must be present; the other three must be
|
|
93
|
+
* non-empty when `enabled=true`. The wrapper itself only writes the
|
|
94
|
+
* `enabled` setting — the embedder fields are written through the
|
|
95
|
+
* generic Settings admin route and read by the wrapper at validation
|
|
96
|
+
* time.
|
|
97
|
+
*/
|
|
98
|
+
export const LlmToggleRequestSchema = z.object({
|
|
99
|
+
enabled: z.boolean(),
|
|
100
|
+
/**
|
|
101
|
+
* When omitted, applies to every channel in the setting's scope
|
|
102
|
+
* (parallels SettingsAdminService.setValueForAllChannels). When
|
|
103
|
+
* present, applies only to the listed channels.
|
|
104
|
+
*/
|
|
105
|
+
salesChannelCodes: z.array(z.string().min(1)).optional(),
|
|
106
|
+
/**
|
|
107
|
+
* Optimistic-concurrency token from the latest GET of
|
|
108
|
+
* `search.llm.enabled`. When stale, the call rejects with
|
|
109
|
+
* `409 VERSION_CONFLICT` (mirrors Settings' existing model).
|
|
110
|
+
*/
|
|
111
|
+
expectedVersion: z.string().nullable().optional(),
|
|
112
|
+
});
|
|
113
|
+
export const LlmToggleResponseSchema = z.object({
|
|
114
|
+
/** Always `search.llm.enabled` — present for parity with the generic Settings route. */
|
|
115
|
+
code: z.literal('search.llm.enabled'),
|
|
116
|
+
enabled: z.boolean(),
|
|
117
|
+
/** New optimistic-concurrency token; the admin UI stores it for the next save. */
|
|
118
|
+
newVersion: z.string(),
|
|
119
|
+
/**
|
|
120
|
+
* Channel UUIDs whose `setting_values` row was written. Mirrors the
|
|
121
|
+
* `affectedChannelIds` SetValueResult shape from feature 004.
|
|
122
|
+
*/
|
|
123
|
+
appliedChannelIds: z.array(z.uuid()),
|
|
124
|
+
});
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// (3) POST /api/v1/search/record — US3 / T030
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
/**
|
|
129
|
+
* Fire-and-forget analytics ingest. The storefront's `/search` page
|
|
130
|
+
* fires this on render, AFTER `listProducts` resolves so `resultCount`
|
|
131
|
+
* is meaningful. The endpoint always returns `202 { ok: true }` once
|
|
132
|
+
* the input passes shape validation; persistence failures degrade to a
|
|
133
|
+
* warn log (FR-015 — recording must never delay or fail the search
|
|
134
|
+
* response).
|
|
135
|
+
*/
|
|
136
|
+
export const RecordPhraseRequestSchema = z.object({
|
|
137
|
+
phrase: z
|
|
138
|
+
.string()
|
|
139
|
+
.min(1)
|
|
140
|
+
.max(SEARCH_PHRASE_MAX_LENGTH),
|
|
141
|
+
/** Result-page count; `0` for dead-end phrases (FR-014). */
|
|
142
|
+
resultCount: z.number().int().nonnegative().optional(),
|
|
143
|
+
});
|
|
144
|
+
export const RecordPhraseResponseSchema = z.object({
|
|
145
|
+
ok: z.literal(true),
|
|
146
|
+
});
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// (4) POST /api/v1/admin/search/reindex — manual full Meilisearch reindex
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
/**
|
|
151
|
+
* Triggers an immediate, synchronous full reindex of every sales-channel
|
|
152
|
+
* Meilisearch index — the same work the periodic background sweep performs
|
|
153
|
+
* (`search.reindex_interval_minutes`). Body is empty; the response carries a
|
|
154
|
+
* per-run summary so the admin UI can confirm what was rebuilt.
|
|
155
|
+
*/
|
|
156
|
+
export const SearchReindexResponseSchema = z.object({
|
|
157
|
+
channelsReindexed: z.number().int().nonnegative(),
|
|
158
|
+
documentCount: z.number().int().nonnegative(),
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/seo.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* SEO meta + sitemap contracts (T235 / FR-101, FR-102).
|
|
4
|
+
*
|
|
5
|
+
* The `entityType` enum is closed — only entities the storefront actually
|
|
6
|
+
* renders public pages for can carry meta overrides.
|
|
7
|
+
*/
|
|
8
|
+
export declare const seoEntityTypeSchema: z.ZodEnum<{
|
|
9
|
+
category: "category";
|
|
10
|
+
cms_page: "cms_page";
|
|
11
|
+
product: "product";
|
|
12
|
+
}>;
|
|
13
|
+
export type SeoEntityType = z.infer<typeof seoEntityTypeSchema>;
|
|
14
|
+
export declare const resolvedMetaSchema: z.ZodObject<{
|
|
15
|
+
title: z.ZodString;
|
|
16
|
+
description: z.ZodString;
|
|
17
|
+
openGraph: z.ZodObject<{
|
|
18
|
+
title: z.ZodString;
|
|
19
|
+
description: z.ZodString;
|
|
20
|
+
image: z.ZodNullable<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
source: z.ZodEnum<{
|
|
23
|
+
override: "override";
|
|
24
|
+
rule: "rule";
|
|
25
|
+
}>;
|
|
26
|
+
locale: z.ZodString;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
export type ResolvedMeta = z.infer<typeof resolvedMetaSchema>;
|
|
29
|
+
export declare const seoMetaOverrideSchema: z.ZodObject<{
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
entityType: z.ZodEnum<{
|
|
32
|
+
category: "category";
|
|
33
|
+
cms_page: "cms_page";
|
|
34
|
+
product: "product";
|
|
35
|
+
}>;
|
|
36
|
+
entityId: z.ZodString;
|
|
37
|
+
locale: z.ZodString;
|
|
38
|
+
title: z.ZodNullable<z.ZodString>;
|
|
39
|
+
description: z.ZodNullable<z.ZodString>;
|
|
40
|
+
ogTitle: z.ZodNullable<z.ZodString>;
|
|
41
|
+
ogDescription: z.ZodNullable<z.ZodString>;
|
|
42
|
+
ogImageUrl: z.ZodNullable<z.ZodString>;
|
|
43
|
+
createdAt: z.ZodString;
|
|
44
|
+
updatedAt: z.ZodString;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
export declare const upsertSeoMetaOverrideRequestSchema: z.ZodObject<{
|
|
47
|
+
locale: z.ZodString;
|
|
48
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
50
|
+
ogTitle: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
51
|
+
ogDescription: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
|
+
ogImageUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
export type UpsertSeoMetaOverrideRequest = z.infer<typeof upsertSeoMetaOverrideRequestSchema>;
|
|
55
|
+
export declare const sitemapStatusSchema: z.ZodObject<{
|
|
56
|
+
generatedAt: z.ZodNullable<z.ZodString>;
|
|
57
|
+
byteSize: z.ZodNullable<z.ZodNumber>;
|
|
58
|
+
urlCount: z.ZodNullable<z.ZodNumber>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
export type SitemapStatus = z.infer<typeof sitemapStatusSchema>;
|
|
61
|
+
/**
|
|
62
|
+
* Per-channel sitemap row returned by the admin list endpoint
|
|
63
|
+
* (`GET /api/v1/admin/seo/sitemap`). One row per active sales channel —
|
|
64
|
+
* each carries its own cache (regenerate, preview and download act on a
|
|
65
|
+
* single channel) and its own resolved storefront URL.
|
|
66
|
+
*/
|
|
67
|
+
export declare const sitemapChannelStatusSchema: z.ZodObject<{
|
|
68
|
+
generatedAt: z.ZodNullable<z.ZodString>;
|
|
69
|
+
byteSize: z.ZodNullable<z.ZodNumber>;
|
|
70
|
+
urlCount: z.ZodNullable<z.ZodNumber>;
|
|
71
|
+
salesChannelCode: z.ZodString;
|
|
72
|
+
salesChannelName: z.ZodString;
|
|
73
|
+
storefrontUrl: z.ZodString;
|
|
74
|
+
storefrontUrlSource: z.ZodEnum<{
|
|
75
|
+
env: "env";
|
|
76
|
+
setting: "setting";
|
|
77
|
+
fallback: "fallback";
|
|
78
|
+
}>;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
export type SitemapChannelStatus = z.infer<typeof sitemapChannelStatusSchema>;
|
|
81
|
+
export declare const sitemapChannelListResponseSchema: z.ZodObject<{
|
|
82
|
+
data: z.ZodArray<z.ZodObject<{
|
|
83
|
+
generatedAt: z.ZodNullable<z.ZodString>;
|
|
84
|
+
byteSize: z.ZodNullable<z.ZodNumber>;
|
|
85
|
+
urlCount: z.ZodNullable<z.ZodNumber>;
|
|
86
|
+
salesChannelCode: z.ZodString;
|
|
87
|
+
salesChannelName: z.ZodString;
|
|
88
|
+
storefrontUrl: z.ZodString;
|
|
89
|
+
storefrontUrlSource: z.ZodEnum<{
|
|
90
|
+
env: "env";
|
|
91
|
+
setting: "setting";
|
|
92
|
+
fallback: "fallback";
|
|
93
|
+
}>;
|
|
94
|
+
}, z.core.$strip>>;
|
|
95
|
+
}, z.core.$strip>;
|
|
96
|
+
export type SitemapChannelListResponse = z.infer<typeof sitemapChannelListResponseSchema>;
|
|
97
|
+
/**
|
|
98
|
+
* Container name: `seoMetaWritePort`. Owner: `seo`.
|
|
99
|
+
*
|
|
100
|
+
* Narrow write surface for PIM importers (feature 089 / FR-029): upsert product
|
|
101
|
+
* meta overrides by locale. Channel dimension does not exist on Endora SEO rows.
|
|
102
|
+
*
|
|
103
|
+
* **Owner off:** resolving this port throws `ModuleDisabledError` (503).
|
|
104
|
+
*/
|
|
105
|
+
export interface SeoMetaWritePort {
|
|
106
|
+
upsertProductMeta(input: {
|
|
107
|
+
productId: string;
|
|
108
|
+
locale: string;
|
|
109
|
+
title?: string | null;
|
|
110
|
+
description?: string | null;
|
|
111
|
+
}): Promise<void>;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=seo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../src/seo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AAEH,eAAO,MAAM,mBAAmB;;;;EAA8C,CAAC;AAC/E,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;iBAW7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;iBAYhC,CAAC;AAEH,eAAO,MAAM,kCAAkC;;;;;;;iBAO7C,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F,eAAO,MAAM,mBAAmB;;;;iBAI9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;iBAKrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;iBAE3C,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,CAAC,KAAK,EAAE;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB"}
|
package/dist/seo.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isoDateTimeSchema, uuidSchema } from './common.js';
|
|
3
|
+
/**
|
|
4
|
+
* SEO meta + sitemap contracts (T235 / FR-101, FR-102).
|
|
5
|
+
*
|
|
6
|
+
* The `entityType` enum is closed — only entities the storefront actually
|
|
7
|
+
* renders public pages for can carry meta overrides.
|
|
8
|
+
*/
|
|
9
|
+
export const seoEntityTypeSchema = z.enum(['product', 'category', 'cms_page']);
|
|
10
|
+
export const resolvedMetaSchema = z.object({
|
|
11
|
+
title: z.string(),
|
|
12
|
+
description: z.string(),
|
|
13
|
+
openGraph: z.object({
|
|
14
|
+
title: z.string(),
|
|
15
|
+
description: z.string(),
|
|
16
|
+
image: z.string().nullable(),
|
|
17
|
+
}),
|
|
18
|
+
/** Whether the resolved values came from a stored override or the rule. */
|
|
19
|
+
source: z.enum(['override', 'rule']),
|
|
20
|
+
locale: z.string(),
|
|
21
|
+
});
|
|
22
|
+
export const seoMetaOverrideSchema = z.object({
|
|
23
|
+
id: uuidSchema,
|
|
24
|
+
entityType: seoEntityTypeSchema,
|
|
25
|
+
entityId: uuidSchema,
|
|
26
|
+
locale: z.string().min(2).max(10),
|
|
27
|
+
title: z.string().nullable(),
|
|
28
|
+
description: z.string().nullable(),
|
|
29
|
+
ogTitle: z.string().nullable(),
|
|
30
|
+
ogDescription: z.string().nullable(),
|
|
31
|
+
ogImageUrl: z.string().url().nullable(),
|
|
32
|
+
createdAt: isoDateTimeSchema,
|
|
33
|
+
updatedAt: isoDateTimeSchema,
|
|
34
|
+
});
|
|
35
|
+
export const upsertSeoMetaOverrideRequestSchema = z.object({
|
|
36
|
+
locale: z.string().min(2).max(10),
|
|
37
|
+
title: z.string().min(1).max(160).nullable().optional(),
|
|
38
|
+
description: z.string().min(1).max(400).nullable().optional(),
|
|
39
|
+
ogTitle: z.string().min(1).max(160).nullable().optional(),
|
|
40
|
+
ogDescription: z.string().min(1).max(400).nullable().optional(),
|
|
41
|
+
ogImageUrl: z.string().url().nullable().optional(),
|
|
42
|
+
});
|
|
43
|
+
export const sitemapStatusSchema = z.object({
|
|
44
|
+
generatedAt: isoDateTimeSchema.nullable(),
|
|
45
|
+
byteSize: z.number().int().nonnegative().nullable(),
|
|
46
|
+
urlCount: z.number().int().nonnegative().nullable(),
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* Per-channel sitemap row returned by the admin list endpoint
|
|
50
|
+
* (`GET /api/v1/admin/seo/sitemap`). One row per active sales channel —
|
|
51
|
+
* each carries its own cache (regenerate, preview and download act on a
|
|
52
|
+
* single channel) and its own resolved storefront URL.
|
|
53
|
+
*/
|
|
54
|
+
export const sitemapChannelStatusSchema = sitemapStatusSchema.extend({
|
|
55
|
+
salesChannelCode: z.string(),
|
|
56
|
+
salesChannelName: z.string(),
|
|
57
|
+
storefrontUrl: z.string(),
|
|
58
|
+
storefrontUrlSource: z.enum(['setting', 'env', 'fallback']),
|
|
59
|
+
});
|
|
60
|
+
export const sitemapChannelListResponseSchema = z.object({
|
|
61
|
+
data: z.array(sitemapChannelStatusSchema),
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=seo.js.map
|