@voyant-travel/catalog 0.117.2

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.
Files changed (243) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +190 -0
  3. package/dist/adapter/booking-forwarding.d.ts +2 -0
  4. package/dist/adapter/booking-forwarding.d.ts.map +1 -0
  5. package/dist/adapter/booking-forwarding.js +1 -0
  6. package/dist/adapter/channel-push-contracts.d.ts +2 -0
  7. package/dist/adapter/channel-push-contracts.d.ts.map +1 -0
  8. package/dist/adapter/channel-push-contracts.js +1 -0
  9. package/dist/adapter/contract.d.ts +2 -0
  10. package/dist/adapter/contract.d.ts.map +1 -0
  11. package/dist/adapter/contract.js +1 -0
  12. package/dist/adapter/contract.test.d.ts +2 -0
  13. package/dist/adapter/contract.test.d.ts.map +1 -0
  14. package/dist/adapter/contract.test.js +390 -0
  15. package/dist/adapter/provider-contracts.d.ts +2 -0
  16. package/dist/adapter/provider-contracts.d.ts.map +1 -0
  17. package/dist/adapter/provider-contracts.js +1 -0
  18. package/dist/adapter/provider-contracts.test.d.ts +2 -0
  19. package/dist/adapter/provider-contracts.test.d.ts.map +1 -0
  20. package/dist/adapter/provider-contracts.test.js +206 -0
  21. package/dist/adapter/schemas.d.ts +2 -0
  22. package/dist/adapter/schemas.d.ts.map +1 -0
  23. package/dist/adapter/schemas.js +1 -0
  24. package/dist/adapter/schemas.test.d.ts +2 -0
  25. package/dist/adapter/schemas.test.d.ts.map +1 -0
  26. package/dist/adapter/schemas.test.js +344 -0
  27. package/dist/booking-engine/book.d.ts +124 -0
  28. package/dist/booking-engine/book.d.ts.map +1 -0
  29. package/dist/booking-engine/book.js +311 -0
  30. package/dist/booking-engine/cancel.d.ts +40 -0
  31. package/dist/booking-engine/cancel.d.ts.map +1 -0
  32. package/dist/booking-engine/cancel.js +56 -0
  33. package/dist/booking-engine/checkout-finalize.d.ts +146 -0
  34. package/dist/booking-engine/checkout-finalize.d.ts.map +1 -0
  35. package/dist/booking-engine/checkout-finalize.js +132 -0
  36. package/dist/booking-engine/contracts.d.ts +9 -0
  37. package/dist/booking-engine/contracts.d.ts.map +1 -0
  38. package/dist/booking-engine/contracts.js +8 -0
  39. package/dist/booking-engine/contracts.test.d.ts +2 -0
  40. package/dist/booking-engine/contracts.test.d.ts.map +1 -0
  41. package/dist/booking-engine/contracts.test.js +116 -0
  42. package/dist/booking-engine/draft-shape.d.ts +10 -0
  43. package/dist/booking-engine/draft-shape.d.ts.map +1 -0
  44. package/dist/booking-engine/draft-shape.js +9 -0
  45. package/dist/booking-engine/draft-shape.test.d.ts +2 -0
  46. package/dist/booking-engine/draft-shape.test.d.ts.map +1 -0
  47. package/dist/booking-engine/draft-shape.test.js +74 -0
  48. package/dist/booking-engine/drafts-schema.d.ts +302 -0
  49. package/dist/booking-engine/drafts-schema.d.ts.map +1 -0
  50. package/dist/booking-engine/drafts-schema.js +53 -0
  51. package/dist/booking-engine/drafts-service.d.ts +41 -0
  52. package/dist/booking-engine/drafts-service.d.ts.map +1 -0
  53. package/dist/booking-engine/drafts-service.js +108 -0
  54. package/dist/booking-engine/errors.d.ts +81 -0
  55. package/dist/booking-engine/errors.d.ts.map +1 -0
  56. package/dist/booking-engine/errors.js +113 -0
  57. package/dist/booking-engine/index.d.ts +36 -0
  58. package/dist/booking-engine/index.d.ts.map +1 -0
  59. package/dist/booking-engine/index.js +34 -0
  60. package/dist/booking-engine/orders.d.ts +41 -0
  61. package/dist/booking-engine/orders.d.ts.map +1 -0
  62. package/dist/booking-engine/orders.js +49 -0
  63. package/dist/booking-engine/owned-handler.d.ts +166 -0
  64. package/dist/booking-engine/owned-handler.d.ts.map +1 -0
  65. package/dist/booking-engine/owned-handler.js +50 -0
  66. package/dist/booking-engine/owned-handler.test.d.ts +2 -0
  67. package/dist/booking-engine/owned-handler.test.d.ts.map +1 -0
  68. package/dist/booking-engine/owned-handler.test.js +63 -0
  69. package/dist/booking-engine/promotions-contract.d.ts +8 -0
  70. package/dist/booking-engine/promotions-contract.d.ts.map +1 -0
  71. package/dist/booking-engine/promotions-contract.js +7 -0
  72. package/dist/booking-engine/quote-enricher.test.d.ts +12 -0
  73. package/dist/booking-engine/quote-enricher.test.d.ts.map +1 -0
  74. package/dist/booking-engine/quote-enricher.test.js +138 -0
  75. package/dist/booking-engine/quote.d.ts +163 -0
  76. package/dist/booking-engine/quote.d.ts.map +1 -0
  77. package/dist/booking-engine/quote.js +259 -0
  78. package/dist/booking-engine/registry.d.ts +85 -0
  79. package/dist/booking-engine/registry.d.ts.map +1 -0
  80. package/dist/booking-engine/registry.js +118 -0
  81. package/dist/booking-engine/registry.test.d.ts +2 -0
  82. package/dist/booking-engine/registry.test.d.ts.map +1 -0
  83. package/dist/booking-engine/registry.test.js +132 -0
  84. package/dist/booking-engine/routes-contracts.d.ts +169 -0
  85. package/dist/booking-engine/routes-contracts.d.ts.map +1 -0
  86. package/dist/booking-engine/routes-contracts.js +63 -0
  87. package/dist/booking-engine/routes.d.ts +7 -0
  88. package/dist/booking-engine/routes.d.ts.map +1 -0
  89. package/dist/booking-engine/routes.js +443 -0
  90. package/dist/booking-engine/routes.test.d.ts +2 -0
  91. package/dist/booking-engine/routes.test.d.ts.map +1 -0
  92. package/dist/booking-engine/routes.test.js +304 -0
  93. package/dist/booking-engine/schema.d.ts +455 -0
  94. package/dist/booking-engine/schema.d.ts.map +1 -0
  95. package/dist/booking-engine/schema.js +75 -0
  96. package/dist/booking-engine/snapshot-content.d.ts +120 -0
  97. package/dist/booking-engine/snapshot-content.d.ts.map +1 -0
  98. package/dist/booking-engine/snapshot-content.js +110 -0
  99. package/dist/booking-engine/snapshot-content.test.d.ts +2 -0
  100. package/dist/booking-engine/snapshot-content.test.d.ts.map +1 -0
  101. package/dist/booking-engine/snapshot-content.test.js +213 -0
  102. package/dist/booking-engine/sync.d.ts +136 -0
  103. package/dist/booking-engine/sync.d.ts.map +1 -0
  104. package/dist/booking-engine/sync.js +177 -0
  105. package/dist/booking-engine/sync.test.d.ts +2 -0
  106. package/dist/booking-engine/sync.test.d.ts.map +1 -0
  107. package/dist/booking-engine/sync.test.js +377 -0
  108. package/dist/contract.d.ts +2 -0
  109. package/dist/contract.d.ts.map +1 -0
  110. package/dist/contract.js +1 -0
  111. package/dist/contract.test.d.ts +2 -0
  112. package/dist/contract.test.d.ts.map +1 -0
  113. package/dist/contract.test.js +107 -0
  114. package/dist/drift/events.d.ts +2 -0
  115. package/dist/drift/events.d.ts.map +1 -0
  116. package/dist/drift/events.js +1 -0
  117. package/dist/drift/events.test.d.ts +2 -0
  118. package/dist/drift/events.test.d.ts.map +1 -0
  119. package/dist/drift/events.test.js +100 -0
  120. package/dist/embeddings/contract.d.ts +85 -0
  121. package/dist/embeddings/contract.d.ts.map +1 -0
  122. package/dist/embeddings/contract.js +42 -0
  123. package/dist/embeddings/contract.test.d.ts +2 -0
  124. package/dist/embeddings/contract.test.d.ts.map +1 -0
  125. package/dist/embeddings/contract.test.js +30 -0
  126. package/dist/embeddings/gemini.d.ts +110 -0
  127. package/dist/embeddings/gemini.d.ts.map +1 -0
  128. package/dist/embeddings/gemini.js +118 -0
  129. package/dist/embeddings/gemini.test.d.ts +2 -0
  130. package/dist/embeddings/gemini.test.d.ts.map +1 -0
  131. package/dist/embeddings/gemini.test.js +132 -0
  132. package/dist/embeddings/model-registry.d.ts +62 -0
  133. package/dist/embeddings/model-registry.d.ts.map +1 -0
  134. package/dist/embeddings/model-registry.js +78 -0
  135. package/dist/embeddings/model-registry.test.d.ts +2 -0
  136. package/dist/embeddings/model-registry.test.d.ts.map +1 -0
  137. package/dist/embeddings/model-registry.test.js +81 -0
  138. package/dist/embeddings/openai.d.ts +81 -0
  139. package/dist/embeddings/openai.d.ts.map +1 -0
  140. package/dist/embeddings/openai.js +123 -0
  141. package/dist/embeddings/openai.test.d.ts +2 -0
  142. package/dist/embeddings/openai.test.d.ts.map +1 -0
  143. package/dist/embeddings/openai.test.js +164 -0
  144. package/dist/events/taxonomy.d.ts +158 -0
  145. package/dist/events/taxonomy.d.ts.map +1 -0
  146. package/dist/events/taxonomy.js +99 -0
  147. package/dist/events/taxonomy.test.d.ts +2 -0
  148. package/dist/events/taxonomy.test.d.ts.map +1 -0
  149. package/dist/events/taxonomy.test.js +48 -0
  150. package/dist/index.d.ts +27 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +39 -0
  153. package/dist/indexer/contract.d.ts +203 -0
  154. package/dist/indexer/contract.d.ts.map +1 -0
  155. package/dist/indexer/contract.js +16 -0
  156. package/dist/indexer/typesense-search-query.d.ts +31 -0
  157. package/dist/indexer/typesense-search-query.d.ts.map +1 -0
  158. package/dist/indexer/typesense-search-query.js +185 -0
  159. package/dist/indexer/typesense.d.ts +105 -0
  160. package/dist/indexer/typesense.d.ts.map +1 -0
  161. package/dist/indexer/typesense.js +394 -0
  162. package/dist/indexer/typesense.test.d.ts +2 -0
  163. package/dist/indexer/typesense.test.d.ts.map +1 -0
  164. package/dist/indexer/typesense.test.js +253 -0
  165. package/dist/overlay/resolver.d.ts +101 -0
  166. package/dist/overlay/resolver.d.ts.map +1 -0
  167. package/dist/overlay/resolver.js +167 -0
  168. package/dist/overlay/resolver.test.d.ts +2 -0
  169. package/dist/overlay/resolver.test.d.ts.map +1 -0
  170. package/dist/overlay/resolver.test.js +179 -0
  171. package/dist/overlay/schema.d.ts +266 -0
  172. package/dist/overlay/schema.d.ts.map +1 -0
  173. package/dist/overlay/schema.js +71 -0
  174. package/dist/provenance.d.ts +2 -0
  175. package/dist/provenance.d.ts.map +1 -0
  176. package/dist/provenance.js +1 -0
  177. package/dist/schema-sourced-entries.d.ts +344 -0
  178. package/dist/schema-sourced-entries.d.ts.map +1 -0
  179. package/dist/schema-sourced-entries.js +75 -0
  180. package/dist/schema.d.ts +21 -0
  181. package/dist/schema.d.ts.map +1 -0
  182. package/dist/schema.js +20 -0
  183. package/dist/search/federate.d.ts +58 -0
  184. package/dist/search/federate.d.ts.map +1 -0
  185. package/dist/search/federate.js +103 -0
  186. package/dist/search/federate.test.d.ts +2 -0
  187. package/dist/search/federate.test.d.ts.map +1 -0
  188. package/dist/search/federate.test.js +146 -0
  189. package/dist/search/rerank.d.ts +77 -0
  190. package/dist/search/rerank.d.ts.map +1 -0
  191. package/dist/search/rerank.js +68 -0
  192. package/dist/search/rerank.test.d.ts +2 -0
  193. package/dist/search/rerank.test.d.ts.map +1 -0
  194. package/dist/search/rerank.test.js +60 -0
  195. package/dist/search/routes.d.ts +144 -0
  196. package/dist/search/routes.d.ts.map +1 -0
  197. package/dist/search/routes.js +288 -0
  198. package/dist/search/routes.test.d.ts +2 -0
  199. package/dist/search/routes.test.d.ts.map +1 -0
  200. package/dist/search/routes.test.js +322 -0
  201. package/dist/search/semantic.d.ts +63 -0
  202. package/dist/search/semantic.d.ts.map +1 -0
  203. package/dist/search/semantic.js +75 -0
  204. package/dist/search/semantic.test.d.ts +2 -0
  205. package/dist/search/semantic.test.d.ts.map +1 -0
  206. package/dist/search/semantic.test.js +143 -0
  207. package/dist/services/build-indexer-document.test.d.ts +2 -0
  208. package/dist/services/build-indexer-document.test.d.ts.map +1 -0
  209. package/dist/services/build-indexer-document.test.js +102 -0
  210. package/dist/services/content-service.d.ts +125 -0
  211. package/dist/services/content-service.d.ts.map +1 -0
  212. package/dist/services/content-service.js +139 -0
  213. package/dist/services/content-service.test.d.ts +2 -0
  214. package/dist/services/content-service.test.d.ts.map +1 -0
  215. package/dist/services/content-service.test.js +322 -0
  216. package/dist/services/indexer-service.d.ts +109 -0
  217. package/dist/services/indexer-service.d.ts.map +1 -0
  218. package/dist/services/indexer-service.js +123 -0
  219. package/dist/services/indexer-service.test.d.ts +2 -0
  220. package/dist/services/indexer-service.test.d.ts.map +1 -0
  221. package/dist/services/indexer-service.test.js +176 -0
  222. package/dist/services/overlay-service.d.ts +108 -0
  223. package/dist/services/overlay-service.d.ts.map +1 -0
  224. package/dist/services/overlay-service.js +211 -0
  225. package/dist/services/overlay-service.test.d.ts +2 -0
  226. package/dist/services/overlay-service.test.d.ts.map +1 -0
  227. package/dist/services/overlay-service.test.js +79 -0
  228. package/dist/services/snapshot-builder.test.d.ts +2 -0
  229. package/dist/services/snapshot-builder.test.d.ts.map +1 -0
  230. package/dist/services/snapshot-builder.test.js +93 -0
  231. package/dist/services/snapshot-service.d.ts +78 -0
  232. package/dist/services/snapshot-service.d.ts.map +1 -0
  233. package/dist/services/snapshot-service.js +165 -0
  234. package/dist/services/sourced-entry-service.d.ts +142 -0
  235. package/dist/services/sourced-entry-service.d.ts.map +1 -0
  236. package/dist/services/sourced-entry-service.js +203 -0
  237. package/dist/services/sourced-entry-service.test.d.ts +10 -0
  238. package/dist/services/sourced-entry-service.test.d.ts.map +1 -0
  239. package/dist/services/sourced-entry-service.test.js +66 -0
  240. package/dist/snapshot/schema.d.ts +362 -0
  241. package/dist/snapshot/schema.d.ts.map +1 -0
  242. package/dist/snapshot/schema.js +102 -0
  243. package/package.json +210 -0
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Overlay store schema — editorial overrides keyed by
3
+ * `(entity_module, entity_id, field_path, locale, audience, market)`.
4
+ *
5
+ * One overlay table serves every vertical. Rows hold the override value plus
6
+ * provenance about *which* writer (admin UI / CMS plugin / bulk import / AI /
7
+ * external API) produced the override, for audit and revert workflows.
8
+ *
9
+ * See `docs/architecture/catalog-architecture.md` §5.2 for the full design.
10
+ */
11
+ import type { Visibility } from "../contract.js";
12
+ /**
13
+ * Audit identifier indicating where an overlay row came from. Discriminated
14
+ * by `kind`; consumers may pattern-match for revert / filter workflows.
15
+ */
16
+ export type OverlayOrigin = {
17
+ kind: "admin-ui";
18
+ user_id: string;
19
+ } | {
20
+ kind: "cms";
21
+ provider: string;
22
+ cms_doc_id: string;
23
+ } | {
24
+ kind: "bulk-import";
25
+ batch_id: string;
26
+ } | {
27
+ kind: "ai-generated";
28
+ model: string;
29
+ prompt_hash?: string;
30
+ } | {
31
+ kind: "external-api";
32
+ api_key_id: string;
33
+ };
34
+ /**
35
+ * Sentinel value used in `locale`, `audience`, and `market` columns to mark
36
+ * "no specific scope" — the broadest fallback in the resolver chain.
37
+ */
38
+ export declare const OVERLAY_DEFAULT_SCOPE = "default";
39
+ /**
40
+ * `catalog_overlay` — single table holding editorial overrides for every
41
+ * vertical. Composite uniqueness on `(entity_module, entity_id, field_path,
42
+ * locale, audience, market)` prevents duplicate overlays for the same scope.
43
+ */
44
+ export declare const catalogOverlayTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
45
+ name: "catalog_overlay";
46
+ schema: undefined;
47
+ columns: {
48
+ id: import("drizzle-orm/pg-core").PgColumn<{
49
+ name: string;
50
+ tableName: "catalog_overlay";
51
+ dataType: "string";
52
+ columnType: "PgText";
53
+ data: string;
54
+ driverParam: string;
55
+ notNull: true;
56
+ hasDefault: true;
57
+ isPrimaryKey: true;
58
+ isAutoincrement: false;
59
+ hasRuntimeDefault: true;
60
+ enumValues: [string, ...string[]];
61
+ baseColumn: never;
62
+ identity: undefined;
63
+ generated: undefined;
64
+ }, {}, {}>;
65
+ entity_module: import("drizzle-orm/pg-core").PgColumn<{
66
+ name: "entity_module";
67
+ tableName: "catalog_overlay";
68
+ dataType: "string";
69
+ columnType: "PgText";
70
+ data: string;
71
+ driverParam: string;
72
+ notNull: true;
73
+ hasDefault: false;
74
+ isPrimaryKey: false;
75
+ isAutoincrement: false;
76
+ hasRuntimeDefault: false;
77
+ enumValues: [string, ...string[]];
78
+ baseColumn: never;
79
+ identity: undefined;
80
+ generated: undefined;
81
+ }, {}, {}>;
82
+ entity_id: import("drizzle-orm/pg-core").PgColumn<{
83
+ name: "entity_id";
84
+ tableName: "catalog_overlay";
85
+ dataType: "string";
86
+ columnType: "PgText";
87
+ data: string;
88
+ driverParam: string;
89
+ notNull: true;
90
+ hasDefault: false;
91
+ isPrimaryKey: false;
92
+ isAutoincrement: false;
93
+ hasRuntimeDefault: false;
94
+ enumValues: [string, ...string[]];
95
+ baseColumn: never;
96
+ identity: undefined;
97
+ generated: undefined;
98
+ }, {}, {}>;
99
+ field_path: import("drizzle-orm/pg-core").PgColumn<{
100
+ name: "field_path";
101
+ tableName: "catalog_overlay";
102
+ dataType: "string";
103
+ columnType: "PgText";
104
+ data: string;
105
+ driverParam: string;
106
+ notNull: true;
107
+ hasDefault: false;
108
+ isPrimaryKey: false;
109
+ isAutoincrement: false;
110
+ hasRuntimeDefault: false;
111
+ enumValues: [string, ...string[]];
112
+ baseColumn: never;
113
+ identity: undefined;
114
+ generated: undefined;
115
+ }, {}, {}>;
116
+ locale: import("drizzle-orm/pg-core").PgColumn<{
117
+ name: "locale";
118
+ tableName: "catalog_overlay";
119
+ dataType: "string";
120
+ columnType: "PgText";
121
+ data: string;
122
+ driverParam: string;
123
+ notNull: true;
124
+ hasDefault: true;
125
+ isPrimaryKey: false;
126
+ isAutoincrement: false;
127
+ hasRuntimeDefault: false;
128
+ enumValues: [string, ...string[]];
129
+ baseColumn: never;
130
+ identity: undefined;
131
+ generated: undefined;
132
+ }, {}, {}>;
133
+ audience: import("drizzle-orm/pg-core").PgColumn<{
134
+ name: "audience";
135
+ tableName: "catalog_overlay";
136
+ dataType: "string";
137
+ columnType: "PgText";
138
+ data: "default" | Visibility;
139
+ driverParam: string;
140
+ notNull: true;
141
+ hasDefault: true;
142
+ isPrimaryKey: false;
143
+ isAutoincrement: false;
144
+ hasRuntimeDefault: false;
145
+ enumValues: [string, ...string[]];
146
+ baseColumn: never;
147
+ identity: undefined;
148
+ generated: undefined;
149
+ }, {}, {
150
+ $type: "default" | Visibility;
151
+ }>;
152
+ market: import("drizzle-orm/pg-core").PgColumn<{
153
+ name: "market";
154
+ tableName: "catalog_overlay";
155
+ dataType: "string";
156
+ columnType: "PgText";
157
+ data: string;
158
+ driverParam: string;
159
+ notNull: true;
160
+ hasDefault: true;
161
+ isPrimaryKey: false;
162
+ isAutoincrement: false;
163
+ hasRuntimeDefault: false;
164
+ enumValues: [string, ...string[]];
165
+ baseColumn: never;
166
+ identity: undefined;
167
+ generated: undefined;
168
+ }, {}, {}>;
169
+ value: import("drizzle-orm/pg-core").PgColumn<{
170
+ name: "value";
171
+ tableName: "catalog_overlay";
172
+ dataType: "json";
173
+ columnType: "PgJsonb";
174
+ data: unknown;
175
+ driverParam: unknown;
176
+ notNull: true;
177
+ hasDefault: false;
178
+ isPrimaryKey: false;
179
+ isAutoincrement: false;
180
+ hasRuntimeDefault: false;
181
+ enumValues: undefined;
182
+ baseColumn: never;
183
+ identity: undefined;
184
+ generated: undefined;
185
+ }, {}, {}>;
186
+ origin: import("drizzle-orm/pg-core").PgColumn<{
187
+ name: "origin";
188
+ tableName: "catalog_overlay";
189
+ dataType: "json";
190
+ columnType: "PgJsonb";
191
+ data: OverlayOrigin;
192
+ driverParam: unknown;
193
+ notNull: true;
194
+ hasDefault: false;
195
+ isPrimaryKey: false;
196
+ isAutoincrement: false;
197
+ hasRuntimeDefault: false;
198
+ enumValues: undefined;
199
+ baseColumn: never;
200
+ identity: undefined;
201
+ generated: undefined;
202
+ }, {}, {
203
+ $type: OverlayOrigin;
204
+ }>;
205
+ deleted_at: import("drizzle-orm/pg-core").PgColumn<{
206
+ name: "deleted_at";
207
+ tableName: "catalog_overlay";
208
+ dataType: "date";
209
+ columnType: "PgTimestamp";
210
+ data: Date;
211
+ driverParam: string;
212
+ notNull: false;
213
+ hasDefault: false;
214
+ isPrimaryKey: false;
215
+ isAutoincrement: false;
216
+ hasRuntimeDefault: false;
217
+ enumValues: undefined;
218
+ baseColumn: never;
219
+ identity: undefined;
220
+ generated: undefined;
221
+ }, {}, {}>;
222
+ created_at: import("drizzle-orm/pg-core").PgColumn<{
223
+ name: "created_at";
224
+ tableName: "catalog_overlay";
225
+ dataType: "date";
226
+ columnType: "PgTimestamp";
227
+ data: Date;
228
+ driverParam: string;
229
+ notNull: true;
230
+ hasDefault: true;
231
+ isPrimaryKey: false;
232
+ isAutoincrement: false;
233
+ hasRuntimeDefault: false;
234
+ enumValues: undefined;
235
+ baseColumn: never;
236
+ identity: undefined;
237
+ generated: undefined;
238
+ }, {}, {}>;
239
+ updated_at: import("drizzle-orm/pg-core").PgColumn<{
240
+ name: "updated_at";
241
+ tableName: "catalog_overlay";
242
+ dataType: "date";
243
+ columnType: "PgTimestamp";
244
+ data: Date;
245
+ driverParam: string;
246
+ notNull: true;
247
+ hasDefault: true;
248
+ isPrimaryKey: false;
249
+ isAutoincrement: false;
250
+ hasRuntimeDefault: false;
251
+ enumValues: undefined;
252
+ baseColumn: never;
253
+ identity: undefined;
254
+ generated: undefined;
255
+ }, {}, {}>;
256
+ };
257
+ dialect: "pg";
258
+ }>;
259
+ export type InsertCatalogOverlay = typeof catalogOverlayTable.$inferInsert;
260
+ export type SelectCatalogOverlay = typeof catalogOverlayTable.$inferSelect;
261
+ /**
262
+ * Foreign-key column helper for tables that reference an overlay row.
263
+ * Rare — consumers typically query overlays by entity, not by FK.
264
+ */
265
+ export declare const overlayIdRef: (columnName: string) => import("drizzle-orm/pg-core").PgTextBuilderInitial<string, [string, ...string[]]>;
266
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/overlay/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,YAAY,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4D/B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAA;AAC1E,MAAM,MAAM,oBAAoB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAA;AAE1E;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,sFAA0B,CAAA"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Overlay store schema — editorial overrides keyed by
3
+ * `(entity_module, entity_id, field_path, locale, audience, market)`.
4
+ *
5
+ * One overlay table serves every vertical. Rows hold the override value plus
6
+ * provenance about *which* writer (admin UI / CMS plugin / bulk import / AI /
7
+ * external API) produced the override, for audit and revert workflows.
8
+ *
9
+ * See `docs/architecture/catalog-architecture.md` §5.2 for the full design.
10
+ */
11
+ import { typeId, typeIdRef } from "@voyant-travel/db/lib/typeid-column";
12
+ import { sql } from "drizzle-orm";
13
+ import { index, jsonb, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
14
+ /**
15
+ * Sentinel value used in `locale`, `audience`, and `market` columns to mark
16
+ * "no specific scope" — the broadest fallback in the resolver chain.
17
+ */
18
+ export const OVERLAY_DEFAULT_SCOPE = "default";
19
+ /**
20
+ * `catalog_overlay` — single table holding editorial overrides for every
21
+ * vertical. Composite uniqueness on `(entity_module, entity_id, field_path,
22
+ * locale, audience, market)` prevents duplicate overlays for the same scope.
23
+ */
24
+ export const catalogOverlayTable = pgTable("catalog_overlay", {
25
+ id: typeId("catalog_overlay"),
26
+ // Entity identity (which vertical, which entity).
27
+ entity_module: text("entity_module").notNull(),
28
+ entity_id: text("entity_id").notNull(),
29
+ // Field-policy path the override targets. Validated against the vertical's
30
+ // field policy at write time (the policy must exist and must allow
31
+ // overrides for the requesting editor role).
32
+ field_path: text("field_path").notNull(),
33
+ // Variant axes. Each defaults to OVERLAY_DEFAULT_SCOPE for entries that
34
+ // apply across the broadest scope.
35
+ locale: text("locale").notNull().default(OVERLAY_DEFAULT_SCOPE),
36
+ audience: text("audience")
37
+ .$type()
38
+ .notNull()
39
+ .default(OVERLAY_DEFAULT_SCOPE),
40
+ market: text("market").notNull().default(OVERLAY_DEFAULT_SCOPE),
41
+ // Override value. JSONB to accommodate every field type (strings, lists,
42
+ // structured objects, etc.). The resolver pairs this with the field policy
43
+ // to apply the correct merge rule.
44
+ value: jsonb("value").notNull(),
45
+ // Provenance: where this override came from.
46
+ origin: jsonb("origin").$type().notNull(),
47
+ // Soft-delete. When set, the row is preserved for retention / restore but
48
+ // no longer active in the resolver merge.
49
+ deleted_at: timestamp("deleted_at", { withTimezone: true }),
50
+ created_at: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
51
+ updated_at: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
52
+ }, (table) => [
53
+ // The variant-tuple identifies one overlay row uniquely. `WHERE deleted_at
54
+ // IS NULL` is enforced via partial unique index so soft-deleted rows can
55
+ // be re-created without conflict.
56
+ uniqueIndex("catalog_overlay_variant_uniq")
57
+ .on(table.entity_module, table.entity_id, table.field_path, table.locale, table.audience, table.market)
58
+ // agent-quality: raw-sql reviewed -- owner: catalog; dynamic SQL interpolation uses Drizzle parameter binding or vetted SQL identifiers.
59
+ .where(sql `${table.deleted_at} IS NULL`),
60
+ // Lookup index for the resolver: given an entity, find all its active
61
+ // overlays in one query.
62
+ index("catalog_overlay_entity_idx").on(table.entity_module, table.entity_id, table.deleted_at),
63
+ // Lookup index for cross-source queries: find overlays by origin (e.g.
64
+ // "all overlays from this CMS plugin" for revert / re-sync workflows).
65
+ index("catalog_overlay_origin_idx").on(table.origin),
66
+ ]);
67
+ /**
68
+ * Foreign-key column helper for tables that reference an overlay row.
69
+ * Rare — consumers typically query overlays by entity, not by FK.
70
+ */
71
+ export const overlayIdRef = (columnName) => typeIdRef(columnName);
@@ -0,0 +1,2 @@
1
+ export * from "@voyant-travel/catalog-contracts/provenance";
2
+ //# sourceMappingURL=provenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA,cAAc,6CAA6C,CAAA"}
@@ -0,0 +1 @@
1
+ export * from "@voyant-travel/catalog-contracts/provenance";
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Sourced-entry store — durable provenance + projection capture for every
3
+ * non-owned entity that lands in the catalog plane via `discover()`.
4
+ *
5
+ * This is the load-bearing prerequisite for the content cache, the read
6
+ * service, drift invalidation, and snapshot capture. All of them assume
7
+ * there's a durable local row per sourced entity that records *what we
8
+ * know about it locally* — provenance (which adapter, which connection,
9
+ * which upstream id), lifecycle (when first seen, when last seen, whether
10
+ * still active), and the canonical local copy of the indexed projection.
11
+ *
12
+ * Owned entities do NOT have a row here — `provenance.source_kind ===
13
+ * "owned"` reads provenance from the vertical's owned schema. The
14
+ * sourced-entry store is sourced-only.
15
+ *
16
+ * See `docs/architecture/catalog-sourced-content.md` §2.5 for the full
17
+ * design.
18
+ */
19
+ import type { SourceFreshness } from "./contract.js";
20
+ /**
21
+ * Lifecycle status for a sourced entry. Independent of any drift / hold
22
+ * the booking engine might apply — this tracks whether the upstream still
23
+ * advertises the entity, not whether it's bookable right now.
24
+ */
25
+ export type SourcedEntryStatus = "active" | "withdrawn" | "delisted";
26
+ /**
27
+ * `catalog_sourced_entries` — single durable record per sourced entity,
28
+ * keyed two ways: by Voyant-side `(entity_module, entity_id)` for
29
+ * read-path lookup, and by upstream-side `(source_kind,
30
+ * source_connection_id, source_ref)` for discover-time idempotency.
31
+ *
32
+ * The `projection` JSONB column is the canonical local copy of what
33
+ * `adapter.discover()` returned. Read it for thin-content synthesis (when
34
+ * the adapter declares `supportsContentFetch: false`) and for
35
+ * provenance-aware dispatch — never the search index. Search indexes are
36
+ * optimized for full-text/facet queries, not point-reads of rich detail.
37
+ */
38
+ export declare const catalogSourcedEntriesTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
39
+ name: "catalog_sourced_entries";
40
+ schema: undefined;
41
+ columns: {
42
+ id: import("drizzle-orm/pg-core").PgColumn<{
43
+ name: string;
44
+ tableName: "catalog_sourced_entries";
45
+ dataType: "string";
46
+ columnType: "PgText";
47
+ data: string;
48
+ driverParam: string;
49
+ notNull: true;
50
+ hasDefault: true;
51
+ isPrimaryKey: true;
52
+ isAutoincrement: false;
53
+ hasRuntimeDefault: true;
54
+ enumValues: [string, ...string[]];
55
+ baseColumn: never;
56
+ identity: undefined;
57
+ generated: undefined;
58
+ }, {}, {}>;
59
+ entity_module: import("drizzle-orm/pg-core").PgColumn<{
60
+ name: "entity_module";
61
+ tableName: "catalog_sourced_entries";
62
+ dataType: "string";
63
+ columnType: "PgText";
64
+ data: string;
65
+ driverParam: string;
66
+ notNull: true;
67
+ hasDefault: false;
68
+ isPrimaryKey: false;
69
+ isAutoincrement: false;
70
+ hasRuntimeDefault: false;
71
+ enumValues: [string, ...string[]];
72
+ baseColumn: never;
73
+ identity: undefined;
74
+ generated: undefined;
75
+ }, {}, {}>;
76
+ entity_id: import("drizzle-orm/pg-core").PgColumn<{
77
+ name: "entity_id";
78
+ tableName: "catalog_sourced_entries";
79
+ dataType: "string";
80
+ columnType: "PgText";
81
+ data: string;
82
+ driverParam: string;
83
+ notNull: true;
84
+ hasDefault: false;
85
+ isPrimaryKey: false;
86
+ isAutoincrement: false;
87
+ hasRuntimeDefault: false;
88
+ enumValues: [string, ...string[]];
89
+ baseColumn: never;
90
+ identity: undefined;
91
+ generated: undefined;
92
+ }, {}, {}>;
93
+ source_kind: import("drizzle-orm/pg-core").PgColumn<{
94
+ name: "source_kind";
95
+ tableName: "catalog_sourced_entries";
96
+ dataType: "string";
97
+ columnType: "PgText";
98
+ data: string;
99
+ driverParam: string;
100
+ notNull: true;
101
+ hasDefault: false;
102
+ isPrimaryKey: false;
103
+ isAutoincrement: false;
104
+ hasRuntimeDefault: false;
105
+ enumValues: [string, ...string[]];
106
+ baseColumn: never;
107
+ identity: undefined;
108
+ generated: undefined;
109
+ }, {}, {
110
+ $type: string;
111
+ }>;
112
+ source_provider: import("drizzle-orm/pg-core").PgColumn<{
113
+ name: "source_provider";
114
+ tableName: "catalog_sourced_entries";
115
+ dataType: "string";
116
+ columnType: "PgText";
117
+ data: string;
118
+ driverParam: string;
119
+ notNull: false;
120
+ hasDefault: false;
121
+ isPrimaryKey: false;
122
+ isAutoincrement: false;
123
+ hasRuntimeDefault: false;
124
+ enumValues: [string, ...string[]];
125
+ baseColumn: never;
126
+ identity: undefined;
127
+ generated: undefined;
128
+ }, {}, {}>;
129
+ source_connection_id: import("drizzle-orm/pg-core").PgColumn<{
130
+ name: "source_connection_id";
131
+ tableName: "catalog_sourced_entries";
132
+ dataType: "string";
133
+ columnType: "PgText";
134
+ data: string;
135
+ driverParam: string;
136
+ notNull: false;
137
+ hasDefault: false;
138
+ isPrimaryKey: false;
139
+ isAutoincrement: false;
140
+ hasRuntimeDefault: false;
141
+ enumValues: [string, ...string[]];
142
+ baseColumn: never;
143
+ identity: undefined;
144
+ generated: undefined;
145
+ }, {}, {}>;
146
+ source_ref: import("drizzle-orm/pg-core").PgColumn<{
147
+ name: "source_ref";
148
+ tableName: "catalog_sourced_entries";
149
+ dataType: "string";
150
+ columnType: "PgText";
151
+ data: string;
152
+ driverParam: string;
153
+ notNull: false;
154
+ hasDefault: false;
155
+ isPrimaryKey: false;
156
+ isAutoincrement: false;
157
+ hasRuntimeDefault: false;
158
+ enumValues: [string, ...string[]];
159
+ baseColumn: never;
160
+ identity: undefined;
161
+ generated: undefined;
162
+ }, {}, {}>;
163
+ source_freshness: import("drizzle-orm/pg-core").PgColumn<{
164
+ name: "source_freshness";
165
+ tableName: "catalog_sourced_entries";
166
+ dataType: "string";
167
+ columnType: "PgText";
168
+ data: SourceFreshness;
169
+ driverParam: string;
170
+ notNull: true;
171
+ hasDefault: false;
172
+ isPrimaryKey: false;
173
+ isAutoincrement: false;
174
+ hasRuntimeDefault: false;
175
+ enumValues: [string, ...string[]];
176
+ baseColumn: never;
177
+ identity: undefined;
178
+ generated: undefined;
179
+ }, {}, {
180
+ $type: SourceFreshness;
181
+ }>;
182
+ last_sourced_at: import("drizzle-orm/pg-core").PgColumn<{
183
+ name: "last_sourced_at";
184
+ tableName: "catalog_sourced_entries";
185
+ dataType: "date";
186
+ columnType: "PgTimestamp";
187
+ data: Date;
188
+ driverParam: string;
189
+ notNull: false;
190
+ hasDefault: false;
191
+ isPrimaryKey: false;
192
+ isAutoincrement: false;
193
+ hasRuntimeDefault: false;
194
+ enumValues: undefined;
195
+ baseColumn: never;
196
+ identity: undefined;
197
+ generated: undefined;
198
+ }, {}, {}>;
199
+ status: import("drizzle-orm/pg-core").PgColumn<{
200
+ name: "status";
201
+ tableName: "catalog_sourced_entries";
202
+ dataType: "string";
203
+ columnType: "PgText";
204
+ data: SourcedEntryStatus;
205
+ driverParam: string;
206
+ notNull: true;
207
+ hasDefault: true;
208
+ isPrimaryKey: false;
209
+ isAutoincrement: false;
210
+ hasRuntimeDefault: false;
211
+ enumValues: [string, ...string[]];
212
+ baseColumn: never;
213
+ identity: undefined;
214
+ generated: undefined;
215
+ }, {}, {
216
+ $type: SourcedEntryStatus;
217
+ }>;
218
+ first_seen_at: import("drizzle-orm/pg-core").PgColumn<{
219
+ name: "first_seen_at";
220
+ tableName: "catalog_sourced_entries";
221
+ dataType: "date";
222
+ columnType: "PgTimestamp";
223
+ data: Date;
224
+ driverParam: string;
225
+ notNull: true;
226
+ hasDefault: true;
227
+ isPrimaryKey: false;
228
+ isAutoincrement: false;
229
+ hasRuntimeDefault: false;
230
+ enumValues: undefined;
231
+ baseColumn: never;
232
+ identity: undefined;
233
+ generated: undefined;
234
+ }, {}, {}>;
235
+ last_seen_at: import("drizzle-orm/pg-core").PgColumn<{
236
+ name: "last_seen_at";
237
+ tableName: "catalog_sourced_entries";
238
+ dataType: "date";
239
+ columnType: "PgTimestamp";
240
+ data: Date;
241
+ driverParam: string;
242
+ notNull: true;
243
+ hasDefault: true;
244
+ isPrimaryKey: false;
245
+ isAutoincrement: false;
246
+ hasRuntimeDefault: false;
247
+ enumValues: undefined;
248
+ baseColumn: never;
249
+ identity: undefined;
250
+ generated: undefined;
251
+ }, {}, {}>;
252
+ projection: import("drizzle-orm/pg-core").PgColumn<{
253
+ name: "projection";
254
+ tableName: "catalog_sourced_entries";
255
+ dataType: "json";
256
+ columnType: "PgJsonb";
257
+ data: Record<string, unknown>;
258
+ driverParam: unknown;
259
+ notNull: true;
260
+ hasDefault: false;
261
+ isPrimaryKey: false;
262
+ isAutoincrement: false;
263
+ hasRuntimeDefault: false;
264
+ enumValues: undefined;
265
+ baseColumn: never;
266
+ identity: undefined;
267
+ generated: undefined;
268
+ }, {}, {
269
+ $type: Record<string, unknown>;
270
+ }>;
271
+ projection_etag: import("drizzle-orm/pg-core").PgColumn<{
272
+ name: "projection_etag";
273
+ tableName: "catalog_sourced_entries";
274
+ dataType: "string";
275
+ columnType: "PgText";
276
+ data: string;
277
+ driverParam: string;
278
+ notNull: false;
279
+ hasDefault: false;
280
+ isPrimaryKey: false;
281
+ isAutoincrement: false;
282
+ hasRuntimeDefault: false;
283
+ enumValues: [string, ...string[]];
284
+ baseColumn: never;
285
+ identity: undefined;
286
+ generated: undefined;
287
+ }, {}, {}>;
288
+ projection_seen_at: import("drizzle-orm/pg-core").PgColumn<{
289
+ name: "projection_seen_at";
290
+ tableName: "catalog_sourced_entries";
291
+ dataType: "date";
292
+ columnType: "PgTimestamp";
293
+ data: Date;
294
+ driverParam: string;
295
+ notNull: true;
296
+ hasDefault: true;
297
+ isPrimaryKey: false;
298
+ isAutoincrement: false;
299
+ hasRuntimeDefault: false;
300
+ enumValues: undefined;
301
+ baseColumn: never;
302
+ identity: undefined;
303
+ generated: undefined;
304
+ }, {}, {}>;
305
+ created_at: import("drizzle-orm/pg-core").PgColumn<{
306
+ name: "created_at";
307
+ tableName: "catalog_sourced_entries";
308
+ dataType: "date";
309
+ columnType: "PgTimestamp";
310
+ data: Date;
311
+ driverParam: string;
312
+ notNull: true;
313
+ hasDefault: true;
314
+ isPrimaryKey: false;
315
+ isAutoincrement: false;
316
+ hasRuntimeDefault: false;
317
+ enumValues: undefined;
318
+ baseColumn: never;
319
+ identity: undefined;
320
+ generated: undefined;
321
+ }, {}, {}>;
322
+ updated_at: import("drizzle-orm/pg-core").PgColumn<{
323
+ name: "updated_at";
324
+ tableName: "catalog_sourced_entries";
325
+ dataType: "date";
326
+ columnType: "PgTimestamp";
327
+ data: Date;
328
+ driverParam: string;
329
+ notNull: true;
330
+ hasDefault: true;
331
+ isPrimaryKey: false;
332
+ isAutoincrement: false;
333
+ hasRuntimeDefault: false;
334
+ enumValues: undefined;
335
+ baseColumn: never;
336
+ identity: undefined;
337
+ generated: undefined;
338
+ }, {}, {}>;
339
+ };
340
+ dialect: "pg";
341
+ }>;
342
+ export type InsertCatalogSourcedEntry = typeof catalogSourcedEntriesTable.$inferInsert;
343
+ export type SelectCatalogSourcedEntry = typeof catalogSourcedEntriesTable.$inferSelect;
344
+ //# sourceMappingURL=schema-sourced-entries.d.ts.map