@contractspec/example.marketplace 3.7.6 → 3.8.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 (86) hide show
  1. package/README.md +64 -131
  2. package/dist/browser/entities/index.js +470 -470
  3. package/dist/browser/index.js +1257 -1019
  4. package/dist/browser/marketplace.feature.js +175 -0
  5. package/dist/browser/order/index.js +155 -155
  6. package/dist/browser/order/order.event.js +1 -1
  7. package/dist/browser/payout/index.js +71 -71
  8. package/dist/browser/payout/payout.event.js +1 -1
  9. package/dist/browser/product/index.js +104 -104
  10. package/dist/browser/product/product.event.js +1 -1
  11. package/dist/browser/review/index.js +75 -75
  12. package/dist/browser/review/review.event.js +1 -1
  13. package/dist/browser/store/index.js +68 -68
  14. package/dist/browser/store/store.event.js +1 -1
  15. package/dist/browser/ui/MarketplaceDashboard.js +328 -110
  16. package/dist/browser/ui/MarketplaceDashboard.visualizations.js +216 -0
  17. package/dist/browser/ui/hooks/index.js +1 -1
  18. package/dist/browser/ui/hooks/useMarketplaceData.js +1 -1
  19. package/dist/browser/ui/index.js +590 -359
  20. package/dist/browser/ui/renderers/index.js +190 -4
  21. package/dist/browser/ui/renderers/marketplace.markdown.js +190 -4
  22. package/dist/browser/visualizations/catalog.js +126 -0
  23. package/dist/browser/visualizations/index.js +183 -0
  24. package/dist/browser/visualizations/selectors.js +177 -0
  25. package/dist/entities/index.d.ts +110 -110
  26. package/dist/entities/index.js +470 -470
  27. package/dist/index.d.ts +4 -3
  28. package/dist/index.js +1257 -1019
  29. package/dist/marketplace.feature.js +175 -0
  30. package/dist/node/entities/index.js +470 -470
  31. package/dist/node/index.js +1257 -1019
  32. package/dist/node/marketplace.feature.js +175 -0
  33. package/dist/node/order/index.js +155 -155
  34. package/dist/node/order/order.event.js +1 -1
  35. package/dist/node/payout/index.js +71 -71
  36. package/dist/node/payout/payout.event.js +1 -1
  37. package/dist/node/product/index.js +104 -104
  38. package/dist/node/product/product.event.js +1 -1
  39. package/dist/node/review/index.js +75 -75
  40. package/dist/node/review/review.event.js +1 -1
  41. package/dist/node/store/index.js +68 -68
  42. package/dist/node/store/store.event.js +1 -1
  43. package/dist/node/ui/MarketplaceDashboard.js +328 -110
  44. package/dist/node/ui/MarketplaceDashboard.visualizations.js +216 -0
  45. package/dist/node/ui/hooks/index.js +1 -1
  46. package/dist/node/ui/hooks/useMarketplaceData.js +1 -1
  47. package/dist/node/ui/index.js +590 -359
  48. package/dist/node/ui/renderers/index.js +190 -4
  49. package/dist/node/ui/renderers/marketplace.markdown.js +190 -4
  50. package/dist/node/visualizations/catalog.js +126 -0
  51. package/dist/node/visualizations/index.js +183 -0
  52. package/dist/node/visualizations/selectors.js +177 -0
  53. package/dist/order/index.d.ts +2 -2
  54. package/dist/order/index.js +155 -155
  55. package/dist/order/order.event.js +1 -1
  56. package/dist/payout/index.d.ts +2 -2
  57. package/dist/payout/index.js +71 -71
  58. package/dist/payout/payout.event.js +1 -1
  59. package/dist/product/index.d.ts +2 -2
  60. package/dist/product/index.js +104 -104
  61. package/dist/product/product.event.js +1 -1
  62. package/dist/review/index.d.ts +2 -2
  63. package/dist/review/index.js +75 -75
  64. package/dist/review/review.event.js +1 -1
  65. package/dist/store/index.d.ts +2 -2
  66. package/dist/store/index.js +68 -68
  67. package/dist/store/store.event.js +1 -1
  68. package/dist/ui/MarketplaceDashboard.js +328 -110
  69. package/dist/ui/MarketplaceDashboard.visualizations.d.ts +5 -0
  70. package/dist/ui/MarketplaceDashboard.visualizations.js +217 -0
  71. package/dist/ui/hooks/index.d.ts +1 -1
  72. package/dist/ui/hooks/index.js +1 -1
  73. package/dist/ui/hooks/useMarketplaceData.js +1 -1
  74. package/dist/ui/index.d.ts +2 -2
  75. package/dist/ui/index.js +590 -359
  76. package/dist/ui/renderers/index.d.ts +1 -1
  77. package/dist/ui/renderers/index.js +190 -4
  78. package/dist/ui/renderers/marketplace.markdown.js +190 -4
  79. package/dist/visualizations/catalog.d.ts +10 -0
  80. package/dist/visualizations/catalog.js +127 -0
  81. package/dist/visualizations/index.d.ts +2 -0
  82. package/dist/visualizations/index.js +184 -0
  83. package/dist/visualizations/selectors.d.ts +11 -0
  84. package/dist/visualizations/selectors.js +178 -0
  85. package/dist/visualizations/selectors.test.d.ts +1 -0
  86. package/package.json +66 -10
@@ -1,250 +1,12 @@
1
1
  // @bun
2
- // src/entities/store.ts
2
+ // src/entities/order.ts
3
3
  import {
4
4
  defineEntity,
5
5
  defineEntityEnum,
6
6
  field,
7
7
  index
8
8
  } from "@contractspec/lib.schema";
