@voyantjs/products 0.95.0 → 0.96.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/dist/content-shape.d.ts +2 -216
- package/dist/content-shape.d.ts.map +1 -1
- package/dist/content-shape.js +2 -140
- package/package.json +9 -8
package/dist/content-shape.d.ts
CHANGED
|
@@ -1,220 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Products content shape — the rich detail-page content shape returned
|
|
3
|
-
* by `getContent` and stored in `products_sourced_content.payload`.
|
|
4
|
-
*
|
|
5
|
-
* Schema versions are managed by this module: the constant
|
|
6
|
-
* `PRODUCTS_CONTENT_SCHEMA_VERSION` stamps every cache write; reads
|
|
7
|
-
* skip rows with an unrecognized version (treated as cache miss). Bump
|
|
8
|
-
* the version when the shape changes; old cache rows are then evicted
|
|
9
|
-
* by a single `DELETE WHERE content_schema_version != current`.
|
|
10
|
-
*
|
|
11
|
-
* Pure types + Zod + a vertical-specific `mergeOverlaysIntoProductContent`
|
|
12
|
-
* that wraps the catalog plane's content-shape-aware merger with this
|
|
13
|
-
* vertical's validator.
|
|
14
|
-
*
|
|
15
|
-
* See `docs/architecture/catalog-sourced-content.md` §3.2, §3.5.4, §3.6.
|
|
16
|
-
*/
|
|
17
1
|
import { type ContentOverlay, type MergeOverlaysOptions } from "@voyantjs/catalog";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
* The current content-schema version. Stamped on every cache write.
|
|
21
|
-
* Bump when the `productContentSchema` shape changes incompatibly.
|
|
22
|
-
*/
|
|
23
|
-
export declare const PRODUCTS_CONTENT_SCHEMA_VERSION = "products/v1";
|
|
24
|
-
/**
|
|
25
|
-
* Top-level product summary fields. Maps loosely to the owned `products`
|
|
26
|
-
* table — the read service synthesizes from indexed projection + overlay
|
|
27
|
-
* for thin adapters, or stores adapter-served data for rich ones.
|
|
28
|
-
*/
|
|
29
|
-
export declare const productSummarySchema: z.ZodObject<{
|
|
30
|
-
id: z.ZodString;
|
|
31
|
-
name: z.ZodString;
|
|
32
|
-
status: z.ZodOptional<z.ZodString>;
|
|
33
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
|
-
inclusions_html: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
35
|
-
exclusions_html: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
36
|
-
terms_html: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
37
|
-
contract_template_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
38
|
-
contractTemplateId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
39
|
-
highlights: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
40
|
-
hero_image_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
41
|
-
duration_days: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
42
|
-
start_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
43
|
-
end_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
44
|
-
sell_currency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
45
|
-
supplier: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
46
|
-
country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
47
|
-
departure_city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
48
|
-
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
49
|
-
}, z.core.$strip>;
|
|
50
|
-
export declare const productMediaItemSchema: z.ZodObject<{
|
|
51
|
-
url: z.ZodString;
|
|
52
|
-
type: z.ZodDefault<z.ZodEnum<{
|
|
53
|
-
image: "image";
|
|
54
|
-
video: "video";
|
|
55
|
-
document: "document";
|
|
56
|
-
}>>;
|
|
57
|
-
caption: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
58
|
-
alt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
59
|
-
}, z.core.$strip>;
|
|
60
|
-
export declare const productOptionUnitSchema: z.ZodObject<{
|
|
61
|
-
id: z.ZodString;
|
|
62
|
-
type: z.ZodString;
|
|
63
|
-
label: z.ZodOptional<z.ZodString>;
|
|
64
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
|
-
capacity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
66
|
-
}, z.core.$strip>;
|
|
67
|
-
export declare const productOptionSchema: z.ZodObject<{
|
|
68
|
-
id: z.ZodString;
|
|
69
|
-
name: z.ZodString;
|
|
70
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
71
|
-
units: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
72
|
-
id: z.ZodString;
|
|
73
|
-
type: z.ZodString;
|
|
74
|
-
label: z.ZodOptional<z.ZodString>;
|
|
75
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
76
|
-
capacity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
77
|
-
}, z.core.$strip>>>>;
|
|
78
|
-
inclusions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
79
|
-
}, z.core.$strip>;
|
|
80
|
-
export declare const productDaySchema: z.ZodObject<{
|
|
81
|
-
day_number: z.ZodNumber;
|
|
82
|
-
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
83
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
84
|
-
location: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
85
|
-
hero_image_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
|
-
services: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
87
|
-
}, z.core.$strip>;
|
|
88
|
-
export declare const productPolicySchema: z.ZodObject<{
|
|
89
|
-
kind: z.ZodEnum<{
|
|
90
|
-
supplier_notes: "supplier_notes";
|
|
91
|
-
payment: "payment";
|
|
92
|
-
cancellation: "cancellation";
|
|
93
|
-
requirements: "requirements";
|
|
94
|
-
}>;
|
|
95
|
-
body: z.ZodString;
|
|
96
|
-
rules: z.ZodOptional<z.ZodUnknown>;
|
|
97
|
-
}, z.core.$strip>;
|
|
98
|
-
/**
|
|
99
|
-
* A single bookable departure / time slot — the "when" surface of the
|
|
100
|
-
* product. ISO 8601 timestamps for `starts_at` / `ends_at` so locale
|
|
101
|
-
* formatting happens at render time, never in the cache.
|
|
102
|
-
*
|
|
103
|
-
* Owned products derive these from `availability_slots`; sourced
|
|
104
|
-
* adapters return them via `getContent`. Empty array = "always-on"
|
|
105
|
-
* product (e.g. an evergreen transfer service) or one whose schedule
|
|
106
|
-
* is on-request.
|
|
107
|
-
*/
|
|
108
|
-
export declare const productDepartureSchema: z.ZodObject<{
|
|
109
|
-
id: z.ZodString;
|
|
110
|
-
starts_at: z.ZodString;
|
|
111
|
-
ends_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
112
|
-
status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
113
|
-
capacity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
114
|
-
remaining: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
115
|
-
lowest_price_cents: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
116
|
-
currency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
117
|
-
note: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
118
|
-
}, z.core.$strip>;
|
|
119
|
-
/**
|
|
120
|
-
* The product content payload. Cache writes validate against this
|
|
121
|
-
* schema; cache reads skip rows that don't validate (treated as cache
|
|
122
|
-
* miss to surface adapter integration bugs without corrupting reads).
|
|
123
|
-
*/
|
|
124
|
-
export declare const productContentSchema: z.ZodObject<{
|
|
125
|
-
product: z.ZodObject<{
|
|
126
|
-
id: z.ZodString;
|
|
127
|
-
name: z.ZodString;
|
|
128
|
-
status: z.ZodOptional<z.ZodString>;
|
|
129
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
130
|
-
inclusions_html: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
131
|
-
exclusions_html: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
132
|
-
terms_html: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
133
|
-
contract_template_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
134
|
-
contractTemplateId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
|
-
highlights: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
136
|
-
hero_image_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
137
|
-
duration_days: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
138
|
-
start_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
139
|
-
end_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
140
|
-
sell_currency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
141
|
-
supplier: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
142
|
-
country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
143
|
-
departure_city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
144
|
-
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
145
|
-
}, z.core.$strip>;
|
|
146
|
-
options: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
147
|
-
id: z.ZodString;
|
|
148
|
-
name: z.ZodString;
|
|
149
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
150
|
-
units: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
151
|
-
id: z.ZodString;
|
|
152
|
-
type: z.ZodString;
|
|
153
|
-
label: z.ZodOptional<z.ZodString>;
|
|
154
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
155
|
-
capacity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
156
|
-
}, z.core.$strip>>>>;
|
|
157
|
-
inclusions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
158
|
-
}, z.core.$strip>>>;
|
|
159
|
-
days: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
160
|
-
day_number: z.ZodNumber;
|
|
161
|
-
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
162
|
-
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
163
|
-
location: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
164
|
-
hero_image_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
165
|
-
services: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
166
|
-
}, z.core.$strip>>>;
|
|
167
|
-
media: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
168
|
-
url: z.ZodString;
|
|
169
|
-
type: z.ZodDefault<z.ZodEnum<{
|
|
170
|
-
image: "image";
|
|
171
|
-
video: "video";
|
|
172
|
-
document: "document";
|
|
173
|
-
}>>;
|
|
174
|
-
caption: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
175
|
-
alt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
176
|
-
}, z.core.$strip>>>;
|
|
177
|
-
policies: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
178
|
-
kind: z.ZodEnum<{
|
|
179
|
-
supplier_notes: "supplier_notes";
|
|
180
|
-
payment: "payment";
|
|
181
|
-
cancellation: "cancellation";
|
|
182
|
-
requirements: "requirements";
|
|
183
|
-
}>;
|
|
184
|
-
body: z.ZodString;
|
|
185
|
-
rules: z.ZodOptional<z.ZodUnknown>;
|
|
186
|
-
}, z.core.$strip>>>;
|
|
187
|
-
departures: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
188
|
-
id: z.ZodString;
|
|
189
|
-
starts_at: z.ZodString;
|
|
190
|
-
ends_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
191
|
-
status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
192
|
-
capacity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
193
|
-
remaining: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
194
|
-
lowest_price_cents: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
195
|
-
currency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
196
|
-
note: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
197
|
-
}, z.core.$strip>>>;
|
|
198
|
-
}, z.core.$strip>;
|
|
199
|
-
export type ProductContent = z.infer<typeof productContentSchema>;
|
|
200
|
-
export type ProductSummary = z.infer<typeof productSummarySchema>;
|
|
201
|
-
export type ProductMediaItem = z.infer<typeof productMediaItemSchema>;
|
|
202
|
-
export type ProductOption = z.infer<typeof productOptionSchema>;
|
|
203
|
-
export type ProductDeparture = z.infer<typeof productDepartureSchema>;
|
|
204
|
-
export type ProductDay = z.infer<typeof productDaySchema>;
|
|
205
|
-
export type ProductPolicy = z.infer<typeof productPolicySchema>;
|
|
206
|
-
/**
|
|
207
|
-
* Validate a `ProductContent` payload. Returns the parsed result on
|
|
208
|
-
* success or a structured failure on rejection. Used by the cache write
|
|
209
|
-
* path and by `mergeOverlaysIntoProductContent` to gate overlay merges.
|
|
210
|
-
*/
|
|
211
|
-
export declare function validateProductContent(payload: unknown): {
|
|
212
|
-
valid: true;
|
|
213
|
-
content: ProductContent;
|
|
214
|
-
} | {
|
|
215
|
-
valid: false;
|
|
216
|
-
reason: string;
|
|
217
|
-
};
|
|
2
|
+
import { type ProductContent } from "@voyantjs/products-contracts/content-shape";
|
|
3
|
+
export { PRODUCTS_CONTENT_SCHEMA_VERSION, type ProductContent, type ProductDay, type ProductDeparture, type ProductMediaItem, type ProductOption, type ProductPolicy, type ProductSummary, productContentSchema, productDaySchema, productDepartureSchema, productMediaItemSchema, productOptionSchema, productOptionUnitSchema, productPolicySchema, productSummarySchema, validateProductContent, } from "@voyantjs/products-contracts/content-shape";
|
|
218
4
|
/**
|
|
219
5
|
* Apply a list of editorial overlays to a product content payload via
|
|
220
6
|
* RFC 6901 JSON pointers. Validates the merged result against the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-shape.d.ts","sourceRoot":"","sources":["../src/content-shape.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"content-shape.d.ts","sourceRoot":"","sources":["../src/content-shape.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAE1B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,4CAA4C,CAAA;AAEnD,OAAO,EACL,+BAA+B,EAC/B,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,4CAA4C,CAAA;AAEnD;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,EACvC,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,CAAM,GACzD,cAAc,CAchB"}
|
package/dist/content-shape.js
CHANGED
|
@@ -1,144 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Products content shape — the rich detail-page content shape returned
|
|
3
|
-
* by `getContent` and stored in `products_sourced_content.payload`.
|
|
4
|
-
*
|
|
5
|
-
* Schema versions are managed by this module: the constant
|
|
6
|
-
* `PRODUCTS_CONTENT_SCHEMA_VERSION` stamps every cache write; reads
|
|
7
|
-
* skip rows with an unrecognized version (treated as cache miss). Bump
|
|
8
|
-
* the version when the shape changes; old cache rows are then evicted
|
|
9
|
-
* by a single `DELETE WHERE content_schema_version != current`.
|
|
10
|
-
*
|
|
11
|
-
* Pure types + Zod + a vertical-specific `mergeOverlaysIntoProductContent`
|
|
12
|
-
* that wraps the catalog plane's content-shape-aware merger with this
|
|
13
|
-
* vertical's validator.
|
|
14
|
-
*
|
|
15
|
-
* See `docs/architecture/catalog-sourced-content.md` §3.2, §3.5.4, §3.6.
|
|
16
|
-
*/
|
|
17
1
|
import { mergeOverlaysIntoContent, } from "@voyantjs/catalog";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
* The current content-schema version. Stamped on every cache write.
|
|
21
|
-
* Bump when the `productContentSchema` shape changes incompatibly.
|
|
22
|
-
*/
|
|
23
|
-
export const PRODUCTS_CONTENT_SCHEMA_VERSION = "products/v1";
|
|
24
|
-
/**
|
|
25
|
-
* Top-level product summary fields. Maps loosely to the owned `products`
|
|
26
|
-
* table — the read service synthesizes from indexed projection + overlay
|
|
27
|
-
* for thin adapters, or stores adapter-served data for rich ones.
|
|
28
|
-
*/
|
|
29
|
-
export const productSummarySchema = z.object({
|
|
30
|
-
id: z.string(),
|
|
31
|
-
name: z.string(),
|
|
32
|
-
status: z.string().optional(),
|
|
33
|
-
description: z.string().nullable().optional(),
|
|
34
|
-
inclusions_html: z.string().nullable().optional(),
|
|
35
|
-
exclusions_html: z.string().nullable().optional(),
|
|
36
|
-
terms_html: z.string().nullable().optional(),
|
|
37
|
-
contract_template_id: z.string().nullable().optional(),
|
|
38
|
-
contractTemplateId: z.string().nullable().optional(),
|
|
39
|
-
highlights: z.array(z.string()).optional(),
|
|
40
|
-
hero_image_url: z.string().nullable().optional(),
|
|
41
|
-
duration_days: z.number().int().nonnegative().nullable().optional(),
|
|
42
|
-
start_date: z.string().nullable().optional(),
|
|
43
|
-
end_date: z.string().nullable().optional(),
|
|
44
|
-
sell_currency: z.string().nullable().optional(),
|
|
45
|
-
supplier: z.string().nullable().optional(),
|
|
46
|
-
country: z.string().nullable().optional(),
|
|
47
|
-
departure_city: z.string().nullable().optional(),
|
|
48
|
-
tags: z.array(z.string()).optional(),
|
|
49
|
-
});
|
|
50
|
-
export const productMediaItemSchema = z.object({
|
|
51
|
-
url: z.string(),
|
|
52
|
-
type: z.enum(["image", "video", "document"]).default("image"),
|
|
53
|
-
caption: z.string().nullable().optional(),
|
|
54
|
-
alt: z.string().nullable().optional(),
|
|
55
|
-
});
|
|
56
|
-
export const productOptionUnitSchema = z.object({
|
|
57
|
-
id: z.string(),
|
|
58
|
-
type: z.string(),
|
|
59
|
-
label: z.string().optional(),
|
|
60
|
-
description: z.string().nullable().optional(),
|
|
61
|
-
capacity: z.number().int().nonnegative().nullable().optional(),
|
|
62
|
-
});
|
|
63
|
-
export const productOptionSchema = z.object({
|
|
64
|
-
id: z.string(),
|
|
65
|
-
name: z.string(),
|
|
66
|
-
description: z.string().nullable().optional(),
|
|
67
|
-
units: z.array(productOptionUnitSchema).optional().default([]),
|
|
68
|
-
inclusions: z.array(z.string()).optional().default([]),
|
|
69
|
-
});
|
|
70
|
-
export const productDaySchema = z.object({
|
|
71
|
-
day_number: z.number().int().positive(),
|
|
72
|
-
title: z.string().nullable().optional(),
|
|
73
|
-
description: z.string().nullable().optional(),
|
|
74
|
-
location: z.string().nullable().optional(),
|
|
75
|
-
/** Day-level hero image (catalog detail sheet thumbnail). */
|
|
76
|
-
hero_image_url: z.string().nullable().optional(),
|
|
77
|
-
services: z.array(z.string()).optional().default([]),
|
|
78
|
-
});
|
|
79
|
-
export const productPolicySchema = z.object({
|
|
80
|
-
kind: z.enum(["cancellation", "payment", "supplier_notes", "requirements"]),
|
|
81
|
-
body: z.string(),
|
|
82
|
-
/** Optional structured rules — vertical-specific. */
|
|
83
|
-
rules: z.unknown().optional(),
|
|
84
|
-
});
|
|
85
|
-
/**
|
|
86
|
-
* A single bookable departure / time slot — the "when" surface of the
|
|
87
|
-
* product. ISO 8601 timestamps for `starts_at` / `ends_at` so locale
|
|
88
|
-
* formatting happens at render time, never in the cache.
|
|
89
|
-
*
|
|
90
|
-
* Owned products derive these from `availability_slots`; sourced
|
|
91
|
-
* adapters return them via `getContent`. Empty array = "always-on"
|
|
92
|
-
* product (e.g. an evergreen transfer service) or one whose schedule
|
|
93
|
-
* is on-request.
|
|
94
|
-
*/
|
|
95
|
-
export const productDepartureSchema = z.object({
|
|
96
|
-
id: z.string(),
|
|
97
|
-
starts_at: z.string(),
|
|
98
|
-
ends_at: z.string().nullable().optional(),
|
|
99
|
-
/** "open" | "limited" | "sold_out" | "closed" | "on_request" — display only. */
|
|
100
|
-
status: z.string().nullable().optional(),
|
|
101
|
-
/** Total capacity for the slot, when known. */
|
|
102
|
-
capacity: z.number().int().nonnegative().nullable().optional(),
|
|
103
|
-
/** Remaining capacity. Null = unknown / not surfaced; 0 = sold out. */
|
|
104
|
-
remaining: z.number().int().nonnegative().nullable().optional(),
|
|
105
|
-
/** Lowest pricing hint in cents — display only. Real price comes via liveResolve. */
|
|
106
|
-
lowest_price_cents: z.number().int().nonnegative().nullable().optional(),
|
|
107
|
-
currency: z.string().nullable().optional(),
|
|
108
|
-
/** Free-form note (weather caveat, sales window, etc). */
|
|
109
|
-
note: z.string().nullable().optional(),
|
|
110
|
-
});
|
|
111
|
-
/**
|
|
112
|
-
* The product content payload. Cache writes validate against this
|
|
113
|
-
* schema; cache reads skip rows that don't validate (treated as cache
|
|
114
|
-
* miss to surface adapter integration bugs without corrupting reads).
|
|
115
|
-
*/
|
|
116
|
-
export const productContentSchema = z.object({
|
|
117
|
-
product: productSummarySchema,
|
|
118
|
-
options: z.array(productOptionSchema).default([]),
|
|
119
|
-
days: z.array(productDaySchema).default([]),
|
|
120
|
-
media: z.array(productMediaItemSchema).default([]),
|
|
121
|
-
policies: z.array(productPolicySchema).default([]),
|
|
122
|
-
departures: z.array(productDepartureSchema).default([]),
|
|
123
|
-
});
|
|
124
|
-
/**
|
|
125
|
-
* Validate a `ProductContent` payload. Returns the parsed result on
|
|
126
|
-
* success or a structured failure on rejection. Used by the cache write
|
|
127
|
-
* path and by `mergeOverlaysIntoProductContent` to gate overlay merges.
|
|
128
|
-
*/
|
|
129
|
-
export function validateProductContent(payload) {
|
|
130
|
-
const result = productContentSchema.safeParse(payload);
|
|
131
|
-
if (result.success) {
|
|
132
|
-
return { valid: true, content: result.data };
|
|
133
|
-
}
|
|
134
|
-
// Take the first issue's message — that's enough signal for ops; full
|
|
135
|
-
// detail is available on `result.error.issues` if a caller cares.
|
|
136
|
-
const issue = result.error.issues[0];
|
|
137
|
-
return {
|
|
138
|
-
valid: false,
|
|
139
|
-
reason: issue ? `${issue.path.join(".")}: ${issue.message}` : "validation failed",
|
|
140
|
-
};
|
|
141
|
-
}
|
|
2
|
+
import { productContentSchema, validateProductContent, } from "@voyantjs/products-contracts/content-shape";
|
|
3
|
+
export { PRODUCTS_CONTENT_SCHEMA_VERSION, productContentSchema, productDaySchema, productDepartureSchema, productMediaItemSchema, productOptionSchema, productOptionUnitSchema, productPolicySchema, productSummarySchema, validateProductContent, } from "@voyantjs/products-contracts/content-shape";
|
|
142
4
|
/**
|
|
143
5
|
* Apply a list of editorial overlays to a product content payload via
|
|
144
6
|
* RFC 6901 JSON pointers. Validates the merged result against the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/products",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.96.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -132,13 +132,14 @@
|
|
|
132
132
|
"pdf-lib": "^1.17.1",
|
|
133
133
|
"sanitize-html": "^2.17.4",
|
|
134
134
|
"zod": "^4.3.6",
|
|
135
|
-
"@voyantjs/action-ledger": "0.
|
|
136
|
-
"@voyantjs/core": "0.
|
|
137
|
-
"@voyantjs/db": "0.
|
|
138
|
-
"@voyantjs/hono": "0.
|
|
139
|
-
"@voyantjs/
|
|
140
|
-
"@voyantjs/
|
|
141
|
-
"@voyantjs/
|
|
135
|
+
"@voyantjs/action-ledger": "0.96.0",
|
|
136
|
+
"@voyantjs/core": "0.96.0",
|
|
137
|
+
"@voyantjs/db": "0.96.0",
|
|
138
|
+
"@voyantjs/hono": "0.96.0",
|
|
139
|
+
"@voyantjs/products-contracts": "0.96.0",
|
|
140
|
+
"@voyantjs/utils": "0.96.0",
|
|
141
|
+
"@voyantjs/catalog": "0.96.0",
|
|
142
|
+
"@voyantjs/storage": "0.96.0"
|
|
142
143
|
},
|
|
143
144
|
"devDependencies": {
|
|
144
145
|
"@types/sanitize-html": "^2.16.1",
|