@unifiedcommerce/plugin-marketplace 0.0.1

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 (122) hide show
  1. package/README.md +479 -0
  2. package/dist/analytics-models.d.ts +13 -0
  3. package/dist/analytics-models.d.ts.map +1 -0
  4. package/dist/analytics-models.js +69 -0
  5. package/dist/hooks.d.ts +4 -0
  6. package/dist/hooks.d.ts.map +1 -0
  7. package/dist/hooks.js +187 -0
  8. package/dist/index.d.ts +4 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +105 -0
  11. package/dist/mcp-tools.d.ts +21 -0
  12. package/dist/mcp-tools.d.ts.map +1 -0
  13. package/dist/mcp-tools.js +183 -0
  14. package/dist/routes/b2b.d.ts +9 -0
  15. package/dist/routes/b2b.d.ts.map +1 -0
  16. package/dist/routes/b2b.js +156 -0
  17. package/dist/routes/commission.d.ts +6 -0
  18. package/dist/routes/commission.d.ts.map +1 -0
  19. package/dist/routes/commission.js +85 -0
  20. package/dist/routes/disputes-returns-reviews.d.ts +10 -0
  21. package/dist/routes/disputes-returns-reviews.d.ts.map +1 -0
  22. package/dist/routes/disputes-returns-reviews.js +179 -0
  23. package/dist/routes/payouts.d.ts +6 -0
  24. package/dist/routes/payouts.d.ts.map +1 -0
  25. package/dist/routes/payouts.js +40 -0
  26. package/dist/routes/sub-orders.d.ts +6 -0
  27. package/dist/routes/sub-orders.d.ts.map +1 -0
  28. package/dist/routes/sub-orders.js +44 -0
  29. package/dist/routes/util.d.ts +23 -0
  30. package/dist/routes/util.d.ts.map +1 -0
  31. package/dist/routes/util.js +41 -0
  32. package/dist/routes/vendor-portal.d.ts +14 -0
  33. package/dist/routes/vendor-portal.d.ts.map +1 -0
  34. package/dist/routes/vendor-portal.js +255 -0
  35. package/dist/routes/vendors.d.ts +11 -0
  36. package/dist/routes/vendors.d.ts.map +1 -0
  37. package/dist/routes/vendors.js +185 -0
  38. package/dist/schema.d.ts +3255 -0
  39. package/dist/schema.d.ts.map +1 -0
  40. package/dist/schema.js +225 -0
  41. package/dist/schemas/b2b.d.ts +1009 -0
  42. package/dist/schemas/b2b.d.ts.map +1 -0
  43. package/dist/schemas/b2b.js +208 -0
  44. package/dist/schemas/commission.d.ts +532 -0
  45. package/dist/schemas/commission.d.ts.map +1 -0
  46. package/dist/schemas/commission.js +113 -0
  47. package/dist/schemas/disputes-returns-reviews.d.ts +1405 -0
  48. package/dist/schemas/disputes-returns-reviews.d.ts.map +1 -0
  49. package/dist/schemas/disputes-returns-reviews.js +270 -0
  50. package/dist/schemas/payouts.d.ts +375 -0
  51. package/dist/schemas/payouts.d.ts.map +1 -0
  52. package/dist/schemas/payouts.js +78 -0
  53. package/dist/schemas/sub-orders.d.ts +303 -0
  54. package/dist/schemas/sub-orders.d.ts.map +1 -0
  55. package/dist/schemas/sub-orders.js +67 -0
  56. package/dist/schemas/vendor-portal.d.ts +1785 -0
  57. package/dist/schemas/vendor-portal.d.ts.map +1 -0
  58. package/dist/schemas/vendor-portal.js +294 -0
  59. package/dist/schemas/vendors.d.ts +1348 -0
  60. package/dist/schemas/vendors.d.ts.map +1 -0
  61. package/dist/schemas/vendors.js +245 -0
  62. package/dist/services/commission.d.ts +81 -0
  63. package/dist/services/commission.d.ts.map +1 -0
  64. package/dist/services/commission.js +98 -0
  65. package/dist/services/contract-price.d.ts +64 -0
  66. package/dist/services/contract-price.d.ts.map +1 -0
  67. package/dist/services/contract-price.js +57 -0
  68. package/dist/services/dispute.d.ts +156 -0
  69. package/dist/services/dispute.d.ts.map +1 -0
  70. package/dist/services/dispute.js +77 -0
  71. package/dist/services/payout.d.ts +126 -0
  72. package/dist/services/payout.d.ts.map +1 -0
  73. package/dist/services/payout.js +130 -0
  74. package/dist/services/return.d.ts +181 -0
  75. package/dist/services/return.d.ts.map +1 -0
  76. package/dist/services/return.js +80 -0
  77. package/dist/services/review.d.ts +70 -0
  78. package/dist/services/review.d.ts.map +1 -0
  79. package/dist/services/review.js +60 -0
  80. package/dist/services/rfq.d.ts +122 -0
  81. package/dist/services/rfq.d.ts.map +1 -0
  82. package/dist/services/rfq.js +60 -0
  83. package/dist/services/sub-order.d.ts +336 -0
  84. package/dist/services/sub-order.d.ts.map +1 -0
  85. package/dist/services/sub-order.js +121 -0
  86. package/dist/services/vendor.d.ts +528 -0
  87. package/dist/services/vendor.d.ts.map +1 -0
  88. package/dist/services/vendor.js +119 -0
  89. package/dist/types.d.ts +67 -0
  90. package/dist/types.d.ts.map +1 -0
  91. package/dist/types.js +13 -0
  92. package/package.json +43 -0
  93. package/src/analytics-models.ts +75 -0
  94. package/src/hooks.ts +215 -0
  95. package/src/index.ts +124 -0
  96. package/src/mcp-tools.ts +210 -0
  97. package/src/routes/b2b.ts +179 -0
  98. package/src/routes/commission.ts +95 -0
  99. package/src/routes/disputes-returns-reviews.ts +209 -0
  100. package/src/routes/payouts.ts +49 -0
  101. package/src/routes/sub-orders.ts +54 -0
  102. package/src/routes/util.ts +42 -0
  103. package/src/routes/vendor-portal.ts +277 -0
  104. package/src/routes/vendors.ts +201 -0
  105. package/src/schema.ts +260 -0
  106. package/src/schemas/b2b.ts +238 -0
  107. package/src/schemas/commission.ts +129 -0
  108. package/src/schemas/disputes-returns-reviews.ts +311 -0
  109. package/src/schemas/payouts.ts +90 -0
  110. package/src/schemas/sub-orders.ts +77 -0
  111. package/src/schemas/vendor-portal.ts +344 -0
  112. package/src/schemas/vendors.ts +281 -0
  113. package/src/services/commission.ts +120 -0
  114. package/src/services/contract-price.ts +80 -0
  115. package/src/services/dispute.ts +92 -0
  116. package/src/services/payout.ts +154 -0
  117. package/src/services/return.ts +92 -0
  118. package/src/services/review.ts +76 -0
  119. package/src/services/rfq.ts +82 -0
  120. package/src/services/sub-order.ts +136 -0
  121. package/src/services/vendor.ts +151 -0
  122. package/src/types.ts +164 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js ADDED