9
- var StoreStatusEnum = defineEntityEnum({
10
- name: "StoreStatus",
11
- values: ["PENDING", "ACTIVE", "SUSPENDED", "CLOSED"],
12
- schema: "marketplace",
13
- description: "Status of a store."
14
- });
15
- var StoreTypeEnum = defineEntityEnum({
16
- name: "StoreType",
17
- values: ["INDIVIDUAL", "BUSINESS", "ENTERPRISE"],
18
- schema: "marketplace",
19
- description: "Type of store account."
20
- });
21
- var StoreEntity = defineEntity({
22
- name: "Store",
23
- description: "A seller storefront on the marketplace.",
24
- schema: "marketplace",
25
- map: "store",
26
- fields: {
27
- id: field.id({ description: "Unique store ID" }),
28
- name: field.string({ description: "Store display name" }),
29
- slug: field.string({ description: "URL-friendly identifier" }),
30
- description: field.string({ isOptional: true }),
31
- status: field.enum("StoreStatus", { default: "PENDING" }),
32
- type: field.enum("StoreType", { default: "INDIVIDUAL" }),
33
- ownerId: field.foreignKey({ description: "Store owner user ID" }),
34
- organizationId: field.foreignKey({ isOptional: true }),
35
- logoFileId: field.string({
36
- isOptional: true,
37
- description: "Logo file reference"
38
- }),
39
- bannerFileId: field.string({
40
- isOptional: true,
41
- description: "Banner file reference"
42
- }),
43
- email: field.string({ isOptional: true }),
44
- phone: field.string({ isOptional: true }),
45
- website: field.string({ isOptional: true }),
46
- country: field.string({ isOptional: true }),
47
- currency: field.string({ default: '"USD"' }),
48
- timezone: field.string({ isOptional: true }),
49
- commissionRate: field.decimal({
50
- default: 0.1,
51
- description: "Platform commission rate (e.g., 0.1 = 10%)"
52
- }),
53
- isVerified: field.boolean({ default: false }),
54
- verifiedAt: field.dateTime({ isOptional: true }),
55
- settings: field.json({ isOptional: true }),
56
- metadata: field.json({ isOptional: true }),
57
- totalProducts: field.int({ default: 0 }),
58
- totalOrders: field.int({ default: 0 }),
59
- totalRevenue: field.decimal({ default: 0 }),
60
- averageRating: field.decimal({ default: 0 }),
61
- createdAt: field.createdAt(),
62
- updatedAt: field.updatedAt(),
63
- products: field.hasMany("Product"),
64
- orders: field.hasMany("Order"),
65
- payouts: field.hasMany("Payout")
66
- },
67
- indexes: [
68
- index.unique(["slug"]),
69
- index.on(["ownerId"]),
70
- index.on(["status"]),
71
- index.on(["country", "status"]),
72
- index.on(["averageRating"])
73
- ],
74
- enums: [StoreStatusEnum, StoreTypeEnum]
75
- });
76
- var StoreCategoryEntity = defineEntity({
77
- name: "StoreCategory",
78
- description: "Category assignment for stores.",
79
- schema: "marketplace",
80
- map: "store_category",
81
- fields: {
82
- id: field.id(),
83
- storeId: field.foreignKey(),
84
- categoryId: field.foreignKey(),
85
- isPrimary: field.boolean({ default: false }),
86
- createdAt: field.createdAt(),
87
- store: field.belongsTo("Store", ["storeId"], ["id"], {
88
- onDelete: "Cascade"
89
- })
90
- },
91
- indexes: [index.unique(["storeId", "categoryId"]), index.on(["categoryId"])]
92
- });
93
-
94
- // src/entities/product.ts
95
- import {
96
- defineEntity as defineEntity2,
97
- defineEntityEnum as defineEntityEnum2,
98
- field as field2,
99
- index as index2
100
- } from "@contractspec/lib.schema";
101
- var ProductStatusEnum = defineEntityEnum2({
102
- name: "ProductStatus",
103
- values: [
104
- "DRAFT",
105
- "PENDING_REVIEW",
106
- "ACTIVE",
107
- "OUT_OF_STOCK",
108
- "DISCONTINUED",
109
- "REJECTED"
110
- ],
111
- schema: "marketplace",
112
- description: "Status of a product listing."
113
- });
114
- var ProductTypeEnum = defineEntityEnum2({
115
- name: "ProductType",
116
- values: ["PHYSICAL", "DIGITAL", "SERVICE", "SUBSCRIPTION"],
117
- schema: "marketplace",
118
- description: "Type of product."
119
- });
120
- var ProductEntity = defineEntity2({
121
- name: "Product",
122
- description: "A product listing on the marketplace.",
123
- schema: "marketplace",
124
- map: "product",
125
- fields: {
126
- id: field2.id({ description: "Unique product ID" }),
127
- storeId: field2.foreignKey(),
128
- name: field2.string({ description: "Product name" }),
129
- slug: field2.string({ description: "URL-friendly identifier" }),
130
- description: field2.string({ isOptional: true }),
131
- shortDescription: field2.string({ isOptional: true }),
132
- status: field2.enum("ProductStatus", { default: "DRAFT" }),
133
- type: field2.enum("ProductType", { default: "PHYSICAL" }),
134
- price: field2.decimal({ description: "Base price" }),
135
- compareAtPrice: field2.decimal({
136
- isOptional: true,
137
- description: "Original price for showing discounts"
138
- }),
139
- currency: field2.string({ default: '"USD"' }),
140
- sku: field2.string({ isOptional: true }),
141
- barcode: field2.string({ isOptional: true }),
142
- quantity: field2.int({ default: 0 }),
143
- trackInventory: field2.boolean({ default: true }),
144
- allowBackorder: field2.boolean({ default: false }),
145
- lowStockThreshold: field2.int({ default: 5 }),
146
- weight: field2.decimal({ isOptional: true }),
147
- weightUnit: field2.string({ default: '"kg"' }),
148
- categoryId: field2.string({ isOptional: true }),
149
- tags: field2.string({ isArray: true }),
150
- primaryImageId: field2.string({ isOptional: true }),
151
- seoTitle: field2.string({ isOptional: true }),
152
- seoDescription: field2.string({ isOptional: true }),
153
- attributes: field2.json({
154
- isOptional: true,
155
- description: "Custom product attributes"
156
- }),
157
- reviewCount: field2.int({ default: 0 }),
158
- averageRating: field2.decimal({ default: 0 }),
159
- totalSold: field2.int({ default: 0 }),
160
- createdAt: field2.createdAt(),
161
- updatedAt: field2.updatedAt(),
162
- publishedAt: field2.dateTime({ isOptional: true }),
163
- store: field2.belongsTo("Store", ["storeId"], ["id"]),
164
- variants: field2.hasMany("ProductVariant"),
165
- orderItems: field2.hasMany("OrderItem"),
166
- reviews: field2.hasMany("Review")
167
- },
168
- indexes: [
169
- index2.unique(["storeId", "slug"]),
170
- index2.on(["storeId", "status"]),
171
- index2.on(["status", "publishedAt"]),
172
- index2.on(["categoryId", "status"]),
173
- index2.on(["averageRating"]),
174
- index2.on(["totalSold"]),
175
- index2.on(["price"])
176
- ],
177
- enums: [ProductStatusEnum, ProductTypeEnum]
178
- });
179
- var ProductVariantEntity = defineEntity2({
180
- name: "ProductVariant",
181
- description: "A variant of a product with specific options.",
182
- schema: "marketplace",
183
- map: "product_variant",
184
- fields: {
185
- id: field2.id(),
186
- productId: field2.foreignKey(),
187
- name: field2.string({ description: 'Variant name (e.g., "Large / Blue")' }),
188
- options: field2.json({
189
- description: 'Variant options (e.g., {size: "L", color: "Blue"})'
190
- }),
191
- price: field2.decimal({ description: "Variant-specific price" }),
192
- compareAtPrice: field2.decimal({ isOptional: true }),
193
- sku: field2.string({ isOptional: true }),
194
- barcode: field2.string({ isOptional: true }),
195
- quantity: field2.int({ default: 0 }),
196
- imageId: field2.string({ isOptional: true }),
197
- isActive: field2.boolean({ default: true }),
198
- position: field2.int({ default: 0 }),
199
- createdAt: field2.createdAt(),
200
- updatedAt: field2.updatedAt(),
201
- product: field2.belongsTo("Product", ["productId"], ["id"], {
202
- onDelete: "Cascade"
203
- })
204
- },
205
- indexes: [
206
- index2.on(["productId", "sku"]),
207
- index2.on(["productId", "position"]),
208
- index2.on(["barcode"])
209
- ]
210
- });
211
- var CategoryEntity = defineEntity2({
212
- name: "Category",
213
- description: "Product category for organization.",
214
- schema: "marketplace",
215
- map: "category",
216
- fields: {
217
- id: field2.id(),
218
- name: field2.string(),
219
- slug: field2.string(),
220
- description: field2.string({ isOptional: true }),
221
- parentId: field2.string({ isOptional: true }),
222
- path: field2.string({ description: "Full path for hierarchical queries" }),
223
- level: field2.int({ default: 0 }),
224
- position: field2.int({ default: 0 }),
225
- imageId: field2.string({ isOptional: true }),
226
- isActive: field2.boolean({ default: true }),
227
- createdAt: field2.createdAt(),
228
- updatedAt: field2.updatedAt(),
229
- parent: field2.belongsTo("Category", ["parentId"], ["id"]),
230
- children: field2.hasMany("Category")
231
- },
232
- indexes: [
233
- index2.unique(["slug"]),
234
- index2.on(["parentId", "position"]),
235
- index2.on(["path"]),
236
- index2.on(["isActive"])
237
- ]
238
- });
239
-
240
- // src/entities/order.ts
241
- import {
242
- defineEntity as defineEntity3,
243
- defineEntityEnum as defineEntityEnum3,
244
- field as field3,
245
- index as index3
246
- } from "@contractspec/lib.schema";
247
- var OrderStatusEnum = defineEntityEnum3({
9
+ var OrderStatusEnum = defineEntityEnum({
248
10
  name: "OrderStatus",
249
11
  values: [
250
12
  "PENDING",
@@ -261,7 +23,7 @@ var OrderStatusEnum = defineEntityEnum3({
261
23
  schema: "marketplace",
262
24
  description: "Status of an order."
263
25
  });
264
- var PaymentStatusEnum = defineEntityEnum3({
26
+ var PaymentStatusEnum = defineEntityEnum({
265
27
  name: "PaymentStatus",
266
28
  values: [
267
29
  "PENDING",
@@ -274,384 +36,622 @@ var PaymentStatusEnum = defineEntityEnum3({
274
36
  schema: "marketplace",
275
37
  description: "Status of payment."
276
38
  });
277
- var OrderEntity = defineEntity3({
39
+ var OrderEntity = defineEntity({
278
40
  name: "Order",
279
41
  description: "A purchase order on the marketplace.",
280
42
  schema: "marketplace",
281
43
  map: "order",
282
44
  fields: {
283
- id: field3.id({ description: "Unique order ID" }),
284
- orderNumber: field3.string({ description: "Human-readable order number" }),
285
- buyerId: field3.foreignKey({ description: "Buyer user ID" }),
286
- storeId: field3.foreignKey({ description: "Seller store ID" }),
287
- status: field3.enum("OrderStatus", { default: "PENDING" }),
288
- paymentStatus: field3.enum("PaymentStatus", { default: "PENDING" }),
289
- subtotal: field3.decimal({ description: "Sum of item prices" }),
290
- shippingTotal: field3.decimal({ default: 0 }),
291
- taxTotal: field3.decimal({ default: 0 }),
292
- discountTotal: field3.decimal({ default: 0 }),
293
- total: field3.decimal({ description: "Final total" }),
294
- currency: field3.string({ default: '"USD"' }),
295
- platformFee: field3.decimal({ description: "Platform commission amount" }),
296
- sellerPayout: field3.decimal({ description: "Amount due to seller" }),
297
- shippingAddress: field3.json({ isOptional: true }),
298
- billingAddress: field3.json({ isOptional: true }),
299
- shippingMethod: field3.string({ isOptional: true }),
300
- trackingNumber: field3.string({ isOptional: true }),
301
- trackingUrl: field3.string({ isOptional: true }),
302
- paymentMethod: field3.string({ isOptional: true }),
303
- paymentIntentId: field3.string({ isOptional: true }),
304
- buyerNote: field3.string({ isOptional: true }),
305
- sellerNote: field3.string({ isOptional: true }),
306
- internalNote: field3.string({ isOptional: true }),
307
- createdAt: field3.createdAt(),
308
- updatedAt: field3.updatedAt(),
309
- paidAt: field3.dateTime({ isOptional: true }),
310
- shippedAt: field3.dateTime({ isOptional: true }),
311
- deliveredAt: field3.dateTime({ isOptional: true }),
312
- completedAt: field3.dateTime({ isOptional: true }),
313
- cancelledAt: field3.dateTime({ isOptional: true }),
314
- store: field3.belongsTo("Store", ["storeId"], ["id"]),
315
- items: field3.hasMany("OrderItem"),
316
- refunds: field3.hasMany("Refund")
45
+ id: field.id({ description: "Unique order ID" }),
46
+ orderNumber: field.string({ description: "Human-readable order number" }),
47
+ buyerId: field.foreignKey({ description: "Buyer user ID" }),
48
+ storeId: field.foreignKey({ description: "Seller store ID" }),
49
+ status: field.enum("OrderStatus", { default: "PENDING" }),
50
+ paymentStatus: field.enum("PaymentStatus", { default: "PENDING" }),
51
+ subtotal: field.decimal({ description: "Sum of item prices" }),
52
+ shippingTotal: field.decimal({ default: 0 }),
53
+ taxTotal: field.decimal({ default: 0 }),
54
+ discountTotal: field.decimal({ default: 0 }),
55
+ total: field.decimal({ description: "Final total" }),
56
+ currency: field.string({ default: '"USD"' }),
57
+ platformFee: field.decimal({ description: "Platform commission amount" }),
58
+ sellerPayout: field.decimal({ description: "Amount due to seller" }),
59
+ shippingAddress: field.json({ isOptional: true }),
60
+ billingAddress: field.json({ isOptional: true }),
61
+ shippingMethod: field.string({ isOptional: true }),
62
+ trackingNumber: field.string({ isOptional: true }),
63
+ trackingUrl: field.string({ isOptional: true }),
64
+ paymentMethod: field.string({ isOptional: true }),
65
+ paymentIntentId: field.string({ isOptional: true }),
66
+ buyerNote: field.string({ isOptional: true }),
67
+ sellerNote: field.string({ isOptional: true }),
68
+ internalNote: field.string({ isOptional: true }),
69
+ createdAt: field.createdAt(),
70
+ updatedAt: field.updatedAt(),
71
+ paidAt: field.dateTime({ isOptional: true }),
72
+ shippedAt: field.dateTime({ isOptional: true }),
73
+ deliveredAt: field.dateTime({ isOptional: true }),
74
+ completedAt: field.dateTime({ isOptional: true }),
75
+ cancelledAt: field.dateTime({ isOptional: true }),
76
+ store: field.belongsTo("Store", ["storeId"], ["id"]),
77
+ items: field.hasMany("OrderItem"),
78
+ refunds: field.hasMany("Refund")
317
79
  },
318
80
  indexes: [
319
- index3.unique(["orderNumber"]),
320
- index3.on(["buyerId", "status"]),
321
- index3.on(["storeId", "status"]),
322
- index3.on(["status", "createdAt"]),
323
- index3.on(["paymentStatus"]),
324
- index3.on(["createdAt"])
81
+ index.unique(["orderNumber"]),
82
+ index.on(["buyerId", "status"]),
83
+ index.on(["storeId", "status"]),
84
+ index.on(["status", "createdAt"]),
85
+ index.on(["paymentStatus"]),
86
+ index.on(["createdAt"])
325
87
  ],
326
88
  enums: [OrderStatusEnum, PaymentStatusEnum]
327
89
  });
328
- var OrderItemEntity = defineEntity3({
90
+ var OrderItemEntity = defineEntity({
329
91
  name: "OrderItem",
330
92
  description: "An item within an order.",
331
93
  schema: "marketplace",
332
94
  map: "order_item",
333
95
  fields: {
334
- id: field3.id(),
335
- orderId: field3.foreignKey(),
336
- productId: field3.foreignKey(),
337
- variantId: field3.string({ isOptional: true }),
338
- productName: field3.string(),
339
- variantName: field3.string({ isOptional: true }),
340
- sku: field3.string({ isOptional: true }),
341
- unitPrice: field3.decimal(),
342
- quantity: field3.int(),
343
- subtotal: field3.decimal(),
344
- quantityFulfilled: field3.int({ default: 0 }),
345
- quantityRefunded: field3.int({ default: 0 }),
346
- createdAt: field3.createdAt(),
347
- updatedAt: field3.updatedAt(),
348
- order: field3.belongsTo("Order", ["orderId"], ["id"], {
96
+ id: field.id(),
97
+ orderId: field.foreignKey(),
98
+ productId: field.foreignKey(),
99
+ variantId: field.string({ isOptional: true }),
100
+ productName: field.string(),
101
+ variantName: field.string({ isOptional: true }),
102
+ sku: field.string({ isOptional: true }),
103
+ unitPrice: field.decimal(),
104
+ quantity: field.int(),
105
+ subtotal: field.decimal(),
106
+ quantityFulfilled: field.int({ default: 0 }),
107
+ quantityRefunded: field.int({ default: 0 }),
108
+ createdAt: field.createdAt(),
109
+ updatedAt: field.updatedAt(),
110
+ order: field.belongsTo("Order", ["orderId"], ["id"], {
349
111
  onDelete: "Cascade"
350
112
  }),
351
- product: field3.belongsTo("Product", ["productId"], ["id"])
113
+ product: field.belongsTo("Product", ["productId"], ["id"])
352
114
  },
353
- indexes: [index3.on(["orderId"]), index3.on(["productId"])]
115
+ indexes: [index.on(["orderId"]), index.on(["productId"])]
354
116
  });
355
- var RefundEntity = defineEntity3({
117
+ var RefundEntity = defineEntity({
356
118
  name: "Refund",
357
119
  description: "A refund for an order.",
358
120
  schema: "marketplace",
359
121
  map: "refund",
360
122
  fields: {
361
- id: field3.id(),
362
- orderId: field3.foreignKey(),
363
- amount: field3.decimal(),
364
- currency: field3.string(),
365
- reason: field3.string(),
366
- notes: field3.string({ isOptional: true }),
367
- status: field3.string({ default: '"PENDING"' }),
368
- refundId: field3.string({
123
+ id: field.id(),
124
+ orderId: field.foreignKey(),
125
+ amount: field.decimal(),
126
+ currency: field.string(),
127
+ reason: field.string(),
128
+ notes: field.string({ isOptional: true }),
129
+ status: field.string({ default: '"PENDING"' }),
130
+ refundId: field.string({
369
131
  isOptional: true,
370
132
  description: "Payment provider refund ID"
371
133
  }),
372
- issuedBy: field3.foreignKey({ description: "User who issued the refund" }),
373
- createdAt: field3.createdAt(),
374
- processedAt: field3.dateTime({ isOptional: true }),
375
- order: field3.belongsTo("Order", ["orderId"], ["id"]),
376
- items: field3.hasMany("RefundItem")
134
+ issuedBy: field.foreignKey({ description: "User who issued the refund" }),
135
+ createdAt: field.createdAt(),
136
+ processedAt: field.dateTime({ isOptional: true }),
137
+ order: field.belongsTo("Order", ["orderId"], ["id"]),
138
+ items: field.hasMany("RefundItem")
377
139
  },
378
- indexes: [index3.on(["orderId"]), index3.on(["status"])]
140
+ indexes: [index.on(["orderId"]), index.on(["status"])]
379
141
  });
380
- var RefundItemEntity = defineEntity3({
142
+ var RefundItemEntity = defineEntity({
381
143
  name: "RefundItem",
382
144
  description: "An item within a refund.",
383
145
  schema: "marketplace",
384
146
  map: "refund_item",
385
147
  fields: {
386
- id: field3.id(),
387
- refundId: field3.foreignKey(),
388
- orderItemId: field3.foreignKey(),
389
- quantity: field3.int(),
390
- amount: field3.decimal(),
391
- createdAt: field3.createdAt(),
392
- refund: field3.belongsTo("Refund", ["refundId"], ["id"], {
148
+ id: field.id(),
149
+ refundId: field.foreignKey(),
150
+ orderItemId: field.foreignKey(),
151
+ quantity: field.int(),
152
+ amount: field.decimal(),
153
+ createdAt: field.createdAt(),
154
+ refund: field.belongsTo("Refund", ["refundId"], ["id"], {
393
155
  onDelete: "Cascade"
394
156
  }),
395
- orderItem: field3.belongsTo("OrderItem", ["orderItemId"], ["id"])
157
+ orderItem: field.belongsTo("OrderItem", ["orderItemId"], ["id"])
396
158
  },
397
- indexes: [index3.on(["refundId"]), index3.on(["orderItemId"])]
159
+ indexes: [index.on(["refundId"]), index.on(["orderItemId"])]
398
160
  });
399
161
 
400
162
  // src/entities/payout.ts
401
163
  import {
402
- defineEntity as defineEntity4,
403
- defineEntityEnum as defineEntityEnum4,
404
- field as field4,
405
- index as index4
164
+ defineEntity as defineEntity2,
165
+ defineEntityEnum as defineEntityEnum2,
166
+ field as field2,
167
+ index as index2
406
168
  } from "@contractspec/lib.schema";
407
- var PayoutStatusEnum = defineEntityEnum4({
169
+ var PayoutStatusEnum = defineEntityEnum2({
408
170
  name: "PayoutStatus",
409
171
  values: ["PENDING", "PROCESSING", "PAID", "FAILED", "CANCELLED"],
410
172
  schema: "marketplace",
411
173
  description: "Status of a payout."
412
174
  });
413
- var PayoutScheduleEnum = defineEntityEnum4({
175
+ var PayoutScheduleEnum = defineEntityEnum2({
414
176
  name: "PayoutSchedule",
415
177
  values: ["DAILY", "WEEKLY", "BIWEEKLY", "MONTHLY", "MANUAL"],
416
178
  schema: "marketplace",
417
179
  description: "Payout schedule frequency."
418
180
  });
419
- var PayoutEntity = defineEntity4({
181
+ var PayoutEntity = defineEntity2({
420
182
  name: "Payout",
421
183
  description: "A payout to a seller.",
422
184
  schema: "marketplace",
423
185
  map: "payout",
424
186
  fields: {
425
- id: field4.id({ description: "Unique payout ID" }),
426
- storeId: field4.foreignKey(),
427
- payoutNumber: field4.string({ description: "Human-readable payout number" }),
428
- status: field4.enum("PayoutStatus", { default: "PENDING" }),
429
- grossAmount: field4.decimal({ description: "Total before fees" }),
430
- platformFees: field4.decimal({ description: "Platform fees deducted" }),
431
- otherDeductions: field4.decimal({ default: 0 }),
432
- netAmount: field4.decimal({ description: "Final payout amount" }),
433
- currency: field4.string({ default: '"USD"' }),
434
- periodStart: field4.dateTime({ description: "Start of payout period" }),
435
- periodEnd: field4.dateTime({ description: "End of payout period" }),
436
- paymentMethod: field4.string({ isOptional: true }),
437
- paymentReference: field4.string({ isOptional: true }),
438
- bankAccountId: field4.string({ isOptional: true }),
439
- bankAccountLast4: field4.string({ isOptional: true }),
440
- notes: field4.string({ isOptional: true }),
441
- failureReason: field4.string({ isOptional: true }),
442
- orderCount: field4.int({ default: 0 }),
443
- createdAt: field4.createdAt(),
444
- updatedAt: field4.updatedAt(),
445
- scheduledAt: field4.dateTime({ isOptional: true }),
446
- processedAt: field4.dateTime({ isOptional: true }),
447
- paidAt: field4.dateTime({ isOptional: true }),
448
- store: field4.belongsTo("Store", ["storeId"], ["id"]),
449
- items: field4.hasMany("PayoutItem")
187
+ id: field2.id({ description: "Unique payout ID" }),
188
+ storeId: field2.foreignKey(),
189
+ payoutNumber: field2.string({ description: "Human-readable payout number" }),
190
+ status: field2.enum("PayoutStatus", { default: "PENDING" }),
191
+ grossAmount: field2.decimal({ description: "Total before fees" }),
192
+ platformFees: field2.decimal({ description: "Platform fees deducted" }),
193
+ otherDeductions: field2.decimal({ default: 0 }),
194
+ netAmount: field2.decimal({ description: "Final payout amount" }),
195
+ currency: field2.string({ default: '"USD"' }),
196
+ periodStart: field2.dateTime({ description: "Start of payout period" }),
197
+ periodEnd: field2.dateTime({ description: "End of payout period" }),
198
+ paymentMethod: field2.string({ isOptional: true }),
199
+ paymentReference: field2.string({ isOptional: true }),
200
+ bankAccountId: field2.string({ isOptional: true }),
201
+ bankAccountLast4: field2.string({ isOptional: true }),
202
+ notes: field2.string({ isOptional: true }),
203
+ failureReason: field2.string({ isOptional: true }),
204
+ orderCount: field2.int({ default: 0 }),
205
+ createdAt: field2.createdAt(),
206
+ updatedAt: field2.updatedAt(),
207
+ scheduledAt: field2.dateTime({ isOptional: true }),
208
+ processedAt: field2.dateTime({ isOptional: true }),
209
+ paidAt: field2.dateTime({ isOptional: true }),
210
+ store: field2.belongsTo("Store", ["storeId"], ["id"]),
211
+ items: field2.hasMany("PayoutItem")
450
212
  },
451
213
  indexes: [
452
- index4.unique(["payoutNumber"]),
453
- index4.on(["storeId", "status"]),
454
- index4.on(["status", "scheduledAt"]),
455
- index4.on(["periodStart", "periodEnd"])
214
+ index2.unique(["payoutNumber"]),
215
+ index2.on(["storeId", "status"]),
216
+ index2.on(["status", "scheduledAt"]),
217
+ index2.on(["periodStart", "periodEnd"])
456
218
  ],
457
219
  enums: [PayoutStatusEnum]
458
220
  });
459
- var PayoutItemEntity = defineEntity4({
221
+ var PayoutItemEntity = defineEntity2({
460
222
  name: "PayoutItem",
461
223
  description: "An order included in a payout.",
462
224
  schema: "marketplace",
463
225
  map: "payout_item",
464
226
  fields: {
465
- id: field4.id(),
466
- payoutId: field4.foreignKey(),
467
- orderId: field4.foreignKey(),
468
- orderTotal: field4.decimal(),
469
- platformFee: field4.decimal(),
470
- netAmount: field4.decimal(),
471
- createdAt: field4.createdAt(),
472
- payout: field4.belongsTo("Payout", ["payoutId"], ["id"], {
227
+ id: field2.id(),
228
+ payoutId: field2.foreignKey(),
229
+ orderId: field2.foreignKey(),
230
+ orderTotal: field2.decimal(),
231
+ platformFee: field2.decimal(),
232
+ netAmount: field2.decimal(),
233
+ createdAt: field2.createdAt(),
234
+ payout: field2.belongsTo("Payout", ["payoutId"], ["id"], {
473
235
  onDelete: "Cascade"
474
236
  }),
475
- order: field4.belongsTo("Order", ["orderId"], ["id"])
237
+ order: field2.belongsTo("Order", ["orderId"], ["id"])
476
238
  },
477
- indexes: [index4.on(["payoutId"]), index4.on(["orderId"])]
239
+ indexes: [index2.on(["payoutId"]), index2.on(["orderId"])]
478
240
  });
479
- var BankAccountEntity = defineEntity4({
241
+ var BankAccountEntity = defineEntity2({
480
242
  name: "BankAccount",
481
243
  description: "A bank account for receiving payouts.",
482
244
  schema: "marketplace",
483
245
  map: "bank_account",
484
246
  fields: {
485
- id: field4.id(),
486
- storeId: field4.foreignKey(),
487
- accountHolderName: field4.string(),
488
- accountType: field4.string({ default: '"CHECKING"' }),
489
- bankName: field4.string({ isOptional: true }),
490
- last4: field4.string({ description: "Last 4 digits of account" }),
491
- routingLast4: field4.string({ isOptional: true }),
492
- externalId: field4.string({
247
+ id: field2.id(),
248
+ storeId: field2.foreignKey(),
249
+ accountHolderName: field2.string(),
250
+ accountType: field2.string({ default: '"CHECKING"' }),
251
+ bankName: field2.string({ isOptional: true }),
252
+ last4: field2.string({ description: "Last 4 digits of account" }),
253
+ routingLast4: field2.string({ isOptional: true }),
254
+ externalId: field2.string({
493
255
  isOptional: true,
494
256
  description: "External provider account ID"
495
257
  }),
496
- isDefault: field4.boolean({ default: false }),
497
- isVerified: field4.boolean({ default: false }),
498
- createdAt: field4.createdAt(),
499
- updatedAt: field4.updatedAt(),
500
- verifiedAt: field4.dateTime({ isOptional: true }),
501
- store: field4.belongsTo("Store", ["storeId"], ["id"])
258
+ isDefault: field2.boolean({ default: false }),
259
+ isVerified: field2.boolean({ default: false }),
260
+ createdAt: field2.createdAt(),
261
+ updatedAt: field2.updatedAt(),
262
+ verifiedAt: field2.dateTime({ isOptional: true }),
263
+ store: field2.belongsTo("Store", ["storeId"], ["id"])
502
264
  },
503
- indexes: [index4.on(["storeId", "isDefault"]), index4.on(["externalId"])]
265
+ indexes: [index2.on(["storeId", "isDefault"]), index2.on(["externalId"])]
504
266
  });
505
- var PayoutSettingsEntity = defineEntity4({
267
+ var PayoutSettingsEntity = defineEntity2({
506
268
  name: "PayoutSettings",
507
269
  description: "Payout configuration for a store.",
508
270
  schema: "marketplace",
509
271
  map: "payout_settings",
510
272
  fields: {
511
- id: field4.id(),
512
- storeId: field4.foreignKey(),
513
- schedule: field4.enum("PayoutSchedule", { default: "WEEKLY" }),
514
- dayOfWeek: field4.int({
273
+ id: field2.id(),
274
+ storeId: field2.foreignKey(),
275
+ schedule: field2.enum("PayoutSchedule", { default: "WEEKLY" }),
276
+ dayOfWeek: field2.int({
515
277
  isOptional: true,
516
278
  description: "Day for weekly/biweekly (0=Sunday)"
517
279
  }),
518
- dayOfMonth: field4.int({
280
+ dayOfMonth: field2.int({
519
281
  isOptional: true,
520
282
  description: "Day for monthly (1-28)"
521
283
  }),
522
- minimumPayout: field4.decimal({
284
+ minimumPayout: field2.decimal({
523
285
  default: 50,
524
286
  description: "Minimum amount for payout"
525
287
  }),
526
- defaultBankAccountId: field4.string({ isOptional: true }),
527
- createdAt: field4.createdAt(),
528
- updatedAt: field4.updatedAt(),
529
- store: field4.belongsTo("Store", ["storeId"], ["id"])
288
+ defaultBankAccountId: field2.string({ isOptional: true }),
289
+ createdAt: field2.createdAt(),
290
+ updatedAt: field2.updatedAt(),
291
+ store: field2.belongsTo("Store", ["storeId"], ["id"])
530
292
  },
531
- indexes: [index4.unique(["storeId"])],
293
+ indexes: [index2.unique(["storeId"])],
532
294
  enums: [PayoutScheduleEnum]
533
295
  });
534
296
 
297
+ // src/entities/product.ts
298
+ import {
299
+ defineEntity as defineEntity3,
300
+ defineEntityEnum as defineEntityEnum3,
301
+ field as field3,
302
+ index as index3
303
+ } from "@contractspec/lib.schema";
304
+ var ProductStatusEnum = defineEntityEnum3({
305
+ name: "ProductStatus",
306
+ values: [
307
+ "DRAFT",
308
+ "PENDING_REVIEW",
309
+ "ACTIVE",
310
+ "OUT_OF_STOCK",
311
+ "DISCONTINUED",
312
+ "REJECTED"
313
+ ],
314
+ schema: "marketplace",
315
+ description: "Status of a product listing."
316
+ });
317
+ var ProductTypeEnum = defineEntityEnum3({
318
+ name: "ProductType",
319
+ values: ["PHYSICAL", "DIGITAL", "SERVICE", "SUBSCRIPTION"],
320
+ schema: "marketplace",
321
+ description: "Type of product."
322
+ });
323
+ var ProductEntity = defineEntity3({
324
+ name: "Product",
325
+ description: "A product listing on the marketplace.",
326
+ schema: "marketplace",
327
+ map: "product",
328
+ fields: {
329
+ id: field3.id({ description: "Unique product ID" }),
330
+ storeId: field3.foreignKey(),
331
+ name: field3.string({ description: "Product name" }),
332
+ slug: field3.string({ description: "URL-friendly identifier" }),
333
+ description: field3.string({ isOptional: true }),
334
+ shortDescription: field3.string({ isOptional: true }),
335
+ status: field3.enum("ProductStatus", { default: "DRAFT" }),
336
+ type: field3.enum("ProductType", { default: "PHYSICAL" }),
337
+ price: field3.decimal({ description: "Base price" }),
338
+ compareAtPrice: field3.decimal({
339
+ isOptional: true,
340
+ description: "Original price for showing discounts"
341
+ }),
342
+ currency: field3.string({ default: '"USD"' }),
343
+ sku: field3.string({ isOptional: true }),
344
+ barcode: field3.string({ isOptional: true }),
345
+ quantity: field3.int({ default: 0 }),
346
+ trackInventory: field3.boolean({ default: true }),
347
+ allowBackorder: field3.boolean({ default: false }),
348
+ lowStockThreshold: field3.int({ default: 5 }),
349
+ weight: field3.decimal({ isOptional: true }),
350
+ weightUnit: field3.string({ default: '"kg"' }),
351
+ categoryId: field3.string({ isOptional: true }),
352
+ tags: field3.string({ isArray: true }),
353
+ primaryImageId: field3.string({ isOptional: true }),
354
+ seoTitle: field3.string({ isOptional: true }),
355
+ seoDescription: field3.string({ isOptional: true }),
356
+ attributes: field3.json({
357
+ isOptional: true,
358
+ description: "Custom product attributes"
359
+ }),
360
+ reviewCount: field3.int({ default: 0 }),
361
+ averageRating: field3.decimal({ default: 0 }),
362
+ totalSold: field3.int({ default: 0 }),
363
+ createdAt: field3.createdAt(),
364
+ updatedAt: field3.updatedAt(),
365
+ publishedAt: field3.dateTime({ isOptional: true }),
366
+ store: field3.belongsTo("Store", ["storeId"], ["id"]),
367
+ variants: field3.hasMany("ProductVariant"),
368
+ orderItems: field3.hasMany("OrderItem"),
369
+ reviews: field3.hasMany("Review")
370
+ },
371
+ indexes: [
372
+ index3.unique(["storeId", "slug"]),
373
+ index3.on(["storeId", "status"]),
374
+ index3.on(["status", "publishedAt"]),
375
+ index3.on(["categoryId", "status"]),
376
+ index3.on(["averageRating"]),
377
+ index3.on(["totalSold"]),
378
+ index3.on(["price"])
379
+ ],
380
+ enums: [ProductStatusEnum, ProductTypeEnum]
381
+ });
382
+ var ProductVariantEntity = defineEntity3({
383
+ name: "ProductVariant",
384
+ description: "A variant of a product with specific options.",
385
+ schema: "marketplace",
386
+ map: "product_variant",
387
+ fields: {
388
+ id: field3.id(),
389
+ productId: field3.foreignKey(),
390
+ name: field3.string({ description: 'Variant name (e.g., "Large / Blue")' }),
391
+ options: field3.json({
392
+ description: 'Variant options (e.g., {size: "L", color: "Blue"})'
393
+ }),
394
+ price: field3.decimal({ description: "Variant-specific price" }),
395
+ compareAtPrice: field3.decimal({ isOptional: true }),
396
+ sku: field3.string({ isOptional: true }),
397
+ barcode: field3.string({ isOptional: true }),
398
+ quantity: field3.int({ default: 0 }),
399
+ imageId: field3.string({ isOptional: true }),
400
+ isActive: field3.boolean({ default: true }),
401
+ position: field3.int({ default: 0 }),
402
+ createdAt: field3.createdAt(),
403
+ updatedAt: field3.updatedAt(),
404
+ product: field3.belongsTo("Product", ["productId"], ["id"], {
405
+ onDelete: "Cascade"
406
+ })
407
+ },
408
+ indexes: [
409
+ index3.on(["productId", "sku"]),
410
+ index3.on(["productId", "position"]),
411
+ index3.on(["barcode"])
412
+ ]
413
+ });
414
+ var CategoryEntity = defineEntity3({
415
+ name: "Category",
416
+ description: "Product category for organization.",
417
+ schema: "marketplace",
418
+ map: "category",
419
+ fields: {
420
+ id: field3.id(),
421
+ name: field3.string(),
422
+ slug: field3.string(),
423
+ description: field3.string({ isOptional: true }),
424
+ parentId: field3.string({ isOptional: true }),
425
+ path: field3.string({ description: "Full path for hierarchical queries" }),
426
+ level: field3.int({ default: 0 }),
427
+ position: field3.int({ default: 0 }),
428
+ imageId: field3.string({ isOptional: true }),
429
+ isActive: field3.boolean({ default: true }),
430
+ createdAt: field3.createdAt(),
431
+ updatedAt: field3.updatedAt(),
432
+ parent: field3.belongsTo("Category", ["parentId"], ["id"]),
433
+ children: field3.hasMany("Category")
434
+ },
435
+ indexes: [
436
+ index3.unique(["slug"]),
437
+ index3.on(["parentId", "position"]),
438
+ index3.on(["path"]),
439
+ index3.on(["isActive"])
440
+ ]
441
+ });
442
+
535
443
  // src/entities/review.ts
536
444
  import {
537
- defineEntity as defineEntity5,
538
- defineEntityEnum as defineEntityEnum5,
539
- field as field5,
540
- index as index5
445
+ defineEntity as defineEntity4,
446
+ defineEntityEnum as defineEntityEnum4,
447
+ field as field4,
448
+ index as index4
541
449
  } from "@contractspec/lib.schema";
542
- var ReviewStatusEnum = defineEntityEnum5({
450
+ var ReviewStatusEnum = defineEntityEnum4({
543
451
  name: "ReviewStatus",
544
452
  values: ["PENDING", "APPROVED", "REJECTED", "FLAGGED"],
545
453
  schema: "marketplace",
546
454
  description: "Status of a review."
547
455
  });
548
- var ReviewTypeEnum = defineEntityEnum5({
456
+ var ReviewTypeEnum = defineEntityEnum4({
549
457
  name: "ReviewType",
550
458
  values: ["PRODUCT", "STORE", "ORDER"],
551
459
  schema: "marketplace",
552
460
  description: "Type of review."
553
461
  });
554
- var ReviewEntity = defineEntity5({
462
+ var ReviewEntity = defineEntity4({
555
463
  name: "Review",
556
464
  description: "A customer review on the marketplace.",
557
465
  schema: "marketplace",
558
466
  map: "review",
559
467
  fields: {
560
- id: field5.id({ description: "Unique review ID" }),
561
- type: field5.enum("ReviewType", { default: "PRODUCT" }),
562
- productId: field5.string({ isOptional: true }),
563
- storeId: field5.string({ isOptional: true }),
564
- orderId: field5.string({ isOptional: true }),
565
- orderItemId: field5.string({ isOptional: true }),
566
- authorId: field5.foreignKey({ description: "Reviewer user ID" }),
567
- rating: field5.int({ description: "Rating 1-5" }),
568
- title: field5.string({ isOptional: true }),
569
- content: field5.string({ isOptional: true }),
570
- isVerifiedPurchase: field5.boolean({ default: false }),
571
- status: field5.enum("ReviewStatus", { default: "PENDING" }),
572
- hasMedia: field5.boolean({ default: false }),
573
- helpfulCount: field5.int({ default: 0 }),
574
- notHelpfulCount: field5.int({ default: 0 }),
575
- moderatedBy: field5.string({ isOptional: true }),
576
- moderatedAt: field5.dateTime({ isOptional: true }),
577
- moderationNote: field5.string({ isOptional: true }),
578
- hasResponse: field5.boolean({ default: false }),
579
- createdAt: field5.createdAt(),
580
- updatedAt: field5.updatedAt(),
581
- product: field5.belongsTo("Product", ["productId"], ["id"]),
582
- store: field5.belongsTo("Store", ["storeId"], ["id"]),
583
- responses: field5.hasMany("ReviewResponse"),
584
- votes: field5.hasMany("ReviewVote")
468
+ id: field4.id({ description: "Unique review ID" }),
469
+ type: field4.enum("ReviewType", { default: "PRODUCT" }),
470
+ productId: field4.string({ isOptional: true }),
471
+ storeId: field4.string({ isOptional: true }),
472
+ orderId: field4.string({ isOptional: true }),
473
+ orderItemId: field4.string({ isOptional: true }),
474
+ authorId: field4.foreignKey({ description: "Reviewer user ID" }),
475
+ rating: field4.int({ description: "Rating 1-5" }),
476
+ title: field4.string({ isOptional: true }),
477
+ content: field4.string({ isOptional: true }),
478
+ isVerifiedPurchase: field4.boolean({ default: false }),
479
+ status: field4.enum("ReviewStatus", { default: "PENDING" }),
480
+ hasMedia: field4.boolean({ default: false }),
481
+ helpfulCount: field4.int({ default: 0 }),
482
+ notHelpfulCount: field4.int({ default: 0 }),
483
+ moderatedBy: field4.string({ isOptional: true }),
484
+ moderatedAt: field4.dateTime({ isOptional: true }),
485
+ moderationNote: field4.string({ isOptional: true }),
486
+ hasResponse: field4.boolean({ default: false }),
487
+ createdAt: field4.createdAt(),
488
+ updatedAt: field4.updatedAt(),
489
+ product: field4.belongsTo("Product", ["productId"], ["id"]),
490
+ store: field4.belongsTo("Store", ["storeId"], ["id"]),
491
+ responses: field4.hasMany("ReviewResponse"),
492
+ votes: field4.hasMany("ReviewVote")
585
493
  },
586
494
  indexes: [
587
- index5.on(["productId", "status", "createdAt"]),
588
- index5.on(["storeId", "status", "createdAt"]),
589
- index5.on(["authorId"]),
590
- index5.on(["orderId"]),
591
- index5.on(["status"]),
592
- index5.on(["rating"]),
593
- index5.on(["isVerifiedPurchase", "status"])
495
+ index4.on(["productId", "status", "createdAt"]),
496
+ index4.on(["storeId", "status", "createdAt"]),
497
+ index4.on(["authorId"]),
498
+ index4.on(["orderId"]),
499
+ index4.on(["status"]),
500
+ index4.on(["rating"]),
501
+ index4.on(["isVerifiedPurchase", "status"])
594
502
  ],
595
503
  enums: [ReviewStatusEnum, ReviewTypeEnum]
596
504
  });
597
- var ReviewResponseEntity = defineEntity5({
505
+ var ReviewResponseEntity = defineEntity4({
598
506
  name: "ReviewResponse",
599
507
  description: "A seller response to a review.",
600
508
  schema: "marketplace",
601
509
  map: "review_response",
602
510
  fields: {
603
- id: field5.id(),
604
- reviewId: field5.foreignKey(),
605
- authorId: field5.foreignKey(),
606
- content: field5.string(),
607
- createdAt: field5.createdAt(),
608
- updatedAt: field5.updatedAt(),
609
- review: field5.belongsTo("Review", ["reviewId"], ["id"], {
511
+ id: field4.id(),
512
+ reviewId: field4.foreignKey(),
513
+ authorId: field4.foreignKey(),
514
+ content: field4.string(),
515
+ createdAt: field4.createdAt(),
516
+ updatedAt: field4.updatedAt(),
517
+ review: field4.belongsTo("Review", ["reviewId"], ["id"], {
610
518
  onDelete: "Cascade"
611
519
  })
612
520
  },
613
- indexes: [index5.on(["reviewId"]), index5.on(["authorId"])]
521
+ indexes: [index4.on(["reviewId"]), index4.on(["authorId"])]
614
522
  });
615
- var ReviewVoteEntity = defineEntity5({
523
+ var ReviewVoteEntity = defineEntity4({
616
524
  name: "ReviewVote",
617
525
  description: "A helpfulness vote on a review.",
618
526
  schema: "marketplace",
619
527
  map: "review_vote",
620
528
  fields: {
621
- id: field5.id(),
622
- reviewId: field5.foreignKey(),
623
- userId: field5.foreignKey(),
624
- isHelpful: field5.boolean(),
625
- createdAt: field5.createdAt(),
626
- review: field5.belongsTo("Review", ["reviewId"], ["id"], {
529
+ id: field4.id(),
530
+ reviewId: field4.foreignKey(),
531
+ userId: field4.foreignKey(),
532
+ isHelpful: field4.boolean(),
533
+ createdAt: field4.createdAt(),
534
+ review: field4.belongsTo("Review", ["reviewId"], ["id"], {
627
535
  onDelete: "Cascade"
628
536
  })
629
537
  },
630
- indexes: [index5.unique(["reviewId", "userId"]), index5.on(["userId"])]
538
+ indexes: [index4.unique(["reviewId", "userId"]), index4.on(["userId"])]
631
539
  });
632
- var ReviewReportEntity = defineEntity5({
540
+ var ReviewReportEntity = defineEntity4({
633
541
  name: "ReviewReport",
634
542
  description: "A report/flag on a review.",
635
543
  schema: "marketplace",
636
544
  map: "review_report",
637
545
  fields: {
638
- id: field5.id(),
639
- reviewId: field5.foreignKey(),
640
- reporterId: field5.foreignKey(),
641
- reason: field5.string({ description: "Report reason category" }),
642
- details: field5.string({ isOptional: true }),
643
- status: field5.string({ default: '"PENDING"' }),
644
- resolvedBy: field5.string({ isOptional: true }),
645
- resolvedAt: field5.dateTime({ isOptional: true }),
646
- resolution: field5.string({ isOptional: true }),
546
+ id: field4.id(),
547
+ reviewId: field4.foreignKey(),
548
+ reporterId: field4.foreignKey(),
549
+ reason: field4.string({ description: "Report reason category" }),
550
+ details: field4.string({ isOptional: true }),
551
+ status: field4.string({ default: '"PENDING"' }),
552
+ resolvedBy: field4.string({ isOptional: true }),
553
+ resolvedAt: field4.dateTime({ isOptional: true }),
554
+ resolution: field4.string({ isOptional: true }),
555
+ createdAt: field4.createdAt(),
556
+ review: field4.belongsTo("Review", ["reviewId"], ["id"])
557
+ },
558
+ indexes: [
559
+ index4.on(["reviewId"]),
560
+ index4.on(["status"]),
561
+ index4.on(["reporterId"])
562
+ ]
563
+ });
564
+
565
+ // src/entities/store.ts
566
+ import {
567
+ defineEntity as defineEntity5,
568
+ defineEntityEnum as defineEntityEnum5,
569
+ field as field5,
570
+ index as index5
571
+ } from "@contractspec/lib.schema";
572
+ var StoreStatusEnum = defineEntityEnum5({
573
+ name: "StoreStatus",
574
+ values: ["PENDING", "ACTIVE", "SUSPENDED", "CLOSED"],
575
+ schema: "marketplace",
576
+ description: "Status of a store."
577
+ });
578
+ var StoreTypeEnum = defineEntityEnum5({
579
+ name: "StoreType",
580
+ values: ["INDIVIDUAL", "BUSINESS", "ENTERPRISE"],
581
+ schema: "marketplace",
582
+ description: "Type of store account."
583
+ });
584
+ var StoreEntity = defineEntity5({
585
+ name: "Store",
586
+ description: "A seller storefront on the marketplace.",
587
+ schema: "marketplace",
588
+ map: "store",
589
+ fields: {
590
+ id: field5.id({ description: "Unique store ID" }),
591
+ name: field5.string({ description: "Store display name" }),
592
+ slug: field5.string({ description: "URL-friendly identifier" }),
593
+ description: field5.string({ isOptional: true }),
594
+ status: field5.enum("StoreStatus", { default: "PENDING" }),
595
+ type: field5.enum("StoreType", { default: "INDIVIDUAL" }),
596
+ ownerId: field5.foreignKey({ description: "Store owner user ID" }),
597
+ organizationId: field5.foreignKey({ isOptional: true }),
598
+ logoFileId: field5.string({
599
+ isOptional: true,
600
+ description: "Logo file reference"
601
+ }),
602
+ bannerFileId: field5.string({
603
+ isOptional: true,
604
+ description: "Banner file reference"
605
+ }),
606
+ email: field5.string({ isOptional: true }),
607
+ phone: field5.string({ isOptional: true }),
608
+ website: field5.string({ isOptional: true }),
609
+ country: field5.string({ isOptional: true }),
610
+ currency: field5.string({ default: '"USD"' }),
611
+ timezone: field5.string({ isOptional: true }),
612
+ commissionRate: field5.decimal({
613
+ default: 0.1,
614
+ description: "Platform commission rate (e.g., 0.1 = 10%)"
615
+ }),
616
+ isVerified: field5.boolean({ default: false }),
617
+ verifiedAt: field5.dateTime({ isOptional: true }),
618
+ settings: field5.json({ isOptional: true }),
619
+ metadata: field5.json({ isOptional: true }),
620
+ totalProducts: field5.int({ default: 0 }),
621
+ totalOrders: field5.int({ default: 0 }),
622
+ totalRevenue: field5.decimal({ default: 0 }),
623
+ averageRating: field5.decimal({ default: 0 }),
647
624
  createdAt: field5.createdAt(),
648
- review: field5.belongsTo("Review", ["reviewId"], ["id"])
625
+ updatedAt: field5.updatedAt(),
626
+ products: field5.hasMany("Product"),
627
+ orders: field5.hasMany("Order"),
628
+ payouts: field5.hasMany("Payout")
649
629
  },
650
630
  indexes: [
651
- index5.on(["reviewId"]),
631
+ index5.unique(["slug"]),
632
+ index5.on(["ownerId"]),
652
633
  index5.on(["status"]),
653
- index5.on(["reporterId"])
654
- ]
634
+ index5.on(["country", "status"]),
635
+ index5.on(["averageRating"])
636
+ ],
637
+ enums: [StoreStatusEnum, StoreTypeEnum]
638
+ });
639
+ var StoreCategoryEntity = defineEntity5({
640
+ name: "StoreCategory",
641
+ description: "Category assignment for stores.",
642
+ schema: "marketplace",
643
+ map: "store_category",
644
+ fields: {
645
+ id: field5.id(),
646
+ storeId: field5.foreignKey(),
647
+ categoryId: field5.foreignKey(),
648
+ isPrimary: field5.boolean({ default: false }),
649
+ createdAt: field5.createdAt(),
650
+ store: field5.belongsTo("Store", ["storeId"], ["id"], {
651
+ onDelete: "Cascade"
652
+ })
653
+ },
654
+ indexes: [index5.unique(["storeId", "categoryId"]), index5.on(["categoryId"])]
655
655
  });
656
656
  // src/entities/index.ts
657
657
  var marketplaceEntities = [