@fayz-ai/shop 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.cjs +38 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +38 -27
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +6 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/supabase-provider.d.ts.map +1 -1
- package/dist/tables.d.ts +10 -0
- package/dist/tables.d.ts.map +1 -0
- package/package.json +10 -4
- package/src/provider.ts +6 -0
- package/src/supabase-provider.ts +30 -29
- package/src/tables.ts +12 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase-provider.d.ts","sourceRoot":"","sources":["../src/supabase-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"supabase-provider.d.ts","sourceRoot":"","sources":["../src/supabase-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/tables.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const T: {
|
|
2
|
+
readonly products: "plg_shop_products";
|
|
3
|
+
readonly productImages: "plg_shop_product_images";
|
|
4
|
+
readonly categories: "plg_shop_categories";
|
|
5
|
+
readonly orders: "plg_shop_orders";
|
|
6
|
+
readonly orderItems: "plg_shop_order_items";
|
|
7
|
+
readonly customers: "plg_shop_customers";
|
|
8
|
+
readonly discounts: "plg_shop_discounts";
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,CAAC;;;;;;;;CAQJ,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fayz-ai/shop",
|
|
3
|
-
"
|
|
3
|
+
"fayz": {
|
|
4
|
+
"status": "beta"
|
|
5
|
+
},
|
|
6
|
+
"version": "0.8.0",
|
|
4
7
|
"description": "Fayz SDK ecommerce layer — products, orders, customers, discounts, shipping",
|
|
5
8
|
"type": "module",
|
|
6
9
|
"main": "./dist/index.cjs",
|
|
@@ -64,9 +67,9 @@
|
|
|
64
67
|
"lucide-react": "^0.400.0",
|
|
65
68
|
"@supabase/supabase-js": "^2.45.0",
|
|
66
69
|
"zustand": "^4.5.0",
|
|
67
|
-
"@fayz-ai/auth": "^0.
|
|
68
|
-
"@fayz-ai/core": "^0.
|
|
69
|
-
"@fayz-ai/ui": "^0.
|
|
70
|
+
"@fayz-ai/auth": "^0.8.0",
|
|
71
|
+
"@fayz-ai/core": "^0.8.0",
|
|
72
|
+
"@fayz-ai/ui": "^0.8.0"
|
|
70
73
|
},
|
|
71
74
|
"peerDependencies": {
|
|
72
75
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -87,6 +90,9 @@
|
|
|
87
90
|
"supabase"
|
|
88
91
|
],
|
|
89
92
|
"license": "MIT",
|
|
93
|
+
"publishConfig": {
|
|
94
|
+
"access": "public"
|
|
95
|
+
},
|
|
90
96
|
"scripts": {
|
|
91
97
|
"build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap --noEmit false",
|
|
92
98
|
"dev": "tsup --watch",
|
package/src/provider.ts
CHANGED
|
@@ -34,6 +34,12 @@ export interface ShopProvider {
|
|
|
34
34
|
getOrder(id: string): Promise<Order | null>
|
|
35
35
|
createOrder(input: CreateOrderInput): Promise<Order>
|
|
36
36
|
updateOrder(id: string, input: UpdateOrderInput): Promise<Order>
|
|
37
|
+
/**
|
|
38
|
+
* Mock/dev payment seam: pending->paid transition via a whitelisted RPC
|
|
39
|
+
* (anon storefronts have no UPDATE grant on the orders table). Real PSPs
|
|
40
|
+
* confirm via webhook with service_role instead.
|
|
41
|
+
*/
|
|
42
|
+
confirmPayment?(id: string, reference?: string): Promise<Order | null>
|
|
37
43
|
/**
|
|
38
44
|
* Trusted order placement: the server re-reads product prices + stock,
|
|
39
45
|
* validates the discount, computes totals, and decrements inventory
|
package/src/supabase-provider.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getSupabaseClientOptional } from '@fayz-ai/core'
|
|
2
2
|
import type { ShopProvider } from './provider'
|
|
3
3
|
import { getShopTenantId } from './tenant'
|
|
4
|
+
import { T } from './tables'
|
|
4
5
|
import type {
|
|
5
6
|
Product, ProductImage, Category,
|
|
6
7
|
Order, ShopCustomer, Discount,
|
|
@@ -150,7 +151,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
150
151
|
async listProducts(options?: ListProductsOptions): Promise<Product[]> {
|
|
151
152
|
const db = getDb()
|
|
152
153
|
const tenantId = getTenantId()
|
|
153
|
-
let q = db.from(
|
|
154
|
+
let q = db.from(T.products).select(`*, images:${T.productImages}(*)`)
|
|
154
155
|
if (tenantId) q = q.eq('tenant_id', tenantId)
|
|
155
156
|
if (options?.status) q = q.eq('status', options.status)
|
|
156
157
|
if (options?.categoryId) q = q.eq('category_id', options.categoryId)
|
|
@@ -167,8 +168,8 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
167
168
|
async getProduct(id: string): Promise<Product | null> {
|
|
168
169
|
const db = getDb()
|
|
169
170
|
const { data, error } = await db
|
|
170
|
-
.from(
|
|
171
|
-
.select(
|
|
171
|
+
.from(T.products)
|
|
172
|
+
.select(`*, images:${T.productImages}(*)`)
|
|
172
173
|
.eq('id', id)
|
|
173
174
|
.maybeSingle()
|
|
174
175
|
if (error) throw error
|
|
@@ -179,7 +180,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
179
180
|
const db = getDb()
|
|
180
181
|
const tenantId = getTenantId()
|
|
181
182
|
const { data, error } = await db
|
|
182
|
-
.from(
|
|
183
|
+
.from(T.products)
|
|
183
184
|
.insert({
|
|
184
185
|
tenant_id: tenantId,
|
|
185
186
|
name: input.name,
|
|
@@ -198,7 +199,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
198
199
|
weight: input.weight ?? null,
|
|
199
200
|
weight_unit: input.weightUnit ?? 'kg',
|
|
200
201
|
})
|
|
201
|
-
.select(
|
|
202
|
+
.select(`*, images:${T.productImages}(*)`)
|
|
202
203
|
.single()
|
|
203
204
|
if (error) throw error
|
|
204
205
|
return rowToProduct(data)
|
|
@@ -220,15 +221,15 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
220
221
|
if (input.isPhysical !== undefined) updates.is_physical = input.isPhysical
|
|
221
222
|
if (input.weight !== undefined) updates.weight = input.weight
|
|
222
223
|
const { data, error } = await db
|
|
223
|
-
.from(
|
|
224
|
-
.select(
|
|
224
|
+
.from(T.products).update(updates).eq('id', id)
|
|
225
|
+
.select(`*, images:${T.productImages}(*)`)
|
|
225
226
|
.single()
|
|
226
227
|
if (error) throw error
|
|
227
228
|
return rowToProduct(data)
|
|
228
229
|
}
|
|
229
230
|
|
|
230
231
|
async deleteProduct(id: string): Promise<void> {
|
|
231
|
-
const { error } = await getDb().from(
|
|
232
|
+
const { error } = await getDb().from(T.products).delete().eq('id', id)
|
|
232
233
|
if (error) throw error
|
|
233
234
|
}
|
|
234
235
|
|
|
@@ -240,7 +241,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
240
241
|
if (uploadErr) throw uploadErr
|
|
241
242
|
const { data: { publicUrl } } = db.storage.from('shop-images').getPublicUrl(path)
|
|
242
243
|
const { data, error } = await db
|
|
243
|
-
.from(
|
|
244
|
+
.from(T.productImages)
|
|
244
245
|
.insert({ product_id: productId, tenant_id: tenantId, url: publicUrl, sort_order: 0, is_primary: false })
|
|
245
246
|
.select().single()
|
|
246
247
|
if (error) throw error
|
|
@@ -248,7 +249,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
248
249
|
}
|
|
249
250
|
|
|
250
251
|
async deleteProductImage(imageId: string): Promise<void> {
|
|
251
|
-
const { error } = await getDb().from(
|
|
252
|
+
const { error } = await getDb().from(T.productImages).delete().eq('id', imageId)
|
|
252
253
|
if (error) throw error
|
|
253
254
|
}
|
|
254
255
|
|
|
@@ -259,7 +260,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
259
260
|
async listCategories(): Promise<Category[]> {
|
|
260
261
|
const db = getDb()
|
|
261
262
|
const tenantId = getTenantId()
|
|
262
|
-
let q = db.from(
|
|
263
|
+
let q = db.from(T.categories).select('*').order('sort_order', { ascending: true })
|
|
263
264
|
if (tenantId) q = q.eq('tenant_id', tenantId)
|
|
264
265
|
const { data, error } = await q
|
|
265
266
|
if (error) throw error
|
|
@@ -269,7 +270,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
269
270
|
async createCategory(input: CreateCategoryInput): Promise<Category> {
|
|
270
271
|
const db = getDb()
|
|
271
272
|
const { data, error } = await db
|
|
272
|
-
.from(
|
|
273
|
+
.from(T.categories)
|
|
273
274
|
.insert({ tenant_id: getTenantId(), name: input.name, slug: input.slug ?? slugify(input.name), description: input.description ?? null, parent_id: input.parentId ?? null, sort_order: input.sortOrder ?? 0 })
|
|
274
275
|
.select().single()
|
|
275
276
|
if (error) throw error
|
|
@@ -284,13 +285,13 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
284
285
|
if (input.description !== undefined) updates.description = input.description
|
|
285
286
|
if (input.parentId !== undefined) updates.parent_id = input.parentId
|
|
286
287
|
if (input.sortOrder !== undefined) updates.sort_order = input.sortOrder
|
|
287
|
-
const { data, error } = await db.from(
|
|
288
|
+
const { data, error } = await db.from(T.categories).update(updates).eq('id', id).select().single()
|
|
288
289
|
if (error) throw error
|
|
289
290
|
return rowToCategory(data)
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
async deleteCategory(id: string): Promise<void> {
|
|
293
|
-
const { error } = await getDb().from(
|
|
294
|
+
const { error } = await getDb().from(T.categories).delete().eq('id', id)
|
|
294
295
|
if (error) throw error
|
|
295
296
|
}
|
|
296
297
|
|
|
@@ -301,7 +302,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
301
302
|
async listOrders(options?: ListOrdersOptions): Promise<Order[]> {
|
|
302
303
|
const db = getDb()
|
|
303
304
|
const tenantId = getTenantId()
|
|
304
|
-
let q = db.from(
|
|
305
|
+
let q = db.from(T.orders).select(`*, items:${T.orderItems}(*)`)
|
|
305
306
|
if (tenantId) q = q.eq('tenant_id', tenantId)
|
|
306
307
|
if (options?.status) q = q.eq('status', options.status)
|
|
307
308
|
if (options?.financialStatus) q = q.eq('financial_status', options.financialStatus)
|
|
@@ -318,7 +319,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
318
319
|
|
|
319
320
|
async getOrder(id: string): Promise<Order | null> {
|
|
320
321
|
const { data, error } = await getDb()
|
|
321
|
-
.from(
|
|
322
|
+
.from(T.orders).select(`*, items:${T.orderItems}(*)`)
|
|
322
323
|
.eq('id', id).maybeSingle()
|
|
323
324
|
if (error) throw error
|
|
324
325
|
return data ? rowToOrder(data) : null
|
|
@@ -332,12 +333,12 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
332
333
|
const shippingTotal = input.shippingTotal ?? 0
|
|
333
334
|
const total = Math.round((subtotal - discountTotal + shippingTotal) * 100) / 100
|
|
334
335
|
const { data: order, error: orderErr } = await db
|
|
335
|
-
.from(
|
|
336
|
+
.from(T.orders)
|
|
336
337
|
.insert({ tenant_id: tenantId, customer_id: input.customerId ?? null, customer_name: input.customerName ?? null, customer_email: input.customerEmail ?? null, currency: input.currency ?? 'BRL', notes: input.notes ?? null, subtotal, discount_total: discountTotal, shipping_total: shippingTotal, discount_code: input.discountCode ?? null, total, status: 'open', financial_status: 'pending', fulfillment_status: 'unfulfilled' })
|
|
337
338
|
.select().single()
|
|
338
339
|
if (orderErr) throw orderErr
|
|
339
340
|
const items = input.items.map(i => ({ order_id: order.id, product_id: asUuid(i.productId), name: i.name, sku: i.sku ?? null, quantity: i.quantity, unit_price: i.unitPrice, total: i.quantity * i.unitPrice, image_url: i.imageUrl ?? null }))
|
|
340
|
-
await db.from(
|
|
341
|
+
await db.from(T.orderItems).insert(items)
|
|
341
342
|
return this.getOrder(order.id) as Promise<Order>
|
|
342
343
|
}
|
|
343
344
|
|
|
@@ -347,7 +348,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
347
348
|
if (input.financialStatus !== undefined) updates.financial_status = input.financialStatus
|
|
348
349
|
if (input.fulfillmentStatus !== undefined) updates.fulfillment_status = input.fulfillmentStatus
|
|
349
350
|
if (input.notes !== undefined) updates.notes = input.notes
|
|
350
|
-
const { error } = await getDb().from(
|
|
351
|
+
const { error } = await getDb().from(T.orders).update(updates).eq('id', id)
|
|
351
352
|
if (error) throw error
|
|
352
353
|
return this.getOrder(id) as Promise<Order>
|
|
353
354
|
}
|
|
@@ -383,7 +384,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
383
384
|
async listCustomers(options?: ListCustomersOptions): Promise<ShopCustomer[]> {
|
|
384
385
|
const db = getDb()
|
|
385
386
|
const tenantId = getTenantId()
|
|
386
|
-
let q = db.from(
|
|
387
|
+
let q = db.from(T.customers).select('*').order('first_name', { ascending: true })
|
|
387
388
|
if (tenantId) q = q.eq('tenant_id', tenantId)
|
|
388
389
|
if (options?.search) q = q.or(`first_name.ilike.%${options.search}%,last_name.ilike.%${options.search}%,email.ilike.%${options.search}%`)
|
|
389
390
|
if (options?.limit) q = q.limit(options.limit)
|
|
@@ -393,14 +394,14 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
393
394
|
}
|
|
394
395
|
|
|
395
396
|
async getCustomer(id: string): Promise<ShopCustomer | null> {
|
|
396
|
-
const { data, error } = await getDb().from(
|
|
397
|
+
const { data, error } = await getDb().from(T.customers).select('*').eq('id', id).maybeSingle()
|
|
397
398
|
if (error) throw error
|
|
398
399
|
return data ? rowToCustomer(data) : null
|
|
399
400
|
}
|
|
400
401
|
|
|
401
402
|
async createCustomer(input: CreateCustomerInput): Promise<ShopCustomer> {
|
|
402
403
|
const { data, error } = await getDb()
|
|
403
|
-
.from(
|
|
404
|
+
.from(T.customers)
|
|
404
405
|
.insert({ tenant_id: getTenantId(), first_name: input.firstName, last_name: input.lastName ?? '', email: input.email ?? null, phone: input.phone ?? null, notes: input.notes ?? null })
|
|
405
406
|
.select().single()
|
|
406
407
|
if (error) throw error
|
|
@@ -414,13 +415,13 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
414
415
|
if (input.email !== undefined) updates.email = input.email
|
|
415
416
|
if (input.phone !== undefined) updates.phone = input.phone
|
|
416
417
|
if (input.notes !== undefined) updates.notes = input.notes
|
|
417
|
-
const { data, error } = await getDb().from(
|
|
418
|
+
const { data, error } = await getDb().from(T.customers).update(updates).eq('id', id).select().single()
|
|
418
419
|
if (error) throw error
|
|
419
420
|
return rowToCustomer(data)
|
|
420
421
|
}
|
|
421
422
|
|
|
422
423
|
async deleteCustomer(id: string): Promise<void> {
|
|
423
|
-
const { error } = await getDb().from(
|
|
424
|
+
const { error } = await getDb().from(T.customers).delete().eq('id', id)
|
|
424
425
|
if (error) throw error
|
|
425
426
|
}
|
|
426
427
|
|
|
@@ -448,7 +449,7 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
448
449
|
async listDiscounts(options?: ListDiscountsOptions): Promise<Discount[]> {
|
|
449
450
|
const db = getDb()
|
|
450
451
|
const tenantId = getTenantId()
|
|
451
|
-
let q = db.from(
|
|
452
|
+
let q = db.from(T.discounts).select('*').order('created_at', { ascending: false })
|
|
452
453
|
if (tenantId) q = q.eq('tenant_id', tenantId)
|
|
453
454
|
if (options?.status) q = q.eq('status', options.status)
|
|
454
455
|
if (options?.type) q = q.eq('type', options.type)
|
|
@@ -460,14 +461,14 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
460
461
|
}
|
|
461
462
|
|
|
462
463
|
async getDiscount(id: string): Promise<Discount | null> {
|
|
463
|
-
const { data, error } = await getDb().from(
|
|
464
|
+
const { data, error } = await getDb().from(T.discounts).select('*').eq('id', id).maybeSingle()
|
|
464
465
|
if (error) throw error
|
|
465
466
|
return data ? rowToDiscount(data) : null
|
|
466
467
|
}
|
|
467
468
|
|
|
468
469
|
async createDiscount(input: CreateDiscountInput): Promise<Discount> {
|
|
469
470
|
const { data, error } = await getDb()
|
|
470
|
-
.from(
|
|
471
|
+
.from(T.discounts)
|
|
471
472
|
.insert({ tenant_id: getTenantId(), title: input.title, code: input.code ?? null, type: input.type, method: input.method ?? 'code', value: input.value, usage_limit: input.usageLimit ?? null, once_per_customer: input.oncePerCustomer ?? false, starts_at: input.startsAt ?? new Date().toISOString(), ends_at: input.endsAt ?? null, status: input.status ?? 'active', times_used: 0 })
|
|
472
473
|
.select().single()
|
|
473
474
|
if (error) throw error
|
|
@@ -483,13 +484,13 @@ export class SupabaseShopProvider implements ShopProvider {
|
|
|
483
484
|
if (input.usageLimit !== undefined) updates.usage_limit = input.usageLimit
|
|
484
485
|
if (input.status !== undefined) updates.status = input.status
|
|
485
486
|
if (input.endsAt !== undefined) updates.ends_at = input.endsAt
|
|
486
|
-
const { data, error } = await getDb().from(
|
|
487
|
+
const { data, error } = await getDb().from(T.discounts).update(updates).eq('id', id).select().single()
|
|
487
488
|
if (error) throw error
|
|
488
489
|
return rowToDiscount(data)
|
|
489
490
|
}
|
|
490
491
|
|
|
491
492
|
async deleteDiscount(id: string): Promise<void> {
|
|
492
|
-
const { error } = await getDb().from(
|
|
493
|
+
const { error } = await getDb().from(T.discounts).delete().eq('id', id)
|
|
493
494
|
if (error) throw error
|
|
494
495
|
}
|
|
495
496
|
}
|
package/src/tables.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Physical table names for @fayz-ai/shop. Renamed to the plg_shop_* industry-pool
|
|
2
|
+
// prefix (was shop_*) when the core DB moved into the public schema. RPC function
|
|
3
|
+
// names (shop_place_order, shop_get_order, shop_resolve_customer) are unchanged.
|
|
4
|
+
export const T = {
|
|
5
|
+
products: 'plg_shop_products',
|
|
6
|
+
productImages: 'plg_shop_product_images',
|
|
7
|
+
categories: 'plg_shop_categories',
|
|
8
|
+
orders: 'plg_shop_orders',
|
|
9
|
+
orderItems: 'plg_shop_order_items',
|
|
10
|
+
customers: 'plg_shop_customers',
|
|
11
|
+
discounts: 'plg_shop_discounts',
|
|
12
|
+
} as const
|