@nymbalhq/platform 0.0.0-stage → 0.2.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/dist/chunk-74KODSYJ.js +2564 -0
- package/dist/chunk-74KODSYJ.js.map +1 -0
- package/dist/chunk-PW6ILJF7.js +740 -0
- package/dist/chunk-PW6ILJF7.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/db/schema/index.d.ts +10125 -0
- package/dist/db/schema/index.js +10 -0
- package/dist/db/schema/index.js.map +1 -0
- package/dist/index.d.ts +1372 -0
- package/dist/index.js +6652 -0
- package/dist/index.js.map +1 -0
- package/dist/register-IVFYBJSX.js +8 -0
- package/dist/register-IVFYBJSX.js.map +1 -0
- package/drizzle.config.postgres.ts +10 -0
- package/drizzle.config.sqlite.ts +10 -0
- package/migrations/postgres/0000_tearful_longshot.sql +166 -0
- package/migrations/postgres/0001_neat_zeigeist.sql +1 -0
- package/migrations/postgres/0002_sloppy_mad_thinker.sql +20 -0
- package/migrations/postgres/0003_violet_violations.sql +15 -0
- package/migrations/postgres/0004_white_reavers.sql +15 -0
- package/migrations/postgres/0005_natural_nico_minoru.sql +12 -0
- package/migrations/postgres/0006_minor_dragon_man.sql +28 -0
- package/migrations/postgres/meta/0000_snapshot.json +1172 -0
- package/migrations/postgres/meta/0001_snapshot.json +1187 -0
- package/migrations/postgres/meta/0002_snapshot.json +1325 -0
- package/migrations/postgres/meta/0003_snapshot.json +1432 -0
- package/migrations/postgres/meta/0004_snapshot.json +1439 -0
- package/migrations/postgres/meta/0005_snapshot.json +1461 -0
- package/migrations/postgres/meta/0006_snapshot.json +1598 -0
- package/migrations/postgres/meta/_journal.json +55 -0
- package/migrations/sqlite/0000_glorious_vision.sql +166 -0
- package/migrations/sqlite/0001_tricky_glorian.sql +1 -0
- package/migrations/sqlite/0002_puzzling_epoch.sql +19 -0
- package/migrations/sqlite/0003_fantastic_captain_stacy.sql +15 -0
- package/migrations/sqlite/0004_remarkable_shriek.sql +12 -0
- package/migrations/sqlite/0005_conscious_speedball.sql +13 -0
- package/migrations/sqlite/0006_flat_psylocke.sql +28 -0
- package/migrations/sqlite/meta/0000_snapshot.json +1093 -0
- package/migrations/sqlite/meta/0001_snapshot.json +1100 -0
- package/migrations/sqlite/meta/0002_snapshot.json +1222 -0
- package/migrations/sqlite/meta/0003_snapshot.json +1320 -0
- package/migrations/sqlite/meta/0004_snapshot.json +1328 -0
- package/migrations/sqlite/meta/0005_snapshot.json +1343 -0
- package/migrations/sqlite/meta/0006_snapshot.json +1470 -0
- package/migrations/sqlite/meta/_journal.json +55 -0
- package/package.json +69 -3
- package/README.md +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/routes/auth-middleware.ts","../src/routes/auth.ts","../src/routes/envelope.ts","../src/routes/products.ts","../src/routes/categories.ts","../src/routes/cart.ts","../src/routes/checkout.ts","../src/routes/orders.ts","../src/routes/role-middleware.ts","../src/routes/customers.ts","../src/routes/admin-me.ts","../src/routes/admin-dashboard.ts","../src/routes/admin-orders.ts","../src/services/refund-service.ts","../src/money.ts","../src/routes/admin-products.ts","../src/routes/admin-inventory.ts","../src/routes/admin-customers.ts","../src/routes/admin-search.ts","../src/routes/admin-reviews.ts","../src/routes/admin.ts","../src/routes/admin-static.ts","../src/routes/events-sse.ts","../src/routes/webhooks-stripe.ts","../src/routes/validated-adapter.ts","../src/routes/schemas.ts","../src/routes/register.ts"],"sourcesContent":["import type { MiddlewareHandler } from '@nymbalhq/types'\nimport type { AuthService } from '../services/auth-service.js'\n\n/**\n * Non-blocking: decodes a bearer token if present and populates ctx.auth.\n * Downstream routes that require auth should use `requireAuth` or `requireRole`.\n */\nexport function createAuthMiddleware(auth: AuthService): MiddlewareHandler {\n return async (ctx) => {\n const raw = ctx.headers.authorization\n const header = Array.isArray(raw) ? raw[0] : raw\n if (!header || !header.toLowerCase().startsWith('bearer ')) return\n const token = header.slice('bearer '.length).trim()\n try {\n const payload = await auth.verifyAccessToken(token)\n ctx.auth = {\n userId: payload.sub,\n roles: payload.roles,\n token,\n }\n } catch {\n // silently ignore — endpoints may still succeed for anonymous users\n }\n return\n }\n}\n","import {\n AuthError,\n type HttpAdapter,\n type ResponseEnvelope,\n type ResponseCookie,\n} from '@nymbalhq/types'\nimport type { AuthService } from '../services/auth-service.js'\nimport { ok, fail, renderError } from './envelope.js'\n\ninterface RegisterBody {\n email?: string\n password?: string\n firstName?: string\n lastName?: string\n phone?: string\n}\ninterface LoginBody {\n email?: string\n password?: string\n}\ninterface RefreshBody {\n refreshToken?: string\n}\n\nconst REFRESH_COOKIE = 'nymbal.refresh'\n\nfunction refreshCookies(token: string, maxAgeSeconds: number): ResponseCookie[] {\n return [\n {\n name: REFRESH_COOKIE,\n value: token,\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure: process.env.NODE_ENV === 'production',\n maxAge: maxAgeSeconds,\n },\n ]\n}\n\nfunction expiredCookies(): ResponseCookie[] {\n return [{ name: REFRESH_COOKIE, value: '', path: '/', maxAge: 0, httpOnly: true }]\n}\n\nexport function registerAuthRoutes(adapter: HttpAdapter, auth: AuthService): void {\n adapter.registerRoute('POST', '/api/auth/register', async (ctx) => {\n try {\n const body = ctx.body as RegisterBody | undefined\n if (!body?.email || !body.password) {\n return fail('auth.invalid_input', 'email and password are required', 400)\n }\n const registerInput: Parameters<AuthService['register']>[0] = {\n email: body.email,\n password: body.password,\n ...(body.firstName !== undefined && { firstName: body.firstName }),\n ...(body.lastName !== undefined && { lastName: body.lastName }),\n ...(body.phone !== undefined && { phone: body.phone }),\n }\n const result = await auth.register(registerInput)\n const envelope = ok(\n { customer: result.customer, accessToken: result.tokens.accessToken, expiresIn: result.tokens.expiresIn },\n undefined,\n 201,\n )\n envelope.cookies = refreshCookies(result.tokens.refreshToken, 60 * 60 * 24 * 7)\n return envelope as ResponseEnvelope\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('POST', '/api/auth/login', async (ctx) => {\n try {\n const body = ctx.body as LoginBody | undefined\n if (!body?.email || !body.password) {\n return fail('auth.invalid_input', 'email and password are required', 400)\n }\n const result = await auth.login(body.email, body.password)\n const envelope = ok({\n customer: result.customer,\n accessToken: result.tokens.accessToken,\n expiresIn: result.tokens.expiresIn,\n })\n envelope.cookies = refreshCookies(result.tokens.refreshToken, 60 * 60 * 24 * 7)\n return envelope as ResponseEnvelope\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('POST', '/api/auth/refresh', async (ctx) => {\n try {\n const body = ctx.body as RefreshBody | undefined\n const refreshToken = body?.refreshToken ?? ctx.cookies[REFRESH_COOKIE]\n if (!refreshToken) throw new AuthError('token_invalid', 'refresh token missing')\n const tokens = await auth.refresh(refreshToken)\n const envelope = ok({ accessToken: tokens.accessToken, expiresIn: tokens.expiresIn })\n envelope.cookies = refreshCookies(tokens.refreshToken, 60 * 60 * 24 * 7)\n return envelope as ResponseEnvelope\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('POST', '/api/auth/logout', async (ctx) => {\n try {\n const refreshToken =\n (ctx.body as RefreshBody | undefined)?.refreshToken ?? ctx.cookies[REFRESH_COOKIE]\n if (refreshToken) await auth.logout(refreshToken)\n const envelope = ok({ ok: true })\n envelope.cookies = expiredCookies()\n return envelope as ResponseEnvelope\n } catch (err) {\n return renderError(err)\n }\n })\n}\n","import {\n CheckoutError,\n HttpError,\n NotFoundError,\n NymbalError,\n OrderConflictError,\n StatusTransitionError,\n ValidationError,\n type ResponseEnvelope,\n} from '@nymbalhq/types'\n\nexport interface Envelope<T> {\n data?: T\n meta?: Record<string, unknown>\n error?: { code: string; message: string; context?: Record<string, unknown> }\n}\n\nexport function ok<T>(\n data: T,\n meta?: Record<string, unknown>,\n status = 200,\n): ResponseEnvelope<Envelope<T>> {\n const body: Envelope<T> = { data, ...(meta !== undefined && { meta }) }\n return { status, body }\n}\n\nexport function fail(\n code: string,\n message: string,\n status = 400,\n context?: Record<string, unknown>,\n): ResponseEnvelope<Envelope<never>> {\n const body: Envelope<never> = {\n error: { code, message, ...(context !== undefined && { context }) },\n }\n return { status, body }\n}\n\n/**\n * What the shopper can fix answers 4xx. `finalize_failed` is a fault and stays 5xx: the payment provider retries a\n * webhook only on a non-2xx.\n */\nconst CHECKOUT_STATUS: Record<string, number> = {\n 'checkout.cart_empty': 409,\n 'checkout.in_progress': 409,\n 'checkout.payment_in_progress': 409,\n 'checkout.out_of_stock': 409,\n 'checkout.reservation_failed': 409,\n 'checkout.variant_missing': 422,\n}\n\nexport function renderError(err: unknown): ResponseEnvelope<Envelope<never>> {\n if (err instanceof HttpError) {\n return fail(err.code, err.message, err.status)\n }\n if (err instanceof NotFoundError) {\n return fail(err.code, err.message, 404, err.context)\n }\n if (err instanceof ValidationError) {\n return fail(err.code, err.message, 400, err.context)\n }\n // A transition the table forbids, or money that does not allow the command: the caller's to fix, never a fault.\n if (err instanceof StatusTransitionError || err instanceof OrderConflictError) {\n return fail(err.code, err.message, 409, err.context)\n }\n if (err instanceof CheckoutError) {\n return fail(err.code, err.message, CHECKOUT_STATUS[err.code] ?? 500, err.context)\n }\n if (err instanceof NymbalError) {\n return fail(err.code, err.message, 500, err.context)\n }\n const message = err instanceof Error ? err.message : String(err)\n return fail('internal', message, 500)\n}\n","import {\n DEFAULT_PRODUCT_SORT,\n NotFoundError,\n type DocumentStoreAdapter,\n type ProductSortKey,\n type QueryParams,\n type Facet,\n type HttpAdapter,\n type ReviewsAdapter,\n} from '@nymbalhq/types'\nimport type { SearchService } from '../services/search-service.js'\nimport { ok, renderError, fail } from './envelope.js'\n\nconst ORDER_BY: Record<ProductSortKey, NonNullable<QueryParams['orderBy']>> = {\n newest: { field: 'createdAt', direction: 'desc' },\n 'price-asc': { field: 'priceRange.minMinor', direction: 'asc', nulls: 'last' },\n 'price-desc': { field: 'priceRange.minMinor', direction: 'desc', nulls: 'last' },\n 'name-asc': { field: 'name', direction: 'asc' },\n 'name-desc': { field: 'name', direction: 'desc' },\n}\n\nfunction buildCategoryFacet(products: Array<Record<string, unknown>>): Facet {\n const counts = new Map<string, { name: string; count: number }>()\n for (const product of products) {\n const categories = product['categories'] as\n | Array<{ id: string; name: string; slug: string }>\n | undefined\n if (!Array.isArray(categories)) continue\n for (const cat of categories) {\n const entry = counts.get(cat.slug)\n if (entry) entry.count++\n else counts.set(cat.slug, { name: cat.name, count: 1 })\n }\n }\n return {\n field: 'category',\n label: 'Category',\n values: Array.from(counts.entries()).map(([slug, { name, count }]) => ({\n value: slug,\n label: name,\n count,\n })),\n }\n}\n\nexport function registerProductRoutes(\n adapter: HttpAdapter,\n documentStore: DocumentStoreAdapter,\n storeName: string,\n reviewsAdapter?: ReviewsAdapter,\n searchService?: SearchService,\n): void {\n adapter.registerRoute('GET', '/api/products/search', async (ctx) => {\n try {\n const rawQ = ctx.query.q\n const q = Array.isArray(rawQ) ? rawQ[0] : rawQ\n if (!q || !q.trim()) return ok({ items: [], nextCursor: null, facets: [] })\n if (!searchService) return ok({ items: [], nextCursor: null, facets: [] })\n const rawLimit = ctx.query.limit\n const limit = rawLimit\n ? Math.min(100, Math.max(1, Number(Array.isArray(rawLimit) ? rawLimit[0] : rawLimit) || 20))\n : 20\n const rawCursor = ctx.query.cursor\n const cursor = Array.isArray(rawCursor) ? rawCursor[0] : rawCursor\n const searchResult = await searchService.products(q.trim(), {\n limit,\n ...(cursor !== undefined && { cursor }),\n })\n const slugs = searchResult.items\n .map((doc) => String((doc.fields as Record<string, unknown>)?.slug ?? ''))\n .filter(Boolean)\n const products = await Promise.all(slugs.map((slug) => documentStore.get('products', slug)))\n const items = products.filter(Boolean)\n return ok({ items, nextCursor: searchResult.nextCursor, facets: [] })\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('GET', '/api/products', async (ctx) => {\n try {\n const rawLimit = ctx.query.limit\n const limit = Math.min(\n 100,\n Math.max(1, Number(Array.isArray(rawLimit) ? rawLimit[0] : rawLimit) || 20),\n )\n const rawCursor = ctx.query.cursor\n const cursor = Array.isArray(rawCursor) ? rawCursor[0] : rawCursor\n const rawCategory = ctx.query.category\n const category = Array.isArray(rawCategory) ? rawCategory[0] : rawCategory\n // The schema admits only a known key.\n const sort = (ctx.query.sort as ProductSortKey | undefined) ?? DEFAULT_PRODUCT_SORT\n const orderBy = ORDER_BY[sort]\n\n const result = await (category\n ? documentStore.query('products-by-category', {\n partitionKey: { field: 'partitionKey', value: `category:${category}` },\n orderBy,\n limit,\n ...(cursor !== undefined && { cursor }),\n })\n : documentStore.query('products', {\n partitionKey: { field: 'storeId', value: storeName },\n orderBy,\n limit,\n ...(cursor !== undefined && { cursor }),\n }))\n\n // Facets come from the full catalogue, never the page: a page holds only some of each category (the newest\n // products lead the default order), so its counts would understate what a filter returns.\n const allResult = await documentStore.query('products', {\n partitionKey: { field: 'storeId', value: storeName },\n limit: 1000,\n })\n const categoryFacet = buildCategoryFacet(allResult.items as Array<Record<string, unknown>>)\n return ok({ items: result.items, nextCursor: result.nextCursor, facets: [categoryFacet] })\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('GET', '/api/products/:slug', async (ctx) => {\n try {\n const slug = ctx.params.slug\n if (!slug) return fail('products.slug_required', 'slug param required', 400)\n const doc = await documentStore.get('products', slug)\n if (!doc) throw new NotFoundError('product', slug)\n return ok(doc)\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('GET', '/api/products/:id/reviews', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('products.id_required', 'id param required', 400)\n if (!reviewsAdapter) return ok({ items: [], nextCursor: null })\n const rawLimit = ctx.query.limit\n const limit = rawLimit\n ? Math.min(100, Math.max(1, Number(Array.isArray(rawLimit) ? rawLimit[0] : rawLimit) || 20))\n : 20\n const rawCursor = ctx.query.cursor\n const cursor = Array.isArray(rawCursor) ? rawCursor[0] : rawCursor\n const result = await reviewsAdapter.getProductReviews(id, {\n limit,\n ...(cursor && { cursor }),\n })\n return ok(result)\n } catch (err) {\n return renderError(err)\n }\n })\n}\n","import type { Category, DocumentStoreAdapter, HttpAdapter } from '@nymbalhq/types'\nimport { ok, renderError } from './envelope.js'\n\nexport function registerCategoryRoutes(\n adapter: HttpAdapter,\n documentStore: DocumentStoreAdapter,\n storeName: string,\n): void {\n adapter.registerRoute('GET', '/api/categories', async () => {\n try {\n const result = await documentStore.query<Category & { storeId: string; position: number }>(\n 'categories',\n { partitionKey: { field: 'storeId', value: storeName }, limit: 500 },\n )\n const sorted = result.items.slice().sort((a, b) => (a.position ?? 0) - (b.position ?? 0))\n return ok(sorted)\n } catch (err) {\n return renderError(err)\n }\n })\n}\n","import { type HttpAdapter, type ResponseCookie, type ResponseEnvelope } from '@nymbalhq/types'\nimport type { CartService } from '../services/cart-service.js'\nimport type { ProductRepository } from '../repositories/product.js'\nimport type { VariantRepository } from '../repositories/variant.js'\nimport { ok, fail, renderError } from './envelope.js'\n\nconst CART_COOKIE = 'nymbal.cart'\n\ninterface AddItemBody {\n variantId?: string\n qty?: number\n}\n\ninterface UpdateBody {\n qty?: number\n}\n\nfunction cookie(token: string): ResponseCookie[] {\n return [\n {\n name: CART_COOKIE,\n value: token,\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure: process.env.NODE_ENV === 'production',\n maxAge: 60 * 60 * 24 * 30,\n },\n ]\n}\n\nexport interface RegisterCartRoutesDeps {\n cart: CartService\n productRepo: ProductRepository\n variantRepo: VariantRepository\n}\n\nexport function registerCartRoutes(adapter: HttpAdapter, deps: RegisterCartRoutesDeps): void {\n const { cart, productRepo, variantRepo } = deps\n\n adapter.registerRoute('GET', '/api/cart', async (ctx) => {\n try {\n const token = ctx.cookies[CART_COOKIE]\n const existing = token ? await cart.get(token) : null\n if (existing) return ok(existing) as ResponseEnvelope\n const fresh = await cart.getOrCreate()\n const env = ok(fresh)\n env.cookies = cookie(fresh.token)\n return env as ResponseEnvelope\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('POST', '/api/cart/items', async (ctx) => {\n try {\n const body = ctx.body as AddItemBody | undefined\n if (!body?.variantId) return fail('cart.invalid', 'variantId required', 400)\n const qty = body.qty ?? 1\n const { variantId } = body\n const variant = await variantRepo.store.read((tx) => variantRepo.findById(tx, variantId))\n if (!variant) return fail('cart.variant_missing', 'variant not found', 404)\n if (variant.stock < qty) {\n return fail('cart.out_of_stock', 'insufficient stock', 409, {\n variantId: variant.id,\n available: variant.stock,\n })\n }\n const product = await productRepo.store.read((tx) =>\n productRepo.findById(tx, variant.productId),\n )\n if (!product) return fail('cart.product_missing', 'product not found', 404)\n const token = ctx.cookies[CART_COOKIE] ?? (await cart.getOrCreate()).token\n const updated = await cart.addItem(token, {\n variantId: variant.id,\n productId: product.id,\n productName: product.name,\n variantName: variant.name,\n priceMinor: variant.priceMinor,\n qty,\n imageUrl: (product.media[0] as { url?: string } | undefined)?.url ?? '',\n })\n const env = ok(updated)\n env.cookies = cookie(token)\n return env as ResponseEnvelope\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('PATCH', '/api/cart/items/:variantId', async (ctx) => {\n try {\n const token = ctx.cookies[CART_COOKIE]\n if (!token) return fail('cart.missing', 'no active cart', 404)\n const variantId = ctx.params.variantId\n if (!variantId) return fail('cart.variant_required', 'variantId param required', 400)\n const qty = (ctx.body as UpdateBody | undefined)?.qty ?? 0\n const updated = await cart.updateItemQuantity(token, variantId, qty)\n return ok(updated)\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('DELETE', '/api/cart/items/:variantId', async (ctx) => {\n try {\n const token = ctx.cookies[CART_COOKIE]\n if (!token) return fail('cart.missing', 'no active cart', 404)\n const variantId = ctx.params.variantId\n if (!variantId) return fail('cart.variant_required', 'variantId param required', 400)\n const updated = await cart.removeItem(token, variantId)\n return ok(updated)\n } catch (err) {\n return renderError(err)\n }\n })\n\n adapter.registerRoute('DELETE', '/api/cart', async (ctx) => {\n try {\n const token = ctx.cookies[CART_COOKIE]\n if (!token) return fail('cart.missing', 'no active cart', 404)\n const cleared = await cart.clear(token)\n return ok(cleared)\n } catch (err) {\n return renderError(err)\n }\n })\n}\n","import { type Address, type HttpAdapter } from '@nymbalhq/types'\nimport type { CheckoutService } from '../services/checkout-service.js'\nimport { ok, fail, renderError } from './envelope.js'\n\nconst CART_COOKIE = 'nymbal.cart'\n\ninterface BeginBody {\n email?: string\n billingAddress?: Address\n shippingAddress?: Address\n notes?: string\n}\n\nexport function registerCheckoutRoutes(adapter: HttpAdapter, checkout: CheckoutService): void {\n adapter.registerRoute('POST', '/api/checkout', async (ctx) => {\n try {\n const body = ctx.body as BeginBody | undefined\n const cartToken = ctx.cookies[CART_COOKIE]\n if (!cartToken) return fail('checkout.no_cart', 'No active cart', 400)\n if (!body?.email || !body.billingAddress || !body.shippingAddress) {\n return fail('checkout.invalid', 'email, billingAddress, shippingAddress are required', 400)\n }\n const result = await checkout.beginCheckout({\n cartToken,\n ...(ctx.auth?.userId !== undefined && { customerId: ctx.auth.userId }),\n email: body.email,\n billingAddress: body.billingAddress,\n shippingAddress: body.shippingAddress,\n ...(body.notes !== undefined && { notes: body.notes }),\n })\n return ok({\n orderId: result.orderId,\n orderNumber: result.orderNumber,\n paymentIntent: result.paymentIntent,\n currency: result.currency,\n totalMinor: result.totalMinor,\n orderStatus: result.orderStatus,\n payment: result.payment,\n })\n } catch (err) {\n return renderError(err)\n }\n })\n}\n","import {\n NotFoundError,\n type DocumentStoreAdapter,\n type HttpAdapter,\n} from '@nymbalhq/types'\nimport type { OrderService } from '../services/order-service.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireAuth } from './role-middleware.js'\n\nexport function registerOrderRoutes(\n adapter: HttpAdapter,\n orders: OrderService,\n documentStore: DocumentStoreAdapter,\n): void {\n adapter.registerRoute(\n 'GET',\n '/api/orders',\n requireAuth(async (ctx) => {\n try {\n const customerId = ctx.auth!.userId!\n const result = await documentStore.query('orders-by-customer', {\n partitionKey: { field: 'partitionKey', value: `customer:${customerId}` },\n limit: 50,\n })\n return ok(result.items, { nextCursor: result.nextCursor })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n adapter.registerRoute('GET', '/api/orders/:orderNumber', async (ctx) => {\n try {\n const orderNumber = ctx.params.orderNumber\n if (!orderNumber) return fail('orders.invalid', 'orderNumber required', 400)\n const doc = await documentStore.get('orders', orderNumber)\n if (!doc) throw new NotFoundError('order', orderNumber)\n // For authenticated users, only allow their own orders\n if (ctx.auth?.userId) {\n const o = doc as { customerId?: string }\n if (o.customerId && o.customerId !== ctx.auth.userId) {\n return fail('auth.forbidden', 'forbidden', 403)\n }\n }\n return ok(doc)\n } catch (err) {\n return renderError(err)\n }\n })\n}\n","import { AuthError, type RequestContext, type ResponseEnvelope, type Role, type RouteHandler } from '@nymbalhq/types'\nimport { fail } from './envelope.js'\n\nexport function requireAuth<T = unknown>(handler: RouteHandler<T>): RouteHandler<T> {\n return (ctx) => {\n if (!ctx.auth?.userId) {\n return fail('auth.unauthorized', 'Authentication required', 401)\n }\n return handler(ctx)\n }\n}\n\nexport function requireRole<T = unknown>(role: Role, handler: RouteHandler<T>): RouteHandler<T> {\n return (ctx) => {\n if (!ctx.auth?.userId) {\n return fail('auth.unauthorized', 'Authentication required', 401)\n }\n if (!ctx.auth.roles?.includes(role)) {\n return fail('auth.forbidden', `Role required: ${role}`, 403)\n }\n return handler(ctx)\n }\n}\n\nexport function asAuthError(ctx: RequestContext): ResponseEnvelope {\n throw new AuthError('unauthorized', 'Authentication required', { context: { path: ctx.path } })\n}\n","import { type HttpAdapter } from '@nymbalhq/types'\nimport type { CustomerService } from '../services/customer-service.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireAuth } from './role-middleware.js'\n\ninterface AddressBody {\n id?: string\n firstName: string\n lastName: string\n addressLine1: string\n addressLine2?: string\n city: string\n region: string\n postalCode: string\n country: string\n phone?: string\n isDefaultBilling?: boolean\n isDefaultShipping?: boolean\n company?: string\n}\n\nexport function registerCustomerRoutes(adapter: HttpAdapter, customers: CustomerService): void {\n adapter.registerRoute(\n 'GET',\n '/api/customers/me',\n requireAuth(async (ctx) => {\n try {\n return ok(await customers.getProfile(ctx.auth!.userId!))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n adapter.registerRoute(\n 'PATCH',\n '/api/customers/me',\n requireAuth(async (ctx) => {\n try {\n const patch = ctx.body as Record<string, unknown>\n const profile = await customers.updateProfile(ctx.auth!.userId!, {\n ...(typeof patch.firstName === 'string' && { firstName: patch.firstName }),\n ...(typeof patch.lastName === 'string' && { lastName: patch.lastName }),\n ...(typeof patch.phone === 'string' && { phone: patch.phone }),\n })\n return ok(profile)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n adapter.registerRoute(\n 'GET',\n '/api/customers/me/addresses',\n requireAuth(async (ctx) => {\n try {\n return ok(await customers.listAddresses(ctx.auth!.userId!))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n adapter.registerRoute(\n 'POST',\n '/api/customers/me/addresses',\n requireAuth(async (ctx) => {\n try {\n const body = ctx.body as AddressBody\n if (!body || !body.addressLine1) return fail('address.invalid', 'address invalid', 400)\n const addr = await customers.addAddress(ctx.auth!.userId!, {\n firstName: body.firstName,\n lastName: body.lastName,\n addressLine1: body.addressLine1,\n city: body.city,\n region: body.region,\n postalCode: body.postalCode,\n country: body.country,\n isDefaultBilling: body.isDefaultBilling ?? false,\n isDefaultShipping: body.isDefaultShipping ?? false,\n ...(body.addressLine2 !== undefined && { addressLine2: body.addressLine2 }),\n ...(body.company !== undefined && { company: body.company }),\n ...(body.phone !== undefined && { phone: body.phone }),\n })\n return ok(addr, undefined, 201)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n adapter.registerRoute(\n 'DELETE',\n '/api/customers/me/addresses/:id',\n requireAuth(async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('address.invalid', 'id required', 400)\n await customers.deleteAddress(ctx.auth!.userId!, id)\n return ok({ ok: true })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { ok, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface RegisterAdminMeRouteDeps {\n config: NymbalConfig\n}\n\nexport function registerAdminMeRoute(\n adapter: HttpAdapter,\n deps: RegisterAdminMeRouteDeps,\n): void {\n const { config } = deps\n\n adapter.registerRoute(\n 'GET',\n '/api/admin/me',\n requireRole('admin', async (ctx) => {\n try {\n return ok({\n userId: ctx.auth!.userId,\n roles: ctx.auth!.roles,\n storeName: config.store.name,\n environment: process.env['NODE_ENV'] ?? 'development',\n })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport type { Repositories } from '../repositories/index.js'\nimport { ok, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface InventoryRow {\n variantId: string\n productId: string\n productName: string\n sku: string\n stock: number\n threshold: number\n status: 'low_stock' | 'out_of_stock'\n}\n\nexport interface RegisterAdminDashboardRouteDeps {\n repos: Repositories\n config: NymbalConfig\n}\n\nexport function registerAdminDashboardRoute(\n adapter: HttpAdapter,\n deps: RegisterAdminDashboardRouteDeps,\n): void {\n const { repos } = deps\n const { store } = repos.order\n\n adapter.registerRoute(\n 'GET',\n '/api/admin/dashboard',\n requireRole('admin', async () => {\n try {\n const startOfToday = new Date(new Date().setHours(0, 0, 0, 0))\n\n // Fetch recent orders (last 200 to compute today's stats)\n const allOrders = await store.read((tx) => repos.order.list(tx, { limit: 200 }))\n\n const todayOrders = allOrders.filter((o) => new Date(o.createdAt) >= startOfToday)\n\n const shippedStatuses = new Set(['shipped', 'delivered'])\n\n const todayOrderCount = todayOrders.length\n // Revenue is the money kept: what was captured less what was refunded, whatever the status says.\n const todayRevenueMinor = todayOrders.reduce(\n (sum, o) => sum + o.capturedMinor - o.refundedMinor,\n 0,\n )\n const todayItemsShipped = todayOrders.filter((o) => shippedStatuses.has(o.status)).length\n\n // Recent orders — last 10 overall\n const recentOrders = allOrders.slice(0, 10)\n\n // Low stock: get all products and check variants\n const productVariants = await store.read(async (tx) => {\n const products = await repos.product.list(tx, { limit: 1000 })\n const out = []\n for (const product of products) {\n out.push({ product, variants: await repos.variant.findByProduct(tx, product.id) })\n }\n return out\n })\n const lowStock: InventoryRow[] = []\n\n for (const { product, variants } of productVariants) {\n for (const variant of variants) {\n if (variant.stock <= variant.lowStockThreshold) {\n lowStock.push({\n variantId: variant.id,\n productId: product.id,\n productName: product.name,\n sku: variant.sku,\n stock: variant.stock,\n threshold: variant.lowStockThreshold,\n status: variant.stock <= 0 ? 'out_of_stock' : 'low_stock',\n })\n }\n }\n }\n\n return ok({\n today: {\n orderCount: todayOrderCount,\n revenueMinor: todayRevenueMinor,\n itemsShipped: todayItemsShipped,\n },\n recentOrders,\n lowStock,\n })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import {\n OrderConflictError,\n canTransitionOrder,\n type HttpAdapter,\n type Order,\n type OrderPayment,\n type OrderStatus,\n} from '@nymbalhq/types'\nimport type { ReadTx } from '../db/command-store.js'\nimport type { OrderService } from '../services/order-service.js'\nimport type { ManualPayments } from '../services/checkout-service.js'\nimport { orderPayment, type RefundService } from '../services/refund-service.js'\nimport type { Repositories } from '../repositories/index.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface NoteEntry {\n body: string\n actor: string\n at: string\n}\n\nexport interface RegisterAdminOrdersRoutesDeps {\n order: OrderService\n checkout: ManualPayments\n refund: RefundService\n repos: Repositories\n}\n\n/** An order as the admin reads it: with what was actually paid and refunded. */\ntype AdminOrder = Order & { payment: OrderPayment }\n\nfunction parseNotes(rawNotes: string, createdAt: string): NoteEntry[] {\n if (!rawNotes) return []\n try {\n const parsed = JSON.parse(rawNotes) as unknown\n if (Array.isArray(parsed)) return parsed as NoteEntry[]\n // old plain-string format\n return [{ body: rawNotes, actor: 'system', at: createdAt }]\n } catch {\n return [{ body: rawNotes, actor: 'system', at: createdAt }]\n }\n}\n\nexport function registerAdminOrdersRoutes(\n adapter: HttpAdapter,\n deps: RegisterAdminOrdersRoutesDeps,\n): void {\n const { order, checkout, refund, repos } = deps\n const { store } = repos.order\n\n async function withPayments(tx: ReadTx, orders: Order[]): Promise<AdminOrder[]> {\n const refunds = await repos.orderRefund.listByOrders(\n tx,\n orders.map((o) => o.id),\n )\n return orders.map((o) => ({ ...o, payment: orderPayment(o, refunds.get(o.id) ?? []) }))\n }\n\n /** The order a command left, as the admin reads it. */\n async function adminOrder(fresh: Order): Promise<AdminOrder> {\n const [read] = await store.read((tx) => withPayments(tx, [fresh]))\n return read!\n }\n\n // Try direct id lookup first, then orderNumber\n async function findOrder(tx: ReadTx, idOrNumber: string): Promise<Order | null> {\n return (\n (await repos.order.findById(tx, idOrNumber)) ??\n (await repos.order.findByOrderNumber(tx, idOrNumber))\n )\n }\n\n // GET /api/admin/orders\n adapter.registerRoute(\n 'GET',\n '/api/admin/orders',\n requireRole('admin', async (ctx) => {\n try {\n const q = ctx.query\n const statusRaw = Array.isArray(q.status) ? q.status[0] : q.status\n const dateFrom = Array.isArray(q.dateFrom) ? q.dateFrom[0] : q.dateFrom\n const dateTo = Array.isArray(q.dateTo) ? q.dateTo[0] : q.dateTo\n const customer = Array.isArray(q.customer) ? q.customer[0] : q.customer\n const search = Array.isArray(q.q) ? q.q[0] : q.q\n const limitRaw = Array.isArray(q.limit) ? q.limit[0] : q.limit\n const offsetRaw = Array.isArray(q.offset) ? q.offset[0] : q.offset\n\n const limit = limitRaw ? Math.min(parseInt(limitRaw, 10) || 50, 200) : 50\n const offset = offsetRaw ? parseInt(offsetRaw, 10) || 0 : 0\n\n const listOpts: { status?: OrderStatus; limit?: number; offset?: number } = {\n limit: limit + offset + 200, // over-fetch for in-memory filtering\n offset: 0,\n }\n if (statusRaw) listOpts.status = statusRaw as OrderStatus\n let orders = await store.read((tx) => repos.order.list(tx, listOpts))\n\n // In-memory filters\n if (dateFrom) {\n const from = new Date(dateFrom)\n orders = orders.filter((o) => new Date(o.createdAt) >= from)\n }\n if (dateTo) {\n const to = new Date(dateTo)\n orders = orders.filter((o) => new Date(o.createdAt) <= to)\n }\n if (customer) {\n const lc = customer.toLowerCase()\n orders = orders.filter(\n (o) =>\n (o.customerId ?? '').toLowerCase().includes(lc) || o.email.toLowerCase().includes(lc),\n )\n }\n if (search) {\n const lc = search.toLowerCase()\n orders = orders.filter(\n (o) => o.orderNumber.toLowerCase().includes(lc) || o.email.toLowerCase().includes(lc),\n )\n }\n\n // Pagination slice\n const page = orders.slice(offset, offset + limit)\n return ok(await store.read((tx) => withPayments(tx, page)))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // GET /api/admin/orders/:orderNumber\n adapter.registerRoute(\n 'GET',\n '/api/admin/orders/:orderNumber',\n requireRole('admin', async (ctx) => {\n try {\n const orderNumber = ctx.params.orderNumber\n if (!orderNumber) return fail('admin.invalid', 'orderNumber required', 400)\n const detail = await store.read(async (tx) => {\n const found = await repos.order.findByOrderNumber(tx, orderNumber)\n if (!found) return null\n const [read] = await withPayments(tx, [found])\n return { ...read!, history: await repos.orderHistory.listByOrder(tx, found.id) }\n })\n if (!detail) return fail('orders.not_found', `Order not found: ${orderNumber}`, 404)\n return ok(detail)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/confirm\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/confirm',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n // Only money confirms an order: an unpaid one is confirmed by recording its payment (mark-paid).\n const current = await order.getById(id)\n if (canTransitionOrder(current.status, 'confirmed') && current.capturedMinor === 0) {\n throw new OrderConflictError(\n 'order.unpaid',\n `Order ${current.orderNumber} is unpaid: record its payment to confirm it`,\n )\n }\n const fresh = await order.updateStatus(id, 'confirmed', `admin:${ctx.auth!.userId}`)\n return ok(await adminOrder(fresh))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/process — confirmed → processing\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/process',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const fresh = await order.updateStatus(id, 'processing', `admin:${ctx.auth!.userId}`)\n return ok(await adminOrder(fresh))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/cancel\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/cancel',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { reason?: string } | undefined\n const reason = body?.reason ?? 'Cancelled by admin'\n const fresh = await order.cancel(id, reason, `admin:${ctx.auth!.userId}`)\n return ok(await adminOrder(fresh))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/mark-paid\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/mark-paid',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { note?: string } | undefined\n const fresh = await checkout.markPaid(id, `admin:${ctx.auth!.userId}`, body?.note)\n return ok(await adminOrder(fresh))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/mark-delivered\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/mark-delivered',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const fresh = await order.markDelivered(id, `admin:${ctx.auth!.userId}`)\n return ok(await adminOrder(fresh))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/ship\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/ship',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { trackingNumber?: string; carrier?: string } | undefined\n if (!body?.trackingNumber || !body.carrier) {\n return fail('orders.invalid', 'trackingNumber and carrier required', 400)\n }\n const fresh = await order.markShipped(\n id,\n body.trackingNumber,\n body.carrier,\n `admin:${ctx.auth!.userId}`,\n )\n return ok(await adminOrder(fresh))\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/refund\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/refund',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { amountMinor: number; reason?: string; requestId?: string }\n const result = await refund.refund({\n orderId: id,\n amountMinor: body.amountMinor,\n ...(body.reason !== undefined && { reason: body.reason }),\n ...(body.requestId !== undefined && { requestId: body.requestId }),\n actor: `admin:${ctx.auth!.userId}`,\n })\n return ok(result)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // GET /api/admin/orders/:id/timeline\n adapter.registerRoute(\n 'GET',\n '/api/admin/orders/:id/timeline',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const history = await store.read(async (tx) => {\n const found = await findOrder(tx, id)\n return found ? repos.orderHistory.listByOrder(tx, found.id) : null\n })\n if (!history) return fail('orders.not_found', `Order not found: ${id}`, 404)\n return ok(history)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // GET /api/admin/orders/:id/notes\n adapter.registerRoute(\n 'GET',\n '/api/admin/orders/:id/notes',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const found = await store.read((tx) => findOrder(tx, id))\n if (!found) return fail('orders.not_found', `Order not found: ${id}`, 404)\n const notes = parseNotes(found.notes, found.createdAt)\n return ok(notes)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/notes\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/notes',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { body?: string } | undefined\n if (!body?.body?.trim()) {\n return fail('orders.invalid', 'note body required', 400)\n }\n const newNote: NoteEntry = {\n body: body.body.trim(),\n actor: `admin:${ctx.auth!.userId}`,\n at: new Date().toISOString(),\n }\n const noted = await store.transaction(async (tx) => {\n const found = await findOrder(tx, id)\n if (!found) return false\n const updated = [...parseNotes(found.notes, found.createdAt), newNote]\n await repos.order.setNotes(tx, found.id, JSON.stringify(updated), new Date())\n return true\n })\n if (!noted) return fail('orders.not_found', `Order not found: ${id}`, 404)\n return ok({ note: newNote })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/orders/:id/resend-confirmation\n adapter.registerRoute(\n 'POST',\n '/api/admin/orders/:id/resend-confirmation',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n return ok({ sent: true, orderId: id })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_ORDER_PARTIALLY_REFUNDED,\n EVT_ORDER_REFUNDED,\n EVT_PAYMENT_REFUNDED,\n NotFoundError,\n OrderConflictError,\n PaymentError,\n StatusTransitionError,\n ValidationError,\n canTransitionOrder,\n paymentState,\n refundableMinor,\n type Logger,\n type Order,\n type OrderPayment,\n type OrderRefund,\n type OrderRefundStatus,\n type PaymentsAdapter,\n type Refund,\n} from '@nymbalhq/types'\nimport type { CommandStore, Tx } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { OrderRefundInsert } from '../repositories/order-refund.js'\nimport type { EventPublisher } from '../events/publisher.js'\nimport { formatMoney } from '../money.js'\n\n/** What the shop tells the provider; the merchant's own words stay on the refund row. */\nexport const PROVIDER_REFUND_REASON = 'requested_by_customer'\n\nexport interface RefundInput {\n orderId: string\n amountMinor: number\n reason?: string\n actor: string\n /** The client's key for this request: a repeat on the order answers the refund the first one made. */\n requestId?: string\n}\n\nexport interface RefundResult {\n order: Order\n payment: OrderPayment\n refund: OrderRefund\n}\n\nexport interface RefundService {\n /**\n * Refunds part or all of what the order captured, through the payments provider when the provider took the money.\n * The refund is held as a `pending` row under the order's lock, the provider is called outside any transaction with\n * the row id as its idempotency key, and the row is settled under the lock again by the provider's answer. A\n * `requestId` the order has already seen answers that refund as it stands and moves no money;\n * `refund.request_reused` when the amount differs.\n */\n refund(input: RefundInput): Promise<RefundResult>\n}\n\nexport interface CreateRefundServiceDeps {\n store: CommandStore\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n payments: PaymentsAdapter\n}\n\nexport function orderPayment(order: Order, refunds: OrderRefund[]): OrderPayment {\n return {\n state: paymentState(order),\n capturedMinor: order.capturedMinor,\n refundedMinor: order.refundedMinor,\n refundableMinor: refundableMinor(order, refunds),\n currency: order.currency,\n refunds,\n }\n}\n\nexport interface Settlement {\n status: OrderRefundStatus\n providerRefundId: string | null\n /** The provider answered for another amount or currency than the row's. */\n mismatch: boolean\n}\n\n/** The provider's answer settles a refund row as succeeded only when it is for the row's amount and currency. */\nexport function settlementOf(\n answer: Refund,\n row: Pick<OrderRefund, 'amountMinor' | 'currency'>,\n): Settlement {\n const matches =\n answer.amountMinor === row.amountMinor &&\n answer.currency.toUpperCase() === row.currency.toUpperCase()\n const providerRefundId = answer.refundId\n if (answer.status === 'failed') return { status: 'failed', providerRefundId, mismatch: false }\n if (!matches) return { status: 'pending', providerRefundId, mismatch: true }\n return { status: answer.status, providerRefundId, mismatch: false }\n}\n\n/** Writes `refunded_minor` as Σ of the order's succeeded refunds. */\nexport async function refreshRefunded(\n repos: Repositories,\n tx: Tx,\n orderId: string,\n at: Date,\n): Promise<{ refunds: OrderRefund[]; refundedMinor: number }> {\n const refunds = await repos.orderRefund.listByOrder(tx, orderId)\n const refundedMinor = refunds\n .filter((r) => r.status === 'succeeded')\n .reduce((sum, r) => sum + r.amountMinor, 0)\n await repos.order.setRefunded(tx, orderId, refundedMinor, at)\n return { refunds, refundedMinor }\n}\n\nexport function createRefundService(deps: CreateRefundServiceDeps): RefundService {\n const { store, repos, publisher, logger, payments } = deps\n\n /**\n * Step 1, under the order's lock: a repeated request answers its refund; otherwise the refund is checked against\n * what is refundable and held as a pending row.\n */\n async function hold(\n tx: Tx,\n input: RefundInput,\n ): Promise<{ order: Order; row: OrderRefundInsert } | { repeat: RefundResult }> {\n const order = await repos.order.lock(tx, input.orderId)\n if (!order) throw new NotFoundError('order', input.orderId)\n if (input.requestId !== undefined) {\n const earlier = await repos.orderRefund.findByRequestId(tx, order.id, input.requestId)\n if (earlier !== null) {\n if (earlier.amountMinor !== input.amountMinor) {\n throw new OrderConflictError(\n 'refund.request_reused',\n `Request ${input.requestId} already refunded ${formatMoney(earlier.amountMinor, earlier.currency)} on order ${order.orderNumber}`,\n {\n context: { amountMinor: input.amountMinor, earlierAmountMinor: earlier.amountMinor },\n },\n )\n }\n const refunds = await repos.orderRefund.listByOrder(tx, order.id)\n return { repeat: { order, payment: orderPayment(order, refunds), refund: earlier } }\n }\n }\n if (\n order.capturedMinor <= 0 ||\n (order.captureMethod === 'provider' && !order.paymentIntentId)\n ) {\n throw new OrderConflictError(\n 'refund.not_captured',\n `Order ${order.orderNumber} has no captured payment to refund`,\n )\n }\n const refundable = refundableMinor(order, await repos.orderRefund.listByOrder(tx, order.id))\n if (input.amountMinor > refundable) {\n throw new OrderConflictError(\n 'refund.exceeds_captured',\n `Refund of ${formatMoney(input.amountMinor, order.currency)} exceeds the ${formatMoney(refundable, order.currency)} refundable on order ${order.orderNumber}`,\n { context: { amountMinor: input.amountMinor, refundableMinor: refundable } },\n )\n }\n if (!canTransitionOrder(order.status, 'refunded')) {\n throw new StatusTransitionError('order', order.status, 'refunded')\n }\n const row: OrderRefundInsert = {\n id: uuidv7(),\n orderId: order.id,\n amountMinor: input.amountMinor,\n currency: order.currency,\n providerRefundId: null,\n status: 'pending',\n reason: input.reason ?? null,\n actor: input.actor,\n createdAt: new Date(),\n requestId: input.requestId ?? null,\n }\n await repos.orderRefund.insert(tx, row)\n return { order, row }\n }\n\n /**\n * Step 2, outside any transaction. A manual or imported capture moves no money through the provider. A definite\n * refusal fails the row; an unknown outcome leaves it pending, held against the capture until it is reconciled.\n */\n async function moveMoney(order: Order, row: OrderRefundInsert): Promise<Settlement> {\n if (order.captureMethod !== 'provider') {\n return { status: 'succeeded', providerRefundId: null, mismatch: false }\n }\n const context = { orderId: order.id, refundId: row.id, amountMinor: row.amountMinor }\n try {\n const answer = await payments.refund(\n order.paymentIntentId!,\n row.amountMinor,\n PROVIDER_REFUND_REASON,\n { idempotencyKey: row.id, currency: order.currency },\n )\n const settlement = settlementOf(answer, row)\n if (settlement.mismatch) {\n logger.error(\n { ...context, answer: { amountMinor: answer.amountMinor, currency: answer.currency } },\n 'provider refund answer differs from the refund; left pending',\n )\n }\n return settlement\n } catch (err) {\n if (err instanceof PaymentError && err.code === 'payment.refund_rejected') {\n logger.warn({ ...context, err }, 'provider refused the refund')\n return { status: 'failed', providerRefundId: null, mismatch: false }\n }\n logger.error({ ...context, err }, 'refund outcome unknown; left pending until reconciled')\n return { status: 'pending', providerRefundId: null, mismatch: false }\n }\n }\n\n /**\n * Step 3, under the order's lock again: the row is settled, `refunded_minor` recomputed from the rows, and the status\n * moved. The money has moved by now, so a status that no longer allows the move is kept and logged, never an error.\n */\n async function settle(\n tx: Tx,\n orderId: string,\n row: OrderRefundInsert,\n settlement: Settlement,\n ): Promise<RefundResult> {\n const order = await repos.order.lock(tx, orderId)\n if (!order) throw new NotFoundError('order', orderId)\n await repos.orderRefund.settle(tx, row.id, {\n status: settlement.status,\n providerRefundId: settlement.providerRefundId,\n })\n const now = new Date()\n const { refunds, refundedMinor } = await refreshRefunded(repos, tx, order.id, now)\n const refund = refunds.find((r) => r.id === row.id)!\n if (refund.status === 'succeeded') await recordSucceeded(tx, order, refundedMinor, refund, now)\n const fresh = (await repos.order.findById(tx, order.id))!\n return { order: fresh, payment: orderPayment(fresh, refunds), refund }\n }\n\n async function recordSucceeded(\n tx: Tx,\n order: Order,\n refundedMinor: number,\n refund: OrderRefund,\n now: Date,\n ): Promise<void> {\n const full = refundedMinor >= order.capturedMinor\n const target = full ? 'refunded' : 'partially_refunded'\n const note = `refund of ${formatMoney(refund.amountMinor, refund.currency)}${refund.reason ? `: ${refund.reason}` : ''}`\n let toStatus = order.status\n if (order.status !== target && canTransitionOrder(order.status, target)) {\n await repos.order.setStatus(tx, order.id, target, now)\n toStatus = target\n } else if (order.status !== target) {\n logger.warn(\n { orderId: order.id, refundId: refund.id, status: order.status, wanted: target },\n 'refund settled; the order status no longer allows the move and is kept',\n )\n }\n await repos.orderHistory.append(tx, {\n id: uuidv7(),\n orderId: order.id,\n fromStatus: order.status,\n toStatus,\n actor: refund.actor,\n note,\n timestamp: now,\n })\n if (order.customerId) {\n await repos.customer.incrementStats(tx, order.customerId, 0, -refund.amountMinor, now)\n }\n const payload = {\n orderId: order.id,\n refundId: refund.id,\n amountMinor: refund.amountMinor,\n currency: refund.currency,\n reason: refund.reason ?? '',\n }\n await publisher.publish(full ? EVT_ORDER_REFUNDED : EVT_ORDER_PARTIALLY_REFUNDED, payload)\n await publisher.publish(EVT_PAYMENT_REFUNDED, {\n paymentId: order.captureMethod === 'provider' ? (order.paymentIntentId ?? '') : '',\n orderId: order.id,\n refundId: refund.id,\n amountMinor: refund.amountMinor,\n currency: refund.currency,\n })\n }\n\n return {\n async refund(input) {\n if (!Number.isInteger(input.amountMinor) || input.amountMinor <= 0) {\n throw new ValidationError('amountMinor must be a positive whole number of minor units', {\n context: { amountMinor: input.amountMinor },\n })\n }\n const held = await store.transaction((tx) => hold(tx, input))\n if ('repeat' in held) return held.repeat\n const { order, row } = held\n const settlement = await moveMoney(order, row)\n return store.transaction((tx) => settle(tx, order.id, row, settlement))\n },\n }\n}\n","/**\n * An amount in the currency's own minor units as money, the way the admin shows it: 1999 GBP is £19.99,\n * 1999 JPY is ¥1,999.\n */\nexport function formatMoney(amountMinor: number, currency: string): string {\n const code = currency.toUpperCase()\n const format = new Intl.NumberFormat('en-GB', { style: 'currency', currency: code })\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2\n return format.format(amountMinor / 10 ** digits)\n}\n","import type { HttpAdapter, AiAdapter, ProductStatus } from '@nymbalhq/types'\nimport type { ProductService } from '../services/product-service.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface RegisterAdminProductsRoutesDeps {\n product: ProductService\n ai: AiAdapter | null\n}\n\nexport function registerAdminProductsRoutes(\n adapter: HttpAdapter,\n deps: RegisterAdminProductsRoutesDeps,\n): void {\n const { product } = deps\n\n // GET /api/admin/products\n adapter.registerRoute(\n 'GET',\n '/api/admin/products',\n requireRole('admin', async (ctx) => {\n try {\n const q = ctx.query\n const statusRaw = Array.isArray(q.status) ? q.status[0] : q.status\n const search = Array.isArray(q.q) ? q.q[0] : q.q\n const limitRaw = Array.isArray(q.limit) ? q.limit[0] : q.limit\n const offsetRaw = Array.isArray(q.offset) ? q.offset[0] : q.offset\n\n const limit = limitRaw ? Math.min(parseInt(limitRaw, 10) || 50, 200) : 50\n const offset = offsetRaw ? parseInt(offsetRaw, 10) || 0 : 0\n\n const listOpts: { status?: ProductStatus; limit?: number; offset?: number } = {\n limit: limit + offset + 200,\n offset: 0,\n }\n if (statusRaw) listOpts.status = statusRaw as ProductStatus\n let products = await product.list(listOpts)\n\n // In-memory q filter\n if (search) {\n const lc = search.toLowerCase()\n products = products.filter((p) => p.name.toLowerCase().includes(lc))\n }\n\n const page = products.slice(offset, offset + limit)\n return ok(page)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/products\n adapter.registerRoute(\n 'POST',\n '/api/admin/products',\n requireRole('admin', async (ctx) => {\n try {\n const snap = await product.create(ctx.body as Parameters<ProductService['create']>[0])\n return ok(snap, undefined, 201)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // PATCH /api/admin/products/:id\n adapter.registerRoute(\n 'PATCH',\n '/api/admin/products/:id',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const snap = await product.update(\n id,\n ctx.body as Parameters<ProductService['update']>[1],\n )\n return ok(snap)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // DELETE /api/admin/products/:id\n adapter.registerRoute(\n 'DELETE',\n '/api/admin/products/:id',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n await product.delete(id)\n return ok({ ok: true })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/products/:id/publish\n adapter.registerRoute(\n 'POST',\n '/api/admin/products/:id/publish',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n await product.publish(id)\n return ok({ ok: true })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/products/:id/unpublish\n adapter.registerRoute(\n 'POST',\n '/api/admin/products/:id/unpublish',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n await product.unpublish(id)\n return ok({ ok: true })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/products/:id/archive\n adapter.registerRoute(\n 'POST',\n '/api/admin/products/:id/archive',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const snap = await product.update(id, { status: 'archived' })\n return ok(snap)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/products/:id/duplicate\n adapter.registerRoute(\n 'POST',\n '/api/admin/products/:id/duplicate',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const original = await product.getById(id)\n\n const newSlug = `${original.slug}-copy`\n const snap = await product.create({\n slug: newSlug,\n name: `${original.name} (Copy)`,\n description: original.description,\n shortDescription: original.shortDescription,\n status: 'draft',\n type: original.type,\n seoTitle: original.seoTitle,\n seoDescription: original.seoDescription,\n media: original.media,\n metadata: original.metadata,\n categoryIds: original.categoryIds,\n variants: original.variants.map((v) => ({\n sku: `${v.sku}-COPY`,\n name: v.name,\n priceMinor: v.priceMinor,\n compareAtPriceMinor: v.compareAtPriceMinor,\n weightGrams: v.weightGrams,\n dimensions: v.dimensions,\n stock: v.stock,\n lowStockThreshold: v.lowStockThreshold,\n options: v.options,\n status: v.status,\n })),\n })\n return ok(snap, undefined, 201)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/products/:id/enhance\n adapter.registerRoute(\n 'POST',\n '/api/admin/products/:id/enhance',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as {\n field?: 'description' | 'alt' | 'title' | 'seoDescription'\n context?: Record<string, string>\n } | undefined\n if (!body?.field) return fail('admin.invalid', 'field required', 400)\n const validFields = ['description', 'alt', 'title', 'seoDescription']\n if (!validFields.includes(body.field)) {\n return fail('admin.invalid', `field must be one of: ${validFields.join(', ')}`, 400)\n }\n if (!deps.ai) {\n return fail('admin.unavailable', 'AI adapter not configured', 503)\n }\n\n const context = body.context ?? {}\n let prompt: string\n switch (body.field) {\n case 'description':\n prompt = `Write a compelling product description for: ${context['name'] ?? 'this product'}. Current description: ${context['current'] ?? '(empty)'}. Keep it under 200 words, engaging, and highlight key benefits.`\n break\n case 'seoDescription':\n prompt = `Write an SEO meta description (under 155 chars) for product: ${context['name'] ?? 'this product'}`\n break\n case 'title':\n prompt = `Write an SEO title tag (under 60 chars) for product: ${context['name'] ?? 'this product'}`\n break\n case 'alt':\n prompt = `Write alt text for a product image of: ${context['name'] ?? 'this product'}. Keep it under 100 chars, descriptive.`\n break\n default:\n return fail('admin.invalid', 'unknown field', 400)\n }\n\n const suggestion = await deps.ai.complete(prompt, { maxTokens: 300 })\n return ok({ suggestion })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter, StockAdjustmentReason, VariantOption } from '@nymbalhq/types'\nimport type { InventoryService } from '../services/inventory-service.js'\nimport type { ProductService } from '../services/product-service.js'\nimport type { Repositories } from '../repositories/index.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface InventoryRow {\n variantId: string\n productId: string\n productName: string\n sku: string\n options: VariantOption[]\n stock: number\n threshold: number\n status: 'in_stock' | 'low_stock' | 'out_of_stock'\n updatedAt: string\n}\n\nexport interface RegisterAdminInventoryRoutesDeps {\n inventory: InventoryService\n product: ProductService\n repos: Repositories\n}\n\nfunction stockStatus(stock: number, threshold: number): 'in_stock' | 'low_stock' | 'out_of_stock' {\n if (stock <= 0) return 'out_of_stock'\n if (stock <= threshold) return 'low_stock'\n return 'in_stock'\n}\n\nfunction urgencyOrder(status: InventoryRow['status']): number {\n if (status === 'out_of_stock') return 0\n if (status === 'low_stock') return 1\n return 2\n}\n\nexport function registerAdminInventoryRoutes(\n adapter: HttpAdapter,\n deps: RegisterAdminInventoryRoutesDeps,\n): void {\n const { inventory, product, repos } = deps\n\n // GET /api/admin/inventory\n adapter.registerRoute(\n 'GET',\n '/api/admin/inventory',\n requireRole('admin', async (ctx) => {\n try {\n const q = ctx.query\n const statusFilter = Array.isArray(q.status) ? q.status[0] : q.status\n const search = Array.isArray(q.q) ? q.q[0] : q.q\n const limitRaw = Array.isArray(q.limit) ? q.limit[0] : q.limit\n const offsetRaw = Array.isArray(q.offset) ? q.offset[0] : q.offset\n\n const limit = limitRaw ? Math.min(parseInt(limitRaw, 10) || 100, 500) : 100\n const offset = offsetRaw ? parseInt(offsetRaw, 10) || 0 : 0\n\n // Build inventory rows from all products\n const allProducts = await product.list({ limit: 1000 })\n let rows: InventoryRow[] = []\n\n for (const p of allProducts) {\n for (const variant of p.variants) {\n rows.push({\n variantId: variant.id,\n productId: p.id,\n productName: p.name,\n sku: variant.sku,\n options: variant.options,\n stock: variant.stock,\n threshold: variant.lowStockThreshold,\n status: stockStatus(variant.stock, variant.lowStockThreshold),\n updatedAt: variant.updatedAt,\n })\n }\n }\n\n // Filters\n if (statusFilter) {\n rows = rows.filter((r) => r.status === statusFilter)\n }\n if (search) {\n const lc = search.toLowerCase()\n rows = rows.filter(\n (r) => r.sku.toLowerCase().includes(lc) || r.productName.toLowerCase().includes(lc),\n )\n }\n\n // Sort by urgency\n rows.sort((a, b) => {\n const urgencyDiff = urgencyOrder(a.status) - urgencyOrder(b.status)\n if (urgencyDiff !== 0) return urgencyDiff\n // Within same urgency: low_stock sorted ascending by stock\n return a.stock - b.stock\n })\n\n const page = rows.slice(offset, offset + limit)\n return ok(page)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/inventory/:variantId/adjust\n adapter.registerRoute(\n 'POST',\n '/api/admin/inventory/:variantId/adjust',\n requireRole('admin', async (ctx) => {\n try {\n const variantId = ctx.params.variantId\n if (!variantId) return fail('admin.invalid', 'variantId required', 400)\n const body = ctx.body as { delta?: number; reason?: StockAdjustmentReason } | undefined\n if (body?.delta == null) return fail('inventory.invalid', 'delta required', 400)\n if (!body.reason) return fail('inventory.invalid', 'reason required', 400)\n\n const result = await inventory.adjustStock(\n variantId,\n body.delta,\n body.reason,\n `admin:${ctx.auth!.userId}`,\n )\n return ok({ newQty: result.newQty, variantId })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // GET /api/admin/inventory/:variantId/history\n adapter.registerRoute(\n 'GET',\n '/api/admin/inventory/:variantId/history',\n requireRole('admin', async (ctx) => {\n try {\n const variantId = ctx.params.variantId\n if (!variantId) return fail('admin.invalid', 'variantId required', 400)\n const history = await repos.stockAdjustment.store.read((tx) =>\n repos.stockAdjustment.listByVariant(tx, variantId, 100),\n )\n return ok(history)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter, Customer, Order } from '@nymbalhq/types'\nimport type { OrderService } from '../services/order-service.js'\nimport type { Repositories } from '../repositories/index.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface NoteEntry {\n body: string\n actor: string\n at: string\n}\n\nexport interface CustomerStats {\n orderCount: number\n lifetimeRevenueMinor: number\n avgOrderValueMinor: number\n firstOrderAt: string | null\n lastOrderAt: string | null\n}\n\nexport interface RegisterAdminCustomersRoutesDeps {\n order: OrderService\n repos: Repositories\n}\n\nfunction computeStats(orders: Order[]): CustomerStats {\n if (orders.length === 0) {\n return {\n orderCount: 0,\n lifetimeRevenueMinor: 0,\n avgOrderValueMinor: 0,\n firstOrderAt: null,\n lastOrderAt: null,\n }\n }\n const sorted = [...orders].sort(\n (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),\n )\n const paidStatuses = new Set([\n 'confirmed',\n 'processing',\n 'shipped',\n 'delivered',\n 'partially_refunded',\n ])\n const lifetimeRevenueMinor = orders\n .filter((o) => paidStatuses.has(o.status))\n .reduce((sum, o) => sum + o.totalMinor, 0)\n return {\n orderCount: orders.length,\n lifetimeRevenueMinor,\n avgOrderValueMinor: orders.length > 0 ? Math.round(lifetimeRevenueMinor / orders.length) : 0,\n firstOrderAt: sorted[0]?.createdAt ?? null,\n lastOrderAt: sorted[sorted.length - 1]?.createdAt ?? null,\n }\n}\n\nexport function registerAdminCustomersRoutes(\n adapter: HttpAdapter,\n deps: RegisterAdminCustomersRoutesDeps,\n): void {\n const { repos } = deps\n const { store } = repos.customer\n\n // GET /api/admin/customers\n adapter.registerRoute(\n 'GET',\n '/api/admin/customers',\n requireRole('admin', async (ctx) => {\n try {\n const q = ctx.query\n const search = Array.isArray(q.q) ? q.q[0] : q.q\n const sortRaw = Array.isArray(q.sort) ? q.sort[0] : q.sort\n const limitRaw = Array.isArray(q.limit) ? q.limit[0] : q.limit\n const offsetRaw = Array.isArray(q.offset) ? q.offset[0] : q.offset\n\n const limit = limitRaw ? Math.min(parseInt(limitRaw, 10) || 50, 200) : 50\n const offset = offsetRaw ? parseInt(offsetRaw, 10) || 0 : 0\n\n // Use order list to discover customers (v0.1 approach)\n const customerResults = await store.read(async (tx) => {\n const allOrders = await repos.order.list(tx, { limit: 500 })\n const customerIdSet = new Set<string>()\n for (const o of allOrders) {\n if (o.customerId) customerIdSet.add(o.customerId)\n }\n return Promise.all([...customerIdSet].map((id) => repos.customer.findById(tx, id)))\n })\n let customers: Customer[] = customerResults\n .filter((c): c is NonNullable<typeof c> => c !== null)\n .map(({ passwordHash: _pw, ...rest }) => rest)\n\n // q filter\n if (search) {\n const lc = search.toLowerCase()\n customers = customers.filter(\n (c) =>\n c.email.toLowerCase().includes(lc) ||\n c.firstName.toLowerCase().includes(lc) ||\n c.lastName.toLowerCase().includes(lc),\n )\n }\n\n // Sort\n const sortField = sortRaw?.split(':')[0] ?? 'totalSpentMinor'\n const sortDir = sortRaw?.split(':')[1] ?? 'desc'\n customers.sort((a, b) => {\n const aVal = (a as unknown as Record<string, unknown>)[sortField]\n const bVal = (b as unknown as Record<string, unknown>)[sortField]\n const aNum = typeof aVal === 'number' ? aVal : 0\n const bNum = typeof bVal === 'number' ? bVal : 0\n return sortDir === 'asc' ? aNum - bNum : bNum - aNum\n })\n\n const page = customers.slice(offset, offset + limit)\n return ok({ customers: page })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // GET /api/admin/customers/:id\n adapter.registerRoute(\n 'GET',\n '/api/admin/customers/:id',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const found = await store.read(async (tx) => {\n const raw = await repos.customer.findById(tx, id)\n return raw ? { raw, orders: await repos.order.listByCustomer(tx, id) } : null\n })\n if (!found) return fail('customers.not_found', `Customer not found: ${id}`, 404)\n const { passwordHash: _pw, ...customer } = found.raw\n const { orders } = found\n const stats = computeStats(orders)\n return ok({ customer, stats })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // GET /api/admin/customers/:id/orders\n adapter.registerRoute(\n 'GET',\n '/api/admin/customers/:id/orders',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const orders = await store.read((tx) => repos.order.listByCustomer(tx, id))\n return ok(orders)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/customers/:id/notes\n adapter.registerRoute(\n 'POST',\n '/api/admin/customers/:id/notes',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { body?: string } | undefined\n if (!body?.body?.trim()) {\n return fail('customers.invalid', 'note body required', 400)\n }\n const newNote: NoteEntry = {\n body: body.body.trim(),\n actor: `admin:${ctx.auth!.userId}`,\n at: new Date().toISOString(),\n }\n const noted = await store.transaction(async (tx) => {\n const raw = await repos.customer.findById(tx, id)\n if (!raw) return false\n const existingNotes = (raw.metadata.adminNotes as NoteEntry[] | undefined) ?? []\n const updatedMeta = {\n ...raw.metadata,\n adminNotes: [...existingNotes, newNote],\n }\n await repos.customer.update(tx, id, {\n metadata: updatedMeta,\n updatedAt: new Date(),\n })\n return true\n })\n if (!noted) return fail('customers.not_found', `Customer not found: ${id}`, 404)\n return ok({ note: newNote })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter } from '@nymbalhq/types'\nimport type { OrderService } from '../services/order-service.js'\nimport type { ProductService } from '../services/product-service.js'\nimport type { Repositories } from '../repositories/index.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface RegisterAdminSearchRouteDeps {\n order: OrderService\n product: ProductService\n repos: Repositories\n}\n\nexport function registerAdminSearchRoute(\n adapter: HttpAdapter,\n deps: RegisterAdminSearchRouteDeps,\n): void {\n const { product, repos } = deps\n\n adapter.registerRoute(\n 'GET',\n '/api/admin/search',\n requireRole('admin', async (ctx) => {\n try {\n const qRaw = Array.isArray(ctx.query.q) ? ctx.query.q[0] : ctx.query.q\n if (!qRaw?.trim()) {\n return fail('search.invalid', 'q parameter required', 400)\n }\n const q = qRaw.toLowerCase()\n\n // Orders\n const allOrders = await repos.order.store.read((tx) => repos.order.list(tx, { limit: 100 }))\n const matchedOrders = allOrders\n .filter(\n (o) => o.orderNumber.toLowerCase().includes(q) || o.email.toLowerCase().includes(q),\n )\n .slice(0, 5)\n\n // Products\n const allProducts = await product.list({ limit: 200 })\n const matchedProducts = allProducts\n .filter((p) => p.name.toLowerCase().includes(q) || p.slug.toLowerCase().includes(q))\n .slice(0, 5)\n\n // Customers — discover via orders\n const customerResults = await repos.order.store.read(async (tx) => {\n const allOrdersFull = await repos.order.list(tx, { limit: 500 })\n const customerIdSet = new Set<string>()\n for (const o of allOrdersFull) {\n if (o.customerId) customerIdSet.add(o.customerId)\n }\n return Promise.all([...customerIdSet].map((id) => repos.customer.findById(tx, id)))\n })\n const matchedCustomers = customerResults\n .filter((c): c is NonNullable<typeof c> => c !== null)\n .filter(\n (c) =>\n c.email.toLowerCase().includes(q) ||\n c.firstName.toLowerCase().includes(q) ||\n c.lastName.toLowerCase().includes(q),\n )\n .slice(0, 5)\n .map(({ passwordHash: _pw, ...rest }) => rest)\n\n return ok({\n orders: matchedOrders,\n products: matchedProducts,\n customers: matchedCustomers,\n })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter, ReviewsAdapter } from '@nymbalhq/types'\nimport type { ReviewRepository } from '../repositories/review.js'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nexport interface RegisterAdminReviewsRoutesDeps {\n reviewsAdapter: ReviewsAdapter\n reviewRepo: ReviewRepository\n}\n\nexport function registerAdminReviewsRoutes(\n adapter: HttpAdapter,\n deps: RegisterAdminReviewsRoutesDeps,\n): void {\n const { reviewRepo } = deps\n\n // GET /api/admin/reviews — list pending reviews\n adapter.registerRoute(\n 'GET',\n '/api/admin/reviews',\n requireRole('admin', async () => {\n try {\n const pending = await reviewRepo.store.read((tx) => reviewRepo.listByStatus(tx, 'pending'))\n return ok(pending)\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n // POST /api/admin/reviews/:id/moderate — approve or reject\n adapter.registerRoute(\n 'POST',\n '/api/admin/reviews/:id/moderate',\n requireRole('admin', async (ctx) => {\n try {\n const id = ctx.params.id\n if (!id) return fail('admin.invalid', 'id required', 400)\n const body = ctx.body as { status?: 'approved' | 'rejected' } | undefined\n if (!body?.status || !['approved', 'rejected'].includes(body.status)) {\n return fail('reviews.invalid', 'status must be approved|rejected', 400)\n }\n const status = body.status\n await reviewRepo.store.transaction((tx) =>\n reviewRepo.setModerationStatus(tx, id, status, `admin:${ctx.auth!.userId}`, new Date()),\n )\n return ok({ ok: true })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n}\n","import type { HttpAdapter } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport type { ServiceRegistry } from '../services/index.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { AdapterRegistry } from '../adapters/registry.js'\nimport { registerAdminMeRoute } from './admin-me.js'\nimport { registerAdminDashboardRoute } from './admin-dashboard.js'\nimport { registerAdminOrdersRoutes } from './admin-orders.js'\nimport { registerAdminProductsRoutes } from './admin-products.js'\nimport { registerAdminInventoryRoutes } from './admin-inventory.js'\nimport { registerAdminCustomersRoutes } from './admin-customers.js'\nimport { registerAdminSearchRoute } from './admin-search.js'\nimport { registerAdminReviewsRoutes } from './admin-reviews.js'\n\nexport interface RegisterAdminRoutesDeps {\n config: NymbalConfig\n services: ServiceRegistry\n repos: Repositories\n adapters: AdapterRegistry\n}\n\nexport function registerAdminRoutes(adapter: HttpAdapter, deps: RegisterAdminRoutesDeps): void {\n const { config, services, repos, adapters } = deps\n\n registerAdminMeRoute(adapter, { config })\n registerAdminDashboardRoute(adapter, { repos, config })\n registerAdminOrdersRoutes(adapter, {\n order: services.order,\n checkout: services.checkout,\n refund: services.refund,\n repos,\n })\n registerAdminProductsRoutes(adapter, { product: services.product, ai: adapters.ai })\n registerAdminInventoryRoutes(adapter, {\n inventory: services.inventory,\n product: services.product,\n repos,\n })\n registerAdminCustomersRoutes(adapter, { order: services.order, repos })\n registerAdminSearchRoute(adapter, {\n order: services.order,\n product: services.product,\n repos,\n })\n registerAdminReviewsRoutes(adapter, {\n reviewsAdapter: adapters.reviews,\n reviewRepo: repos.review,\n })\n}\n","import { readFile, realpath, stat } from 'node:fs/promises'\nimport { extname, resolve, sep } from 'node:path'\nimport type { HttpAdapter, ResponseEnvelope } from '@nymbalhq/types'\n\nconst MIME = new Map<string, string>([\n ['.html', 'text/html; charset=utf-8'],\n ['.js', 'text/javascript; charset=utf-8'],\n ['.mjs', 'text/javascript; charset=utf-8'],\n ['.css', 'text/css; charset=utf-8'],\n ['.json', 'application/json; charset=utf-8'],\n ['.svg', 'image/svg+xml'],\n ['.png', 'image/png'],\n ['.jpg', 'image/jpeg'],\n ['.jpeg', 'image/jpeg'],\n ['.webp', 'image/webp'],\n ['.ico', 'image/x-icon'],\n ['.woff', 'font/woff'],\n ['.woff2', 'font/woff2'],\n ['.ttf', 'font/ttf'],\n])\n\nconst BUILD_HINT =\n 'The Nymbal admin is not built. Run `pnpm --filter @nymbalhq/admin build` in the Nymbal repository, ' +\n 'or install the `@nymbalhq/admin` package beside `nymbal`.\\n'\n\nconst notFound = (body = 'Not found\\n'): ResponseEnvelope => ({\n status: 404,\n headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'no-cache' },\n body,\n})\n\n/** The file under `root` that a request path names, or null when it names nothing inside the root. */\nasync function fileWithin(root: string, requestPath: string): Promise<string | null> {\n if (requestPath.includes('\\0') || requestPath.includes('\\\\')) return null\n const candidate = resolve(root, `.${sep}${requestPath}`)\n if (candidate !== root && !candidate.startsWith(root + sep)) return null\n try {\n if (!(await stat(candidate)).isFile()) return null\n // A symlink inside the root may point outside it.\n const real = await realpath(candidate)\n return real.startsWith(root + sep) ? real : null\n } catch {\n return null\n }\n}\n\n/**\n * Serves the admin's built files at /admin/ beside /api, one origin, so its relative API URLs and the refresh cookie\n * work without a proxy. `root` is the admin's dist directory, or null when none is installed: then /admin/ answers 404\n * with how to build it.\n */\nexport function registerAdminStaticRoute(adapter: HttpAdapter, root: string | null): void {\n adapter.registerRoute('GET', '/admin', async () => ({\n status: 308,\n headers: { Location: '/admin/' },\n body: undefined,\n }))\n\n let realRoot: Promise<string | null> | null = null\n const resolvedRoot = (): Promise<string | null> =>\n (realRoot ??= root === null ? Promise.resolve(null) : realpath(root).catch(() => null))\n\n const serve = async (wildcard: string): Promise<ResponseEnvelope> => {\n const base = await resolvedRoot()\n if (base === null) return notFound(BUILD_HINT)\n\n const requestPath = wildcard === '' ? 'index.html' : wildcard\n const file = await fileWithin(base, requestPath)\n if (file !== null) {\n const ext = extname(file).toLowerCase()\n return {\n status: 200,\n headers: {\n 'Content-Type': MIME.get(ext) ?? 'application/octet-stream',\n 'Cache-Control': requestPath.startsWith('assets/')\n ? 'public, max-age=31536000, immutable'\n : 'no-cache',\n },\n body: await readFile(file),\n }\n }\n\n // A missing asset is a 404; anything else is a client-side route, answered with the app. A missing index.html is\n // an unbuilt admin, answered with the build hint.\n if (requestPath !== 'index.html' && MIME.has(extname(requestPath).toLowerCase())) {\n return notFound()\n }\n const index = await fileWithin(base, 'index.html')\n if (index === null) return notFound(BUILD_HINT)\n return {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-cache' },\n body: await readFile(index),\n }\n }\n\n adapter.registerRoute('GET', '/admin/', () => serve(''))\n adapter.registerRoute('GET', '/admin/*', (ctx) => serve(ctx.params['*'] ?? ''))\n}\n","import { createHmac, randomBytes } from 'node:crypto'\nimport {\n type DocumentStoreAdapter,\n type EventBusAdapter,\n type HttpAdapter,\n type Role,\n} from '@nymbalhq/types'\nimport { ok, fail, renderError } from './envelope.js'\nimport { requireRole } from './role-middleware.js'\n\nconst TICKET_TTL_SECONDS = 60\nconst NONCE_COLLECTION = 'sse-ticket-nonces'\n\ninterface TicketPayload {\n uid: string\n roles: Role[]\n iat: number\n nonce: string\n}\n\nfunction sign(payload: TicketPayload, secret: string): string {\n const body = Buffer.from(JSON.stringify(payload)).toString('base64url')\n const sig = createHmac('sha256', secret).update(body).digest('base64url')\n return `${body}.${sig}`\n}\n\nfunction verify(token: string, secret: string): TicketPayload | null {\n const [body, sig] = token.split('.')\n if (!body || !sig) return null\n const expected = createHmac('sha256', secret).update(body).digest('base64url')\n if (expected !== sig) return null\n try {\n return JSON.parse(Buffer.from(body, 'base64url').toString('utf8')) as TicketPayload\n } catch {\n return null\n }\n}\n\nexport interface RegisterEventsSseDeps {\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n ticketSecret: string\n}\n\nexport function registerEventsSseRoute(adapter: HttpAdapter, deps: RegisterEventsSseDeps): void {\n const { eventBus, documentStore, ticketSecret } = deps\n\n adapter.registerRoute(\n 'POST',\n '/api/admin/events/ticket',\n requireRole('admin', (ctx) => {\n try {\n const nonce = randomBytes(12).toString('base64url')\n const payload: TicketPayload = {\n uid: ctx.auth!.userId!,\n roles: (ctx.auth!.roles as Role[]) ?? ['admin'],\n iat: Math.floor(Date.now() / 1000),\n nonce,\n }\n const token = sign(payload, ticketSecret)\n return ok({ ticket: token, expiresIn: TICKET_TTL_SECONDS })\n } catch (err) {\n return renderError(err)\n }\n }),\n )\n\n adapter.registerStreamRoute('GET', '/api/admin/events', async (ctx, stream) => {\n const rawTicket = ctx.query.ticket\n const ticket = Array.isArray(rawTicket) ? rawTicket[0] : rawTicket\n if (!ticket) {\n stream.send({ event: 'error', data: { code: 'ticket.missing' } })\n stream.close()\n return\n }\n const payload = verify(ticket, ticketSecret)\n if (!payload) {\n stream.send({ event: 'error', data: { code: 'ticket.invalid' } })\n stream.close()\n return\n }\n if (Math.floor(Date.now() / 1000) - payload.iat > TICKET_TTL_SECONDS) {\n stream.send({ event: 'error', data: { code: 'ticket.expired' } })\n stream.close()\n return\n }\n // One-time nonce enforcement\n const nonceKey = `${payload.uid}:${payload.nonce}`\n const seen = await documentStore.get<{ seen: true }>(NONCE_COLLECTION, nonceKey)\n if (seen) {\n stream.send({ event: 'error', data: { code: 'ticket.replayed' } })\n stream.close()\n return\n }\n await documentStore.put(NONCE_COLLECTION, nonceKey, { seen: true }, { ttl: 120 })\n if (!payload.roles.includes('admin')) {\n stream.send({ event: 'error', data: { code: 'ticket.forbidden' } })\n stream.close()\n return\n }\n\n const subscription = await eventBus.subscribe(\n ['order.*', 'payment.*', 'inventory.*', 'adapter.*'],\n (event) => {\n stream.send({\n id: event.id,\n event: event.type,\n data: { id: event.id, type: event.type, timestamp: event.timestamp, payload: event.payload },\n })\n },\n { name: 'sse-admin-events' },\n )\n\n stream.onClose(() => {\n subscription.unsubscribe().catch(() => undefined)\n })\n stream.send({ event: 'connected', data: { at: new Date().toISOString() } })\n })\n\n void fail\n}\n","import {\n EVT_PAYMENT_FAILED,\n PaymentError,\n type HttpAdapter,\n type PaymentsAdapter,\n type WebhookResult,\n} from '@nymbalhq/types'\nimport type { CommandStore, Tx } from '../db/command-store.js'\nimport type { OrderRepository } from '../repositories/order.js'\nimport type { ProcessedEventRepository } from '../repositories/processed-event.js'\nimport type { CheckoutService } from '../services/checkout-service.js'\nimport type { EventPublisher } from '../events/publisher.js'\nimport { ok, fail, renderError } from './envelope.js'\n\n/** The handler name of this route's processed-event records. */\nconst HANDLER = 'webhook:stripe'\n\nexport interface RegisterStripeWebhookDeps {\n payments: PaymentsAdapter\n checkout: CheckoutService\n publisher: EventPublisher\n store: CommandStore\n processedEvents: ProcessedEventRepository\n orders: OrderRepository\n}\n\nexport function registerStripeWebhookRoute(\n adapter: HttpAdapter,\n deps: RegisterStripeWebhookDeps,\n): void {\n const { payments, checkout, publisher, store, processedEvents, orders } = deps\n\n /** payment.failed for the intent, naming its order when there is one. */\n async function publishFailed(tx: Tx, paymentIntentId: string, reason: string): Promise<void> {\n const order = paymentIntentId ? await orders.findByPaymentIntentId(tx, paymentIntentId) : null\n await publisher.publish(EVT_PAYMENT_FAILED, {\n paymentId: paymentIntentId,\n orderId: order?.id ?? '',\n reason,\n })\n }\n\n async function handle(tx: Tx, result: WebhookResult) {\n if (result.kind === 'payment.captured') {\n const paymentIntentId = result.paymentIntentId ?? ''\n if (\n paymentIntentId === '' ||\n typeof result.amountMinor !== 'number' ||\n typeof result.currency !== 'string' ||\n result.currency === ''\n ) {\n await publishFailed(tx, paymentIntentId, 'malformed_capture')\n return ok({ finalized: false, reason: 'malformed_capture' })\n }\n const finalized = await checkout.finalize(paymentIntentId, {\n amountMinor: result.amountMinor,\n currency: result.currency,\n })\n return finalized.finalized\n ? ok({ finalized: true, orderNumber: finalized.orderNumber })\n : ok({ finalized: false, reason: finalized.reason })\n }\n if (result.kind === 'payment.failed' && result.paymentIntentId) {\n await publishFailed(tx, result.paymentIntentId, result.reason ?? 'unknown')\n return ok({ failed: true })\n }\n return ok({ ignored: true })\n }\n\n adapter.registerRoute(\n 'POST',\n '/api/webhooks/stripe',\n async (ctx) => {\n try {\n const rawSig = ctx.headers['stripe-signature']\n const sig = Array.isArray(rawSig) ? rawSig[0] : rawSig\n if (!sig) return fail('webhook.signature_missing', 'stripe-signature header missing', 400)\n // The signature covers the exact bytes sent; a body re-serialised from its parse would not verify.\n if (ctx.rawBody === undefined) {\n return fail('webhook.raw_body_missing', 'the HTTP adapter kept no raw request body', 500)\n }\n let result: WebhookResult\n try {\n result = await payments.parseWebhook(ctx.rawBody, sig)\n } catch (err) {\n if (err instanceof PaymentError && err.code === 'payment.webhook_invalid') {\n return fail('webhook.invalid', 'signature verification failed', 400)\n }\n throw err\n }\n if (!result.verified) return fail('webhook.invalid', 'signature verification failed', 400)\n\n // The record commits with the work or its recorded outcome, so a delivery whose work threw is run again.\n return await store.transaction(async (tx) => {\n if (await processedEvents.seen(tx, HANDLER, result.eventId)) return ok({ deduped: true })\n const answer = await handle(tx, result)\n await processedEvents.markProcessed(tx, HANDLER, result.eventId, new Date())\n return answer\n })\n } catch (err) {\n return renderError(err)\n }\n },\n { csrf: false, rawBody: true },\n )\n}\n","import {\n ConfigError,\n type HttpAdapter,\n type HttpMethod,\n type RequestContext,\n type ResponseEnvelope,\n} from '@nymbalhq/types'\nimport { fail } from './envelope.js'\nimport { routeSchemas, type RouteSchema } from './schemas.js'\n\ninterface Issue {\n path: Array<string | number>\n message: string\n}\n\ntype Parsed = { ok: true; ctx: RequestContext } | { ok: false; issues: Issue[] }\n\nconst PARTS = ['params', 'query', 'body'] as const\n\nfunction schemaFor(method: HttpMethod, path: string): RouteSchema {\n const key = `${method} ${path}`\n const schema = routeSchemas[key]\n if (!schema) {\n throw new ConfigError(`route ${key} has no entry in routeSchemas`, {\n code: 'config.route_schema_missing',\n context: { method, path },\n })\n }\n return schema\n}\n\n/** The context the handler sees: each part parsed by its schema, an undeclared part empty. */\nfunction parseInput(schema: RouteSchema, ctx: RequestContext): Parsed {\n const issues: Issue[] = []\n const parsed: { params: unknown; query: unknown; body: unknown } = {\n params: {},\n query: {},\n body: undefined,\n }\n for (const part of PARTS) {\n const partSchema = schema[part]\n if (!partSchema) continue\n const result = partSchema.safeParse(ctx[part])\n if (result.success) parsed[part] = result.data\n else {\n for (const issue of result.error.issues) {\n issues.push({ path: [part, ...issue.path], message: issue.message })\n }\n }\n }\n if (issues.length > 0) return { ok: false, issues }\n return {\n ok: true,\n ctx: {\n ...ctx,\n params: parsed.params as RequestContext['params'],\n query: parsed.query as RequestContext['query'],\n body: parsed.body,\n },\n }\n}\n\nfunction invalid(issues: Issue[]): ResponseEnvelope {\n return fail('validation.failed', 'The request input is invalid', 400, { issues })\n}\n\n/**\n * The adapter `registerAllRoutes` registers through: a route with no entry in `routeSchemas` stops startup, and\n * every request's params, query and body are parsed after the adapter's guard and middlewares, before the handler.\n */\nexport function validatedAdapter(adapter: HttpAdapter): HttpAdapter {\n return {\n registerRoute(method, path, handler, options) {\n const schema = schemaFor(method, path)\n adapter.registerRoute(\n method,\n path,\n async (ctx) => {\n const input = parseInput(schema, ctx)\n return input.ok ? handler(input.ctx) : invalid(input.issues)\n },\n options,\n )\n },\n registerStreamRoute(method, path, handler, options) {\n const schema = schemaFor(method, path)\n adapter.registerStreamRoute(\n method,\n path,\n async (ctx, stream) => {\n const input = parseInput(schema, ctx)\n if (input.ok) return handler(input.ctx, stream)\n stream.send({ event: 'error', data: { code: 'validation.failed', issues: input.issues } })\n stream.close()\n },\n options,\n )\n },\n registerMiddleware(middleware) {\n adapter.registerMiddleware(middleware)\n },\n setDefaultHeaders(headers) {\n adapter.setDefaultHeaders(headers)\n },\n start(port, host) {\n return adapter.start(port, host)\n },\n stop() {\n return adapter.stop()\n },\n }\n}\n","import { z, type ZodTypeAny } from 'zod'\nimport { PRODUCT_SORT_KEYS } from '@nymbalhq/types'\n\n/**\n * The input of one route: what `registerAllRoutes` parses before the handler runs, and what a tool definition is\n * generated from. Unknown keys are stripped, so a handler sees only what is declared here.\n */\nexport interface RouteSchema {\n /** Unique, dotted: `cart.addItem`. */\n name: string\n description: string\n params?: ZodTypeAny\n query?: ZodTypeAny\n body?: ZodTypeAny\n}\n\nconst id = z.string().min(1)\n/** A query value as the HTTP layer hands it over: repeated keys arrive as an array. */\nconst queryValue = z.union([z.string(), z.array(z.string())]).optional()\nconst paging = { limit: queryValue, offset: queryValue }\n\nconst idParams = z.object({ id })\nconst orderIdParams = idParams\nconst variantIdParams = z.object({ variantId: id })\nconst orderNumberParams = z.object({ orderNumber: id })\n\nconst address = z.object({\n firstName: z.string(),\n lastName: z.string(),\n company: z.string().optional(),\n addressLine1: z.string().min(1),\n addressLine2: z.string().optional(),\n city: z.string(),\n region: z.string(),\n postalCode: z.string(),\n country: z.string(),\n phone: z.string().optional(),\n})\n\nconst money = z.number().int()\nconst productStatus = z.enum(['draft', 'active', 'archived'])\nconst productMedia = z.object({ url: z.string(), altText: z.string(), position: z.number() })\nconst variantDimensions = z.object({\n lengthMm: z.number().optional(),\n widthMm: z.number().optional(),\n heightMm: z.number().optional(),\n})\nconst productVariant = z.object({\n id: z.string().optional(),\n sku: z.string(),\n name: z.string(),\n priceMinor: money,\n compareAtPriceMinor: money.nullable().optional(),\n weightGrams: z.number().nullable().optional(),\n dimensions: variantDimensions.nullable().optional(),\n stock: z.number().int(),\n lowStockThreshold: z.number().int().optional(),\n options: z.array(z.object({ name: z.string(), value: z.string() })),\n status: z.enum(['active', 'inactive']).optional(),\n})\nconst productFields = {\n description: z.string().optional(),\n shortDescription: z.string().optional(),\n status: productStatus.optional(),\n type: z.enum(['simple', 'variable']).optional(),\n seoTitle: z.string().optional(),\n seoDescription: z.string().optional(),\n media: z.array(productMedia).optional(),\n metadata: z.record(z.unknown()).optional(),\n categoryIds: z.array(z.string()).optional(),\n}\n\nconst noteBody = z.object({ body: z.string().min(1) })\n/** A refresh token in the body, or none: the cookie carries it for a browser. */\nconst optionalRefresh = z.object({ refreshToken: z.string().optional() }).optional()\n\nexport const routeSchemas: Record<string, RouteSchema> = {\n // Auth\n 'POST /api/auth/register': {\n name: 'auth.register',\n description: 'Create a customer account and sign it in.',\n body: z.object({\n email: z.string().min(1),\n password: z.string().min(1),\n firstName: z.string().optional(),\n lastName: z.string().optional(),\n phone: z.string().optional(),\n }),\n },\n 'POST /api/auth/login': {\n name: 'auth.login',\n description: 'Sign a customer in with email and password.',\n body: z.object({ email: z.string().min(1), password: z.string().min(1) }),\n },\n 'POST /api/auth/refresh': {\n name: 'auth.refresh',\n description: 'Exchange a refresh token for a new access token.',\n body: optionalRefresh,\n },\n 'POST /api/auth/logout': {\n name: 'auth.logout',\n description: 'Revoke the refresh token and clear its cookie.',\n body: optionalRefresh,\n },\n\n // Catalogue\n 'GET /api/categories': {\n name: 'categories.list',\n description: 'List the store categories in display order.',\n },\n 'GET /api/products/search': {\n name: 'products.search',\n description: 'Search products by text.',\n query: z.object({ q: queryValue, limit: queryValue, cursor: queryValue }),\n },\n 'GET /api/products': {\n name: 'products.list',\n description:\n 'List products, optionally in one category, in one of the sort orders (default newest).',\n query: z.object({\n limit: queryValue,\n cursor: queryValue,\n category: queryValue,\n sort: z.enum(PRODUCT_SORT_KEYS).optional(),\n }),\n },\n 'GET /api/products/:slug': {\n name: 'products.get',\n description: 'Get one product by slug.',\n params: z.object({ slug: id }),\n },\n 'GET /api/products/:id/reviews': {\n name: 'products.reviews',\n description: 'List the published reviews of a product.',\n params: idParams,\n query: z.object({ limit: queryValue, cursor: queryValue }),\n },\n\n // Cart\n 'GET /api/cart': {\n name: 'cart.get',\n description: 'Get the current cart, creating one when there is none.',\n },\n 'POST /api/cart/items': {\n name: 'cart.addItem',\n description: 'Add a quantity of a variant to the cart.',\n body: z.object({ variantId: id, qty: z.number().int().positive().optional() }),\n },\n 'PATCH /api/cart/items/:variantId': {\n name: 'cart.updateItem',\n description: 'Set the quantity of a variant in the cart.',\n params: variantIdParams,\n body: z.object({ qty: z.number().int().nonnegative() }),\n },\n 'DELETE /api/cart/items/:variantId': {\n name: 'cart.removeItem',\n description: 'Remove a variant from the cart.',\n params: variantIdParams,\n },\n 'DELETE /api/cart': {\n name: 'cart.clear',\n description: 'Remove every item from the cart.',\n },\n\n // Checkout and orders\n 'POST /api/checkout': {\n name: 'checkout.begin',\n description: 'Place an order for the cart and start its payment.',\n body: z.object({\n email: z.string().min(1),\n billingAddress: address,\n shippingAddress: address,\n notes: z.string().optional(),\n }),\n },\n 'GET /api/orders': {\n name: 'orders.list',\n description: \"List the signed-in customer's orders.\",\n },\n 'GET /api/orders/:orderNumber': {\n name: 'orders.get',\n description: 'Get one order by its number.',\n params: orderNumberParams,\n },\n\n // Customer account\n 'GET /api/customers/me': {\n name: 'customers.me',\n description: \"Get the signed-in customer's profile.\",\n },\n 'PATCH /api/customers/me': {\n name: 'customers.updateMe',\n description: \"Update the signed-in customer's name or phone.\",\n body: z.object({\n firstName: z.string().optional(),\n lastName: z.string().optional(),\n phone: z.string().optional(),\n }),\n },\n 'GET /api/customers/me/addresses': {\n name: 'customers.addresses',\n description: \"List the signed-in customer's saved addresses.\",\n },\n 'POST /api/customers/me/addresses': {\n name: 'customers.addAddress',\n description: 'Save an address for the signed-in customer.',\n body: address.extend({\n isDefaultBilling: z.boolean().optional(),\n isDefaultShipping: z.boolean().optional(),\n }),\n },\n 'DELETE /api/customers/me/addresses/:id': {\n name: 'customers.removeAddress',\n description: \"Delete one of the signed-in customer's saved addresses.\",\n params: idParams,\n },\n\n // Admin: session and overview\n 'GET /api/admin/me': {\n name: 'admin.me',\n description: 'Get the signed-in admin and the store it administers.',\n },\n 'GET /api/admin/dashboard': {\n name: 'admin.dashboard',\n description: \"Today's order figures, recent orders and low stock.\",\n },\n 'GET /api/admin/search': {\n name: 'admin.search',\n description: 'Search orders, products and customers.',\n query: z.object({ q: queryValue }),\n },\n\n // Admin: orders\n 'GET /api/admin/orders': {\n name: 'admin.orders.list',\n description: 'List orders, filtered by status, date, customer or text.',\n query: z.object({\n status: queryValue,\n dateFrom: queryValue,\n dateTo: queryValue,\n customer: queryValue,\n q: queryValue,\n ...paging,\n }),\n },\n 'GET /api/admin/orders/:orderNumber': {\n name: 'admin.orders.get',\n description: 'Get one order with its status history.',\n params: orderNumberParams,\n },\n 'POST /api/admin/orders/:id/confirm': {\n name: 'admin.orders.confirm',\n description:\n 'Move a paid order to confirmed; an unpaid order is refused (record its payment instead).',\n params: orderIdParams,\n },\n 'POST /api/admin/orders/:id/process': {\n name: 'admin.orders.process',\n description: 'Move a confirmed order to processing.',\n params: orderIdParams,\n },\n 'POST /api/admin/orders/:id/cancel': {\n name: 'admin.orders.cancel',\n description: 'Cancel an order nothing was captured for, with an optional reason.',\n params: orderIdParams,\n body: z.object({ reason: z.string().optional() }).optional(),\n },\n 'POST /api/admin/orders/:id/mark-paid': {\n name: 'admin.orders.markPaid',\n description:\n \"Record a payment of the order's total taken outside the store, confirming the order.\",\n params: orderIdParams,\n body: z.object({ note: z.string().optional() }).optional(),\n },\n 'POST /api/admin/orders/:id/mark-delivered': {\n name: 'admin.orders.markDelivered',\n description: 'Move a shipped order to delivered.',\n params: orderIdParams,\n },\n 'POST /api/admin/orders/:id/ship': {\n name: 'admin.orders.ship',\n description: 'Mark an order shipped with its tracking number and carrier.',\n params: orderIdParams,\n body: z.object({ trackingNumber: z.string().min(1), carrier: z.string().min(1) }),\n },\n 'POST /api/admin/orders/:id/refund': {\n name: 'admin.orders.refund',\n description:\n 'Refund part or all of what an order captured, through the payments provider. A repeated requestId answers the refund it made and moves no money.',\n params: orderIdParams,\n body: z.object({\n amountMinor: money.positive(),\n reason: z.string().optional(),\n requestId: z.string().uuid().optional(),\n }),\n },\n 'GET /api/admin/orders/:id/timeline': {\n name: 'admin.orders.timeline',\n description: \"List an order's status history.\",\n params: orderIdParams,\n },\n 'GET /api/admin/orders/:id/notes': {\n name: 'admin.orders.notes',\n description: \"List an order's internal notes.\",\n params: orderIdParams,\n },\n 'POST /api/admin/orders/:id/notes': {\n name: 'admin.orders.addNote',\n description: 'Add an internal note to an order.',\n params: orderIdParams,\n body: noteBody,\n },\n 'POST /api/admin/orders/:id/resend-confirmation': {\n name: 'admin.orders.resendConfirmation',\n description: \"Resend an order's confirmation email.\",\n params: orderIdParams,\n },\n\n // Admin: products\n 'GET /api/admin/products': {\n name: 'admin.products.list',\n description: 'List products, filtered by status or name.',\n query: z.object({ status: queryValue, q: queryValue, ...paging }),\n },\n 'POST /api/admin/products': {\n name: 'admin.products.create',\n description: 'Create a product with its variants.',\n body: z.object({\n slug: z.string().min(1),\n name: z.string().min(1),\n ...productFields,\n variants: z.array(productVariant).optional(),\n }),\n },\n 'PATCH /api/admin/products/:id': {\n name: 'admin.products.update',\n description: \"Update a product's fields.\",\n params: idParams,\n body: z.object({ name: z.string().optional(), ...productFields }),\n },\n 'DELETE /api/admin/products/:id': {\n name: 'admin.products.delete',\n description: 'Delete a product.',\n params: idParams,\n },\n 'POST /api/admin/products/:id/publish': {\n name: 'admin.products.publish',\n description: 'Make a product visible in the store.',\n params: idParams,\n },\n 'POST /api/admin/products/:id/unpublish': {\n name: 'admin.products.unpublish',\n description: 'Hide a product from the store.',\n params: idParams,\n },\n 'POST /api/admin/products/:id/archive': {\n name: 'admin.products.archive',\n description: 'Archive a product.',\n params: idParams,\n },\n 'POST /api/admin/products/:id/duplicate': {\n name: 'admin.products.duplicate',\n description: 'Copy a product as a draft.',\n params: idParams,\n },\n 'POST /api/admin/products/:id/enhance': {\n name: 'admin.products.enhance',\n description: 'Suggest copy for one product field with the AI adapter.',\n params: idParams,\n body: z.object({\n field: z.enum(['description', 'alt', 'title', 'seoDescription']),\n context: z.record(z.string()).optional(),\n }),\n },\n\n // Admin: inventory\n 'GET /api/admin/inventory': {\n name: 'admin.inventory.list',\n description: 'List variant stock, most urgent first.',\n query: z.object({ status: queryValue, q: queryValue, ...paging }),\n },\n 'POST /api/admin/inventory/:variantId/adjust': {\n name: 'admin.inventory.adjust',\n description: \"Adjust a variant's stock by a delta, with a reason.\",\n params: variantIdParams,\n body: z.object({\n delta: z.number().int(),\n reason: z.enum([\n 'sale',\n 'return',\n 'manual',\n 'import',\n 'reservation-commit',\n 'reservation-release',\n ]),\n }),\n },\n 'GET /api/admin/inventory/:variantId/history': {\n name: 'admin.inventory.history',\n description: \"List a variant's stock adjustments.\",\n params: variantIdParams,\n },\n\n // Admin: customers\n 'GET /api/admin/customers': {\n name: 'admin.customers.list',\n description: 'List customers who have ordered, filtered and sorted.',\n query: z.object({ q: queryValue, sort: queryValue, ...paging }),\n },\n 'GET /api/admin/customers/:id': {\n name: 'admin.customers.get',\n description: 'Get one customer with order statistics.',\n params: idParams,\n },\n 'GET /api/admin/customers/:id/orders': {\n name: 'admin.customers.orders',\n description: \"List one customer's orders.\",\n params: idParams,\n },\n 'POST /api/admin/customers/:id/notes': {\n name: 'admin.customers.addNote',\n description: 'Add an internal note to a customer.',\n params: idParams,\n body: noteBody,\n },\n\n // Admin: reviews\n 'GET /api/admin/reviews': {\n name: 'admin.reviews.pending',\n description: 'List reviews awaiting moderation.',\n },\n 'POST /api/admin/reviews/:id/moderate': {\n name: 'admin.reviews.moderate',\n description: 'Approve or reject a review.',\n params: idParams,\n body: z.object({ status: z.enum(['approved', 'rejected']) }),\n },\n\n // Admin: live events\n 'POST /api/admin/events/ticket': {\n name: 'admin.events.ticket',\n description: 'Issue a one-time ticket for the admin event stream.',\n },\n 'GET /api/admin/events': {\n name: 'admin.events.stream',\n description: 'Stream order, payment and inventory events to the admin (SSE).',\n query: z.object({ ticket: queryValue }),\n },\n\n // Webhooks\n 'POST /api/webhooks/stripe': {\n name: 'webhooks.stripe',\n description: 'Receive a signed Stripe event.',\n // The signature covers the raw bytes, and a malformed event is answered by the handler itself.\n body: z.unknown(),\n },\n\n // The admin SPA, served when attachHttp is given an admin root (or NYMBAL_ADMIN_DIST is set)\n 'GET /admin': {\n name: 'admin.app.redirect',\n description: 'Redirect to the admin app.',\n },\n 'GET /admin/': {\n name: 'admin.app.index',\n description: 'Serve the admin app.',\n },\n 'GET /admin/*': {\n name: 'admin.app.asset',\n description: 'Serve the admin app and its assets.',\n params: z.object({ '*': z.string().optional() }),\n },\n}\n","import type { HttpAdapter, DocumentStoreAdapter, EventBusAdapter } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport type { ServiceRegistry } from '../services/index.js'\nimport type { AdapterRegistry } from '../adapters/registry.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\nimport { createAuthMiddleware } from './auth-middleware.js'\nimport { registerAuthRoutes } from './auth.js'\nimport { registerProductRoutes } from './products.js'\nimport { registerCategoryRoutes } from './categories.js'\nimport { registerCartRoutes } from './cart.js'\nimport { registerCheckoutRoutes } from './checkout.js'\nimport { registerOrderRoutes } from './orders.js'\nimport { registerCustomerRoutes } from './customers.js'\nimport { registerAdminRoutes } from './admin.js'\nimport { registerAdminStaticRoute } from './admin-static.js'\nimport { registerEventsSseRoute } from './events-sse.js'\nimport { registerStripeWebhookRoute } from './webhooks-stripe.js'\nimport { validatedAdapter } from './validated-adapter.js'\n\nexport interface RegisterAllRoutesDeps {\n config: NymbalConfig\n adapter: HttpAdapter\n services: ServiceRegistry\n adapters: AdapterRegistry\n repos: Repositories\n documentStore: DocumentStoreAdapter\n eventBus: EventBusAdapter\n publisher: EventPublisher\n /** The admin's dist directory, or null for a 404 that says how to build it; undefined serves no admin. */\n adminRoot?: string | null | undefined\n}\n\nexport function registerAllRoutes(deps: RegisterAllRoutesDeps): void {\n const { config, services, adapters, repos, documentStore, eventBus, publisher } = deps\n const adapter = validatedAdapter(deps.adapter)\n\n // Auth middleware — decodes bearer if present.\n adapter.registerMiddleware(createAuthMiddleware(services.auth))\n\n registerAuthRoutes(adapter, services.auth)\n registerCategoryRoutes(adapter, documentStore, config.store.name)\n registerProductRoutes(\n adapter,\n documentStore,\n config.store.name,\n adapters.reviews,\n services.search,\n )\n registerCartRoutes(adapter, {\n cart: services.cart,\n productRepo: repos.product,\n variantRepo: repos.variant,\n })\n registerCheckoutRoutes(adapter, services.checkout)\n registerOrderRoutes(adapter, services.order, documentStore)\n registerCustomerRoutes(adapter, services.customer)\n registerAdminRoutes(adapter, {\n config,\n services,\n repos,\n adapters,\n })\n registerEventsSseRoute(adapter, {\n eventBus,\n documentStore,\n ticketSecret: config.security.auth.jwtSecret,\n })\n registerStripeWebhookRoute(adapter, {\n payments: adapters.payments,\n checkout: services.checkout,\n publisher,\n store: repos.processedEvent.store,\n processedEvents: repos.processedEvent,\n orders: repos.order,\n })\n if (deps.adminRoot !== undefined) registerAdminStaticRoute(adapter, deps.adminRoot)\n}\n"],"mappings":"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","names":["NotFoundError","NotFoundError","id","CART_COOKIE","NotFoundError","AuthError","NotFoundError","id","OrderConflictError","canTransitionOrder","NotFoundError","OrderConflictError","StatusTransitionError","ValidationError","NotFoundError","OrderConflictError","StatusTransitionError","ValidationError","id","canTransitionOrder","OrderConflictError","id","id","id","id","PaymentError","PaymentError"]}
|