@voyantjs/products 0.1.1 → 0.3.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.
Files changed (39) hide show
  1. package/dist/routes.d.ts +4 -4
  2. package/dist/schema-core.d.ts +897 -0
  3. package/dist/schema-core.d.ts.map +1 -0
  4. package/dist/schema-core.js +77 -0
  5. package/dist/schema-itinerary.d.ts +828 -0
  6. package/dist/schema-itinerary.d.ts.map +1 -0
  7. package/dist/schema-itinerary.js +77 -0
  8. package/dist/schema-relations.d.ts +99 -0
  9. package/dist/schema-relations.d.ts.map +1 -0
  10. package/dist/schema-relations.js +155 -0
  11. package/dist/schema-settings.d.ts +1749 -0
  12. package/dist/schema-settings.d.ts.map +1 -0
  13. package/dist/schema-settings.js +175 -0
  14. package/dist/schema-shared.d.ts +15 -0
  15. package/dist/schema-shared.d.ts.map +1 -0
  16. package/dist/schema-shared.js +91 -0
  17. package/dist/schema-taxonomy.d.ts +573 -0
  18. package/dist/schema-taxonomy.d.ts.map +1 -0
  19. package/dist/schema-taxonomy.js +65 -0
  20. package/dist/schema.d.ts +6 -4155
  21. package/dist/schema.d.ts.map +1 -1
  22. package/dist/schema.js +6 -653
  23. package/dist/service.d.ts +4 -4
  24. package/dist/validation-config.d.ts +233 -0
  25. package/dist/validation-config.d.ts.map +1 -0
  26. package/dist/validation-config.js +73 -0
  27. package/dist/validation-content.d.ts +358 -0
  28. package/dist/validation-content.d.ts.map +1 -0
  29. package/dist/validation-content.js +177 -0
  30. package/dist/validation-core.d.ts +268 -0
  31. package/dist/validation-core.d.ts.map +1 -0
  32. package/dist/validation-core.js +91 -0
  33. package/dist/validation-shared.d.ts +103 -0
  34. package/dist/validation-shared.d.ts.map +1 -0
  35. package/dist/validation-shared.js +86 -0
  36. package/dist/validation.d.ts +4 -854
  37. package/dist/validation.d.ts.map +1 -1
  38. package/dist/validation.js +4 -433
  39. package/package.json +4 -4
