@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/db/command-store.ts","../src/document-store/factory.ts","../src/document-store/in-memory.ts","../src/event-bus/factory.ts","../src/event-bus/in-process.ts","../src/logger.ts","../src/platform.ts","../src/db/migrate.ts","../src/db/repositories/products.ts","../src/db/repositories/categories.ts","../src/repositories/product.ts","../src/repositories/json.ts","../src/repositories/variant.ts","../src/repositories/category.ts","../src/repositories/product-category.ts","../src/repositories/customer.ts","../src/repositories/refresh-token.ts","../src/repositories/order.ts","../src/repositories/order-history.ts","../src/repositories/order-refund.ts","../src/repositories/order-sequence.ts","../src/repositories/inventory-reservation.ts","../src/repositories/stock-adjustment.ts","../src/repositories/review.ts","../src/repositories/processed-event.ts","../src/repositories/event-log.ts","../src/repositories/cart.ts","../src/repositories/index.ts","../src/events/builder.ts","../src/events/publisher.ts","../src/events/relay.ts","../src/handlers/idempotency.ts","../src/handlers/projections/category-projection.ts","../src/handlers/projections/product-projection.ts","../src/handlers/projections/order-projection.ts","../src/handlers/projections/customer-projection.ts","../src/handlers/projections/inventory-projection.ts","../src/handlers/side-effects/email-handler.ts","../src/handlers/side-effects/search-handler.ts","../src/handlers/side-effects/reviews-handler.ts","../src/handlers/register.ts","../src/app.ts","../src/adapters/security/headers.ts","../src/adapters/base.ts","../src/adapters/security/middleware-adapter.ts","../src/adapters/payments/stripe-adapter.ts","../src/adapters/payments/native-stub.ts","../src/adapters/email/native-email-adapter.ts","../src/adapters/email/templates.ts","../src/adapters/search/native-adapter.ts","../src/adapters/reviews/native-adapter.ts","../src/adapters/analytics/native-adapter.ts","../src/adapters/shipping/native-adapter.ts","../src/adapters/tax/native-adapter.ts","../src/adapters/ai/native-adapter.ts","../src/adapters/ai/anthropic-adapter.ts","../src/adapters/registry.ts","../src/services/product-service.ts","../src/services/category-service.ts","../src/services/cart-service.ts","../src/services/customer-service.ts","../src/services/auth-service.ts","../src/services/order-service.ts","../src/services/inventory-service.ts","../src/services/checkout-service.ts","../src/services/search-service.ts","../src/services/index.ts","../src/warm-document-store.ts","../src/sweepers/inventory-reservation-sweeper.ts","../src/sweepers/cart-abandonment-sweeper.ts","../src/sweepers/event-retention-sweeper.ts","../src/adapters/security/rate-limit.ts","../src/seed/run.ts","../src/seed/data.ts","../src/media/local-fs-storage.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { envOptional } from '@nymbalhq/config'\nimport { AdapterError, ConfigError } from '@nymbalhq/types'\n\nimport BetterSqlite3 from 'better-sqlite3'\nimport pg from 'pg'\nimport { drizzle as drizzleSqlite } from 'drizzle-orm/better-sqlite3'\nimport type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'\nimport { drizzle as drizzlePg } from 'drizzle-orm/node-postgres'\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres'\n\nimport * as sqliteSchema from './schema/sqlite.js'\nimport * as postgresSchema from './schema/postgres.js'\n\nexport type SqliteClient = BetterSQLite3Database<typeof sqliteSchema>\nexport type PostgresClient = NodePgDatabase<typeof postgresSchema>\n\ndeclare const readBrand: unique symbol\ndeclare const writeBrand: unique symbol\n/** A handle for reads: committed data, or the open transaction's view when one is open in the call chain. */\nexport interface ReadTx {\n readonly kind: 'sqlite' | 'postgres'\n readonly [readBrand]: true\n}\n/** A handle for writes: only `CommandStore.transaction` hands one out. */\nexport interface Tx extends ReadTx {\n readonly [writeBrand]: true\n}\n\nexport interface CommandStore {\n readonly kind: 'sqlite' | 'postgres'\n /** Runs reads. Inside an open transaction (same async call chain) it uses that transaction's Tx; outside, committed\n * data only (SQLite: it takes its turn on the queue; Postgres: a pool connection for the callback). */\n read<T>(fn: (tx: ReadTx) => Promise<T>): Promise<T>\n /** Opens a transaction, or joins the one open in the same async call chain (no new BEGIN; commits and rolls back\n * with the outermost). */\n transaction<T>(fn: (tx: Tx) => Promise<T>): Promise<T>\n /** Runs `fn` behind a savepoint in the transaction open in the same async call chain: if `fn` throws, its writes\n * (and only its writes) are undone, the error is rethrown, and the enclosing transaction carries on. With no\n * transaction open it is `transaction`. */\n savepoint<T>(fn: (tx: Tx) => Promise<T>): Promise<T>\n close(): Promise<void>\n}\n\n/** A repository over one command store. A caller handed only the repository (a projection, a sweeper) opens its\n * reads and transactions on `store`. */\nexport interface StoreRepository {\n readonly store: CommandStore\n}\n\nexport type RawClients =\n | { kind: 'sqlite'; db: SqliteClient; raw: BetterSqlite3.Database }\n | { kind: 'postgres'; db: PostgresClient; pool: pg.Pool }\n\nexport interface CommandStoreOptions {\n sqlitePath?: string\n postgresUrl?: string\n}\n\ntype Client = { kind: 'sqlite'; db: SqliteClient } | { kind: 'postgres'; db: PostgresClient }\n\n/**\n * One `read` or outermost `transaction` callback and everything it awaits. It is also the handle the callback gets as\n * its `ReadTx` or `Tx`.\n */\nclass Scope {\n settled = false\n /** The first rejection of a joined block: the outermost rolls back even if a caller swallowed it. */\n failure: { error: unknown } | undefined\n /** Sends held until the outermost commits; the same function held twice runs once. */\n readonly held = new Set<() => Promise<void>>()\n /** Savepoints opened so far, for unique names. */\n savepoints = 0\n\n constructor(\n readonly owner: object,\n readonly client: Client,\n readonly writable: boolean,\n /** Runs one SQL statement on the transaction's connection; reads have none. */\n readonly exec?: (sql: string) => Promise<void>,\n ) {}\n\n get kind(): Client['kind'] {\n return this.client.kind\n }\n}\n\nconst context = new AsyncLocalStorage<Scope>()\nconst rawByStore = new WeakMap<CommandStore, RawClients>()\n\nfunction liveScope(tx: ReadTx): Scope {\n if (!(tx instanceof Scope)) {\n throw new TypeError('expected a handle from CommandStore.read or CommandStore.transaction')\n }\n if (tx.settled) {\n throw new Error('a command-store handle was used after its read or transaction settled')\n }\n return tx\n}\n\n/** The SQLite Drizzle client behind a handle. For repositories. */\nexport function sqliteDb(tx: ReadTx): SqliteClient {\n const { client } = liveScope(tx)\n if (client.kind !== 'sqlite') throw new TypeError('expected a SQLite handle')\n return client.db\n}\n\n/** The Postgres Drizzle client behind a handle: the transaction's (or read's) own connection. For repositories. */\nexport function postgresDb(tx: ReadTx): PostgresClient {\n const { client } = liveScope(tx)\n if (client.kind !== 'postgres') throw new TypeError('expected a Postgres handle')\n return client.db\n}\n\n/**\n * Runs `send` now, or, inside an open transaction, holds it until the outermost commits; a rollback drops it. The\n * same function held more than once in one transaction runs once. The publisher drains the event relay through here,\n * after the slot or connection is released, so subscribers only see committed writes.\n */\nexport async function afterCommit(send: () => Promise<void>): Promise<void> {\n const scope = context.getStore()\n if (scope !== undefined && scope.writable && !scope.settled) {\n scope.held.add(send)\n return\n }\n await send()\n}\n\n/** For migrations, seeding and tests only; no repository or service imports it. */\nexport function rawClients(store: CommandStore): RawClients {\n const clients = rawByStore.get(store)\n if (clients === undefined) throw new TypeError('not a store from createCommandStore')\n return clients\n}\n\n/** The open scope of this store in the current async call chain, if any. */\nfunction joinable(owner: object): Scope | undefined {\n const scope = context.getStore()\n return scope !== undefined && scope.owner === owner && !scope.settled ? scope : undefined\n}\n\nasync function join<T>(scope: Scope, fn: (tx: Tx) => Promise<T>): Promise<T> {\n if (!scope.writable) {\n throw new Error(\n 'CommandStore.transaction() was called inside CommandStore.read(); open the transaction first',\n )\n }\n try {\n return await fn(scope as unknown as Tx)\n } catch (error) {\n scope.failure ??= { error }\n throw error\n }\n}\n\nasync function savepoint<T>(scope: Scope, fn: (tx: Tx) => Promise<T>): Promise<T> {\n if (!scope.writable || scope.exec === undefined) {\n throw new Error(\n 'CommandStore.savepoint() was called inside CommandStore.read(); open the transaction first',\n )\n }\n const exec = scope.exec\n const name = `nymbal_sp_${(scope.savepoints += 1)}`\n const failure = scope.failure\n const held = new Set(scope.held)\n await exec(`SAVEPOINT ${name}`)\n try {\n const result = await fn(scope as unknown as Tx)\n await exec(`RELEASE SAVEPOINT ${name}`)\n return result\n } catch (error) {\n try {\n await exec(`ROLLBACK TO SAVEPOINT ${name}`)\n await exec(`RELEASE SAVEPOINT ${name}`)\n } catch (rollbackError) {\n scope.failure ??= { error: rollbackError }\n throw new AggregateError([error, rollbackError], 'savepoint failed and so did its rollback')\n }\n // The failure recorded inside, and the sends held inside, went with the writes the rollback undid.\n scope.failure = failure\n for (const send of scope.held) if (!held.has(send)) scope.held.delete(send)\n throw error\n }\n}\n\ninterface Connection {\n client: Client\n /** One statement on the transaction's connection: savepoints. */\n exec(sql: string): Promise<void>\n begin(): Promise<void>\n /** Throws unless the transaction committed. */\n commit(): Promise<void>\n rollback(): Promise<void>\n /** `unusable`: the rollback failed, so the connection must not be reused. */\n release(unusable?: Error): void\n}\n\nasync function deliver(held: Iterable<() => Promise<void>>): Promise<void> {\n let failed: { error: unknown } | undefined\n for (const send of held) {\n try {\n await send()\n } catch (error) {\n // The writes are committed: keep delivering the rest, then report the first failure.\n failed ??= { error }\n }\n }\n if (failed !== undefined) throw failed.error\n}\n\nasync function runTransaction<T>(\n owner: object,\n connection: Connection,\n fn: (tx: Tx) => Promise<T>,\n): Promise<T> {\n const scope = new Scope(owner, connection.client, true, (sql) => connection.exec(sql))\n let result: T\n let begun = false\n let unusable: Error | undefined\n try {\n await connection.begin()\n begun = true\n try {\n result = await context.run(scope, () => fn(scope as unknown as Tx))\n } finally {\n // Once its callback has settled, nothing joins this transaction or writes through its handle.\n scope.settled = true\n }\n if (scope.failure !== undefined) throw scope.failure.error\n await connection.commit()\n } catch (error) {\n if (begun) {\n try {\n await connection.rollback()\n } catch (rollbackError) {\n unusable = rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError))\n throw new AggregateError(\n [error, rollbackError],\n 'transaction failed and so did its rollback',\n )\n }\n }\n throw error\n } finally {\n scope.settled = true\n connection.release(unusable)\n }\n // Delivered after the slot or connection is free and outside this transaction's context, so a subscriber that\n // reads or writes starts afresh instead of joining (or waiting on) the transaction that published.\n await context.exit(() => deliver(scope.held))\n return result\n}\n\nasync function runRead<T>(\n owner: object,\n client: Client,\n release: () => void,\n fn: (tx: ReadTx) => Promise<T>,\n): Promise<T> {\n const scope = new Scope(owner, client, false)\n try {\n return await context.run(scope, () => fn(scope as unknown as ReadTx))\n } finally {\n scope.settled = true\n release()\n }\n}\n\n/** One holder at a time, in arrival order. */\nfunction createQueue(): { acquire(): Promise<() => void> } {\n let tail: Promise<void> = Promise.resolve()\n return {\n async acquire() {\n const previous = tail\n let release!: () => void\n tail = new Promise<void>((resolve) => {\n release = resolve\n })\n await previous\n return release\n },\n }\n}\n\n/** How long a SQLite writer waits for another connection's write transaction: better-sqlite3's own default. */\nconst SQLITE_BUSY_WAIT_MS = 5000\n\n/**\n * `BEGIN IMMEDIATE`, waiting for another connection's write transaction between event-loop turns. The driver's busy\n * handler sleeps the thread instead, so when the holder is another command store in this process it can never reach\n * its COMMIT, and every writer after the first fails with SQLITE_BUSY once the wait runs out.\n */\nasync function beginImmediate(raw: BetterSqlite3.Database): Promise<void> {\n const deadline = Date.now() + SQLITE_BUSY_WAIT_MS\n raw.pragma('busy_timeout = 0')\n try {\n for (let pauseMs = 1; ; pauseMs = Math.min(pauseMs * 2, 20)) {\n try {\n raw.exec('BEGIN IMMEDIATE')\n return\n } catch (error) {\n if ((error as { code?: unknown }).code !== 'SQLITE_BUSY' || Date.now() >= deadline) {\n throw error\n }\n }\n await new Promise((resolve) => setTimeout(resolve, pauseMs))\n }\n } finally {\n raw.pragma(`busy_timeout = ${SQLITE_BUSY_WAIT_MS}`)\n }\n}\n\nexport function createCommandStore(\n config: NymbalConfig,\n options: CommandStoreOptions = {},\n): CommandStore {\n if (config.infrastructure.commandStore === 'sqlite') {\n const path = options.sqlitePath ?? envOptional('NYMBAL_SQLITE_PATH') ?? './nymbal.db'\n const raw = new BetterSqlite3(path)\n raw.pragma('journal_mode = WAL')\n raw.pragma('foreign_keys = ON')\n const db = drizzleSqlite(raw, { schema: sqliteSchema })\n const client: Client = { kind: 'sqlite', db }\n // One connection: a transaction holds it from BEGIN to COMMIT across awaits, so every other read and transaction\n // waits its turn here rather than interleaving its statements into the open transaction.\n const queue = createQueue()\n const owner = {}\n const store: CommandStore = {\n kind: 'sqlite',\n async read(fn) {\n const scope = joinable(owner)\n if (scope !== undefined) return fn(scope as unknown as ReadTx)\n return runRead(owner, client, await queue.acquire(), fn)\n },\n async transaction(fn) {\n const scope = joinable(owner)\n if (scope !== undefined) return join(scope, fn)\n const release = await queue.acquire()\n return runTransaction(\n owner,\n {\n client,\n async exec(sql) {\n raw.exec(sql)\n },\n begin: () => beginImmediate(raw),\n async commit() {\n raw.exec('COMMIT')\n },\n async rollback() {\n if (raw.inTransaction) raw.exec('ROLLBACK')\n },\n release,\n },\n fn,\n )\n },\n async savepoint(fn) {\n const scope = joinable(owner)\n return scope === undefined ? store.transaction(fn) : savepoint(scope, fn)\n },\n async close() {\n raw.close()\n },\n }\n rawByStore.set(store, { kind: 'sqlite', db, raw })\n return store\n }\n\n if (config.infrastructure.commandStore === 'postgres') {\n const connectionString = options.postgresUrl ?? envOptional('DATABASE_URL')\n if (!connectionString) {\n throw new ConfigError(\n 'commandStore=postgres requires DATABASE_URL to be set (or pass postgresUrl option).',\n { context: { commandStore: 'postgres' } },\n )\n }\n const pool = new pg.Pool({ connectionString })\n const db = drizzlePg(pool, { schema: postgresSchema })\n const owner = {}\n const connect = async (): Promise<{ client: Client; connection: pg.PoolClient }> => {\n const connection = await pool.connect()\n return {\n connection,\n client: { kind: 'postgres', db: drizzlePg(connection, { schema: postgresSchema }) },\n }\n }\n const store: CommandStore = {\n kind: 'postgres',\n async read(fn) {\n const scope = joinable(owner)\n if (scope !== undefined) return fn(scope as unknown as ReadTx)\n const { client, connection } = await connect()\n return runRead(owner, client, () => connection.release(), fn)\n },\n async transaction(fn) {\n const scope = joinable(owner)\n if (scope !== undefined) return join(scope, fn)\n const { client, connection } = await connect()\n return runTransaction(\n owner,\n {\n client,\n async exec(sql) {\n await connection.query(sql)\n },\n async begin() {\n await connection.query('BEGIN')\n },\n async commit() {\n // An aborted transaction answers COMMIT with ROLLBACK instead of an error.\n const result = await connection.query('COMMIT')\n if (result.command !== 'COMMIT') {\n throw new AdapterError(\n 'command_store.rolled_back',\n 'Postgres rolled the transaction back at COMMIT: a statement inside it failed',\n { context: { command: result.command } },\n )\n }\n },\n async rollback() {\n await connection.query('ROLLBACK')\n },\n release(unusable) {\n // An error destroys the connection instead of returning it to the pool.\n connection.release(unusable)\n },\n },\n fn,\n )\n },\n async savepoint(fn) {\n const scope = joinable(owner)\n return scope === undefined ? store.transaction(fn) : savepoint(scope, fn)\n },\n async close() {\n await pool.end()\n },\n }\n rawByStore.set(store, { kind: 'postgres', db, pool })\n return store\n }\n\n throw new ConfigError(`Unsupported commandStore: ${String(config.infrastructure.commandStore)}`, {\n context: { commandStore: config.infrastructure.commandStore },\n })\n}\n","import type { NymbalConfig } from '@nymbalhq/config'\nimport { ConfigError } from '@nymbalhq/types'\nimport type { DocumentStoreAdapter } from '@nymbalhq/types'\nimport { InMemoryDocumentStore } from './in-memory.js'\n\nexport function createDocumentStore(config: NymbalConfig): DocumentStoreAdapter {\n switch (config.infrastructure.documentStore) {\n case 'in-memory':\n return new InMemoryDocumentStore()\n case 'dynamodb':\n case 'firestore':\n case 'cosmosdb':\n case 'postgres-jsonb':\n throw new ConfigError(\n `documentStore=${config.infrastructure.documentStore} is planned for v1.0 and not yet implemented.`,\n { context: { documentStore: config.infrastructure.documentStore } },\n )\n default: {\n const exhaustive: never = config.infrastructure.documentStore\n throw new ConfigError(`Unknown documentStore: ${String(exhaustive)}`)\n }\n }\n}\n","import { AdapterError, ValidationError } from '@nymbalhq/types'\nimport type { DocumentStoreAdapter, PutOptions, QueryParams, QueryResult } from '@nymbalhq/types'\n\ninterface Entry {\n doc: unknown\n expiresAt: number | null\n}\n\nexport interface InMemoryDocumentStoreOptions {\n sweepIntervalMs?: number\n now?: () => number\n}\n\nexport class InMemoryDocumentStore implements DocumentStoreAdapter {\n readonly #data = new Map<string, Map<string, Entry>>()\n readonly #now: () => number\n readonly #sweepTimer: NodeJS.Timeout | null\n\n constructor(options: InMemoryDocumentStoreOptions = {}) {\n this.#now = options.now ?? Date.now\n const interval = options.sweepIntervalMs ?? 60_000\n if (interval > 0) {\n this.#sweepTimer = setInterval(() => this.#sweep(), interval)\n this.#sweepTimer.unref?.()\n } else {\n this.#sweepTimer = null\n }\n }\n\n async get<T>(collection: string, key: string): Promise<T | null> {\n const entry = this.#data.get(collection)?.get(key)\n if (!entry) return null\n if (this.#isExpired(entry)) {\n this.#data.get(collection)?.delete(key)\n return null\n }\n return entry.doc as T\n }\n\n async put<T>(\n collection: string,\n key: string,\n document: T,\n options: PutOptions = {},\n ): Promise<void> {\n const bucket = this.#getOrCreate(collection)\n if (options.conditionKey !== undefined) {\n const existing = bucket.get(key)\n if (!existing || this.#isExpired(existing)) {\n throw new AdapterError(\n 'condition-failed',\n `Condition failed on ${collection}/${key}: document does not exist`,\n { context: { collection, key, conditionKey: options.conditionKey } },\n )\n }\n const actual = (existing.doc as Record<string, unknown>)[options.conditionKey]\n if (actual !== options.conditionValue) {\n throw new AdapterError(\n 'condition-failed',\n `Condition failed on ${collection}/${key}: ${options.conditionKey} mismatch`,\n {\n context: {\n collection,\n key,\n conditionKey: options.conditionKey,\n expected: options.conditionValue,\n actual,\n },\n },\n )\n }\n }\n const expiresAt = options.ttl !== undefined ? this.#now() + options.ttl * 1000 : null\n bucket.set(key, { doc: document, expiresAt })\n }\n\n async delete(collection: string, key: string): Promise<void> {\n this.#data.get(collection)?.delete(key)\n }\n\n async query<T>(collection: string, params: QueryParams): Promise<QueryResult<T>> {\n const bucket = this.#data.get(collection)\n if (!bucket) return { items: [], nextCursor: null }\n\n const ascending = params.ascending ?? true\n const limit = params.limit ?? 50\n const decodedCursor = params.cursor ? decodeCursor(params.cursor) : null\n\n const matches: Array<{ key: string; doc: Record<string, unknown> }> = []\n for (const [key, entry] of bucket) {\n if (this.#isExpired(entry)) continue\n const doc = entry.doc as Record<string, unknown>\n const partition = params.partitionKey\n if (partition.value !== '*' && doc[partition.field] !== partition.value) continue\n if (params.sortKey) {\n const value = doc[params.sortKey.field]\n if (!sortKeyMatches(value, params.sortKey.operator, params.sortKey.value)) continue\n }\n matches.push({ key, doc })\n }\n\n if (params.orderBy) return orderedPage<T>(matches, params.orderBy, params, limit)\n\n const sortField = params.sortKey?.field\n matches.sort((a, b) => {\n const aKey = sortField ? a.doc[sortField] : a.key\n const bKey = sortField ? b.doc[sortField] : b.key\n const cmp = compare(aKey, bKey)\n return ascending ? cmp : -cmp\n })\n\n let start = 0\n if (decodedCursor) {\n const idx = matches.findIndex((m) => m.key === decodedCursor)\n start = idx >= 0 ? idx + 1 : 0\n }\n const page = matches.slice(start, start + limit)\n const nextCursor =\n start + limit < matches.length && page.length > 0\n ? encodeCursor(page[page.length - 1]!.key)\n : null\n return { items: page.map((m) => m.doc as T), nextCursor }\n }\n\n async batchGet<T>(collection: string, keys: string[]): Promise<Map<string, T>> {\n const result = new Map<string, T>()\n for (const key of keys) {\n const value = await this.get<T>(collection, key)\n if (value !== null) result.set(key, value)\n }\n return result\n }\n\n async batchPut<T>(collection: string, items: Map<string, T>): Promise<void> {\n for (const [key, doc] of items) {\n await this.put(collection, key, doc)\n }\n }\n\n async close(): Promise<void> {\n if (this.#sweepTimer) clearInterval(this.#sweepTimer)\n this.#data.clear()\n }\n\n #getOrCreate(collection: string): Map<string, Entry> {\n let bucket = this.#data.get(collection)\n if (!bucket) {\n bucket = new Map()\n this.#data.set(collection, bucket)\n }\n return bucket\n }\n\n #isExpired(entry: Entry): boolean {\n return entry.expiresAt !== null && entry.expiresAt <= this.#now()\n }\n\n #sweep(): void {\n const now = this.#now()\n for (const bucket of this.#data.values()) {\n for (const [key, entry] of bucket) {\n if (entry.expiresAt !== null && entry.expiresAt <= now) {\n bucket.delete(key)\n }\n }\n }\n }\n}\n\nfunction sortKeyMatches(\n value: unknown,\n operator: 'eq' | 'gt' | 'lt' | 'between',\n target: unknown,\n): boolean {\n switch (operator) {\n case 'eq':\n return value === target\n case 'gt':\n return compare(value, target) > 0\n case 'lt':\n return compare(value, target) < 0\n case 'between': {\n if (!Array.isArray(target) || target.length !== 2) return false\n const [low, high] = target\n return compare(value, low) >= 0 && compare(value, high) <= 0\n }\n }\n}\n\nfunction compare(a: unknown, b: unknown): number {\n if (a === b) return 0\n if (a === null || a === undefined) return -1\n if (b === null || b === undefined) return 1\n if (typeof a === 'number' && typeof b === 'number') return a - b\n return String(a) < String(b) ? -1 : 1\n}\n\ntype OrderBy = NonNullable<QueryParams['orderBy']>\n\ninterface Position {\n key: string\n value: unknown\n}\n\nfunction orderedPage<T>(\n matches: Array<{ key: string; doc: Record<string, unknown> }>,\n orderBy: OrderBy,\n params: QueryParams,\n limit: number,\n): QueryResult<T> {\n // The cursor names the order and partition it was issued under, so a cursor reused elsewhere is refused instead of\n // silently paging a different list.\n const order = JSON.stringify([\n orderBy.field,\n orderBy.direction,\n orderBy.nulls ?? null,\n params.partitionKey,\n ])\n const positions = matches.map((m) => ({\n position: { key: m.key, value: valueAt(m.doc, orderBy.field) },\n doc: m.doc,\n }))\n positions.sort((a, b) => compareOrdered(a.position, b.position, orderBy))\n\n let start = 0\n if (params.cursor) {\n const after = decodeOrderedCursor(params.cursor, order)\n // Seek by value, not by finding the key again, so a document deleted between pages does not restart the walk.\n const idx = positions.findIndex((p) => compareOrdered(p.position, after, orderBy) > 0)\n start = idx >= 0 ? idx : positions.length\n }\n const page = positions.slice(start, start + limit)\n const last = page[page.length - 1]\n const nextCursor =\n start + limit < positions.length && last !== undefined\n ? Buffer.from(\n JSON.stringify({ o: order, k: last.position.key, v: last.position.value }),\n 'utf8',\n ).toString('base64url')\n : null\n return { items: page.map((p) => p.doc as T), nextCursor }\n}\n\nfunction decodeOrderedCursor(cursor: string, order: string): Position {\n let decoded: unknown\n try {\n decoded = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'))\n } catch {\n decoded = null\n }\n const c = decoded as { o?: unknown; k?: unknown; v?: unknown } | null\n if (c === null || typeof c !== 'object' || typeof c.k !== 'string' || !('v' in c)) {\n throw new ValidationError('The cursor is not valid', { context: { cursor } })\n }\n if (c.o !== order) {\n throw new ValidationError('The cursor was issued under another order', { context: { cursor } })\n }\n return { key: c.k, value: c.v }\n}\n\nfunction valueAt(doc: Record<string, unknown>, path: string): unknown {\n let value: unknown = doc\n for (const part of path.split('.')) {\n if (value === null || typeof value !== 'object') return null\n value = (value as Record<string, unknown>)[part]\n }\n return value ?? null\n}\n\nconst collator = new Intl.Collator(undefined, { sensitivity: 'base' })\n\n/** Strings compare by locale at base sensitivity (case and accents tie), then by key, so the order is total. */\nfunction compareOrdered(a: Position, b: Position, orderBy: OrderBy): number {\n const aNull = a.value === null\n const bNull = b.value === null\n let c = 0\n if (orderBy.nulls === 'last' && aNull !== bNull) return aNull ? 1 : -1\n if (typeof a.value === 'string' && typeof b.value === 'string')\n c = collator.compare(a.value, b.value)\n else c = compare(a.value, b.value)\n if (orderBy.direction === 'desc') c = -c\n if (c !== 0) return c\n return a.key < b.key ? -1 : a.key > b.key ? 1 : 0\n}\n\nfunction encodeCursor(key: string): string {\n return Buffer.from(key, 'utf8').toString('base64url')\n}\n\nfunction decodeCursor(cursor: string): string {\n return Buffer.from(cursor, 'base64url').toString('utf8')\n}\n","import type { NymbalConfig } from '@nymbalhq/config'\nimport { ConfigError } from '@nymbalhq/types'\nimport type { EventBusAdapter, Logger } from '@nymbalhq/types'\nimport { InProcessEventBus } from './in-process.js'\n\nexport function createEventBus(config: NymbalConfig, logger?: Logger): EventBusAdapter {\n switch (config.infrastructure.eventBus) {\n case 'in-process':\n return new InProcessEventBus(logger ? { logger } : {})\n case 'eventbridge':\n case 'pubsub':\n case 'service-bus':\n case 'redis-streams':\n throw new ConfigError(\n `eventBus=${config.infrastructure.eventBus} is planned for v1.0 and not yet implemented.`,\n { context: { eventBus: config.infrastructure.eventBus } },\n )\n default: {\n const exhaustive: never = config.infrastructure.eventBus\n throw new ConfigError(`Unknown eventBus: ${String(exhaustive)}`)\n }\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport type {\n EventBusAdapter,\n EventHandler,\n NymbalEvent,\n Subscription,\n SubscriptionConfig,\n Logger,\n} from '@nymbalhq/types'\nimport { ValidationError } from '@nymbalhq/types'\n\ninterface Registration {\n id: string\n patterns: string[]\n regexes: RegExp[]\n handler: EventHandler\n config: SubscriptionConfig | undefined\n}\n\nexport interface InProcessEventBusOptions {\n logger?: Logger\n}\n\nexport class InProcessEventBus implements EventBusAdapter {\n readonly #registrations = new Map<string, Registration>()\n readonly #logger: Logger | undefined\n\n constructor(options: InProcessEventBusOptions = {}) {\n this.#logger = options.logger\n }\n\n async publish<T>(event: NymbalEvent<T>): Promise<void> {\n await this.#deliver(event, () => true)\n }\n\n async publishBatch(events: NymbalEvent<unknown>[]): Promise<void> {\n for (const event of events) {\n await this.publish(event)\n }\n }\n\n async replay(events: NymbalEvent<unknown>[]): Promise<void> {\n for (const event of events) {\n await this.#deliver(event, (r) => r.config?.derived === true)\n }\n }\n\n async #deliver<T>(event: NymbalEvent<T>, eligible: (r: Registration) => boolean): Promise<void> {\n this.#validate(event)\n const matches = Array.from(this.#registrations.values()).filter(\n (r) => eligible(r) && r.regexes.some((re) => re.test(event.type)),\n )\n await Promise.all(\n matches.map(async (r) => {\n try {\n await r.handler(event)\n } catch (err) {\n this.#logger?.error(\n { err, subscriptionId: r.id, eventType: event.type, eventId: event.id },\n 'Event handler failed',\n )\n }\n }),\n )\n }\n\n async subscribe(\n eventPattern: string | string[],\n handler: EventHandler,\n config?: SubscriptionConfig,\n ): Promise<Subscription> {\n const patterns = Array.isArray(eventPattern) ? eventPattern : [eventPattern]\n const regexes = patterns.map(compilePattern)\n const id = uuidv7()\n const registration: Registration = { id, patterns, regexes, handler, config }\n this.#registrations.set(id, registration)\n const self = this\n return {\n id,\n patterns,\n async unsubscribe() {\n self.#registrations.delete(id)\n },\n }\n }\n\n async unsubscribe(subscription: Subscription): Promise<void> {\n this.#registrations.delete(subscription.id)\n }\n\n async close(): Promise<void> {\n this.#registrations.clear()\n }\n\n #validate(event: NymbalEvent<unknown>): void {\n if (!event.id || !event.type || !event.timestamp || !event.source) {\n throw new ValidationError('Event is missing required envelope fields', {\n context: { event },\n })\n }\n if (!event.metadata || !event.metadata.storeId || !event.metadata.environment) {\n throw new ValidationError('Event metadata is missing required fields', {\n context: { event },\n })\n }\n }\n}\n\nfunction compilePattern(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\*]/g, '\\\\$&').replace(/\\\\\\*/g, '.*')\n return new RegExp(`^${escaped}$`)\n}\n","import { pino, type Logger as PinoLogger } from 'pino'\nimport type { Logger } from '@nymbalhq/types'\n\nexport interface CreateLoggerOptions {\n level?: string\n pretty?: boolean\n base?: Record<string, unknown>\n}\n\nexport function createLogger(options: CreateLoggerOptions = {}): Logger {\n const isProduction = process.env.NODE_ENV === 'production'\n const pretty = options.pretty ?? !isProduction\n const logger = pino({\n level: options.level ?? process.env.LOG_LEVEL ?? (isProduction ? 'info' : 'debug'),\n base: options.base ?? {},\n ...(pretty && {\n transport: {\n target: 'pino-pretty',\n options: { colorize: true, translateTime: 'HH:MM:ss.l', ignore: 'pid,hostname' },\n },\n }),\n })\n return wrap(logger)\n}\n\nfunction wrap(p: PinoLogger): Logger {\n return {\n trace: (obj, msg) => p.trace(obj as object, msg),\n debug: (obj, msg) => p.debug(obj as object, msg),\n info: (obj, msg) => p.info(obj as object, msg),\n warn: (obj, msg) => p.warn(obj as object, msg),\n error: (obj, msg) => p.error(obj as object, msg),\n child: (bindings) => wrap(p.child(bindings)),\n }\n}\n","import type { NymbalConfig } from '@nymbalhq/config'\nimport type { DocumentStoreAdapter, EventBusAdapter, Logger } from '@nymbalhq/types'\nimport { createCommandStore, type CommandStore } from './db/command-store.js'\nimport { createDocumentStore } from './document-store/factory.js'\nimport { createEventBus } from './event-bus/factory.js'\nimport { createLogger } from './logger.js'\n\nexport interface Platform {\n config: NymbalConfig\n commandStore: CommandStore\n documentStore: DocumentStoreAdapter\n eventBus: EventBusAdapter\n logger: Logger\n close(): Promise<void>\n}\n\nexport interface CreatePlatformOptions {\n logger?: Logger\n sqlitePath?: string\n postgresUrl?: string\n}\n\nexport function createPlatform(\n config: NymbalConfig,\n options: CreatePlatformOptions = {},\n): Platform {\n const logger =\n options.logger ??\n createLogger({\n base: { store: config.store.name },\n })\n const commandStore = createCommandStore(config, {\n ...(options.sqlitePath !== undefined && { sqlitePath: options.sqlitePath }),\n ...(options.postgresUrl !== undefined && { postgresUrl: options.postgresUrl }),\n })\n const documentStore = createDocumentStore(config)\n const eventBus = createEventBus(config, logger)\n return {\n config,\n commandStore,\n documentStore,\n eventBus,\n logger,\n async close() {\n await commandStore.close()\n await documentStore.close()\n await eventBus.close()\n },\n }\n}\n","import { resolve } from 'node:path'\nimport { migrate as migrateSqlite } from 'drizzle-orm/better-sqlite3/migrator'\nimport { migrate as migratePostgres } from 'drizzle-orm/node-postgres/migrator'\nimport { rawClients, type CommandStore } from './command-store.js'\n\nexport interface MigrateOptions {\n migrationsRoot?: string\n}\n\nexport async function runMigrations(\n store: CommandStore,\n options: MigrateOptions = {},\n): Promise<void> {\n const root = options.migrationsRoot ?? resolve(process.cwd(), 'migrations')\n const clients = rawClients(store)\n if (clients.kind === 'sqlite') {\n migrateSqlite(clients.db, { migrationsFolder: resolve(root, 'sqlite') })\n } else {\n await migratePostgres(clients.db, { migrationsFolder: resolve(root, 'postgres') })\n }\n}\n","import { eq } from 'drizzle-orm'\nimport { rawClients, type CommandStore } from '../command-store.js'\nimport * as sqliteSchema from '../schema/sqlite.js'\nimport * as postgresSchema from '../schema/postgres.js'\n\nexport interface ProductInsert {\n id: string\n slug: string\n name: string\n description: string\n shortDescription?: string\n status?: 'draft' | 'active' | 'archived'\n type?: 'simple' | 'variable'\n seoTitle?: string\n seoDescription?: string\n media?: unknown[]\n metadata?: Record<string, unknown>\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface ProductRow {\n id: string\n slug: string\n name: string\n description: string\n shortDescription: string\n status: 'draft' | 'active' | 'archived'\n type: 'simple' | 'variable'\n seoTitle: string\n seoDescription: string\n media: unknown[]\n metadata: Record<string, unknown>\n createdAt: Date | string\n updatedAt: Date | string\n}\n\nfunction parseJson<T>(value: unknown, fallback: T): T {\n if (typeof value === 'string') {\n try {\n return JSON.parse(value) as T\n } catch {\n return fallback\n }\n }\n return (value ?? fallback) as T\n}\n\nfunction rowToDomain(row: Record<string, unknown>): ProductRow {\n return {\n id: String(row.id),\n slug: String(row.slug),\n name: String(row.name),\n description: String(row.description ?? ''),\n shortDescription: String(row.shortDescription ?? ''),\n status: row.status as 'draft' | 'active' | 'archived',\n type: row.type as 'simple' | 'variable',\n seoTitle: String(row.seoTitle ?? ''),\n seoDescription: String(row.seoDescription ?? ''),\n media: parseJson(row.media, [] as unknown[]),\n metadata: parseJson(row.metadata, {} as Record<string, unknown>),\n createdAt: row.createdAt as Date | string,\n updatedAt: row.updatedAt as Date | string,\n }\n}\n\nexport function createProductRepository(store: CommandStore) {\n const clients = rawClients(store)\n return {\n async findAll(): Promise<ProductRow[]> {\n if (clients.kind === 'sqlite') {\n const rows = clients.db.select().from(sqliteSchema.products).all()\n return rows.map((r) => rowToDomain(r as Record<string, unknown>))\n }\n const rows = await clients.db.select().from(postgresSchema.products)\n return rows.map((r) => rowToDomain(r as Record<string, unknown>))\n },\n\n async findBySlug(slug: string): Promise<ProductRow | null> {\n if (clients.kind === 'sqlite') {\n const row = clients.db\n .select()\n .from(sqliteSchema.products)\n .where(eq(sqliteSchema.products.slug, slug))\n .get()\n return row ? rowToDomain(row as Record<string, unknown>) : null\n }\n const [row] = await clients.db\n .select()\n .from(postgresSchema.products)\n .where(eq(postgresSchema.products.slug, slug))\n return row ? rowToDomain(row as Record<string, unknown>) : null\n },\n\n async insertMany(items: ProductInsert[]): Promise<void> {\n if (items.length === 0) return\n if (clients.kind === 'sqlite') {\n const rows = items.map((item) => ({\n id: item.id,\n slug: item.slug,\n name: item.name,\n description: item.description,\n shortDescription: item.shortDescription ?? '',\n status: item.status ?? 'active',\n type: item.type ?? 'simple',\n seoTitle: item.seoTitle ?? '',\n seoDescription: item.seoDescription ?? '',\n media: JSON.stringify(item.media ?? []),\n metadata: JSON.stringify(item.metadata ?? {}),\n createdAt: item.createdAt.toISOString(),\n updatedAt: item.updatedAt.toISOString(),\n }))\n clients.db.insert(sqliteSchema.products).values(rows).run()\n return\n }\n const rows = items.map((item) => ({\n id: item.id,\n slug: item.slug,\n name: item.name,\n description: item.description,\n shortDescription: item.shortDescription ?? '',\n status: item.status ?? 'active',\n type: item.type ?? 'simple',\n seoTitle: item.seoTitle ?? '',\n seoDescription: item.seoDescription ?? '',\n media: item.media ?? [],\n metadata: item.metadata ?? {},\n createdAt: item.createdAt,\n updatedAt: item.updatedAt,\n }))\n await clients.db.insert(postgresSchema.products).values(rows)\n },\n }\n}\n","import { rawClients, type CommandStore } from '../command-store.js'\nimport * as sqliteSchema from '../schema/sqlite.js'\nimport * as postgresSchema from '../schema/postgres.js'\n\nexport interface CategoryInsert {\n id: string\n parentId?: string | null\n slug: string\n name: string\n description: string\n position?: number\n createdAt: Date\n}\n\nexport interface CategoryRow {\n id: string\n parentId: string | null\n slug: string\n name: string\n description: string\n position: number\n createdAt: Date | string\n}\n\nexport function createCategoryRepository(store: CommandStore) {\n const clients = rawClients(store)\n return {\n async findAll(): Promise<CategoryRow[]> {\n if (clients.kind === 'sqlite') {\n const rows = clients.db.select().from(sqliteSchema.categories).all()\n return rows as CategoryRow[]\n }\n const rows = await clients.db.select().from(postgresSchema.categories)\n return rows as CategoryRow[]\n },\n\n async insertMany(items: CategoryInsert[]): Promise<void> {\n if (items.length === 0) return\n if (clients.kind === 'sqlite') {\n const rows = items.map((item) => ({\n id: item.id,\n parentId: item.parentId ?? null,\n slug: item.slug,\n name: item.name,\n description: item.description,\n position: item.position ?? 0,\n createdAt: item.createdAt.toISOString(),\n }))\n clients.db.insert(sqliteSchema.categories).values(rows).run()\n return\n }\n const rows = items.map((item) => ({\n id: item.id,\n parentId: item.parentId ?? null,\n slug: item.slug,\n name: item.name,\n description: item.description,\n position: item.position ?? 0,\n createdAt: item.createdAt,\n }))\n await clients.db.insert(postgresSchema.categories).values(rows)\n },\n }\n}\n","import { eq } from 'drizzle-orm'\nimport type { Product, ProductStatus, ProductType, ProductMedia } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { parseJson, serialiseJson, fromTimestamp } from './json.js'\n\nexport interface ProductInsert {\n id: string\n slug: string\n name: string\n description?: string\n shortDescription?: string\n status?: ProductStatus\n type?: ProductType\n seoTitle?: string\n seoDescription?: string\n media?: ProductMedia[]\n metadata?: Record<string, unknown>\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface ProductUpdate {\n name?: string\n description?: string\n shortDescription?: string\n status?: ProductStatus\n type?: ProductType\n seoTitle?: string\n seoDescription?: string\n media?: ProductMedia[]\n metadata?: Record<string, unknown>\n updatedAt: Date\n}\n\nfunction rowToProduct(store: CommandStore['kind'], row: Record<string, unknown>): Product {\n return {\n id: String(row.id),\n slug: String(row.slug),\n name: String(row.name),\n description: String(row.description ?? ''),\n shortDescription: String(row.shortDescription ?? ''),\n status: row.status as ProductStatus,\n type: row.type as ProductType,\n seoTitle: String(row.seoTitle ?? ''),\n seoDescription: String(row.seoDescription ?? ''),\n media: parseJson<ProductMedia[]>(store, row.media, []),\n metadata: parseJson<Record<string, unknown>>(store, row.metadata, {}),\n createdAt: fromTimestamp(row.createdAt),\n updatedAt: fromTimestamp(row.updatedAt),\n }\n}\n\nexport interface ProductRepository extends StoreRepository {\n findById(tx: ReadTx, id: string): Promise<Product | null>\n findBySlug(tx: ReadTx, slug: string): Promise<Product | null>\n list(\n tx: ReadTx,\n opts?: { status?: ProductStatus; limit?: number; offset?: number },\n ): Promise<Product[]>\n insert(tx: Tx, p: ProductInsert): Promise<void>\n update(tx: Tx, id: string, patch: ProductUpdate): Promise<void>\n delete(tx: Tx, id: string): Promise<void>\n setStatus(tx: Tx, id: string, status: ProductStatus, updatedAt: Date): Promise<void>\n}\n\nexport function createProductRepository(store: CommandStore): ProductRepository {\n async function _find(tx: ReadTx, column: 'id' | 'slug', value: string): Promise<Product | null> {\n if (tx.kind === 'sqlite') {\n const col = column === 'id' ? sqliteSchema.products.id : sqliteSchema.products.slug\n const row = sqliteDb(tx).select().from(sqliteSchema.products).where(eq(col, value)).get()\n return row ? rowToProduct(tx.kind, row as Record<string, unknown>) : null\n }\n const col = column === 'id' ? postgresSchema.products.id : postgresSchema.products.slug\n const [row] = await postgresDb(tx).select().from(postgresSchema.products).where(eq(col, value))\n return row ? rowToProduct(tx.kind, row as Record<string, unknown>) : null\n }\n\n return {\n store,\n async findById(tx, id) {\n return _find(tx, 'id', id)\n },\n async findBySlug(tx, slug) {\n return _find(tx, 'slug', slug)\n },\n async list(tx, opts = {}) {\n const limit = opts.limit ?? 100\n const offset = opts.offset ?? 0\n if (tx.kind === 'sqlite') {\n const base = sqliteDb(tx).select().from(sqliteSchema.products)\n const filtered = opts.status\n ? base.where(eq(sqliteSchema.products.status, opts.status))\n : base\n const rows = filtered.limit(limit).offset(offset).all()\n return rows.map((r) => rowToProduct('sqlite', r as Record<string, unknown>))\n }\n const base = postgresDb(tx).select().from(postgresSchema.products)\n const filtered = opts.status\n ? base.where(eq(postgresSchema.products.status, opts.status))\n : base\n const rows = await filtered.limit(limit).offset(offset)\n return rows.map((r) => rowToProduct('postgres', r as Record<string, unknown>))\n },\n async insert(tx, p) {\n const common = {\n id: p.id,\n slug: p.slug,\n name: p.name,\n description: p.description ?? '',\n shortDescription: p.shortDescription ?? '',\n status: p.status ?? 'draft',\n type: p.type ?? 'simple',\n seoTitle: p.seoTitle ?? '',\n seoDescription: p.seoDescription ?? '',\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.products)\n .values({\n ...common,\n media: serialiseJson('sqlite', p.media ?? []) as string,\n metadata: serialiseJson('sqlite', p.metadata ?? {}) as string,\n createdAt: p.createdAt.toISOString(),\n updatedAt: p.updatedAt.toISOString(),\n })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.products)\n .values({\n ...common,\n media: p.media ?? [],\n metadata: p.metadata ?? {},\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n })\n },\n async update(tx, id, patch) {\n const pg: Record<string, unknown> = { updatedAt: patch.updatedAt }\n const sq: Record<string, unknown> = { updatedAt: patch.updatedAt.toISOString() }\n if (patch.name !== undefined) {\n pg.name = patch.name\n sq.name = patch.name\n }\n if (patch.description !== undefined) {\n pg.description = patch.description\n sq.description = patch.description\n }\n if (patch.shortDescription !== undefined) {\n pg.shortDescription = patch.shortDescription\n sq.shortDescription = patch.shortDescription\n }\n if (patch.status !== undefined) {\n pg.status = patch.status\n sq.status = patch.status\n }\n if (patch.type !== undefined) {\n pg.type = patch.type\n sq.type = patch.type\n }\n if (patch.seoTitle !== undefined) {\n pg.seoTitle = patch.seoTitle\n sq.seoTitle = patch.seoTitle\n }\n if (patch.seoDescription !== undefined) {\n pg.seoDescription = patch.seoDescription\n sq.seoDescription = patch.seoDescription\n }\n if (patch.media !== undefined) {\n pg.media = patch.media\n sq.media = JSON.stringify(patch.media)\n }\n if (patch.metadata !== undefined) {\n pg.metadata = patch.metadata\n sq.metadata = JSON.stringify(patch.metadata)\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.products)\n .set(sq)\n .where(eq(sqliteSchema.products.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.products)\n .set(pg)\n .where(eq(postgresSchema.products.id, id))\n },\n async delete(tx, id) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx).delete(sqliteSchema.products).where(eq(sqliteSchema.products.id, id)).run()\n return\n }\n await postgresDb(tx).delete(postgresSchema.products).where(eq(postgresSchema.products.id, id))\n },\n async setStatus(tx, id, status, updatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.products)\n .set({ status, updatedAt: updatedAt.toISOString() })\n .where(eq(sqliteSchema.products.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.products)\n .set({ status, updatedAt })\n .where(eq(postgresSchema.products.id, id))\n },\n }\n}\n","export function serialiseJson(store: 'sqlite' | 'postgres', value: unknown): unknown {\n if (store === 'sqlite') {\n return JSON.stringify(value)\n }\n return value\n}\n\nexport function parseJson<T>(store: 'sqlite' | 'postgres', value: unknown, fallback: T): T {\n if (store === 'sqlite' && typeof value === 'string') {\n try {\n return JSON.parse(value) as T\n } catch {\n return fallback\n }\n }\n return (value ?? fallback) as T\n}\n\nexport function toIso(store: 'sqlite' | 'postgres', d: Date): Date | string {\n return store === 'sqlite' ? d.toISOString() : d\n}\n\nexport function fromTimestamp(value: unknown): string {\n if (value instanceof Date) return value.toISOString()\n return String(value)\n}\n","import { and, eq, gte, sql } from 'drizzle-orm'\nimport type { Variant, VariantOption, VariantStatus, VariantDimensions } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { parseJson, fromTimestamp } from './json.js'\n\nexport interface VariantInsert {\n id: string\n productId: string\n sku: string\n name: string\n priceMinor: number\n compareAtPriceMinor?: number | null\n weightGrams?: number | null\n dimensions?: VariantDimensions | null\n stock: number\n lowStockThreshold?: number\n options: VariantOption[]\n status?: VariantStatus\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface VariantUpdate {\n name?: string\n priceMinor?: number\n compareAtPriceMinor?: number | null\n weightGrams?: number | null\n dimensions?: VariantDimensions | null\n lowStockThreshold?: number\n options?: VariantOption[]\n status?: VariantStatus\n updatedAt: Date\n}\n\nfunction rowToVariant(store: CommandStore['kind'], row: Record<string, unknown>): Variant {\n return {\n id: String(row.id),\n productId: String(row.productId),\n sku: String(row.sku),\n name: String(row.name ?? ''),\n priceMinor: Number(row.priceMinor),\n compareAtPriceMinor: row.compareAtPriceMinor == null ? null : Number(row.compareAtPriceMinor),\n weightGrams: row.weightGrams == null ? null : Number(row.weightGrams),\n dimensions: parseJson<VariantDimensions | null>(store, row.dimensions, null),\n stock: Number(row.stock),\n lowStockThreshold: Number(row.lowStockThreshold ?? 0),\n options: parseJson<VariantOption[]>(store, row.options, []),\n status: row.status as VariantStatus,\n createdAt: fromTimestamp(row.createdAt),\n updatedAt: fromTimestamp(row.updatedAt),\n }\n}\n\nexport interface VariantRepository extends StoreRepository {\n findById(tx: ReadTx, id: string): Promise<Variant | null>\n findBySku(tx: ReadTx, sku: string): Promise<Variant | null>\n findByProduct(tx: ReadTx, productId: string): Promise<Variant[]>\n insert(tx: Tx, v: VariantInsert): Promise<void>\n update(tx: Tx, id: string, patch: VariantUpdate): Promise<void>\n /** One conditional UPDATE: the new stock, or null when the variant is missing or holds fewer than `qty`. */\n decrementStock(tx: Tx, id: string, qty: number, at: Date): Promise<number | null>\n /** The new stock, or null when there is no such variant. */\n incrementStock(tx: Tx, id: string, qty: number, at: Date): Promise<number | null>\n delete(tx: Tx, id: string): Promise<void>\n}\n\nexport function createVariantRepository(store: CommandStore): VariantRepository {\n return {\n store,\n async findById(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.variants)\n .where(eq(sqliteSchema.variants.id, id))\n .get()\n return row ? rowToVariant('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.variants)\n .where(eq(postgresSchema.variants.id, id))\n return row ? rowToVariant('postgres', row as Record<string, unknown>) : null\n },\n async findBySku(tx, sku) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.variants)\n .where(eq(sqliteSchema.variants.sku, sku))\n .get()\n return row ? rowToVariant('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.variants)\n .where(eq(postgresSchema.variants.sku, sku))\n return row ? rowToVariant('postgres', row as Record<string, unknown>) : null\n },\n async findByProduct(tx, productId) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.variants)\n .where(eq(sqliteSchema.variants.productId, productId))\n .all()\n return rows.map((r) => rowToVariant('sqlite', r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.variants)\n .where(eq(postgresSchema.variants.productId, productId))\n return rows.map((r) => rowToVariant('postgres', r as Record<string, unknown>))\n },\n async insert(tx, v) {\n const common = {\n id: v.id,\n productId: v.productId,\n sku: v.sku,\n name: v.name,\n priceMinor: v.priceMinor,\n compareAtPriceMinor: v.compareAtPriceMinor ?? null,\n weightGrams: v.weightGrams ?? null,\n stock: v.stock,\n lowStockThreshold: v.lowStockThreshold ?? 0,\n status: v.status ?? 'active',\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.variants)\n .values({\n ...common,\n dimensions: v.dimensions ? JSON.stringify(v.dimensions) : null,\n options: JSON.stringify(v.options),\n createdAt: v.createdAt.toISOString(),\n updatedAt: v.updatedAt.toISOString(),\n })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.variants)\n .values({\n ...common,\n dimensions: v.dimensions ?? null,\n options: v.options,\n createdAt: v.createdAt,\n updatedAt: v.updatedAt,\n })\n },\n async update(tx, id, patch) {\n const pg: Record<string, unknown> = { updatedAt: patch.updatedAt }\n const sq: Record<string, unknown> = { updatedAt: patch.updatedAt.toISOString() }\n for (const k of [\n 'name',\n 'priceMinor',\n 'compareAtPriceMinor',\n 'weightGrams',\n 'lowStockThreshold',\n 'status',\n ] as const) {\n if (patch[k] !== undefined) {\n pg[k] = patch[k]\n sq[k] = patch[k]\n }\n }\n if (patch.dimensions !== undefined) {\n pg.dimensions = patch.dimensions ?? null\n sq.dimensions = patch.dimensions ? JSON.stringify(patch.dimensions) : null\n }\n if (patch.options !== undefined) {\n pg.options = patch.options\n sq.options = JSON.stringify(patch.options)\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.variants)\n .set(sq)\n .where(eq(sqliteSchema.variants.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.variants)\n .set(pg)\n .where(eq(postgresSchema.variants.id, id))\n },\n async decrementStock(tx, id, qty, at) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .update(sqliteSchema.variants)\n .set({ stock: sql`${sqliteSchema.variants.stock} - ${qty}`, updatedAt: at.toISOString() })\n .where(and(eq(sqliteSchema.variants.id, id), gte(sqliteSchema.variants.stock, qty)))\n .returning({ stock: sqliteSchema.variants.stock })\n .get()\n return row ? Number(row.stock) : null\n }\n const [row] = await postgresDb(tx)\n .update(postgresSchema.variants)\n .set({ stock: sql`${postgresSchema.variants.stock} - ${qty}`, updatedAt: at })\n .where(and(eq(postgresSchema.variants.id, id), gte(postgresSchema.variants.stock, qty)))\n .returning({ stock: postgresSchema.variants.stock })\n return row ? Number(row.stock) : null\n },\n async incrementStock(tx, id, qty, at) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .update(sqliteSchema.variants)\n .set({ stock: sql`${sqliteSchema.variants.stock} + ${qty}`, updatedAt: at.toISOString() })\n .where(eq(sqliteSchema.variants.id, id))\n .returning({ stock: sqliteSchema.variants.stock })\n .get()\n return row ? Number(row.stock) : null\n }\n const [row] = await postgresDb(tx)\n .update(postgresSchema.variants)\n .set({ stock: sql`${postgresSchema.variants.stock} + ${qty}`, updatedAt: at })\n .where(eq(postgresSchema.variants.id, id))\n .returning({ stock: postgresSchema.variants.stock })\n return row ? Number(row.stock) : null\n },\n async delete(tx, id) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx).delete(sqliteSchema.variants).where(eq(sqliteSchema.variants.id, id)).run()\n return\n }\n await postgresDb(tx).delete(postgresSchema.variants).where(eq(postgresSchema.variants.id, id))\n },\n }\n}\n","import { eq } from 'drizzle-orm'\nimport type { Category } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface CategoryInsert {\n id: string\n parentId?: string | null\n slug: string\n name: string\n description?: string\n position?: number\n createdAt: Date\n}\n\nexport interface CategoryUpdate {\n parentId?: string | null\n name?: string\n description?: string\n position?: number\n}\n\nfunction rowToCategory(row: Record<string, unknown>): Category {\n return {\n id: String(row.id),\n parentId: (row.parentId as string | null) ?? null,\n slug: String(row.slug),\n name: String(row.name),\n description: String(row.description ?? ''),\n position: Number(row.position ?? 0),\n createdAt: fromTimestamp(row.createdAt),\n }\n}\n\nexport interface CategoryRepository extends StoreRepository {\n findById(tx: ReadTx, id: string): Promise<Category | null>\n findBySlug(tx: ReadTx, slug: string): Promise<Category | null>\n list(tx: ReadTx): Promise<Category[]>\n insert(tx: Tx, c: CategoryInsert): Promise<void>\n update(tx: Tx, id: string, patch: CategoryUpdate): Promise<void>\n delete(tx: Tx, id: string): Promise<void>\n}\n\nexport function createCategoryRepository(store: CommandStore): CategoryRepository {\n return {\n store,\n async findById(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.categories)\n .where(eq(sqliteSchema.categories.id, id))\n .get()\n return row ? rowToCategory(row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.categories)\n .where(eq(postgresSchema.categories.id, id))\n return row ? rowToCategory(row as Record<string, unknown>) : null\n },\n async findBySlug(tx, slug) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.categories)\n .where(eq(sqliteSchema.categories.slug, slug))\n .get()\n return row ? rowToCategory(row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.categories)\n .where(eq(postgresSchema.categories.slug, slug))\n return row ? rowToCategory(row as Record<string, unknown>) : null\n },\n async list(tx) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx).select().from(sqliteSchema.categories).all()\n return rows.map((r) => rowToCategory(r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx).select().from(postgresSchema.categories)\n return rows.map((r) => rowToCategory(r as Record<string, unknown>))\n },\n async insert(tx, c) {\n const common = {\n id: c.id,\n parentId: c.parentId ?? null,\n slug: c.slug,\n name: c.name,\n description: c.description ?? '',\n position: c.position ?? 0,\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.categories)\n .values({ ...common, createdAt: c.createdAt.toISOString() })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.categories)\n .values({ ...common, createdAt: c.createdAt })\n },\n async update(tx, id, patch) {\n const set: Record<string, unknown> = {}\n if (patch.parentId !== undefined) set.parentId = patch.parentId\n if (patch.name !== undefined) set.name = patch.name\n if (patch.description !== undefined) set.description = patch.description\n if (patch.position !== undefined) set.position = patch.position\n if (Object.keys(set).length === 0) return\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.categories)\n .set(set)\n .where(eq(sqliteSchema.categories.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.categories)\n .set(set)\n .where(eq(postgresSchema.categories.id, id))\n },\n async delete(tx, id) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx).delete(sqliteSchema.categories).where(eq(sqliteSchema.categories.id, id)).run()\n return\n }\n await postgresDb(tx)\n .delete(postgresSchema.categories)\n .where(eq(postgresSchema.categories.id, id))\n },\n }\n}\n","import { and, eq } from 'drizzle-orm'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\n\nexport interface ProductCategoryRepository extends StoreRepository {\n attach(tx: Tx, productId: string, categoryId: string): Promise<void>\n detach(tx: Tx, productId: string, categoryId: string): Promise<void>\n detachAllForProduct(tx: Tx, productId: string): Promise<void>\n listCategoriesForProduct(tx: ReadTx, productId: string): Promise<string[]>\n listProductsForCategory(tx: ReadTx, categoryId: string): Promise<string[]>\n}\n\nexport function createProductCategoryRepository(store: CommandStore): ProductCategoryRepository {\n return {\n store,\n async attach(tx, productId, categoryId) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.productCategories)\n .values({ productId, categoryId })\n .onConflictDoNothing()\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.productCategories)\n .values({ productId, categoryId })\n .onConflictDoNothing()\n },\n async detach(tx, productId, categoryId) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .delete(sqliteSchema.productCategories)\n .where(\n and(\n eq(sqliteSchema.productCategories.productId, productId),\n eq(sqliteSchema.productCategories.categoryId, categoryId),\n ),\n )\n .run()\n return\n }\n await postgresDb(tx)\n .delete(postgresSchema.productCategories)\n .where(\n and(\n eq(postgresSchema.productCategories.productId, productId),\n eq(postgresSchema.productCategories.categoryId, categoryId),\n ),\n )\n },\n async detachAllForProduct(tx, productId) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .delete(sqliteSchema.productCategories)\n .where(eq(sqliteSchema.productCategories.productId, productId))\n .run()\n return\n }\n await postgresDb(tx)\n .delete(postgresSchema.productCategories)\n .where(eq(postgresSchema.productCategories.productId, productId))\n },\n async listCategoriesForProduct(tx, productId) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select({ categoryId: sqliteSchema.productCategories.categoryId })\n .from(sqliteSchema.productCategories)\n .where(eq(sqliteSchema.productCategories.productId, productId))\n .all()\n return rows.map((r) => r.categoryId)\n }\n const rows = await postgresDb(tx)\n .select({ categoryId: postgresSchema.productCategories.categoryId })\n .from(postgresSchema.productCategories)\n .where(eq(postgresSchema.productCategories.productId, productId))\n return rows.map((r) => r.categoryId)\n },\n async listProductsForCategory(tx, categoryId) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select({ productId: sqliteSchema.productCategories.productId })\n .from(sqliteSchema.productCategories)\n .where(eq(sqliteSchema.productCategories.categoryId, categoryId))\n .all()\n return rows.map((r) => r.productId)\n }\n const rows = await postgresDb(tx)\n .select({ productId: postgresSchema.productCategories.productId })\n .from(postgresSchema.productCategories)\n .where(eq(postgresSchema.productCategories.categoryId, categoryId))\n return rows.map((r) => r.productId)\n },\n }\n}\n","import { eq, sql } from 'drizzle-orm'\nimport type { Customer, CustomerAddress, Role } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { parseJson, fromTimestamp } from './json.js'\n\nexport interface CustomerInsert {\n id: string\n email: string\n passwordHash: string\n firstName?: string\n lastName?: string\n phone?: string\n addresses?: CustomerAddress[]\n metadata?: Record<string, unknown>\n /** Defaults to `['customer']`; only seed and admin code pass anything else. */\n roles?: Role[]\n requiresPasswordReset?: boolean\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface CustomerUpdate {\n firstName?: string\n lastName?: string\n phone?: string\n addresses?: CustomerAddress[]\n metadata?: Record<string, unknown>\n passwordHash?: string\n requiresPasswordReset?: boolean\n updatedAt: Date\n}\n\nfunction rowToCustomer(\n store: CommandStore['kind'],\n row: Record<string, unknown>,\n): CustomerWithHash {\n return {\n id: String(row.id),\n email: String(row.email),\n passwordHash: String(row.passwordHash),\n firstName: String(row.firstName ?? ''),\n lastName: String(row.lastName ?? ''),\n phone: String(row.phone ?? ''),\n addresses: parseJson<CustomerAddress[]>(store, row.addresses, []),\n orderCount: Number(row.orderCount ?? 0),\n totalSpentMinor: Number(row.totalSpentMinor ?? 0),\n metadata: parseJson<Record<string, unknown>>(store, row.metadata, {}),\n roles: parseJson<Role[]>(store, row.roles, ['customer']),\n requiresPasswordReset: Boolean(row.requiresPasswordReset),\n createdAt: fromTimestamp(row.createdAt),\n updatedAt: fromTimestamp(row.updatedAt),\n }\n}\n\n/** A stored customer: its roles column is always read. */\nexport type CustomerWithHash = Customer & { passwordHash: string; roles: Role[] }\n\nexport interface CustomerRepository extends StoreRepository {\n findById(tx: ReadTx, id: string): Promise<CustomerWithHash | null>\n findByEmail(tx: ReadTx, email: string): Promise<CustomerWithHash | null>\n list(tx: ReadTx, opts?: { limit?: number; offset?: number }): Promise<CustomerWithHash[]>\n insert(tx: Tx, c: CustomerInsert): Promise<void>\n update(tx: Tx, id: string, patch: CustomerUpdate): Promise<void>\n incrementStats(\n tx: Tx,\n id: string,\n deltaOrders: number,\n deltaSpentMinor: number,\n updatedAt: Date,\n ): Promise<void>\n delete(tx: Tx, id: string): Promise<void>\n}\n\nexport function createCustomerRepository(store: CommandStore): CustomerRepository {\n return {\n store,\n async findById(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.customers)\n .where(eq(sqliteSchema.customers.id, id))\n .get()\n return row ? rowToCustomer('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.customers)\n .where(eq(postgresSchema.customers.id, id))\n return row ? rowToCustomer('postgres', row as Record<string, unknown>) : null\n },\n async findByEmail(tx, email) {\n const normalized = email.toLowerCase()\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.customers)\n .where(eq(sqliteSchema.customers.email, normalized))\n .get()\n return row ? rowToCustomer('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.customers)\n .where(eq(postgresSchema.customers.email, normalized))\n return row ? rowToCustomer('postgres', row as Record<string, unknown>) : null\n },\n async list(tx, opts = {}) {\n const limit = opts.limit ?? 1000\n const offset = opts.offset ?? 0\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.customers)\n .limit(limit)\n .offset(offset)\n .all()\n return rows.map((r) => rowToCustomer('sqlite', r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.customers)\n .limit(limit)\n .offset(offset)\n return rows.map((r) => rowToCustomer('postgres', r as Record<string, unknown>))\n },\n async insert(tx, c) {\n const email = c.email.toLowerCase()\n const common = {\n id: c.id,\n email,\n passwordHash: c.passwordHash,\n firstName: c.firstName ?? '',\n lastName: c.lastName ?? '',\n phone: c.phone ?? '',\n orderCount: 0,\n totalSpentMinor: 0,\n requiresPasswordReset: c.requiresPasswordReset ?? false,\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.customers)\n .values({\n ...common,\n addresses: JSON.stringify(c.addresses ?? []),\n metadata: JSON.stringify(c.metadata ?? {}),\n roles: JSON.stringify(c.roles ?? ['customer']),\n createdAt: c.createdAt.toISOString(),\n updatedAt: c.updatedAt.toISOString(),\n })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.customers)\n .values({\n ...common,\n addresses: c.addresses ?? [],\n metadata: c.metadata ?? {},\n roles: c.roles ?? ['customer'],\n createdAt: c.createdAt,\n updatedAt: c.updatedAt,\n })\n },\n async update(tx, id, patch) {\n const pg: Record<string, unknown> = { updatedAt: patch.updatedAt }\n const sq: Record<string, unknown> = { updatedAt: patch.updatedAt.toISOString() }\n for (const k of [\n 'firstName',\n 'lastName',\n 'phone',\n 'passwordHash',\n 'requiresPasswordReset',\n ] as const) {\n if (patch[k] !== undefined) {\n pg[k] = patch[k]\n sq[k] = patch[k]\n }\n }\n if (patch.addresses !== undefined) {\n pg.addresses = patch.addresses\n sq.addresses = JSON.stringify(patch.addresses)\n }\n if (patch.metadata !== undefined) {\n pg.metadata = patch.metadata\n sq.metadata = JSON.stringify(patch.metadata)\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.customers)\n .set(sq)\n .where(eq(sqliteSchema.customers.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.customers)\n .set(pg)\n .where(eq(postgresSchema.customers.id, id))\n },\n async incrementStats(tx, id, deltaOrders, deltaSpent, updatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.customers)\n .set({\n orderCount: sql`${sqliteSchema.customers.orderCount} + ${deltaOrders}`,\n totalSpentMinor: sql`${sqliteSchema.customers.totalSpentMinor} + ${deltaSpent}`,\n updatedAt: updatedAt.toISOString(),\n })\n .where(eq(sqliteSchema.customers.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.customers)\n .set({\n orderCount: sql`${postgresSchema.customers.orderCount} + ${deltaOrders}`,\n totalSpentMinor: sql`${postgresSchema.customers.totalSpentMinor} + ${deltaSpent}`,\n updatedAt,\n })\n .where(eq(postgresSchema.customers.id, id))\n },\n async delete(tx, id) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx).delete(sqliteSchema.customers).where(eq(sqliteSchema.customers.id, id)).run()\n return\n }\n await postgresDb(tx)\n .delete(postgresSchema.customers)\n .where(eq(postgresSchema.customers.id, id))\n },\n }\n}\n","import { and, eq, isNull, lt } from 'drizzle-orm'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface RefreshTokenInsert {\n id: string\n customerId: string\n tokenHash: string\n expiresAt: Date\n createdAt: Date\n}\n\nexport interface RefreshTokenRow {\n id: string\n customerId: string\n tokenHash: string\n revokedAt: string | null\n replacedByJti: string | null\n expiresAt: string\n createdAt: string\n}\n\nfunction rowToToken(row: Record<string, unknown>): RefreshTokenRow {\n return {\n id: String(row.id),\n customerId: String(row.customerId),\n tokenHash: String(row.tokenHash),\n revokedAt: row.revokedAt == null ? null : fromTimestamp(row.revokedAt),\n replacedByJti: (row.replacedByJti as string | null) ?? null,\n expiresAt: fromTimestamp(row.expiresAt),\n createdAt: fromTimestamp(row.createdAt),\n }\n}\n\nexport interface RefreshTokenRepository extends StoreRepository {\n insert(tx: Tx, t: RefreshTokenInsert): Promise<void>\n findById(tx: ReadTx, id: string): Promise<RefreshTokenRow | null>\n rotate(tx: Tx, oldJti: string, next: RefreshTokenInsert): Promise<void>\n revoke(tx: Tx, id: string): Promise<void>\n revokeAllForCustomer(tx: Tx, customerId: string): Promise<void>\n purgeExpired(tx: Tx, now: Date): Promise<number>\n}\n\nexport function createRefreshTokenRepository(store: CommandStore): RefreshTokenRepository {\n return {\n store,\n async insert(tx, t) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.refreshTokens)\n .values({\n id: t.id,\n customerId: t.customerId,\n tokenHash: t.tokenHash,\n revokedAt: null,\n replacedByJti: null,\n expiresAt: t.expiresAt.toISOString(),\n createdAt: t.createdAt.toISOString(),\n })\n .run()\n return\n }\n await postgresDb(tx).insert(postgresSchema.refreshTokens).values({\n id: t.id,\n customerId: t.customerId,\n tokenHash: t.tokenHash,\n revokedAt: null,\n replacedByJti: null,\n expiresAt: t.expiresAt,\n createdAt: t.createdAt,\n })\n },\n async findById(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.refreshTokens)\n .where(eq(sqliteSchema.refreshTokens.id, id))\n .get()\n return row ? rowToToken(row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.refreshTokens)\n .where(eq(postgresSchema.refreshTokens.id, id))\n return row ? rowToToken(row as Record<string, unknown>) : null\n },\n async rotate(tx, oldJti, next) {\n if (tx.kind === 'sqlite') {\n const db = sqliteDb(tx)\n db.update(sqliteSchema.refreshTokens)\n .set({ revokedAt: new Date().toISOString(), replacedByJti: next.id })\n .where(eq(sqliteSchema.refreshTokens.id, oldJti))\n .run()\n db.insert(sqliteSchema.refreshTokens)\n .values({\n id: next.id,\n customerId: next.customerId,\n tokenHash: next.tokenHash,\n revokedAt: null,\n replacedByJti: null,\n expiresAt: next.expiresAt.toISOString(),\n createdAt: next.createdAt.toISOString(),\n })\n .run()\n return\n }\n const db = postgresDb(tx)\n await db\n .update(postgresSchema.refreshTokens)\n .set({ revokedAt: new Date(), replacedByJti: next.id })\n .where(eq(postgresSchema.refreshTokens.id, oldJti))\n await db.insert(postgresSchema.refreshTokens).values({\n id: next.id,\n customerId: next.customerId,\n tokenHash: next.tokenHash,\n revokedAt: null,\n replacedByJti: null,\n expiresAt: next.expiresAt,\n createdAt: next.createdAt,\n })\n },\n async revoke(tx, id) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.refreshTokens)\n .set({ revokedAt: new Date().toISOString() })\n .where(\n and(\n eq(sqliteSchema.refreshTokens.id, id),\n isNull(sqliteSchema.refreshTokens.revokedAt),\n ),\n )\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.refreshTokens)\n .set({ revokedAt: new Date() })\n .where(\n and(\n eq(postgresSchema.refreshTokens.id, id),\n isNull(postgresSchema.refreshTokens.revokedAt),\n ),\n )\n },\n async revokeAllForCustomer(tx, customerId) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.refreshTokens)\n .set({ revokedAt: new Date().toISOString() })\n .where(eq(sqliteSchema.refreshTokens.customerId, customerId))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.refreshTokens)\n .set({ revokedAt: new Date() })\n .where(eq(postgresSchema.refreshTokens.customerId, customerId))\n },\n async purgeExpired(tx, now) {\n if (tx.kind === 'sqlite') {\n const result = sqliteDb(tx)\n .delete(sqliteSchema.refreshTokens)\n .where(lt(sqliteSchema.refreshTokens.expiresAt, now.toISOString()))\n .run()\n return result.changes\n }\n const result = await postgresDb(tx)\n .delete(postgresSchema.refreshTokens)\n .where(lt(postgresSchema.refreshTokens.expiresAt, now))\n return result.rowCount ?? 0\n },\n }\n}\n","import { and, desc, eq, notInArray } from 'drizzle-orm'\nimport type { Address, CaptureMethod, Order, OrderLineItem, OrderStatus } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { parseJson, fromTimestamp } from './json.js'\n\nexport interface OrderInsert {\n id: string\n orderNumber: string\n sequence: number\n customerId: string | null\n status: OrderStatus\n email: string\n billingAddress: Address\n shippingAddress: Address\n lineItems: OrderLineItem[]\n subtotalMinor: number\n taxTotalMinor: number\n shippingTotalMinor: number\n discountTotalMinor: number\n totalMinor: number\n currency: string\n notes?: string\n metadata?: Record<string, unknown>\n paymentIntentId?: string | null\n /** The cart a checkout order was placed from. */\n cartToken?: string | null\n /** An imported order's money; a checkout order starts with nothing captured. */\n capture?: OrderCapture & { refundedMinor: number }\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface OrderCapture {\n amountMinor: number\n method: CaptureMethod\n at: Date\n}\n\nfunction rowToOrder(store: CommandStore['kind'], row: Record<string, unknown>): Order {\n return {\n id: String(row.id),\n orderNumber: String(row.orderNumber),\n sequence: Number(row.sequence),\n customerId: (row.customerId as string | null) ?? null,\n status: row.status as OrderStatus,\n email: String(row.email),\n billingAddress: parseJson<Address>(store, row.billingAddress, {} as Address),\n shippingAddress: parseJson<Address>(store, row.shippingAddress, {} as Address),\n lineItems: parseJson<OrderLineItem[]>(store, row.lineItems, []),\n subtotalMinor: Number(row.subtotalMinor),\n taxTotalMinor: Number(row.taxTotalMinor ?? 0),\n shippingTotalMinor: Number(row.shippingTotalMinor ?? 0),\n discountTotalMinor: Number(row.discountTotalMinor ?? 0),\n totalMinor: Number(row.totalMinor),\n currency: String(row.currency),\n notes: String(row.notes ?? ''),\n metadata: parseJson<Record<string, unknown>>(store, row.metadata, {}),\n paymentIntentId: (row.paymentIntentId as string | null) ?? null,\n capturedMinor: Number(row.capturedMinor ?? 0),\n capturedAt: row.capturedAt == null ? null : fromTimestamp(row.capturedAt),\n refundedMinor: Number(row.refundedMinor ?? 0),\n captureMethod: (row.captureMethod as CaptureMethod | null) ?? null,\n createdAt: fromTimestamp(row.createdAt),\n updatedAt: fromTimestamp(row.updatedAt),\n }\n}\n\nexport interface OrderRepository extends StoreRepository {\n findById(tx: ReadTx, id: string): Promise<Order | null>\n /** The order, read under its row lock until the transaction ends (Postgres `FOR UPDATE`; on SQLite the open\n * `BEGIN IMMEDIATE` transaction already holds every write). */\n lock(tx: Tx, id: string): Promise<Order | null>\n findByOrderNumber(tx: ReadTx, orderNumber: string): Promise<Order | null>\n findByPaymentIntentId(tx: ReadTx, paymentIntentId: string): Promise<Order | null>\n /** The cart's pending order: at most one, by the partial unique index on `cart_token`. */\n findPendingByCartToken(tx: ReadTx, cartToken: string): Promise<Order | null>\n /** The newest order the cart became: neither pending nor cancelled. */\n findLastConvertedByCartToken(tx: ReadTx, cartToken: string): Promise<Order | null>\n listByCustomer(tx: ReadTx, customerId: string, limit?: number): Promise<Order[]>\n list(\n tx: ReadTx,\n opts?: { status?: OrderStatus; limit?: number; offset?: number },\n ): Promise<Order[]>\n insert(tx: Tx, o: OrderInsert): Promise<void>\n setStatus(tx: Tx, id: string, status: OrderStatus, updatedAt: Date): Promise<void>\n /** Sets `status` only while the order is still `from`; false when it was not, so a concurrent writer got there\n * first. */\n setStatusIf(\n tx: Tx,\n id: string,\n from: OrderStatus,\n status: OrderStatus,\n updatedAt: Date,\n ): Promise<boolean>\n setPaymentIntent(tx: Tx, id: string, paymentIntentId: string, updatedAt: Date): Promise<void>\n recordCapture(tx: Tx, id: string, capture: OrderCapture): Promise<void>\n setRefunded(tx: Tx, id: string, refundedMinor: number, updatedAt: Date): Promise<void>\n setNotes(tx: Tx, id: string, notes: string, updatedAt: Date): Promise<void>\n}\n\nexport function createOrderRepository(store: CommandStore): OrderRepository {\n return {\n store,\n async findById(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.orders)\n .where(eq(sqliteSchema.orders.id, id))\n .get()\n return row ? rowToOrder('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.orders)\n .where(eq(postgresSchema.orders.id, id))\n return row ? rowToOrder('postgres', row as Record<string, unknown>) : null\n },\n async lock(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.orders)\n .where(eq(sqliteSchema.orders.id, id))\n .get()\n return row ? rowToOrder('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.orders)\n .where(eq(postgresSchema.orders.id, id))\n .for('update')\n return row ? rowToOrder('postgres', row as Record<string, unknown>) : null\n },\n async findByOrderNumber(tx, orderNumber) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.orders)\n .where(eq(sqliteSchema.orders.orderNumber, orderNumber))\n .get()\n return row ? rowToOrder('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.orders)\n .where(eq(postgresSchema.orders.orderNumber, orderNumber))\n return row ? rowToOrder('postgres', row as Record<string, unknown>) : null\n },\n async findByPaymentIntentId(tx, paymentIntentId) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.orders)\n .where(eq(sqliteSchema.orders.paymentIntentId, paymentIntentId))\n .get()\n return row ? rowToOrder('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.orders)\n .where(eq(postgresSchema.orders.paymentIntentId, paymentIntentId))\n .limit(1)\n return row ? rowToOrder('postgres', row as Record<string, unknown>) : null\n },\n async findPendingByCartToken(tx, cartToken) {\n if (tx.kind === 'sqlite') {\n const o = sqliteSchema.orders\n const row = sqliteDb(tx)\n .select()\n .from(o)\n .where(and(eq(o.cartToken, cartToken), eq(o.status, 'pending')))\n .get()\n return row ? rowToOrder('sqlite', row as Record<string, unknown>) : null\n }\n const o = postgresSchema.orders\n const [row] = await postgresDb(tx)\n .select()\n .from(o)\n .where(and(eq(o.cartToken, cartToken), eq(o.status, 'pending')))\n return row ? rowToOrder('postgres', row as Record<string, unknown>) : null\n },\n async findLastConvertedByCartToken(tx, cartToken) {\n const unconverted = ['pending', 'cancelled'] as const\n if (tx.kind === 'sqlite') {\n const o = sqliteSchema.orders\n const row = sqliteDb(tx)\n .select()\n .from(o)\n .where(and(eq(o.cartToken, cartToken), notInArray(o.status, [...unconverted])))\n .orderBy(desc(o.sequence))\n .limit(1)\n .get()\n return row ? rowToOrder('sqlite', row as Record<string, unknown>) : null\n }\n const o = postgresSchema.orders\n const [row] = await postgresDb(tx)\n .select()\n .from(o)\n .where(and(eq(o.cartToken, cartToken), notInArray(o.status, [...unconverted])))\n .orderBy(desc(o.sequence))\n .limit(1)\n return row ? rowToOrder('postgres', row as Record<string, unknown>) : null\n },\n async listByCustomer(tx, customerId, limit = 50) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.orders)\n .where(eq(sqliteSchema.orders.customerId, customerId))\n .orderBy(desc(sqliteSchema.orders.createdAt))\n .limit(limit)\n .all()\n return rows.map((r) => rowToOrder('sqlite', r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.orders)\n .where(eq(postgresSchema.orders.customerId, customerId))\n .orderBy(desc(postgresSchema.orders.createdAt))\n .limit(limit)\n return rows.map((r) => rowToOrder('postgres', r as Record<string, unknown>))\n },\n async list(tx, opts = {}) {\n const limit = opts.limit ?? 100\n const offset = opts.offset ?? 0\n if (tx.kind === 'sqlite') {\n const base = sqliteDb(tx).select().from(sqliteSchema.orders)\n const filtered = opts.status\n ? base.where(eq(sqliteSchema.orders.status, opts.status))\n : base\n const rows = filtered\n .orderBy(desc(sqliteSchema.orders.createdAt))\n .limit(limit)\n .offset(offset)\n .all()\n return rows.map((r) => rowToOrder('sqlite', r as Record<string, unknown>))\n }\n const base = postgresDb(tx).select().from(postgresSchema.orders)\n const filtered = opts.status\n ? base.where(eq(postgresSchema.orders.status, opts.status))\n : base\n const rows = await filtered\n .orderBy(desc(postgresSchema.orders.createdAt))\n .limit(limit)\n .offset(offset)\n return rows.map((r) => rowToOrder('postgres', r as Record<string, unknown>))\n },\n async insert(tx, o) {\n const common = {\n id: o.id,\n orderNumber: o.orderNumber,\n sequence: o.sequence,\n customerId: o.customerId,\n status: o.status,\n email: o.email,\n subtotalMinor: o.subtotalMinor,\n taxTotalMinor: o.taxTotalMinor,\n shippingTotalMinor: o.shippingTotalMinor,\n discountTotalMinor: o.discountTotalMinor,\n totalMinor: o.totalMinor,\n currency: o.currency,\n notes: o.notes ?? '',\n paymentIntentId: o.paymentIntentId ?? null,\n cartToken: o.cartToken ?? null,\n capturedMinor: o.capture?.amountMinor ?? 0,\n refundedMinor: o.capture?.refundedMinor ?? 0,\n captureMethod: o.capture?.method ?? null,\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.orders)\n .values({\n ...common,\n billingAddress: JSON.stringify(o.billingAddress),\n shippingAddress: JSON.stringify(o.shippingAddress),\n lineItems: JSON.stringify(o.lineItems),\n metadata: JSON.stringify(o.metadata ?? {}),\n capturedAt: o.capture?.at.toISOString() ?? null,\n createdAt: o.createdAt.toISOString(),\n updatedAt: o.updatedAt.toISOString(),\n })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.orders)\n .values({\n ...common,\n billingAddress: o.billingAddress,\n shippingAddress: o.shippingAddress,\n lineItems: o.lineItems,\n metadata: o.metadata ?? {},\n capturedAt: o.capture?.at ?? null,\n createdAt: o.createdAt,\n updatedAt: o.updatedAt,\n })\n },\n async setStatus(tx, id, status, updatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.orders)\n .set({ status, updatedAt: updatedAt.toISOString() })\n .where(eq(sqliteSchema.orders.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.orders)\n .set({ status, updatedAt })\n .where(eq(postgresSchema.orders.id, id))\n },\n async setStatusIf(tx, id, from, status, updatedAt) {\n if (tx.kind === 'sqlite') {\n const o = sqliteSchema.orders\n const { changes } = sqliteDb(tx)\n .update(o)\n .set({ status, updatedAt: updatedAt.toISOString() })\n .where(and(eq(o.id, id), eq(o.status, from)))\n .run()\n return changes > 0\n }\n const o = postgresSchema.orders\n const result = await postgresDb(tx)\n .update(o)\n .set({ status, updatedAt })\n .where(and(eq(o.id, id), eq(o.status, from)))\n return (result.rowCount ?? 0) > 0\n },\n async setPaymentIntent(tx, id, paymentIntentId, updatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.orders)\n .set({ paymentIntentId, updatedAt: updatedAt.toISOString() })\n .where(eq(sqliteSchema.orders.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.orders)\n .set({ paymentIntentId, updatedAt })\n .where(eq(postgresSchema.orders.id, id))\n },\n async recordCapture(tx, id, capture) {\n const values = {\n capturedMinor: capture.amountMinor,\n captureMethod: capture.method,\n }\n if (tx.kind === 'sqlite') {\n const at = capture.at.toISOString()\n sqliteDb(tx)\n .update(sqliteSchema.orders)\n .set({ ...values, capturedAt: at, updatedAt: at })\n .where(eq(sqliteSchema.orders.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.orders)\n .set({ ...values, capturedAt: capture.at, updatedAt: capture.at })\n .where(eq(postgresSchema.orders.id, id))\n },\n async setRefunded(tx, id, refundedMinor, updatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.orders)\n .set({ refundedMinor, updatedAt: updatedAt.toISOString() })\n .where(eq(sqliteSchema.orders.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.orders)\n .set({ refundedMinor, updatedAt })\n .where(eq(postgresSchema.orders.id, id))\n },\n async setNotes(tx, id, notes, updatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.orders)\n .set({ notes, updatedAt: updatedAt.toISOString() })\n .where(eq(sqliteSchema.orders.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.orders)\n .set({ notes, updatedAt })\n .where(eq(postgresSchema.orders.id, id))\n },\n }\n}\n","import { asc, eq } from 'drizzle-orm'\nimport type { OrderHistoryEntry, OrderStatus } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface OrderHistoryInsert {\n id: string\n orderId: string\n fromStatus: OrderStatus | null\n toStatus: OrderStatus\n actor: string\n note?: string\n timestamp: Date\n}\n\nfunction rowToEntry(row: Record<string, unknown>): OrderHistoryEntry {\n return {\n id: String(row.id),\n orderId: String(row.orderId),\n fromStatus: (row.fromStatus as OrderStatus | null) ?? null,\n toStatus: row.toStatus as OrderStatus,\n actor: String(row.actor),\n note: String(row.note ?? ''),\n timestamp: fromTimestamp(row.timestamp),\n }\n}\n\nexport interface OrderHistoryRepository extends StoreRepository {\n append(tx: Tx, entry: OrderHistoryInsert): Promise<void>\n listByOrder(tx: ReadTx, orderId: string): Promise<OrderHistoryEntry[]>\n}\n\nexport function createOrderHistoryRepository(store: CommandStore): OrderHistoryRepository {\n return {\n store,\n async append(tx, entry) {\n const common = {\n id: entry.id,\n orderId: entry.orderId,\n fromStatus: entry.fromStatus,\n toStatus: entry.toStatus,\n actor: entry.actor,\n note: entry.note ?? '',\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.orderHistory)\n .values({ ...common, timestamp: entry.timestamp.toISOString() })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.orderHistory)\n .values({ ...common, timestamp: entry.timestamp })\n },\n async listByOrder(tx, orderId) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.orderHistory)\n .where(eq(sqliteSchema.orderHistory.orderId, orderId))\n .orderBy(asc(sqliteSchema.orderHistory.timestamp))\n .all()\n return rows.map((r) => rowToEntry(r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.orderHistory)\n .where(eq(postgresSchema.orderHistory.orderId, orderId))\n .orderBy(asc(postgresSchema.orderHistory.timestamp))\n return rows.map((r) => rowToEntry(r as Record<string, unknown>))\n },\n }\n}\n","import { and, asc, eq, inArray } from 'drizzle-orm'\nimport type { OrderRefund, OrderRefundStatus } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface OrderRefundInsert {\n id: string\n orderId: string\n amountMinor: number\n currency: string\n providerRefundId: string | null\n status: OrderRefundStatus\n reason: string | null\n actor: string\n createdAt: Date\n /** The client's key for the request that made the refund; unique per order. */\n requestId?: string | null\n}\n\nfunction rowToRefund(row: Record<string, unknown>): OrderRefund {\n return {\n id: String(row.id),\n orderId: String(row.orderId),\n amountMinor: Number(row.amountMinor),\n currency: String(row.currency),\n providerRefundId: (row.providerRefundId as string | null) ?? null,\n status: row.status as OrderRefundStatus,\n reason: (row.reason as string | null) ?? null,\n actor: String(row.actor),\n createdAt: fromTimestamp(row.createdAt),\n }\n}\n\nexport interface OrderRefundRepository extends StoreRepository {\n insert(tx: Tx, refund: OrderRefundInsert): Promise<void>\n /** Settles a `pending` refund; false when the row is not pending (already settled). */\n settle(\n tx: Tx,\n id: string,\n outcome: { status: OrderRefundStatus; providerRefundId: string | null },\n ): Promise<boolean>\n /** The order's refund made by the request `requestId`, or null. */\n findByRequestId(tx: ReadTx, orderId: string, requestId: string): Promise<OrderRefund | null>\n /** The order's refunds, oldest first. */\n listByOrder(tx: ReadTx, orderId: string): Promise<OrderRefund[]>\n /** The refunds of each order, oldest first; an order without refunds is absent. */\n listByOrders(tx: ReadTx, orderIds: string[]): Promise<Map<string, OrderRefund[]>>\n}\n\nexport function createOrderRefundRepository(store: CommandStore): OrderRefundRepository {\n async function list(tx: ReadTx, orderIds: string[]): Promise<OrderRefund[]> {\n if (orderIds.length === 0) return []\n if (tx.kind === 'sqlite') {\n const r = sqliteSchema.orderRefunds\n const rows = sqliteDb(tx)\n .select()\n .from(r)\n .where(inArray(r.orderId, orderIds))\n .orderBy(asc(r.createdAt), asc(r.id))\n .all()\n return rows.map((row) => rowToRefund(row as Record<string, unknown>))\n }\n const r = postgresSchema.orderRefunds\n const rows = await postgresDb(tx)\n .select()\n .from(r)\n .where(inArray(r.orderId, orderIds))\n .orderBy(asc(r.createdAt), asc(r.id))\n return rows.map((row) => rowToRefund(row as Record<string, unknown>))\n }\n\n return {\n store,\n async insert(tx, refund) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.orderRefunds)\n .values({ ...refund, createdAt: refund.createdAt.toISOString() })\n .run()\n return\n }\n await postgresDb(tx).insert(postgresSchema.orderRefunds).values(refund)\n },\n async settle(tx, id, outcome) {\n if (tx.kind === 'sqlite') {\n const r = sqliteSchema.orderRefunds\n const { changes } = sqliteDb(tx)\n .update(r)\n .set(outcome)\n .where(and(eq(r.id, id), eq(r.status, 'pending')))\n .run()\n return changes > 0\n }\n const r = postgresSchema.orderRefunds\n const result = await postgresDb(tx)\n .update(r)\n .set(outcome)\n .where(and(eq(r.id, id), eq(r.status, 'pending')))\n return (result.rowCount ?? 0) > 0\n },\n async findByRequestId(tx, orderId, requestId) {\n if (tx.kind === 'sqlite') {\n const r = sqliteSchema.orderRefunds\n const row = sqliteDb(tx)\n .select()\n .from(r)\n .where(and(eq(r.orderId, orderId), eq(r.requestId, requestId)))\n .get()\n return row ? rowToRefund(row as Record<string, unknown>) : null\n }\n const r = postgresSchema.orderRefunds\n const [row] = await postgresDb(tx)\n .select()\n .from(r)\n .where(and(eq(r.orderId, orderId), eq(r.requestId, requestId)))\n return row ? rowToRefund(row as Record<string, unknown>) : null\n },\n listByOrder(tx, orderId) {\n return list(tx, [orderId])\n },\n async listByOrders(tx, orderIds) {\n const byOrder = new Map<string, OrderRefund[]>()\n for (const refund of await list(tx, orderIds)) {\n const refunds = byOrder.get(refund.orderId) ?? []\n refunds.push(refund)\n byOrder.set(refund.orderId, refunds)\n }\n return byOrder\n },\n }\n}\n","import { eq, sql } from 'drizzle-orm'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\n\nexport interface OrderSequenceRepository extends StoreRepository {\n nextSequence(tx: Tx, startFrom?: number): Promise<number>\n}\n\nexport function createOrderSequenceRepository(store: CommandStore): OrderSequenceRepository {\n return {\n store,\n async nextSequence(tx, startFrom = 1000): Promise<number> {\n if (tx.kind === 'sqlite') {\n const client = sqliteDb(tx)\n const row = client\n .select()\n .from(sqliteSchema.orderSequences)\n .where(eq(sqliteSchema.orderSequences.id, 1))\n .get()\n if (!row) {\n const next = startFrom + 1\n client.insert(sqliteSchema.orderSequences).values({ id: 1, nextValue: next }).run()\n return startFrom\n }\n const current = row.nextValue\n client\n .update(sqliteSchema.orderSequences)\n .set({ nextValue: current + 1 })\n .where(eq(sqliteSchema.orderSequences.id, 1))\n .run()\n return current\n }\n const client = postgresDb(tx)\n const [row] = await client\n .select()\n .from(postgresSchema.orderSequences)\n .where(eq(postgresSchema.orderSequences.id, 1))\n .for('update')\n if (!row) {\n const next = startFrom + 1\n await client.insert(postgresSchema.orderSequences).values({ id: 1, nextValue: next })\n return startFrom\n }\n const current = row.nextValue\n await client\n .update(postgresSchema.orderSequences)\n .set({ nextValue: sql`${postgresSchema.orderSequences.nextValue} + 1` })\n .where(eq(postgresSchema.orderSequences.id, 1))\n return current\n },\n }\n}\n","import { eq, lt } from 'drizzle-orm'\nimport type { InventoryReservation } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface ReservationInsert {\n reservationId: string\n variantId: string\n qty: number\n orderRef?: string | null\n expiresAt: Date\n createdAt: Date\n}\n\nfunction rowToReservation(row: Record<string, unknown>): InventoryReservation {\n return {\n reservationId: String(row.reservationId),\n variantId: String(row.variantId),\n qty: Number(row.qty),\n orderRef: (row.orderRef as string | null) ?? null,\n expiresAt: fromTimestamp(row.expiresAt),\n createdAt: fromTimestamp(row.createdAt),\n }\n}\n\nexport interface InventoryReservationRepository extends StoreRepository {\n insert(tx: Tx, r: ReservationInsert): Promise<void>\n findById(tx: ReadTx, reservationId: string): Promise<InventoryReservation | null>\n findByVariant(tx: ReadTx, variantId: string): Promise<InventoryReservation[]>\n /** Deletes the reservation and returns the row it removed; null when none was there. Of two concurrent callers\n * only one gets the row, which is what makes a release and a commit of one reservation exclusive. */\n deleteById(tx: Tx, reservationId: string): Promise<InventoryReservation | null>\n /** Reservations whose expiry is before `at`; deletes nothing. */\n findExpiredBefore(tx: ReadTx, at: Date): Promise<InventoryReservation[]>\n setOrderRef(tx: Tx, reservationId: string, orderRef: string): Promise<void>\n}\n\nexport function createInventoryReservationRepository(\n store: CommandStore,\n): InventoryReservationRepository {\n return {\n store,\n async insert(tx, r) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.inventoryReservations)\n .values({\n reservationId: r.reservationId,\n variantId: r.variantId,\n qty: r.qty,\n orderRef: r.orderRef ?? null,\n expiresAt: r.expiresAt.toISOString(),\n createdAt: r.createdAt.toISOString(),\n })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.inventoryReservations)\n .values({\n reservationId: r.reservationId,\n variantId: r.variantId,\n qty: r.qty,\n orderRef: r.orderRef ?? null,\n expiresAt: r.expiresAt,\n createdAt: r.createdAt,\n })\n },\n async findById(tx, reservationId) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.inventoryReservations)\n .where(eq(sqliteSchema.inventoryReservations.reservationId, reservationId))\n .get()\n return row ? rowToReservation(row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.inventoryReservations)\n .where(eq(postgresSchema.inventoryReservations.reservationId, reservationId))\n return row ? rowToReservation(row as Record<string, unknown>) : null\n },\n async findByVariant(tx, variantId) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.inventoryReservations)\n .where(eq(sqliteSchema.inventoryReservations.variantId, variantId))\n .all()\n return rows.map((r) => rowToReservation(r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.inventoryReservations)\n .where(eq(postgresSchema.inventoryReservations.variantId, variantId))\n return rows.map((r) => rowToReservation(r as Record<string, unknown>))\n },\n async deleteById(tx, reservationId) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .delete(sqliteSchema.inventoryReservations)\n .where(eq(sqliteSchema.inventoryReservations.reservationId, reservationId))\n .returning()\n .get()\n return row ? rowToReservation(row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .delete(postgresSchema.inventoryReservations)\n .where(eq(postgresSchema.inventoryReservations.reservationId, reservationId))\n .returning()\n return row ? rowToReservation(row as Record<string, unknown>) : null\n },\n async findExpiredBefore(tx, at) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.inventoryReservations)\n .where(lt(sqliteSchema.inventoryReservations.expiresAt, at.toISOString()))\n .all()\n return rows.map((r) => rowToReservation(r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.inventoryReservations)\n .where(lt(postgresSchema.inventoryReservations.expiresAt, at))\n return rows.map((r) => rowToReservation(r as Record<string, unknown>))\n },\n async setOrderRef(tx, reservationId, orderRef) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.inventoryReservations)\n .set({ orderRef })\n .where(eq(sqliteSchema.inventoryReservations.reservationId, reservationId))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.inventoryReservations)\n .set({ orderRef })\n .where(eq(postgresSchema.inventoryReservations.reservationId, reservationId))\n },\n }\n}\n","import { desc, eq } from 'drizzle-orm'\nimport type { StockAdjustment, StockAdjustmentReason } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface StockAdjustmentInsert {\n id: string\n variantId: string\n adjustment: number\n reason: StockAdjustmentReason\n actor: string\n previousQty: number\n newQty: number\n timestamp: Date\n}\n\nfunction rowToAdjustment(row: Record<string, unknown>): StockAdjustment {\n return {\n id: String(row.id),\n variantId: String(row.variantId),\n adjustment: Number(row.adjustment),\n reason: row.reason as StockAdjustmentReason,\n actor: String(row.actor),\n previousQty: Number(row.previousQty),\n newQty: Number(row.newQty),\n timestamp: fromTimestamp(row.timestamp),\n }\n}\n\nexport interface StockAdjustmentRepository extends StoreRepository {\n append(tx: Tx, a: StockAdjustmentInsert): Promise<void>\n listByVariant(tx: ReadTx, variantId: string, limit?: number): Promise<StockAdjustment[]>\n}\n\nexport function createStockAdjustmentRepository(store: CommandStore): StockAdjustmentRepository {\n return {\n store,\n async append(tx, a) {\n const common = {\n id: a.id,\n variantId: a.variantId,\n adjustment: a.adjustment,\n reason: a.reason,\n actor: a.actor,\n previousQty: a.previousQty,\n newQty: a.newQty,\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.stockAdjustments)\n .values({ ...common, timestamp: a.timestamp.toISOString() })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.stockAdjustments)\n .values({ ...common, timestamp: a.timestamp })\n },\n async listByVariant(tx, variantId, limit = 100) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.stockAdjustments)\n .where(eq(sqliteSchema.stockAdjustments.variantId, variantId))\n .orderBy(desc(sqliteSchema.stockAdjustments.timestamp))\n .limit(limit)\n .all()\n return rows.map((r) => rowToAdjustment(r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.stockAdjustments)\n .where(eq(postgresSchema.stockAdjustments.variantId, variantId))\n .orderBy(desc(postgresSchema.stockAdjustments.timestamp))\n .limit(limit)\n return rows.map((r) => rowToAdjustment(r as Record<string, unknown>))\n },\n }\n}\n","import { and, desc, eq } from 'drizzle-orm'\nimport type { Review, ReviewModerationStatus } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp } from './json.js'\n\nexport interface ReviewInsert {\n id: string\n productId: string\n customerId: string | null\n orderId: string | null\n rating: number\n title: string\n body: string\n moderationStatus?: ReviewModerationStatus\n submittedAt: Date\n}\n\nfunction rowToReview(row: Record<string, unknown>): Review {\n return {\n id: String(row.id),\n productId: String(row.productId),\n customerId: (row.customerId as string | null) ?? null,\n orderId: (row.orderId as string | null) ?? null,\n rating: Number(row.rating),\n title: String(row.title ?? ''),\n body: String(row.body ?? ''),\n moderationStatus: row.moderationStatus as ReviewModerationStatus,\n submittedAt: fromTimestamp(row.submittedAt),\n moderatedAt: row.moderatedAt == null ? null : fromTimestamp(row.moderatedAt),\n moderatedBy: (row.moderatedBy as string | null) ?? null,\n }\n}\n\nexport interface ReviewRepository extends StoreRepository {\n findById(tx: ReadTx, id: string): Promise<Review | null>\n listByProduct(\n tx: ReadTx,\n productId: string,\n status?: ReviewModerationStatus,\n limit?: number,\n ): Promise<Review[]>\n listByStatus(tx: ReadTx, status: ReviewModerationStatus, limit?: number): Promise<Review[]>\n insert(tx: Tx, r: ReviewInsert): Promise<void>\n setModerationStatus(\n tx: Tx,\n id: string,\n status: ReviewModerationStatus,\n moderatedBy: string,\n moderatedAt: Date,\n ): Promise<void>\n aggregateByProduct(\n tx: ReadTx,\n productId: string,\n ): Promise<{\n average: number\n count: number\n histogram: Record<'1' | '2' | '3' | '4' | '5', number>\n }>\n}\n\nexport function createReviewRepository(store: CommandStore): ReviewRepository {\n return {\n store,\n async findById(tx, id) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.reviews)\n .where(eq(sqliteSchema.reviews.id, id))\n .get()\n return row ? rowToReview(row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.reviews)\n .where(eq(postgresSchema.reviews.id, id))\n return row ? rowToReview(row as Record<string, unknown>) : null\n },\n async listByProduct(tx, productId, status, limit = 50) {\n if (tx.kind === 'sqlite') {\n const cond = status\n ? and(\n eq(sqliteSchema.reviews.productId, productId),\n eq(sqliteSchema.reviews.moderationStatus, status),\n )\n : eq(sqliteSchema.reviews.productId, productId)\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.reviews)\n .where(cond)\n .orderBy(desc(sqliteSchema.reviews.submittedAt))\n .limit(limit)\n .all()\n return rows.map((r) => rowToReview(r as Record<string, unknown>))\n }\n const cond = status\n ? and(\n eq(postgresSchema.reviews.productId, productId),\n eq(postgresSchema.reviews.moderationStatus, status),\n )\n : eq(postgresSchema.reviews.productId, productId)\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.reviews)\n .where(cond)\n .orderBy(desc(postgresSchema.reviews.submittedAt))\n .limit(limit)\n return rows.map((r) => rowToReview(r as Record<string, unknown>))\n },\n async listByStatus(tx, status, limit = 100) {\n if (tx.kind === 'sqlite') {\n const rows = sqliteDb(tx)\n .select()\n .from(sqliteSchema.reviews)\n .where(eq(sqliteSchema.reviews.moderationStatus, status))\n .orderBy(desc(sqliteSchema.reviews.submittedAt))\n .limit(limit)\n .all()\n return rows.map((r) => rowToReview(r as Record<string, unknown>))\n }\n const rows = await postgresDb(tx)\n .select()\n .from(postgresSchema.reviews)\n .where(eq(postgresSchema.reviews.moderationStatus, status))\n .orderBy(desc(postgresSchema.reviews.submittedAt))\n .limit(limit)\n return rows.map((r) => rowToReview(r as Record<string, unknown>))\n },\n async insert(tx, r) {\n const common = {\n id: r.id,\n productId: r.productId,\n customerId: r.customerId,\n orderId: r.orderId,\n rating: r.rating,\n title: r.title,\n body: r.body,\n moderationStatus: r.moderationStatus ?? 'pending',\n }\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.reviews)\n .values({\n ...common,\n submittedAt: r.submittedAt.toISOString(),\n moderatedAt: null,\n moderatedBy: null,\n })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.reviews)\n .values({\n ...common,\n submittedAt: r.submittedAt,\n moderatedAt: null,\n moderatedBy: null,\n })\n },\n async setModerationStatus(tx, id, status, moderatedBy, moderatedAt) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(sqliteSchema.reviews)\n .set({\n moderationStatus: status,\n moderatedBy,\n moderatedAt: moderatedAt.toISOString(),\n })\n .where(eq(sqliteSchema.reviews.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(postgresSchema.reviews)\n .set({ moderationStatus: status, moderatedBy, moderatedAt })\n .where(eq(postgresSchema.reviews.id, id))\n },\n async aggregateByProduct(tx, productId) {\n const approved = await this.listByProduct(tx, productId, 'approved', 1000)\n const histogram: Record<'1' | '2' | '3' | '4' | '5', number> = {\n '1': 0,\n '2': 0,\n '3': 0,\n '4': 0,\n '5': 0,\n }\n let total = 0\n for (const r of approved) {\n const bucket = String(\n Math.max(1, Math.min(5, Math.round(r.rating))),\n ) as keyof typeof histogram\n histogram[bucket] += 1\n total += r.rating\n }\n const count = approved.length\n const average = count === 0 ? 0 : total / count\n return { average, count, histogram }\n },\n }\n}\n","import { and, eq, lt } from 'drizzle-orm'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\n\n/** Which handler has already run for which event id: what stops a side effect running twice, across restarts. */\nexport interface ProcessedEventRepository extends StoreRepository {\n seen(tx: ReadTx, handlerName: string, eventId: string): Promise<boolean>\n /** Idempotent on (handlerName, eventId): a second call keeps the first record. */\n markProcessed(tx: Tx, handlerName: string, eventId: string, at: Date): Promise<void>\n /** Deletes records processed before `at`; returns how many. */\n deleteBefore(tx: Tx, at: Date): Promise<number>\n}\n\nexport function createProcessedEventRepository(store: CommandStore): ProcessedEventRepository {\n const s = sqliteSchema.processedEvents\n const p = postgresSchema.processedEvents\n return {\n store,\n async seen(tx, handlerName, eventId) {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select({ eventId: s.eventId })\n .from(s)\n .where(and(eq(s.handlerName, handlerName), eq(s.eventId, eventId)))\n .get()\n return row !== undefined\n }\n const rows = await postgresDb(tx)\n .select({ eventId: p.eventId })\n .from(p)\n .where(and(eq(p.handlerName, handlerName), eq(p.eventId, eventId)))\n .limit(1)\n return rows.length > 0\n },\n async markProcessed(tx, handlerName, eventId, at) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(s)\n .values({ handlerName, eventId, processedAt: at.toISOString() })\n .onConflictDoNothing()\n .run()\n return\n }\n await postgresDb(tx)\n .insert(p)\n .values({ handlerName, eventId, processedAt: at })\n .onConflictDoNothing()\n },\n async deleteBefore(tx, at) {\n if (tx.kind === 'sqlite') {\n return sqliteDb(tx).delete(s).where(lt(s.processedAt, at.toISOString())).run().changes\n }\n const result = await postgresDb(tx).delete(p).where(lt(p.processedAt, at))\n return result.rowCount ?? 0\n },\n }\n}\n","import { and, asc, eq, gt, inArray, isNotNull, isNull, lt, sql } from 'drizzle-orm'\nimport type { NymbalEvent } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\n\nexport interface LoggedEvent {\n seq: number\n event: NymbalEvent<unknown>\n deliveredAt: Date | null\n attempts: number\n deadAt: Date | null\n}\n\nexport interface EventLogRepository extends StoreRepository {\n /** Appends in array order, so `seq` follows publish order. */\n append(tx: Tx, events: NymbalEvent<unknown>[]): Promise<void>\n /** Neither delivered nor dead, by `seq`; `afterSeq` pages through one pass without re-reading rows it just tried. */\n listUndelivered(tx: ReadTx, limit: number, afterSeq?: number): Promise<LoggedEvent[]>\n markDelivered(tx: Tx, ids: string[], at: Date): Promise<void>\n /** One more failed attempt; the event is dead (`dead_at = at`) once its attempts reach `maxAttempts`. */\n recordFailure(tx: Tx, id: string, at: Date, maxAttempts: number): Promise<void>\n /** Deletes delivered events delivered before `at`; returns how many. Undelivered and dead events are never deleted. */\n deleteDeliveredBefore(tx: Tx, at: Date): Promise<number>\n listAll(tx: ReadTx): Promise<LoggedEvent[]>\n}\n\n// SQLite's bound-parameter limit is per statement; seven columns a row keeps a chunk well under it.\nconst APPEND_CHUNK = 100\n\nfunction toDate(value: unknown): Date | null {\n if (value === null || value === undefined) return null\n return value instanceof Date ? value : new Date(String(value))\n}\n\nfunction rowToLogged(row: {\n seq: number\n envelope: unknown\n deliveredAt: unknown\n attempts: number\n deadAt: unknown\n}): LoggedEvent {\n const envelope =\n typeof row.envelope === 'string'\n ? (JSON.parse(row.envelope) as NymbalEvent<unknown>)\n : (row.envelope as NymbalEvent<unknown>)\n return {\n seq: Number(row.seq),\n event: envelope,\n deliveredAt: toDate(row.deliveredAt),\n attempts: Number(row.attempts),\n deadAt: toDate(row.deadAt),\n }\n}\n\nexport function createEventLogRepository(store: CommandStore): EventLogRepository {\n const s = sqliteSchema.events\n const p = postgresSchema.events\n return {\n store,\n async append(tx, events) {\n const now = new Date()\n for (let i = 0; i < events.length; i += APPEND_CHUNK) {\n const chunk = events.slice(i, i + APPEND_CHUNK)\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(s)\n .values(\n chunk.map((e) => ({\n id: e.id,\n type: e.type,\n envelope: JSON.stringify(e),\n createdAt: now.toISOString(),\n })),\n )\n .run()\n } else {\n await postgresDb(tx)\n .insert(p)\n .values(chunk.map((e) => ({ id: e.id, type: e.type, envelope: e, createdAt: now })))\n }\n }\n },\n async listUndelivered(tx, limit, afterSeq = 0) {\n if (tx.kind === 'sqlite') {\n return sqliteDb(tx)\n .select()\n .from(s)\n .where(and(isNull(s.deliveredAt), isNull(s.deadAt), gt(s.seq, afterSeq)))\n .orderBy(asc(s.seq))\n .limit(limit)\n .all()\n .map(rowToLogged)\n }\n const rows = await postgresDb(tx)\n .select()\n .from(p)\n .where(and(isNull(p.deliveredAt), isNull(p.deadAt), gt(p.seq, afterSeq)))\n .orderBy(asc(p.seq))\n .limit(limit)\n return rows.map(rowToLogged)\n },\n async markDelivered(tx, ids, at) {\n if (ids.length === 0) return\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(s)\n .set({ deliveredAt: at.toISOString() })\n .where(inArray(s.id, ids))\n .run()\n return\n }\n await postgresDb(tx).update(p).set({ deliveredAt: at }).where(inArray(p.id, ids))\n },\n async recordFailure(tx, id, at, maxAttempts) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .update(s)\n .set({\n attempts: sql`${s.attempts} + 1`,\n deadAt: sql`CASE WHEN ${s.attempts} + 1 >= ${maxAttempts} THEN ${at.toISOString()} ELSE ${s.deadAt} END`,\n })\n .where(eq(s.id, id))\n .run()\n return\n }\n await postgresDb(tx)\n .update(p)\n .set({\n attempts: sql`${p.attempts} + 1`,\n deadAt: sql`CASE WHEN ${p.attempts} + 1 >= ${maxAttempts} THEN ${at.toISOString()}::timestamptz ELSE ${p.deadAt} END`,\n })\n .where(eq(p.id, id))\n },\n async deleteDeliveredBefore(tx, at) {\n if (tx.kind === 'sqlite') {\n const result = sqliteDb(tx)\n .delete(s)\n .where(and(isNotNull(s.deliveredAt), lt(s.deliveredAt, at.toISOString())))\n .run()\n return result.changes\n }\n const result = await postgresDb(tx)\n .delete(p)\n .where(and(isNotNull(p.deliveredAt), lt(p.deliveredAt, at)))\n return result.rowCount ?? 0\n },\n async listAll(tx) {\n if (tx.kind === 'sqlite') {\n return sqliteDb(tx).select().from(s).orderBy(asc(s.seq)).all().map(rowToLogged)\n }\n const rows = await postgresDb(tx).select().from(p).orderBy(asc(p.seq))\n return rows.map(rowToLogged)\n },\n }\n}\n","import { and, asc, eq, gt, isNull, lt, lte, sql } from 'drizzle-orm'\nimport type { Cart, CartItem } from '@nymbalhq/types'\nimport {\n postgresDb,\n sqliteDb,\n type CommandStore,\n type ReadTx,\n type StoreRepository,\n type Tx,\n} from '../db/command-store.js'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { fromTimestamp, parseJson } from './json.js'\n\n/** What makes a cart due an abandonment notice at `at`: live, holding items, unwritten since `cutoff`, not yet\n * notified in this inactivity period. */\nexport interface AbandonedWindow {\n cutoff: Date\n at: Date\n}\n\nexport interface AbandonedCart {\n token: string\n /** The cart's last write. */\n lastActivityAt: string\n}\n\nexport interface CartRepository extends StoreRepository {\n findByToken(tx: ReadTx, token: string): Promise<Cart | null>\n /** `findByToken`, holding the row for the rest of the transaction so concurrent commands on the cart queue behind\n * this one (Postgres `FOR UPDATE`; SQLite's `BEGIN IMMEDIATE` already holds the database). */\n lock(tx: Tx, token: string): Promise<Cart | null>\n /** Inserts the cart, or replaces an expired row on its token. A live row on the token is left as it is and\n * returned with `created: false`. */\n create(tx: Tx, cart: Cart): Promise<{ cart: Cart; created: boolean }>\n /** Writes the cart whole and starts a new inactivity period (clears the abandonment claim). */\n put(tx: Tx, cart: Cart): Promise<void>\n remove(tx: Tx, token: string): Promise<void>\n /** Empties the cart if it is still live at `at`, in one conditional write; false when there was no live row to\n * empty (expired, or deleted by a sweep or a merge). Starts a new inactivity period; the expiry stays as it was. */\n clearIfLive(tx: Tx, token: string, at: Date): Promise<boolean>\n /** Deletes every cart whose expiry is at or before `at`; returns how many. */\n deleteExpired(tx: Tx, at: Date): Promise<number>\n /** Up to `limit` tokens due a notice, in token order after `after`; claims nothing. */\n listAbandoned(\n tx: ReadTx,\n window: AbandonedWindow,\n page: { after: string | undefined; limit: number },\n ): Promise<string[]>\n /** Marks the cart notified if it is still due a notice; null when it is not (another sweeper claimed it, or a\n * write, expiry or delete came first). */\n claimAbandoned(tx: Tx, token: string, window: AbandonedWindow): Promise<AbandonedCart | null>\n}\n\nfunction rowToCart(store: 'sqlite' | 'postgres', row: Record<string, unknown>): Cart {\n return {\n token: String(row.token),\n customerId: (row.customerId as string | null) ?? null,\n items: parseJson<CartItem[]>(store, row.items, []),\n subtotalMinor: Number(row.subtotalMinor),\n currency: String(row.currency),\n expiresAt: fromTimestamp(row.expiresAt),\n createdAt: fromTimestamp(row.createdAt),\n updatedAt: fromTimestamp(row.updatedAt),\n }\n}\n\nfunction sqliteValues(cart: Cart) {\n return {\n token: cart.token,\n customerId: cart.customerId,\n currency: cart.currency,\n items: JSON.stringify(cart.items),\n lineCount: cart.items.length,\n subtotalMinor: cart.subtotalMinor,\n expiresAt: cart.expiresAt,\n createdAt: cart.createdAt,\n updatedAt: cart.updatedAt,\n abandonedNotifiedAt: null,\n }\n}\n\nfunction postgresValues(cart: Cart) {\n return {\n token: cart.token,\n customerId: cart.customerId,\n currency: cart.currency,\n items: cart.items,\n lineCount: cart.items.length,\n subtotalMinor: cart.subtotalMinor,\n expiresAt: new Date(cart.expiresAt),\n createdAt: new Date(cart.createdAt),\n updatedAt: new Date(cart.updatedAt),\n abandonedNotifiedAt: null,\n }\n}\n\n/** Every column but the key, taken from the row being inserted (`excluded` in both dialects' upsert). */\nconst fromExcluded = {\n customerId: sql`excluded.customer_id`,\n currency: sql`excluded.currency`,\n items: sql`excluded.items`,\n lineCount: sql`excluded.line_count`,\n subtotalMinor: sql`excluded.subtotal_minor`,\n expiresAt: sql`excluded.expires_at`,\n createdAt: sql`excluded.created_at`,\n updatedAt: sql`excluded.updated_at`,\n abandonedNotifiedAt: sql`excluded.abandoned_notified_at`,\n}\n\nfunction sqliteDue(window: AbandonedWindow) {\n const t = sqliteSchema.carts\n return and(\n isNull(t.abandonedNotifiedAt),\n gt(t.lineCount, 0),\n lt(t.updatedAt, window.cutoff.toISOString()),\n gt(t.expiresAt, window.at.toISOString()),\n )\n}\n\nfunction postgresDue(window: AbandonedWindow) {\n const t = postgresSchema.carts\n return and(\n isNull(t.abandonedNotifiedAt),\n gt(t.lineCount, 0),\n lt(t.updatedAt, window.cutoff),\n gt(t.expiresAt, window.at),\n )\n}\n\nexport function createCartRepository(store: CommandStore): CartRepository {\n async function findByToken(tx: ReadTx, token: string): Promise<Cart | null> {\n if (tx.kind === 'sqlite') {\n const row = sqliteDb(tx)\n .select()\n .from(sqliteSchema.carts)\n .where(eq(sqliteSchema.carts.token, token))\n .get()\n return row ? rowToCart('sqlite', row as Record<string, unknown>) : null\n }\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.carts)\n .where(eq(postgresSchema.carts.token, token))\n return row ? rowToCart('postgres', row as Record<string, unknown>) : null\n }\n\n async function lock(tx: Tx, token: string): Promise<Cart | null> {\n if (tx.kind === 'sqlite') return findByToken(tx, token)\n const [row] = await postgresDb(tx)\n .select()\n .from(postgresSchema.carts)\n .where(eq(postgresSchema.carts.token, token))\n .for('update')\n return row ? rowToCart('postgres', row as Record<string, unknown>) : null\n }\n\n return {\n store,\n findByToken,\n lock,\n async create(tx, cart) {\n let inserted: Record<string, unknown> | undefined\n if (tx.kind === 'sqlite') {\n inserted = sqliteDb(tx)\n .insert(sqliteSchema.carts)\n .values(sqliteValues(cart))\n .onConflictDoUpdate({\n target: sqliteSchema.carts.token,\n set: fromExcluded,\n setWhere: lte(sqliteSchema.carts.expiresAt, sql`excluded.updated_at`),\n })\n .returning()\n .get() as Record<string, unknown> | undefined\n } else {\n // A live row on the token makes the update a no-op, and `ON CONFLICT` waits for an insert in flight, so the\n // row read below is committed.\n ;[inserted] = await postgresDb(tx)\n .insert(postgresSchema.carts)\n .values(postgresValues(cart))\n .onConflictDoUpdate({\n target: postgresSchema.carts.token,\n set: fromExcluded,\n setWhere: lte(postgresSchema.carts.expiresAt, sql`excluded.updated_at`),\n })\n .returning()\n }\n if (inserted !== undefined) return { cart: rowToCart(tx.kind, inserted), created: true }\n const live = await lock(tx, cart.token)\n if (live === null) throw new Error(`cart ${cart.token} vanished while it was being created`)\n return { cart: live, created: false }\n },\n async put(tx, cart) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx)\n .insert(sqliteSchema.carts)\n .values(sqliteValues(cart))\n .onConflictDoUpdate({ target: sqliteSchema.carts.token, set: fromExcluded })\n .run()\n return\n }\n await postgresDb(tx)\n .insert(postgresSchema.carts)\n .values(postgresValues(cart))\n .onConflictDoUpdate({ target: postgresSchema.carts.token, set: fromExcluded })\n },\n async remove(tx, token) {\n if (tx.kind === 'sqlite') {\n sqliteDb(tx).delete(sqliteSchema.carts).where(eq(sqliteSchema.carts.token, token)).run()\n return\n }\n await postgresDb(tx).delete(postgresSchema.carts).where(eq(postgresSchema.carts.token, token))\n },\n async clearIfLive(tx, token, at) {\n if (tx.kind === 'sqlite') {\n const t = sqliteSchema.carts\n const result = sqliteDb(tx)\n .update(t)\n .set({\n items: '[]',\n lineCount: 0,\n subtotalMinor: 0,\n updatedAt: at.toISOString(),\n abandonedNotifiedAt: null,\n })\n .where(and(eq(t.token, token), gt(t.expiresAt, at.toISOString())))\n .run()\n return result.changes > 0\n }\n // Under READ COMMITTED the update waits for a concurrent delete or write on the row and re-checks the condition\n // against what that one committed, so a row swept in between is skipped rather than reported missing.\n const t = postgresSchema.carts\n const rows = await postgresDb(tx)\n .update(t)\n .set({\n items: [],\n lineCount: 0,\n subtotalMinor: 0,\n updatedAt: at,\n abandonedNotifiedAt: null,\n })\n .where(and(eq(t.token, token), gt(t.expiresAt, at)))\n .returning({ token: t.token })\n return rows.length > 0\n },\n async deleteExpired(tx, at) {\n if (tx.kind === 'sqlite') {\n const result = sqliteDb(tx)\n .delete(sqliteSchema.carts)\n .where(lte(sqliteSchema.carts.expiresAt, at.toISOString()))\n .run()\n return result.changes\n }\n const rows = await postgresDb(tx)\n .delete(postgresSchema.carts)\n .where(lte(postgresSchema.carts.expiresAt, at))\n .returning({ token: postgresSchema.carts.token })\n return rows.length\n },\n async listAbandoned(tx, window, page) {\n if (tx.kind === 'sqlite') {\n const t = sqliteSchema.carts\n const rows = sqliteDb(tx)\n .select({ token: t.token })\n .from(t)\n .where(\n and(sqliteDue(window), page.after === undefined ? undefined : gt(t.token, page.after)),\n )\n .orderBy(asc(t.token))\n .limit(page.limit)\n .all()\n return rows.map((r) => r.token)\n }\n const t = postgresSchema.carts\n const rows = await postgresDb(tx)\n .select({ token: t.token })\n .from(t)\n .where(\n and(postgresDue(window), page.after === undefined ? undefined : gt(t.token, page.after)),\n )\n .orderBy(asc(t.token))\n .limit(page.limit)\n return rows.map((r) => r.token)\n },\n async claimAbandoned(tx, token, window) {\n if (tx.kind === 'sqlite') {\n const t = sqliteSchema.carts\n const row = sqliteDb(tx)\n .update(t)\n .set({ abandonedNotifiedAt: window.at.toISOString() })\n .where(and(eq(t.token, token), sqliteDue(window)))\n .returning({ token: t.token, updatedAt: t.updatedAt })\n .get()\n return row ? { token: row.token, lastActivityAt: fromTimestamp(row.updatedAt) } : null\n }\n // Under READ COMMITTED the update waits for a concurrent claim or write on the row and re-checks the condition\n // against what that one committed, so of two sweepers only one gets the row back.\n const t = postgresSchema.carts\n const [row] = await postgresDb(tx)\n .update(t)\n .set({ abandonedNotifiedAt: window.at })\n .where(and(eq(t.token, token), postgresDue(window)))\n .returning({ token: t.token, updatedAt: t.updatedAt })\n return row ? { token: row.token, lastActivityAt: fromTimestamp(row.updatedAt) } : null\n },\n }\n}\n","import type { DocumentStoreAdapter } from '@nymbalhq/types'\nimport type { CommandStore } from '../db/command-store.js'\nimport { createProductRepository, type ProductRepository } from './product.js'\nimport { createVariantRepository, type VariantRepository } from './variant.js'\nimport { createCategoryRepository, type CategoryRepository } from './category.js'\nimport {\n createProductCategoryRepository,\n type ProductCategoryRepository,\n} from './product-category.js'\nimport { createCustomerRepository, type CustomerRepository } from './customer.js'\nimport { createRefreshTokenRepository, type RefreshTokenRepository } from './refresh-token.js'\nimport { createOrderRepository, type OrderRepository } from './order.js'\nimport { createOrderHistoryRepository, type OrderHistoryRepository } from './order-history.js'\nimport { createOrderRefundRepository, type OrderRefundRepository } from './order-refund.js'\nimport { createOrderSequenceRepository, type OrderSequenceRepository } from './order-sequence.js'\nimport {\n createInventoryReservationRepository,\n type InventoryReservationRepository,\n} from './inventory-reservation.js'\nimport {\n createStockAdjustmentRepository,\n type StockAdjustmentRepository,\n} from './stock-adjustment.js'\nimport { createReviewRepository, type ReviewRepository } from './review.js'\nimport { createProcessedEventRepository, type ProcessedEventRepository } from './processed-event.js'\nimport { createEventLogRepository, type EventLogRepository } from './event-log.js'\nimport { createCartRepository, type CartRepository } from './cart.js'\n\nexport * from './product.js'\nexport * from './variant.js'\nexport * from './category.js'\nexport * from './product-category.js'\nexport * from './customer.js'\nexport * from './refresh-token.js'\nexport * from './order.js'\nexport * from './order-history.js'\nexport * from './order-refund.js'\nexport * from './order-sequence.js'\nexport * from './inventory-reservation.js'\nexport * from './stock-adjustment.js'\nexport * from './review.js'\nexport * from './processed-event.js'\nexport * from './event-log.js'\nexport * from './cart.js'\n\nexport interface Repositories {\n product: ProductRepository\n variant: VariantRepository\n category: CategoryRepository\n productCategory: ProductCategoryRepository\n customer: CustomerRepository\n refreshToken: RefreshTokenRepository\n order: OrderRepository\n orderHistory: OrderHistoryRepository\n orderRefund: OrderRefundRepository\n orderSequence: OrderSequenceRepository\n inventoryReservation: InventoryReservationRepository\n stockAdjustment: StockAdjustmentRepository\n review: ReviewRepository\n processedEvent: ProcessedEventRepository\n eventLog: EventLogRepository\n cart: CartRepository\n}\n\nexport function buildRepositories(\n commandStore: CommandStore,\n // Every repository is command-store backed; the parameter stays so existing callers keep compiling.\n _documentStore: DocumentStoreAdapter,\n): Repositories {\n return {\n product: createProductRepository(commandStore),\n variant: createVariantRepository(commandStore),\n category: createCategoryRepository(commandStore),\n productCategory: createProductCategoryRepository(commandStore),\n customer: createCustomerRepository(commandStore),\n refreshToken: createRefreshTokenRepository(commandStore),\n order: createOrderRepository(commandStore),\n orderHistory: createOrderHistoryRepository(commandStore),\n orderRefund: createOrderRefundRepository(commandStore),\n orderSequence: createOrderSequenceRepository(commandStore),\n inventoryReservation: createInventoryReservationRepository(commandStore),\n stockAdjustment: createStockAdjustmentRepository(commandStore),\n review: createReviewRepository(commandStore),\n processedEvent: createProcessedEventRepository(commandStore),\n eventLog: createEventLogRepository(commandStore),\n cart: createCartRepository(commandStore),\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport type { NymbalEvent, NymbalEnvironment } from '@nymbalhq/types'\n\nexport interface EventBuilderContext {\n storeId: string\n environment: NymbalEnvironment\n version: string\n source?: string\n}\n\nexport interface MakeEventOptions {\n source?: string\n correlationId?: string\n timestamp?: Date\n}\n\nexport function createEventBuilder(ctx: EventBuilderContext) {\n return function makeEvent<T>(\n type: string,\n payload: T,\n options: MakeEventOptions = {},\n ): NymbalEvent<T> {\n const id = uuidv7()\n return {\n id,\n type,\n timestamp: (options.timestamp ?? new Date()).toISOString(),\n source: options.source ?? ctx.source ?? 'nymbal-platform',\n correlationId: options.correlationId ?? id,\n payload,\n metadata: {\n storeId: ctx.storeId,\n environment: ctx.environment,\n version: ctx.version,\n },\n }\n }\n}\n","import type { EventBusAdapter, NymbalEvent, NymbalEventMap, NymbalEventType } from '@nymbalhq/types'\nimport { afterCommit, type CommandStore } from '../db/command-store.js'\nimport type { EventLogRepository } from '../repositories/event-log.js'\nimport { createEventBuilder, type EventBuilderContext, type MakeEventOptions } from './builder.js'\nimport type { Relay } from './relay.js'\n\nexport interface PublishOptions extends MakeEventOptions {}\n\nexport interface EventPublisher {\n publish<E extends NymbalEventType>(\n type: E,\n payload: NymbalEventMap[E],\n options?: PublishOptions,\n ): Promise<NymbalEvent<NymbalEventMap[E]>>\n publishMany(\n events: Array<\n {\n [E in NymbalEventType]: {\n type: E\n payload: NymbalEventMap[E]\n options?: PublishOptions\n }\n }[NymbalEventType]\n >,\n ): Promise<void>\n correlated(correlationId: string): EventPublisher\n}\n\nexport interface CreatePublisherOptions {\n eventBus: EventBusAdapter\n builderContext: EventBuilderContext\n /** Events are appended to `eventLog` on this store and reach the bus only through `relay`. */\n store: CommandStore\n eventLog: EventLogRepository\n relay: Relay\n correlationId?: string\n}\n\nexport function createEventPublisher(opts: CreatePublisherOptions): EventPublisher {\n const makeEvent = createEventBuilder(opts.builderContext)\n const { store, eventLog, relay } = opts\n\n /**\n * Appends in the open transaction (same COMMIT, gone on rollback) or in one of its own, and drains the relay once\n * the outermost transaction has committed; `afterCommit` holds one drain however many publishes the transaction\n * made.\n */\n async function append(events: NymbalEvent<unknown>[]): Promise<void> {\n if (events.length === 0) return\n await store.transaction(async (tx) => {\n await eventLog.append(tx, events)\n await afterCommit(relay.drain)\n })\n }\n\n function build<E extends NymbalEventType>(\n type: E,\n payload: NymbalEventMap[E],\n options: PublishOptions = {},\n ): NymbalEvent<NymbalEventMap[E]> {\n return makeEvent(type, payload, {\n ...(opts.correlationId !== undefined && { correlationId: opts.correlationId }),\n ...options,\n })\n }\n\n return {\n async publish(type, payload, options) {\n const event = build(type, payload, options ?? {})\n await append([event])\n return event\n },\n async publishMany(events) {\n await append(events.map((e) => build(e.type, e.payload, e.options ?? {})))\n },\n correlated(correlationId) {\n return createEventPublisher({ ...opts, correlationId })\n },\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { EventBusAdapter, Logger } from '@nymbalhq/types'\nimport type { CommandStore } from '../db/command-store.js'\nimport type { EventLogRepository, LoggedEvent } from '../repositories/event-log.js'\n\n/** Hands committed events from the log to the bus. */\nexport interface Relay {\n /** Delivers every undelivered, non-dead event in `seq` order. Never rejects. */\n drain(): Promise<void>\n /** Drains on an interval (the timer does not keep the process alive). */\n start(): void\n /** Stops the interval and starts no new pass; resolves when the pass in flight, if any, has finished, so the\n * store can be closed without cutting a delivery off between the handler and its bookkeeping. */\n stop(): Promise<void>\n}\n\nexport interface CreateRelayOptions {\n store: CommandStore\n eventLog: EventLogRepository\n eventBus: EventBusAdapter\n logger: Logger\n /** Failed bus publishes after which an event is dead and never handed to the bus again. */\n maxAttempts?: number\n intervalMs?: number\n}\n\nconst PAGE_SIZE = 100\n\ninterface Deferred {\n promise: Promise<void>\n resolve(): void\n}\n\nfunction deferred(): Deferred {\n let resolve!: () => void\n const promise = new Promise<void>((r) => {\n resolve = r\n })\n return { promise, resolve }\n}\n\nexport function createRelay(opts: CreateRelayOptions): Relay {\n const { store, eventLog } = opts\n const maxAttempts = opts.maxAttempts ?? 5\n const intervalMs = opts.intervalMs ?? 10_000\n const logger = opts.logger.child({ component: 'event-relay' })\n // Set around each bus publish: a drain asked for by a subscriber (one that ran a command) must not wait for the\n // drain that is delivering to it.\n const delivering = new AsyncLocalStorage<true>()\n\n let active = false\n // Resolved when `active` turns false, i.e. after the last chained follow-up pass.\n let idle: Deferred | undefined\n let followUp: Deferred | undefined\n let timer: ReturnType<typeof setInterval> | undefined\n let stopped = false\n\n async function deliver({ event, attempts }: LoggedEvent): Promise<void> {\n try {\n // Looked up on every call: a wrapper installed on the bus instance after construction must see the event.\n await delivering.run(true, () => opts.eventBus.publish(event))\n } catch (err) {\n const at = new Date()\n await store.transaction((tx) => eventLog.recordFailure(tx, event.id, at, maxAttempts))\n const context = { err, eventId: event.id, eventType: event.type, attempts: attempts + 1 }\n if (attempts + 1 >= maxAttempts) {\n logger.error(context, 'event delivery failed for the last time; the event is dead')\n } else {\n logger.warn(context, 'event delivery failed; the event stays in the log for a later drain')\n }\n return\n }\n await store.transaction((tx) => eventLog.markDelivered(tx, [event.id], new Date()))\n }\n\n /** One pass over the log. The cursor only spans this pass: a row that commits behind it is left for the next\n * pass, which the committing transaction requests. */\n async function pass(): Promise<void> {\n try {\n let afterSeq = 0\n for (;;) {\n if (stopped) return\n const page = await store.read((tx) => eventLog.listUndelivered(tx, PAGE_SIZE, afterSeq))\n for (const logged of page) {\n if (stopped) return\n afterSeq = logged.seq\n await deliver(logged)\n }\n if (page.length < PAGE_SIZE) return\n }\n } catch (err) {\n logger.error({ err }, 'event relay pass failed; undelivered events stay in the log')\n }\n }\n\n async function run(): Promise<void> {\n active = true\n try {\n await pass()\n } finally {\n const next = followUp\n followUp = undefined\n if (next === undefined) {\n active = false\n idle?.resolve()\n idle = undefined\n } else {\n // Still active: nothing can start a second pass alongside this one.\n void run().then(next.resolve)\n }\n }\n }\n\n function request(): Promise<void> {\n if (!active) {\n idle = deferred()\n return run()\n }\n followUp ??= deferred()\n return followUp.promise\n }\n\n return {\n drain() {\n if (stopped) return Promise.resolve()\n const done = request()\n return delivering.getStore() === true ? Promise.resolve() : done\n },\n start() {\n if (timer !== undefined) return\n stopped = false\n timer = setInterval(() => void request(), intervalMs)\n timer.unref()\n },\n stop() {\n stopped = true\n if (timer !== undefined) clearInterval(timer)\n timer = undefined\n // A subscriber that stops the app would otherwise wait on the pass that is waiting on it.\n if (delivering.getStore() === true) return Promise.resolve()\n return idle?.promise ?? Promise.resolve()\n },\n }\n}\n","import type { EventHandler, Logger, NymbalEvent } from '@nymbalhq/types'\nimport type { ProcessedEventRepository } from '../repositories/processed-event.js'\n\nexport interface IdempotencyOptions {\n repo: ProcessedEventRepository\n logger?: Logger\n}\n\nexport function withIdempotency<T = unknown>(\n handlerName: string,\n handler: EventHandler<T>,\n { repo, logger }: IdempotencyOptions,\n): EventHandler<T> {\n return async (event: NymbalEvent<T>) => {\n const { store } = repo\n if (await store.read((tx) => repo.seen(tx, handlerName, event.id))) {\n logger?.debug(\n { handlerName, eventId: event.id, type: event.type },\n 'idempotency: skipping duplicate event',\n )\n return\n }\n await handler(event)\n await store.transaction((tx) => repo.markProcessed(tx, handlerName, event.id, new Date()))\n }\n}\n","import {\n EVT_CATEGORY_CREATED,\n EVT_CATEGORY_DELETED,\n EVT_CATEGORY_UPDATED,\n type CategoryCreatedV1Payload,\n type CategoryDeletedV1Payload,\n type CategoryUpdatedV1Payload,\n type DocumentStoreAdapter,\n type EventBusAdapter,\n type EventHandler,\n type Logger,\n} from '@nymbalhq/types'\n\nconst CATEGORIES = 'categories'\n\nexport interface RegisterCategoryProjectionDeps {\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n logger: Logger\n storeId: string\n}\n\nexport async function registerCategoryProjection(\n deps: RegisterCategoryProjectionDeps,\n): Promise<void> {\n const { eventBus, documentStore, logger, storeId } = deps\n\n const onUpsert: EventHandler<CategoryCreatedV1Payload | CategoryUpdatedV1Payload> = async (\n event,\n ) => {\n const { category } = event.payload\n await documentStore.put(CATEGORIES, category.slug, {\n id: category.id,\n storeId,\n parentId: category.parentId,\n slug: category.slug,\n name: category.name,\n description: category.description,\n position: category.position,\n createdAt: category.createdAt,\n })\n logger.debug({ slug: category.slug, eventType: event.type }, 'category projected')\n }\n\n const onDeleted: EventHandler<CategoryDeletedV1Payload> = async (event) => {\n await documentStore.delete(CATEGORIES, event.payload.slug)\n logger.debug({ slug: event.payload.slug }, 'category projection deleted')\n }\n\n await eventBus.subscribe([EVT_CATEGORY_CREATED, EVT_CATEGORY_UPDATED], onUpsert as EventHandler, {\n name: 'category-projection-upsert',\n derived: true,\n })\n await eventBus.subscribe(EVT_CATEGORY_DELETED, onDeleted as EventHandler, {\n name: 'category-projection-delete',\n derived: true,\n })\n}\n","import {\n EVT_PRODUCT_CREATED,\n EVT_PRODUCT_DELETED,\n EVT_PRODUCT_UPDATED,\n type DocumentStoreAdapter,\n type EventBusAdapter,\n type EventHandler,\n type Logger,\n type NymbalEvent,\n type ProductDeletedV1Payload,\n type ProductSnapshot,\n type ProductCreatedV1Payload,\n type ProductUpdatedV1Payload,\n} from '@nymbalhq/types'\n\nconst PRODUCTS = 'products'\nconst PRODUCTS_BY_CATEGORY = 'products-by-category'\n\nexport interface DenormalisedProduct {\n id: string\n storeId: string\n slug: string\n name: string\n description: string\n shortDescription: string\n status: string\n type: string\n media: unknown\n variantCount: number\n inStock: boolean\n priceRange: { minMinor: number; maxMinor: number } | null\n currency: string | null\n priceMinor: number | null\n variants: Array<{\n id: string\n sku: string\n name: string\n priceMinor: number\n stock: number\n options: unknown\n }>\n categoryIds: string[]\n categories: Array<{ id: string; name: string; slug: string }>\n createdAt: string\n updatedAt: string\n partitionKey?: string\n sortKey?: string\n}\n\nfunction denormalise(\n p: ProductSnapshot,\n storeId: string,\n storeCurrency: string,\n categories: Array<{ id: string; name: string; slug: string }>,\n): DenormalisedProduct {\n const prices = p.variants.map((v) => v.priceMinor)\n const priceRange = prices.length\n ? { minMinor: Math.min(...prices), maxMinor: Math.max(...prices) }\n : null\n const inStock = p.variants.some((v) => v.stock > 0)\n return {\n id: p.id,\n storeId,\n slug: p.slug,\n name: p.name,\n description: p.description,\n shortDescription: p.shortDescription,\n status: p.status,\n type: p.type,\n media: p.media,\n variantCount: p.variants.length,\n inStock,\n priceRange,\n currency: storeCurrency,\n priceMinor: prices[0] ?? null,\n variants: p.variants.map((v) => ({\n id: v.id,\n sku: v.sku,\n name: v.name,\n priceMinor: v.priceMinor,\n stock: v.stock,\n options: v.options,\n })),\n categoryIds: p.categoryIds,\n categories,\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n }\n}\n\nasync function resolveCategories(\n categoryIds: string[],\n documentStore: DocumentStoreAdapter,\n storeId: string,\n): Promise<Array<{ id: string; name: string; slug: string }>> {\n if (categoryIds.length === 0) return []\n const result = await documentStore.query<{ id: string; name: string; slug: string }>(\n 'categories',\n { partitionKey: { field: 'storeId', value: storeId }, limit: 500 },\n )\n const byId = new Map(result.items.map((c) => [c.id, c]))\n return categoryIds.flatMap((id) => {\n const c = byId.get(id)\n return c ? [{ id: c.id, name: c.name, slug: c.slug }] : []\n })\n}\n\nexport interface RegisterProductProjectionDeps {\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n logger: Logger\n storeId: string\n currency: string\n}\n\nexport async function registerProductProjection(\n deps: RegisterProductProjectionDeps,\n): Promise<void> {\n const { eventBus, documentStore, logger, storeId, currency } = deps\n\n const onUpsert: EventHandler<ProductCreatedV1Payload | ProductUpdatedV1Payload> = async (\n event,\n ) => {\n const { product } = event.payload\n const categories = await resolveCategories(product.categoryIds, documentStore, storeId)\n const doc = denormalise(product, storeId, currency, categories)\n await documentStore.put<DenormalisedProduct>(PRODUCTS, product.slug, doc)\n for (const cat of categories) {\n await documentStore.put(\n PRODUCTS_BY_CATEGORY,\n `category:${cat.slug}#product:${product.slug}`,\n { ...doc, partitionKey: `category:${cat.slug}`, sortKey: `product:${product.slug}` },\n )\n }\n logger.debug({ slug: product.slug, eventType: event.type }, 'product projected')\n }\n\n const onDelete: EventHandler<ProductDeletedV1Payload> = async (\n event: NymbalEvent<ProductDeletedV1Payload>,\n ) => {\n const { productId, slug } = event.payload\n const existing = await documentStore.get<DenormalisedProduct>(PRODUCTS, slug)\n if (existing) {\n const catKeys = existing.categories?.length\n ? existing.categories.map((c) => c.slug)\n : existing.categoryIds\n for (const key of catKeys) {\n await documentStore.delete(PRODUCTS_BY_CATEGORY, `category:${key}#product:${slug}`)\n }\n }\n await documentStore.delete(PRODUCTS, slug)\n logger.debug({ productId, slug }, 'product projection deleted')\n }\n\n await eventBus.subscribe([EVT_PRODUCT_CREATED, EVT_PRODUCT_UPDATED], onUpsert as EventHandler, {\n name: 'product-projection-upsert',\n derived: true,\n })\n await eventBus.subscribe(EVT_PRODUCT_DELETED, onDelete as EventHandler, {\n name: 'product-projection-delete',\n derived: true,\n })\n}\n","import {\n EVT_ORDER_CANCELLED,\n EVT_ORDER_DELIVERED,\n EVT_ORDER_PAID,\n EVT_ORDER_PARTIALLY_REFUNDED,\n EVT_ORDER_PLACED,\n EVT_ORDER_REFUNDED,\n EVT_ORDER_SHIPPED,\n type DocumentStoreAdapter,\n type EventBusAdapter,\n type EventHandler,\n type Logger,\n type Order,\n type OrderPlacedV1Payload,\n type OrderStatus,\n} from '@nymbalhq/types'\nimport type { OrderRepository } from '../../repositories/order.js'\nimport type { OrderHistoryRepository } from '../../repositories/order-history.js'\n\nconst ORDERS = 'orders'\nconst ORDERS_BY_CUSTOMER = 'orders-by-customer'\n\nfunction customerSortKey(o: Order): string {\n // descending by timestamp prefix + stable order number\n return `order:${String(\n Number.MAX_SAFE_INTEGER - new Date(String(o.createdAt)).getTime(),\n ).padStart(16, '0')}:${o.orderNumber}`\n}\n\nexport interface RegisterOrderProjectionDeps {\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n logger: Logger\n orderRepo: OrderRepository\n orderHistoryRepo: OrderHistoryRepository\n}\n\ninterface OrderDoc extends Order {\n history: Array<{\n fromStatus: OrderStatus | null\n toStatus: OrderStatus\n actor: string\n note: string\n timestamp: string\n }>\n partitionKey?: string\n sortKey?: string\n}\n\nexport async function registerOrderProjection(deps: RegisterOrderProjectionDeps): Promise<void> {\n const { eventBus, documentStore, logger, orderRepo, orderHistoryRepo } = deps\n\n async function reprojectByOrderId(orderId: string): Promise<void> {\n const found = await orderRepo.store.read(async (tx) => {\n const order = await orderRepo.findById(tx, orderId)\n return order ? { order, history: await orderHistoryRepo.listByOrder(tx, order.id) } : null\n })\n if (!found) return\n const { order, history } = found\n const doc: OrderDoc = {\n ...order,\n history: history.map((h) => ({\n fromStatus: h.fromStatus,\n toStatus: h.toStatus,\n actor: h.actor,\n note: h.note,\n timestamp: String(h.timestamp),\n })),\n }\n await documentStore.put<OrderDoc>(ORDERS, order.orderNumber, doc)\n if (order.customerId) {\n await documentStore.put<OrderDoc>(\n ORDERS_BY_CUSTOMER,\n `customer:${order.customerId}#${customerSortKey(order)}`,\n {\n ...doc,\n partitionKey: `customer:${order.customerId}`,\n sortKey: customerSortKey(order),\n },\n )\n }\n logger.debug({ orderNumber: order.orderNumber, status: order.status }, 'order projected')\n }\n\n const onPlaced: EventHandler<OrderPlacedV1Payload> = async (event) => {\n await reprojectByOrderId(event.payload.order.id)\n }\n\n const onStatusChange: EventHandler<{ orderId: string }> = async (event) => {\n await reprojectByOrderId(event.payload.orderId)\n }\n\n await eventBus.subscribe(EVT_ORDER_PLACED, onPlaced as EventHandler, {\n name: 'order-projection-placed',\n derived: true,\n })\n await eventBus.subscribe(\n [\n EVT_ORDER_PAID,\n EVT_ORDER_SHIPPED,\n EVT_ORDER_DELIVERED,\n EVT_ORDER_CANCELLED,\n EVT_ORDER_REFUNDED,\n EVT_ORDER_PARTIALLY_REFUNDED,\n ],\n onStatusChange as EventHandler,\n { name: 'order-projection-status', derived: true },\n )\n}\n","import {\n EVT_CUSTOMER_CREATED,\n EVT_CUSTOMER_DELETED,\n EVT_CUSTOMER_UPDATED,\n EVT_ORDER_PAID,\n type CustomerCreatedV1Payload,\n type CustomerDeletedV1Payload,\n type CustomerProfile,\n type DocumentStoreAdapter,\n type EventBusAdapter,\n type EventHandler,\n type Logger,\n type OrderPaidV1Payload,\n} from '@nymbalhq/types'\nimport type { CustomerRepository } from '../../repositories/customer.js'\nimport type { OrderRepository } from '../../repositories/order.js'\n\nconst COLLECTION = 'customer-profiles'\n\nexport interface RegisterCustomerProjectionDeps {\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n logger: Logger\n customerRepo: CustomerRepository\n orderRepo: OrderRepository\n}\n\nfunction profileFrom(\n customerId: string,\n orderCount: number,\n totalSpentMinor: number,\n createdAt: string,\n): CustomerProfile {\n return {\n customerId,\n orderCount,\n totalSpentMinor,\n segment:\n totalSpentMinor > 100_000\n ? 'vip'\n : orderCount > 3\n ? 'returning'\n : orderCount > 0\n ? 'active'\n : 'new',\n createdAt,\n }\n}\n\nexport async function registerCustomerProjection(\n deps: RegisterCustomerProjectionDeps,\n): Promise<void> {\n const { eventBus, documentStore, logger, customerRepo } = deps\n\n const onCreated: EventHandler<CustomerCreatedV1Payload> = async (event) => {\n const { customerId } = event.payload\n const c = await customerRepo.store.read((tx) => customerRepo.findById(tx, customerId))\n if (!c) return\n const profile = profileFrom(customerId, 0, 0, String(c.createdAt))\n await documentStore.put<CustomerProfile>(COLLECTION, customerId, profile)\n logger.debug({ customerId }, 'customer profile created')\n }\n\n const onUpdated: EventHandler<{ customerId: string }> = async (event) => {\n const { customerId } = event.payload\n const c = await customerRepo.store.read((tx) => customerRepo.findById(tx, customerId))\n if (!c) return\n await documentStore.put<CustomerProfile>(\n COLLECTION,\n c.id,\n profileFrom(c.id, c.orderCount, c.totalSpentMinor, String(c.createdAt)),\n )\n }\n\n const onDeleted: EventHandler<CustomerDeletedV1Payload> = async (event) => {\n await documentStore.delete(COLLECTION, event.payload.customerId)\n }\n\n const onOrderPaid: EventHandler<OrderPaidV1Payload> = async (event) => {\n // Bump customer stats projection via repo reload.\n // Repo has already been incremented by CheckoutService.finalize.\n // Here we just re-project.\n const { orderId } = event.payload\n const fresh = await customerRepo.store.read((tx) => customerRepo.findById(tx, orderId))\n if (!fresh) return\n await documentStore.put<CustomerProfile>(\n COLLECTION,\n fresh.id,\n profileFrom(fresh.id, fresh.orderCount, fresh.totalSpentMinor, String(fresh.createdAt)),\n )\n }\n\n await eventBus.subscribe(EVT_CUSTOMER_CREATED, onCreated as EventHandler, {\n name: 'customer-projection-created',\n derived: true,\n })\n await eventBus.subscribe(EVT_CUSTOMER_UPDATED, onUpdated as EventHandler, {\n name: 'customer-projection-updated',\n derived: true,\n })\n await eventBus.subscribe(EVT_CUSTOMER_DELETED, onDeleted as EventHandler, {\n name: 'customer-projection-deleted',\n derived: true,\n })\n await eventBus.subscribe(EVT_ORDER_PAID, onOrderPaid as EventHandler, {\n name: 'customer-projection-order-paid',\n derived: true,\n })\n}\n","import {\n EVT_INVENTORY_CHANGED,\n type DocumentStoreAdapter,\n type EventBusAdapter,\n type EventHandler,\n type InventoryChangedV1Payload,\n type Logger,\n} from '@nymbalhq/types'\nimport type { VariantRepository } from '../../repositories/variant.js'\nimport type { ProductRepository } from '../../repositories/product.js'\nimport type { ProductCategoryRepository } from '../../repositories/product-category.js'\nimport type { DenormalisedProduct } from './product-projection.js'\n\nconst PRODUCTS = 'products'\n\nexport interface RegisterInventoryProjectionDeps {\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n logger: Logger\n variantRepo: VariantRepository\n productRepo: ProductRepository\n productCategoryRepo: ProductCategoryRepository\n}\n\nexport async function registerInventoryProjection(\n deps: RegisterInventoryProjectionDeps,\n): Promise<void> {\n const { eventBus, documentStore, logger, variantRepo, productRepo } = deps\n\n const handler: EventHandler<InventoryChangedV1Payload> = async (event) => {\n const { variantId, newQty } = event.payload\n const product = await variantRepo.store.read(async (tx) => {\n const variant = await variantRepo.findById(tx, variantId)\n return variant ? productRepo.findById(tx, variant.productId) : null\n })\n if (!product) return\n const doc = await documentStore.get<DenormalisedProduct>(PRODUCTS, product.slug)\n if (!doc) return\n const variants = doc.variants.map((v) => (v.id === variantId ? { ...v, stock: newQty } : v))\n const inStock = variants.some((v) => v.stock > 0)\n await documentStore.put<DenormalisedProduct>(PRODUCTS, product.slug, {\n ...doc,\n variants,\n inStock,\n })\n logger.debug({ variantId, newQty, slug: product.slug }, 'inventory projection updated')\n }\n\n await eventBus.subscribe(EVT_INVENTORY_CHANGED, handler as EventHandler, {\n name: 'inventory-projection',\n derived: true,\n })\n}\n","import {\n EVT_CART_ABANDONED,\n EVT_CUSTOMER_CREATED,\n EVT_ORDER_PAID,\n EVT_ORDER_SHIPPED,\n type CartAbandonedV1Payload,\n type CustomerCreatedV1Payload,\n type EmailAdapter,\n type EventBusAdapter,\n type EventHandler,\n type Logger,\n type OrderPaidV1Payload,\n type OrderShippedV1Payload,\n} from '@nymbalhq/types'\nimport { formatMoney } from '../../money.js'\nimport { withIdempotency } from '../idempotency.js'\nimport type { OrderRepository } from '../../repositories/order.js'\nimport type { ProcessedEventRepository } from '../../repositories/processed-event.js'\n\n/** The handler name of the order-placed email's records: one per order, whatever number of order.paid it gets. */\nconst ORDER_PAID_EMAIL = 'email:order-paid'\n\nexport interface RegisterEmailHandlerDeps {\n eventBus: EventBusAdapter\n email: EmailAdapter\n logger: Logger\n processedEventRepo: ProcessedEventRepository\n orderRepo: OrderRepository\n storeName: string\n}\n\nexport async function registerEmailHandler(deps: RegisterEmailHandlerDeps): Promise<void> {\n const { eventBus, email, logger, processedEventRepo, orderRepo, storeName } = deps\n\n // Sent on payment, never at placement: an unpaid order (or an imported one) emails nobody. Keyed per order, so a\n // second order.paid for the order (a redelivered or replayed event) sends nothing more.\n const onOrderPaid: EventHandler<OrderPaidV1Payload> = async (event) => {\n const { orderId } = event.payload\n const { store } = processedEventRepo\n if (await store.read((tx) => processedEventRepo.seen(tx, ORDER_PAID_EMAIL, orderId))) return\n const order = await orderRepo.store.read((tx) => orderRepo.findById(tx, orderId))\n if (order === null) {\n logger.warn({ orderId, eventId: event.id }, 'email handler: paid order not found')\n return\n }\n await email.sendTransactional({\n template: 'order-placed',\n to: order.email,\n vars: {\n orderNumber: order.orderNumber,\n customerName: order.billingAddress.firstName,\n totalFormatted: formatMoney(order.totalMinor, order.currency),\n },\n })\n await store.transaction((tx) =>\n processedEventRepo.markProcessed(tx, ORDER_PAID_EMAIL, orderId, new Date()),\n )\n }\n\n const onOrderShipped: EventHandler<OrderShippedV1Payload> = async (event) => {\n logger.debug({ orderId: event.payload.orderId }, 'email handler: order shipped')\n // Need to look up customer email; skip in v0.1 (requires order repo).\n }\n\n const onCustomerCreated: EventHandler<CustomerCreatedV1Payload> = async (event) => {\n await email.sendTransactional({\n template: 'welcome',\n to: event.payload.email,\n vars: { customerName: 'there', storeName },\n })\n }\n\n const onCartAbandoned: EventHandler<CartAbandonedV1Payload> = async (event) => {\n logger.debug({ cartId: event.payload.cartId }, 'email handler: cart abandoned (stub)')\n }\n\n await eventBus.subscribe(EVT_ORDER_PAID, onOrderPaid as EventHandler, {\n name: 'email-order-paid',\n })\n await eventBus.subscribe(\n EVT_ORDER_SHIPPED,\n withIdempotency('email:order-shipped', onOrderShipped as EventHandler, {\n repo: processedEventRepo,\n logger,\n }),\n { name: 'email-order-shipped' },\n )\n await eventBus.subscribe(\n EVT_CUSTOMER_CREATED,\n withIdempotency('email:customer-created', onCustomerCreated as EventHandler, {\n repo: processedEventRepo,\n logger,\n }),\n { name: 'email-customer-created' },\n )\n await eventBus.subscribe(\n EVT_CART_ABANDONED,\n withIdempotency('email:cart-abandoned', onCartAbandoned as EventHandler, {\n repo: processedEventRepo,\n logger,\n }),\n { name: 'email-cart-abandoned' },\n )\n}\n","import {\n EVT_PRODUCT_CREATED,\n EVT_PRODUCT_DELETED,\n EVT_PRODUCT_UPDATED,\n type EventBusAdapter,\n type EventHandler,\n type ProductCreatedV1Payload,\n type ProductDeletedV1Payload,\n type ProductUpdatedV1Payload,\n type SearchAdapter,\n type SearchDocument,\n} from '@nymbalhq/types'\n\nexport interface RegisterSearchHandlerDeps {\n eventBus: EventBusAdapter\n search: SearchAdapter\n}\n\nexport async function registerSearchHandler(deps: RegisterSearchHandlerDeps): Promise<void> {\n const { eventBus, search } = deps\n\n const onUpsert: EventHandler<ProductCreatedV1Payload | ProductUpdatedV1Payload> = async (\n event,\n ) => {\n const p = event.payload.product\n const doc: SearchDocument = {\n id: p.id,\n type: 'product',\n fields: {\n slug: p.slug,\n name: p.name,\n description: p.description,\n status: p.status,\n categoryIds: p.categoryIds,\n variants: p.variants.map((v) => ({ sku: v.sku, name: v.name, priceMinor: v.priceMinor })),\n },\n }\n await search.index([doc])\n }\n\n const onDelete: EventHandler<ProductDeletedV1Payload> = async (event) => {\n await search.remove([event.payload.productId])\n }\n\n // Derived state: indexing and removing by document id is idempotent, so no processed-event record is kept, and\n // warm-up's replay rebuilds the index.\n await eventBus.subscribe([EVT_PRODUCT_CREATED, EVT_PRODUCT_UPDATED], onUpsert as EventHandler, {\n name: 'search-product-upsert',\n derived: true,\n })\n await eventBus.subscribe(EVT_PRODUCT_DELETED, onDelete as EventHandler, {\n name: 'search-product-delete',\n derived: true,\n })\n}\n","import {\n EVT_ORDER_DELIVERED,\n type EventBusAdapter,\n type EventHandler,\n type Logger,\n type OrderDeliveredV1Payload,\n type ReviewsAdapter,\n} from '@nymbalhq/types'\nimport { withIdempotency } from '../idempotency.js'\nimport type { ProcessedEventRepository } from '../../repositories/processed-event.js'\n\nexport interface RegisterReviewsHandlerDeps {\n eventBus: EventBusAdapter\n reviews: ReviewsAdapter\n logger: Logger\n processedEventRepo: ProcessedEventRepository\n}\n\nexport async function registerReviewsHandler(deps: RegisterReviewsHandlerDeps): Promise<void> {\n const { eventBus, reviews, logger, processedEventRepo } = deps\n\n const handler: EventHandler<OrderDeliveredV1Payload> = async (event) => {\n await reviews.requestReview(event.payload.orderId)\n }\n\n await eventBus.subscribe(\n EVT_ORDER_DELIVERED,\n withIdempotency('reviews:order-delivered', handler as EventHandler, {\n repo: processedEventRepo,\n logger,\n }),\n { name: 'reviews-order-delivered' },\n )\n}\n","import type { DocumentStoreAdapter, EventBusAdapter, Logger } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport type { Repositories } from '../repositories/index.js'\nimport type { AdapterRegistry } from '../adapters/registry.js'\nimport { registerCategoryProjection } from './projections/category-projection.js'\nimport { registerProductProjection } from './projections/product-projection.js'\nimport { registerOrderProjection } from './projections/order-projection.js'\nimport { registerCustomerProjection } from './projections/customer-projection.js'\nimport { registerInventoryProjection } from './projections/inventory-projection.js'\nimport { registerEmailHandler } from './side-effects/email-handler.js'\nimport { registerSearchHandler } from './side-effects/search-handler.js'\nimport { registerReviewsHandler } from './side-effects/reviews-handler.js'\n\nexport interface RegisterHandlersDeps {\n config: NymbalConfig\n eventBus: EventBusAdapter\n documentStore: DocumentStoreAdapter\n repos: Repositories\n adapters: AdapterRegistry\n logger: Logger\n}\n\nexport async function registerHandlers(deps: RegisterHandlersDeps): Promise<void> {\n const { config, eventBus, documentStore, repos, adapters, logger } = deps\n const handlerLogger = logger.child({ component: 'handlers' })\n\n await registerCategoryProjection({\n eventBus,\n documentStore,\n logger: handlerLogger.child({ projection: 'category' }),\n storeId: config.store.name,\n })\n await registerProductProjection({\n eventBus,\n documentStore,\n logger: handlerLogger.child({ projection: 'product' }),\n storeId: config.store.name,\n currency: config.store.currency,\n })\n await registerOrderProjection({\n eventBus,\n documentStore,\n logger: handlerLogger.child({ projection: 'order' }),\n orderRepo: repos.order,\n orderHistoryRepo: repos.orderHistory,\n })\n await registerCustomerProjection({\n eventBus,\n documentStore,\n logger: handlerLogger.child({ projection: 'customer' }),\n customerRepo: repos.customer,\n orderRepo: repos.order,\n })\n await registerInventoryProjection({\n eventBus,\n documentStore,\n logger: handlerLogger.child({ projection: 'inventory' }),\n variantRepo: repos.variant,\n productRepo: repos.product,\n productCategoryRepo: repos.productCategory,\n })\n\n await registerEmailHandler({\n eventBus,\n email: adapters.email,\n logger: handlerLogger.child({ handler: 'email' }),\n processedEventRepo: repos.processedEvent,\n orderRepo: repos.order,\n storeName: config.store.name,\n })\n await registerSearchHandler({\n eventBus,\n search: adapters.search,\n })\n await registerReviewsHandler({\n eventBus,\n reviews: adapters.reviews,\n logger: handlerLogger.child({ handler: 'reviews' }),\n processedEventRepo: repos.processedEvent,\n })\n\n logger.info('event handlers registered')\n}\n","import { DEFAULT_JWT_SECRET, type NymbalConfig } from '@nymbalhq/config'\nimport { ConfigError } from '@nymbalhq/types'\nimport { createPlatform, type Platform, type CreatePlatformOptions } from './platform.js'\nimport { buildRepositories, type Repositories } from './repositories/index.js'\nimport { buildAdapters, paymentsAdapterFor, type AdapterRegistry } from './adapters/registry.js'\nimport { buildServices, type ServiceRegistry } from './services/index.js'\nimport { createEventPublisher, type EventPublisher } from './events/publisher.js'\nimport { createRelay, type Relay } from './events/relay.js'\nimport { registerHandlers } from './handlers/register.js'\nimport { warmDocumentStore } from './warm-document-store.js'\nimport {\n startInventoryReservationSweeper,\n startCartAbandonmentSweeper,\n startEventRetentionSweeper,\n type SweeperHandle,\n} from './sweepers/index.js'\nimport type { HttpAdapter } from '@nymbalhq/types'\n\nexport interface NymbalApp {\n platform: Platform\n repos: Repositories\n adapters: AdapterRegistry\n services: ServiceRegistry\n publisher: EventPublisher\n /** Delivers the event log to the bus; started by createApp, stopped by stop(). */\n relay: Relay\n /**\n * Registers the API on the adapter. The admin is served at /admin/ when `adminRoot` is passed (its dist directory,\n * or null for a 404 that says how to build it) or `NYMBAL_ADMIN_DIST` is set.\n */\n attachHttp(adapter: HttpAdapter, options?: AttachHttpOptions): Promise<void>\n stop(): Promise<void>\n}\n\nexport interface AttachHttpOptions {\n adminRoot?: string | null\n}\n\nexport interface CreateAppOptions extends CreatePlatformOptions {\n version?: string\n}\n\n/**\n * A production process must not run on the stub payments adapter (its unsigned webhook confirms any order) or sign\n * tokens with the schema's published default secret. Checked before anything opens the store.\n */\nfunction refuseUnsafeProduction(config: NymbalConfig): void {\n if (process.env.NODE_ENV !== 'production') return\n const provider = config.commerce.payments.provider\n if (paymentsAdapterFor(provider) === 'native-stub') {\n throw new ConfigError(\n `Payments provider \"${provider}\" resolves to the stub adapter, which verifies no webhook signature; ` +\n 'configure a real payments provider for production.',\n { code: 'config.production_stub_payments', context: { provider } },\n )\n }\n if (config.security.auth.jwtSecret === DEFAULT_JWT_SECRET) {\n throw new ConfigError(\n 'security.auth.jwtSecret is the schema default; set a secret of your own for production.',\n { code: 'config.production_default_jwt_secret' },\n )\n }\n}\n\nexport async function createApp(\n config: NymbalConfig,\n options: CreateAppOptions = {},\n): Promise<NymbalApp> {\n refuseUnsafeProduction(config)\n const platform = createPlatform(config, options)\n const version = options.version ?? '0.1.0'\n const logger = platform.logger\n\n const repos = buildRepositories(platform.commandStore, platform.documentStore)\n const adapters = await buildAdapters({\n config,\n logger: logger.child({ layer: 'adapter' }),\n documentStore: platform.documentStore,\n repos,\n })\n const relay = createRelay({\n store: platform.commandStore,\n eventLog: repos.eventLog,\n eventBus: platform.eventBus,\n logger,\n })\n const publisher = createEventPublisher({\n eventBus: platform.eventBus,\n store: platform.commandStore,\n eventLog: repos.eventLog,\n relay,\n builderContext: {\n storeId: config.store.name,\n environment:\n process.env.NODE_ENV === 'production'\n ? 'production'\n : process.env.NODE_ENV === 'staging'\n ? 'staging'\n : 'development',\n version,\n source: 'nymbal-app',\n },\n })\n const services = buildServices({\n config,\n store: platform.commandStore,\n repos,\n publisher,\n logger: logger.child({ layer: 'service' }),\n payments: adapters.payments,\n searchAdapter: adapters.search,\n })\n\n await registerHandlers({\n config,\n eventBus: platform.eventBus,\n documentStore: platform.documentStore,\n repos,\n adapters,\n logger,\n })\n\n await warmDocumentStore({\n config,\n repos,\n eventBus: platform.eventBus,\n logger,\n version,\n })\n\n // Events committed before a crash, or whose delivery failed, go out before the app serves anything.\n await relay.drain()\n relay.start()\n\n const sweepers: SweeperHandle[] = [\n startInventoryReservationSweeper({\n inventoryService: services.inventory,\n reservationRepo: repos.inventoryReservation,\n logger,\n }),\n startCartAbandonmentSweeper({\n store: platform.commandStore,\n carts: repos.cart,\n publisher,\n logger,\n }),\n startEventRetentionSweeper({\n store: platform.commandStore,\n eventLog: repos.eventLog,\n processedEvents: repos.processedEvent,\n logger,\n }),\n ]\n\n const app: NymbalApp = {\n platform,\n repos,\n adapters,\n services,\n publisher,\n relay,\n async attachHttp(adapter, options = {}) {\n await adapters.security.applyMiddleware(adapter, config.security)\n const { registerAllRoutes } = await import('./routes/register.js')\n registerAllRoutes({\n config,\n adapter,\n services,\n adapters,\n repos,\n documentStore: platform.documentStore,\n eventBus: platform.eventBus,\n publisher,\n adminRoot:\n options.adminRoot !== undefined ? options.adminRoot : process.env['NYMBAL_ADMIN_DIST'],\n })\n },\n async stop() {\n await relay.stop()\n for (const s of sweepers) s.stop()\n await platform.close()\n },\n }\n return app\n}\n","import type { SecurityConfigLike } from '@nymbalhq/types'\n\nexport function buildSecurityHeaders(\n security: SecurityConfigLike,\n): Record<string, string> {\n const headers: Record<string, string> = {}\n if (security.headers.hsts) {\n headers['strict-transport-security'] = 'max-age=31536000; includeSubDomains'\n }\n const csp = security.headers.contentSecurityPolicy\n const cspValue =\n csp === 'strict'\n ? \"default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'\"\n : csp === 'relaxed'\n ? \"default-src 'self' https:; img-src * data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'\"\n : csp === 'off'\n ? null\n : csp\n if (cspValue) headers['content-security-policy'] = cspValue\n headers['referrer-policy'] = security.headers.referrerPolicy\n headers['x-frame-options'] = security.headers.xFrameOptions === 'deny' ? 'DENY' : 'SAMEORIGIN'\n headers['x-content-type-options'] = 'nosniff'\n return headers\n}\n\nexport const CSRF_COOKIE = 'nymbal.csrf'\nexport const CSRF_HEADER = 'x-csrf-token'\n","import type { AdapterBase, HealthReport } from '@nymbalhq/types'\n\nexport function noopInitialize(_config: unknown): Promise<void> {\n return Promise.resolve()\n}\n\nexport function okHealth(detail?: string): Promise<HealthReport> {\n const report: HealthReport = { status: 'healthy', ...(detail !== undefined && { detail }) }\n return Promise.resolve(report)\n}\n\nexport function buildBaseFields(\n capabilities: readonly string[],\n producesEvents: readonly string[],\n consumesEvents: readonly string[],\n): Omit<AdapterBase, 'initialize' | 'healthCheck'> {\n return { capabilities, producesEvents, consumesEvents }\n}\n","import type {\n HttpAdapter,\n Logger,\n SecurityAdapter,\n SecurityConfigLike,\n ValidationResult,\n} from '@nymbalhq/types'\nimport { buildSecurityHeaders } from './headers.js'\nimport { noopInitialize, okHealth } from '../base.js'\n\n/**\n * v0.1 security adapter.\n *\n * Rate limiting, CSRF verification and CSRF cookie minting need the request before\n * any middleware and the response after the handler, so the HTTP adapter runs them\n * itself on every route (`FastifyHttpAdapter`'s guard). This adapter only asserts\n * static security headers via `HttpAdapter.setDefaultHeaders(...)`. A future\n * WAF-native adapter will replace both layers.\n */\nexport function createMiddlewareSecurityAdapter(deps: { logger: Logger }): SecurityAdapter {\n const { logger } = deps\n let lastAppliedAt = ''\n return {\n capabilities: ['headers'],\n producesEvents: [],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth(),\n\n async applyMiddleware(app: HttpAdapter, config: SecurityConfigLike): Promise<void> {\n app.setDefaultHeaders(buildSecurityHeaders(config))\n lastAppliedAt = new Date().toISOString()\n logger.debug({ at: lastAppliedAt }, 'security headers attached')\n },\n\n async validate(_config): Promise<ValidationResult> {\n return { valid: true, errors: [] }\n },\n\n async inspect() {\n return {\n rulesApplied: ['headers'],\n lastValidatedAt: lastAppliedAt,\n }\n },\n }\n}\n","import Stripe from 'stripe'\nimport {\n EVT_PAYMENT_CAPTURED,\n EVT_PAYMENT_FAILED,\n EVT_PAYMENT_REFUNDED,\n PaymentError,\n type Logger,\n type PaymentCapture,\n type PaymentIntent,\n type PaymentIntentParams,\n type PaymentStatus,\n type PaymentsAdapter,\n type Refund,\n type WebhookResult,\n} from '@nymbalhq/types'\n\nexport interface StripePaymentsConfig {\n secretKey: string\n webhookSecret: string\n apiVersion?: string\n /** Override the Stripe API host (for stripe-mock style test servers). Omit in production. */\n host?: string\n /** Override the Stripe API port. Only used together with `host`. */\n port?: number\n /** Override the Stripe API protocol. Defaults to https when omitted. */\n protocol?: 'http' | 'https'\n}\n\n/**\n * Stripe returns lowercase ISO currency codes (e.g. \"gbp\"); Nymbal's canonical\n * currency format is uppercase ISO 4217 (e.g. \"GBP\") everywhere else in the\n * domain, so adapter results are normalised on the way out.\n */\nfunction toIsoCurrency(currency: string): string {\n return currency.toUpperCase()\n}\n\nfunction mapStatus(status: Stripe.PaymentIntent.Status): PaymentStatus {\n switch (status) {\n case 'requires_payment_method':\n case 'requires_confirmation':\n case 'requires_action':\n case 'processing':\n case 'requires_capture':\n case 'succeeded':\n case 'canceled':\n return status === 'canceled' ? 'cancelled' : (status as PaymentStatus)\n default:\n return 'failed'\n }\n}\n\nfunction refundStatus(status: string | null): Refund['status'] {\n if (status === 'succeeded') return 'succeeded'\n if (status === 'failed' || status === 'canceled') return 'failed'\n return 'pending'\n}\n\n/**\n * Stripe refused the refund outright (a card error, an invalid request): no money moved. Anything else (an API error,\n * a timeout, a dropped connection) leaves the outcome unknown.\n */\nfunction isDefiniteRefusal(err: unknown): boolean {\n const type = (err as { type?: unknown } | null)?.type\n return type === 'StripeCardError' || type === 'StripeInvalidRequestError'\n}\n\nfunction toIntent(intent: Stripe.PaymentIntent): PaymentIntent {\n return {\n id: intent.id,\n clientSecret: intent.client_secret ?? '',\n amountMinor: intent.amount,\n currency: toIsoCurrency(intent.currency),\n status: mapStatus(intent.status),\n }\n}\n\nexport function createStripePaymentsAdapter(deps: {\n logger: Logger\n config: StripePaymentsConfig\n}): PaymentsAdapter {\n const { logger } = deps\n const cfg = deps.config\n if (!cfg.secretKey) throw new PaymentError('not_configured', 'Stripe secretKey missing')\n if (!cfg.webhookSecret) throw new PaymentError('not_configured', 'Stripe webhookSecret missing')\n const stripeClient = new Stripe(cfg.secretKey, {\n ...(cfg.apiVersion !== undefined && {\n apiVersion: cfg.apiVersion as Stripe.LatestApiVersion,\n }),\n ...(cfg.host !== undefined && { host: cfg.host }),\n ...(cfg.port !== undefined && { port: cfg.port }),\n ...(cfg.protocol !== undefined && { protocol: cfg.protocol }),\n })\n return {\n kind: 'payments',\n providerName: 'stripe',\n capabilities: ['intent', 'capture', 'refund', 'webhook'],\n producesEvents: [EVT_PAYMENT_CAPTURED, EVT_PAYMENT_FAILED, EVT_PAYMENT_REFUNDED],\n consumesEvents: [],\n async initialize() {\n // no-op: Stripe client already constructed\n },\n async healthCheck() {\n try {\n await stripeClient.balance.retrieve()\n return { status: 'healthy' }\n } catch (err) {\n return {\n status: 'down',\n detail: err instanceof Error ? err.message : String(err),\n }\n }\n },\n async createPaymentIntent(params: PaymentIntentParams): Promise<PaymentIntent> {\n try {\n const intent = await stripeClient.paymentIntents.create({\n amount: params.amountMinor,\n currency: params.currency.toLowerCase(),\n automatic_payment_methods: { enabled: true },\n ...(params.receiptEmail !== undefined && { receipt_email: params.receiptEmail }),\n metadata: {\n ...(params.metadata ?? {}),\n ...(params.orderRef !== undefined ? { orderRef: params.orderRef } : {}),\n ...(params.customerId !== undefined ? { customerId: params.customerId } : {}),\n },\n })\n return toIntent(intent)\n } catch (err) {\n throw new PaymentError('intent_failed', 'Stripe createPaymentIntent failed', { cause: err })\n }\n },\n async capturePayment(intentId, amountMinor): Promise<PaymentCapture> {\n try {\n const captured = await stripeClient.paymentIntents.capture(intentId, {\n ...(amountMinor !== undefined && { amount_to_capture: amountMinor }),\n })\n return {\n paymentId: captured.id,\n capturedAmountMinor: captured.amount_received ?? captured.amount,\n currency: toIsoCurrency(captured.currency),\n status: mapStatus(captured.status),\n }\n } catch (err) {\n throw new PaymentError('capture_failed', 'Stripe capturePayment failed', { cause: err })\n }\n },\n async refund(paymentId, amountMinor, reason, opts): Promise<Refund> {\n const params: Stripe.RefundCreateParams = {\n payment_intent: paymentId,\n ...(amountMinor !== undefined && { amount: amountMinor }),\n ...(reason !== undefined && { reason: reason as Stripe.RefundCreateParams.Reason }),\n }\n try {\n const refund =\n opts?.idempotencyKey === undefined\n ? await stripeClient.refunds.create(params)\n : await stripeClient.refunds.create(params, { idempotencyKey: opts.idempotencyKey })\n return {\n refundId: refund.id,\n paymentId,\n amountMinor: refund.amount,\n currency: toIsoCurrency(refund.currency),\n reason: refund.reason ?? null,\n status: refundStatus(refund.status),\n }\n } catch (err) {\n if (isDefiniteRefusal(err)) {\n throw new PaymentError('refund_rejected', 'Stripe refused the refund', { cause: err })\n }\n throw new PaymentError('refund_unknown', 'Stripe refund outcome unknown', { cause: err })\n }\n },\n async getPaymentStatus(intentId): Promise<PaymentStatus> {\n const intent = await stripeClient.paymentIntents.retrieve(intentId)\n return mapStatus(intent.status)\n },\n async getPaymentIntent(intentId): Promise<PaymentIntent> {\n try {\n return toIntent(await stripeClient.paymentIntents.retrieve(intentId))\n } catch (err) {\n throw new PaymentError('intent_failed', 'Stripe getPaymentIntent failed', { cause: err })\n }\n },\n async cancelPaymentIntent(intentId): Promise<void> {\n try {\n await stripeClient.paymentIntents.cancel(intentId)\n } catch (err) {\n // A cancel that lost a race with an earlier one of ours is done; anything else (processing, captured) stays.\n const status = await stripeClient.paymentIntents\n .retrieve(intentId)\n .then((intent) => intent.status)\n .catch(() => undefined)\n if (status === 'canceled') return\n throw new PaymentError('cancel_refused', `Stripe would not cancel ${intentId}`, {\n cause: err,\n })\n }\n },\n async parseWebhook(rawBody, signature): Promise<WebhookResult> {\n let event: Stripe.Event\n try {\n event = stripeClient.webhooks.constructEvent(rawBody, signature, cfg.webhookSecret)\n } catch (err) {\n throw new PaymentError('webhook_invalid', 'Stripe webhook signature invalid', {\n cause: err,\n })\n }\n const baseResult = { verified: true, eventId: event.id } as const\n switch (event.type) {\n case 'payment_intent.succeeded': {\n const intent = event.data.object as Stripe.PaymentIntent\n return {\n ...baseResult,\n kind: 'payment.captured',\n paymentIntentId: intent.id,\n amountMinor: intent.amount_received ?? intent.amount,\n currency: toIsoCurrency(intent.currency),\n raw: { ...intent } as unknown as Record<string, unknown>,\n }\n }\n case 'payment_intent.payment_failed': {\n const intent = event.data.object as Stripe.PaymentIntent\n return {\n ...baseResult,\n kind: 'payment.failed',\n paymentIntentId: intent.id,\n reason: intent.last_payment_error?.message ?? 'payment failed',\n }\n }\n case 'charge.refunded': {\n const charge = event.data.object as Stripe.Charge\n const pi =\n typeof charge.payment_intent === 'string'\n ? charge.payment_intent\n : charge.payment_intent?.id\n return {\n ...baseResult,\n kind: 'payment.refunded',\n ...(pi !== undefined && { paymentIntentId: pi }),\n amountMinor: charge.amount_refunded,\n currency: toIsoCurrency(charge.currency),\n }\n }\n default:\n logger.debug({ type: event.type }, 'stripe webhook ignored')\n return { ...baseResult, kind: 'ignored' }\n }\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_PAYMENT_CAPTURED,\n EVT_PAYMENT_FAILED,\n EVT_PAYMENT_REFUNDED,\n PaymentError,\n type Logger,\n type PaymentCapture,\n type PaymentIntent,\n type PaymentIntentParams,\n type PaymentStatus,\n type PaymentsAdapter,\n type Refund,\n type WebhookResult,\n} from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\ninterface StubIntent {\n id: string\n amountMinor: number\n currency: string\n status: PaymentStatus\n orderRef?: string\n refundedMinor: number\n}\n\nconst STUB_ID_PREFIX = 'pi_stub_'\n\nfunction rejected(message: string): PaymentError {\n return new PaymentError('refund_rejected', message)\n}\n\n/**\n * Like Stripe's test cards, the receipt email's local part picks the outcome: ending `+stub-pending` the intent waits\n * for the shopper (a webhook pays it), ending `+stub-decline` it fails, and otherwise it is captured at creation.\n */\nfunction statusFor(receiptEmail: string | undefined): PaymentStatus {\n const address = receiptEmail ?? ''\n const at = address.lastIndexOf('@')\n const local = at < 0 ? address : address.slice(0, at)\n if (local.endsWith('+stub-pending')) return 'requires_action'\n if (local.endsWith('+stub-decline')) return 'failed'\n return 'succeeded'\n}\n\nfunction toIntent(intent: StubIntent): PaymentIntent {\n return {\n id: intent.id,\n clientSecret: `${intent.id}_secret`,\n amountMinor: intent.amountMinor,\n currency: intent.currency,\n status: intent.status,\n }\n}\n\n/**\n * Deterministic payments adapter for local development without Stripe keys.\n * Every intent succeeds at creation unless the receipt email asks otherwise (`statusFor`); webhook verification is a\n * no-op. Refunds follow a provider's rules for the intents this process holds (captured, and never beyond the\n * capture); an intent of its own lost to a restart is refunded as asked, the shop's refundable check being the guard.\n */\nexport function createNativeStubPaymentsAdapter(deps: { logger: Logger }): PaymentsAdapter {\n const { logger } = deps\n const intents = new Map<string, StubIntent>()\n return {\n kind: 'payments',\n providerName: 'native-stub',\n capabilities: ['intent', 'capture', 'refund', 'webhook'],\n producesEvents: [EVT_PAYMENT_CAPTURED, EVT_PAYMENT_FAILED, EVT_PAYMENT_REFUNDED],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth('stub — always healthy'),\n\n async createPaymentIntent(params: PaymentIntentParams): Promise<PaymentIntent> {\n const id = `${STUB_ID_PREFIX}${uuidv7()}`\n const intent: StubIntent = {\n id,\n amountMinor: params.amountMinor,\n currency: params.currency,\n status: statusFor(params.receiptEmail),\n refundedMinor: 0,\n ...(params.orderRef !== undefined && { orderRef: params.orderRef }),\n }\n intents.set(id, intent)\n logger.debug({ intentId: id, status: intent.status }, 'stub payment intent created')\n return toIntent(intent)\n },\n\n async capturePayment(intentId): Promise<PaymentCapture> {\n const intent = intents.get(intentId)\n if (!intent) throw new PaymentError('capture_failed', `unknown intent ${intentId}`)\n intent.status = 'succeeded'\n return {\n paymentId: intent.id,\n capturedAmountMinor: intent.amountMinor,\n currency: intent.currency,\n status: 'succeeded',\n }\n },\n\n async refund(paymentId, amountMinor, reason, opts): Promise<Refund> {\n if (!paymentId.startsWith(STUB_ID_PREFIX)) throw rejected(`${paymentId} is not a stub intent`)\n const answer = (amount: number, currency: string): Refund => ({\n refundId: `re_stub_${uuidv7()}`,\n paymentId,\n amountMinor: amount,\n currency,\n reason: reason ?? null,\n status: 'succeeded',\n })\n const intent = intents.get(paymentId)\n if (!intent) {\n if (amountMinor === undefined || amountMinor <= 0 || opts?.currency === undefined) {\n throw rejected(`intent ${paymentId} is no longer held: name the amount and currency`)\n }\n return answer(amountMinor, opts.currency)\n }\n if (intent.status !== 'succeeded') throw rejected(`intent ${paymentId} was never captured`)\n const left = intent.amountMinor - intent.refundedMinor\n const amount = amountMinor ?? left\n if (amount <= 0 || amount > left) {\n throw rejected(`refund of ${amount} exceeds the ${left} left on intent ${paymentId}`)\n }\n intent.refundedMinor += amount\n return answer(amount, intent.currency)\n },\n\n async getPaymentStatus(intentId) {\n return intents.get(intentId)?.status ?? 'failed'\n },\n\n async getPaymentIntent(intentId): Promise<PaymentIntent> {\n const intent = intents.get(intentId)\n if (!intent) throw new PaymentError('intent_failed', `unknown intent ${intentId}`)\n return toIntent(intent)\n },\n\n async cancelPaymentIntent(intentId): Promise<void> {\n // An intent this process never made (it restarted) cannot be paid through the stub: nothing to cancel.\n const intent = intents.get(intentId)\n if (!intent) return\n if (intent.status === 'succeeded') {\n throw new PaymentError('cancel_refused', `intent ${intentId} is already captured`)\n }\n intent.status = 'cancelled'\n },\n\n async parseWebhook(rawBody): Promise<WebhookResult> {\n try {\n const body = typeof rawBody === 'string' ? rawBody : rawBody.toString('utf8')\n const event = JSON.parse(body) as {\n id?: string\n kind?: WebhookResult['kind']\n paymentIntentId?: string\n amountMinor?: number\n currency?: string\n }\n // A stub webhook stands in for the shopper paying a waiting intent: the stub now holds it captured.\n const held =\n event.paymentIntentId === undefined ? undefined : intents.get(event.paymentIntentId)\n if (held !== undefined && event.kind === 'payment.captured') held.status = 'succeeded'\n return {\n verified: true,\n eventId: event.id ?? `evt_stub_${uuidv7()}`,\n kind: event.kind ?? 'ignored',\n ...(event.paymentIntentId !== undefined && { paymentIntentId: event.paymentIntentId }),\n ...(event.amountMinor !== undefined && { amountMinor: event.amountMinor }),\n ...(event.currency !== undefined && { currency: event.currency }),\n }\n } catch (err) {\n throw new PaymentError('webhook_invalid', 'stub webhook body not JSON', { cause: err })\n }\n },\n }\n}\n","import nodemailer, { type Transporter } from 'nodemailer'\nimport {\n AdapterError,\n EVT_CART_ABANDONED,\n EVT_CUSTOMER_CREATED,\n EVT_ORDER_PLACED,\n EVT_ORDER_SHIPPED,\n type CustomerProfile,\n type EmailAdapter,\n type Logger,\n type TransactionalEmail,\n} from '@nymbalhq/types'\nimport { okHealth } from '../base.js'\nimport { renderTemplate } from './templates.js'\n\nexport interface NativeEmailAdapterConfig {\n transport?: 'console' | 'smtp'\n from?: string\n smtp?: {\n host: string\n port: number\n user?: string\n pass?: string\n secure?: boolean\n }\n}\n\nexport function createNativeEmailAdapter(deps: {\n logger: Logger\n config?: NativeEmailAdapterConfig\n}): EmailAdapter {\n const log = deps.logger.child({ adapter: 'email', provider: 'native' })\n let cfg: NativeEmailAdapterConfig = deps.config ?? { transport: 'console' }\n let transporter: Transporter | null = null\n\n function ensureTransport(): void {\n if (cfg.transport !== 'smtp') return\n if (transporter) return\n if (!cfg.smtp) {\n throw new AdapterError('email.misconfigured', 'SMTP transport selected but smtp.host not set')\n }\n transporter = nodemailer.createTransport({\n host: cfg.smtp.host,\n port: cfg.smtp.port,\n secure: cfg.smtp.secure ?? cfg.smtp.port === 465,\n ...(cfg.smtp.user !== undefined && cfg.smtp.pass !== undefined\n ? { auth: { user: cfg.smtp.user, pass: cfg.smtp.pass } }\n : {}),\n })\n }\n\n return {\n kind: 'email',\n providerName: 'native',\n capabilities: ['transactional', 'list-sync'],\n producesEvents: [],\n consumesEvents: [\n EVT_ORDER_PLACED,\n EVT_ORDER_SHIPPED,\n EVT_CUSTOMER_CREATED,\n EVT_CART_ABANDONED,\n ],\n async initialize(rawConfig) {\n cfg = { ...cfg, ...(rawConfig as NativeEmailAdapterConfig) }\n if (cfg.transport === 'smtp') ensureTransport()\n },\n async healthCheck() {\n if (cfg.transport === 'smtp' && transporter) {\n try {\n await transporter.verify()\n return { status: 'healthy', detail: 'SMTP verified' }\n } catch (err) {\n return {\n status: 'degraded',\n detail: `SMTP verify failed: ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n return okHealth('console transport')\n },\n\n async sendTransactional(params: TransactionalEmail) {\n const rendered = renderTemplate(params.template, params.vars)\n if (cfg.transport === 'smtp') {\n ensureTransport()\n if (!transporter) {\n throw new AdapterError('email.transport_missing', 'SMTP transport not initialised')\n }\n const info = await transporter.sendMail({\n from: cfg.from ?? 'no-reply@nymbal.dev',\n to: params.to,\n subject: rendered.subject,\n text: rendered.text,\n html: rendered.html,\n })\n return { messageId: info.messageId ?? null, accepted: (info.accepted ?? []).length > 0 }\n }\n log.info(\n { to: params.to, subject: rendered.subject, template: params.template },\n 'email.sent (console)',\n )\n log.debug({ body: rendered.text }, 'email body')\n return { messageId: null, accepted: true }\n },\n\n async syncCustomerToList(customer: CustomerProfile) {\n log.debug({ customerId: customer.customerId }, 'email.syncCustomerToList (stub)')\n },\n\n async removeCustomerFromList(customerId: string) {\n log.debug({ customerId }, 'email.removeCustomerFromList (stub)')\n },\n }\n}\n","export interface RenderedEmail {\n subject: string\n text: string\n html: string\n}\n\nfunction render(template: string, vars: Record<string, unknown>): string {\n return template.replace(/\\{\\{\\s*([\\w.]+)\\s*\\}\\}/g, (_, path: string) => {\n const parts = path.split('.')\n let cur: unknown = vars\n for (const p of parts) {\n if (cur && typeof cur === 'object' && p in (cur as Record<string, unknown>)) {\n cur = (cur as Record<string, unknown>)[p]\n } else {\n return ''\n }\n }\n return cur == null ? '' : String(cur)\n })\n}\n\nconst TEMPLATES: Record<string, { subject: string; body: string }> = {\n 'order-placed': {\n subject: 'Order {{orderNumber}} confirmed',\n body: `Hi {{customerName}},\\n\\nThank you for your order {{orderNumber}}. Total: {{totalFormatted}}.\\n\\nWe'll let you know when it ships.`,\n },\n 'order-shipped': {\n subject: 'Order {{orderNumber}} is on its way',\n body: `Hi {{customerName}},\\n\\nYour order {{orderNumber}} has shipped via {{carrier}}.\\nTracking: {{trackingNumber}}`,\n },\n welcome: {\n subject: 'Welcome to {{storeName}}',\n body: `Welcome {{customerName}}! Your account is ready.`,\n },\n 'cart-abandoned': {\n subject: \"Don't forget your cart at {{storeName}}\",\n body: `Hi,\\n\\nYou left items in your cart. Pick up where you left off: {{resumeUrl}}`,\n },\n}\n\nexport function renderTemplate(template: string, vars: Record<string, unknown>): RenderedEmail {\n const t = TEMPLATES[template]\n if (!t) {\n return {\n subject: `[nymbal] ${template}`,\n text: JSON.stringify(vars),\n html: `<pre>${JSON.stringify(vars, null, 2)}</pre>`,\n }\n }\n const subject = render(t.subject, vars)\n const text = render(t.body, vars)\n const html = `<pre>${text.replace(/</g, '<')}</pre>`\n return { subject, text, html }\n}\n","import {\n EVT_PRODUCT_CREATED,\n EVT_PRODUCT_DELETED,\n EVT_PRODUCT_UPDATED,\n type DocumentStoreAdapter,\n type Facet,\n type IndexResult,\n type Logger,\n type SearchAdapter,\n type SearchResult,\n} from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\nconst INDEX_COLLECTION = 'search-index'\n\ninterface IndexedDoc {\n id: string\n type: string\n fields: Record<string, unknown>\n text: string\n}\n\nfunction flatten(value: unknown): string {\n if (value == null) return ''\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return String(value)\n }\n if (Array.isArray(value)) return value.map(flatten).join(' ')\n if (typeof value === 'object') {\n return Object.values(value).map(flatten).join(' ')\n }\n return ''\n}\n\nexport function createNativeSearchAdapter(deps: {\n documentStore: DocumentStoreAdapter\n logger: Logger\n}): SearchAdapter {\n const { documentStore, logger } = deps\n return {\n kind: 'search',\n providerName: 'native',\n capabilities: ['index', 'search', 'facet'],\n producesEvents: [],\n consumesEvents: [EVT_PRODUCT_CREATED, EVT_PRODUCT_UPDATED, EVT_PRODUCT_DELETED],\n initialize: noopInitialize,\n healthCheck: () => okHealth(),\n\n async index(documents) {\n const entries = new Map<string, IndexedDoc>()\n for (const doc of documents) {\n entries.set(doc.id, {\n id: doc.id,\n type: doc.type,\n fields: doc.fields,\n text: flatten(doc.fields).toLowerCase(),\n })\n }\n await documentStore.batchPut(INDEX_COLLECTION, entries)\n logger.debug({ count: documents.length }, 'search.index')\n return { indexed: documents.length } satisfies IndexResult\n },\n\n async remove(ids) {\n for (const id of ids) {\n await documentStore.delete(INDEX_COLLECTION, id)\n }\n },\n\n async search(query, params) {\n const q = query.trim().toLowerCase()\n const limit = params?.limit ?? 20\n const result = await documentStore.query<IndexedDoc>(INDEX_COLLECTION, {\n partitionKey: { field: 'type', value: 'product' },\n limit: 1000,\n })\n const filtered = result.items.filter((item) => {\n if (!q) return true\n if (!item.text.includes(q)) return false\n for (const [k, v] of Object.entries(params?.filters ?? {})) {\n const field = (item.fields as Record<string, unknown>)[k]\n if (field !== v) return false\n }\n return true\n })\n return {\n items: filtered.slice(0, limit).map((it) => ({\n id: it.id,\n type: it.type,\n fields: it.fields,\n })),\n total: filtered.length,\n nextCursor: null,\n } satisfies SearchResult\n },\n\n async facet(field) {\n const result = await documentStore.query<IndexedDoc>(INDEX_COLLECTION, {\n partitionKey: { field: 'type', value: 'product' },\n limit: 1000,\n })\n const counts = new Map<string, number>()\n for (const item of result.items) {\n const raw = (item.fields as Record<string, unknown>)[field]\n if (raw == null) continue\n const vals = Array.isArray(raw) ? raw : [raw]\n for (const v of vals) {\n const key = String(v)\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n }\n const label = field.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase())\n return {\n field,\n label,\n values: [...counts.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([value, count]) => ({ value, count })),\n } satisfies Facet\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_ORDER_DELIVERED,\n type AggregateRating,\n type Logger,\n type ReviewsAdapter,\n type ReviewsResult,\n type ReviewResult,\n type ReviewSubmission,\n type Review,\n} from '@nymbalhq/types'\nimport type { Repositories } from '../../repositories/index.js'\nimport { noopInitialize, okHealth } from '../base.js'\n\nexport function createNativeReviewsAdapter(deps: {\n repos: Repositories\n logger: Logger\n}): ReviewsAdapter {\n const { repos, logger } = deps\n return {\n kind: 'reviews',\n providerName: 'native',\n capabilities: ['submit', 'moderate', 'aggregate'],\n producesEvents: [],\n consumesEvents: [EVT_ORDER_DELIVERED],\n initialize: noopInitialize,\n healthCheck: () => okHealth(),\n\n async getProductReviews(productId, params) {\n const limit = params?.limit ?? 20\n const items = await repos.review.store.read((tx) =>\n repos.review.listByProduct(tx, productId, params?.status ?? 'approved', limit),\n )\n return { items, nextCursor: null } satisfies ReviewsResult\n },\n\n async getAggregateRating(productId): Promise<AggregateRating> {\n const agg = await repos.review.store.read((tx) =>\n repos.review.aggregateByProduct(tx, productId),\n )\n return { productId, ...agg }\n },\n\n async submitReview(submission: ReviewSubmission): Promise<ReviewResult> {\n const id = uuidv7()\n const now = new Date()\n const review = await repos.review.store.transaction(async (tx) => {\n await repos.review.insert(tx, {\n id,\n productId: submission.productId,\n customerId: submission.customerId,\n orderId: submission.orderId,\n rating: submission.rating,\n title: submission.title,\n body: submission.body,\n moderationStatus: 'pending',\n submittedAt: now,\n })\n return (await repos.review.findById(tx, id)) as Review\n })\n logger.debug({ id, productId: submission.productId }, 'review submitted — pending moderation')\n return { review }\n },\n\n async requestReview(orderId) {\n logger.info({ orderId }, 'review requested (stub: no-op email)')\n },\n }\n}\n","import type { AnalyticsAdapter, Logger } from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\nexport function createNativeAnalyticsAdapter(logger: Logger): AnalyticsAdapter {\n const log = logger.child({ adapter: 'analytics', provider: 'native' })\n return {\n kind: 'analytics',\n providerName: 'native',\n capabilities: ['track', 'identify'],\n producesEvents: [],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth(),\n async track(event, properties) {\n log.debug({ event, properties }, 'analytics.track')\n },\n async identify(userId, traits) {\n log.debug({ userId, traits }, 'analytics.identify')\n },\n }\n}\n","import type { Logger, ShippingAdapter } from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\nexport function createNativeShippingAdapter(logger: Logger): ShippingAdapter {\n const log = logger.child({ adapter: 'shipping', provider: 'native' })\n return {\n kind: 'shipping',\n providerName: 'native',\n capabilities: ['flat-rate'],\n producesEvents: [],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth(),\n async rate(params) {\n log.debug({ params }, 'shipping.rate')\n return [\n {\n carrier: 'native',\n service: 'standard',\n amountMinor: 500,\n currency: params.currency,\n estimatedDays: 5,\n },\n ]\n },\n async createLabel(params) {\n log.info({ params }, 'shipping.createLabel (stub)')\n return {\n labelUrl: `data:text/plain,order:${params.orderId}`,\n trackingNumber: `NATIVE-${params.orderId.slice(0, 8)}`,\n carrier: params.carrier,\n }\n },\n async track(_trackingNumber) {\n return {\n status: 'in_transit',\n lastUpdateAt: new Date().toISOString(),\n }\n },\n }\n}\n","import type { Logger, TaxAdapter } from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\nexport function createNativeTaxAdapter(logger: Logger, defaultRate = 0): TaxAdapter {\n return {\n kind: 'tax',\n providerName: 'native',\n capabilities: ['flat-rate'],\n producesEvents: [],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth(),\n async calculate(params) {\n const ratePerLine = params.lines.map((l) => ({\n taxMinor: Math.round(l.amountMinor * l.qty * defaultRate),\n }))\n const totalTaxMinor = ratePerLine.reduce((s, l) => s + l.taxMinor, 0)\n logger.debug({ defaultRate, totalTaxMinor }, 'tax.calculate')\n return { totalTaxMinor, ratePerLine }\n },\n }\n}\n","import type { AiAdapter, Logger } from '@nymbalhq/types'\nimport { AdapterError } from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\nexport function createNativeAiAdapter(_logger: Logger): AiAdapter {\n return {\n kind: 'ai',\n providerName: 'native',\n capabilities: [],\n producesEvents: [],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth('AI adapter is stubbed — configure a real provider for v1.0'),\n async embed() {\n throw new AdapterError('not_configured', 'AI embedding is not configured in v0.1')\n },\n async complete() {\n throw new AdapterError('not_configured', 'AI completion is not configured in v0.1')\n },\n }\n}\n","import Anthropic from '@anthropic-ai/sdk'\nimport type { AiAdapter, Logger } from '@nymbalhq/types'\nimport { AdapterError } from '@nymbalhq/types'\nimport { noopInitialize, okHealth } from '../base.js'\n\nexport interface AnthropicAiAdapterConfig {\n apiKey: string\n model?: string\n logger: Logger\n}\n\nexport function createAnthropicAiAdapter(config: AnthropicAiAdapterConfig): AiAdapter {\n const model = config.model ?? 'claude-sonnet-4-6'\n const client = new Anthropic({ apiKey: config.apiKey })\n\n return {\n kind: 'ai',\n providerName: 'anthropic',\n capabilities: ['complete'],\n producesEvents: [],\n consumesEvents: [],\n initialize: noopInitialize,\n healthCheck: () => okHealth(`Anthropic AI adapter using model ${model}`),\n\n async embed() {\n throw new AdapterError('not_configured', 'Embedding not yet supported by the Anthropic adapter')\n },\n\n async complete(prompt, opts) {\n const maxTokens = opts?.maxTokens ?? 1024\n const message = await client.messages.create({\n model,\n max_tokens: maxTokens,\n messages: [{ role: 'user', content: prompt }],\n })\n const block = message.content[0]\n if (!block || block.type !== 'text') {\n throw new AdapterError('unexpected_response', 'Anthropic returned no text content')\n }\n return block.text\n },\n }\n}\n","import type {\n AnalyticsAdapter,\n AiAdapter,\n DocumentStoreAdapter,\n EmailAdapter,\n Logger,\n PaymentsAdapter,\n ReviewsAdapter,\n SearchAdapter,\n SecurityAdapter,\n ShippingAdapter,\n TaxAdapter,\n} from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport type { Repositories } from '../repositories/index.js'\nimport { createMiddlewareSecurityAdapter } from './security/middleware-adapter.js'\nimport {\n createStripePaymentsAdapter,\n type StripePaymentsConfig,\n} from './payments/stripe-adapter.js'\nimport { createNativeStubPaymentsAdapter } from './payments/native-stub.js'\nimport {\n createNativeEmailAdapter,\n type NativeEmailAdapterConfig,\n} from './email/native-email-adapter.js'\nimport { createNativeSearchAdapter } from './search/native-adapter.js'\nimport { createNativeReviewsAdapter } from './reviews/native-adapter.js'\nimport { createNativeAnalyticsAdapter } from './analytics/native-adapter.js'\nimport { createNativeShippingAdapter } from './shipping/native-adapter.js'\nimport { createNativeTaxAdapter } from './tax/native-adapter.js'\nimport { createNativeAiAdapter } from './ai/native-adapter.js'\nimport { createAnthropicAiAdapter } from './ai/anthropic-adapter.js'\n\nexport interface AdapterRegistry {\n security: SecurityAdapter\n payments: PaymentsAdapter\n email: EmailAdapter\n search: SearchAdapter\n reviews: ReviewsAdapter\n analytics: AnalyticsAdapter\n shipping: ShippingAdapter\n tax: TaxAdapter\n ai: AiAdapter\n}\n\nexport interface BuildAdaptersDeps {\n config: NymbalConfig\n logger: Logger\n documentStore: DocumentStoreAdapter\n repos: Repositories\n}\n\n/**\n * The `providerName` of the payments adapter a configured provider resolves to. A provider with no adapter of its\n * own falls back to the stub, which verifies no webhook signature.\n */\nexport function paymentsAdapterFor(provider: string): 'stripe' | 'native-stub' {\n return provider === 'stripe' ? 'stripe' : 'native-stub'\n}\n\nexport async function buildAdapters(deps: BuildAdaptersDeps): Promise<AdapterRegistry> {\n const { config, logger, documentStore, repos } = deps\n const payments: PaymentsAdapter =\n paymentsAdapterFor(config.commerce.payments.provider) === 'stripe'\n ? createStripePaymentsAdapter({\n logger: logger.child({ adapter: 'payments' }),\n config: (config.commerce.payments.config ?? {}) as unknown as StripePaymentsConfig,\n })\n : createNativeStubPaymentsAdapter({ logger: logger.child({ adapter: 'payments' }) })\n\n const email: EmailAdapter = createNativeEmailAdapter({\n logger: logger.child({ adapter: 'email' }),\n config: (config.commerce.email.config ?? {}) as NativeEmailAdapterConfig,\n })\n await email.initialize(email ? (config.commerce.email.config ?? {}) : {})\n\n const search = createNativeSearchAdapter({\n documentStore,\n logger: logger.child({ adapter: 'search' }),\n })\n\n const reviews = createNativeReviewsAdapter({\n repos,\n logger: logger.child({ adapter: 'reviews' }),\n })\n\n const analytics = createNativeAnalyticsAdapter(logger)\n const shipping = createNativeShippingAdapter(logger)\n const tax = createNativeTaxAdapter(logger)\n const aiProvider = config.commerce.ai?.provider\n const ai: AiAdapter =\n aiProvider === 'anthropic'\n ? createAnthropicAiAdapter({\n apiKey: process.env['ANTHROPIC_API_KEY'] ?? '',\n model:\n (config.commerce.ai?.config?.['model'] as string | undefined) ?? 'claude-sonnet-4-6',\n logger: logger.child({ adapter: 'ai' }),\n })\n : createNativeAiAdapter(logger)\n const security = createMiddlewareSecurityAdapter({\n logger: logger.child({ adapter: 'security' }),\n })\n\n return { security, payments, email, search, reviews, analytics, shipping, tax, ai }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_PRODUCT_CREATED,\n EVT_PRODUCT_UPDATED,\n EVT_PRODUCT_DELETED,\n EVT_PRODUCT_PUBLISHED,\n EVT_PRODUCT_UNPUBLISHED,\n NotFoundError,\n ValidationError,\n type Product,\n type ProductStatus,\n type Variant,\n type ProductSnapshot,\n type Logger,\n} from '@nymbalhq/types'\nimport type { CommandStore, ReadTx } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { ProductInsert, ProductUpdate } from '../repositories/product.js'\nimport type { VariantInsert } from '../repositories/variant.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nexport interface ProductCreateInput {\n slug: string\n name: string\n description?: string\n shortDescription?: string\n status?: ProductStatus\n type?: 'simple' | 'variable'\n seoTitle?: string\n seoDescription?: string\n media?: Product['media']\n metadata?: Record<string, unknown>\n categoryIds?: string[]\n variants?: Array<\n Omit<VariantInsert, 'id' | 'productId' | 'createdAt' | 'updatedAt'> & { id?: string }\n >\n}\n\nexport interface ProductUpdateInput extends Omit<ProductUpdate, 'updatedAt'> {\n categoryIds?: string[]\n}\n\nexport interface ProductService {\n create(input: ProductCreateInput): Promise<ProductSnapshot>\n update(id: string, input: ProductUpdateInput): Promise<ProductSnapshot>\n delete(id: string): Promise<void>\n publish(id: string): Promise<void>\n unpublish(id: string): Promise<void>\n getById(id: string): Promise<ProductSnapshot>\n getBySlug(slug: string): Promise<ProductSnapshot>\n list(opts?: {\n status?: ProductStatus\n limit?: number\n offset?: number\n }): Promise<ProductSnapshot[]>\n}\n\nexport interface CreateProductServiceDeps {\n store: CommandStore\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n}\n\nasync function snapshot(\n tx: ReadTx,\n repos: Repositories,\n product: Product,\n): Promise<ProductSnapshot> {\n const [variants, categoryIds] = await Promise.all([\n repos.variant.findByProduct(tx, product.id),\n repos.productCategory.listCategoriesForProduct(tx, product.id),\n ])\n return { ...product, variants, categoryIds }\n}\n\nexport function createProductService(deps: CreateProductServiceDeps): ProductService {\n const { store, repos, publisher } = deps\n\n async function requireProduct(tx: ReadTx, id: string): Promise<Product> {\n const product = await repos.product.findById(tx, id)\n if (!product) throw new NotFoundError('product', id)\n return product\n }\n\n return {\n async create(input) {\n if (!input.slug.trim()) throw new ValidationError('Product slug is required')\n if (!input.name.trim()) throw new ValidationError('Product name is required')\n const existing = await store.read((tx) => repos.product.findBySlug(tx, input.slug))\n if (existing) {\n throw new ValidationError(`Product slug already exists: ${input.slug}`, {\n context: { slug: input.slug },\n })\n }\n return store.transaction(async (tx) => {\n const now = new Date()\n const productId = uuidv7()\n const insert: ProductInsert = {\n id: productId,\n slug: input.slug,\n name: input.name,\n ...(input.description !== undefined && { description: input.description }),\n ...(input.shortDescription !== undefined && { shortDescription: input.shortDescription }),\n ...(input.status !== undefined && { status: input.status }),\n ...(input.type !== undefined && { type: input.type }),\n ...(input.seoTitle !== undefined && { seoTitle: input.seoTitle }),\n ...(input.seoDescription !== undefined && { seoDescription: input.seoDescription }),\n ...(input.media !== undefined && { media: input.media }),\n ...(input.metadata !== undefined && { metadata: input.metadata }),\n createdAt: now,\n updatedAt: now,\n }\n await repos.product.insert(tx, insert)\n const variantRows: Variant[] = []\n for (const v of input.variants ?? []) {\n const id = v.id ?? uuidv7()\n const vi: VariantInsert = {\n ...v,\n id,\n productId,\n createdAt: now,\n updatedAt: now,\n }\n await repos.variant.insert(tx, vi)\n const stored = await repos.variant.findById(tx, id)\n if (stored) variantRows.push(stored)\n }\n for (const categoryId of input.categoryIds ?? []) {\n await repos.productCategory.attach(tx, productId, categoryId)\n }\n const created = await requireProduct(tx, productId)\n const snap: ProductSnapshot = {\n ...created,\n variants: variantRows,\n categoryIds: input.categoryIds ?? [],\n }\n await publisher.publish(EVT_PRODUCT_CREATED, { product: snap })\n return snap\n })\n },\n\n async update(id, input) {\n return store.transaction(async (tx) => {\n const product = await requireProduct(tx, id)\n const now = new Date()\n const updateInput: ProductUpdate = {\n ...(input.name !== undefined && { name: input.name }),\n ...(input.description !== undefined && { description: input.description }),\n ...(input.shortDescription !== undefined && { shortDescription: input.shortDescription }),\n ...(input.status !== undefined && { status: input.status }),\n ...(input.type !== undefined && { type: input.type }),\n ...(input.seoTitle !== undefined && { seoTitle: input.seoTitle }),\n ...(input.seoDescription !== undefined && { seoDescription: input.seoDescription }),\n ...(input.media !== undefined && { media: input.media }),\n ...(input.metadata !== undefined && { metadata: input.metadata }),\n updatedAt: now,\n }\n await repos.product.update(tx, product.id, updateInput)\n if (input.categoryIds) {\n await repos.productCategory.detachAllForProduct(tx, product.id)\n for (const categoryId of input.categoryIds) {\n await repos.productCategory.attach(tx, product.id, categoryId)\n }\n }\n const snap = await snapshot(tx, repos, await requireProduct(tx, product.id))\n await publisher.publish(EVT_PRODUCT_UPDATED, { product: snap })\n return snap\n })\n },\n\n async delete(id) {\n await store.transaction(async (tx) => {\n const product = await requireProduct(tx, id)\n await repos.productCategory.detachAllForProduct(tx, product.id)\n const variants = await repos.variant.findByProduct(tx, product.id)\n for (const v of variants) await repos.variant.delete(tx, v.id)\n await repos.product.delete(tx, product.id)\n await publisher.publish(EVT_PRODUCT_DELETED, {\n productId: product.id,\n slug: product.slug,\n })\n })\n },\n\n async publish(id) {\n await store.transaction(async (tx) => {\n const product = await requireProduct(tx, id)\n if (product.status === 'active') return\n await repos.product.setStatus(tx, product.id, 'active', new Date())\n await publisher.publish(EVT_PRODUCT_PUBLISHED, {\n productId: product.id,\n slug: product.slug,\n })\n const fresh = await requireProduct(tx, product.id)\n const snap = await snapshot(tx, repos, fresh)\n await publisher.publish(EVT_PRODUCT_UPDATED, { product: snap })\n })\n },\n\n async unpublish(id) {\n await store.transaction(async (tx) => {\n const product = await requireProduct(tx, id)\n if (product.status === 'draft') return\n await repos.product.setStatus(tx, product.id, 'draft', new Date())\n await publisher.publish(EVT_PRODUCT_UNPUBLISHED, {\n productId: product.id,\n slug: product.slug,\n })\n const fresh = await requireProduct(tx, product.id)\n const snap = await snapshot(tx, repos, fresh)\n await publisher.publish(EVT_PRODUCT_UPDATED, { product: snap })\n })\n },\n\n async getById(id) {\n return store.read(async (tx) => snapshot(tx, repos, await requireProduct(tx, id)))\n },\n\n async getBySlug(slug) {\n return store.read(async (tx) => {\n const product = await repos.product.findBySlug(tx, slug)\n if (!product) throw new NotFoundError('product', slug)\n return snapshot(tx, repos, product)\n })\n },\n\n async list(opts = {}) {\n return store.read(async (tx) => {\n const products = await repos.product.list(tx, opts)\n const out: ProductSnapshot[] = []\n for (const p of products) {\n out.push(await snapshot(tx, repos, p))\n }\n return out\n })\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_CATEGORY_CREATED,\n EVT_CATEGORY_UPDATED,\n EVT_CATEGORY_DELETED,\n NotFoundError,\n ValidationError,\n type Category,\n type Logger,\n} from '@nymbalhq/types'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nexport interface CategoryCreateInput {\n slug: string\n name: string\n description?: string\n parentId?: string | null\n position?: number\n}\n\nexport interface CategoryUpdateInput {\n name?: string\n description?: string\n parentId?: string | null\n position?: number\n}\n\nexport interface CategoryService {\n list(): Promise<Category[]>\n getById(id: string): Promise<Category>\n getBySlug(slug: string): Promise<Category>\n create(input: CategoryCreateInput): Promise<Category>\n update(id: string, input: CategoryUpdateInput): Promise<Category>\n delete(id: string): Promise<void>\n}\n\nexport function createCategoryService(deps: {\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n}): CategoryService {\n const { repos, publisher } = deps\n const { store } = repos.category\n return {\n async list() {\n return store.read((tx) => repos.category.list(tx))\n },\n async getById(id) {\n const c = await store.read((tx) => repos.category.findById(tx, id))\n if (!c) throw new NotFoundError('category', id)\n return c\n },\n async getBySlug(slug) {\n const c = await store.read((tx) => repos.category.findBySlug(tx, slug))\n if (!c) throw new NotFoundError('category', slug)\n return c\n },\n async create(input) {\n if (!input.slug.trim()) throw new ValidationError('Category slug is required')\n return store.transaction(async (tx) => {\n if (await repos.category.findBySlug(tx, input.slug)) {\n throw new ValidationError(`Category slug already exists: ${input.slug}`)\n }\n const now = new Date()\n const category: Category = {\n id: uuidv7(),\n parentId: input.parentId ?? null,\n slug: input.slug,\n name: input.name,\n description: input.description ?? '',\n position: input.position ?? 0,\n createdAt: now.toISOString(),\n }\n await repos.category.insert(tx, { ...category, createdAt: now })\n await publisher.publish(EVT_CATEGORY_CREATED, { category })\n return category\n })\n },\n async update(id, input) {\n return store.transaction(async (tx) => {\n const existing = await repos.category.findById(tx, id)\n if (!existing) throw new NotFoundError('category', id)\n await repos.category.update(tx, id, input)\n const fresh = (await repos.category.findById(tx, id)) as Category\n await publisher.publish(EVT_CATEGORY_UPDATED, { category: fresh })\n return fresh\n })\n },\n async delete(id) {\n await store.transaction(async (tx) => {\n const existing = await repos.category.findById(tx, id)\n if (!existing) throw new NotFoundError('category', id)\n await repos.category.delete(tx, id)\n await publisher.publish(EVT_CATEGORY_DELETED, {\n categoryId: existing.id,\n slug: existing.slug,\n })\n })\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_CART_CREATED,\n EVT_CART_ITEM_ADDED,\n EVT_CART_ITEM_REMOVED,\n EVT_CART_UPDATED,\n NotFoundError,\n ValidationError,\n type Cart,\n type CartItem,\n type Logger,\n} from '@nymbalhq/types'\nimport type { CommandStore, Tx } from '../db/command-store.js'\nimport type { CartRepository } from '../repositories/cart.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nconst TTL_SECONDS_DEFAULT = 60 * 60 * 24 * 30\n\nexport interface CartService {\n getOrCreate(token?: string, customerId?: string | null): Promise<Cart>\n get(token: string): Promise<Cart | null>\n addItem(token: string, item: Omit<CartItem, 'qty'> & { qty?: number }): Promise<Cart>\n updateItemQuantity(token: string, variantId: string, qty: number): Promise<Cart>\n removeItem(token: string, variantId: string): Promise<Cart>\n clear(token: string): Promise<Cart>\n merge(guestToken: string, customerToken: string): Promise<Cart>\n attachCustomer(token: string, customerId: string): Promise<Cart>\n}\n\nexport interface CreateCartServiceDeps {\n store: CommandStore\n carts: CartRepository\n publisher: EventPublisher\n logger: Logger\n currency: string\n ttlSeconds?: number\n now?: () => Date\n}\n\nfunction calcSubtotal(items: CartItem[]): number {\n return items.reduce((sum, item) => sum + item.priceMinor * item.qty, 0)\n}\n\nexport function createCartService(deps: CreateCartServiceDeps): CartService {\n const { store, carts, publisher, currency } = deps\n const ttlMs = (deps.ttlSeconds ?? TTL_SECONDS_DEFAULT) * 1000\n const now = deps.now ?? (() => new Date())\n\n /** A cart past its expiry reads as missing, whether or not the sweeper has deleted it yet. */\n function live(cart: Cart | null, at: Date): cart is Cart {\n return cart !== null && Date.parse(cart.expiresAt) > at.getTime()\n }\n\n /** The cart after a write at `at`: these items, and an expiry that slides to `at + ttl`. */\n function written(cart: Cart, items: CartItem[], at: Date): Cart {\n return {\n ...cart,\n items,\n subtotalMinor: calcSubtotal(items),\n updatedAt: at.toISOString(),\n expiresAt: new Date(at.getTime() + ttlMs).toISOString(),\n }\n }\n\n async function requireCart(tx: Tx, token: string, at: Date): Promise<Cart> {\n const cart = await carts.lock(tx, token)\n if (!live(cart, at)) throw new NotFoundError('cart', token)\n return cart\n }\n\n async function emitUpdated(cart: Cart): Promise<void> {\n await publisher.publish(EVT_CART_UPDATED, {\n cartId: cart.token,\n itemCount: cart.items.reduce((n, i) => n + i.qty, 0),\n totalMinor: cart.subtotalMinor,\n })\n }\n\n /**\n * One command on one cart, in one transaction: the row is held from the read to the write, so a concurrent command\n * (another replica's included) waits and then sees this one's result, and the events commit with the write.\n */\n function command(token: string, change: (cart: Cart, at: Date) => Promise<Cart>): Promise<Cart> {\n return store.transaction(async (tx) => {\n const at = now()\n const next = await change(await requireCart(tx, token, at), at)\n await carts.put(tx, next)\n await emitUpdated(next)\n return next\n })\n }\n\n return {\n async getOrCreate(token, customerId = null) {\n return store.transaction(async (tx) => {\n const at = now()\n const { cart, created } = await carts.create(tx, {\n token: token ?? uuidv7(),\n customerId,\n items: [],\n subtotalMinor: 0,\n currency,\n expiresAt: new Date(at.getTime() + ttlMs).toISOString(),\n createdAt: at.toISOString(),\n updatedAt: at.toISOString(),\n })\n if (created) {\n await publisher.publish(EVT_CART_CREATED, { cartId: cart.token, token: cart.token })\n }\n return cart\n })\n },\n\n async get(token) {\n const at = now()\n const cart = await store.read((tx) => carts.findByToken(tx, token))\n return live(cart, at) ? cart : null\n },\n\n async addItem(token, item) {\n return command(token, async (cart, at) => {\n const qty = item.qty ?? 1\n if (qty <= 0) throw new ValidationError(`qty must be positive, got ${qty}`)\n const onCart = cart.items.some((i) => i.variantId === item.variantId)\n const items = onCart\n ? cart.items.map((i) => (i.variantId === item.variantId ? { ...i, qty: i.qty + qty } : i))\n : [\n ...cart.items,\n {\n variantId: item.variantId,\n productId: item.productId,\n productName: item.productName,\n variantName: item.variantName,\n priceMinor: item.priceMinor,\n imageUrl: item.imageUrl,\n qty,\n },\n ]\n await publisher.publish(EVT_CART_ITEM_ADDED, {\n cartId: cart.token,\n variantId: item.variantId,\n qty,\n })\n return written(cart, items, at)\n })\n },\n\n async updateItemQuantity(token, variantId, qty) {\n if (qty < 0) throw new ValidationError(`qty must be non-negative, got ${qty}`)\n return command(token, async (cart, at) => {\n if (!cart.items.some((i) => i.variantId === variantId)) {\n throw new NotFoundError('cart_item', variantId)\n }\n if (qty === 0) {\n await publisher.publish(EVT_CART_ITEM_REMOVED, { cartId: cart.token, variantId })\n return written(\n cart,\n cart.items.filter((i) => i.variantId !== variantId),\n at,\n )\n }\n return written(\n cart,\n cart.items.map((i) => (i.variantId === variantId ? { ...i, qty } : i)),\n at,\n )\n })\n },\n\n async removeItem(token, variantId) {\n return command(token, async (cart, at) => {\n const items = cart.items.filter((i) => i.variantId !== variantId)\n if (items.length < cart.items.length) {\n await publisher.publish(EVT_CART_ITEM_REMOVED, { cartId: cart.token, variantId })\n }\n return written(cart, items, at)\n })\n },\n\n async clear(token) {\n return command(token, async (cart, at) => written(cart, [], at))\n },\n\n async attachCustomer(token, customerId) {\n return command(token, async (cart, at) => ({ ...written(cart, cart.items, at), customerId }))\n },\n\n async merge(guestToken, customerToken) {\n return store.transaction(async (tx) => {\n const at = now()\n const guest = await carts.lock(tx, guestToken)\n if (!live(guest, at)) return requireCart(tx, customerToken, at)\n const customerCart = await carts.lock(tx, customerToken)\n let merged: Cart\n if (live(customerCart, at)) {\n const held = customerCart.items\n const items = [\n ...held.map((i) => {\n const g = guest.items.find((x) => x.variantId === i.variantId)\n return g ? { ...i, qty: Math.max(i.qty, g.qty) } : i\n }),\n ...guest.items.filter((g) => !held.some((i) => i.variantId === g.variantId)),\n ]\n merged = written(customerCart, items, at)\n } else {\n // The guest cart takes the customer's token, replacing an expired cart there if there is one.\n merged = written({ ...guest, token: customerToken }, guest.items, at)\n }\n await carts.remove(tx, guestToken)\n await carts.put(tx, merged)\n await emitUpdated(merged)\n return merged\n })\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_CUSTOMER_UPDATED,\n NotFoundError,\n ValidationError,\n type Customer,\n type CustomerAddress,\n type Logger,\n} from '@nymbalhq/types'\nimport type { ReadTx } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nexport interface ProfileUpdate {\n firstName?: string\n lastName?: string\n phone?: string\n}\n\nexport interface CustomerService {\n getProfile(customerId: string): Promise<Customer>\n updateProfile(customerId: string, patch: ProfileUpdate): Promise<Customer>\n listAddresses(customerId: string): Promise<CustomerAddress[]>\n addAddress(customerId: string, addr: Omit<CustomerAddress, 'id'>): Promise<CustomerAddress>\n deleteAddress(customerId: string, addressId: string): Promise<void>\n}\n\nfunction stripPassword(c: Customer & { passwordHash: string }): Customer {\n const { passwordHash: _pw, ...rest } = c\n return rest\n}\n\nexport function createCustomerService(deps: {\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n}): CustomerService {\n const { repos, publisher } = deps\n const { store } = repos.customer\n\n async function loadOrThrow(tx: ReadTx, id: string): Promise<Customer & { passwordHash: string }> {\n const c = await repos.customer.findById(tx, id)\n if (!c) throw new NotFoundError('customer', id)\n return c\n }\n\n return {\n async getProfile(customerId) {\n return stripPassword(await store.read((tx) => loadOrThrow(tx, customerId)))\n },\n async updateProfile(customerId, patch) {\n return store.transaction(async (tx) => {\n await loadOrThrow(tx, customerId)\n const now = new Date()\n await repos.customer.update(tx, customerId, { ...patch, updatedAt: now })\n await publisher.publish(EVT_CUSTOMER_UPDATED, { customerId })\n const fresh = await loadOrThrow(tx, customerId)\n return stripPassword(fresh)\n })\n },\n async listAddresses(customerId) {\n const customer = await store.read((tx) => loadOrThrow(tx, customerId))\n return customer.addresses\n },\n async addAddress(customerId, addr) {\n return store.transaction(async (tx) => {\n const customer = await loadOrThrow(tx, customerId)\n const newAddr: CustomerAddress = { ...addr, id: uuidv7() }\n const defaultBilling = newAddr.isDefaultBilling\n const defaultShipping = newAddr.isDefaultShipping\n const addresses = customer.addresses.map((a) => ({\n ...a,\n isDefaultBilling: defaultBilling ? false : a.isDefaultBilling,\n isDefaultShipping: defaultShipping ? false : a.isDefaultShipping,\n }))\n addresses.push(newAddr)\n const now = new Date()\n await repos.customer.update(tx, customerId, { addresses, updatedAt: now })\n await publisher.publish(EVT_CUSTOMER_UPDATED, { customerId })\n return newAddr\n })\n },\n async deleteAddress(customerId, addressId) {\n await store.transaction(async (tx) => {\n const customer = await loadOrThrow(tx, customerId)\n const addresses = customer.addresses.filter((a) => a.id !== addressId)\n if (addresses.length === customer.addresses.length) {\n throw new NotFoundError('address', addressId)\n }\n if (!addresses.length) {\n throw new ValidationError('Cannot remove last address')\n }\n const now = new Date()\n await repos.customer.update(tx, customerId, { addresses, updatedAt: now })\n await publisher.publish(EVT_CUSTOMER_UPDATED, { customerId })\n })\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport bcrypt from 'bcryptjs'\nconst { hash: bcryptHash, compare: bcryptCompare } = bcrypt\nimport { SignJWT, jwtVerify, type JWTPayload } from 'jose'\nimport { createHash } from 'node:crypto'\nimport {\n AuthError,\n EVT_CUSTOMER_CREATED,\n ValidationError,\n type Customer,\n type CustomerAddress,\n type Logger,\n type Role,\n} from '@nymbalhq/types'\nimport type { Repositories } from '../repositories/index.js'\nimport type { CustomerWithHash } from '../repositories/customer.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nexport interface AuthTokens {\n accessToken: string\n refreshToken: string\n expiresIn: number\n}\n\nexport interface RegisterInput {\n email: string\n password: string\n firstName?: string\n lastName?: string\n phone?: string\n}\n\nexport interface CustomerJwtPayload extends JWTPayload {\n sub: string\n email: string\n roles: Role[]\n type: 'access' | 'refresh'\n jti?: string\n}\n\nexport interface ImportCustomerInput {\n email: string\n firstName?: string\n lastName?: string\n phone?: string\n addresses?: CustomerAddress[]\n metadata?: Record<string, unknown>\n}\n\nexport interface AuthService {\n register(input: RegisterInput): Promise<{ customer: Customer; tokens: AuthTokens }>\n login(email: string, password: string): Promise<{ customer: Customer; tokens: AuthTokens }>\n refresh(refreshToken: string): Promise<AuthTokens>\n logout(refreshToken: string): Promise<void>\n verifyAccessToken(token: string): Promise<CustomerJwtPayload>\n importCustomer(input: ImportCustomerInput): Promise<Customer>\n}\n\nexport interface CreateAuthServiceDeps {\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n jwtSecret: string\n accessTtl: string\n refreshTtl: string\n issuer?: string\n}\n\nfunction parseDurationToMs(s: string): number {\n const match = /^(\\d+)(ms|s|m|h|d)$/.exec(s)\n if (!match) throw new ValidationError(`invalid duration: ${s}`)\n const qty = Number(match[1])\n switch (match[2]) {\n case 'ms':\n return qty\n case 's':\n return qty * 1000\n case 'm':\n return qty * 60 * 1000\n case 'h':\n return qty * 60 * 60 * 1000\n case 'd':\n return qty * 24 * 60 * 60 * 1000\n /* c8 ignore next 2 -- regex above only matches ms|s|m|h|d, making this unreachable */\n default:\n throw new ValidationError(`invalid duration unit: ${match[2]}`)\n }\n}\n\nfunction hashRefresh(token: string): string {\n return createHash('sha256').update(token).digest('hex')\n}\n\nfunction stripPassword(c: Customer & { passwordHash: string }): Customer {\n const { passwordHash: _pw, ...rest } = c\n return rest\n}\n\nexport function createAuthService(deps: CreateAuthServiceDeps): AuthService {\n const { repos, publisher, logger, jwtSecret, accessTtl, refreshTtl } = deps\n const { store } = repos.customer\n const issuer = deps.issuer ?? 'nymbal'\n const secretKey = new TextEncoder().encode(jwtSecret)\n const accessTtlMs = parseDurationToMs(accessTtl)\n const refreshTtlMs = parseDurationToMs(refreshTtl)\n\n async function mintAccess(customer: CustomerWithHash): Promise<string> {\n return new SignJWT({\n sub: customer.id,\n email: customer.email,\n roles: customer.roles,\n type: 'access',\n } satisfies CustomerJwtPayload)\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setIssuer(issuer)\n .setExpirationTime(new Date(Date.now() + accessTtlMs))\n .sign(secretKey)\n }\n\n async function mintRefresh(customer: Customer, jti: string): Promise<string> {\n return new SignJWT({\n sub: customer.id,\n email: customer.email,\n roles: ['customer'],\n type: 'refresh',\n jti,\n } satisfies CustomerJwtPayload)\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setJti(jti)\n .setIssuer(issuer)\n .setExpirationTime(new Date(Date.now() + refreshTtlMs))\n .sign(secretKey)\n }\n\n async function issueTokens(customer: CustomerWithHash): Promise<AuthTokens> {\n const jti = uuidv7()\n const refreshToken = await mintRefresh(customer, jti)\n await store.transaction((tx) =>\n repos.refreshToken.insert(tx, {\n id: jti,\n customerId: customer.id,\n tokenHash: hashRefresh(refreshToken),\n expiresAt: new Date(Date.now() + refreshTtlMs),\n createdAt: new Date(),\n }),\n )\n const accessToken = await mintAccess(customer)\n return {\n accessToken,\n refreshToken,\n expiresIn: Math.floor(accessTtlMs / 1000),\n }\n }\n\n return {\n async register(input) {\n if (!input.email.includes('@')) throw new ValidationError('invalid email')\n if (input.password.length < 8) throw new ValidationError('password must be ≥ 8 characters')\n const email = input.email.toLowerCase()\n const existing = await store.read((tx) => repos.customer.findByEmail(tx, email))\n if (existing) {\n throw new AuthError('invalid_credentials', 'An account with this email already exists')\n }\n const id = uuidv7()\n const passwordHash = await bcryptHash(input.password, 10)\n const now = new Date()\n const customer = await store.transaction(async (tx) => {\n await repos.customer.insert(tx, {\n id,\n email,\n passwordHash,\n ...(input.firstName !== undefined && { firstName: input.firstName }),\n ...(input.lastName !== undefined && { lastName: input.lastName }),\n ...(input.phone !== undefined && { phone: input.phone }),\n createdAt: now,\n updatedAt: now,\n })\n const inserted = await repos.customer.findById(tx, id)\n /* c8 ignore next -- defensive: customer was inserted in this transaction */\n if (!inserted) throw new Error('customer disappeared after insert')\n await publisher.publish(EVT_CUSTOMER_CREATED, { customerId: id, email })\n return inserted\n })\n const tokens = await issueTokens(customer)\n logger.info({ customerId: id }, 'customer registered')\n return { customer: stripPassword(customer), tokens }\n },\n\n async login(email, password) {\n const customer = await store.read((tx) => repos.customer.findByEmail(tx, email.toLowerCase()))\n if (!customer) throw new AuthError('invalid_credentials', 'Invalid email or password')\n const ok = await bcryptCompare(password, customer.passwordHash)\n if (!ok) throw new AuthError('invalid_credentials', 'Invalid email or password')\n const tokens = await issueTokens(customer)\n logger.info({ customerId: customer.id }, 'customer login')\n return { customer: stripPassword(customer), tokens }\n },\n\n async refresh(refreshToken) {\n let verified\n try {\n verified = await jwtVerify(refreshToken, secretKey, { issuer })\n } catch {\n throw new AuthError('token_invalid', 'refresh token invalid')\n }\n const payload = verified.payload as CustomerJwtPayload\n if (payload.type !== 'refresh' || !payload.jti || !payload.sub) {\n throw new AuthError('token_invalid', 'not a refresh token')\n }\n const jti = payload.jti\n const customerId = payload.sub\n const record = await store.read((tx) => repos.refreshToken.findById(tx, jti))\n if (!record) throw new AuthError('token_invalid', 'refresh token unknown')\n if (record.revokedAt) throw new AuthError('token_invalid', 'refresh token revoked')\n if (record.tokenHash !== hashRefresh(refreshToken)) {\n // A mismatch means replay with an older token — revoke chain.\n await store.transaction((tx) => repos.refreshToken.revokeAllForCustomer(tx, customerId))\n throw new AuthError('token_invalid', 'refresh token mismatch; revoking chain')\n }\n const customer = await store.read((tx) => repos.customer.findById(tx, customerId))\n if (!customer) throw new AuthError('token_invalid', 'customer missing')\n const nextJti = uuidv7()\n const nextRefresh = await mintRefresh(customer, nextJti)\n await store.transaction((tx) =>\n repos.refreshToken.rotate(tx, jti, {\n id: nextJti,\n customerId: customer.id,\n tokenHash: hashRefresh(nextRefresh),\n expiresAt: new Date(Date.now() + refreshTtlMs),\n createdAt: new Date(),\n }),\n )\n const accessToken = await mintAccess(customer)\n return {\n accessToken,\n refreshToken: nextRefresh,\n expiresIn: Math.floor(accessTtlMs / 1000),\n }\n },\n\n async logout(refreshToken) {\n try {\n const verified = await jwtVerify(refreshToken, secretKey, { issuer })\n const payload = verified.payload as CustomerJwtPayload\n const { jti } = payload\n if (jti) await store.transaction((tx) => repos.refreshToken.revoke(tx, jti))\n } catch {\n // ignore — already invalid\n }\n },\n\n async verifyAccessToken(token) {\n try {\n const verified = await jwtVerify(token, secretKey, { issuer })\n const payload = verified.payload as CustomerJwtPayload\n if (payload.type !== 'access') throw new AuthError('token_invalid', 'not an access token')\n return payload\n } catch (err) {\n if (err instanceof AuthError) throw err\n throw new AuthError('token_invalid', 'access token invalid', { cause: err })\n }\n },\n\n async importCustomer(input) {\n if (!input.email.includes('@')) throw new ValidationError('invalid email')\n const email = input.email.toLowerCase()\n const customer = await store.transaction(async (tx) => {\n const existing = await repos.customer.findByEmail(tx, email)\n if (existing) return existing\n const id = uuidv7()\n const now = new Date()\n await repos.customer.insert(tx, {\n id,\n email,\n passwordHash: 'IMPORTED_NO_PASSWORD',\n requiresPasswordReset: true,\n ...(input.firstName !== undefined && { firstName: input.firstName }),\n ...(input.lastName !== undefined && { lastName: input.lastName }),\n ...(input.phone !== undefined && { phone: input.phone }),\n ...(input.addresses !== undefined && { addresses: input.addresses }),\n ...(input.metadata !== undefined && { metadata: input.metadata }),\n roles: ['customer'],\n createdAt: now,\n updatedAt: now,\n })\n const inserted = await repos.customer.findById(tx, id)\n /* c8 ignore next -- defensive: customer was inserted above */\n if (!inserted) throw new Error('customer disappeared after insert')\n await publisher.publish(EVT_CUSTOMER_CREATED, { customerId: id, email })\n logger.info({ customerId: id }, 'customer imported')\n return inserted\n })\n return stripPassword(customer)\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n EVT_ORDER_CANCELLED,\n EVT_ORDER_DELIVERED,\n EVT_ORDER_PLACED,\n EVT_ORDER_SHIPPED,\n NotFoundError,\n OrderConflictError,\n StatusTransitionError,\n ValidationError,\n assertOrderTransition,\n type Address,\n type CaptureMethod,\n type Logger,\n type Order,\n type OrderLineItem,\n type OrderStatus,\n} from '@nymbalhq/types'\nimport type { CommandStore, ReadTx, Tx } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nexport interface OrderCreateDraftInput {\n orderId: string\n customerId: string | null\n email: string\n billingAddress: Address\n shippingAddress: Address\n lineItems: OrderLineItem[]\n subtotalMinor: number\n taxTotalMinor: number\n shippingTotalMinor: number\n discountTotalMinor: number\n totalMinor: number\n currency: string\n notes?: string\n metadata?: Record<string, unknown>\n paymentIntentId?: string | null\n cartToken?: string | null\n}\n\nexport interface OrderImportInput extends OrderCreateDraftInput {\n orderNumber: string\n status: OrderStatus\n createdAt: Date\n /** What the imported order was paid, taken as captured when it was placed; nothing when absent. */\n capturedMinor?: number\n refundedMinor?: number\n captureMethod?: CaptureMethod | null\n}\n\nexport interface OrderService {\n createFromCheckout(input: OrderCreateDraftInput): Promise<Order>\n importOrder(input: OrderImportInput): Promise<Order>\n getById(id: string): Promise<Order>\n getByOrderNumber(orderNumber: string): Promise<Order>\n listByCustomer(customerId: string): Promise<Order[]>\n updateStatus(id: string, toStatus: OrderStatus, actor: string, note?: string): Promise<Order>\n markShipped(id: string, trackingNumber: string, carrier: string, actor: string): Promise<Order>\n markDelivered(id: string, actor: string): Promise<Order>\n /** Refuses with `order.paid` once anything is captured: a paid order is refunded, never cancelled. */\n cancel(id: string, reason: string, actor: string): Promise<Order>\n}\n\nexport interface CreateOrderServiceDeps {\n store: CommandStore\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n orderNumberPrefix: string\n orderNumberStart: number\n}\n\nexport function createOrderService(deps: CreateOrderServiceDeps): OrderService {\n const { store, repos, publisher } = deps\n\n async function requireOrder(tx: ReadTx, id: string): Promise<Order> {\n const order = await repos.order.findById(tx, id)\n if (!order) throw new NotFoundError('order', id)\n return order\n }\n\n async function doTransition(\n tx: Tx,\n order: Order,\n toStatus: OrderStatus,\n actor: string,\n note: string,\n ): Promise<Order> {\n assertOrderTransition(order.status, toStatus)\n const now = new Date()\n await repos.order.setStatus(tx, order.id, toStatus, now)\n await repos.orderHistory.append(tx, {\n id: uuidv7(),\n orderId: order.id,\n fromStatus: order.status,\n toStatus,\n actor,\n note,\n timestamp: now,\n })\n return requireOrder(tx, order.id)\n }\n\n return {\n async createFromCheckout(input) {\n return store.transaction(async (tx) => {\n const sequence = await repos.orderSequence.nextSequence(tx, deps.orderNumberStart)\n const orderNumber = `${deps.orderNumberPrefix}-${sequence + 1}`\n const now = new Date()\n await repos.order.insert(tx, {\n id: input.orderId,\n orderNumber,\n sequence,\n customerId: input.customerId,\n status: 'pending',\n email: input.email,\n billingAddress: input.billingAddress,\n shippingAddress: input.shippingAddress,\n lineItems: input.lineItems,\n subtotalMinor: input.subtotalMinor,\n taxTotalMinor: input.taxTotalMinor,\n shippingTotalMinor: input.shippingTotalMinor,\n discountTotalMinor: input.discountTotalMinor,\n totalMinor: input.totalMinor,\n currency: input.currency,\n notes: input.notes ?? '',\n metadata: input.metadata ?? {},\n paymentIntentId: input.paymentIntentId ?? null,\n cartToken: input.cartToken ?? null,\n createdAt: now,\n updatedAt: now,\n })\n await repos.orderHistory.append(tx, {\n id: uuidv7(),\n orderId: input.orderId,\n fromStatus: null,\n toStatus: 'pending',\n actor: 'system:checkout',\n note: 'order draft created',\n timestamp: now,\n })\n const fresh = await requireOrder(tx, input.orderId)\n await publisher.publish(EVT_ORDER_PLACED, { order: fresh })\n return fresh\n })\n },\n\n async getById(id) {\n return store.read((tx) => requireOrder(tx, id))\n },\n async getByOrderNumber(orderNumber) {\n const order = await store.read((tx) => repos.order.findByOrderNumber(tx, orderNumber))\n if (!order) throw new NotFoundError('order', orderNumber)\n return order\n },\n async listByCustomer(customerId) {\n return store.read((tx) => repos.order.listByCustomer(tx, customerId))\n },\n async updateStatus(id, toStatus, actor, note = '') {\n return store.transaction(async (tx) => {\n const order = await requireOrder(tx, id)\n return doTransition(tx, order, toStatus, actor, note)\n })\n },\n async markShipped(id, trackingNumber, carrier, actor) {\n return store.transaction(async (tx) => {\n const order = await requireOrder(tx, id)\n const fresh = await doTransition(\n tx,\n order,\n 'shipped',\n actor,\n `Shipped via ${carrier}: ${trackingNumber}`,\n )\n await publisher.publish(EVT_ORDER_SHIPPED, {\n orderId: fresh.id,\n trackingNumber,\n carrier,\n })\n return fresh\n })\n },\n async markDelivered(id, actor) {\n return store.transaction(async (tx) => {\n const order = await requireOrder(tx, id)\n const fresh = await doTransition(tx, order, 'delivered', actor, 'Delivered')\n await publisher.publish(EVT_ORDER_DELIVERED, { orderId: fresh.id })\n return fresh\n })\n },\n async cancel(id, reason, actor) {\n return store.transaction(async (tx) => {\n // Under the row lock no confirm commits between the paid check and the write.\n const order = await repos.order.lock(tx, id)\n if (!order) throw new NotFoundError('order', id)\n if (order.capturedMinor > 0) {\n throw new OrderConflictError(\n 'order.paid',\n `Order ${order.orderNumber} is paid: refund it instead of cancelling`,\n )\n }\n assertOrderTransition(order.status, 'cancelled')\n const now = new Date()\n if (!(await repos.order.setStatusIf(tx, order.id, order.status, 'cancelled', now))) {\n const current = await requireOrder(tx, order.id)\n throw new StatusTransitionError('order', current.status, 'cancelled')\n }\n await repos.orderHistory.append(tx, {\n id: uuidv7(),\n orderId: order.id,\n fromStatus: order.status,\n toStatus: 'cancelled',\n actor,\n note: reason,\n timestamp: now,\n })\n const fresh = await requireOrder(tx, order.id)\n await publisher.publish(EVT_ORDER_CANCELLED, { orderId: fresh.id, reason })\n return fresh\n })\n },\n async importOrder(input) {\n const capturedMinor = input.capturedMinor ?? 0\n const refundedMinor = input.refundedMinor ?? 0\n if (\n !(\n 0 <= refundedMinor &&\n refundedMinor <= capturedMinor &&\n capturedMinor <= input.totalMinor\n ) ||\n capturedMinor > 0 !== (input.captureMethod != null)\n ) {\n throw new ValidationError('imported payment amounts are inconsistent', {\n context: { capturedMinor, refundedMinor, totalMinor: input.totalMinor },\n })\n }\n return store.transaction(async (tx) => {\n const sequence = await repos.orderSequence.nextSequence(tx, deps.orderNumberStart)\n await repos.order.insert(tx, {\n id: input.orderId,\n orderNumber: input.orderNumber,\n sequence,\n customerId: input.customerId,\n status: input.status,\n email: input.email,\n billingAddress: input.billingAddress,\n shippingAddress: input.shippingAddress,\n lineItems: input.lineItems,\n subtotalMinor: input.subtotalMinor,\n taxTotalMinor: input.taxTotalMinor,\n shippingTotalMinor: input.shippingTotalMinor,\n discountTotalMinor: input.discountTotalMinor,\n totalMinor: input.totalMinor,\n currency: input.currency,\n notes: input.notes ?? '',\n metadata: input.metadata ?? {},\n paymentIntentId: input.paymentIntentId ?? null,\n ...(input.captureMethod != null && {\n capture: {\n amountMinor: capturedMinor,\n method: input.captureMethod,\n at: input.createdAt,\n refundedMinor,\n },\n }),\n createdAt: input.createdAt,\n updatedAt: input.createdAt,\n })\n const fresh = await requireOrder(tx, input.orderId)\n await publisher.publish(EVT_ORDER_PLACED, { order: fresh })\n return fresh\n })\n },\n }\n}\n","import { v7 as uuidv7 } from 'uuid'\nimport {\n AdapterError,\n NotFoundError,\n ValidationError,\n EVT_INVENTORY_CHANGED,\n EVT_INVENTORY_RESERVED,\n EVT_INVENTORY_RELEASED,\n EVT_INVENTORY_LOW_STOCK,\n EVT_INVENTORY_OUT_OF_STOCK,\n type Logger,\n type StockAdjustmentReason,\n type StockStatus,\n} from '@nymbalhq/types'\nimport type { CommandStore } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\n\nexport interface ReserveStockResult {\n reservationId: string\n expiresAt: string\n}\n\nexport interface InventoryService {\n adjustStock(\n variantId: string,\n delta: number,\n reason: StockAdjustmentReason,\n actor: string,\n ): Promise<{ newQty: number }>\n reserveStock(\n variantId: string,\n qty: number,\n orderRef?: string | null,\n ttlSeconds?: number,\n ): Promise<ReserveStockResult>\n /** `reserveStock`, answering null instead of throwing when the variant has less than `qty` in stock. */\n tryReserveStock(\n variantId: string,\n qty: number,\n orderRef?: string | null,\n ttlSeconds?: number,\n ): Promise<ReserveStockResult | null>\n releaseReservation(\n reservationId: string,\n reason: 'expired' | 'cancelled' | 'abandoned',\n ): Promise<void>\n commitReservation(reservationId: string, actor: string): Promise<void>\n getStockStatus(\n variantId: string,\n ): Promise<{ stock: number; threshold: number; status: StockStatus }>\n}\n\nexport interface CreateInventoryServiceDeps {\n store: CommandStore\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n defaultReservationTtlSeconds?: number\n}\n\nfunction classifyStock(stock: number, threshold: number): StockStatus {\n if (stock <= 0) return 'out_of_stock'\n if (stock <= threshold) return 'low_stock'\n return 'in_stock'\n}\n\nexport function createInventoryService(deps: CreateInventoryServiceDeps): InventoryService {\n const { store, repos, publisher, logger } = deps\n const defaultTtl = deps.defaultReservationTtlSeconds ?? 15 * 60\n\n async function emitThresholdEvents(\n variantId: string,\n newQty: number,\n threshold: number,\n ): Promise<void> {\n if (newQty <= 0) {\n await publisher.publish(EVT_INVENTORY_OUT_OF_STOCK, { variantId })\n } else if (newQty <= threshold) {\n await publisher.publish(EVT_INVENTORY_LOW_STOCK, {\n variantId,\n currentQty: newQty,\n threshold,\n })\n }\n }\n\n /** The conditional decrement and its reservation row; `available` instead when the stock is short. */\n async function take(\n variantId: string,\n qty: number,\n orderRef: string | null,\n ttlSeconds: number | undefined,\n ): Promise<ReserveStockResult | { available: number }> {\n if (qty <= 0) throw new ValidationError(`Reservation qty must be positive, got ${qty}`)\n return store.transaction(async (tx) => {\n const variant = await repos.variant.findById(tx, variantId)\n if (!variant) throw new NotFoundError('variant', variantId)\n const now = new Date()\n const remaining = await repos.variant.decrementStock(tx, variant.id, qty, now)\n if (remaining === null) return { available: variant.stock }\n const expiresAt = new Date(now.getTime() + (ttlSeconds ?? defaultTtl) * 1000)\n const reservationId = uuidv7()\n await repos.inventoryReservation.insert(tx, {\n reservationId,\n variantId: variant.id,\n qty,\n orderRef,\n expiresAt,\n createdAt: now,\n })\n await publisher.publish(EVT_INVENTORY_RESERVED, {\n variantId: variant.id,\n qty,\n reservationId,\n expiresAt: expiresAt.toISOString(),\n })\n await publisher.publish(EVT_INVENTORY_CHANGED, {\n variantId: variant.id,\n previousQty: remaining + qty,\n newQty: remaining,\n reason: 'manual',\n })\n await emitThresholdEvents(variant.id, remaining, variant.lowStockThreshold)\n return { reservationId, expiresAt: expiresAt.toISOString() }\n })\n }\n\n return {\n async adjustStock(variantId, delta, reason, actor) {\n return store.transaction(async (tx) => {\n const variant = await repos.variant.findById(tx, variantId)\n if (!variant) throw new NotFoundError('variant', variantId)\n const now = new Date()\n const newQty =\n delta < 0\n ? await repos.variant.decrementStock(tx, variant.id, -delta, now)\n : await repos.variant.incrementStock(tx, variant.id, delta, now)\n if (newQty === null) {\n throw new ValidationError(`Cannot reduce stock below zero (variant ${variantId})`, {\n context: { variantId, stock: variant.stock, delta },\n })\n }\n const previousQty = newQty - delta\n await repos.stockAdjustment.append(tx, {\n id: uuidv7(),\n variantId: variant.id,\n adjustment: delta,\n reason,\n actor,\n previousQty,\n newQty,\n timestamp: now,\n })\n await publisher.publish(EVT_INVENTORY_CHANGED, {\n variantId: variant.id,\n previousQty,\n newQty,\n reason,\n })\n await emitThresholdEvents(variant.id, newQty, variant.lowStockThreshold)\n logger.debug({ variantId, delta, newQty, reason }, 'stock adjusted')\n return { newQty }\n })\n },\n\n async reserveStock(variantId, qty, orderRef = null, ttlSeconds) {\n const taken = await take(variantId, qty, orderRef, ttlSeconds)\n if ('available' in taken) {\n throw new AdapterError(\n 'inventory.insufficient',\n `Insufficient stock for variant ${variantId}`,\n {\n context: { variantId, requested: qty, available: taken.available },\n },\n )\n }\n return taken\n },\n\n async tryReserveStock(variantId, qty, orderRef = null, ttlSeconds) {\n const taken = await take(variantId, qty, orderRef, ttlSeconds)\n return 'available' in taken ? null : taken\n },\n\n async releaseReservation(reservationId, reason) {\n await store.transaction(async (tx) => {\n const reservation = await repos.inventoryReservation.deleteById(tx, reservationId)\n if (!reservation) {\n logger.debug(\n { reservationId },\n 'reservation already released, committed or never existed',\n )\n return\n }\n const now = new Date()\n const newQty = await repos.variant.incrementStock(\n tx,\n reservation.variantId,\n reservation.qty,\n now,\n )\n if (newQty !== null) {\n const previousQty = newQty - reservation.qty\n await repos.stockAdjustment.append(tx, {\n id: uuidv7(),\n variantId: reservation.variantId,\n adjustment: reservation.qty,\n reason: 'reservation-release',\n actor: `system:release:${reason}`,\n previousQty,\n newQty,\n timestamp: now,\n })\n await publisher.publish(EVT_INVENTORY_CHANGED, {\n variantId: reservation.variantId,\n previousQty,\n newQty,\n reason: 'reservation-release',\n })\n }\n await publisher.publish(EVT_INVENTORY_RELEASED, {\n variantId: reservation.variantId,\n qty: reservation.qty,\n reservationId: reservation.reservationId,\n reason,\n })\n })\n },\n\n async commitReservation(reservationId, actor) {\n await store.transaction(async (tx) => {\n const reservation = await repos.inventoryReservation.deleteById(tx, reservationId)\n if (!reservation) throw new NotFoundError('reservation', reservationId)\n const variant = await repos.variant.findById(tx, reservation.variantId)\n if (!variant) throw new NotFoundError('variant', reservation.variantId)\n await repos.stockAdjustment.append(tx, {\n id: uuidv7(),\n variantId: variant.id,\n adjustment: -reservation.qty,\n reason: 'reservation-commit',\n actor,\n previousQty: variant.stock + reservation.qty,\n newQty: variant.stock,\n timestamp: new Date(),\n })\n await publisher.publish(EVT_INVENTORY_RELEASED, {\n variantId: reservation.variantId,\n qty: reservation.qty,\n reservationId: reservation.reservationId,\n reason: 'committed',\n })\n })\n },\n\n async getStockStatus(variantId) {\n const variant = await store.read((tx) => repos.variant.findById(tx, variantId))\n if (!variant) throw new NotFoundError('variant', variantId)\n return {\n stock: variant.stock,\n threshold: variant.lowStockThreshold,\n status: classifyStock(variant.stock, variant.lowStockThreshold),\n }\n },\n }\n}\n","import { v5 as uuidv5, v7 as uuidv7 } from 'uuid'\nimport {\n CheckoutError,\n EVT_CART_CONVERTED,\n EVT_CART_UPDATED,\n EVT_ORDER_PAID,\n EVT_PAYMENT_CAPTURED,\n EVT_PAYMENT_FAILED,\n EVT_PAYMENT_REFUNDED,\n NotFoundError,\n OrderConflictError,\n PaymentError,\n StatusTransitionError,\n type Address,\n type CaptureMethod,\n type Cart,\n type CheckoutPayment,\n type Logger,\n type Order,\n type OrderLineItem,\n type OrderStatus,\n type PaymentsAdapter,\n type PaymentIntent,\n type PaymentStatus,\n} from '@nymbalhq/types'\nimport type { CommandStore, Tx } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\nimport { formatMoney } from '../money.js'\nimport type { InventoryService } from './inventory-service.js'\nimport type { OrderService } from './order-service.js'\nimport type { CartService } from './cart-service.js'\nimport {\n PROVIDER_REFUND_REASON,\n refreshRefunded,\n settlementOf,\n type Settlement,\n} from './refund-service.js'\n\nexport interface BeginCheckoutInput {\n cartToken: string\n customerId?: string | null\n email: string\n billingAddress: Address\n shippingAddress: Address\n notes?: string\n}\n\nexport interface BeginCheckoutResult {\n orderId: string\n orderNumber: string\n paymentIntent: PaymentIntent\n currency: string\n totalMinor: number\n /** The order's status as the checkout answers. */\n orderStatus: OrderStatus\n payment: CheckoutPayment\n}\n\n/** What the payment provider captured. */\nexport interface CapturedPayment {\n amountMinor: number\n /** ISO 4217, in any case. */\n currency: string\n}\n\nexport interface FinalizeResult {\n /** Null when no order has the payment intent. */\n orderNumber: string | null\n /** True when the order is confirmed: by this call, or already for this intent. */\n finalized: boolean\n /** Why the captured payment did not confirm the order; recorded as payment.failed. */\n reason?: string\n}\n\nexport interface CheckoutService {\n beginCheckout(input: BeginCheckoutInput): Promise<BeginCheckoutResult>\n /**\n * Confirms the order a captured payment is for, or records why not (a payment.failed with the reason and, when\n * there is an order, a history note) and leaves the order as it was. Joins the caller's transaction.\n */\n finalize(paymentIntentId: string, paid: CapturedPayment): Promise<FinalizeResult>\n cancel(orderId: string, reason: string): Promise<void>\n}\n\n/** The admin's side of a checkout: a payment taken outside the store. */\nexport interface ManualPayments {\n /**\n * Records a payment the merchant took outside the store (a manual capture of the order's total) and confirms the\n * pending order exactly as a provider capture does: its reservations committed (re-taken if released), stats,\n * payment.captured and order.paid, the cart cleared. `order.stock_unavailable` when released stock is gone.\n */\n markPaid(orderId: string, actor: string, note?: string): Promise<Order>\n}\n\nexport interface CreateCheckoutServiceDeps {\n store: CommandStore\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n cart: CartService\n orders: OrderService\n inventory: InventoryService\n payments: PaymentsAdapter\n currency: string\n}\n\ninterface DraftMetadata {\n cartToken: string\n reservationIds: string[]\n}\n\n/** A line whose released reservation cannot be re-taken: another order has the stock now. */\nclass StockUnavailable extends Error {\n constructor(readonly variantId: string) {\n super(`stock unavailable for variant ${variantId}`)\n }\n}\n\n/** The conditional confirm found the order no longer pending: a concurrent writer moved it first. */\nclass NoLongerPending extends Error {}\n\n/** How a confirm records the capture, and who it says confirmed the order. */\ninterface CaptureRecord {\n method: CaptureMethod\n actor: string\n note: string\n}\n\nconst PROVIDER_CAPTURE: CaptureRecord = {\n method: 'provider',\n actor: 'system:checkout',\n note: 'payment captured',\n}\n\nconst FINALIZE_ACTOR = 'system:checkout-finalize'\nconst CANCEL_ACTOR = 'system:checkout-cancel'\n\n/** The outcome of a provider capture refunded because the merchant already holds the order's money. */\nconst DUPLICATE_CAPTURE = 'duplicate_capture_refunded'\n\n/** The processed-event record, keyed by intent, of a duplicate capture already refunded and recorded. */\nconst DUPLICATE_CAPTURE_HANDLER = 'checkout:duplicate-capture'\n\n/** The namespace of the idempotency keys derived from an intent for refunding its capture. */\nconst CAPTURE_REFUND_NAMESPACE = '49e623d3-5784-4331-80e9-6f951d97f7c0'\n\n/** Cancels of a changed cart's earlier intent one checkout makes before it gives up to a busier writer. */\nconst SUPERSEDE_ATTEMPTS = 3\n\n/**\n * A pending order still without an intent this long after it was placed is abandoned (its T2 failed, or the process\n * died between T1 and T2): longer than any provider call takes.\n */\nconst ABANDON_AFTER_MS = 120_000\n\n/** What one pass under the cart lock decided. */\ntype Placement =\n | { kind: 'placed'; order: Order }\n | { kind: 'existing'; order: Order & { paymentIntentId: string } }\n | { kind: 'cancel-first'; order: Order & { paymentIntentId: string } }\n\n/** The shopper's view of an intent the provider has just made. */\nfunction outcomeOf(status: PaymentStatus): CheckoutPayment['status'] {\n if (status === 'succeeded') return 'succeeded'\n if (status === 'failed' || status === 'cancelled') return 'failed'\n return 'requires_action'\n}\n\n/** The pending order is for exactly this cart: the same lines, quantities, prices and total. */\nfunction sameLines(order: Order, cart: Cart): boolean {\n if (order.totalMinor !== cart.subtotalMinor || order.currency !== cart.currency) return false\n if (order.lineItems.length !== cart.items.length) return false\n return cart.items.every((item, i) => {\n const line = order.lineItems[i]\n return (\n line?.variantId === item.variantId &&\n line.qty === item.qty &&\n line.unitPriceMinor === item.priceMinor\n )\n })\n}\n\nexport function createCheckoutService(\n deps: CreateCheckoutServiceDeps,\n): CheckoutService & ManualPayments {\n const { store, repos, publisher, logger, cart, orders, inventory, payments, currency } = deps\n\n /** An empty cart's refusal, naming the order the cart became when it became one. */\n async function cartEmpty(token: string): Promise<CheckoutError> {\n const converted = await store.read((tx) => repos.order.findLastConvertedByCartToken(tx, token))\n return new CheckoutError(\n 'cart_empty',\n 'Cart has no items',\n converted ? { context: { orderNumber: converted.orderNumber } } : {},\n )\n }\n\n async function loadValidCart(token: string): Promise<Cart> {\n const c = await cart.get(token)\n if (!c) throw new NotFoundError('cart', token)\n if (!c.items.length) throw await cartEmpty(token)\n if (c.currency !== currency) {\n throw new CheckoutError(\n 'cart_empty',\n `Cart currency ${c.currency} does not match store currency ${currency}`,\n )\n }\n return c\n }\n\n /** No order for the intent, or an order that is no longer pending. */\n async function settled(\n tx: Tx,\n paymentIntentId: string,\n order: Order | null,\n paid: CapturedPayment,\n ): Promise<FinalizeResult> {\n if (order === null) return recordOutcome(tx, paymentIntentId, null, 'no_order')\n // The merchant already holds this order's money from outside the provider: the provider's capture is a second one.\n if (order.captureMethod === 'manual' || order.captureMethod === 'import') {\n return refundDuplicateCapture(tx, paymentIntentId, paid, order)\n }\n // Idempotent on the order: a second event id or a concurrent delivery for a confirmed order changes nothing.\n if (order.status === 'confirmed') return { orderNumber: order.orderNumber, finalized: true }\n if (order.status === 'cancelled') {\n // Money never stays without an order: a capture for a cancelled order goes back in full, once (a capture already\n // recorded on it was refunded with it, or is held as a pending or failed refund).\n if (order.capturedMinor === 0) await refundCancelledCapture(paymentIntentId, paid, order)\n return recordOutcome(tx, paymentIntentId, order, 'order_cancelled_refunded')\n }\n return recordOutcome(tx, paymentIntentId, order, `order_not_pending: ${order.status}`)\n }\n\n /**\n * A captured payment that does not confirm its order: recorded, and nothing else changes. `detail` is for the\n * merchant's note only; the event and the result carry the bare reason.\n */\n async function recordOutcome(\n tx: Tx,\n paymentIntentId: string,\n order: Order | null,\n reason: string,\n detail?: string,\n ): Promise<FinalizeResult> {\n await publisher.publish(EVT_PAYMENT_FAILED, {\n paymentId: paymentIntentId,\n orderId: order?.id ?? '',\n reason,\n })\n if (order !== null) {\n await repos.orderHistory.append(tx, {\n id: uuidv7(),\n orderId: order.id,\n fromStatus: order.status,\n toStatus: order.status,\n actor: FINALIZE_ACTOR,\n note: `captured payment not applied: ${reason}${detail === undefined ? '' : ` (${detail})`}`,\n timestamp: new Date(),\n })\n }\n logger.warn({ paymentIntentId, orderId: order?.id, reason }, 'captured payment not applied')\n return { orderNumber: order?.orderNumber ?? null, finalized: false, reason }\n }\n\n /**\n * The reservation for line `index`, held or re-taken. The sweeper releases a reservation after its TTL while the\n * order stays pending; a late payment takes the line's stock again with the same conditional decrement.\n */\n async function reservationFor(\n tx: Tx,\n order: Order,\n reservationId: string,\n index: number,\n ): Promise<string> {\n const held = await repos.inventoryReservation.findById(tx, reservationId)\n if (held !== null) return reservationId\n // Checkout reserves one line at a time, in line order.\n const line = order.lineItems[index]\n if (line === undefined) {\n throw new CheckoutError(\n 'finalize_failed',\n `Order ${order.id} has no line for reservation ${reservationId}`,\n )\n }\n // A variant deleted since checkout has no stock to re-take.\n const retaken = await inventory\n .tryReserveStock(line.variantId, line.qty, order.id)\n .catch((err: unknown) => {\n if (err instanceof NotFoundError) return null\n throw err\n })\n if (retaken === null) throw new StockUnavailable(line.variantId)\n return retaken.reservationId\n }\n\n /**\n * The provider's refund of a capture, settled by its answer: a definite refusal is `failed`, an unknown outcome (a\n * timeout, a provider fault) `pending` until it is reconciled, as the refund route settles one.\n */\n async function refundCapture(\n paymentIntentId: string,\n paid: CapturedPayment,\n currency: string,\n key: string,\n context: Record<string, unknown>,\n ): Promise<Settlement> {\n try {\n const answer = await payments.refund(\n paymentIntentId,\n paid.amountMinor,\n PROVIDER_REFUND_REASON,\n {\n idempotencyKey: key,\n currency,\n },\n )\n const settlement = settlementOf(answer, { amountMinor: paid.amountMinor, currency })\n if (settlement.mismatch) {\n logger.error(\n { ...context, answer: { amountMinor: answer.amountMinor, currency: answer.currency } },\n 'provider refund answer differs from the capture; left pending',\n )\n }\n return settlement\n } catch (err) {\n if (err instanceof PaymentError && err.code === 'payment.refund_rejected') {\n logger.error({ ...context, err }, 'provider refused the refund of a capture')\n return { status: 'failed', providerRefundId: null, mismatch: false }\n }\n logger.error(\n { ...context, err },\n 'capture refund outcome unknown; left pending until reconciled',\n )\n return { status: 'pending', providerRefundId: null, mismatch: false }\n }\n }\n\n /**\n * A capture whose order is cancelled, refunded in full and recorded as both a capture and an equal refund, so the\n * cancelled order nets to zero. The capture and a `pending` refund row are written before the provider is asked, the\n * row's id its idempotency key, so an outcome the shop cannot know stays recorded and the delivery is recorded once.\n * The key is derived from the intent, which captures once: a delivery retried after a crash asks with the same key.\n * The provider is asked for the captured amount and the order's currency by name, as every refund is. Joins the\n * caller's transaction when there is one.\n */\n async function refundCancelledCapture(\n paymentIntentId: string,\n paid: CapturedPayment,\n order: Order,\n ): Promise<void> {\n const refundId = uuidv5(`cancelled-capture:${paymentIntentId}`, CAPTURE_REFUND_NAMESPACE)\n const held = await store.transaction(async (tx) => {\n const locked = await repos.order.lock(tx, order.id)\n // A concurrent delivery recorded this capture first.\n if (locked === null || locked.capturedMinor > 0) return false\n const now = new Date()\n await repos.order.recordCapture(tx, order.id, {\n amountMinor: paid.amountMinor,\n method: 'provider',\n at: now,\n })\n await repos.orderRefund.insert(tx, {\n id: refundId,\n orderId: order.id,\n amountMinor: paid.amountMinor,\n currency: order.currency,\n providerRefundId: null,\n status: 'pending',\n reason: 'captured for a cancelled order',\n actor: 'system:checkout',\n createdAt: now,\n })\n return true\n })\n if (!held) return\n const settlement = await refundCapture(paymentIntentId, paid, order.currency, refundId, {\n orderId: order.id,\n refundId,\n })\n if (settlement.status === 'pending') return\n await store.transaction(async (tx) => {\n await repos.order.lock(tx, order.id)\n await repos.orderRefund.settle(tx, refundId, {\n status: settlement.status,\n providerRefundId: settlement.providerRefundId,\n })\n await refreshRefunded(repos, tx, order.id, new Date())\n if (settlement.status === 'succeeded') {\n await publisher.publish(EVT_PAYMENT_REFUNDED, {\n paymentId: paymentIntentId,\n orderId: order.id,\n refundId,\n amountMinor: paid.amountMinor,\n currency: order.currency,\n })\n }\n })\n }\n\n /**\n * A provider capture for an order the merchant was already paid for outside the provider (marked paid, or imported):\n * refunded in full, once per intent, and recorded as an outcome. The order's captured and refunded amounts keep\n * meaning the money the merchant holds, so neither changes. An unknown outcome throws: the delivery is not recorded,\n * and the provider's redelivery asks again under the same key.\n */\n async function refundDuplicateCapture(\n tx: Tx,\n paymentIntentId: string,\n paid: CapturedPayment,\n order: Order,\n ): Promise<FinalizeResult> {\n if (await repos.processedEvent.seen(tx, DUPLICATE_CAPTURE_HANDLER, paymentIntentId)) {\n return { orderNumber: order.orderNumber, finalized: false, reason: DUPLICATE_CAPTURE }\n }\n const key = uuidv5(`duplicate-capture:${paymentIntentId}`, CAPTURE_REFUND_NAMESPACE)\n const settlement = await refundCapture(\n paymentIntentId,\n paid,\n paid.currency.toUpperCase(),\n key,\n {\n orderId: order.id,\n idempotencyKey: key,\n },\n )\n if (settlement.status === 'pending' && !settlement.mismatch) {\n throw new CheckoutError(\n 'finalize_failed',\n `The refund of a second capture of order ${order.orderNumber} has no known outcome`,\n { context: { orderNumber: order.orderNumber } },\n )\n }\n await repos.processedEvent.markProcessed(\n tx,\n DUPLICATE_CAPTURE_HANDLER,\n paymentIntentId,\n new Date(),\n )\n const reason =\n settlement.status === 'succeeded'\n ? DUPLICATE_CAPTURE\n : `duplicate_capture_refund_${settlement.status}`\n return recordOutcome(\n tx,\n paymentIntentId,\n order,\n reason,\n `capture of ${formatMoney(paid.amountMinor, paid.currency)}`,\n )\n }\n\n async function confirm(\n tx: Tx,\n paymentIntentId: string,\n paid: CapturedPayment,\n order: Order,\n capture: CaptureRecord,\n ): Promise<FinalizeResult> {\n const metadata = order.metadata as Partial<DraftMetadata>\n const reservationIds = Array.isArray(metadata.reservationIds)\n ? (metadata.reservationIds as string[])\n : []\n // Committing makes the reservation's decrement permanent, with its stock-adjustment row.\n for (const [index, reservationId] of reservationIds.entries()) {\n const reservation = await reservationFor(tx, order, reservationId, index)\n await inventory.commitReservation(reservation, FINALIZE_ACTOR)\n }\n\n const now = new Date()\n if (!(await repos.order.setStatusIf(tx, order.id, 'pending', 'confirmed', now))) {\n throw new NoLongerPending()\n }\n await repos.order.recordCapture(tx, order.id, {\n amountMinor: paid.amountMinor,\n method: capture.method,\n at: now,\n })\n await repos.orderHistory.append(tx, {\n id: uuidv7(),\n orderId: order.id,\n fromStatus: 'pending',\n toStatus: 'confirmed',\n actor: capture.actor,\n note: capture.note,\n timestamp: now,\n })\n if (order.customerId) {\n await repos.customer.incrementStats(tx, order.customerId, 1, paid.amountMinor, now)\n }\n\n await publisher.publish(EVT_PAYMENT_CAPTURED, {\n paymentId: paymentIntentId,\n orderId: order.id,\n amountMinor: paid.amountMinor,\n currency: order.currency,\n })\n await publisher.publish(EVT_ORDER_PAID, {\n orderId: order.id,\n paymentIntentId,\n amountMinor: paid.amountMinor,\n currency: order.currency,\n })\n\n // The cart empties in the same commit as the payment it became. A cart that expired or was swept while the\n // shopper paid is not a reason to refuse a paid order; cart.converted still records where the order came from.\n const cartToken = metadata.cartToken\n if (cartToken) {\n if (await repos.cart.clearIfLive(tx, cartToken, now)) {\n await publisher.publish(EVT_CART_UPDATED, {\n cartId: cartToken,\n itemCount: 0,\n totalMinor: 0,\n })\n }\n await publisher.publish(EVT_CART_CONVERTED, {\n cartId: cartToken,\n orderId: order.id,\n })\n }\n logger.info({ orderId: order.id, orderNumber: order.orderNumber }, 'checkout finalized')\n return { orderNumber: order.orderNumber, finalized: true }\n }\n\n /** Releases a pending order's reservations and cancels it. Joins the caller's transaction. */\n async function cancelDraft(orderId: string, reason: string): Promise<void> {\n await store.transaction(async (tx) => {\n const order = await repos.order.findById(tx, orderId)\n if (!order) throw new NotFoundError('order', orderId)\n const metadata = order.metadata as Partial<DraftMetadata>\n const reservationIds = Array.isArray(metadata.reservationIds)\n ? (metadata.reservationIds as string[])\n : []\n // A reservation already released or committed is a no-op here.\n for (const rid of reservationIds) {\n await inventory.releaseReservation(rid, 'cancelled')\n }\n await orders.cancel(orderId, reason, CANCEL_ACTOR)\n })\n }\n\n /** A fast, readable refusal; the conditional decrement when reserving is what holds under concurrency. */\n async function checkStock(tx: Tx, cartDoc: Cart): Promise<void> {\n for (const item of cartDoc.items) {\n const v = await repos.variant.findById(tx, item.variantId)\n if (!v) {\n throw new CheckoutError('variant_missing', `Variant missing: ${item.variantId}`)\n }\n if (v.stock < item.qty) {\n throw new CheckoutError(\n 'out_of_stock',\n `Insufficient stock for ${item.variantName}: available ${v.stock}, requested ${item.qty}`,\n )\n }\n }\n }\n\n /**\n * T1, under the cart's row lock: the cart's pending order is returned when it is for this cart, superseded when the\n * cart changed and its intent is cancelled, or cancelled itself when its intent is no longer open (`closed`, by the\n * reason), or abandoned when it never got an intent; or else the stock is reserved and a new pending order created\n * with no intent yet. Nothing is written unless an order is created or cancelled.\n */\n async function place(\n tx: Tx,\n input: BeginCheckoutInput,\n closed: ReadonlyMap<string, string>,\n ): Promise<Placement> {\n // Read again under the lock: the lines to order are the ones no concurrent cart command can change now.\n const cartDoc = await repos.cart.lock(tx, input.cartToken)\n if (cartDoc === null) throw new NotFoundError('cart', input.cartToken)\n if (!cartDoc.items.length) throw await cartEmpty(input.cartToken)\n\n const pending = await repos.order.findPendingByCartToken(tx, input.cartToken)\n if (pending !== null) {\n const { paymentIntentId } = pending\n if (paymentIntentId === null) {\n // Another checkout of this cart is between its order and its intent; a second intent is never made.\n if (Date.now() - Date.parse(pending.createdAt) <= ABANDON_AFTER_MS) {\n throw new CheckoutError('in_progress', 'A checkout for this cart is already in progress')\n }\n await cancelDraft(pending.id, 'abandoned: no payment intent')\n } else {\n const reason = closed.get(paymentIntentId)\n if (reason === undefined) {\n if (sameLines(pending, cartDoc))\n return { kind: 'existing', order: { ...pending, paymentIntentId } }\n return { kind: 'cancel-first', order: { ...pending, paymentIntentId } }\n }\n await cancelDraft(pending.id, reason)\n }\n }\n\n await checkStock(tx, cartDoc)\n const lineItems: OrderLineItem[] = cartDoc.items.map((item) => ({\n variantId: item.variantId,\n productId: item.productId,\n productName: item.productName,\n variantName: item.variantName,\n sku: '',\n qty: item.qty,\n unitPriceMinor: item.priceMinor,\n lineSubtotalMinor: item.priceMinor * item.qty,\n lineTaxMinor: 0,\n lineTotalMinor: item.priceMinor * item.qty,\n imageUrl: item.imageUrl,\n }))\n const orderId = uuidv7()\n const reservationIds: string[] = []\n for (const item of cartDoc.items) {\n try {\n const r = await inventory.reserveStock(item.variantId, item.qty, orderId)\n reservationIds.push(r.reservationId)\n } catch (err) {\n /* c8 ignore next -- inventory.reserveStock never throws CheckoutError; guards future adapters */\n if (err instanceof CheckoutError) throw err\n throw new CheckoutError('reservation_failed', 'Inventory reservation failed', {\n cause: err,\n })\n }\n }\n const order = await orders.createFromCheckout({\n orderId,\n customerId: input.customerId ?? null,\n email: input.email,\n billingAddress: input.billingAddress,\n shippingAddress: input.shippingAddress,\n lineItems,\n subtotalMinor: cartDoc.subtotalMinor,\n taxTotalMinor: 0,\n shippingTotalMinor: 0,\n discountTotalMinor: 0,\n totalMinor: cartDoc.subtotalMinor,\n currency: cartDoc.currency,\n ...(input.notes !== undefined && { notes: input.notes }),\n metadata: { cartToken: cartDoc.token, reservationIds } satisfies DraftMetadata,\n cartToken: cartDoc.token,\n })\n return { kind: 'placed', order }\n }\n\n /**\n * The cart's pending order, answered again with its intent as the provider holds it now, or the reason to cancel the\n * order when the provider failed or cancelled that intent. Never `succeeded`: the order is still pending, and only\n * finalize confirms it.\n */\n async function answerExisting(\n order: Order & { paymentIntentId: string },\n ): Promise<BeginCheckoutResult | { closed: string }> {\n const paymentIntent = await payments.getPaymentIntent(order.paymentIntentId)\n if (outcomeOf(paymentIntent.status) === 'failed') {\n return { closed: `payment_${paymentIntent.status}` }\n }\n return {\n orderId: order.id,\n orderNumber: order.orderNumber,\n paymentIntent,\n currency: order.currency,\n totalMinor: order.totalMinor,\n orderStatus: order.status,\n payment: { status: 'requires_action' },\n }\n }\n\n /** The provider's cancel of a superseded order's intent, outside any transaction. */\n async function cancelIntent(order: Order & { paymentIntentId: string }): Promise<void> {\n try {\n await payments.cancelPaymentIntent(order.paymentIntentId)\n } catch (err) {\n if (!(err instanceof PaymentError && err.code === 'payment.cancel_refused')) throw err\n throw new CheckoutError(\n 'payment_in_progress',\n `The payment for order ${order.orderNumber} is already under way`,\n { cause: err, context: { orderNumber: order.orderNumber } },\n )\n }\n }\n\n /**\n * The intent, outside any transaction, then T2 under the cart lock: the intent is stored and, by its status, the order\n * is confirmed (in the same transaction), cancelled with its stock released, or left pending for the provider.\n */\n async function pay(input: BeginCheckoutInput, order: Order): Promise<BeginCheckoutResult> {\n const params: Parameters<PaymentsAdapter['createPaymentIntent']>[0] = {\n amountMinor: order.totalMinor,\n currency: order.currency,\n orderRef: order.id,\n receiptEmail: input.email,\n metadata: { orderId: order.id, orderNumber: order.orderNumber },\n }\n if (input.customerId != null) params.customerId = input.customerId\n let intent: PaymentIntent\n try {\n intent = await payments.createPaymentIntent(params)\n } catch (err) {\n // An order with no intent would hold the cart at checkout.in_progress for good.\n await cancelDraft(order.id, 'payment intent not created')\n throw err\n }\n\n // Why a captured payment did not confirm the order, when it did not.\n let unconfirmed = null as string | null\n const answer = await store.transaction(async (tx) => {\n await repos.cart.lock(tx, input.cartToken)\n await repos.order.setPaymentIntent(tx, order.id, intent.id, new Date())\n let payment: CheckoutPayment\n const outcome = outcomeOf(intent.status)\n if (outcome === 'succeeded') {\n const done = await finalize(intent.id, {\n amountMinor: intent.amountMinor,\n currency: intent.currency,\n })\n if (!done.finalized) unconfirmed = done.reason ?? 'not_confirmed'\n payment =\n unconfirmed === null ? { status: 'succeeded' } : { status: 'failed', reason: unconfirmed }\n } else if (outcome === 'failed') {\n const reason = `payment_${intent.status}`\n await cancelDraft(order.id, reason)\n await publisher.publish(EVT_PAYMENT_FAILED, {\n paymentId: intent.id,\n orderId: order.id,\n reason,\n })\n payment = { status: 'failed', reason }\n } else {\n payment = { status: 'requires_action' }\n }\n const current = await repos.order.findById(tx, order.id)\n logger.info(\n { orderId: order.id, orderNumber: order.orderNumber, payment: payment.status },\n 'checkout started',\n )\n return {\n orderId: order.id,\n orderNumber: order.orderNumber,\n paymentIntent: intent,\n currency: order.currency,\n totalMinor: order.totalMinor,\n orderStatus: current?.status ?? order.status,\n payment,\n }\n })\n // A capture that did not confirm its still-pending order goes back in full, after the commit and outside any\n // transaction (finalize already refunded one whose order was cancelled). The draft is cancelled first, so the\n // capture is recorded on a cancelled order with its refund, never left on a pending one to confirm.\n if (unconfirmed !== null && answer.orderStatus === 'pending') {\n await cancelDraft(order.id, unconfirmed)\n await refundCancelledCapture(\n intent.id,\n { amountMinor: intent.amountMinor, currency: intent.currency },\n order,\n )\n return { ...answer, orderStatus: 'cancelled' }\n }\n return answer\n }\n\n async function finalize(paymentIntentId: string, paid: CapturedPayment): Promise<FinalizeResult> {\n return store.transaction(async (tx) => {\n const outcome = (order: Order | null, reason: string) =>\n recordOutcome(tx, paymentIntentId, order, reason)\n const order = await repos.order.findByPaymentIntentId(tx, paymentIntentId)\n if (order === null || order.status !== 'pending') {\n return settled(tx, paymentIntentId, order, paid)\n }\n // Amount and currency: an underpayment, overpayment or other currency is an outcome, never a confirmation.\n if (\n paid.amountMinor !== order.totalMinor ||\n paid.currency.toUpperCase() !== order.currency.toUpperCase()\n ) {\n return outcome(\n order,\n `amount_mismatch: paid ${paid.amountMinor} ${paid.currency.toUpperCase()}, ` +\n `due ${order.totalMinor} ${order.currency.toUpperCase()}`,\n )\n }\n try {\n // Behind a savepoint: when stock is gone or the order moved first, whatever the earlier lines took is undone.\n return await store.savepoint(() =>\n confirm(tx, paymentIntentId, paid, order, PROVIDER_CAPTURE),\n )\n } catch (err) {\n if (err instanceof StockUnavailable) {\n // A concurrent writer may have confirmed the order with the units this re-take wanted.\n const current = await repos.order.findById(tx, order.id)\n if (current?.status !== 'pending') return settled(tx, paymentIntentId, current, paid)\n return outcome(current, `stock_unavailable: ${err.variantId}`)\n }\n if (!(err instanceof NoLongerPending)) throw err\n }\n // Another delivery (or an admin) moved the order between the read and the write.\n return settled(tx, paymentIntentId, await repos.order.findById(tx, order.id), paid)\n })\n }\n\n return {\n async beginCheckout(input) {\n await loadValidCart(input.cartToken)\n // Intents no longer open with the provider (cancelled by this checkout, or failed or cancelled there), with the\n // reason the pending order holding one is cancelled when the next pass finds it under the lock.\n const closed = new Map<string, string>()\n for (let attempt = 0; ; attempt += 1) {\n const placement = await store.transaction((tx) => place(tx, input, closed))\n if (placement.kind === 'placed') return pay(input, placement.order)\n if (placement.kind === 'existing') {\n const answer = await answerExisting(placement.order)\n if (!('closed' in answer)) return answer\n closed.set(placement.order.paymentIntentId, answer.closed)\n continue\n }\n if (attempt === SUPERSEDE_ATTEMPTS) {\n throw new CheckoutError('in_progress', 'A checkout for this cart is already in progress')\n }\n await cancelIntent(placement.order)\n closed.set(placement.order.paymentIntentId, 'superseded: the cart changed')\n }\n },\n\n finalize,\n\n async cancel(orderId, reason) {\n await cancelDraft(orderId, reason)\n },\n\n async markPaid(orderId, actor, note) {\n // The order's intent is closed with the provider before the payment is recorded, outside any transaction: left\n // open, the shopper could still pay it and be charged twice.\n const found = await store.read((tx) => repos.order.findById(tx, orderId))\n if (!found) throw new NotFoundError('order', orderId)\n if (found.status !== 'pending') {\n throw new StatusTransitionError('order', found.status, 'confirmed')\n }\n if (found.paymentIntentId) {\n try {\n await payments.cancelPaymentIntent(found.paymentIntentId)\n } catch (err) {\n if (!(err instanceof PaymentError && err.code === 'payment.cancel_refused')) throw err\n throw new OrderConflictError(\n 'order.payment_in_progress',\n `The payment for order ${found.orderNumber} is under way with the provider`,\n { cause: err, context: { orderNumber: found.orderNumber } },\n )\n }\n }\n return store.transaction(async (tx) => {\n const order = await repos.order.lock(tx, orderId)\n if (!order) throw new NotFoundError('order', orderId)\n if (order.status !== 'pending') {\n throw new StatusTransitionError('order', order.status, 'confirmed')\n }\n const capture: CaptureRecord = {\n method: 'manual',\n actor,\n note: note ? `payment recorded manually: ${note}` : 'payment recorded manually',\n }\n const paid = { amountMinor: order.totalMinor, currency: order.currency }\n try {\n // No provider took this payment: the events name none.\n await confirm(tx, '', paid, order, capture)\n } catch (err) {\n if (!(err instanceof StockUnavailable)) throw err\n throw new OrderConflictError(\n 'order.stock_unavailable',\n `The stock order ${order.orderNumber} held has gone to another order`,\n { context: { variantId: err.variantId } },\n )\n }\n return (await repos.order.findById(tx, order.id))!\n })\n },\n }\n}\n","import type { SearchAdapter, SearchParams, SearchResult, Logger } from '@nymbalhq/types'\n\nexport interface SearchService {\n products(query: string, params?: SearchParams): Promise<SearchResult>\n}\n\nexport function createSearchService(deps: {\n adapter: SearchAdapter\n logger: Logger\n}): SearchService {\n return {\n async products(query, params) {\n return deps.adapter.search(query, params)\n },\n }\n}\n","import type { Logger, PaymentsAdapter, SearchAdapter } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport type { CommandStore } from '../db/command-store.js'\nimport type { Repositories } from '../repositories/index.js'\nimport type { EventPublisher } from '../events/publisher.js'\nimport { createProductService, type ProductService } from './product-service.js'\nimport { createCategoryService, type CategoryService } from './category-service.js'\nimport { createCartService, type CartService } from './cart-service.js'\nimport { createCustomerService, type CustomerService } from './customer-service.js'\nimport { createAuthService, type AuthService } from './auth-service.js'\nimport { createOrderService, type OrderService } from './order-service.js'\nimport { createInventoryService, type InventoryService } from './inventory-service.js'\nimport {\n createCheckoutService,\n type CheckoutService,\n type ManualPayments,\n} from './checkout-service.js'\nimport { createSearchService, type SearchService } from './search-service.js'\nimport { createRefundService, type RefundService } from './refund-service.js'\n\nexport * from './product-service.js'\nexport * from './category-service.js'\nexport * from './cart-service.js'\nexport * from './customer-service.js'\nexport * from './auth-service.js'\nexport * from './order-service.js'\nexport * from './inventory-service.js'\nexport * from './checkout-service.js'\nexport * from './search-service.js'\nexport * from './refund-service.js'\n\nexport interface ServiceRegistry {\n product: ProductService\n category: CategoryService\n cart: CartService\n customer: CustomerService\n auth: AuthService\n order: OrderService\n inventory: InventoryService\n checkout: CheckoutService & ManualPayments\n refund: RefundService\n search: SearchService\n}\n\nexport interface BuildServicesDeps {\n config: NymbalConfig\n store: CommandStore\n repos: Repositories\n publisher: EventPublisher\n logger: Logger\n payments: PaymentsAdapter\n searchAdapter: SearchAdapter\n}\n\nexport function buildServices(deps: BuildServicesDeps): ServiceRegistry {\n const { config, store, repos, publisher, logger, payments, searchAdapter } = deps\n const inventory = createInventoryService({\n store,\n repos,\n publisher,\n logger: logger.child({ service: 'inventory' }),\n })\n const orders = createOrderService({\n store,\n repos,\n publisher,\n logger: logger.child({ service: 'order' }),\n orderNumberPrefix: config.commerce.orders.numberPrefix,\n orderNumberStart: config.commerce.orders.numberStart,\n })\n const cart = createCartService({\n store,\n carts: repos.cart,\n publisher,\n logger: logger.child({ service: 'cart' }),\n currency: config.store.currency,\n })\n const checkout = createCheckoutService({\n store,\n repos,\n publisher,\n logger: logger.child({ service: 'checkout' }),\n cart,\n orders,\n inventory,\n payments,\n currency: config.store.currency,\n })\n return {\n product: createProductService({\n store,\n repos,\n publisher,\n logger: logger.child({ service: 'product' }),\n }),\n category: createCategoryService({\n repos,\n publisher,\n logger: logger.child({ service: 'category' }),\n }),\n cart,\n customer: createCustomerService({\n repos,\n publisher,\n logger: logger.child({ service: 'customer' }),\n }),\n auth: createAuthService({\n repos,\n publisher,\n logger: logger.child({ service: 'auth' }),\n jwtSecret: config.security.auth.jwtSecret,\n accessTtl: config.security.auth.accessTtl,\n refreshTtl: config.security.auth.refreshTtl,\n }),\n order: orders,\n inventory,\n checkout,\n refund: createRefundService({\n store,\n repos,\n publisher,\n logger: logger.child({ service: 'refund' }),\n payments,\n }),\n search: createSearchService({\n adapter: searchAdapter,\n logger: logger.child({ service: 'search' }),\n }),\n }\n}\n","import type { NymbalConfig } from '@nymbalhq/config'\nimport type { EventBusAdapter, Logger, NymbalEvent } from '@nymbalhq/types'\nimport {\n EVT_CATEGORY_CREATED,\n EVT_CUSTOMER_CREATED,\n EVT_ORDER_PLACED,\n EVT_PRODUCT_CREATED,\n} from '@nymbalhq/types'\nimport { createEventBuilder } from './events/builder.js'\nimport type { Repositories } from './repositories/index.js'\n\nexport interface WarmDocumentStoreDeps {\n config: NymbalConfig\n repos: Repositories\n eventBus: EventBusAdapter\n logger: Logger\n version: string\n}\n\nexport interface WarmResult {\n products: number\n orders: number\n customers: number\n}\n\nexport async function warmDocumentStore(deps: WarmDocumentStoreDeps): Promise<WarmResult> {\n const { config, repos, eventBus, logger, version } = deps\n const makeEvent = createEventBuilder({\n storeId: config.store.name,\n environment:\n process.env.NODE_ENV === 'production'\n ? 'production'\n : process.env.NODE_ENV === 'staging'\n ? 'staging'\n : 'development',\n version,\n source: 'nymbal-warm',\n })\n\n const { products, categories, orders, customers, productEvents } = await repos.product.store.read(\n async (tx) => {\n const [products, categories, orders, customers] = await Promise.all([\n repos.product.list(tx),\n repos.category.list(tx),\n repos.order.list(tx),\n repos.customer.list(tx),\n ])\n const productEvents: NymbalEvent<unknown>[] = []\n for (const p of products) {\n const [variants, categoryIds] = await Promise.all([\n repos.variant.findByProduct(tx, p.id),\n repos.productCategory.listCategoriesForProduct(tx, p.id),\n ])\n productEvents.push(\n makeEvent(EVT_PRODUCT_CREATED, { product: { ...p, variants, categoryIds } }),\n )\n }\n return { products, categories, orders, customers, productEvents }\n },\n )\n\n const events: NymbalEvent<unknown>[] = []\n\n for (const c of categories) {\n events.push(makeEvent(EVT_CATEGORY_CREATED, { category: c }))\n }\n\n events.push(...productEvents)\n\n for (const o of orders) {\n events.push(makeEvent(EVT_ORDER_PLACED, { order: o }))\n }\n\n for (const c of customers) {\n events.push(makeEvent(EVT_CUSTOMER_CREATED, { customerId: c.id, email: c.email }))\n }\n\n if (events.length > 0) {\n await eventBus.replay(events)\n }\n\n logger.info(\n { products: products.length, orders: orders.length, customers: customers.length },\n `Warmed document store: ${products.length} products, ${orders.length} orders, ${customers.length} customers`,\n )\n\n return { products: products.length, orders: orders.length, customers: customers.length }\n}\n","import type { Logger } from '@nymbalhq/types'\nimport type { InventoryService } from '../services/inventory-service.js'\nimport type { InventoryReservationRepository } from '../repositories/inventory-reservation.js'\n\nexport interface SweeperHandle {\n /** One sweep, awaited; the interval calls it. */\n tick(): Promise<void>\n stop(): void\n}\n\nexport interface InventoryReservationSweeperDeps {\n inventoryService: InventoryService\n reservationRepo: InventoryReservationRepository\n logger: Logger\n intervalMs?: number\n}\n\nexport function startInventoryReservationSweeper(\n deps: InventoryReservationSweeperDeps,\n): SweeperHandle {\n const intervalMs = deps.intervalMs ?? 60_000\n const logger = deps.logger.child({ sweeper: 'inventory-reservation' })\n let running = false\n async function tick(): Promise<void> {\n if (running) return\n running = true\n try {\n const { store } = deps.reservationRepo\n const now = new Date()\n const expired = await store.read((tx) => deps.reservationRepo.findExpiredBefore(tx, now))\n if (expired.length > 0) {\n logger.info({ count: expired.length }, 'releasing expired reservations')\n }\n for (const r of expired) {\n // releaseReservation deletes the row and restores its stock in one transaction; one that a commit or another\n // release already took is a no-op.\n await deps.inventoryService.releaseReservation(r.reservationId, 'expired').catch((err) => {\n logger.error({ err, reservationId: r.reservationId }, 'failed to release')\n })\n }\n } finally {\n running = false\n }\n }\n const handle = setInterval(() => {\n void tick()\n }, intervalMs)\n return {\n tick,\n stop() {\n clearInterval(handle)\n },\n }\n}\n","import { EVT_CART_ABANDONED, type Logger } from '@nymbalhq/types'\nimport type { CommandStore } from '../db/command-store.js'\nimport type { CartRepository } from '../repositories/cart.js'\nimport type { EventPublisher } from '../events/publisher.js'\nimport type { SweeperHandle } from './inventory-reservation-sweeper.js'\n\nexport interface CartAbandonmentSweeperDeps {\n store: CommandStore\n carts: CartRepository\n publisher: EventPublisher\n logger: Logger\n intervalMs?: number\n inactivityMs?: number\n /** Carts claimed per transaction; a tick runs as many as it takes to reach every due cart. */\n batchSize?: number\n now?: () => Date\n}\n\n/**\n * Deletes expired carts, then notifies each cart idle past `inactivityMs` once per inactivity period. The notice is\n * a durable claim on the cart row, committed with its `cart.abandoned` event, so a restart or another replica's\n * sweeper does not notify the same period again; a cart write clears the claim.\n */\nexport function startCartAbandonmentSweeper(deps: CartAbandonmentSweeperDeps): SweeperHandle {\n const { store, carts, publisher } = deps\n const intervalMs = deps.intervalMs ?? 5 * 60_000\n const inactivityMs = deps.inactivityMs ?? 24 * 60 * 60_000\n const batchSize = deps.batchSize ?? 500\n const now = deps.now ?? (() => new Date())\n const logger = deps.logger.child({ sweeper: 'cart-abandonment' })\n\n async function tick(): Promise<void> {\n try {\n const at = now()\n const window = { at, cutoff: new Date(at.getTime() - inactivityMs) }\n // Expired carts go first, so a cart past its expiry is never notified.\n const expired = await store.transaction((tx) => carts.deleteExpired(tx, at))\n let abandoned = 0\n // Pages follow the token order rather than \"whatever is still unclaimed\", so a pass ends even when another\n // sweeper holds or has taken some of the rows.\n let after: string | undefined\n for (;;) {\n const page = await store.transaction(async (tx) => {\n const tokens = await carts.listAbandoned(tx, window, { after, limit: batchSize })\n for (const token of tokens) {\n const claimed = await carts.claimAbandoned(tx, token, window)\n if (claimed === null) continue\n await publisher.publish(EVT_CART_ABANDONED, {\n cartId: claimed.token,\n lastActivityAt: claimed.lastActivityAt,\n })\n abandoned += 1\n }\n return tokens\n })\n if (page.length < batchSize) break\n after = page[page.length - 1]\n }\n if (expired > 0 || abandoned > 0) logger.info({ expired, abandoned }, 'carts swept')\n } catch (err) {\n logger.error({ err }, 'cart-abandonment sweep failed')\n }\n }\n\n const handle = setInterval(() => void tick(), intervalMs)\n return {\n tick,\n stop() {\n clearInterval(handle)\n },\n }\n}\n","import type { Logger } from '@nymbalhq/types'\nimport type { CommandStore } from '../db/command-store.js'\nimport type { EventLogRepository } from '../repositories/event-log.js'\nimport type { ProcessedEventRepository } from '../repositories/processed-event.js'\nimport type { SweeperHandle } from './inventory-reservation-sweeper.js'\n\nexport interface EventRetentionSweeperDeps {\n store: CommandStore\n eventLog: EventLogRepository\n processedEvents: ProcessedEventRepository\n logger: Logger\n retentionDays?: number\n intervalMs?: number\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\n/** Deletes delivered events and processed-event records older than the window; undelivered and dead events stay. */\nexport function startEventRetentionSweeper(deps: EventRetentionSweeperDeps): SweeperHandle {\n const retentionDays = deps.retentionDays ?? 30\n const intervalMs = deps.intervalMs ?? 3_600_000\n const logger = deps.logger.child({ sweeper: 'event-retention' })\n let running = false\n\n async function tick(): Promise<void> {\n if (running) return\n running = true\n try {\n const cutoff = new Date(Date.now() - retentionDays * DAY_MS)\n const deleted = await deps.store.transaction(async (tx) => ({\n events: await deps.eventLog.deleteDeliveredBefore(tx, cutoff),\n processed: await deps.processedEvents.deleteBefore(tx, cutoff),\n }))\n if (deleted.events > 0 || deleted.processed > 0) {\n logger.info({ ...deleted, cutoff: cutoff.toISOString() }, 'deleted expired event records')\n }\n } catch (err) {\n logger.error({ err }, 'event retention sweep failed')\n } finally {\n running = false\n }\n }\n\n const handle = setInterval(() => void tick(), intervalMs)\n handle.unref()\n return {\n tick,\n stop() {\n clearInterval(handle)\n },\n }\n}\n","import type { RateLimitAction } from '@nymbalhq/types'\n\nexport interface ParsedRule {\n pattern: string\n regex: RegExp\n requests: number\n windowMs: number\n action: RateLimitAction\n}\n\ninterface Bucket {\n count: number\n resetAt: number\n}\n\nexport class RateLimiter {\n readonly #rules: ParsedRule[]\n readonly #buckets = new Map<string, Bucket>()\n\n constructor(\n rules: Record<string, { requests: number; window: string; action: RateLimitAction }>,\n ) {\n this.#rules = Object.entries(rules).map(([pattern, rule]) => ({\n pattern,\n regex: compilePathPattern(pattern),\n requests: rule.requests,\n windowMs: parseWindow(rule.window),\n action: rule.action,\n }))\n }\n\n check(ip: string, path: string): { allowed: boolean; action: RateLimitAction; retryAfter?: number } | null {\n const rule = this.#rules.find((r) => r.regex.test(path))\n if (!rule) return null\n const key = `${rule.pattern}|${ip}`\n const now = Date.now()\n const bucket = this.#buckets.get(key)\n if (!bucket || bucket.resetAt <= now) {\n this.#buckets.set(key, { count: 1, resetAt: now + rule.windowMs })\n return { allowed: true, action: rule.action }\n }\n bucket.count += 1\n if (bucket.count > rule.requests) {\n return {\n allowed: false,\n action: rule.action,\n retryAfter: Math.max(1, Math.ceil((bucket.resetAt - now) / 1000)),\n }\n }\n return { allowed: true, action: rule.action }\n }\n\n reset(): void {\n this.#buckets.clear()\n }\n}\n\nfunction parseWindow(window: string): number {\n const match = /^(\\d+)(ms|s|m|h)$/.exec(window)\n if (!match) throw new Error(`Invalid rate-limit window: ${window}`)\n const n = Number(match[1])\n switch (match[2]) {\n case 'ms':\n return n\n case 's':\n return n * 1000\n case 'm':\n return n * 60_000\n case 'h':\n return n * 3_600_000\n default:\n throw new Error(`Unreachable unit: ${match[2]}`)\n }\n}\n\nfunction compilePathPattern(pattern: string): RegExp {\n const escaped = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '__DOUBLESTAR__')\n .replace(/\\*/g, '[^/]+')\n .replace(/__DOUBLESTAR__/g, '.*')\n return new RegExp(`^${escaped}$`)\n}\n","import { inArray } from 'drizzle-orm'\nimport { v7 as uuidv7 } from 'uuid'\nimport bcrypt from 'bcryptjs'\nconst { hashSync } = bcrypt\nimport type { DocumentStoreAdapter, EventBusAdapter, Logger, Role } from '@nymbalhq/types'\nimport type { NymbalConfig } from '@nymbalhq/config'\nimport { rawClients, type CommandStore } from '../db/command-store.js'\nimport { createCategoryRepository } from '../db/repositories/categories.js'\nimport { createProductRepository } from '../db/repositories/products.js'\nimport { createEventBuilder } from '../events/builder.js'\nimport { EVT_CATEGORY_CREATED, EVT_PRODUCT_CREATED, EVT_CUSTOMER_CREATED } from '@nymbalhq/types'\nimport * as sqliteSchema from '../db/schema/sqlite.js'\nimport * as postgresSchema from '../db/schema/postgres.js'\nimport { seedCategories, seedProducts, type SeedProduct } from './data.js'\nimport { buildRepositories } from '../repositories/index.js'\nimport { warmDocumentStore } from '../warm-document-store.js'\n\nexport interface SeedDeps {\n config: NymbalConfig\n commandStore: CommandStore\n documentStore: DocumentStoreAdapter\n eventBus: EventBusAdapter\n logger: Logger\n version: string\n}\n\nexport interface SeedResult {\n categories: number\n products: number\n variants: number\n customers: number\n admins: number\n /** True when any demo row was already in the command store, so nothing was inserted. */\n alreadySeeded: boolean\n}\n\nasync function insertVariants(\n store: CommandStore,\n rows: Array<{\n id: string\n productId: string\n sku: string\n name: string\n priceMinor: number\n stock: number\n options: unknown[]\n createdAt: Date\n updatedAt: Date\n }>,\n): Promise<void> {\n if (rows.length === 0) return\n const clients = rawClients(store)\n if (clients.kind === 'sqlite') {\n const values = rows.map((r) => ({\n id: r.id,\n productId: r.productId,\n sku: r.sku,\n name: r.name,\n priceMinor: r.priceMinor,\n compareAtPriceMinor: null,\n weightGrams: null,\n dimensions: null,\n stock: r.stock,\n lowStockThreshold: 3,\n options: JSON.stringify(r.options),\n status: 'active' as const,\n createdAt: r.createdAt.toISOString(),\n updatedAt: r.updatedAt.toISOString(),\n }))\n clients.db.insert(sqliteSchema.variants).values(values).run()\n return\n }\n const values = rows.map((r) => ({\n id: r.id,\n productId: r.productId,\n sku: r.sku,\n name: r.name,\n priceMinor: r.priceMinor,\n compareAtPriceMinor: null,\n weightGrams: null,\n dimensions: null,\n stock: r.stock,\n lowStockThreshold: 3,\n options: r.options,\n status: 'active' as const,\n createdAt: r.createdAt,\n updatedAt: r.updatedAt,\n }))\n await clients.db.insert(postgresSchema.variants).values(values)\n}\n\nasync function insertProductCategories(\n store: CommandStore,\n rows: Array<{ productId: string; categoryId: string }>,\n): Promise<void> {\n if (rows.length === 0) return\n const clients = rawClients(store)\n if (clients.kind === 'sqlite') {\n clients.db.insert(sqliteSchema.productCategories).values(rows).run()\n return\n }\n await clients.db.insert(postgresSchema.productCategories).values(rows)\n}\n\n/**\n * Any demo row (category slug, product slug, seeded customer email) means an earlier seed ran, in full or in part.\n * Each is unique, so inserting the demo again would fail on the first collision: skip instead.\n */\nasync function demoRowsPresent(store: CommandStore, emails: string[]): Promise<boolean> {\n const categorySlugs = seedCategories.map((c) => c.slug)\n const productSlugs = seedProducts.map((p) => p.slug)\n const clients = rawClients(store)\n if (clients.kind === 'sqlite') {\n const { categories, products, customers } = sqliteSchema\n return (\n clients.db\n .select({ id: categories.id })\n .from(categories)\n .where(inArray(categories.slug, categorySlugs))\n .limit(1)\n .all().length > 0 ||\n clients.db\n .select({ id: products.id })\n .from(products)\n .where(inArray(products.slug, productSlugs))\n .limit(1)\n .all().length > 0 ||\n clients.db\n .select({ id: customers.id })\n .from(customers)\n .where(inArray(customers.email, emails))\n .limit(1)\n .all().length > 0\n )\n }\n const { categories, products, customers } = postgresSchema\n const [category, product, customer] = await Promise.all([\n clients.db\n .select({ id: categories.id })\n .from(categories)\n .where(inArray(categories.slug, categorySlugs))\n .limit(1),\n clients.db\n .select({ id: products.id })\n .from(products)\n .where(inArray(products.slug, productSlugs))\n .limit(1),\n clients.db\n .select({ id: customers.id })\n .from(customers)\n .where(inArray(customers.email, emails))\n .limit(1),\n ])\n return category.length > 0 || product.length > 0 || customer.length > 0\n}\n\nasync function insertCustomer(\n store: CommandStore,\n row: {\n id: string\n email: string\n passwordHash: string\n firstName: string\n lastName: string\n roles?: Role[]\n createdAt: Date\n updatedAt: Date\n },\n): Promise<void> {\n const roles = row.roles ?? ['customer']\n const clients = rawClients(store)\n if (clients.kind === 'sqlite') {\n clients.db\n .insert(sqliteSchema.customers)\n .values({\n id: row.id,\n email: row.email,\n passwordHash: row.passwordHash,\n firstName: row.firstName,\n lastName: row.lastName,\n phone: '',\n addresses: '[]',\n orderCount: 0,\n totalSpentMinor: 0,\n metadata: '{}',\n roles: JSON.stringify(roles),\n requiresPasswordReset: false,\n createdAt: row.createdAt.toISOString(),\n updatedAt: row.updatedAt.toISOString(),\n })\n .run()\n return\n }\n await clients.db.insert(postgresSchema.customers).values({\n id: row.id,\n email: row.email,\n passwordHash: row.passwordHash,\n firstName: row.firstName,\n lastName: row.lastName,\n phone: '',\n addresses: [],\n orderCount: 0,\n totalSpentMinor: 0,\n metadata: {},\n roles,\n requiresPasswordReset: false,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n })\n}\n\nexport async function runSeed(deps: SeedDeps): Promise<SeedResult> {\n const { config, commandStore, documentStore, eventBus, logger, version } = deps\n const categoryRepo = createCategoryRepository(commandStore)\n const productRepo = createProductRepository(commandStore)\n const makeEvent = createEventBuilder({\n storeId: config.store.name,\n environment: (process.env.NODE_ENV === 'production' ? 'production' : 'development') as\n | 'production'\n | 'development',\n version,\n source: 'nymbal-seed',\n })\n\n const demoEmail = 'demo@nymbal.dev'\n const adminEmail = process.env['NYMBAL_ADMIN_EMAIL'] ?? 'admin@nymbal.local'\n if (await demoRowsPresent(commandStore, [demoEmail, adminEmail])) {\n logger.info({}, 'Demo content already present, seed skipped')\n return { categories: 0, products: 0, variants: 0, customers: 0, admins: 0, alreadySeeded: true }\n }\n\n const now = new Date()\n\n // Categories\n const categoryInserts = seedCategories.map((c, i) => ({\n id: uuidv7(),\n slug: c.slug,\n name: c.name,\n description: c.description,\n parentId: null,\n position: i,\n createdAt: now,\n }))\n await categoryRepo.insertMany(categoryInserts)\n const categoryBySlug = new Map(categoryInserts.map((c) => [c.slug, c]))\n\n // Products\n const productInserts = seedProducts.map((p) => ({\n id: uuidv7(),\n slug: p.slug,\n name: p.title,\n description: p.description,\n shortDescription: '',\n status: 'active' as const,\n type: 'simple' as const,\n seoTitle: p.title,\n seoDescription: p.description.slice(0, 160),\n media: [{ url: p.imageUrl, altText: p.title, position: 0 }],\n metadata: {},\n createdAt: now,\n updatedAt: now,\n }))\n await productRepo.insertMany(productInserts)\n\n // Variants — one per product (simple type)\n const variantInserts = productInserts.map((p, i) => {\n const seed = seedProducts[i] as SeedProduct\n return {\n id: uuidv7(),\n productId: p.id,\n sku: p.slug.toUpperCase().replaceAll('-', '_'),\n name: 'Default',\n priceMinor: seed.priceMinor,\n stock: 25,\n options: [],\n createdAt: now,\n updatedAt: now,\n }\n })\n await insertVariants(commandStore, variantInserts)\n\n // Product ↔ Category joins\n const joinRows = productInserts.map((p, i) => {\n const seed = seedProducts[i] as SeedProduct\n const cat = categoryBySlug.get(seed.categorySlug)\n if (!cat) throw new Error(`Seed references unknown category: ${seed.categorySlug}`)\n return { productId: p.id, categoryId: cat.id }\n })\n await insertProductCategories(commandStore, joinRows)\n\n // Demo customer — password: nymbal\n const demoCustomer = {\n id: uuidv7(),\n email: demoEmail,\n passwordHash: hashSync('nymbal', 10),\n firstName: 'Demo',\n lastName: 'User',\n createdAt: now,\n updatedAt: now,\n }\n await insertCustomer(commandStore, demoCustomer)\n\n // Admin user — email and password from env, defaults for dev\n const adminPassword = process.env['NYMBAL_ADMIN_PASSWORD'] ?? 'nymbal-admin-dev'\n const adminRoles: Role[] = ['admin']\n const adminCustomer = {\n id: uuidv7(),\n email: adminEmail,\n passwordHash: hashSync(adminPassword, 10),\n firstName: 'Admin',\n lastName: 'User',\n roles: adminRoles,\n createdAt: now,\n updatedAt: now,\n }\n await insertCustomer(commandStore, adminCustomer)\n\n // Document-store read-model rebuild\n const productDocs = new Map<string, Record<string, unknown>>()\n for (let i = 0; i < productInserts.length; i++) {\n const p = productInserts[i]!\n const v = variantInserts[i]!\n const seed = seedProducts[i] as SeedProduct\n const catSlug = seed.categorySlug\n productDocs.set(p.slug, {\n id: p.id,\n storeId: config.store.name,\n slug: p.slug,\n name: p.name,\n description: p.description,\n shortDescription: p.shortDescription,\n status: p.status,\n type: p.type,\n media: p.media,\n priceMinor: v.priceMinor,\n currency: config.store.currency,\n categorySlugs: [catSlug],\n variants: [\n {\n id: v.id,\n sku: v.sku,\n name: v.name,\n priceMinor: v.priceMinor,\n stock: v.stock,\n options: v.options,\n },\n ],\n variantCount: 1,\n inStock: true,\n priceRange: { minMinor: v.priceMinor, maxMinor: v.priceMinor },\n createdAt: now.toISOString(),\n updatedAt: now.toISOString(),\n })\n }\n await documentStore.batchPut('products', productDocs)\n\n // Secondary index: products-by-category\n const byCategory = new Map<string, Record<string, unknown>>()\n for (let i = 0; i < productInserts.length; i++) {\n const p = productInserts[i]!\n const seed = seedProducts[i] as SeedProduct\n const doc = productDocs.get(p.slug)!\n byCategory.set(`category:${seed.categorySlug}#product:${p.slug}`, {\n partitionKey: `category:${seed.categorySlug}`,\n sortKey: `product:${p.slug}`,\n ...doc,\n })\n }\n await documentStore.batchPut('products-by-category', byCategory)\n\n // Category docs\n const categoryDocs = new Map<string, Record<string, unknown>>()\n for (const c of categoryInserts) {\n categoryDocs.set(c.slug, {\n id: c.id,\n storeId: config.store.name,\n slug: c.slug,\n name: c.name,\n description: c.description,\n position: c.position,\n createdAt: now.toISOString(),\n })\n }\n await documentStore.batchPut('categories', categoryDocs)\n\n // Customer profile (no PII)\n await documentStore.put('customer-profiles', demoCustomer.id, {\n customerId: demoCustomer.id,\n orderCount: 0,\n totalSpentMinor: 0,\n segment: 'new',\n createdAt: now.toISOString(),\n })\n\n // Emit events\n const events = [\n ...categoryInserts.map((c) =>\n makeEvent(EVT_CATEGORY_CREATED, {\n category: {\n id: c.id,\n parentId: c.parentId,\n name: c.name,\n slug: c.slug,\n description: c.description,\n position: c.position,\n createdAt: now.toISOString(),\n },\n }),\n ),\n ...productInserts.map((p, i) => {\n const v = variantInserts[i]!\n const seed = seedProducts[i] as SeedProduct\n const cat = categoryBySlug.get(seed.categorySlug)!\n return makeEvent(EVT_PRODUCT_CREATED, {\n product: {\n id: p.id,\n slug: p.slug,\n name: p.name,\n description: p.description,\n shortDescription: p.shortDescription,\n status: p.status,\n type: p.type,\n seoTitle: p.seoTitle,\n seoDescription: p.seoDescription,\n media: p.media,\n metadata: p.metadata,\n createdAt: now.toISOString(),\n updatedAt: now.toISOString(),\n variants: [\n {\n id: v.id,\n productId: p.id,\n sku: v.sku,\n name: v.name,\n priceMinor: v.priceMinor,\n compareAtPriceMinor: null,\n weightGrams: null,\n dimensions: null,\n stock: v.stock,\n lowStockThreshold: 3,\n options: v.options,\n status: 'active' as const,\n createdAt: now.toISOString(),\n updatedAt: now.toISOString(),\n },\n ],\n categoryIds: [cat.id],\n },\n })\n }),\n makeEvent(EVT_CUSTOMER_CREATED, {\n customerId: demoCustomer.id,\n email: demoCustomer.email,\n }),\n makeEvent(EVT_CUSTOMER_CREATED, {\n customerId: adminCustomer.id,\n email: adminCustomer.email,\n }),\n ]\n await eventBus.publishBatch(events)\n\n logger.info({ adminEmail }, 'Admin user seeded')\n if (!process.env['NYMBAL_ADMIN_EMAIL']) {\n console.log(\n `Admin seeded: ${adminEmail} / ${adminPassword} (change NYMBAL_ADMIN_PASSWORD to override)`,\n )\n }\n\n logger.info(\n {\n categories: categoryInserts.length,\n products: productInserts.length,\n variants: variantInserts.length,\n customers: 1,\n admins: 1,\n },\n 'Seed complete',\n )\n\n const repos = buildRepositories(commandStore, documentStore)\n await warmDocumentStore({ config, repos, eventBus, logger, version })\n\n return {\n categories: categoryInserts.length,\n products: productInserts.length,\n variants: variantInserts.length,\n customers: 1,\n admins: 1,\n alreadySeeded: false,\n }\n}\n","export interface SeedCategory {\n slug: string\n name: string\n description: string\n}\n\nexport interface SeedProduct {\n slug: string\n title: string\n description: string\n priceMinor: number\n categorySlug: string\n imageUrl: string\n}\n\nexport const seedCategories: SeedCategory[] = [\n {\n slug: 'apparel',\n name: 'Apparel',\n description: 'Everyday clothing and accessories',\n },\n { slug: 'home', name: 'Home', description: 'Homeware, decor, and kitchen essentials' },\n {\n slug: 'electronics',\n name: 'Electronics',\n description: 'Gadgets, audio, and computing accessories',\n },\n { slug: 'books', name: 'Books', description: 'Fiction, non-fiction, and reference' },\n]\n\nfunction img(seed: string): string {\n return `https://picsum.photos/seed/${encodeURIComponent(seed)}/600/600`\n}\n\nexport const seedProducts: SeedProduct[] = [\n // Apparel — 6\n { slug: 'merino-crew', title: 'Merino Crew Sweater', description: 'Midweight merino wool, unisex fit.', priceMinor: 8900, categorySlug: 'apparel', imageUrl: img('merino-crew') },\n { slug: 'organic-tee', title: 'Organic Cotton Tee', description: 'Heavyweight organic cotton, pre-washed.', priceMinor: 2400, categorySlug: 'apparel', imageUrl: img('organic-tee') },\n { slug: 'selvedge-denim', title: 'Selvedge Denim Jeans', description: '14oz Japanese selvedge, straight leg.', priceMinor: 14500, categorySlug: 'apparel', imageUrl: img('selvedge-denim') },\n { slug: 'runner-socks', title: 'Runner Socks (3-pack)', description: 'Moisture-wicking, cushioned heel.', priceMinor: 1800, categorySlug: 'apparel', imageUrl: img('runner-socks') },\n { slug: 'wool-beanie', title: 'Ribbed Wool Beanie', description: 'Hand-knit in Scotland, one size.', priceMinor: 3200, categorySlug: 'apparel', imageUrl: img('wool-beanie') },\n { slug: 'leather-belt', title: 'Bridle Leather Belt', description: 'Full-grain English bridle leather.', priceMinor: 6500, categorySlug: 'apparel', imageUrl: img('leather-belt') },\n\n // Home — 6\n { slug: 'ceramic-mug', title: 'Stoneware Mug', description: 'Hand-thrown stoneware, 350ml.', priceMinor: 1900, categorySlug: 'home', imageUrl: img('ceramic-mug') },\n { slug: 'linen-sheets', title: 'Washed Linen Sheet Set', description: 'French linen, stonewashed for softness.', priceMinor: 17900, categorySlug: 'home', imageUrl: img('linen-sheets') },\n { slug: 'cast-iron-pan', title: 'Cast Iron Skillet 12\"', description: 'Pre-seasoned, made in the USA.', priceMinor: 7900, categorySlug: 'home', imageUrl: img('cast-iron-pan') },\n { slug: 'soy-candle', title: 'Soy Candle — Fig & Cedar', description: 'Hand-poured, 50hr burn time.', priceMinor: 3400, categorySlug: 'home', imageUrl: img('soy-candle') },\n { slug: 'walnut-board', title: 'Walnut Cutting Board', description: 'End-grain walnut, oiled finish.', priceMinor: 8900, categorySlug: 'home', imageUrl: img('walnut-board') },\n { slug: 'wool-throw', title: 'Lambswool Throw', description: 'Welsh-woven lambswool, 130×180cm.', priceMinor: 11500, categorySlug: 'home', imageUrl: img('wool-throw') },\n\n // Electronics — 6\n { slug: 'wireless-earbuds', title: 'Wireless Earbuds', description: 'Active noise cancellation, 30hr case.', priceMinor: 14900, categorySlug: 'electronics', imageUrl: img('wireless-earbuds') },\n { slug: 'mechanical-keyboard', title: '75% Mechanical Keyboard', description: 'Hot-swap switches, PBT keycaps.', priceMinor: 16500, categorySlug: 'electronics', imageUrl: img('mechanical-keyboard') },\n { slug: 'portable-ssd', title: 'Portable SSD 1TB', description: 'USB-C, 1050MB/s read.', priceMinor: 11900, categorySlug: 'electronics', imageUrl: img('portable-ssd') },\n { slug: 'desk-lamp', title: 'Bias Desk Lamp', description: 'Tunable white, monitor-friendly glare shield.', priceMinor: 9800, categorySlug: 'electronics', imageUrl: img('desk-lamp') },\n { slug: 'usb-c-hub', title: '7-in-1 USB-C Hub', description: 'HDMI 4K60, 100W PD pass-through.', priceMinor: 5900, categorySlug: 'electronics', imageUrl: img('usb-c-hub') },\n { slug: 'bluetooth-speaker', title: 'Portable Bluetooth Speaker', description: 'IPX7 waterproof, 20hr battery.', priceMinor: 8900, categorySlug: 'electronics', imageUrl: img('bluetooth-speaker') },\n\n // Books — 6\n { slug: 'designing-data-intensive-applications', title: 'Designing Data-Intensive Applications', description: 'Martin Kleppmann’s canonical guide to modern data systems.', priceMinor: 3600, categorySlug: 'books', imageUrl: img('ddia') },\n { slug: 'the-pragmatic-programmer', title: 'The Pragmatic Programmer (20th anniversary)', description: 'Hunt & Thomas on the craft of software.', priceMinor: 3200, categorySlug: 'books', imageUrl: img('pragprog') },\n { slug: 'shape-up', title: 'Shape Up', description: 'Stop running in circles — ship work that matters.', priceMinor: 2500, categorySlug: 'books', imageUrl: img('shapeup') },\n { slug: 'the-manager-path', title: 'The Manager’s Path', description: 'Camille Fournier on engineering leadership.', priceMinor: 2800, categorySlug: 'books', imageUrl: img('manager-path') },\n { slug: 'accelerate', title: 'Accelerate', description: 'The science of lean software and DevOps.', priceMinor: 2400, categorySlug: 'books', imageUrl: img('accelerate') },\n { slug: 'working-effectively-with-legacy-code', title: 'Working Effectively with Legacy Code', description: 'Michael Feathers on rescuing complex codebases.', priceMinor: 3400, categorySlug: 'books', imageUrl: img('legacy-code') },\n]\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { MediaStorage } from './storage.js'\n\nexport interface LocalFsMediaStorageOptions {\n root: string\n urlPrefix?: string\n}\n\nexport function createLocalFsMediaStorage(options: LocalFsMediaStorageOptions): MediaStorage {\n const { root } = options\n const urlPrefix = options.urlPrefix ?? '/imported-media'\n\n return {\n async put(key, body, _contentType) {\n const dest = join(root, key)\n const dir = dest.substring(0, dest.lastIndexOf('/'))\n await mkdir(dir, { recursive: true })\n await writeFile(dest, body)\n return { url: `${urlPrefix}/${key}` }\n },\n }\n}\n"],"mappings":"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","names":["sql","resolve","ConfigError","AdapterError","ConfigError","ConfigError","ValidationError","events","ConfigError","rows","products","row","rows","categories","eq","parseJson","parseJson","createProductRepository","col","row","eq","products","base","filtered","rows","pg","eq","parseJson","row","eq","variants","rows","pg","eq","createCategoryRepository","row","eq","categories","rows","and","eq","productCategories","and","eq","rows","eq","sql","parseJson","row","eq","customers","rows","pg","sql","and","eq","refreshTokens","row","eq","db","and","result","and","eq","parseJson","row","eq","orders","o","and","rows","base","filtered","eq","orderHistory","rows","eq","and","asc","eq","r","rows","asc","orderRefunds","and","eq","row","eq","sql","client","row","eq","current","orderSequences","sql","eq","lt","inventoryReservations","row","eq","rows","lt","desc","eq","stockAdjustments","rows","eq","desc","and","desc","eq","row","eq","reviews","cond","and","rows","desc","and","eq","lt","processedEvents","and","eq","lt","and","asc","eq","inArray","isNull","lt","sql","events","and","isNull","asc","inArray","sql","eq","result","lt","and","asc","eq","gt","isNull","lt","sql","parseJson","sql","and","isNull","gt","lt","carts","row","eq","t","rows","asc","createProductRepository","createCategoryRepository","uuidv7","events","AsyncLocalStorage","resolve","deliver","context","categories","order","EVT_ORDER_PAID","PRODUCTS","variants","EVT_CUSTOMER_CREATED","EVT_ORDER_PAID","EVT_ORDER_SHIPPED","EVT_ORDER_PAID","EVT_ORDER_SHIPPED","EVT_CUSTOMER_CREATED","EVT_PRODUCT_CREATED","EVT_PRODUCT_DELETED","EVT_PRODUCT_UPDATED","EVT_ORDER_DELIVERED","reviews","EVT_ORDER_DELIVERED","ConfigError","uuidv7","EVT_PAYMENT_CAPTURED","EVT_PAYMENT_FAILED","EVT_PAYMENT_REFUNDED","PaymentError","PaymentError","toIntent","EVT_PAYMENT_CAPTURED","EVT_PAYMENT_FAILED","EVT_PAYMENT_REFUNDED","uuidv7","amount","AdapterError","EVT_CART_ABANDONED","EVT_CUSTOMER_CREATED","EVT_ORDER_PLACED","EVT_ORDER_SHIPPED","AdapterError","EVT_ORDER_PLACED","EVT_ORDER_SHIPPED","EVT_CUSTOMER_CREATED","EVT_CART_ABANDONED","EVT_PRODUCT_CREATED","EVT_PRODUCT_DELETED","EVT_PRODUCT_UPDATED","EVT_PRODUCT_CREATED","EVT_PRODUCT_UPDATED","EVT_PRODUCT_DELETED","uuidv7","EVT_ORDER_DELIVERED","EVT_ORDER_DELIVERED","uuidv7","AdapterError","AdapterError","AdapterError","AdapterError","reviews","uuidv7","EVT_PRODUCT_CREATED","EVT_PRODUCT_UPDATED","EVT_PRODUCT_DELETED","ValidationError","variants","products","uuidv7","EVT_CATEGORY_CREATED","EVT_CATEGORY_UPDATED","EVT_CATEGORY_DELETED","NotFoundError","ValidationError","uuidv7","NotFoundError","ValidationError","carts","uuidv7","EVT_CUSTOMER_UPDATED","NotFoundError","ValidationError","uuidv7","EVT_CUSTOMER_CREATED","ValidationError","stripPassword","uuidv7","EVT_ORDER_CANCELLED","EVT_ORDER_DELIVERED","EVT_ORDER_PLACED","EVT_ORDER_SHIPPED","NotFoundError","ValidationError","uuidv7","AdapterError","NotFoundError","ValidationError","EVT_INVENTORY_CHANGED","uuidv7","EVT_CART_UPDATED","EVT_ORDER_PAID","EVT_PAYMENT_CAPTURED","EVT_PAYMENT_FAILED","EVT_PAYMENT_REFUNDED","NotFoundError","OrderConflictError","PaymentError","StatusTransitionError","orders","NotFoundError","EVT_PAYMENT_FAILED","uuidv7","currency","context","PaymentError","EVT_PAYMENT_REFUNDED","EVT_PAYMENT_CAPTURED","EVT_ORDER_PAID","EVT_CART_UPDATED","order","StatusTransitionError","OrderConflictError","orders","EVT_CATEGORY_CREATED","EVT_CUSTOMER_CREATED","EVT_ORDER_PLACED","EVT_PRODUCT_CREATED","products","categories","orders","customers","productEvents","variants","EVT_PRODUCT_CREATED","events","EVT_CATEGORY_CREATED","EVT_ORDER_PLACED","EVT_CUSTOMER_CREATED","EVT_CART_ABANDONED","carts","ConfigError","options","registerAllRoutes","inArray","uuidv7","bcrypt","EVT_CATEGORY_CREATED","EVT_PRODUCT_CREATED","EVT_CUSTOMER_CREATED","bcrypt","values","variants","productCategories","categories","products","customers","inArray","uuidv7","events","EVT_CATEGORY_CREATED","EVT_PRODUCT_CREATED","EVT_CUSTOMER_CREATED","join"]}
|