@voyantjs/extras 0.19.0 → 0.21.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/catalog-policy.d.ts +30 -0
- package/dist/catalog-policy.d.ts.map +1 -0
- package/dist/catalog-policy.js +305 -0
- package/dist/content-shape.d.ts +118 -0
- package/dist/content-shape.d.ts.map +1 -0
- package/dist/content-shape.js +98 -0
- package/dist/draft-shape.d.ts +34 -0
- package/dist/draft-shape.d.ts.map +1 -0
- package/dist/draft-shape.js +69 -0
- package/dist/routes.d.ts +35 -31
- package/dist/routes.d.ts.map +1 -1
- package/dist/schema-sourced-content.d.ts +254 -0
- package/dist/schema-sourced-content.d.ts.map +1 -0
- package/dist/schema-sourced-content.js +45 -0
- package/dist/schema.d.ts +21 -3
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +6 -0
- package/dist/service-catalog-plane.d.ts +79 -0
- package/dist/service-catalog-plane.d.ts.map +1 -0
- package/dist/service-catalog-plane.js +157 -0
- package/dist/service-content-synthesizer.d.ts +41 -0
- package/dist/service-content-synthesizer.d.ts.map +1 -0
- package/dist/service-content-synthesizer.js +138 -0
- package/dist/service-content.d.ts +48 -0
- package/dist/service-content.d.ts.map +1 -0
- package/dist/service-content.js +253 -0
- package/dist/service.d.ts +29 -25
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +2 -0
- package/dist/validation.d.ts +28 -24
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +2 -0
- package/package.json +7 -6
package/dist/routes.d.ts
CHANGED
|
@@ -13,10 +13,11 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
13
13
|
data: {
|
|
14
14
|
id: string;
|
|
15
15
|
productId: string;
|
|
16
|
+
supplierId: string | null;
|
|
16
17
|
code: string | null;
|
|
17
18
|
name: string;
|
|
18
19
|
description: string | null;
|
|
19
|
-
selectionType: "
|
|
20
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
20
21
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
21
22
|
pricedPerPerson: boolean;
|
|
22
23
|
minQuantity: number | null;
|
|
@@ -44,24 +45,25 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
44
45
|
input: {};
|
|
45
46
|
output: {
|
|
46
47
|
data: {
|
|
47
|
-
metadata: {
|
|
48
|
-
[x: string]: import("hono/utils/types").JSONValue;
|
|
49
|
-
} | null;
|
|
50
48
|
id: string;
|
|
51
|
-
|
|
49
|
+
code: string | null;
|
|
52
50
|
createdAt: string;
|
|
53
51
|
updatedAt: string;
|
|
54
|
-
description: string | null;
|
|
55
|
-
code: string | null;
|
|
56
|
-
active: boolean;
|
|
57
52
|
productId: string;
|
|
58
|
-
|
|
53
|
+
supplierId: string | null;
|
|
54
|
+
name: string;
|
|
55
|
+
description: string | null;
|
|
56
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
59
57
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
60
58
|
pricedPerPerson: boolean;
|
|
61
59
|
minQuantity: number | null;
|
|
62
60
|
maxQuantity: number | null;
|
|
63
61
|
defaultQuantity: number | null;
|
|
62
|
+
active: boolean;
|
|
64
63
|
sortOrder: number;
|
|
64
|
+
metadata: {
|
|
65
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
66
|
+
} | null;
|
|
65
67
|
} | null;
|
|
66
68
|
};
|
|
67
69
|
outputFormat: "json";
|
|
@@ -91,10 +93,11 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
91
93
|
data: {
|
|
92
94
|
id: string;
|
|
93
95
|
productId: string;
|
|
96
|
+
supplierId: string | null;
|
|
94
97
|
code: string | null;
|
|
95
98
|
name: string;
|
|
96
99
|
description: string | null;
|
|
97
|
-
selectionType: "
|
|
100
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
98
101
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
99
102
|
pricedPerPerson: boolean;
|
|
100
103
|
minQuantity: number | null;
|
|
@@ -136,10 +139,11 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
136
139
|
data: {
|
|
137
140
|
id: string;
|
|
138
141
|
productId: string;
|
|
142
|
+
supplierId: string | null;
|
|
139
143
|
code: string | null;
|
|
140
144
|
name: string;
|
|
141
145
|
description: string | null;
|
|
142
|
-
selectionType: "
|
|
146
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required";
|
|
143
147
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
144
148
|
pricedPerPerson: boolean;
|
|
145
149
|
minQuantity: number | null;
|
|
@@ -193,7 +197,7 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
193
197
|
id: string;
|
|
194
198
|
optionId: string;
|
|
195
199
|
productExtraId: string;
|
|
196
|
-
selectionType: "
|
|
200
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
197
201
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
198
202
|
pricedPerPerson: boolean | null;
|
|
199
203
|
minQuantity: number | null;
|
|
@@ -223,21 +227,21 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
223
227
|
input: {};
|
|
224
228
|
output: {
|
|
225
229
|
data: {
|
|
226
|
-
metadata: {
|
|
227
|
-
[x: string]: import("hono/utils/types").JSONValue;
|
|
228
|
-
} | null;
|
|
229
230
|
id: string;
|
|
230
231
|
createdAt: string;
|
|
231
232
|
updatedAt: string;
|
|
232
|
-
|
|
233
|
-
active: boolean;
|
|
234
|
-
selectionType: "optional" | "required" | "default_selected" | "unavailable" | null;
|
|
233
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
235
234
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
236
235
|
pricedPerPerson: boolean | null;
|
|
237
236
|
minQuantity: number | null;
|
|
238
237
|
maxQuantity: number | null;
|
|
239
238
|
defaultQuantity: number | null;
|
|
239
|
+
active: boolean;
|
|
240
240
|
sortOrder: number;
|
|
241
|
+
metadata: {
|
|
242
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
243
|
+
} | null;
|
|
244
|
+
notes: string | null;
|
|
241
245
|
optionId: string;
|
|
242
246
|
productExtraId: string;
|
|
243
247
|
isDefault: boolean;
|
|
@@ -271,7 +275,7 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
271
275
|
id: string;
|
|
272
276
|
optionId: string;
|
|
273
277
|
productExtraId: string;
|
|
274
|
-
selectionType: "
|
|
278
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
275
279
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
276
280
|
pricedPerPerson: boolean | null;
|
|
277
281
|
minQuantity: number | null;
|
|
@@ -316,7 +320,7 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
316
320
|
id: string;
|
|
317
321
|
optionId: string;
|
|
318
322
|
productExtraId: string;
|
|
319
|
-
selectionType: "
|
|
323
|
+
selectionType: "unavailable" | "optional" | "default_selected" | "required" | null;
|
|
320
324
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free" | null;
|
|
321
325
|
pricedPerPerson: boolean | null;
|
|
322
326
|
minQuantity: number | null;
|
|
@@ -375,7 +379,7 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
375
379
|
optionExtraConfigId: string | null;
|
|
376
380
|
name: string;
|
|
377
381
|
description: string | null;
|
|
378
|
-
status: "
|
|
382
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
379
383
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
380
384
|
pricedPerPerson: boolean;
|
|
381
385
|
quantity: number;
|
|
@@ -406,22 +410,22 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
406
410
|
input: {};
|
|
407
411
|
output: {
|
|
408
412
|
data: {
|
|
409
|
-
metadata: {
|
|
410
|
-
[x: string]: import("hono/utils/types").JSONValue;
|
|
411
|
-
} | null;
|
|
412
413
|
id: string;
|
|
413
|
-
name: string;
|
|
414
414
|
createdAt: string;
|
|
415
415
|
updatedAt: string;
|
|
416
|
-
|
|
417
|
-
notes: string | null;
|
|
416
|
+
name: string;
|
|
418
417
|
description: string | null;
|
|
419
|
-
bookingId: string;
|
|
420
418
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
421
419
|
pricedPerPerson: boolean;
|
|
420
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
421
|
+
metadata: {
|
|
422
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
423
|
+
} | null;
|
|
424
|
+
bookingId: string;
|
|
425
|
+
quantity: number;
|
|
426
|
+
notes: string | null;
|
|
422
427
|
productExtraId: string | null;
|
|
423
428
|
optionExtraConfigId: string | null;
|
|
424
|
-
quantity: number;
|
|
425
429
|
sellCurrency: string;
|
|
426
430
|
unitSellAmountCents: number | null;
|
|
427
431
|
totalSellAmountCents: number | null;
|
|
@@ -461,7 +465,7 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
461
465
|
optionExtraConfigId: string | null;
|
|
462
466
|
name: string;
|
|
463
467
|
description: string | null;
|
|
464
|
-
status: "
|
|
468
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
465
469
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
466
470
|
pricedPerPerson: boolean;
|
|
467
471
|
quantity: number;
|
|
@@ -510,7 +514,7 @@ export declare const extrasRoutes: import("hono/hono-base").HonoBase<Env, {
|
|
|
510
514
|
optionExtraConfigId: string | null;
|
|
511
515
|
name: string;
|
|
512
516
|
description: string | null;
|
|
513
|
-
status: "
|
|
517
|
+
status: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
514
518
|
pricingMode: "included" | "per_person" | "per_booking" | "quantity_based" | "on_request" | "free";
|
|
515
519
|
pricedPerPerson: boolean;
|
|
516
520
|
quantity: number;
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAgBjE,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAgBjE,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAsGrB,CAAA;AAEJ,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAA"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extras sourced-content cache. Sibling to the products / cruises /
|
|
3
|
+
* hospitality / charters variants — same shape, different vertical.
|
|
4
|
+
*
|
|
5
|
+
* One row per sourced extra × locale × market. Stores the content the
|
|
6
|
+
* upstream adapter served via `getContent`, plus the SWR metadata the
|
|
7
|
+
* read service needs.
|
|
8
|
+
*
|
|
9
|
+
* Extras are booking add-ons (optional line items layered on a parent
|
|
10
|
+
* product). Per `catalog-policy.ts`, extras are a partial-adoption
|
|
11
|
+
* vertical: they don't appear in the search index, but sourced extras
|
|
12
|
+
* (e.g. a TUI excursion add-on) still need rich content for the
|
|
13
|
+
* booking-flow's add-on selection UI. The sourced-content cache covers
|
|
14
|
+
* exactly that surface.
|
|
15
|
+
*
|
|
16
|
+
* See `docs/architecture/catalog-sourced-content.md` §3.2.
|
|
17
|
+
*/
|
|
18
|
+
export type ExtrasSourcedContentFetchStatus = "ok" | "stale" | "error" | "unsupported";
|
|
19
|
+
export declare const EXTRAS_CONTENT_MARKET_ANY = "*";
|
|
20
|
+
export declare const extrasSourcedContentTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
21
|
+
name: "extras_sourced_content";
|
|
22
|
+
schema: undefined;
|
|
23
|
+
columns: {
|
|
24
|
+
entity_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
25
|
+
name: "entity_id";
|
|
26
|
+
tableName: "extras_sourced_content";
|
|
27
|
+
dataType: "string";
|
|
28
|
+
columnType: "PgText";
|
|
29
|
+
data: string;
|
|
30
|
+
driverParam: string;
|
|
31
|
+
notNull: true;
|
|
32
|
+
hasDefault: false;
|
|
33
|
+
isPrimaryKey: false;
|
|
34
|
+
isAutoincrement: false;
|
|
35
|
+
hasRuntimeDefault: false;
|
|
36
|
+
enumValues: [string, ...string[]];
|
|
37
|
+
baseColumn: never;
|
|
38
|
+
identity: undefined;
|
|
39
|
+
generated: undefined;
|
|
40
|
+
}, {}, {}>;
|
|
41
|
+
locale: import("drizzle-orm/pg-core").PgColumn<{
|
|
42
|
+
name: "locale";
|
|
43
|
+
tableName: "extras_sourced_content";
|
|
44
|
+
dataType: "string";
|
|
45
|
+
columnType: "PgText";
|
|
46
|
+
data: string;
|
|
47
|
+
driverParam: string;
|
|
48
|
+
notNull: true;
|
|
49
|
+
hasDefault: false;
|
|
50
|
+
isPrimaryKey: false;
|
|
51
|
+
isAutoincrement: false;
|
|
52
|
+
hasRuntimeDefault: false;
|
|
53
|
+
enumValues: [string, ...string[]];
|
|
54
|
+
baseColumn: never;
|
|
55
|
+
identity: undefined;
|
|
56
|
+
generated: undefined;
|
|
57
|
+
}, {}, {}>;
|
|
58
|
+
market: import("drizzle-orm/pg-core").PgColumn<{
|
|
59
|
+
name: "market";
|
|
60
|
+
tableName: "extras_sourced_content";
|
|
61
|
+
dataType: "string";
|
|
62
|
+
columnType: "PgText";
|
|
63
|
+
data: string;
|
|
64
|
+
driverParam: string;
|
|
65
|
+
notNull: true;
|
|
66
|
+
hasDefault: true;
|
|
67
|
+
isPrimaryKey: false;
|
|
68
|
+
isAutoincrement: false;
|
|
69
|
+
hasRuntimeDefault: false;
|
|
70
|
+
enumValues: [string, ...string[]];
|
|
71
|
+
baseColumn: never;
|
|
72
|
+
identity: undefined;
|
|
73
|
+
generated: undefined;
|
|
74
|
+
}, {}, {}>;
|
|
75
|
+
payload: import("drizzle-orm/pg-core").PgColumn<{
|
|
76
|
+
name: "payload";
|
|
77
|
+
tableName: "extras_sourced_content";
|
|
78
|
+
dataType: "json";
|
|
79
|
+
columnType: "PgJsonb";
|
|
80
|
+
data: Record<string, unknown>;
|
|
81
|
+
driverParam: unknown;
|
|
82
|
+
notNull: true;
|
|
83
|
+
hasDefault: false;
|
|
84
|
+
isPrimaryKey: false;
|
|
85
|
+
isAutoincrement: false;
|
|
86
|
+
hasRuntimeDefault: false;
|
|
87
|
+
enumValues: undefined;
|
|
88
|
+
baseColumn: never;
|
|
89
|
+
identity: undefined;
|
|
90
|
+
generated: undefined;
|
|
91
|
+
}, {}, {
|
|
92
|
+
$type: Record<string, unknown>;
|
|
93
|
+
}>;
|
|
94
|
+
content_schema_version: import("drizzle-orm/pg-core").PgColumn<{
|
|
95
|
+
name: "content_schema_version";
|
|
96
|
+
tableName: "extras_sourced_content";
|
|
97
|
+
dataType: "string";
|
|
98
|
+
columnType: "PgText";
|
|
99
|
+
data: string;
|
|
100
|
+
driverParam: string;
|
|
101
|
+
notNull: true;
|
|
102
|
+
hasDefault: false;
|
|
103
|
+
isPrimaryKey: false;
|
|
104
|
+
isAutoincrement: false;
|
|
105
|
+
hasRuntimeDefault: false;
|
|
106
|
+
enumValues: [string, ...string[]];
|
|
107
|
+
baseColumn: never;
|
|
108
|
+
identity: undefined;
|
|
109
|
+
generated: undefined;
|
|
110
|
+
}, {}, {}>;
|
|
111
|
+
returned_locale: import("drizzle-orm/pg-core").PgColumn<{
|
|
112
|
+
name: "returned_locale";
|
|
113
|
+
tableName: "extras_sourced_content";
|
|
114
|
+
dataType: "string";
|
|
115
|
+
columnType: "PgText";
|
|
116
|
+
data: string;
|
|
117
|
+
driverParam: string;
|
|
118
|
+
notNull: true;
|
|
119
|
+
hasDefault: false;
|
|
120
|
+
isPrimaryKey: false;
|
|
121
|
+
isAutoincrement: false;
|
|
122
|
+
hasRuntimeDefault: false;
|
|
123
|
+
enumValues: [string, ...string[]];
|
|
124
|
+
baseColumn: never;
|
|
125
|
+
identity: undefined;
|
|
126
|
+
generated: undefined;
|
|
127
|
+
}, {}, {}>;
|
|
128
|
+
machine_translated: import("drizzle-orm/pg-core").PgColumn<{
|
|
129
|
+
name: "machine_translated";
|
|
130
|
+
tableName: "extras_sourced_content";
|
|
131
|
+
dataType: "boolean";
|
|
132
|
+
columnType: "PgBoolean";
|
|
133
|
+
data: boolean;
|
|
134
|
+
driverParam: boolean;
|
|
135
|
+
notNull: true;
|
|
136
|
+
hasDefault: true;
|
|
137
|
+
isPrimaryKey: false;
|
|
138
|
+
isAutoincrement: false;
|
|
139
|
+
hasRuntimeDefault: false;
|
|
140
|
+
enumValues: undefined;
|
|
141
|
+
baseColumn: never;
|
|
142
|
+
identity: undefined;
|
|
143
|
+
generated: undefined;
|
|
144
|
+
}, {}, {}>;
|
|
145
|
+
source_updated_at: import("drizzle-orm/pg-core").PgColumn<{
|
|
146
|
+
name: "source_updated_at";
|
|
147
|
+
tableName: "extras_sourced_content";
|
|
148
|
+
dataType: "date";
|
|
149
|
+
columnType: "PgTimestamp";
|
|
150
|
+
data: Date;
|
|
151
|
+
driverParam: string;
|
|
152
|
+
notNull: false;
|
|
153
|
+
hasDefault: false;
|
|
154
|
+
isPrimaryKey: false;
|
|
155
|
+
isAutoincrement: false;
|
|
156
|
+
hasRuntimeDefault: false;
|
|
157
|
+
enumValues: undefined;
|
|
158
|
+
baseColumn: never;
|
|
159
|
+
identity: undefined;
|
|
160
|
+
generated: undefined;
|
|
161
|
+
}, {}, {}>;
|
|
162
|
+
fetched_at: import("drizzle-orm/pg-core").PgColumn<{
|
|
163
|
+
name: "fetched_at";
|
|
164
|
+
tableName: "extras_sourced_content";
|
|
165
|
+
dataType: "date";
|
|
166
|
+
columnType: "PgTimestamp";
|
|
167
|
+
data: Date;
|
|
168
|
+
driverParam: string;
|
|
169
|
+
notNull: true;
|
|
170
|
+
hasDefault: true;
|
|
171
|
+
isPrimaryKey: false;
|
|
172
|
+
isAutoincrement: false;
|
|
173
|
+
hasRuntimeDefault: false;
|
|
174
|
+
enumValues: undefined;
|
|
175
|
+
baseColumn: never;
|
|
176
|
+
identity: undefined;
|
|
177
|
+
generated: undefined;
|
|
178
|
+
}, {}, {}>;
|
|
179
|
+
fresh_until: import("drizzle-orm/pg-core").PgColumn<{
|
|
180
|
+
name: "fresh_until";
|
|
181
|
+
tableName: "extras_sourced_content";
|
|
182
|
+
dataType: "date";
|
|
183
|
+
columnType: "PgTimestamp";
|
|
184
|
+
data: Date;
|
|
185
|
+
driverParam: string;
|
|
186
|
+
notNull: false;
|
|
187
|
+
hasDefault: false;
|
|
188
|
+
isPrimaryKey: false;
|
|
189
|
+
isAutoincrement: false;
|
|
190
|
+
hasRuntimeDefault: false;
|
|
191
|
+
enumValues: undefined;
|
|
192
|
+
baseColumn: never;
|
|
193
|
+
identity: undefined;
|
|
194
|
+
generated: undefined;
|
|
195
|
+
}, {}, {}>;
|
|
196
|
+
etag: import("drizzle-orm/pg-core").PgColumn<{
|
|
197
|
+
name: "etag";
|
|
198
|
+
tableName: "extras_sourced_content";
|
|
199
|
+
dataType: "string";
|
|
200
|
+
columnType: "PgText";
|
|
201
|
+
data: string;
|
|
202
|
+
driverParam: string;
|
|
203
|
+
notNull: false;
|
|
204
|
+
hasDefault: false;
|
|
205
|
+
isPrimaryKey: false;
|
|
206
|
+
isAutoincrement: false;
|
|
207
|
+
hasRuntimeDefault: false;
|
|
208
|
+
enumValues: [string, ...string[]];
|
|
209
|
+
baseColumn: never;
|
|
210
|
+
identity: undefined;
|
|
211
|
+
generated: undefined;
|
|
212
|
+
}, {}, {}>;
|
|
213
|
+
fetch_status: import("drizzle-orm/pg-core").PgColumn<{
|
|
214
|
+
name: "fetch_status";
|
|
215
|
+
tableName: "extras_sourced_content";
|
|
216
|
+
dataType: "string";
|
|
217
|
+
columnType: "PgText";
|
|
218
|
+
data: ExtrasSourcedContentFetchStatus;
|
|
219
|
+
driverParam: string;
|
|
220
|
+
notNull: true;
|
|
221
|
+
hasDefault: true;
|
|
222
|
+
isPrimaryKey: false;
|
|
223
|
+
isAutoincrement: false;
|
|
224
|
+
hasRuntimeDefault: false;
|
|
225
|
+
enumValues: [string, ...string[]];
|
|
226
|
+
baseColumn: never;
|
|
227
|
+
identity: undefined;
|
|
228
|
+
generated: undefined;
|
|
229
|
+
}, {}, {
|
|
230
|
+
$type: ExtrasSourcedContentFetchStatus;
|
|
231
|
+
}>;
|
|
232
|
+
fetch_error: import("drizzle-orm/pg-core").PgColumn<{
|
|
233
|
+
name: "fetch_error";
|
|
234
|
+
tableName: "extras_sourced_content";
|
|
235
|
+
dataType: "string";
|
|
236
|
+
columnType: "PgText";
|
|
237
|
+
data: string;
|
|
238
|
+
driverParam: string;
|
|
239
|
+
notNull: false;
|
|
240
|
+
hasDefault: false;
|
|
241
|
+
isPrimaryKey: false;
|
|
242
|
+
isAutoincrement: false;
|
|
243
|
+
hasRuntimeDefault: false;
|
|
244
|
+
enumValues: [string, ...string[]];
|
|
245
|
+
baseColumn: never;
|
|
246
|
+
identity: undefined;
|
|
247
|
+
generated: undefined;
|
|
248
|
+
}, {}, {}>;
|
|
249
|
+
};
|
|
250
|
+
dialect: "pg";
|
|
251
|
+
}>;
|
|
252
|
+
export type InsertExtrasSourcedContent = typeof extrasSourcedContentTable.$inferInsert;
|
|
253
|
+
export type SelectExtrasSourcedContent = typeof extrasSourcedContentTable.$inferSelect;
|
|
254
|
+
//# sourceMappingURL=schema-sourced-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-sourced-content.d.ts","sourceRoot":"","sources":["../src/schema-sourced-content.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,+BAA+B,GAAG,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,CAAA;AAEtF,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCrC,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG,OAAO,yBAAyB,CAAC,YAAY,CAAA;AACtF,MAAM,MAAM,0BAA0B,GAAG,OAAO,yBAAyB,CAAC,YAAY,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extras sourced-content cache. Sibling to the products / cruises /
|
|
3
|
+
* hospitality / charters variants — same shape, different vertical.
|
|
4
|
+
*
|
|
5
|
+
* One row per sourced extra × locale × market. Stores the content the
|
|
6
|
+
* upstream adapter served via `getContent`, plus the SWR metadata the
|
|
7
|
+
* read service needs.
|
|
8
|
+
*
|
|
9
|
+
* Extras are booking add-ons (optional line items layered on a parent
|
|
10
|
+
* product). Per `catalog-policy.ts`, extras are a partial-adoption
|
|
11
|
+
* vertical: they don't appear in the search index, but sourced extras
|
|
12
|
+
* (e.g. a TUI excursion add-on) still need rich content for the
|
|
13
|
+
* booking-flow's add-on selection UI. The sourced-content cache covers
|
|
14
|
+
* exactly that surface.
|
|
15
|
+
*
|
|
16
|
+
* See `docs/architecture/catalog-sourced-content.md` §3.2.
|
|
17
|
+
*/
|
|
18
|
+
import { boolean, index, jsonb, pgTable, primaryKey, text, timestamp } from "drizzle-orm/pg-core";
|
|
19
|
+
export const EXTRAS_CONTENT_MARKET_ANY = "*";
|
|
20
|
+
export const extrasSourcedContentTable = pgTable("extras_sourced_content", {
|
|
21
|
+
/** TypeID matching the extras module — `pxtr_*` (product_extras). */
|
|
22
|
+
entity_id: text("entity_id").notNull(),
|
|
23
|
+
/** BCP 47 language tag. */
|
|
24
|
+
locale: text("locale").notNull(),
|
|
25
|
+
/** Market id, or `'*'` for all-markets. */
|
|
26
|
+
market: text("market").notNull().default(EXTRAS_CONTENT_MARKET_ANY),
|
|
27
|
+
payload: jsonb("payload").$type().notNull(),
|
|
28
|
+
content_schema_version: text("content_schema_version").notNull(),
|
|
29
|
+
returned_locale: text("returned_locale").notNull(),
|
|
30
|
+
machine_translated: boolean("machine_translated").notNull().default(false),
|
|
31
|
+
source_updated_at: timestamp("source_updated_at", { withTimezone: true }),
|
|
32
|
+
fetched_at: timestamp("fetched_at", { withTimezone: true }).notNull().defaultNow(),
|
|
33
|
+
fresh_until: timestamp("fresh_until", { withTimezone: true }),
|
|
34
|
+
etag: text("etag"),
|
|
35
|
+
fetch_status: text("fetch_status")
|
|
36
|
+
.$type()
|
|
37
|
+
.notNull()
|
|
38
|
+
.default("ok"),
|
|
39
|
+
fetch_error: text("fetch_error"),
|
|
40
|
+
}, (table) => [
|
|
41
|
+
primaryKey({ columns: [table.entity_id, table.locale, table.market] }),
|
|
42
|
+
index("extras_sourced_content_locale_fresh_idx").on(table.locale, table.fresh_until),
|
|
43
|
+
index("extras_sourced_content_returned_locale_idx").on(table.entity_id, table.returned_locale),
|
|
44
|
+
index("extras_sourced_content_schema_version_idx").on(table.content_schema_version),
|
|
45
|
+
]);
|
package/dist/schema.d.ts
CHANGED
|
@@ -39,6 +39,23 @@ export declare const productExtras: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
39
39
|
identity: undefined;
|
|
40
40
|
generated: undefined;
|
|
41
41
|
}, {}, {}>;
|
|
42
|
+
supplierId: import("drizzle-orm/pg-core").PgColumn<{
|
|
43
|
+
name: "supplier_id";
|
|
44
|
+
tableName: "product_extras";
|
|
45
|
+
dataType: "string";
|
|
46
|
+
columnType: "PgText";
|
|
47
|
+
data: string;
|
|
48
|
+
driverParam: string;
|
|
49
|
+
notNull: false;
|
|
50
|
+
hasDefault: false;
|
|
51
|
+
isPrimaryKey: false;
|
|
52
|
+
isAutoincrement: false;
|
|
53
|
+
hasRuntimeDefault: false;
|
|
54
|
+
enumValues: [string, ...string[]];
|
|
55
|
+
baseColumn: never;
|
|
56
|
+
identity: undefined;
|
|
57
|
+
generated: undefined;
|
|
58
|
+
}, {}, {}>;
|
|
42
59
|
code: import("drizzle-orm/pg-core").PgColumn<{
|
|
43
60
|
name: "code";
|
|
44
61
|
tableName: "product_extras";
|
|
@@ -95,7 +112,7 @@ export declare const productExtras: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
95
112
|
tableName: "product_extras";
|
|
96
113
|
dataType: "string";
|
|
97
114
|
columnType: "PgEnumColumn";
|
|
98
|
-
data: "
|
|
115
|
+
data: "unavailable" | "optional" | "default_selected" | "required";
|
|
99
116
|
driverParam: string;
|
|
100
117
|
notNull: true;
|
|
101
118
|
hasDefault: true;
|
|
@@ -342,7 +359,7 @@ export declare const optionExtraConfigs: import("drizzle-orm/pg-core").PgTableWi
|
|
|
342
359
|
tableName: "option_extra_configs";
|
|
343
360
|
dataType: "string";
|
|
344
361
|
columnType: "PgEnumColumn";
|
|
345
|
-
data: "
|
|
362
|
+
data: "unavailable" | "optional" | "default_selected" | "required";
|
|
346
363
|
driverParam: string;
|
|
347
364
|
notNull: false;
|
|
348
365
|
hasDefault: false;
|
|
@@ -674,7 +691,7 @@ export declare const bookingExtras: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
674
691
|
tableName: "booking_extras";
|
|
675
692
|
dataType: "string";
|
|
676
693
|
columnType: "PgEnumColumn";
|
|
677
|
-
data: "
|
|
694
|
+
data: "confirmed" | "cancelled" | "draft" | "selected" | "fulfilled";
|
|
678
695
|
driverParam: string;
|
|
679
696
|
notNull: true;
|
|
680
697
|
hasDefault: true;
|
|
@@ -930,4 +947,5 @@ export declare const bookingExtrasRelations: import("drizzle-orm").Relations<"bo
|
|
|
930
947
|
productExtra: import("drizzle-orm").One<"product_extras", false>;
|
|
931
948
|
optionExtraConfig: import("drizzle-orm").One<"option_extra_configs", false>;
|
|
932
949
|
}>;
|
|
950
|
+
export { EXTRAS_CONTENT_MARKET_ANY, type ExtrasSourcedContentFetchStatus, extrasSourcedContentTable, type InsertExtrasSourcedContent, type SelectExtrasSourcedContent, } from "./schema-sourced-content.js";
|
|
933
951
|
//# sourceMappingURL=schema.d.ts.map
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,sBAAsB,mGAKjC,CAAA;AAEF,eAAO,MAAM,oBAAoB,yHAO/B,CAAA;AAEF,eAAO,MAAM,sBAAsB,oGAMjC,CAAA;AAEF,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,sBAAsB,mGAKjC,CAAA;AAEF,eAAO,MAAM,oBAAoB,yHAO/B,CAAA;AAEF,eAAO,MAAM,sBAAsB,oGAMjC,CAAA;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCzB,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyC9B,CAAA;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCzB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAC,YAAY,CAAA;AAC5D,MAAM,MAAM,eAAe,GAAG,OAAO,aAAa,CAAC,YAAY,CAAA;AAC/D,MAAM,MAAM,iBAAiB,GAAG,OAAO,kBAAkB,CAAC,YAAY,CAAA;AACtE,MAAM,MAAM,oBAAoB,GAAG,OAAO,kBAAkB,CAAC,YAAY,CAAA;AACzE,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAC,YAAY,CAAA;AAC5D,MAAM,MAAM,eAAe,GAAG,OAAO,aAAa,CAAC,YAAY,CAAA;AAE/D,eAAO,MAAM,sBAAsB;;;EAGhC,CAAA;AAEH,eAAO,MAAM,2BAA2B;;;EAMrC,CAAA;AAEH,eAAO,MAAM,sBAAsB;;;EAShC,CAAA;AAKH,OAAO,EACL,yBAAyB,EACzB,KAAK,+BAA+B,EACpC,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,GAChC,MAAM,6BAA6B,CAAA"}
|
package/dist/schema.js
CHANGED
|
@@ -25,6 +25,7 @@ export const bookingExtraStatusEnum = pgEnum("booking_extra_status", [
|
|
|
25
25
|
export const productExtras = pgTable("product_extras", {
|
|
26
26
|
id: typeId("product_extras"),
|
|
27
27
|
productId: text("product_id").notNull(),
|
|
28
|
+
supplierId: text("supplier_id"),
|
|
28
29
|
code: text("code"),
|
|
29
30
|
name: text("name").notNull(),
|
|
30
31
|
description: text("description"),
|
|
@@ -42,6 +43,7 @@ export const productExtras = pgTable("product_extras", {
|
|
|
42
43
|
}, (table) => [
|
|
43
44
|
index("idx_product_extras_sort_name").on(table.sortOrder, table.name),
|
|
44
45
|
index("idx_product_extras_product_sort_name").on(table.productId, table.sortOrder, table.name),
|
|
46
|
+
index("idx_product_extras_supplier_sort_name").on(table.supplierId, table.sortOrder, table.name),
|
|
45
47
|
index("idx_product_extras_active_sort_name").on(table.active, table.sortOrder, table.name),
|
|
46
48
|
uniqueIndex("uidx_product_extras_product_code").on(table.productId, table.code),
|
|
47
49
|
]);
|
|
@@ -124,3 +126,7 @@ export const bookingExtrasRelations = relations(bookingExtras, ({ one }) => ({
|
|
|
124
126
|
references: [optionExtraConfigs.id],
|
|
125
127
|
}),
|
|
126
128
|
}));
|
|
129
|
+
// ─── Sourced-content cache ──────────────────────────────────────────
|
|
130
|
+
// Re-exported here so templates pick it up via the package's `./schema`
|
|
131
|
+
// entry without needing a separate config entry.
|
|
132
|
+
export { EXTRAS_CONTENT_MARKET_ANY, extrasSourcedContentTable, } from "./schema-sourced-content.js";
|