package/dist/schema.js CHANGED
@@ -1,653 +1,6 @@
1
- import { typeId, typeIdRef } from "@voyantjs/db/lib/typeid-column";
2
- import { relations } from "drizzle-orm";
3
- import { boolean, date, doublePrecision, index, integer, jsonb, pgEnum, pgTable, primaryKey, text, timestamp, uniqueIndex, } from "drizzle-orm/pg-core";
4
- export const productStatusEnum = pgEnum("product_status", ["draft", "active", "archived"]);
5
- export const productOptionStatusEnum = pgEnum("product_option_status", [
6
- "draft",
7
- "active",
8
- "archived",
9
- ]);
10
- export const optionUnitTypeEnum = pgEnum("option_unit_type", [
11
- "person",
12
- "group",
13
- "room",
14
- "vehicle",
15
- "service",
16
- "other",
17
- ]);
18
- export const productBookingModeEnum = pgEnum("product_booking_mode", [
19
- "date",
20
- "date_time",
21
- "open",
22
- "stay",
23
- "transfer",
24
- "itinerary",
25
- "other",
26
- ]);
27
- export const productCapacityModeEnum = pgEnum("product_capacity_mode", [
28
- "free_sale",
29
- "limited",
30
- "on_request",
31
- ]);
32
- export const productVisibilityEnum = pgEnum("product_visibility", ["public", "private", "hidden"]);
33
- export const productActivationModeEnum = pgEnum("product_activation_mode", [
34
- "manual",
35
- "scheduled",
36
- "channel_controlled",
37
- ]);
38
- export const productTicketFulfillmentEnum = pgEnum("product_ticket_fulfillment", [
39
- "none",
40
- "per_booking",
41
- "per_participant",
42
- "per_item",
43
- ]);
44
- export const productDeliveryFormatEnum = pgEnum("product_delivery_format", [
45
- "voucher",
46
- "ticket",
47
- "pdf",
48
- "qr_code",
49
- "barcode",
50
- "email",
51
- "mobile",
52
- "none",
53
- ]);
54
- export const productCapabilityEnum = pgEnum("product_capability", [
55
- "instant_confirmation",
56
- "on_request",
57
- "pickup_available",
58
- "dropoff_available",
59
- "guided",
60
- "private",
61
- "shared",
62
- "digital_ticket",
63
- "voucher_required",
64
- "external_inventory",
65
- "multi_day",
66
- "accommodation",
67
- "transport",
68
- ]);
69
- export const productFeatureTypeEnum = pgEnum("product_feature_type", [
70
- "inclusion",
71
- "exclusion",
72
- "highlight",
73
- "important_information",
74
- "other",
75
- ]);
76
- export const productLocationTypeEnum = pgEnum("product_location_type", [
77
- "start",
78
- "end",
79
- "meeting_point",
80
- "pickup",
81
- "dropoff",
82
- "point_of_interest",
83
- "other",
84
- ]);
85
- // Inlined from suppliers to avoid cross-package schema dependency
86
- export const serviceTypeEnum = pgEnum("service_type", [
87
- "accommodation",
88
- "transfer",
89
- "experience",
90
- "guide",
91
- "meal",
92
- "other",
93
- ]);
94
- // ---------- products ----------
95
- export const products = pgTable("products", {
96
- id: typeId("products"),
97
- name: text("name").notNull(),
98
- status: productStatusEnum("status").notNull().default("draft"),
99
- description: text("description"),
100
- bookingMode: productBookingModeEnum("booking_mode").notNull().default("date"),
101
- capacityMode: productCapacityModeEnum("capacity_mode").notNull().default("limited"),
102
- timezone: text("timezone"),
103
- visibility: productVisibilityEnum("visibility").notNull().default("private"),
104
- activated: boolean("activated").notNull().default(false),
105
- reservationTimeoutMinutes: integer("reservation_timeout_minutes"),
106
- // Pricing
107
- sellCurrency: text("sell_currency").notNull(),
108
- sellAmountCents: integer("sell_amount_cents"),
109
- costAmountCents: integer("cost_amount_cents"),
110
- marginPercent: integer("margin_percent"),
111
- // Client link — person/organization associations now live in cross-module link tables
112
- // (see `defineLink(crmModule.linkable.person, productsModule.linkable.product)`).
113
- facilityId: text("facility_id"),
114
- // Trip details
115
- startDate: date("start_date"),
116
- endDate: date("end_date"),
117
- pax: integer("pax"),
118
- // Taxonomy
119
- productTypeId: text("product_type_id"),
120
- // Metadata
121
- tags: jsonb("tags").$type().default([]),
122
- // Timestamps
123
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
124
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
125
- }, (table) => [
126
- index("idx_products_status").on(table.status),
127
- index("idx_products_facility").on(table.facilityId),
128
- index("idx_products_product_type").on(table.productTypeId),
129
- ]);
130
- // ---------- product_options ----------
131
- export const productOptions = pgTable("product_options", {
132
- id: typeId("product_options"),
133
- productId: typeIdRef("product_id")
134
- .notNull()
135
- .references(() => products.id, { onDelete: "cascade" }),
136
- name: text("name").notNull(),
137
- code: text("code"),
138
- description: text("description"),
139
- status: productOptionStatusEnum("status").notNull().default("draft"),
140
- isDefault: boolean("is_default").notNull().default(false),
141
- sortOrder: integer("sort_order").notNull().default(0),
142
- availableFrom: date("available_from"),
143
- availableTo: date("available_to"),
144
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
145
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
146
- }, (table) => [
147
- index("idx_product_options_product").on(table.productId),
148
- index("idx_product_options_status").on(table.status),
149
- index("idx_product_options_default").on(table.isDefault),
150
- uniqueIndex("uidx_product_options_product_code").on(table.productId, table.code),
151
- ]);
152
- // ---------- option_units ----------
153
- export const optionUnits = pgTable("option_units", {
154
- id: typeId("option_units"),
155
- optionId: typeIdRef("option_id")
156
- .notNull()
157
- .references(() => productOptions.id, { onDelete: "cascade" }),
158
- name: text("name").notNull(),
159
- code: text("code"),
160
- description: text("description"),
161
- unitType: optionUnitTypeEnum("unit_type").notNull().default("person"),
162
- minQuantity: integer("min_quantity"),
163
- maxQuantity: integer("max_quantity"),
164
- minAge: integer("min_age"),
165
- maxAge: integer("max_age"),
166
- occupancyMin: integer("occupancy_min"),
167
- occupancyMax: integer("occupancy_max"),
168
- isRequired: boolean("is_required").notNull().default(false),
169
- isHidden: boolean("is_hidden").notNull().default(false),
170
- sortOrder: integer("sort_order").notNull().default(0),
171
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
172
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
173
- }, (table) => [
174
- index("idx_option_units_option").on(table.optionId),
175
- index("idx_option_units_type").on(table.unitType),
176
- uniqueIndex("uidx_option_units_option_code").on(table.optionId, table.code),
177
- ]);
178
- // ---------- product operating configuration ----------
179
- export const productActivationSettings = pgTable("product_activation_settings", {
180
- id: typeId("product_activation_settings"),
181
- productId: typeIdRef("product_id")
182
- .notNull()
183
- .references(() => products.id, { onDelete: "cascade" }),
184
- activationMode: productActivationModeEnum("activation_mode").notNull().default("manual"),
185
- activateAt: timestamp("activate_at", { withTimezone: true }),
186
- deactivateAt: timestamp("deactivate_at", { withTimezone: true }),
187
- sellAt: timestamp("sell_at", { withTimezone: true }),
188
- stopSellAt: timestamp("stop_sell_at", { withTimezone: true }),
189
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
190
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
191
- }, (table) => [
192
- uniqueIndex("uidx_product_activation_settings_product").on(table.productId),
193
- index("idx_product_activation_settings_mode").on(table.activationMode),
194
- ]);
195
- export const productTicketSettings = pgTable("product_ticket_settings", {
196
- id: typeId("product_ticket_settings"),
197
- productId: typeIdRef("product_id")
198
- .notNull()
199
- .references(() => products.id, { onDelete: "cascade" }),
200
- fulfillmentMode: productTicketFulfillmentEnum("fulfillment_mode").notNull().default("none"),
201
- defaultDeliveryFormat: productDeliveryFormatEnum("default_delivery_format")
202
- .notNull()
203
- .default("none"),
204
- ticketPerUnit: boolean("ticket_per_unit").notNull().default(false),
205
- barcodeFormat: text("barcode_format"),
206
- voucherMessage: text("voucher_message"),
207
- ticketMessage: text("ticket_message"),
208
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
209
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
210
- }, (table) => [uniqueIndex("uidx_product_ticket_settings_product").on(table.productId)]);
211
- export const productVisibilitySettings = pgTable("product_visibility_settings", {
212
- id: typeId("product_visibility_settings"),
213
- productId: typeIdRef("product_id")
214
- .notNull()
215
- .references(() => products.id, { onDelete: "cascade" }),
216
- isSearchable: boolean("is_searchable").notNull().default(false),
217
- isBookable: boolean("is_bookable").notNull().default(false),
218
- isFeatured: boolean("is_featured").notNull().default(false),
219
- requiresAuthentication: boolean("requires_authentication").notNull().default(false),
220
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
221
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
222
- }, (table) => [uniqueIndex("uidx_product_visibility_settings_product").on(table.productId)]);
223
- export const productCapabilities = pgTable("product_capabilities", {
224
- id: typeId("product_capabilities"),
225
- productId: typeIdRef("product_id")
226
- .notNull()
227
- .references(() => products.id, { onDelete: "cascade" }),
228
- capability: productCapabilityEnum("capability").notNull(),
229
- enabled: boolean("enabled").notNull().default(true),
230
- notes: text("notes"),
231
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
232
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
233
- }, (table) => [
234
- index("idx_product_capabilities_product").on(table.productId),
235
- index("idx_product_capabilities_capability").on(table.capability),
236
- uniqueIndex("uidx_product_capabilities_product_capability").on(table.productId, table.capability),
237
- ]);
238
- export const productDeliveryFormats = pgTable("product_delivery_formats", {
239
- id: typeId("product_delivery_formats"),
240
- productId: typeIdRef("product_id")
241
- .notNull()
242
- .references(() => products.id, { onDelete: "cascade" }),
243
- format: productDeliveryFormatEnum("format").notNull(),
244
- isDefault: boolean("is_default").notNull().default(false),
245
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
246
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
247
- }, (table) => [
248
- index("idx_product_delivery_formats_product").on(table.productId),
249
- uniqueIndex("uidx_product_delivery_formats_product_format").on(table.productId, table.format),
250
- ]);
251
- // ---------- structured content ----------
252
- export const productFeatures = pgTable("product_features", {
253
- id: typeId("product_features"),
254
- productId: typeIdRef("product_id")
255
- .notNull()
256
- .references(() => products.id, { onDelete: "cascade" }),
257
- featureType: productFeatureTypeEnum("feature_type").notNull().default("highlight"),
258
- title: text("title").notNull(),
259
- description: text("description"),
260
- sortOrder: integer("sort_order").notNull().default(0),
261
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
262
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
263
- }, (table) => [
264
- index("idx_product_features_product").on(table.productId),
265
- index("idx_product_features_type").on(table.featureType),
266
- ]);
267
- export const productFaqs = pgTable("product_faqs", {
268
- id: typeId("product_faqs"),
269
- productId: typeIdRef("product_id")
270
- .notNull()
271
- .references(() => products.id, { onDelete: "cascade" }),
272
- question: text("question").notNull(),
273
- answer: text("answer").notNull(),
274
- sortOrder: integer("sort_order").notNull().default(0),
275
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
276
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
277
- }, (table) => [index("idx_product_faqs_product").on(table.productId)]);
278
- export const productLocations = pgTable("product_locations", {
279
- id: typeId("product_locations"),
280
- productId: typeIdRef("product_id")
281
- .notNull()
282
- .references(() => products.id, { onDelete: "cascade" }),
283
- locationType: productLocationTypeEnum("location_type").notNull().default("point_of_interest"),
284
- title: text("title").notNull(),
285
- address: text("address"),
286
- city: text("city"),
287
- countryCode: text("country_code"),
288
- latitude: doublePrecision("latitude"),
289
- longitude: doublePrecision("longitude"),
290
- googlePlaceId: text("google_place_id"),
291
- applePlaceId: text("apple_place_id"),
292
- tripadvisorLocationId: text("tripadvisor_location_id"),
293
- sortOrder: integer("sort_order").notNull().default(0),
294
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
295
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
296
- }, (table) => [
297
- index("idx_product_locations_product").on(table.productId),
298
- index("idx_product_locations_type").on(table.locationType),
299
- ]);
300
- // ---------- translations ----------
301
- export const productTranslations = pgTable("product_translations", {
302
- id: typeId("product_translations"),
303
- productId: typeIdRef("product_id")
304
- .notNull()
305
- .references(() => products.id, { onDelete: "cascade" }),
306
- languageTag: text("language_tag").notNull(),
307
- slug: text("slug"),
308
- name: text("name").notNull(),
309
- shortDescription: text("short_description"),
310
- description: text("description"),
311
- seoTitle: text("seo_title"),
312
- seoDescription: text("seo_description"),
313
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
314
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
315
- }, (table) => [
316
- index("idx_product_translations_product").on(table.productId),
317
- index("idx_product_translations_language").on(table.languageTag),
318
- uniqueIndex("uidx_product_translations_product_language").on(table.productId, table.languageTag),
319
- ]);
320
- export const productOptionTranslations = pgTable("product_option_translations", {
321
- id: typeId("product_option_translations"),
322
- optionId: typeIdRef("option_id")
323
- .notNull()
324
- .references(() => productOptions.id, { onDelete: "cascade" }),
325
- languageTag: text("language_tag").notNull(),
326
- name: text("name").notNull(),
327
- shortDescription: text("short_description"),
328
- description: text("description"),
329
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
330
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
331
- }, (table) => [
332
- index("idx_product_option_translations_option").on(table.optionId),
333
- index("idx_product_option_translations_language").on(table.languageTag),
334
- uniqueIndex("uidx_product_option_translations_option_language").on(table.optionId, table.languageTag),
335
- ]);
336
- export const optionUnitTranslations = pgTable("option_unit_translations", {
337
- id: typeId("option_unit_translations"),
338
- unitId: typeIdRef("unit_id")
339
- .notNull()
340
- .references(() => optionUnits.id, { onDelete: "cascade" }),
341
- languageTag: text("language_tag").notNull(),
342
- name: text("name").notNull(),
343
- shortDescription: text("short_description"),
344
- description: text("description"),
345
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
346
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
347
- }, (table) => [
348
- index("idx_option_unit_translations_unit").on(table.unitId),
349
- index("idx_option_unit_translations_language").on(table.languageTag),
350
- uniqueIndex("uidx_option_unit_translations_unit_language").on(table.unitId, table.languageTag),
351
- ]);
352
- // ---------- product_days ----------
353
- export const productDays = pgTable("product_days", {
354
- id: typeId("product_days"),
355
- productId: typeIdRef("product_id")
356
- .notNull()
357
- .references(() => products.id, { onDelete: "cascade" }),
358
- dayNumber: integer("day_number").notNull(),
359
- title: text("title"),
360
- description: text("description"),
361
- location: text("location"),
362
- // Timestamps
363
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
364
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
365
- }, (table) => [index("idx_product_days_product").on(table.productId)]);
366
- // ---------- product_day_services ----------
367
- export const productDayServices = pgTable("product_day_services", {
368
- id: typeId("product_day_services"),
369
- dayId: typeIdRef("day_id")
370
- .notNull()
371
- .references(() => productDays.id, { onDelete: "cascade" }),
372
- // Supplier link (snapshot)
373
- supplierServiceId: text("supplier_service_id"),
374
- serviceType: serviceTypeEnum("service_type").notNull(),
375
- name: text("name").notNull(),
376
- description: text("description"),
377
- // Cost (independent currency per service)
378
- costCurrency: text("cost_currency").notNull(),
379
- costAmountCents: integer("cost_amount_cents").notNull(),
380
- quantity: integer("quantity").notNull().default(1),
381
- sortOrder: integer("sort_order"),
382
- notes: text("notes"),
383
- // Timestamps
384
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
385
- }, (table) => [
386
- index("idx_product_day_services_day").on(table.dayId),
387
- index("idx_product_day_services_supplier_service").on(table.supplierServiceId),
388
- ]);
389
- // ---------- product_versions ----------
390
- export const productVersions = pgTable("product_versions", {
391
- id: typeId("product_versions"),
392
- productId: typeIdRef("product_id")
393
- .notNull()
394
- .references(() => products.id, { onDelete: "cascade" }),
395
- versionNumber: integer("version_number").notNull(),
396
- snapshot: jsonb("snapshot").notNull(),
397
- authorId: text("author_id").notNull(),
398
- notes: text("notes"),
399
- // Timestamps
400
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
401
- }, (table) => [index("idx_product_versions_product").on(table.productId)]);
402
- // ---------- product_notes ----------
403
- export const productNotes = pgTable("product_notes", {
404
- id: typeId("product_notes"),
405
- productId: typeIdRef("product_id")
406
- .notNull()
407
- .references(() => products.id, { onDelete: "cascade" }),
408
- authorId: text("author_id").notNull(),
409
- content: text("content").notNull(),
410
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
411
- }, (table) => [index("idx_product_notes_product").on(table.productId)]);
412
- // ---------- product_media ----------
413
- export const productMediaTypeEnum = pgEnum("product_media_type", ["image", "video", "document"]);
414
- export const productMedia = pgTable("product_media", {
415
- id: typeId("product_media"),
416
- productId: typeIdRef("product_id")
417
- .notNull()
418
- .references(() => products.id, { onDelete: "cascade" }),
419
- dayId: typeIdRef("day_id").references(() => productDays.id, { onDelete: "cascade" }),
420
- mediaType: productMediaTypeEnum("media_type").notNull(),
421
- name: text("name").notNull(),
422
- url: text("url").notNull(),
423
- storageKey: text("storage_key"),
424
- mimeType: text("mime_type"),
425
- fileSize: integer("file_size"),
426
- altText: text("alt_text"),
427
- sortOrder: integer("sort_order").notNull().default(0),
428
- isCover: boolean("is_cover").notNull().default(false),
429
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
430
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
431
- }, (table) => [
432
- index("idx_product_media_product").on(table.productId),
433
- index("idx_product_media_day").on(table.dayId),
434
- index("idx_product_media_product_day").on(table.productId, table.dayId),
435
- ]);
436
- // ---------- product_types ----------
437
- export const productTypes = pgTable("product_types", {
438
- id: typeId("product_types"),
439
- name: text("name").notNull(),
440
- code: text("code").notNull(),
441
- description: text("description"),
442
- sortOrder: integer("sort_order").notNull().default(0),
443
- active: boolean("active").notNull().default(true),
444
- metadata: jsonb("metadata").$type(),
445
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
446
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
447
- }, (table) => [
448
- uniqueIndex("uidx_product_types_code").on(table.code),
449
- index("idx_product_types_active").on(table.active),
450
- ]);
451
- // ---------- product_categories ----------
452
- export const productCategories = pgTable("product_categories", {
453
- id: typeId("product_categories"),
454
- parentId: text("parent_id"),
455
- name: text("name").notNull(),
456
- slug: text("slug").notNull(),
457
- description: text("description"),
458
- sortOrder: integer("sort_order").notNull().default(0),
459
- active: boolean("active").notNull().default(true),
460
- metadata: jsonb("metadata").$type(),
461
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
462
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
463
- }, (table) => [
464
- uniqueIndex("uidx_product_categories_slug").on(table.slug),
465
- index("idx_product_categories_parent").on(table.parentId),
466
- index("idx_product_categories_active").on(table.active),
467
- ]);
468
- // ---------- product_tags ----------
469
- export const productTags = pgTable("product_tags", {
470
- id: typeId("product_tags"),
471
- name: text("name").notNull(),
472
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
473
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
474
- }, (table) => [uniqueIndex("uidx_product_tags_name").on(table.name)]);
475
- // ---------- product_category_products (junction) ----------
476
- export const productCategoryProducts = pgTable("product_category_products", {
477
- productId: typeIdRef("product_id")
478
- .notNull()
479
- .references(() => products.id, { onDelete: "cascade" }),
480
- categoryId: typeIdRef("category_id")
481
- .notNull()
482
- .references(() => productCategories.id, { onDelete: "cascade" }),
483
- sortOrder: integer("sort_order").notNull().default(0),
484
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
485
- updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
486
- }, (table) => [
487
- primaryKey({ columns: [table.productId, table.categoryId] }),
488
- index("idx_pcp_category").on(table.categoryId),
489
- ]);
490
- // ---------- product_tag_products (junction) ----------
491
- export const productTagProducts = pgTable("product_tag_products", {
492
- productId: typeIdRef("product_id")
493
- .notNull()
494
- .references(() => products.id, { onDelete: "cascade" }),
495
- tagId: typeIdRef("tag_id")
496
- .notNull()
497
- .references(() => productTags.id, { onDelete: "cascade" }),
498
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
499
- }, (table) => [
500
- primaryKey({ columns: [table.productId, table.tagId] }),
501
- index("idx_ptp_tag").on(table.tagId),
502
- ]);
503
- // ---------- relations ----------
504
- export const productsRelations = relations(products, ({ one, many }) => ({
505
- productType: one(productTypes, {
506
- fields: [products.productTypeId],
507
- references: [productTypes.id],
508
- }),
509
- activationSettings: many(productActivationSettings),
510
- ticketSettings: many(productTicketSettings),
511
- visibilitySettings: many(productVisibilitySettings),
512
- capabilities: many(productCapabilities),
513
- deliveryFormats: many(productDeliveryFormats),
514
- features: many(productFeatures),
515
- faqs: many(productFaqs),
516
- locations: many(productLocations),
517
- options: many(productOptions),
518
- translations: many(productTranslations),
519
- days: many(productDays),
520
- versions: many(productVersions),
521
- notes: many(productNotes),
522
- media: many(productMedia),
523
- categoryLinks: many(productCategoryProducts),
524
- tagLinks: many(productTagProducts),
525
- }));
526
- export const productOptionsRelations = relations(productOptions, ({ one, many }) => ({
527
- product: one(products, { fields: [productOptions.productId], references: [products.id] }),
528
- translations: many(productOptionTranslations),
529
- units: many(optionUnits),
530
- }));
531
- export const optionUnitsRelations = relations(optionUnits, ({ one, many }) => ({
532
- option: one(productOptions, { fields: [optionUnits.optionId], references: [productOptions.id] }),
533
- translations: many(optionUnitTranslations),
534
- }));
535
- export const productActivationSettingsRelations = relations(productActivationSettings, ({ one }) => ({
536
- product: one(products, {
537
- fields: [productActivationSettings.productId],
538
- references: [products.id],
539
- }),
540
- }));
541
- export const productTicketSettingsRelations = relations(productTicketSettings, ({ one }) => ({
542
- product: one(products, {
543
- fields: [productTicketSettings.productId],
544
- references: [products.id],
545
- }),
546
- }));
547
- export const productVisibilitySettingsRelations = relations(productVisibilitySettings, ({ one }) => ({
548
- product: one(products, {
549
- fields: [productVisibilitySettings.productId],
550
- references: [products.id],
551
- }),
552
- }));
553
- export const productCapabilitiesRelations = relations(productCapabilities, ({ one }) => ({
554
- product: one(products, {
555
- fields: [productCapabilities.productId],
556
- references: [products.id],
557
- }),
558
- }));
559
- export const productDeliveryFormatsRelations = relations(productDeliveryFormats, ({ one }) => ({
560
- product: one(products, {
561
- fields: [productDeliveryFormats.productId],
562
- references: [products.id],
563
- }),
564
- }));
565
- export const productFeaturesRelations = relations(productFeatures, ({ one }) => ({
566
- product: one(products, {
567
- fields: [productFeatures.productId],
568
- references: [products.id],
569
- }),
570
- }));
571
- export const productFaqsRelations = relations(productFaqs, ({ one }) => ({
572
- product: one(products, {
573
- fields: [productFaqs.productId],
574
- references: [products.id],
575
- }),
576
- }));
577
- export const productLocationsRelations = relations(productLocations, ({ one }) => ({
578
- product: one(products, {
579
- fields: [productLocations.productId],
580
- references: [products.id],
581
- }),
582
- }));
583
- export const productTranslationsRelations = relations(productTranslations, ({ one }) => ({
584
- product: one(products, {
585
- fields: [productTranslations.productId],
586
- references: [products.id],
587
- }),
588
- }));
589
- export const productOptionTranslationsRelations = relations(productOptionTranslations, ({ one }) => ({
590
- option: one(productOptions, {
591
- fields: [productOptionTranslations.optionId],
592
- references: [productOptions.id],
593
- }),
594
- }));
595
- export const optionUnitTranslationsRelations = relations(optionUnitTranslations, ({ one }) => ({
596
- unit: one(optionUnits, {
597
- fields: [optionUnitTranslations.unitId],
598
- references: [optionUnits.id],
599
- }),
600
- }));
601
- export const productDaysRelations = relations(productDays, ({ one, many }) => ({
602
- product: one(products, { fields: [productDays.productId], references: [products.id] }),
603
- services: many(productDayServices),
604
- media: many(productMedia),
605
- }));
606
- export const productDayServicesRelations = relations(productDayServices, ({ one }) => ({
607
- day: one(productDays, { fields: [productDayServices.dayId], references: [productDays.id] }),
608
- }));
609
- export const productVersionsRelations = relations(productVersions, ({ one }) => ({
610
- product: one(products, { fields: [productVersions.productId], references: [products.id] }),
611
- }));
612
- export const productNotesRelations = relations(productNotes, ({ one }) => ({
613
- product: one(products, { fields: [productNotes.productId], references: [products.id] }),
614
- }));
615
- export const productMediaRelations = relations(productMedia, ({ one }) => ({
616
- product: one(products, { fields: [productMedia.productId], references: [products.id] }),
617
- day: one(productDays, { fields: [productMedia.dayId], references: [productDays.id] }),
618
- }));
619
- export const productTypesRelations = relations(productTypes, ({ many }) => ({
620
- products: many(products),
621
- }));
622
- export const productCategoriesRelations = relations(productCategories, ({ one, many }) => ({
623
- parent: one(productCategories, {
624
- fields: [productCategories.parentId],
625
- references: [productCategories.id],
626
- relationName: "parentChild",
627
- }),
628
- children: many(productCategories, { relationName: "parentChild" }),
629
- productLinks: many(productCategoryProducts),
630
- }));
631
- export const productTagsRelations = relations(productTags, ({ many }) => ({
632
- productLinks: many(productTagProducts),
633
- }));
634
- export const productCategoryProductsRelations = relations(productCategoryProducts, ({ one }) => ({
635
- product: one(products, {
636
- fields: [productCategoryProducts.productId],
637
- references: [products.id],
638
- }),
639
- category: one(productCategories, {
640
- fields: [productCategoryProducts.categoryId],
641
- references: [productCategories.id],
642
- }),
643
- }));
644
- export const productTagProductsRelations = relations(productTagProducts, ({ one }) => ({
645
- product: one(products, {
646
- fields: [productTagProducts.productId],
647
- references: [products.id],
648
- }),
649
- tag: one(productTags, {
650
- fields: [productTagProducts.tagId],
651
- references: [productTags.id],
652
- }),
653
- }));
1
+ export * from "./schema-core";
2
+ export * from "./schema-itinerary";
3
+ export * from "./schema-relations";
4
+ export * from "./schema-settings";
5
+ export * from "./schema-shared";
6
+ export * from "./schema-taxonomy";