@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/settings.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
// Settings module — feature 004 contract surface.
|
|
2
|
+
// Holds three logical sections in one file (matching the convention used by
|
|
3
|
+
// every other module in @endora-commerce/contracts):
|
|
4
|
+
// (1) Setting value-type Zod registry.
|
|
5
|
+
// (2) Module manifest schemas — the cross-module registration contract that
|
|
6
|
+
// any backend module may use to declare its setting groups and settings
|
|
7
|
+
// (see specs/004-settings-module/contracts/settings-004.contract.md, A).
|
|
8
|
+
// (3) Admin HTTP request/response schemas (section C).
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// (1) Value types
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
export const SettingValueTypeSchema = z.enum([
|
|
14
|
+
'string',
|
|
15
|
+
'number',
|
|
16
|
+
'boolean',
|
|
17
|
+
'json',
|
|
18
|
+
'string_list',
|
|
19
|
+
'secret',
|
|
20
|
+
// Feature 058 — references a saved credential configuration by its code,
|
|
21
|
+
// constrained to one configuration type (see `configurationType` below).
|
|
22
|
+
'credential_ref',
|
|
23
|
+
]);
|
|
24
|
+
/**
|
|
25
|
+
* Returns the Zod schema corresponding to a setting's declared `valueType`.
|
|
26
|
+
* Callers supplying their own narrower schema to `SettingsService.get<T>()`
|
|
27
|
+
* still get the looser per-type validation through this helper at write time.
|
|
28
|
+
*
|
|
29
|
+
* `secret` accepts a plain string on write (the backend encrypts before
|
|
30
|
+
* persisting — feature 043 / FR-021); read endpoints never return it.
|
|
31
|
+
*/
|
|
32
|
+
export function valueSchemaForType(t) {
|
|
33
|
+
switch (t) {
|
|
34
|
+
case 'string':
|
|
35
|
+
return z.string();
|
|
36
|
+
case 'number':
|
|
37
|
+
return z.number();
|
|
38
|
+
case 'boolean':
|
|
39
|
+
return z.boolean();
|
|
40
|
+
case 'json':
|
|
41
|
+
return z.unknown();
|
|
42
|
+
case 'string_list':
|
|
43
|
+
return z.array(z.string());
|
|
44
|
+
case 'secret':
|
|
45
|
+
return z.string();
|
|
46
|
+
case 'credential_ref':
|
|
47
|
+
// The stored value is a configuration code (or '' when not configured).
|
|
48
|
+
return z.string();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// (2) Module manifest
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
const groupCodeRe = /^[a-z][a-z0-9_]{0,118}[a-z0-9]$/;
|
|
55
|
+
/**
|
|
56
|
+
* Setting code shape. Exported because feature 073's module activation block
|
|
57
|
+
* (`ModuleActivationSchema` in `modules.ts`) declares the code of an ordinary
|
|
58
|
+
* Setting row and must validate it identically.
|
|
59
|
+
*/
|
|
60
|
+
export const settingCodeRe = /^[a-z][a-z0-9_][a-z0-9_.]*[a-z0-9]$/;
|
|
61
|
+
const moduleCodeRe = /^[a-z][a-z0-9_]{0,118}[a-z0-9]$/;
|
|
62
|
+
export const GroupManifestEntrySchema = z.object({
|
|
63
|
+
code: z.string().regex(groupCodeRe),
|
|
64
|
+
name: z.string().min(1).max(200),
|
|
65
|
+
/**
|
|
66
|
+
* Sales-channel scope by `sales_channels.code`. Omit (or empty) to mean
|
|
67
|
+
* "applies to all channels" (R-5 / FR-004).
|
|
68
|
+
*/
|
|
69
|
+
salesChannelCodes: z.array(z.string()).optional(),
|
|
70
|
+
/**
|
|
71
|
+
* Reserved for the built-in `general` group only — other modules MUST NOT
|
|
72
|
+
* set this to `true`. The reconciler refuses such manifests at boot.
|
|
73
|
+
*/
|
|
74
|
+
isSystemProtected: z.boolean().optional(),
|
|
75
|
+
});
|
|
76
|
+
export const SettingManifestEntrySchema = z
|
|
77
|
+
.object({
|
|
78
|
+
code: z.string().regex(settingCodeRe),
|
|
79
|
+
name: z.string().min(1).max(200),
|
|
80
|
+
description: z.string().max(2000).optional(),
|
|
81
|
+
/** Defaults to `'general'` when omitted. */
|
|
82
|
+
groupCode: z.string().optional(),
|
|
83
|
+
valueType: SettingValueTypeSchema,
|
|
84
|
+
defaultValue: z.unknown(),
|
|
85
|
+
/**
|
|
86
|
+
* Stored `default_value`s this manifest's current `defaultValue`
|
|
87
|
+
* supersedes (feature 078, D-95.3).
|
|
88
|
+
*
|
|
89
|
+
* `ManifestReconciler` refuses a `defaultValue` change as breaking, because
|
|
90
|
+
* a silent default change alters behaviour for every deployment that never
|
|
91
|
+
* overrode it. Declaring the prior value is how a module says which change
|
|
92
|
+
* is intended and bounded: a stored default equal to one of these is
|
|
93
|
+
* updated to the new one at boot, and anything else still throws
|
|
94
|
+
* `BreakingChangeRejected`. Same shape, and the same self-healing argument,
|
|
95
|
+
* as the sanctioned `string` → `secret` valueType upgrade.
|
|
96
|
+
*/
|
|
97
|
+
previousDefaultValues: z.array(z.unknown()).optional(),
|
|
98
|
+
salesChannelCodes: z.array(z.string()).optional(),
|
|
99
|
+
/**
|
|
100
|
+
* Closed list of allowed values for a `string` setting. When present the
|
|
101
|
+
* setting behaves like an enum: the admin renders a dropdown instead of a
|
|
102
|
+
* free-text input and the backend rejects any value outside the list. Only
|
|
103
|
+
* valid for `valueType: 'string'`; the `defaultValue` must be one of the
|
|
104
|
+
* options.
|
|
105
|
+
*/
|
|
106
|
+
enumOptions: z.array(z.string().min(1)).min(1).optional(),
|
|
107
|
+
/**
|
|
108
|
+
* Feature 058 — the configuration type a `credential_ref` setting is
|
|
109
|
+
* constrained to (e.g. `'llm'`). REQUIRED when `valueType === 'credential_ref'`
|
|
110
|
+
* and forbidden otherwise. The admin renders a picker of matching
|
|
111
|
+
* configurations; the backend never interprets provider meaning.
|
|
112
|
+
*/
|
|
113
|
+
configurationType: z.string().min(1).optional(),
|
|
114
|
+
/**
|
|
115
|
+
* When true, the setting is registered and remains fully readable/writable
|
|
116
|
+
* through its owning module's dedicated surface (e.g. the PWA settings
|
|
117
|
+
* page), but is excluded from the generic admin Settings screen so it is
|
|
118
|
+
* managed in exactly one place. A group whose settings are all hidden does
|
|
119
|
+
* not appear in the generic Settings list at all.
|
|
120
|
+
*/
|
|
121
|
+
hidden: z.boolean().optional(),
|
|
122
|
+
})
|
|
123
|
+
.refine((s) => s.valueType !== 'secret' || s.defaultValue === '', {
|
|
124
|
+
message: "A 'secret' setting's defaultValue must be the empty string — manifests can never ship a real credential.",
|
|
125
|
+
path: ['defaultValue'],
|
|
126
|
+
})
|
|
127
|
+
.refine((s) => s.enumOptions === undefined || s.valueType === 'string', {
|
|
128
|
+
message: "enumOptions is only supported for valueType 'string'.",
|
|
129
|
+
path: ['enumOptions'],
|
|
130
|
+
})
|
|
131
|
+
.refine((s) => (s.valueType === 'credential_ref') === (s.configurationType !== undefined), {
|
|
132
|
+
message: "configurationType is required for valueType 'credential_ref' and forbidden otherwise.",
|
|
133
|
+
path: ['configurationType'],
|
|
134
|
+
})
|
|
135
|
+
.refine((s) => s.enumOptions === undefined ||
|
|
136
|
+
(typeof s.defaultValue === 'string' && s.enumOptions.includes(s.defaultValue)), {
|
|
137
|
+
message: 'An enum setting defaultValue must be one of its enumOptions.',
|
|
138
|
+
path: ['defaultValue'],
|
|
139
|
+
});
|
|
140
|
+
export const ModuleSettingsManifestSchema = z.object({
|
|
141
|
+
moduleCode: z.string().regex(moduleCodeRe),
|
|
142
|
+
groups: z.array(GroupManifestEntrySchema).default([]),
|
|
143
|
+
settings: z.array(SettingManifestEntrySchema).default([]),
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* Identity-with-validation helper for module authors. Modules export a single
|
|
147
|
+
* constant with `defineModuleSettingsManifest({...})`; this gives them full
|
|
148
|
+
* TypeScript inference and the reconciler can ingest the value directly.
|
|
149
|
+
*/
|
|
150
|
+
export function defineModuleSettingsManifest(m) {
|
|
151
|
+
return ModuleSettingsManifestSchema.parse(m);
|
|
152
|
+
}
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// (3) Admin HTTP
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
export const SettingValueByChannelSchema = z.object({
|
|
157
|
+
salesChannelId: z.uuid(),
|
|
158
|
+
salesChannelCode: z.string(),
|
|
159
|
+
value: z.unknown(),
|
|
160
|
+
/**
|
|
161
|
+
* Secret settings only (feature 043 / FR-021): `value` is redacted to
|
|
162
|
+
* `null` on every read; `isSet` tells the UI whether a value exists.
|
|
163
|
+
* Absent for non-secret settings.
|
|
164
|
+
*/
|
|
165
|
+
isSet: z.boolean().optional(),
|
|
166
|
+
updatedAt: z.iso.datetime(),
|
|
167
|
+
});
|
|
168
|
+
export const SettingDtoSchema = z.object({
|
|
169
|
+
id: z.uuid(),
|
|
170
|
+
code: z.string(),
|
|
171
|
+
name: z.string(),
|
|
172
|
+
description: z.string().nullable(),
|
|
173
|
+
valueType: SettingValueTypeSchema,
|
|
174
|
+
ownerModule: z.string(),
|
|
175
|
+
salesChannelCodes: z.array(z.string()),
|
|
176
|
+
/**
|
|
177
|
+
* Closed list of allowed values for an enum-style `string` setting (manifest
|
|
178
|
+
* `enumOptions`). Empty/absent for ordinary free-text settings; when present
|
|
179
|
+
* the admin renders a dropdown bound to these values.
|
|
180
|
+
*/
|
|
181
|
+
enumOptions: z.array(z.string()).nullish(),
|
|
182
|
+
/**
|
|
183
|
+
* Feature 058 — for a `credential_ref` setting, the configuration type the
|
|
184
|
+
* reference is constrained to (e.g. `'llm'`); the admin filters the config
|
|
185
|
+
* picker by this. Null/absent for every other value type.
|
|
186
|
+
*/
|
|
187
|
+
configurationType: z.string().nullish(),
|
|
188
|
+
/**
|
|
189
|
+
* Manifest-declared default value (immutable; surfaces in `defaultValue`).
|
|
190
|
+
*/
|
|
191
|
+
defaultValue: z.unknown(),
|
|
192
|
+
/**
|
|
193
|
+
* Platform-wide global override the admin has set, or `null` when the
|
|
194
|
+
* admin has not customised it. Resolver chain when reading a value:
|
|
195
|
+
* per-channel SettingValue row → globalValue (when non-null) → defaultValue.
|
|
196
|
+
* "All channels" admin writes update this field only and leave per-channel
|
|
197
|
+
* rows untouched.
|
|
198
|
+
*/
|
|
199
|
+
globalValue: z.unknown().nullable(),
|
|
200
|
+
/**
|
|
201
|
+
* Secret settings only (feature 043 / FR-021): `defaultValue` and
|
|
202
|
+
* `globalValue` are redacted to `null` on every read; this flag tells the
|
|
203
|
+
* UI whether a global override exists. Absent for non-secret settings.
|
|
204
|
+
*/
|
|
205
|
+
globalValueIsSet: z.boolean().optional(),
|
|
206
|
+
valuesByChannel: z.array(SettingValueByChannelSchema),
|
|
207
|
+
/**
|
|
208
|
+
* Server-computed effective version (= `max(setting.updatedAt,
|
|
209
|
+
* max(values.updatedAt))`). Echo back as `expectedVersion` on PUT
|
|
210
|
+
* /:code/value to detect concurrent edits — matches the ETag header
|
|
211
|
+
* returned by the detail endpoint.
|
|
212
|
+
*/
|
|
213
|
+
version: z.iso.datetime(),
|
|
214
|
+
/**
|
|
215
|
+
* Feature 073 — `false` when the owning module is not effectively present.
|
|
216
|
+
* The value is still read (off is not uninstall: the stored configuration
|
|
217
|
+
* survives), but every write against it is refused (FR-033). Classified per
|
|
218
|
+
* setting rather than per group because the module's own activation control
|
|
219
|
+
* stays writable while it is off, so a group-level filter would either hide
|
|
220
|
+
* the control or render the whole group.
|
|
221
|
+
*/
|
|
222
|
+
editable: z.boolean().optional(),
|
|
223
|
+
/**
|
|
224
|
+
* Feature 073 — this setting **is** its module's activation control: the
|
|
225
|
+
* single exception that stays writable while the module is off, and the one
|
|
226
|
+
* setting the ordinary write path refuses (the audited Command owns it).
|
|
227
|
+
*/
|
|
228
|
+
activationControl: z.boolean().optional(),
|
|
229
|
+
});
|
|
230
|
+
export const SettingGroupDtoSchema = z.object({
|
|
231
|
+
id: z.uuid(),
|
|
232
|
+
code: z.string(),
|
|
233
|
+
name: z.string(),
|
|
234
|
+
isSystemProtected: z.boolean(),
|
|
235
|
+
ownerModule: z.string(),
|
|
236
|
+
salesChannelCodes: z.array(z.string()),
|
|
237
|
+
settings: z.array(SettingDtoSchema),
|
|
238
|
+
});
|
|
239
|
+
export const SettingsListResponseSchema = z.object({
|
|
240
|
+
groups: z.array(SettingGroupDtoSchema),
|
|
241
|
+
});
|
|
242
|
+
export const SettingsListQuerySchema = z.object({
|
|
243
|
+
groupCode: z.string().optional(),
|
|
244
|
+
});
|
|
245
|
+
export const SetValueAllRequestSchema = z.object({
|
|
246
|
+
scope: z.literal('all'),
|
|
247
|
+
value: z.unknown(),
|
|
248
|
+
});
|
|
249
|
+
export const SetValueSubsetRequestSchema = z.object({
|
|
250
|
+
scope: z.literal('subset'),
|
|
251
|
+
salesChannelCodes: z.array(z.string()).min(1),
|
|
252
|
+
value: z.unknown(),
|
|
253
|
+
});
|
|
254
|
+
export const SetValueRequestSchema = z.discriminatedUnion('scope', [
|
|
255
|
+
SetValueAllRequestSchema,
|
|
256
|
+
SetValueSubsetRequestSchema,
|
|
257
|
+
]);
|
|
258
|
+
export const ResetValueQuerySchema = z.object({
|
|
259
|
+
/** Comma-separated list; omit to reset for every channel. */
|
|
260
|
+
salesChannelCodes: z.string().optional(),
|
|
261
|
+
});
|
|
262
|
+
export const GroupCreateRequestSchema = z.object({
|
|
263
|
+
code: z.string().regex(groupCodeRe),
|
|
264
|
+
name: z.string().min(1).max(200),
|
|
265
|
+
salesChannelCodes: z.array(z.string()).optional(),
|
|
266
|
+
});
|
|
267
|
+
export const GroupUpdateRequestSchema = z.object({
|
|
268
|
+
name: z.string().min(1).max(200).optional(),
|
|
269
|
+
salesChannelCodes: z.array(z.string()).optional(),
|
|
270
|
+
});
|
|
271
|
+
export const SettingDetailResponseSchema = SettingDtoSchema;
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
// (4) Storefront shop-information surface
|
|
274
|
+
// ---------------------------------------------------------------------------
|
|
275
|
+
/**
|
|
276
|
+
* Public shop / company contact information resolved for the active sales
|
|
277
|
+
* channel. Backs the storefront footer, the 404 "need help?" block and the
|
|
278
|
+
* contact form. Every field is a string; an unset (or not-yet-registered)
|
|
279
|
+
* setting resolves to an empty string so the storefront can decide what to
|
|
280
|
+
* render. The contact-form recipient list is intentionally omitted — it is
|
|
281
|
+
* an internal routing concern, not public information.
|
|
282
|
+
*/
|
|
283
|
+
export const ShopInfoSchema = z.object({
|
|
284
|
+
name: z.string(),
|
|
285
|
+
address: z.string(),
|
|
286
|
+
contactEmail: z.string(),
|
|
287
|
+
supportEmail: z.string(),
|
|
288
|
+
phone: z.string(),
|
|
289
|
+
});
|
|
290
|
+
export const ShopInfoResponseSchema = z.object({ data: ShopInfoSchema });
|
|
291
|
+
// ---------------------------------------------------------------------------
|
|
292
|
+
// (5) Cache administration (maintenance)
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
/**
|
|
295
|
+
* A clearable cache namespace surfaced in the admin "Clear cache" page. `key`
|
|
296
|
+
* is the stable identifier the client sends back to clear it; `label` and
|
|
297
|
+
* `description` are human-readable (English defaults — the admin localises via
|
|
298
|
+
* the `settings.cache.namespace.<key>.*` i18n keys).
|
|
299
|
+
*/
|
|
300
|
+
export const CacheNamespaceDtoSchema = z.object({
|
|
301
|
+
key: z.string(),
|
|
302
|
+
label: z.string(),
|
|
303
|
+
description: z.string(),
|
|
304
|
+
});
|
|
305
|
+
export const CacheNamespacesResponseSchema = z.object({
|
|
306
|
+
data: z.array(CacheNamespaceDtoSchema),
|
|
307
|
+
/** False when no Redis cache is wired (clearing is a no-op). */
|
|
308
|
+
cacheEnabled: z.boolean(),
|
|
309
|
+
});
|
|
310
|
+
export const ClearCacheRequestSchema = z.object({
|
|
311
|
+
/** Namespace keys to clear, or the literal `"all"` for every namespace. */
|
|
312
|
+
namespaces: z.union([z.literal('all'), z.array(z.string()).min(1)]),
|
|
313
|
+
});
|
|
314
|
+
export const ClearedCacheNamespaceSchema = z.object({
|
|
315
|
+
key: z.string(),
|
|
316
|
+
deletedKeysCount: z.number().int().nonnegative(),
|
|
317
|
+
});
|
|
318
|
+
export const ClearCacheResultSchema = z.object({
|
|
319
|
+
data: z.object({
|
|
320
|
+
cleared: z.array(ClearedCacheNamespaceSchema),
|
|
321
|
+
totalDeletedKeys: z.number().int().nonnegative(),
|
|
322
|
+
}),
|
|
323
|
+
});
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
// (6) Storefront home-page configuration
|
|
326
|
+
// ---------------------------------------------------------------------------
|
|
327
|
+
/**
|
|
328
|
+
* Resolved storefront home-page configuration for the active sales channel.
|
|
329
|
+
* `cmsPageSlug` is the CMS page slug an operator chose as the home page, or
|
|
330
|
+
* null when none is configured (the storefront then renders its built-in
|
|
331
|
+
* landing page).
|
|
332
|
+
*/
|
|
333
|
+
export const HomepageConfigSchema = z.object({
|
|
334
|
+
cmsPageSlug: z.string().nullable(),
|
|
335
|
+
});
|
|
336
|
+
export const HomepageConfigResponseSchema = z.object({ data: HomepageConfigSchema });
|
|
337
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shipments` module contracts — the in-process port surface (feature 075,
|
|
3
|
+
* Phase P).
|
|
4
|
+
*
|
|
5
|
+
* One inbound site, and it is the delivery-side twin of the one `payments`
|
|
6
|
+
* published in wave 1: the order-confirmation e-mail renders a shipping line,
|
|
7
|
+
* and `orders` reaches this module's renderer registry for it.
|
|
8
|
+
*
|
|
9
|
+
* Plain TypeScript rather than Zod: this describes an in-process call. The
|
|
10
|
+
* module's HTTP shapes live in `shipping-methods.ts`, which is
|
|
11
|
+
* `delivery_methods`' contracts file and covers the shipment record too.
|
|
12
|
+
*/
|
|
13
|
+
import type { ShipmentStatus } from './shipping-methods.js';
|
|
14
|
+
/** What the order-confirmation e-mail knows about the shipping method. */
|
|
15
|
+
export interface ShippingEmailContext {
|
|
16
|
+
/** Resolved display name of the shipping method. */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Flat surcharge (`price`) applied for this method, in the order currency. */
|
|
19
|
+
cost: number;
|
|
20
|
+
currency: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Container name: `shippingEmailRendererPort`. Owner: `shipments`.
|
|
24
|
+
*
|
|
25
|
+
* A shipping adapter may register a custom renderer under a key (feature 035,
|
|
26
|
+
* FR-016/FR-017); when none is registered the platform default is used, so the
|
|
27
|
+
* shipping section always renders.
|
|
28
|
+
*
|
|
29
|
+
* `orders` reaches the resolver today and then calls the function it gets
|
|
30
|
+
* back. The port collapses those two steps for the reason its payment twin
|
|
31
|
+
* gives: a consumer that resolved a renderer and got `undefined` would have to
|
|
32
|
+
* hold a copy of the default text, and two copies of a default are how a
|
|
33
|
+
* default stops being one.
|
|
34
|
+
*
|
|
35
|
+
* Bodies are plain text (see `EmailMailerSendInput.text`), so a renderer is a
|
|
36
|
+
* `(ctx) => string` builder rather than a component.
|
|
37
|
+
*
|
|
38
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
39
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`, so nothing
|
|
40
|
+
* half-executes. Whether `shipments` has an off state at all is its manifest's
|
|
41
|
+
* `activation` to say, not this line's: a module declaring
|
|
42
|
+
* `nonDeactivatable` never enters one.
|
|
43
|
+
*/
|
|
44
|
+
export interface ShippingEmailRendererPort {
|
|
45
|
+
render(rendererKey: string | null, ctx: ShippingEmailContext): string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Container name: `shipmentUsagePort`. Owner: `shipments`.
|
|
49
|
+
*
|
|
50
|
+
* "Has this delivery method ever shipped anything?" — the one question
|
|
51
|
+
* `delivery_methods` has to ask before it deletes a method row (feature 035,
|
|
52
|
+
* FR-003; feature 077, D-87).
|
|
53
|
+
*
|
|
54
|
+
* It asked it in raw SQL until feature 075 drained the shard:
|
|
55
|
+
* `select count(*) from "shipments" where "delivery_method_id" = ?`, inside the
|
|
56
|
+
* delete Command's own transaction. The statement named no import specifier, so
|
|
57
|
+
* the boundary it crossed compiled and returned rows.
|
|
58
|
+
*
|
|
59
|
+
* **`shipments.delivery_method_id` carries no foreign key** — the table was
|
|
60
|
+
* created without one — so this count is the only thing standing between a
|
|
61
|
+
* delete and permanently orphaned shipment history. That is why the answer is
|
|
62
|
+
* asked of the owner rather than approximated, and why the caller refuses the
|
|
63
|
+
* delete when it cannot get one.
|
|
64
|
+
*
|
|
65
|
+
* The count runs on this module's own `EntityManager`, so it is outside any
|
|
66
|
+
* transaction the caller has open. That costs nothing here: `shipments` is a
|
|
67
|
+
* table the delete transaction never writes, so there is no write of its own
|
|
68
|
+
* for the read to be blind to, and the race a cross-module read cannot close —
|
|
69
|
+
* a shipment created between the count and the commit — was equally open to the
|
|
70
|
+
* in-transaction statement this replaced, which took no lock either.
|
|
71
|
+
*
|
|
72
|
+
* **Owner off:** `delivery_methods` decides this module's presence *before* it
|
|
73
|
+
* resolves the port and refuses the delete with a sentence naming this module,
|
|
74
|
+
* rather than resolving a gate and catching it — see its manifest's
|
|
75
|
+
* `nonBindingDependencies` entry. The edge is non-binding because `shipments`
|
|
76
|
+
* declares `delivery_methods`, so declaring it back closes a cycle, and
|
|
77
|
+
* acknowledging it would make `shipments` unswitchable for as long as delivery
|
|
78
|
+
* methods are present.
|
|
79
|
+
*/
|
|
80
|
+
export interface ShipmentUsagePort {
|
|
81
|
+
/** How many shipment rows — of any status — reference this delivery method. */
|
|
82
|
+
countForDeliveryMethod(deliveryMethodId: string): Promise<number>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* One shipment attempt as it crosses a module boundary — a plain shape, never
|
|
86
|
+
* the ORM entity (FR-011).
|
|
87
|
+
*
|
|
88
|
+
* `providerDetails` is the carrier envelope the adapter deposited. It stays
|
|
89
|
+
* opaque here for the reason the order's `shippingAdapterData` does: only the
|
|
90
|
+
* adapter that wrote it knows its shape, and the reader that needs it is that
|
|
91
|
+
* same adapter reading back what it wrote.
|
|
92
|
+
*/
|
|
93
|
+
export interface ShipmentRecord {
|
|
94
|
+
id: string;
|
|
95
|
+
orderId: string;
|
|
96
|
+
deliveryMethodId: string;
|
|
97
|
+
status: ShipmentStatus;
|
|
98
|
+
externalReference: string | null;
|
|
99
|
+
providerDetails: Record<string, unknown> | null;
|
|
100
|
+
failureReason: string | null;
|
|
101
|
+
attemptNo: number;
|
|
102
|
+
createdAt: Date;
|
|
103
|
+
updatedAt: Date;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Container name: `shipmentReadPort`. Owner: `shipments`.
|
|
107
|
+
*
|
|
108
|
+
* "What state is this shipment in, and which carrier reference does it carry?"
|
|
109
|
+
* — the question a carrier module asks twice: when an inbound webhook names
|
|
110
|
+
* only the carrier's own id, and when an admin asks for the label of an
|
|
111
|
+
* attempt it opened.
|
|
112
|
+
*
|
|
113
|
+
* Published for feature 068. `inpost` answered both by loading this module's
|
|
114
|
+
* `Shipment` entity directly, which its cross-module ledger recorded as debt
|
|
115
|
+
* with exactly this port as the retiring condition. It is a **read**, so it is
|
|
116
|
+
* a method here and not an `EntityManager`-taking apply port: handing a read a
|
|
117
|
+
* transaction handle re-opens a write seam to serve it.
|
|
118
|
+
*
|
|
119
|
+
* `findByExternalReference` is not a duplicate of `findById`. A carrier that
|
|
120
|
+
* signs nothing and names only its own id has to be correlated, and until the
|
|
121
|
+
* first `receive_shipment` lands, `externalReference` is where the adapter put
|
|
122
|
+
* that id — after it, a tracking number replaces it. The lookup is an indexed
|
|
123
|
+
* equality read, and the caller is expected to have its own correlation table
|
|
124
|
+
* for everything after the first event.
|
|
125
|
+
*
|
|
126
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
127
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`. That is the
|
|
128
|
+
* right answer for both callers: a label for a shipment the platform will not
|
|
129
|
+
* read, and a carrier callback the platform cannot apply, are both operations
|
|
130
|
+
* that must not half-execute.
|
|
131
|
+
*/
|
|
132
|
+
export interface ShipmentReadPort {
|
|
133
|
+
findById(id: string): Promise<ShipmentRecord | null>;
|
|
134
|
+
/**
|
|
135
|
+
* The most recent attempt carrying `reference`, or null. Newest first, so a
|
|
136
|
+
* reference re-used across attempts answers with the live one.
|
|
137
|
+
*/
|
|
138
|
+
findByExternalReference(reference: string): Promise<ShipmentRecord | null>;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=shipments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shipments.d.ts","sourceRoot":"","sources":["../src/shipments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAAC;CACvE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,sBAAsB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnE;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrD;;;OAGG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC5E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shipments` module contracts — the in-process port surface (feature 075,
|
|
3
|
+
* Phase P).
|
|
4
|
+
*
|
|
5
|
+
* One inbound site, and it is the delivery-side twin of the one `payments`
|
|
6
|
+
* published in wave 1: the order-confirmation e-mail renders a shipping line,
|
|
7
|
+
* and `orders` reaches this module's renderer registry for it.
|
|
8
|
+
*
|
|
9
|
+
* Plain TypeScript rather than Zod: this describes an in-process call. The
|
|
10
|
+
* module's HTTP shapes live in `shipping-methods.ts`, which is
|
|
11
|
+
* `delivery_methods`' contracts file and covers the shipment record too.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=shipments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shipments.js","sourceRoot":"","sources":["../src/shipments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|