@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
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// Sales Channels module — feature 005 contract surface.
|
|
2
|
+
// Single file with logical sections (matching the convention used by every
|
|
3
|
+
// other module in @endora-commerce/contracts):
|
|
4
|
+
// (1) Identity primitives (channel code, summary, detail).
|
|
5
|
+
// (2) Resolver middleware contract (header / query schemas).
|
|
6
|
+
// (3) Admin HTTP request/response schemas (list / detail / create / edit
|
|
7
|
+
// / lifecycle).
|
|
8
|
+
// (4) Membership endpoints (the bidirectional channel-side / entity-side
|
|
9
|
+
// routes; one shape, used by all 10 entity types).
|
|
10
|
+
// (5) Storefront / public read-only schemas.
|
|
11
|
+
// (6) Audit-action constants — free-form action strings written through
|
|
12
|
+
// the existing AuditLogService.
|
|
13
|
+
// (7) Attribution registry — the contribution seam that answers "who still
|
|
14
|
+
// points at this channel?" before a delete (feature 075, D-87).
|
|
15
|
+
// See specs/005-sales-channels/contracts/sales-channels-005.contract.md
|
|
16
|
+
// for the prose contract and the error-code references in `errors.ts`.
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { isoDateTimeSchema, uuidSchema } from './common.js';
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// (1) Identity primitives
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/**
|
|
23
|
+
* Machine-friendly Sales Channel code. Lower-case, starts with a letter,
|
|
24
|
+
* may contain digits, hyphens, and underscores. Stored as `varchar(32)`
|
|
25
|
+
* (foundation 001).
|
|
26
|
+
*/
|
|
27
|
+
export const SalesChannelCodeSchema = z
|
|
28
|
+
.string()
|
|
29
|
+
.min(1)
|
|
30
|
+
.max(32)
|
|
31
|
+
.regex(/^[a-z][a-z0-9_-]*$/, 'sales channel code must be lowercase machine-friendly');
|
|
32
|
+
/** i18n display name keyed by language code, e.g. `{ en: 'Default' }`. */
|
|
33
|
+
export const SalesChannelNameSchema = z
|
|
34
|
+
.record(z.string(), z.string())
|
|
35
|
+
.refine((o) => Object.keys(o).length > 0, 'name must include at least one locale');
|
|
36
|
+
/** Short summary returned in list views. */
|
|
37
|
+
export const SalesChannelSummarySchema = z.object({
|
|
38
|
+
id: uuidSchema,
|
|
39
|
+
code: SalesChannelCodeSchema,
|
|
40
|
+
name: SalesChannelNameSchema,
|
|
41
|
+
active: z.boolean(),
|
|
42
|
+
systemDefault: z.boolean(),
|
|
43
|
+
defaultLanguage: z.string(),
|
|
44
|
+
defaultCurrency: z.string(),
|
|
45
|
+
themeCode: z.string().nullable(),
|
|
46
|
+
logoAssetId: uuidSchema.nullable(),
|
|
47
|
+
version: z.number().int().positive(),
|
|
48
|
+
createdAt: isoDateTimeSchema,
|
|
49
|
+
updatedAt: isoDateTimeSchema,
|
|
50
|
+
});
|
|
51
|
+
/** Full detail returned by the admin GET-by-code endpoint. */
|
|
52
|
+
export const SalesChannelDetailSchema = SalesChannelSummarySchema.extend({
|
|
53
|
+
languages: z.array(z.string()).min(1),
|
|
54
|
+
currencies: z.array(z.string()).min(1),
|
|
55
|
+
/** Resolved through the assets module on response; nullable when no logo set. */
|
|
56
|
+
logoUrl: z.string().url().nullable(),
|
|
57
|
+
});
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// (2) Resolver middleware contract
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/** `X-Sales-Channel: <code>` header schema. */
|
|
62
|
+
export const SalesChannelHeaderSchema = z.object({
|
|
63
|
+
'x-sales-channel': SalesChannelCodeSchema.optional(),
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* `?salesChannel=<code>` query parameter schema. Used by storefront SSR
|
|
67
|
+
* paths and link-shareable previews; ignored on `/api/v1/admin/*` paths
|
|
68
|
+
* by the resolver middleware to prevent cross-channel admin bleed.
|
|
69
|
+
*/
|
|
70
|
+
export const SalesChannelQuerySchema = z.object({
|
|
71
|
+
salesChannel: SalesChannelCodeSchema.optional(),
|
|
72
|
+
});
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// (3) Admin HTTP request/response schemas
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
const themeCodeRe = /^[a-z][a-z0-9_-]*$/;
|
|
77
|
+
/** Body shape for POST /api/v1/admin/sales-channels. */
|
|
78
|
+
export const SalesChannelCreateBodySchema = z
|
|
79
|
+
.object({
|
|
80
|
+
code: SalesChannelCodeSchema,
|
|
81
|
+
name: SalesChannelNameSchema,
|
|
82
|
+
logoAssetId: uuidSchema.nullable().optional(),
|
|
83
|
+
themeCode: z
|
|
84
|
+
.string()
|
|
85
|
+
.regex(themeCodeRe, 'theme code must be lowercase machine-friendly')
|
|
86
|
+
.nullable()
|
|
87
|
+
.optional(),
|
|
88
|
+
languages: z.array(z.string()).min(1),
|
|
89
|
+
defaultLanguage: z.string(),
|
|
90
|
+
currencies: z.array(z.string()).min(1),
|
|
91
|
+
defaultCurrency: z.string(),
|
|
92
|
+
active: z.boolean().optional().default(true),
|
|
93
|
+
})
|
|
94
|
+
.superRefine((v, ctx) => {
|
|
95
|
+
if (!v.languages.includes(v.defaultLanguage)) {
|
|
96
|
+
ctx.addIssue({
|
|
97
|
+
code: 'custom',
|
|
98
|
+
path: ['defaultLanguage'],
|
|
99
|
+
message: 'defaultLanguage must be one of languages',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (!v.currencies.includes(v.defaultCurrency)) {
|
|
103
|
+
ctx.addIssue({
|
|
104
|
+
code: 'custom',
|
|
105
|
+
path: ['defaultCurrency'],
|
|
106
|
+
message: 'defaultCurrency must be one of currencies',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
/**
|
|
111
|
+
* Body shape for PATCH /api/v1/admin/sales-channels/{code}. Every field optional.
|
|
112
|
+
*
|
|
113
|
+
* `code` is accepted only when it repeats the channel's current code: a channel's
|
|
114
|
+
* code is written once, at creation, and is immutable afterwards — on every
|
|
115
|
+
* channel, not only the system default. A code is an identity other systems hold
|
|
116
|
+
* onto (`SALES_CHANNEL_HOST_MAP`, cached storefront responses, integration
|
|
117
|
+
* configuration), so changing it renames something those systems cannot follow.
|
|
118
|
+
* A different value is refused with 422 `SALES_CHANNEL_CODE_IMMUTABLE`; the field
|
|
119
|
+
* stays in the shape so the refusal is explicit rather than a silently stripped
|
|
120
|
+
* property that answers 200 and changes nothing. A mistyped code is fixed by
|
|
121
|
+
* creating the channel again under the right code and deleting the old one —
|
|
122
|
+
* for the default channel, after moving the flag off it with `set-default`.
|
|
123
|
+
* The `name` stays freely editable.
|
|
124
|
+
*/
|
|
125
|
+
export const SalesChannelUpdateBodySchema = z
|
|
126
|
+
.object({
|
|
127
|
+
code: SalesChannelCodeSchema.optional(),
|
|
128
|
+
name: SalesChannelNameSchema.optional(),
|
|
129
|
+
logoAssetId: uuidSchema.nullable().optional(),
|
|
130
|
+
themeCode: z.string().regex(themeCodeRe).nullable().optional(),
|
|
131
|
+
languages: z.array(z.string()).min(1).optional(),
|
|
132
|
+
defaultLanguage: z.string().optional(),
|
|
133
|
+
currencies: z.array(z.string()).min(1).optional(),
|
|
134
|
+
defaultCurrency: z.string().optional(),
|
|
135
|
+
active: z.boolean().optional(),
|
|
136
|
+
})
|
|
137
|
+
.superRefine((v, ctx) => {
|
|
138
|
+
if (v.defaultLanguage !== undefined && v.languages && !v.languages.includes(v.defaultLanguage)) {
|
|
139
|
+
ctx.addIssue({
|
|
140
|
+
code: 'custom',
|
|
141
|
+
path: ['defaultLanguage'],
|
|
142
|
+
message: 'defaultLanguage must be one of languages',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (v.defaultCurrency !== undefined && v.currencies && !v.currencies.includes(v.defaultCurrency)) {
|
|
146
|
+
ctx.addIssue({
|
|
147
|
+
code: 'custom',
|
|
148
|
+
path: ['defaultCurrency'],
|
|
149
|
+
message: 'defaultCurrency must be one of currencies',
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
/**
|
|
154
|
+
* Body shape for POST /api/v1/admin/sales-channels/{code}/set-default.
|
|
155
|
+
*
|
|
156
|
+
* The target is the path parameter, so the body carries nothing today. It is
|
|
157
|
+
* declared rather than omitted because the endpoint is a state transition, not a
|
|
158
|
+
* patch: an operator's client sends `{}` and any later option (a reason, a
|
|
159
|
+
* scheduled cut-over) lands here instead of on the query string.
|
|
160
|
+
*/
|
|
161
|
+
export const SalesChannelSetDefaultBodySchema = z.object({});
|
|
162
|
+
/**
|
|
163
|
+
* Response shape for POST /api/v1/admin/sales-channels/{code}/set-default.
|
|
164
|
+
*
|
|
165
|
+
* `changed` is false when the target already held the flag — promoting the
|
|
166
|
+
* current default is a no-op success, not an error, so a double-click and a
|
|
167
|
+
* retried request both answer 200 with the same body. `previousDefaultCode` is
|
|
168
|
+
* the code that held the flag before the call, which on the no-op path is the
|
|
169
|
+
* target's own code; it names the channel a subsequent `set-default` would move
|
|
170
|
+
* the flag back to.
|
|
171
|
+
*/
|
|
172
|
+
export const SalesChannelSetDefaultResponseSchema = z.object({
|
|
173
|
+
channel: SalesChannelDetailSchema,
|
|
174
|
+
previousDefaultCode: SalesChannelCodeSchema.nullable(),
|
|
175
|
+
changed: z.boolean(),
|
|
176
|
+
});
|
|
177
|
+
/** Response shape for GET /api/v1/admin/sales-channels (paginated list). */
|
|
178
|
+
export const SalesChannelListResponseSchema = z.object({
|
|
179
|
+
items: z.array(SalesChannelSummarySchema),
|
|
180
|
+
page: z.number().int().nonnegative(),
|
|
181
|
+
pageSize: z.number().int().positive(),
|
|
182
|
+
total: z.number().int().nonnegative(),
|
|
183
|
+
});
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// (4) Membership endpoints (bidirectional)
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
/** Channel-scoped entity types tracked by the M:N membership service. */
|
|
188
|
+
export const ChannelMemberEntityTypeSchema = z.enum([
|
|
189
|
+
'product',
|
|
190
|
+
'category',
|
|
191
|
+
'payment-method',
|
|
192
|
+
'delivery-method',
|
|
193
|
+
'organization',
|
|
194
|
+
'tax',
|
|
195
|
+
'customer',
|
|
196
|
+
'promotion',
|
|
197
|
+
'cms-page',
|
|
198
|
+
]);
|
|
199
|
+
/** `GET /api/v1/admin/sales-channels/{code}/{entityType}` — list members. */
|
|
200
|
+
export const ChannelMembershipListResponseSchema = z.object({
|
|
201
|
+
channels: z.array(SalesChannelSummarySchema),
|
|
202
|
+
});
|
|
203
|
+
/** `GET /api/v1/admin/{entityType}/{id}/sales-channels` — list channels of an entity. */
|
|
204
|
+
export const EntityMembershipListResponseSchema = z.object({
|
|
205
|
+
entityType: ChannelMemberEntityTypeSchema,
|
|
206
|
+
entityId: uuidSchema,
|
|
207
|
+
channels: z.array(SalesChannelSummarySchema),
|
|
208
|
+
});
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// (5) Storefront / public read-only
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
/**
|
|
213
|
+
* `GET /api/v1/storefront/sales-channel` — what the storefront app fetches
|
|
214
|
+
* on first paint to know its theme / language / currency.
|
|
215
|
+
*
|
|
216
|
+
* Deliberately drops `id`, `active`, `systemDefault`, and `version`
|
|
217
|
+
* (admin-only fields).
|
|
218
|
+
*/
|
|
219
|
+
export const PublicSalesChannelSchema = z.object({
|
|
220
|
+
code: SalesChannelCodeSchema,
|
|
221
|
+
name: SalesChannelNameSchema,
|
|
222
|
+
defaultLanguage: z.string(),
|
|
223
|
+
defaultCurrency: z.string(),
|
|
224
|
+
languages: z.array(z.string()),
|
|
225
|
+
currencies: z.array(z.string()),
|
|
226
|
+
themeCode: z.string().nullable(),
|
|
227
|
+
logoUrl: z.string().url().nullable(),
|
|
228
|
+
});
|
|
229
|
+
/** Response envelope of `GET /api/v1/storefront/sales-channel`. */
|
|
230
|
+
export const PublicSalesChannelResponseSchema = z.object({
|
|
231
|
+
data: PublicSalesChannelSchema,
|
|
232
|
+
});
|
|
233
|
+
/**
|
|
234
|
+
* **The platform no longer holds a list of storefront themes** — owner ruling
|
|
235
|
+
* D-199, implemented by `specs/102-storefront-theme-discovery/`.
|
|
236
|
+
*
|
|
237
|
+
* `STOREFRONT_THEME_CODES`, `StorefrontThemeCodeSchema`, `StorefrontThemeCode`,
|
|
238
|
+
* `DEFAULT_STOREFRONT_THEME_CODE` and `isStorefrontThemeCode` used to live here
|
|
239
|
+
* and are gone. A theme is a token set a **third party** may publish as an
|
|
240
|
+
* ordinary npm package, so no set this repository can compile is the whole set:
|
|
241
|
+
* the answer belongs to the storefront instance that has the packages
|
|
242
|
+
* installed, and it is generated in that instance's own tree
|
|
243
|
+
* (`storefront/lib/theme/`).
|
|
244
|
+
*
|
|
245
|
+
* The **write** schemas above are unchanged and must stay so. They have never
|
|
246
|
+
* used the enum: `themeCodeRe` is the whole validation, and a backend that
|
|
247
|
+
* refused a code it has never heard of would make the field unusable for
|
|
248
|
+
* exactly the deployments it exists for. `PublicSalesChannelSchema.themeCode`
|
|
249
|
+
* is likewise unchanged — the wire shape gains and loses nothing.
|
|
250
|
+
*
|
|
251
|
+
* What an unknown code does is the storefront's answer and is unchanged too:
|
|
252
|
+
* it renders the instance's default rather than blank, reports the code once
|
|
253
|
+
* per process, marks the document with `data-theme-requested`, never writes the
|
|
254
|
+
* value back and never guesses at a near match. See
|
|
255
|
+
* `specs/102-storefront-theme-discovery/contracts/theme-package.md` for what a
|
|
256
|
+
* theme author ships, and `contracts/instance-theme-registry.md` for how an
|
|
257
|
+
* instance discovers its own.
|
|
258
|
+
*/
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
// (6) Audit-action constants
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
/**
|
|
263
|
+
* Action strings written by `SalesChannelsService` / `SalesChannelMembershipService`
|
|
264
|
+
* through the existing `AuditLogService.record({ action, ... })`. They are
|
|
265
|
+
* free-form strings (the audit log uses `action: string`, not an enum)
|
|
266
|
+
* but every consumer should use these constants so a typo can't drift.
|
|
267
|
+
*/
|
|
268
|
+
export const SALES_CHANNEL_AUDIT_ACTIONS = {
|
|
269
|
+
IDENTITY_CHANGED: 'sales_channel.identity.changed',
|
|
270
|
+
MEMBERSHIP_CHANGED: 'sales_channel.membership.changed',
|
|
271
|
+
LIFECYCLE_CHANGED: 'sales_channel.lifecycle.changed',
|
|
272
|
+
};
|
|
273
|
+
export const SalesChannelAuditActionSchema = z.enum([
|
|
274
|
+
SALES_CHANNEL_AUDIT_ACTIONS.IDENTITY_CHANGED,
|
|
275
|
+
SALES_CHANNEL_AUDIT_ACTIONS.MEMBERSHIP_CHANGED,
|
|
276
|
+
SALES_CHANNEL_AUDIT_ACTIONS.LIFECYCLE_CHANGED,
|
|
277
|
+
]);
|
|
278
|
+
export const SalesChannelLifecycleOpSchema = z.enum([
|
|
279
|
+
'deactivated',
|
|
280
|
+
'activated',
|
|
281
|
+
'deleted',
|
|
282
|
+
'system-default-promoted',
|
|
283
|
+
]);
|
|
284
|
+
export const SalesChannelMembershipOpSchema = z.enum(['add', 'remove']);
|
|
285
|
+
//# sourceMappingURL=sales-channels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sales-channels.js","sourceRoot":"","sources":["../src/sales-channels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Why a listing came back empty, when "empty" and "nothing exists" are not the
|
|
4
|
+
* same statement (feature 087, owner decision of 2026-08-29).
|
|
5
|
+
*
|
|
6
|
+
* `customerFilterCond`'s `allowed-set` arm refuses **every** row of a
|
|
7
|
+
* `@CustomerScoped` table that carries no `organization_id`, because no row in
|
|
8
|
+
* such a table is inside a scoped actor's authority (FR-011). The refusal is
|
|
9
|
+
* correct. What is not correct is the silence: the client receives `[]`, which
|
|
10
|
+
* is indistinguishable from "there is nothing here", and an operator reading it
|
|
11
|
+
* concludes something false about the **data** rather than something true about
|
|
12
|
+
* their own reach.
|
|
13
|
+
*
|
|
14
|
+
* So the server says which of the two it meant. The notice is **derived** —
|
|
15
|
+
* the filter records that it emitted the refusing predicate, and the host's
|
|
16
|
+
* request hook puts the code on the response envelope — so no route sets a flag
|
|
17
|
+
* and no screen has to be remembered. It stops being emitted, everywhere at
|
|
18
|
+
* once and with no edit, on the day a table gains its column and the same arm
|
|
19
|
+
* starts granting.
|
|
20
|
+
*
|
|
21
|
+
* It is a *notice*, never an error: the response is a 200 with a truthful body.
|
|
22
|
+
*/
|
|
23
|
+
export declare const SCOPE_NOTICE_CODES: {
|
|
24
|
+
/**
|
|
25
|
+
* The records this surface lists carry no organization at all yet, so a
|
|
26
|
+
* viewer confined to a set of organizations can be shown none of them. The
|
|
27
|
+
* operator-facing sentences live in the `core` i18n bundle under
|
|
28
|
+
* `scopeNotice.organizationAttributionPending.*`.
|
|
29
|
+
*/
|
|
30
|
+
readonly ORGANIZATION_ATTRIBUTION_PENDING: "ORGANIZATION_ATTRIBUTION_PENDING";
|
|
31
|
+
};
|
|
32
|
+
export declare const scopeNoticeCodeSchema: z.ZodEnum<{
|
|
33
|
+
ORGANIZATION_ATTRIBUTION_PENDING: "ORGANIZATION_ATTRIBUTION_PENDING";
|
|
34
|
+
}>;
|
|
35
|
+
export type ScopeNoticeCode = z.infer<typeof scopeNoticeCodeSchema>;
|
|
36
|
+
/**
|
|
37
|
+
* The envelope slot the notice occupies: `meta.scopeNotice`, on any successful
|
|
38
|
+
* response. `meta` is the one place the three surfaces this covers could share
|
|
39
|
+
* — their bodies are `{ data, meta }`, `{ data }` and a bare page object — and
|
|
40
|
+
* the key is absent rather than null when there is nothing to say.
|
|
41
|
+
*/
|
|
42
|
+
export declare const scopeNoticeMetaSchema: z.ZodObject<{
|
|
43
|
+
scopeNotice: z.ZodOptional<z.ZodEnum<{
|
|
44
|
+
ORGANIZATION_ATTRIBUTION_PENDING: "ORGANIZATION_ATTRIBUTION_PENDING";
|
|
45
|
+
}>>;
|
|
46
|
+
}, z.core.$strip>;
|
|
47
|
+
export type ScopeNoticeMeta = z.infer<typeof scopeNoticeMetaSchema>;
|
|
48
|
+
/** The envelope shape a client reads the notice out of. */
|
|
49
|
+
export interface ScopeNoticeEnvelope {
|
|
50
|
+
readonly meta?: {
|
|
51
|
+
readonly scopeNotice?: ScopeNoticeCode;
|
|
52
|
+
} | undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Read the notice off any response body, or `null` when the body carries none.
|
|
56
|
+
* Written here rather than per client so that "what a notice looks like on the
|
|
57
|
+
* wire" has one definition on both sides of the boundary.
|
|
58
|
+
*/
|
|
59
|
+
export declare function scopeNoticeOf(response: unknown): ScopeNoticeCode | null;
|
|
60
|
+
//# sourceMappingURL=scope-notice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-notice.d.ts","sourceRoot":"","sources":["../src/scope-notice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;;;;OAKG;;CAEK,CAAC;AAEX,eAAO,MAAM,qBAAqB;;EAA+C,CAAC;AAClF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;iBAEhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,2DAA2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAA;KAAE,GAAG,SAAS,CAAC;CACxE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAMvE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Why a listing came back empty, when "empty" and "nothing exists" are not the
|
|
4
|
+
* same statement (feature 087, owner decision of 2026-08-29).
|
|
5
|
+
*
|
|
6
|
+
* `customerFilterCond`'s `allowed-set` arm refuses **every** row of a
|
|
7
|
+
* `@CustomerScoped` table that carries no `organization_id`, because no row in
|
|
8
|
+
* such a table is inside a scoped actor's authority (FR-011). The refusal is
|
|
9
|
+
* correct. What is not correct is the silence: the client receives `[]`, which
|
|
10
|
+
* is indistinguishable from "there is nothing here", and an operator reading it
|
|
11
|
+
* concludes something false about the **data** rather than something true about
|
|
12
|
+
* their own reach.
|
|
13
|
+
*
|
|
14
|
+
* So the server says which of the two it meant. The notice is **derived** —
|
|
15
|
+
* the filter records that it emitted the refusing predicate, and the host's
|
|
16
|
+
* request hook puts the code on the response envelope — so no route sets a flag
|
|
17
|
+
* and no screen has to be remembered. It stops being emitted, everywhere at
|
|
18
|
+
* once and with no edit, on the day a table gains its column and the same arm
|
|
19
|
+
* starts granting.
|
|
20
|
+
*
|
|
21
|
+
* It is a *notice*, never an error: the response is a 200 with a truthful body.
|
|
22
|
+
*/
|
|
23
|
+
export const SCOPE_NOTICE_CODES = {
|
|
24
|
+
/**
|
|
25
|
+
* The records this surface lists carry no organization at all yet, so a
|
|
26
|
+
* viewer confined to a set of organizations can be shown none of them. The
|
|
27
|
+
* operator-facing sentences live in the `core` i18n bundle under
|
|
28
|
+
* `scopeNotice.organizationAttributionPending.*`.
|
|
29
|
+
*/
|
|
30
|
+
ORGANIZATION_ATTRIBUTION_PENDING: 'ORGANIZATION_ATTRIBUTION_PENDING',
|
|
31
|
+
};
|
|
32
|
+
export const scopeNoticeCodeSchema = z.enum(['ORGANIZATION_ATTRIBUTION_PENDING']);
|
|
33
|
+
/**
|
|
34
|
+
* The envelope slot the notice occupies: `meta.scopeNotice`, on any successful
|
|
35
|
+
* response. `meta` is the one place the three surfaces this covers could share
|
|
36
|
+
* — their bodies are `{ data, meta }`, `{ data }` and a bare page object — and
|
|
37
|
+
* the key is absent rather than null when there is nothing to say.
|
|
38
|
+
*/
|
|
39
|
+
export const scopeNoticeMetaSchema = z.object({
|
|
40
|
+
scopeNotice: scopeNoticeCodeSchema.optional(),
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Read the notice off any response body, or `null` when the body carries none.
|
|
44
|
+
* Written here rather than per client so that "what a notice looks like on the
|
|
45
|
+
* wire" has one definition on both sides of the boundary.
|
|
46
|
+
*/
|
|
47
|
+
export function scopeNoticeOf(response) {
|
|
48
|
+
if (typeof response !== 'object' || response === null)
|
|
49
|
+
return null;
|
|
50
|
+
const meta = response.meta;
|
|
51
|
+
if (typeof meta !== 'object' || meta === null)
|
|
52
|
+
return null;
|
|
53
|
+
const code = meta.scopeNotice;
|
|
54
|
+
return scopeNoticeCodeSchema.safeParse(code).success ? code : null;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=scope-notice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-notice.js","sourceRoot":"","sources":["../src/scope-notice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC;;;;;OAKG;IACH,gCAAgC,EAAE,kCAAkC;CAC5D,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC;AAGlF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,WAAW,EAAE,qBAAqB,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC;AAQH;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,QAAiB;IAC7C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,IAAI,GAAI,QAA+B,CAAC,IAAI,CAAC;IACnD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,IAAI,GAAI,IAAkC,CAAC,WAAW,CAAC;IAC7D,OAAO,qBAAqB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,IAAwB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1F,CAAC"}
|