294 lines
5.9 KiB
TypeScript
294 lines
5.9 KiB
TypeScript
/**
|
|
* rCart Automerge document schemas.
|
|
*
|
|
* Two document types:
|
|
* - Catalog: one doc per space holding all catalog entries.
|
|
* DocId: {space}:cart:catalog
|
|
* - Orders: one doc per order (server-validated via Intent/Claim).
|
|
* DocId: {space}:cart:orders:{orderId}
|
|
*/
|
|
|
|
import type { DocSchema } from '../../shared/local-first/document';
|
|
|
|
// ── Document types ──
|
|
|
|
export interface CatalogEntry {
|
|
id: string;
|
|
artifactId: string;
|
|
artifact: unknown;
|
|
title: string;
|
|
productType: string | null;
|
|
requiredCapabilities: string[];
|
|
substrates: string[];
|
|
creatorId: string | null;
|
|
sourceSpace: string | null;
|
|
tags: string[];
|
|
status: string;
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
}
|
|
|
|
export interface CatalogDoc {
|
|
meta: {
|
|
module: string;
|
|
collection: string;
|
|
version: number;
|
|
spaceSlug: string;
|
|
createdAt: number;
|
|
};
|
|
items: Record<string, CatalogEntry>;
|
|
}
|
|
|
|
export interface OrderMeta {
|
|
id: string;
|
|
catalogEntryId: string;
|
|
artifactId: string;
|
|
buyerId: string | null;
|
|
buyerLocation: string | null;
|
|
buyerContact: string | null;
|
|
providerId: string | null;
|
|
providerName: string | null;
|
|
providerDistanceKm: number | null;
|
|
quantity: number;
|
|
productionCost: number | null;
|
|
creatorPayout: number | null;
|
|
communityPayout: number | null;
|
|
totalPrice: number | null;
|
|
currency: string;
|
|
status: string;
|
|
paymentMethod: string | null;
|
|
paymentTx: string | null;
|
|
paymentNetwork: string | null;
|
|
createdAt: number;
|
|
paidAt: number;
|
|
acceptedAt: number;
|
|
completedAt: number;
|
|
updatedAt: number;
|
|
}
|
|
|
|
export interface OrderDoc {
|
|
meta: {
|
|
module: string;
|
|
collection: string;
|
|
version: number;
|
|
spaceSlug: string;
|
|
createdAt: number;
|
|
};
|
|
order: OrderMeta;
|
|
}
|
|
|
|
// ── Schema registration ──
|
|
|
|
export const catalogSchema: DocSchema<CatalogDoc> = {
|
|
module: 'cart',
|
|
collection: 'catalog',
|
|
version: 1,
|
|
init: (): CatalogDoc => ({
|
|
meta: {
|
|
module: 'cart',
|
|
collection: 'catalog',
|
|
version: 1,
|
|
spaceSlug: '',
|
|
createdAt: Date.now(),
|
|
},
|
|
items: {},
|
|
}),
|
|
};
|
|
|
|
export const orderSchema: DocSchema<OrderDoc> = {
|
|
module: 'cart',
|
|
collection: 'orders',
|
|
version: 1,
|
|
init: (): OrderDoc => ({
|
|
meta: {
|
|
module: 'cart',
|
|
collection: 'orders',
|
|
version: 1,
|
|
spaceSlug: '',
|
|
createdAt: Date.now(),
|
|
},
|
|
order: {
|
|
id: '',
|
|
catalogEntryId: '',
|
|
artifactId: '',
|
|
buyerId: null,
|
|
buyerLocation: null,
|
|
buyerContact: null,
|
|
providerId: null,
|
|
providerName: null,
|
|
providerDistanceKm: null,
|
|
quantity: 1,
|
|
productionCost: null,
|
|
creatorPayout: null,
|
|
communityPayout: null,
|
|
totalPrice: null,
|
|
currency: 'USD',
|
|
status: 'pending',
|
|
paymentMethod: null,
|
|
paymentTx: null,
|
|
paymentNetwork: null,
|
|
createdAt: Date.now(),
|
|
paidAt: 0,
|
|
acceptedAt: 0,
|
|
completedAt: 0,
|
|
updatedAt: Date.now(),
|
|
},
|
|
}),
|
|
};
|
|
|
|
// ── Shopping Cart types ──
|
|
|
|
export type CartStatus = 'OPEN' | 'FUNDING' | 'FUNDED' | 'CHECKING_OUT' | 'ORDERED' | 'CLOSED';
|
|
|
|
export interface CartItemVendor {
|
|
name: string;
|
|
domain: string;
|
|
platform: string | null; // 'amazon' | 'shopify' | 'etsy' | null
|
|
}
|
|
|
|
export interface CartItem {
|
|
name: string;
|
|
price: number | null;
|
|
currency: string;
|
|
quantity: number;
|
|
sourceUrl: string;
|
|
imageUrl: string | null;
|
|
description: string | null;
|
|
vendor: CartItemVendor;
|
|
addedBy: string | null; // DID
|
|
addedAt: number;
|
|
sku: string | null;
|
|
}
|
|
|
|
export interface CartContribution {
|
|
userId: string | null;
|
|
username: string;
|
|
amount: number;
|
|
currency: string;
|
|
paymentMethod: string; // 'MANUAL' for MVP
|
|
status: string; // 'pending' | 'confirmed'
|
|
txHash: string | null;
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
}
|
|
|
|
export interface CartEvent {
|
|
type: string; // 'item_added' | 'item_removed' | 'contribution' | 'status_change'
|
|
actor: string;
|
|
detail: string;
|
|
timestamp: number;
|
|
}
|
|
|
|
export interface ShoppingCartDoc {
|
|
meta: {
|
|
module: string;
|
|
collection: string;
|
|
version: number;
|
|
spaceSlug: string;
|
|
createdAt: number;
|
|
};
|
|
cart: {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
status: CartStatus;
|
|
createdBy: string | null;
|
|
targetAmount: number;
|
|
fundedAmount: number;
|
|
currency: string;
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
};
|
|
items: Record<string, CartItem>;
|
|
contributions: Record<string, CartContribution>;
|
|
events: CartEvent[];
|
|
}
|
|
|
|
export interface ShoppingCartIndexEntry {
|
|
name: string;
|
|
status: CartStatus;
|
|
itemCount: number;
|
|
totalAmount: number;
|
|
fundedAmount: number;
|
|
currency: string;
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
}
|
|
|
|
export interface ShoppingCartIndexDoc {
|
|
meta: {
|
|
module: string;
|
|
collection: string;
|
|
version: number;
|
|
spaceSlug: string;
|
|
createdAt: number;
|
|
};
|
|
carts: Record<string, ShoppingCartIndexEntry>;
|
|
}
|
|
|
|
// ── Shopping Cart schema registration ──
|
|
|
|
export const shoppingCartSchema: DocSchema<ShoppingCartDoc> = {
|
|
module: 'cart',
|
|
collection: 'shopping',
|
|
version: 1,
|
|
init: (): ShoppingCartDoc => ({
|
|
meta: {
|
|
module: 'cart',
|
|
collection: 'shopping',
|
|
version: 1,
|
|
spaceSlug: '',
|
|
createdAt: Date.now(),
|
|
},
|
|
cart: {
|
|
id: '',
|
|
name: '',
|
|
description: '',
|
|
status: 'OPEN',
|
|
createdBy: null,
|
|
targetAmount: 0,
|
|
fundedAmount: 0,
|
|
currency: 'USD',
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
},
|
|
items: {},
|
|
contributions: {},
|
|
events: [],
|
|
}),
|
|
};
|
|
|
|
export const shoppingCartIndexSchema: DocSchema<ShoppingCartIndexDoc> = {
|
|
module: 'cart',
|
|
collection: 'shopping-index',
|
|
version: 1,
|
|
init: (): ShoppingCartIndexDoc => ({
|
|
meta: {
|
|
module: 'cart',
|
|
collection: 'shopping-index',
|
|
version: 1,
|
|
spaceSlug: '',
|
|
createdAt: Date.now(),
|
|
},
|
|
carts: {},
|
|
}),
|
|
};
|
|
|
|
// ── Helpers ──
|
|
|
|
export function catalogDocId(space: string) {
|
|
return `${space}:cart:catalog` as const;
|
|
}
|
|
|
|
export function orderDocId(space: string, orderId: string) {
|
|
return `${space}:cart:orders:${orderId}` as const;
|
|
}
|
|
|
|
export function shoppingCartDocId(space: string, cartId: string) {
|
|
return `${space}:cart:shopping:${cartId}` as const;
|
|
}
|
|
|
|
export function shoppingCartIndexDocId(space: string) {
|
|
return `${space}:cart:shopping-index` as const;
|
|
}
|