@@ -0,0 +1,225 @@
1
+ import { boolean, integer, jsonb, pgTable, text, timestamp, uuid, index, uniqueIndex } from "drizzle-orm/pg-core";
2
+ // ─── Vendors ─────────────────────────────────────────────────────────────────
3
+ export const vendors = pgTable("marketplace_vendors", {
4
+ id: uuid("id").defaultRandom().primaryKey(),
5
+ organizationId: text("organization_id").notNull(),
6
+ name: text("name").notNull(),
7
+ slug: text("slug"),
8
+ email: text("email"),
9
+ description: text("description"),
10
+ logoUrl: text("logo_url"),
11
+ bannerUrl: text("banner_url"),
12
+ contactPhone: text("contact_phone"),
13
+ businessAddress: jsonb("business_address").$type(),
14
+ bankAccount: jsonb("bank_account").$type(),
15
+ taxId: text("tax_id"),
16
+ status: text("status").notNull().default("pending"),
17
+ verificationStatus: text("verification_status").notNull().default("unverified"),
18
+ rejectionReason: text("rejection_reason"),
19
+ approvedCategories: jsonb("approved_categories").$type(),
20
+ tier: text("tier").notNull().default("standard"),
21
+ performanceScore: integer("performance_score").notNull().default(100),
22
+ suspensionReason: text("suspension_reason"),
23
+ suspendedAt: timestamp("suspended_at", { withTimezone: true }),
24
+ commissionRateBps: integer("commission_rate_bps").notNull().default(1000),
25
+ payoutSchedule: text("payout_schedule").notNull().default("weekly"),
26
+ payoutMinimumCents: integer("payout_minimum_cents").notNull().default(5000),
27
+ holdbackDays: integer("holdback_days").notNull().default(7),
28
+ metadata: jsonb("metadata").$type().default({}),
29
+ // ─── Store Connection (links vendor to their Shopify/WooCommerce store) ─────
30
+ storeConnectionProvider: text("store_connection_provider"), // "shopify" | "woocommerce" | null
31
+ storeConnectionUrl: text("store_connection_url"),
32
+ storeAccessToken: text("store_access_token"), // Shopify token or WC consumer key
33
+ storeConsumerSecret: text("store_consumer_secret"), // WooCommerce consumer secret (null for Shopify)
34
+ storeWebhookSecret: text("store_webhook_secret"),
35
+ lastSyncAt: timestamp("last_sync_at", { withTimezone: true }),
36
+ syncStatus: text("sync_status").default("disconnected"), // "healthy" | "stale" | "error" | "disconnected"
37
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
38
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
39
+ }, (table) => ({
40
+ orgSlugUnique: uniqueIndex("marketplace_vendors_org_slug_unique").on(table.organizationId, table.slug),
41
+ orgIdx: index("idx_marketplace_vendors_org").on(table.organizationId),
42
+ }));
43
+ // ─── Vendor–Entity Links ─────────────────────────────────────────────────────
44
+ export const vendorEntities = pgTable("marketplace_vendor_entities", {
45
+ id: uuid("id").defaultRandom().primaryKey(),
46
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
47
+ entityId: uuid("entity_id").notNull(), // FK: → sellable_entities.id (cross-package; skipped due to drizzle-orm version mismatch between core and plugin)
48
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
49
+ });
50
+ // ─── Vendor Documents ────────────────────────────────────────────────────────
51
+ export const vendorDocuments = pgTable("marketplace_vendor_documents", {
52
+ id: uuid("id").defaultRandom().primaryKey(),
53
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
54
+ type: text("type").notNull(),
55
+ fileUrl: text("file_url").notNull(),
56
+ status: text("status").notNull().default("pending"),
57
+ reviewerNotes: text("reviewer_notes"),
58
+ uploadedAt: timestamp("uploaded_at", { withTimezone: true }).defaultNow().notNull(),
59
+ reviewedAt: timestamp("reviewed_at", { withTimezone: true }),
60
+ });
61
+ // ─── Commission Rules ────────────────────────────────────────────────────────
62
+ export const commissionRules = pgTable("marketplace_commission_rules", {
63
+ id: uuid("id").defaultRandom().primaryKey(),
64
+ name: text("name").notNull(),
65
+ type: text("type").notNull(),
66
+ categorySlug: text("category_slug"),
67
+ vendorId: uuid("vendor_id").references(() => vendors.id, { onDelete: "cascade" }),
68
+ vendorTier: text("vendor_tier"),
69
+ minVolumeCents: integer("min_volume_cents"),
70
+ maxVolumeCents: integer("max_volume_cents"),
71
+ rateBps: integer("rate_bps").notNull(),
72
+ validFrom: timestamp("valid_from", { withTimezone: true }),
73
+ validUntil: timestamp("valid_until", { withTimezone: true }),
74
+ priority: integer("priority").notNull().default(0),
75
+ isActive: boolean("is_active").notNull().default(true),
76
+ });
77
+ // ─── Sub-Orders ──────────────────────────────────────────────────────────────
78
+ export const vendorSubOrders = pgTable("marketplace_vendor_sub_orders", {
79
+ id: uuid("id").defaultRandom().primaryKey(),
80
+ orderId: uuid("order_id").notNull(), // FK: → orders.id (cross-package; skipped due to drizzle-orm version mismatch between core and plugin)
81
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
82
+ status: text("status").notNull().default("pending"),
83
+ subtotal: integer("subtotal").notNull().default(0),
84
+ commissionAmount: integer("commission_amount").notNull().default(0),
85
+ payoutAmount: integer("payout_amount").notNull().default(0),
86
+ notified: boolean("notified").notNull().default(false),
87
+ lineItems: jsonb("line_items").$type().default([]),
88
+ trackingNumber: text("tracking_number"),
89
+ trackingUrl: text("tracking_url"),
90
+ carrier: text("carrier"),
91
+ fulfillmentStatus: text("fulfillment_status").notNull().default("unfulfilled"), // "unfulfilled" | "partially_fulfilled" | "fulfilled"
92
+ confirmedAt: timestamp("confirmed_at", { withTimezone: true }),
93
+ shippedAt: timestamp("shipped_at", { withTimezone: true }),
94
+ deliveredAt: timestamp("delivered_at", { withTimezone: true }),
95
+ cancelledAt: timestamp("cancelled_at", { withTimezone: true }),
96
+ cancellationReason: text("cancellation_reason"),
97
+ vendorNotes: text("vendor_notes"),
98
+ // ─── External Store Sync ────────────────────────────────────────────────────
99
+ externalOrderId: text("external_order_id"), // Order ID in vendor's external store
100
+ externalOrderUrl: text("external_order_url"), // Admin URL for vendor to view the order
101
+ externalSyncStatus: text("external_sync_status").default("pending"), // "pending" | "synced" | "failed"
102
+ metadata: jsonb("metadata").$type().default({}),
103
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
104
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
105
+ });
106
+ // ─── Payouts ─────────────────────────────────────────────────────────────────
107
+ export const vendorPayouts = pgTable("marketplace_vendor_payouts", {
108
+ id: uuid("id").defaultRandom().primaryKey(),
109
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
110
+ subOrderId: uuid("sub_order_id"),
111
+ amount: integer("amount").notNull().default(0),
112
+ status: text("status").notNull().default("pending"),
113
+ payoutMethod: text("payout_method"),
114
+ externalReference: text("external_reference"),
115
+ periodStart: timestamp("period_start", { withTimezone: true }),
116
+ periodEnd: timestamp("period_end", { withTimezone: true }),
117
+ grossAmount: integer("gross_amount"),
118
+ deductions: jsonb("deductions").$type(),
119
+ netAmount: integer("net_amount"),
120
+ failedAt: timestamp("failed_at", { withTimezone: true }),
121
+ failureReason: text("failure_reason"),
122
+ retryCount: integer("retry_count").notNull().default(0),
123
+ processedAt: timestamp("processed_at", { withTimezone: true }),
124
+ metadata: jsonb("metadata").$type().default({}),
125
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
126
+ });
127
+ // ─── Vendor Balance Ledger ───────────────────────────────────────────────────
128
+ export const vendorBalances = pgTable("marketplace_vendor_balances", {
129
+ id: uuid("id").defaultRandom().primaryKey(),
130
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
131
+ type: text("type").notNull(),
132
+ amountCents: integer("amount_cents").notNull(),
133
+ runningBalanceCents: integer("running_balance_cents").notNull(),
134
+ referenceType: text("reference_type"),
135
+ referenceId: uuid("reference_id"),
136
+ description: text("description"),
137
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
138
+ });
139
+ // ─── Disputes ────────────────────────────────────────────────────────────────
140
+ export const disputes = pgTable("marketplace_disputes", {
141
+ id: uuid("id").defaultRandom().primaryKey(),
142
+ subOrderId: uuid("sub_order_id").notNull().references(() => vendorSubOrders.id, { onDelete: "cascade" }),
143
+ openedBy: text("opened_by").notNull(),
144
+ reason: text("reason").notNull(),
145
+ description: text("description"),
146
+ status: text("status").notNull().default("open"),
147
+ resolution: text("resolution"),
148
+ resolutionNotes: text("resolution_notes"),
149
+ refundAmountCents: integer("refund_amount_cents"),
150
+ evidence: jsonb("evidence").$type().default([]),
151
+ resolvedBy: text("resolved_by"),
152
+ deadlineAt: timestamp("deadline_at", { withTimezone: true }),
153
+ openedAt: timestamp("opened_at", { withTimezone: true }).defaultNow().notNull(),
154
+ resolvedAt: timestamp("resolved_at", { withTimezone: true }),
155
+ });
156
+ // ─── Vendor Reviews ──────────────────────────────────────────────────────────
157
+ export const vendorReviews = pgTable("marketplace_vendor_reviews", {
158
+ id: uuid("id").defaultRandom().primaryKey(),
159
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
160
+ customerId: uuid("customer_id"),
161
+ orderId: uuid("order_id"),
162
+ rating: integer("rating").notNull(),
163
+ title: text("title"),
164
+ body: text("body"),
165
+ status: text("status").notNull().default("published"),
166
+ vendorResponse: text("vendor_response"),
167
+ vendorRespondedAt: timestamp("vendor_responded_at", { withTimezone: true }),
168
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
169
+ });
170
+ // ─── Return Requests ─────────────────────────────────────────────────────────
171
+ export const returnRequests = pgTable("marketplace_return_requests", {
172
+ id: uuid("id").defaultRandom().primaryKey(),
173
+ subOrderId: uuid("sub_order_id").notNull().references(() => vendorSubOrders.id, { onDelete: "cascade" }),
174
+ customerId: uuid("customer_id"),
175
+ reason: text("reason").notNull(),
176
+ description: text("description"),
177
+ status: text("status").notNull().default("requested"),
178
+ lineItems: jsonb("line_items").$type(),
179
+ refundAmountCents: integer("refund_amount_cents"),
180
+ vendorNotes: text("vendor_notes"),
181
+ trackingNumber: text("tracking_number"),
182
+ requestedAt: timestamp("requested_at", { withTimezone: true }).defaultNow().notNull(),
183
+ resolvedAt: timestamp("resolved_at", { withTimezone: true }),
184
+ });
185
+ // ─── RFQ (B2B) ──────────────────────────────────────────────────────────────
186
+ export const rfqs = pgTable("marketplace_rfq", {
187
+ id: uuid("id").defaultRandom().primaryKey(),
188
+ buyerId: uuid("buyer_id"),
189
+ title: text("title").notNull(),
190
+ description: text("description"),
191
+ categorySlug: text("category_slug"),
192
+ quantity: integer("quantity"),
193
+ budgetCents: integer("budget_cents"),
194
+ currency: text("currency").notNull().default("USD"),
195
+ deadlineAt: timestamp("deadline_at", { withTimezone: true }),
196
+ status: text("status").notNull().default("open"),
197
+ awardedVendorId: uuid("awarded_vendor_id"),
198
+ metadata: jsonb("metadata").$type().default({}),
199
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
200
+ });
201
+ export const rfqResponses = pgTable("marketplace_rfq_responses", {
202
+ id: uuid("id").defaultRandom().primaryKey(),
203
+ rfqId: uuid("rfq_id").notNull().references(() => rfqs.id, { onDelete: "cascade" }),
204
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
205
+ unitPriceCents: integer("unit_price_cents").notNull(),
206
+ totalPriceCents: integer("total_price_cents").notNull(),
207
+ leadTimeDays: integer("lead_time_days"),
208
+ notes: text("notes"),
209
+ status: text("status").notNull().default("submitted"),
210
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
211
+ });
212
+ // ─── Contract Prices (B2B) ───────────────────────────────────────────────────
213
+ export const contractPrices = pgTable("marketplace_contract_prices", {
214
+ id: uuid("id").defaultRandom().primaryKey(),
215
+ vendorId: uuid("vendor_id").notNull().references(() => vendors.id, { onDelete: "cascade" }),
216
+ buyerId: uuid("buyer_id").notNull(),
217
+ entityId: uuid("entity_id").notNull(),
218
+ variantId: uuid("variant_id"),
219
+ priceCents: integer("price_cents").notNull(),
220
+ minQuantity: integer("min_quantity").notNull().default(1),
221
+ currency: text("currency").notNull().default("USD"),
222
+ validFrom: timestamp("valid_from", { withTimezone: true }),
223
+ validUntil: timestamp("valid_until", { withTimezone: true }),
224
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
225
+ });