qumra-pos-storage 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -0
- package/dist/StorageAdapter-B2IgHcUF.d.cts +27 -0
- package/dist/StorageAdapter-B2IgHcUF.d.ts +27 -0
- package/dist/better-sqlite3.cjs +96 -0
- package/dist/better-sqlite3.cjs.map +1 -0
- package/dist/better-sqlite3.d.cts +94 -0
- package/dist/better-sqlite3.d.ts +94 -0
- package/dist/better-sqlite3.js +90 -0
- package/dist/better-sqlite3.js.map +1 -0
- package/dist/chunk-CELALQHK.js +38 -0
- package/dist/chunk-CELALQHK.js.map +1 -0
- package/dist/chunk-HXRUTEU7.js +163 -0
- package/dist/chunk-HXRUTEU7.js.map +1 -0
- package/dist/conformance.cjs +170 -0
- package/dist/conformance.cjs.map +1 -0
- package/dist/conformance.d.cts +42 -0
- package/dist/conformance.d.ts +42 -0
- package/dist/conformance.js +3 -0
- package/dist/conformance.js.map +1 -0
- package/dist/index.cjs +1335 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +518 -0
- package/dist/index.d.ts +518 -0
- package/dist/index.js +1154 -0
- package/dist/index.js.map +1 -0
- package/dist/op-sqlite.cjs +73 -0
- package/dist/op-sqlite.cjs.map +1 -0
- package/dist/op-sqlite.d.cts +23 -0
- package/dist/op-sqlite.d.ts +23 -0
- package/dist/op-sqlite.js +38 -0
- package/dist/op-sqlite.js.map +1 -0
- package/dist/wa-sqlite.cjs +68 -0
- package/dist/wa-sqlite.cjs.map +1 -0
- package/dist/wa-sqlite.d.cts +39 -0
- package/dist/wa-sqlite.d.ts +39 -0
- package/dist/wa-sqlite.js +32 -0
- package/dist/wa-sqlite.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema/001_initial.ts","../src/schema/002_outbox_inflight.ts","../src/schema/index.ts","../src/time.ts","../src/migrator.ts","../src/ids.ts","../src/repositories/OrdersRepository.ts","../src/repositories/OutboxRepository.ts","../src/repositories/ProductsRepository.ts","../src/repositories/ReportsRepository.ts","../src/repositories/ShiftsRepository.ts","../src/createStorage.ts","../src/sync/backoff.ts","../src/sync/resources.ts","../src/sync/SyncStateRepository.ts","../src/sync/types.ts","../src/sync/SyncEngine.ts","../src/conformance/assert.ts","../src/conformance/cases.ts","../src/conformance/index.ts"],"names":["uuidv7"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Migration 001 — سكيما v1 الكاملة.\n *\n * محفوظة كـ ثابت نصي في TypeScript (مش ملف .sql خام) عشان يتبنى بنفس الشكل على\n * Node و Electron و React Native والمتصفح من غير أي loader/plugin. Forward-only:\n * أول ما يتشحن في release الملف ده بيتقفل — أي تغيير بيبقى migration جديد.\n */\nexport const SQL_001 = /* sql */ `\n-- ===========================================================================\n-- جداول العمليات (بتتولّد محلياً وبتترفع للسحابة)\n-- ===========================================================================\n\nCREATE TABLE shifts (\n id TEXT PRIMARY KEY,\n cashier_id TEXT NOT NULL,\n opened_at TEXT NOT NULL,\n closed_at TEXT,\n opening_cash INTEGER NOT NULL, -- قروش\n counted_cash INTEGER,\n status TEXT NOT NULL -- open | closed\n);\n\nCREATE TABLE orders (\n id TEXT PRIMARY KEY,\n shift_id TEXT NOT NULL REFERENCES shifts(id),\n cashier_id TEXT NOT NULL,\n status TEXT NOT NULL, -- completed | voided | refunded\n subtotal INTEGER NOT NULL,\n discount INTEGER NOT NULL DEFAULT 0,\n tax INTEGER NOT NULL DEFAULT 0,\n total INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n sync_status TEXT NOT NULL DEFAULT 'pending'\n);\nCREATE INDEX idx_orders_shift ON orders(shift_id);\nCREATE INDEX idx_orders_created ON orders(created_at);\n\n-- snapshot كامل لكل سطر وقت البيع.\nCREATE TABLE order_items (\n id TEXT PRIMARY KEY,\n order_id TEXT NOT NULL REFERENCES orders(id),\n product_id TEXT NOT NULL,\n name_snapshot TEXT NOT NULL, -- الاسم وقت البيع\n unit_price INTEGER NOT NULL, -- السعر وقت البيع\n qty REAL NOT NULL, -- REAL للسماح بالوزني (كيلو)\n line_total INTEGER NOT NULL\n);\nCREATE INDEX idx_items_order ON order_items(order_id);\n\n-- الطلب الواحد ممكن يتدفع بأكتر من طريقة.\nCREATE TABLE payments (\n id TEXT PRIMARY KEY,\n order_id TEXT NOT NULL REFERENCES orders(id),\n method TEXT NOT NULL, -- cash | card | wallet | ...\n amount INTEGER NOT NULL,\n created_at TEXT NOT NULL\n);\nCREATE INDEX idx_payments_order ON payments(order_id);\n\n-- ===========================================================================\n-- الجداول المرجعية (بتنزل من السيرفر — السيرفر مصدر الحقيقة)\n-- ===========================================================================\n\nCREATE TABLE products (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n sku TEXT,\n barcode TEXT,\n price INTEGER NOT NULL,\n category_id TEXT,\n is_active INTEGER NOT NULL DEFAULT 1,\n updated_at TEXT NOT NULL,\n is_local INTEGER NOT NULL DEFAULT 0 -- منتج اتعمل يدوي أوفلاين\n);\nCREATE INDEX idx_products_barcode ON products(barcode);\n\nCREATE TABLE cashiers (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n role TEXT NOT NULL,\n pin_hash TEXT NOT NULL,\n pin_salt TEXT NOT NULL,\n is_active INTEGER NOT NULL DEFAULT 1,\n updated_at TEXT NOT NULL\n);\n\nCREATE TABLE settings (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\n-- ===========================================================================\n-- جداول البنية التحتية\n-- ===========================================================================\n\n-- الـ Outbox: قلب التشغيل الأوفلاين كله.\nCREATE TABLE pending_operations (\n id TEXT PRIMARY KEY, -- UUIDv7 == ترتيب زمني\n op_type TEXT NOT NULL, -- order.create | shift.open | ...\n payload TEXT NOT NULL, -- النسخة الكاملة (JSON) للعملية\n idempotency_key TEXT NOT NULL UNIQUE,\n client_ts TEXT NOT NULL,\n attempts INTEGER NOT NULL DEFAULT 0,\n status TEXT NOT NULL DEFAULT 'pending', -- pending | inflight | synced | failed\n last_error TEXT\n);\nCREATE INDEX idx_ops_status ON pending_operations(status, id);\n\n-- حالة المزامنة لكل مورد (للـ delta pull).\nCREATE TABLE sync_state (\n resource TEXT PRIMARY KEY, -- products | cashiers | settings\n last_pulled TEXT NOT NULL,\n cursor TEXT\n);\n`;\n","/**\n * Migration 002 — تتبّع وقت دخول العملية في حالة inflight.\n *\n * الـ SyncEngine بيعلّم العمليات inflight وهي بتترفع. لو التطبيق اتقفل وسط رفعة،\n * العملية بتفضل عالقة inflight للأبد. عمود inflight_at بيسمح للـ recovery إنه\n * يرجّع أي inflight أقدم من مهلة معيّنة (دقيقتين) لـ pending تاني — والـ idempotency\n * بيحمينا لو كانت وصلت السيرفر فعلاً.\n */\nexport const SQL_002 = /* sql */ `\nALTER TABLE pending_operations ADD COLUMN inflight_at TEXT;\n`;\n","import { SQL_001 } from \"./001_initial\";\nimport { SQL_002 } from \"./002_outbox_inflight\";\n\nexport interface Migration {\n version: number;\n sql: string;\n}\n\n/**\n * migrations مرقّمة و forward-only. جدول _migrations بيتفحص في createStorage().\n * ممنوع تعديل migration اتشحن في release — اعمل واحد جديد بدل التعديل.\n */\nexport const MIGRATIONS: Migration[] = [\n { version: 1, sql: SQL_001 },\n { version: 2, sql: SQL_002 },\n];\n","/** التواريخ بتتخزّن كنصوص ISO-8601 UTC في كل مكان. */\nexport const nowISO = (): string => new Date().toISOString();\n","import type { StorageAdapter } from \"./ports/StorageAdapter\";\nimport { MIGRATIONS } from \"./schema\";\nimport { nowISO } from \"./time\";\n\n/**\n * بيطبّق أي migrations مستنية بالترتيب. كل migration بتتنفذ جوه transaction خاصة\n * بيها، ونسختها بتتسجّل في _migrations جوه نفس الـ transaction — فمستحيل migration\n * اتطبّق نص ونص يتعلّم إنه خلص.\n */\nexport async function runMigrations(adapter: StorageAdapter): Promise<void> {\n await adapter.execute(\n `CREATE TABLE IF NOT EXISTS _migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL\n );`,\n );\n\n const rows = await adapter.query<{ version: number }>(\n `SELECT version FROM _migrations`,\n );\n const applied = new Set(rows.map((r) => r.version));\n\n const pending = MIGRATIONS.filter((m) => !applied.has(m.version)).sort(\n (a, b) => a.version - b.version,\n );\n\n for (const migration of pending) {\n await adapter.transaction(async (tx) => {\n await tx.execute(migration.sql);\n await tx.execute(\n `INSERT INTO _migrations (version, applied_at) VALUES (?, ?)`,\n [migration.version, nowISO()],\n );\n });\n }\n}\n","import { uuidv7 } from \"uuidv7\";\n\n/**\n * كل الـ IDs عبارة عن UUIDv7 بتتولّد على الجهاز. الـ v7 بيحط timestamp في أوله،\n * فالترتيب الأبجدي == الترتيب الزمني — يعني ORDER BY id على الـ outbox بيدينا ترتيب\n * الرفع الصحيح ببلاش، والفهارس بتفضل صغيرة وأكفأ.\n */\nexport const newId = (): string => uuidv7();\n","import { newId } from \"../ids\";\nimport type { StorageAdapter } from \"../ports/StorageAdapter\";\nimport { nowISO } from \"../time\";\nimport type {\n CreateOrderInput,\n Order,\n OrderItem,\n OrderWithDetails,\n Payment,\n} from \"../types\";\nimport type { OutboxRepository } from \"./OutboxRepository\";\n\nexport class OrdersRepository {\n constructor(\n private readonly adapter: StorageAdapter,\n private readonly outbox: OutboxRepository,\n ) {}\n\n /**\n * بيع atomic: الطلب + العناصر + المدفوعات + سطر outbox واحد، كلهم في transaction\n * واحدة. بيتحقق إن مجموع المدفوعات = total الطلب قبل الكتابة — الـ validation في\n * الـ core مش في الـ UI. لو أي جزء فشل، كله بيترجع (rollback).\n */\n async create(input: CreateOrderInput): Promise<OrderWithDetails> {\n if (input.items.length === 0) {\n throw new Error(\"Cannot create an order with no items\");\n }\n if (input.payments.length === 0) {\n throw new Error(\"Cannot create an order with no payments\");\n }\n\n const createdAt = input.createdAt ?? nowISO();\n const orderId = newId();\n const discount = input.discount ?? 0;\n const tax = input.tax ?? 0;\n\n const items: OrderItem[] = input.items.map((it) => ({\n id: newId(),\n order_id: orderId,\n product_id: it.productId,\n name_snapshot: it.nameSnapshot,\n unit_price: it.unitPrice,\n qty: it.qty,\n line_total: it.lineTotal ?? Math.round(it.unitPrice * it.qty),\n }));\n\n const subtotal = items.reduce((sum, it) => sum + it.line_total, 0);\n const total = input.total ?? subtotal - discount + tax;\n\n const payments: Payment[] = input.payments.map((p) => ({\n id: newId(),\n order_id: orderId,\n method: p.method,\n amount: p.amount,\n created_at: createdAt,\n }));\n\n const paymentsTotal = payments.reduce((sum, p) => sum + p.amount, 0);\n if (paymentsTotal !== total) {\n throw new Error(\n `Payments (${paymentsTotal}) do not match order total (${total})`,\n );\n }\n\n const order: Order = {\n id: orderId,\n shift_id: input.shiftId,\n cashier_id: input.cashierId,\n status: input.status ?? \"completed\",\n subtotal,\n discount,\n tax,\n total,\n created_at: createdAt,\n sync_status: \"pending\",\n };\n\n await this.adapter.transaction(async (tx) => {\n await tx.execute(\n `INSERT INTO orders\n (id, shift_id, cashier_id, status, subtotal, discount, tax, total, created_at, sync_status)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n order.id,\n order.shift_id,\n order.cashier_id,\n order.status,\n order.subtotal,\n order.discount,\n order.tax,\n order.total,\n order.created_at,\n order.sync_status,\n ],\n );\n\n for (const it of items) {\n await tx.execute(\n `INSERT INTO order_items\n (id, order_id, product_id, name_snapshot, unit_price, qty, line_total)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n [\n it.id,\n it.order_id,\n it.product_id,\n it.name_snapshot,\n it.unit_price,\n it.qty,\n it.line_total,\n ],\n );\n }\n\n for (const p of payments) {\n await tx.execute(\n `INSERT INTO payments (id, order_id, method, amount, created_at)\n VALUES (?, ?, ?, ?, ?)`,\n [p.id, p.order_id, p.method, p.amount, p.created_at],\n );\n }\n\n await this.outbox.enqueue(tx, {\n opType: \"order.create\",\n payload: { ...order, items, payments },\n idempotencyKey: `order.create:${order.id}`,\n clientTs: createdAt,\n });\n });\n\n return { ...order, items, payments };\n }\n\n async void(orderId: string, opts: { reason: string }): Promise<Order> {\n const voidedAt = nowISO();\n\n return this.adapter.transaction(async (tx) => {\n const rows = await tx.query<Order>(`SELECT * FROM orders WHERE id = ?`, [\n orderId,\n ]);\n const order = rows[0];\n if (!order) throw new Error(`Order not found: ${orderId}`);\n if (order.status === \"voided\") {\n throw new Error(`Order already voided: ${orderId}`);\n }\n\n await tx.execute(`UPDATE orders SET status = 'voided' WHERE id = ?`, [\n orderId,\n ]);\n const voided: Order = { ...order, status: \"voided\" };\n\n await this.outbox.enqueue(tx, {\n opType: \"order.void\",\n payload: { orderId, reason: opts.reason, voidedAt },\n idempotencyKey: `order.void:${orderId}`,\n clientTs: voidedAt,\n });\n\n return voided;\n });\n }\n\n async findByShift(shiftId: string): Promise<Order[]> {\n return this.adapter.query<Order>(\n `SELECT * FROM orders WHERE shift_id = ? ORDER BY created_at`,\n [shiftId],\n );\n }\n\n async getWithDetails(orderId: string): Promise<OrderWithDetails | null> {\n const orders = await this.adapter.query<Order>(\n `SELECT * FROM orders WHERE id = ?`,\n [orderId],\n );\n const order = orders[0];\n if (!order) return null;\n\n const items = await this.adapter.query<OrderItem>(\n `SELECT * FROM order_items WHERE order_id = ?`,\n [orderId],\n );\n const payments = await this.adapter.query<Payment>(\n `SELECT * FROM payments WHERE order_id = ?`,\n [orderId],\n );\n\n return { ...order, items, payments };\n }\n}\n","import { newId } from \"../ids\";\nimport type { SqlParam, StorageAdapter, Tx } from \"../ports/StorageAdapter\";\nimport { nowISO } from \"../time\";\nimport type { PendingOperation } from \"../types\";\n\nexport interface EnqueueInput {\n opType: string;\n /** النسخة الكاملة للعملية، مش diff — أبسط في المعالجة على السيرفر وأسهل في الـ debug. */\n payload: unknown;\n /** لازم يكون فريد عالمياً؛ هو أساس الـ idempotency على السيرفر. */\n idempotencyKey: string;\n clientTs: string;\n}\n\n/** نتيجة عملية بعد ردّ السيرفر: synced (applied/duplicate) أو failed (rejected). */\nexport interface OpResolution {\n op: PendingOperation;\n outcome: \"synced\" | \"failed\";\n error: string | null;\n}\n\n/**\n * جانب الكتابة/القراءة للـ Outbox. دالة enqueue بتتنفذ دايماً جوه نفس الـ transaction\n * بتاعة الكتابة اللي هي تابعة ليها — القاعدة رقم واحد في الكود ريفيو: مفيش كتابة من\n * غير سطر outbox مقابل. جانب الرفع في الـ SyncEngine (مرحلة لاحقة) هو اللي بيستهلكه.\n */\nexport class OutboxRepository {\n constructor(private readonly adapter: StorageAdapter) {}\n\n /** إضافة عملية. اتنادى جوه transaction بتاعة اللي بينادي، ومرّرله الـ tx. */\n async enqueue(tx: Tx, input: EnqueueInput): Promise<void> {\n await tx.execute(\n `INSERT INTO pending_operations\n (id, op_type, payload, idempotency_key, client_ts, attempts, status, last_error)\n VALUES (?, ?, ?, ?, ?, 0, 'pending', NULL)`,\n [\n newId(),\n input.opType,\n JSON.stringify(input.payload),\n input.idempotencyKey,\n input.clientTs,\n ] satisfies SqlParam[],\n );\n }\n\n /** العمليات المستنية بالترتيب الزمني (UUIDv7) — وهو ترتيب الرفع. */\n async listPending(limit = 50): Promise<PendingOperation[]> {\n return this.adapter.query<PendingOperation>(\n `SELECT * FROM pending_operations\n WHERE status = 'pending'\n ORDER BY id\n LIMIT ?`,\n [limit],\n );\n }\n\n async countByStatus(): Promise<Record<string, number>> {\n const rows = await this.adapter.query<{ status: string; n: number }>(\n `SELECT status, COUNT(*) AS n FROM pending_operations GROUP BY status`,\n );\n return Object.fromEntries(rows.map((r) => [r.status, r.n]));\n }\n\n // -------------------------------------------------------------------------\n // جانب المزامنة (بيستهلكه الـ SyncEngine)\n // -------------------------------------------------------------------------\n\n /**\n * بيحجز أقدم دفعة pending (بترتيب UUIDv7) ويعلّمها inflight في transaction واحدة —\n * فمفيش دفعتين بترفعوا نفس العملية. بيزوّد attempts وبيسجّل inflight_at.\n */\n async claimBatch(\n limit = 50,\n inflightAt: string = nowISO(),\n ): Promise<PendingOperation[]> {\n return this.adapter.transaction(async (tx) => {\n const rows = await tx.query<PendingOperation>(\n `SELECT * FROM pending_operations\n WHERE status = 'pending'\n ORDER BY id\n LIMIT ?`,\n [limit],\n );\n if (rows.length === 0) return [];\n\n const ids = rows.map((r) => r.id);\n const placeholders = ids.map(() => \"?\").join(\",\");\n await tx.execute(\n `UPDATE pending_operations\n SET status = 'inflight', inflight_at = ?, attempts = attempts + 1\n WHERE id IN (${placeholders})`,\n [inflightAt, ...ids],\n );\n\n return rows.map((r) => ({\n ...r,\n status: \"inflight\" as const,\n inflight_at: inflightAt,\n attempts: r.attempts + 1,\n }));\n });\n }\n\n /**\n * بيثبّت نتايج الرفع: العمليات الناجحة → synced، والمرفوضة → failed + السبب. وبيعكس\n * الحالة على صف الطلب (orders.sync_status) لعمليات order.* — كله في transaction واحدة.\n */\n async settle(resolutions: OpResolution[]): Promise<void> {\n if (resolutions.length === 0) return;\n await this.adapter.transaction(async (tx) => {\n for (const { op, outcome, error } of resolutions) {\n if (outcome === \"synced\") {\n await tx.execute(\n `UPDATE pending_operations SET status = 'synced', last_error = NULL WHERE id = ?`,\n [op.id],\n );\n } else {\n await tx.execute(\n `UPDATE pending_operations SET status = 'failed', last_error = ? WHERE id = ?`,\n [error, op.id],\n );\n }\n\n // الطلبات بس عندها عمود sync_status محلي نعكس عليه حالة الرفع.\n if (op.op_type === \"order.create\" || op.op_type === \"order.void\") {\n const orderId = op.idempotency_key.slice(op.op_type.length + 1);\n await tx.execute(`UPDATE orders SET sync_status = ? WHERE id = ?`, [\n outcome,\n orderId,\n ]);\n }\n }\n });\n }\n\n /** إرجاع عمليات inflight لـ pending (فشل شبكة أو السيرفر مردّش عليها). */\n async releaseToPending(ids: string[]): Promise<void> {\n if (ids.length === 0) return;\n const placeholders = ids.map(() => \"?\").join(\",\");\n await this.adapter.execute(\n `UPDATE pending_operations\n SET status = 'pending', inflight_at = NULL\n WHERE id IN (${placeholders})`,\n ids,\n );\n }\n\n /**\n * استرجاع العمليات العالقة inflight (تطبيق اتقفل وسط رفعة): أي inflight إما بلا\n * inflight_at أو أقدم من الـ cutoff بترجع pending. الـ idempotency بيحمي لو وصلت فعلاً.\n */\n async recoverStuckInflight(cutoffIso: string): Promise<void> {\n await this.adapter.execute(\n `UPDATE pending_operations\n SET status = 'pending', inflight_at = NULL\n WHERE status = 'inflight'\n AND (inflight_at IS NULL OR inflight_at <= ?)`,\n [cutoffIso],\n );\n }\n\n /** العمليات اللي رُفضت من السيرفر (للعرض للمدير). */\n async listFailed(limit = 50): Promise<PendingOperation[]> {\n return this.adapter.query<PendingOperation>(\n `SELECT * FROM pending_operations\n WHERE status = 'failed'\n ORDER BY id\n LIMIT ?`,\n [limit],\n );\n }\n\n /** إعادة عمليات فاشلة لـ pending (المدير بيعيد المحاولة). بلا ids = كل الفاشلة. */\n async retryFailed(ids?: string[]): Promise<void> {\n if (ids && ids.length > 0) {\n const placeholders = ids.map(() => \"?\").join(\",\");\n await this.adapter.execute(\n `UPDATE pending_operations\n SET status = 'pending', last_error = NULL\n WHERE status = 'failed' AND id IN (${placeholders})`,\n ids,\n );\n } else {\n await this.adapter.execute(\n `UPDATE pending_operations\n SET status = 'pending', last_error = NULL\n WHERE status = 'failed'`,\n );\n }\n }\n}\n","import { newId } from \"../ids\";\nimport type { StorageAdapter } from \"../ports/StorageAdapter\";\nimport { nowISO } from \"../time\";\nimport type { CreateLocalProductInput, Product } from \"../types\";\nimport type { OutboxRepository } from \"./OutboxRepository\";\n\n/** SQLite بيخزّن الـ booleans كـ 0/1 integers؛ نوع الـ domain بيستخدم booleans حقيقية. */\ninterface ProductRow {\n id: string;\n name: string;\n sku: string | null;\n barcode: string | null;\n price: number;\n category_id: string | null;\n is_active: number;\n updated_at: string;\n is_local: number;\n}\n\nconst toProduct = (r: ProductRow): Product => ({\n ...r,\n is_active: r.is_active === 1,\n is_local: r.is_local === 1,\n});\n\nexport class ProductsRepository {\n constructor(\n private readonly adapter: StorageAdapter,\n private readonly outbox: OutboxRepository,\n ) {}\n\n /** البحث في المنتجات النشطة بالاسم أو الباركود أو الـ SKU. */\n async search(text: string): Promise<Product[]> {\n const like = `%${text}%`;\n const rows = await this.adapter.query<ProductRow>(\n `SELECT * FROM products\n WHERE is_active = 1\n AND (name LIKE ? OR barcode LIKE ? OR sku LIKE ?)\n ORDER BY name\n LIMIT 50`,\n [like, like, like],\n );\n return rows.map(toProduct);\n }\n\n async getByBarcode(barcode: string): Promise<Product | null> {\n const rows = await this.adapter.query<ProductRow>(\n `SELECT * FROM products WHERE barcode = ? AND is_active = 1 LIMIT 1`,\n [barcode],\n );\n return rows[0] ? toProduct(rows[0]) : null;\n }\n\n async getById(id: string): Promise<Product | null> {\n const rows = await this.adapter.query<ProductRow>(\n `SELECT * FROM products WHERE id = ?`,\n [id],\n );\n return rows[0] ? toProduct(rows[0]) : null;\n }\n\n /** إنشاء منتج يدوي أوفلاين (is_local = 1). بيترفع كـ draft للمراجعة. */\n async createLocal(input: CreateLocalProductInput): Promise<Product> {\n const product: Product = {\n id: newId(),\n name: input.name,\n sku: input.sku ?? null,\n barcode: input.barcode ?? null,\n price: input.price,\n category_id: input.categoryId ?? null,\n is_active: true,\n updated_at: nowISO(),\n is_local: true,\n };\n\n await this.adapter.transaction(async (tx) => {\n await tx.execute(\n `INSERT INTO products\n (id, name, sku, barcode, price, category_id, is_active, updated_at, is_local)\n VALUES (?, ?, ?, ?, ?, ?, 1, ?, 1)`,\n [\n product.id,\n product.name,\n product.sku,\n product.barcode,\n product.price,\n product.category_id,\n product.updated_at,\n ],\n );\n await this.outbox.enqueue(tx, {\n opType: \"product.create_local\",\n payload: product,\n idempotencyKey: `product.create_local:${product.id}`,\n clientTs: product.updated_at,\n });\n });\n\n return product;\n }\n\n /**\n * upsert بالجملة من delta pull بتاع السيرفر (السيرفر مصدر الحقيقة). مفيش سطر\n * outbox — دي بيانات داخلة (inbound)، مش عملية محلية.\n */\n async upsertMany(products: Product[]): Promise<void> {\n if (products.length === 0) return;\n await this.adapter.transaction(async (tx) => {\n for (const p of products) {\n await tx.execute(\n `INSERT OR REPLACE INTO products\n (id, name, sku, barcode, price, category_id, is_active, updated_at, is_local)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n p.id,\n p.name,\n p.sku,\n p.barcode,\n p.price,\n p.category_id,\n p.is_active ? 1 : 0,\n p.updated_at,\n p.is_local ? 1 : 0,\n ],\n );\n }\n });\n }\n}\n","import type { StorageAdapter } from \"../ports/StorageAdapter\";\nimport type { Cents } from \"../types\";\n\nexport interface ShiftSummary {\n shiftId: string;\n totalSales: Cents;\n orderCount: number;\n byPaymentMethod: Record<string, Cents>;\n topProducts: Array<{ productId: string; name: string; qty: number; total: Cents }>;\n}\n\nexport class ReportsRepository {\n constructor(private readonly adapter: StorageAdapter) {}\n\n async shiftSummary(shiftId: string): Promise<ShiftSummary> {\n // الطلبات المكتملة فقط.\n const totals = await this.adapter.query<{ total: number; n: number }>(\n `SELECT COALESCE(SUM(total), 0) AS total, COUNT(*) AS n\n FROM orders\n WHERE shift_id = ? AND status = 'completed'`,\n [shiftId],\n );\n const totalRow = totals[0] ?? { total: 0, n: 0 };\n\n const byMethodRows = await this.adapter.query<{\n method: string;\n amount: number;\n }>(\n `SELECT p.method AS method, COALESCE(SUM(p.amount), 0) AS amount\n FROM payments p\n JOIN orders o ON o.id = p.order_id\n WHERE o.shift_id = ? AND o.status = 'completed'\n GROUP BY p.method`,\n [shiftId],\n );\n\n const topRows = await this.adapter.query<{\n product_id: string;\n name: string;\n qty: number;\n total: number;\n }>(\n `SELECT oi.product_id AS product_id,\n oi.name_snapshot AS name,\n SUM(oi.qty) AS qty,\n SUM(oi.line_total) AS total\n FROM order_items oi\n JOIN orders o ON o.id = oi.order_id\n WHERE o.shift_id = ? AND o.status = 'completed'\n GROUP BY oi.product_id, oi.name_snapshot\n ORDER BY total DESC\n LIMIT 10`,\n [shiftId],\n );\n\n return {\n shiftId,\n totalSales: totalRow.total,\n orderCount: totalRow.n,\n byPaymentMethod: Object.fromEntries(\n byMethodRows.map((r) => [r.method, r.amount]),\n ),\n topProducts: topRows.map((r) => ({\n productId: r.product_id,\n name: r.name,\n qty: r.qty,\n total: r.total,\n })),\n };\n }\n}\n","import { newId } from \"../ids\";\nimport type { StorageAdapter } from \"../ports/StorageAdapter\";\nimport { nowISO } from \"../time\";\nimport type { CloseShiftInput, OpenShiftInput, Shift } from \"../types\";\nimport type { OutboxRepository } from \"./OutboxRepository\";\n\nexport class ShiftsRepository {\n constructor(\n private readonly adapter: StorageAdapter,\n private readonly outbox: OutboxRepository,\n ) {}\n\n async open(input: OpenShiftInput): Promise<Shift> {\n const shift: Shift = {\n id: newId(),\n cashier_id: input.cashierId,\n opened_at: input.openedAt ?? nowISO(),\n closed_at: null,\n opening_cash: input.openingCash,\n counted_cash: null,\n status: \"open\",\n };\n\n await this.adapter.transaction(async (tx) => {\n await tx.execute(\n `INSERT INTO shifts\n (id, cashier_id, opened_at, closed_at, opening_cash, counted_cash, status)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n [\n shift.id,\n shift.cashier_id,\n shift.opened_at,\n shift.closed_at,\n shift.opening_cash,\n shift.counted_cash,\n shift.status,\n ],\n );\n await this.outbox.enqueue(tx, {\n opType: \"shift.open\",\n payload: shift,\n idempotencyKey: `shift.open:${shift.id}`,\n clientTs: shift.opened_at,\n });\n });\n\n return shift;\n }\n\n async close(shiftId: string, input: CloseShiftInput): Promise<Shift> {\n const closedAt = input.closedAt ?? nowISO();\n\n const shift = await this.adapter.transaction(async (tx) => {\n const existing = await tx.query<Shift>(\n `SELECT * FROM shifts WHERE id = ?`,\n [shiftId],\n );\n const current = existing[0];\n if (!current) throw new Error(`Shift not found: ${shiftId}`);\n if (current.status !== \"open\") {\n throw new Error(`Shift already closed: ${shiftId}`);\n }\n\n await tx.execute(\n `UPDATE shifts\n SET closed_at = ?, counted_cash = ?, status = 'closed'\n WHERE id = ?`,\n [closedAt, input.countedCash, shiftId],\n );\n\n const closed: Shift = {\n ...current,\n closed_at: closedAt,\n counted_cash: input.countedCash,\n status: \"closed\",\n };\n\n await this.outbox.enqueue(tx, {\n opType: \"shift.close\",\n payload: closed,\n idempotencyKey: `shift.close:${shiftId}`,\n clientTs: closedAt,\n });\n\n return closed;\n });\n\n return shift;\n }\n\n /** الوردية المفتوحة الوحيدة على الجهاز ده (v1: وردية == جهاز واحد). */\n async getCurrent(): Promise<Shift | null> {\n const rows = await this.adapter.query<Shift>(\n `SELECT * FROM shifts WHERE status = 'open' ORDER BY opened_at DESC LIMIT 1`,\n );\n return rows[0] ?? null;\n }\n\n async findById(shiftId: string): Promise<Shift | null> {\n const rows = await this.adapter.query<Shift>(\n `SELECT * FROM shifts WHERE id = ?`,\n [shiftId],\n );\n return rows[0] ?? null;\n }\n}\n","import { runMigrations } from \"./migrator\";\nimport type { StorageAdapter } from \"./ports/StorageAdapter\";\nimport { OrdersRepository } from \"./repositories/OrdersRepository\";\nimport { OutboxRepository } from \"./repositories/OutboxRepository\";\nimport { ProductsRepository } from \"./repositories/ProductsRepository\";\nimport { ReportsRepository } from \"./repositories/ReportsRepository\";\nimport { ShiftsRepository } from \"./repositories/ShiftsRepository\";\n\n/**\n * الواجهة المُنمَّطة (typed) اللي التطبيقات بتشوفها. الـ UI عمره ما يكتب SQL —\n * بيتعامل بس مع الـ repositories اللي بترجّع typed domain objects.\n */\nexport interface Storage {\n shifts: ShiftsRepository;\n orders: OrdersRepository;\n products: ProductsRepository;\n reports: ReportsRepository;\n outbox: OutboxRepository;\n /** منفذ خلفي للـ SyncEngine / الاستخدامات المتقدمة. */\n adapter: StorageAdapter;\n close(): Promise<void>;\n}\n\n/**\n * بيركّب طبقة التخزين فوق adapter المنصة: بيطبّق الـ migrations المستنية، وبعدين\n * بيبني الـ repositories. نفس مسار الكود على كل المنصات.\n */\nexport async function createStorage(adapter: StorageAdapter): Promise<Storage> {\n await runMigrations(adapter);\n\n const outbox = new OutboxRepository(adapter);\n return {\n shifts: new ShiftsRepository(adapter, outbox),\n orders: new OrdersRepository(adapter, outbox),\n products: new ProductsRepository(adapter, outbox),\n reports: new ReportsRepository(adapter),\n outbox,\n adapter,\n close: () => adapter.close(),\n };\n}\n","/**\n * Backoff أسّي مع jitter. مهم لما مية جهاز يرجعلهم النت في نفس اللحظة بعد انقطاع\n * عام — من غير jitter هيضربوا السيرفر في نفس الثانية (thundering herd).\n */\nexport interface BackoffConfig {\n baseMs: number;\n capMs: number;\n}\n\nexport const DEFAULT_BACKOFF: BackoffConfig = {\n baseMs: 1000, // 1s\n capMs: 5 * 60 * 1000, // 5 دقايق\n};\n\n/**\n * يحسب مدة الانتظار قبل المحاولة رقم `attempt` (بيبدأ من 1).\n * الأساس أسّي: 1s → 2s → 4s … بسقف، مع \"equal jitter\": نص المدة ثابت + نص عشوائي،\n * فبيفضل تصاعد واضح لكن مع تشتيت كفاية يمنع التزامن.\n */\nexport function computeBackoff(\n attempt: number,\n cfg: BackoffConfig = DEFAULT_BACKOFF,\n random: () => number = Math.random,\n): number {\n const exponent = Math.max(0, attempt - 1);\n const raw = cfg.baseMs * 2 ** exponent;\n const capped = Math.min(cfg.capMs, raw);\n const half = capped / 2;\n return Math.round(half + random() * half);\n}\n","import type { ResourceConfig } from \"./types\";\n\n/** SQLite بيخزّن booleans كـ 0/1. */\nconst bool = (v: unknown, fallback = true): number =>\n (v ?? fallback) ? 1 : 0;\n\nconst nullableStr = (v: unknown): string | null =>\n v == null ? null : String(v);\n\n/**\n * المنتجات: السيرفر مصدر الحقيقة. is_local بيتصفّر دايماً — أي حاجة جاية من السيرفر\n * مش منتج محلي بحكم التعريف، والمحلي بيترفع كـ draft منفصل (مفيش دمج تلقائي).\n * guardLocal بيمنع الـ tombstones من مسح منتج محلي بالغلط.\n */\nexport const PRODUCTS_RESOURCE: ResourceConfig = {\n resource: \"products\",\n table: \"products\",\n guardLocal: true,\n toRow: (r) => ({\n id: String(r.id),\n name: String(r.name),\n sku: nullableStr(r.sku),\n barcode: nullableStr(r.barcode),\n price: Number(r.price),\n category_id: nullableStr(r.category_id),\n is_active: bool(r.is_active),\n updated_at: String(r.updated_at),\n is_local: 0,\n }),\n};\n\nexport const CASHIERS_RESOURCE: ResourceConfig = {\n resource: \"cashiers\",\n table: \"cashiers\",\n toRow: (r) => ({\n id: String(r.id),\n name: String(r.name),\n role: String(r.role),\n pin_hash: String(r.pin_hash),\n pin_salt: String(r.pin_salt),\n is_active: bool(r.is_active),\n updated_at: String(r.updated_at),\n }),\n};\n\nexport const SETTINGS_RESOURCE: ResourceConfig = {\n resource: \"settings\",\n table: \"settings\",\n idColumn: \"key\",\n toRow: (r) => ({\n key: String(r.key),\n value: String(r.value),\n updated_at: String(r.updated_at),\n }),\n};\n\n/** الموارد الافتراضية للـ pull بالترتيب. */\nexport const DEFAULT_RESOURCES: ResourceConfig[] = [\n PRODUCTS_RESOURCE,\n CASHIERS_RESOURCE,\n SETTINGS_RESOURCE,\n];\n","import type { StorageAdapter } from \"../ports/StorageAdapter\";\n\n/** صف حالة المزامنة لمورد واحد (كل مورد بيتزامن مستقل). */\nexport interface SyncStateRow {\n resource: string;\n last_pulled: string;\n cursor: string | null;\n}\n\n/**\n * جدول sync_state: لكل مورد (products/cashiers/settings) آخر وقت pull والمؤشر —\n * عشان الـ delta pull يكمّل من حيث وقف.\n */\nexport class SyncStateRepository {\n constructor(private readonly adapter: StorageAdapter) {}\n\n async get(resource: string): Promise<SyncStateRow | null> {\n const rows = await this.adapter.query<SyncStateRow>(\n `SELECT * FROM sync_state WHERE resource = ?`,\n [resource],\n );\n return rows[0] ?? null;\n }\n\n async set(\n resource: string,\n lastPulled: string,\n cursor: string | null,\n ): Promise<void> {\n await this.adapter.execute(\n `INSERT OR REPLACE INTO sync_state (resource, last_pulled, cursor)\n VALUES (?, ?, ?)`,\n [resource, lastPulled, cursor],\n );\n }\n}\n","/**\n * عقود الـ SyncEngine مع العالم الخارجي. الـ transport هو نقطة الحقن الوحيدة —\n * الاختبارات بتمرّر mock server، والإنتاج بيمرّر تطبيقك أنت للـ transport (REST/GraphQL).\n */\nimport type { SqlParam } from \"../ports/StorageAdapter\";\n\n// ---------------------------------------------------------------------------\n// Push — رفع الـ Outbox\n// ---------------------------------------------------------------------------\n\n/** الشكل اللي العملية بتتبعت بيه للسيرفر (payload متفكوك من JSON). */\nexport interface PushOperation {\n idempotency_key: string;\n op_type: string;\n client_ts: string;\n payload: unknown;\n}\n\nexport type OpResultStatus = \"applied\" | \"duplicate\" | \"rejected\";\n\n/** نتيجة السيرفر لكل عملية. applied و duplicate الاتنين نجاح. */\nexport interface OpResult {\n idempotency_key: string;\n status: OpResultStatus;\n /** موجود مع rejected بس. */\n error?: string;\n}\n\nexport interface PushResponse {\n results: OpResult[];\n}\n\n// ---------------------------------------------------------------------------\n// Pull — تنزيل البيانات المرجعية (delta)\n// ---------------------------------------------------------------------------\n\nexport interface DeltaResponse {\n /** صفوف اتغيّرت/اتضافت (السيرفر مصدر الحقيقة). */\n changed: Record<string, unknown>[];\n /** IDs محذوفة (tombstones) — الحذف صريح مش استنتاج من الغياب. */\n deleted: string[];\n /** المؤشر الجديد اللي نبعته في الـ pull الجاي. */\n cursor: string;\n /** فيه صفحات أكتر ورا المؤشر ده؟ */\n hasMore?: boolean;\n}\n\n/** سياق بيتمرّر لكل نداء transport (التوكن؛ null معناه مفيش auth). */\nexport interface TransportContext {\n token: string | null;\n}\n\nexport interface SyncTransport {\n /** POST /pos/v1/operations/batch — يرمي عند فشل الشبكة/السيرفر (5xx). */\n pushBatch(\n ops: PushOperation[],\n ctx: TransportContext,\n ): Promise<PushResponse>;\n\n /** GET /pos/v1/catalog/delta — يرمي عند فشل الشبكة/السيرفر (5xx). */\n pullDelta(\n resource: string,\n since: string,\n cursor: string | null,\n ctx: TransportContext,\n ): Promise<DeltaResponse>;\n}\n\n// ---------------------------------------------------------------------------\n// إعداد الموارد للـ pull\n// ---------------------------------------------------------------------------\n\n/**\n * بيوصّف إزاي مورد سيرفر بيتكتب محلياً. أسماء الجدول/الأعمدة من عندنا (مش إدخال\n * مستخدم) فآمنة، والقيم دايماً بتتمرّر كـ parameters.\n */\nexport interface ResourceConfig {\n resource: string;\n table: string;\n /** العمود المفتاح للحذف بالـ tombstones (افتراضي \"id\"). */\n idColumn?: string;\n /** يحوّل صف السيرفر (JSON) لصف قاعدة بيانات (booleans → 0/1 …). */\n toRow(serverRow: Record<string, unknown>): Record<string, SqlParam>;\n /** يحمي الصفوف المحلية (is_local=1) من الحذف بالـ tombstones. للمنتجات. */\n guardLocal?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// الحالة للـ UI\n// ---------------------------------------------------------------------------\n\nexport interface FailedOp {\n id: string;\n opType: string;\n error: string;\n}\n\nexport interface SyncStatus {\n /** آخر نداء شبكة نجح؟ */\n online: boolean;\n /** متوقّف بسبب انتهاء الـ auth (getAuthToken=null)؟ */\n paused: boolean;\n /** المحرك شغّال (start اتنادى ولسه ما stopناش)؟ */\n running: boolean;\n pendingCount: number;\n inflightCount: number;\n failedOps: FailedOp[];\n lastPushAt: string | null;\n lastPullAt: string | null;\n lastError: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// نتايج الدورات\n// ---------------------------------------------------------------------------\n\nexport interface PushOutcome {\n synced: number;\n duplicated: number;\n failed: number;\n /** الـ outbox اتفضّى بالكامل؟ (false لو وقف بسبب شبكة/توقّف/pause). */\n drained: boolean;\n}\n\nexport interface PullOutcome {\n upserted: number;\n deleted: number;\n}\n\n/** فشل شبكة/سيرفر (قابل لإعادة المحاولة) — على عكس رفض عملية (دائم). */\nexport class SyncNetworkError extends Error {\n constructor(message: string, cause?: unknown) {\n super(message, { cause });\n this.name = \"SyncNetworkError\";\n }\n}\n","import type { Storage } from \"../createStorage\";\nimport type { StorageAdapter } from \"../ports/StorageAdapter\";\nimport type {\n OpResolution,\n OutboxRepository,\n} from \"../repositories/OutboxRepository\";\nimport type { PendingOperation } from \"../types\";\nimport { computeBackoff, DEFAULT_BACKOFF, type BackoffConfig } from \"./backoff\";\nimport { DEFAULT_RESOURCES } from \"./resources\";\nimport { SyncStateRepository } from \"./SyncStateRepository\";\nimport {\n SyncNetworkError,\n type PullOutcome,\n type PushOperation,\n type PushOutcome,\n type ResourceConfig,\n type SyncStatus,\n type SyncTransport,\n} from \"./types\";\n\nconst FIVE_MIN = 5 * 60 * 1000;\nconst TWO_MIN = 2 * 60 * 1000;\n\nexport interface SyncEngineOptions {\n transport: SyncTransport;\n /** حجم دفعة الرفع (افتراضي 50). */\n batchSize?: number;\n /** فترة الـ pull الدوري (افتراضي 5 دقايق). */\n pullIntervalMs?: number;\n /** مهلة اعتبار عملية inflight عالقة (افتراضي دقيقتين). */\n stuckInflightMs?: number;\n backoff?: Partial<BackoffConfig>;\n /** سقف محاولات الـ backoff قبل الاستسلام لهذه الدورة (افتراضي بلا سقف). */\n maxPushRetries?: number;\n /** موارد الـ pull (افتراضي products/cashiers/settings). */\n resources?: ResourceConfig[];\n /** التوكن الحالي؛ null معناه إيقاف مؤقت (مش استثناء) — الـ sync بيقف بس. */\n getAuthToken?: () => string | null;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n random?: () => number;\n onError?: (err: unknown, ctx: string) => void;\n}\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst errMsg = (err: unknown): string =>\n err instanceof Error ? err.message : String(err);\n\nconst toPushOp = (op: PendingOperation): PushOperation => ({\n idempotency_key: op.idempotency_key,\n op_type: op.op_type,\n client_ts: op.client_ts,\n payload: JSON.parse(op.payload),\n});\n\n/** نتيجة داخلية لدورة push واحدة — بتحمل فشل الشبكة بدل ما ترميه، عشان التجميع. */\ninterface PushCycle extends PushOutcome {\n networkError: SyncNetworkError | null;\n paused: boolean;\n}\n\n/**\n * محرك المزامنة: بيرفع الـ outbox (push) وبينزّل البيانات المرجعية (pull).\n *\n * قابل للحقن بالكامل (transport/now/sleep/random) عشان اختبارات المحاكاة تتحكم في\n * الزمن والشبكة. القواعد:\n * - Push: دفعات 50 بترتيب UUIDv7؛ applied|duplicate = نجاح، rejected = فشل دائم،\n * فشل شبكة = رجوع pending + backoff.\n * - Pull: delta لكل مورد مستقل، INSERT OR REPLACE + حذف بالـ tombstones.\n */\nexport class SyncEngine {\n private readonly transport: SyncTransport;\n private readonly outbox: OutboxRepository;\n private readonly adapter: StorageAdapter;\n private readonly syncState: SyncStateRepository;\n private readonly resources: ResourceConfig[];\n private readonly batchSize: number;\n private readonly pullIntervalMs: number;\n private readonly stuckInflightMs: number;\n private readonly backoff: BackoffConfig;\n private readonly maxPushRetries: number;\n private readonly getAuthToken: () => string | null;\n private readonly now: () => number;\n private readonly sleep: (ms: number) => Promise<void>;\n private readonly random: () => number;\n private readonly onError: (err: unknown, ctx: string) => void;\n\n private readonly listeners = new Set<(s: SyncStatus) => void>();\n private status: SyncStatus = {\n online: false,\n paused: false,\n running: false,\n pendingCount: 0,\n inflightCount: 0,\n failedOps: [],\n lastPushAt: null,\n lastPullAt: null,\n lastError: null,\n };\n private stopped = false;\n private pullTimer: ReturnType<typeof setInterval> | null = null;\n /** يخلّي الـ push single-flight — نداءات requestPush بتتسلسل. */\n private pushChain: Promise<unknown> = Promise.resolve();\n\n constructor(storage: Storage, opts: SyncEngineOptions) {\n this.transport = opts.transport;\n this.outbox = storage.outbox;\n this.adapter = storage.adapter;\n this.syncState = new SyncStateRepository(storage.adapter);\n this.resources = opts.resources ?? DEFAULT_RESOURCES;\n this.batchSize = opts.batchSize ?? 50;\n this.pullIntervalMs = opts.pullIntervalMs ?? FIVE_MIN;\n this.stuckInflightMs = opts.stuckInflightMs ?? TWO_MIN;\n this.backoff = { ...DEFAULT_BACKOFF, ...opts.backoff };\n this.maxPushRetries = opts.maxPushRetries ?? Number.POSITIVE_INFINITY;\n this.getAuthToken = opts.getAuthToken ?? (() => \"\");\n this.now = opts.now ?? Date.now;\n this.sleep = opts.sleep ?? defaultSleep;\n this.random = opts.random ?? Math.random;\n this.onError = opts.onError ?? (() => {});\n }\n\n // -------------------------------------------------------------------------\n // الحالة\n // -------------------------------------------------------------------------\n\n getStatus(): SyncStatus {\n return this.snapshot();\n }\n\n /** اشتراك في تغيّر الحالة. بيتنادى فوراً بالحالة الحالية، ويرجّع دالة إلغاء. */\n onStatusChange(cb: (s: SyncStatus) => void): () => void {\n this.listeners.add(cb);\n cb(this.snapshot());\n return () => this.listeners.delete(cb);\n }\n\n private snapshot(): SyncStatus {\n return { ...this.status, failedOps: this.status.failedOps.map((f) => ({ ...f })) };\n }\n\n private emit(): void {\n const snap = this.snapshot();\n for (const cb of this.listeners) {\n try {\n cb(snap);\n } catch (err) {\n this.onError(err, \"listener\");\n }\n }\n }\n\n private async refreshCounts(): Promise<void> {\n const counts = await this.outbox.countByStatus();\n this.status.pendingCount = counts[\"pending\"] ?? 0;\n this.status.inflightCount = counts[\"inflight\"] ?? 0;\n const failed = await this.outbox.listFailed(50);\n this.status.failedOps = failed.map((o) => ({\n id: o.id,\n opType: o.op_type,\n error: o.last_error ?? \"unknown\",\n }));\n }\n\n private isPaused(): boolean {\n return this.getAuthToken() === null;\n }\n\n private isoNow(): string {\n return new Date(this.now()).toISOString();\n }\n\n // -------------------------------------------------------------------------\n // الاسترجاع عند الإقلاع\n // -------------------------------------------------------------------------\n\n /** يرجّع أي عملية inflight عالقة (أقدم من المهلة) لـ pending. اتنادى عند الإقلاع. */\n async recover(): Promise<void> {\n const cutoff = new Date(this.now() - this.stuckInflightMs).toISOString();\n await this.outbox.recoverStuckInflight(cutoff);\n await this.refreshCounts();\n this.emit();\n }\n\n // -------------------------------------------------------------------------\n // Push\n // -------------------------------------------------------------------------\n\n /**\n * يفضّي الـ outbox في دفعات لحد ما يخلص أو يقابل فشل شبكة/توقّف/pause.\n * مابيرميش لفشل الشبكة — بيرجّعه في النتيجة عشان pushWithBackoff يجمّع ويعيد.\n */\n private async pushCycle(): Promise<PushCycle> {\n const result: PushCycle = {\n synced: 0,\n duplicated: 0,\n failed: 0,\n drained: false,\n networkError: null,\n paused: false,\n };\n\n if (this.isPaused()) {\n this.status.paused = true;\n result.paused = true;\n this.emit();\n return result;\n }\n this.status.paused = false;\n\n for (;;) {\n if (this.stopped) return result;\n\n const batch = await this.outbox.claimBatch(this.batchSize, this.isoNow());\n if (batch.length === 0) {\n result.drained = true;\n return result;\n }\n\n let resp;\n try {\n resp = await this.transport.pushBatch(batch.map(toPushOp), {\n token: this.getAuthToken(),\n });\n } catch (err) {\n // فشل شبكة/سيرفر: رجّع الدفعة pending واخرج للـ backoff.\n await this.outbox.releaseToPending(batch.map((b) => b.id));\n this.status.online = false;\n this.status.lastError = errMsg(err);\n await this.refreshCounts();\n this.emit();\n result.networkError = new SyncNetworkError(errMsg(err), err);\n return result;\n }\n\n const byKey = new Map(resp.results.map((r) => [r.idempotency_key, r]));\n const resolutions: OpResolution[] = [];\n const orphaned: string[] = [];\n\n for (const op of batch) {\n const r = byKey.get(op.idempotency_key);\n if (!r) {\n // السيرفر مردّش على العملية دي — رجّعها pending للدورة الجاية.\n orphaned.push(op.id);\n continue;\n }\n if (r.status === \"applied\" || r.status === \"duplicate\") {\n // الاتنين نجاح: duplicate معناها رفعة سابقة وصلت بس الـ ack ضاع.\n resolutions.push({ op, outcome: \"synced\", error: null });\n if (r.status === \"duplicate\") result.duplicated++;\n else result.synced++;\n } else {\n resolutions.push({ op, outcome: \"failed\", error: r.error ?? \"rejected\" });\n result.failed++;\n }\n }\n\n await this.outbox.settle(resolutions);\n await this.outbox.releaseToPending(orphaned);\n\n this.status.online = true;\n this.status.lastError = null;\n this.status.lastPushAt = this.isoNow();\n await this.refreshCounts();\n this.emit();\n }\n }\n\n /**\n * push مع إعادة محاولة تلقائية + exponential backoff عند فشل الشبكة، لحد ما\n * يفضّي الـ outbox أو يتوقّف/يتعلّق (pause) أو يوصل سقف المحاولات.\n */\n async push(): Promise<PushOutcome> {\n const agg: PushOutcome = {\n synced: 0,\n duplicated: 0,\n failed: 0,\n drained: false,\n };\n let attempt = 0;\n\n for (;;) {\n if (this.stopped) return agg;\n\n // pushCycle بيكتشف الـ pause بنفسه (بيضبط status.paused ويرجّع paused=true).\n const cycle = await this.pushCycle();\n agg.synced += cycle.synced;\n agg.duplicated += cycle.duplicated;\n agg.failed += cycle.failed;\n agg.drained = cycle.drained;\n\n if (cycle.paused) return agg;\n if (!cycle.networkError) return agg; // اتفضّى بنجاح\n\n attempt++;\n if (attempt > this.maxPushRetries) return agg;\n await this.sleep(computeBackoff(attempt, this.backoff, this.random));\n }\n }\n\n /** يجدول push على سلسلة single-flight (نداءات متتالية مبتتزاحمش). */\n requestPush(): Promise<void> {\n this.pushChain = this.pushChain\n .catch(() => undefined)\n .then(() => this.push())\n .catch((err) => this.onError(err, \"push\"));\n return this.pushChain.then(() => undefined);\n }\n\n // -------------------------------------------------------------------------\n // Pull\n // -------------------------------------------------------------------------\n\n /** ينزّل delta لكل مورد ويكتبه محلياً. بيرمي SyncNetworkError عند فشل الشبكة. */\n async pull(): Promise<PullOutcome> {\n const outcome: PullOutcome = { upserted: 0, deleted: 0 };\n\n if (this.isPaused()) {\n this.status.paused = true;\n this.emit();\n return outcome;\n }\n this.status.paused = false;\n\n for (const cfg of this.resources) {\n const state = await this.syncState.get(cfg.resource);\n let since = state?.last_pulled ?? \"\";\n let cursor = state?.cursor ?? null;\n\n for (;;) {\n let delta;\n try {\n delta = await this.transport.pullDelta(cfg.resource, since, cursor, {\n token: this.getAuthToken(),\n });\n } catch (err) {\n this.status.online = false;\n this.status.lastError = errMsg(err);\n this.emit();\n throw new SyncNetworkError(errMsg(err), err);\n }\n\n await this.applyDelta(cfg, delta);\n outcome.upserted += delta.changed.length;\n outcome.deleted += delta.deleted.length;\n\n const pulledAt = this.isoNow();\n await this.syncState.set(cfg.resource, pulledAt, delta.cursor);\n since = pulledAt;\n cursor = delta.cursor;\n\n if (!delta.hasMore) break;\n }\n }\n\n this.status.online = true;\n this.status.lastError = null;\n this.status.lastPullAt = this.isoNow();\n this.emit();\n return outcome;\n }\n\n /** كتابة دفعة delta في transaction واحدة: upsert للمتغيّر + حذف الـ tombstones. */\n private async applyDelta(\n cfg: ResourceConfig,\n delta: { changed: Record<string, unknown>[]; deleted: string[] },\n ): Promise<void> {\n if (delta.changed.length === 0 && delta.deleted.length === 0) return;\n const idColumn = cfg.idColumn ?? \"id\";\n\n await this.adapter.transaction(async (tx) => {\n for (const raw of delta.changed) {\n const row = cfg.toRow(raw);\n const cols = Object.keys(row);\n const placeholders = cols.map(() => \"?\").join(\",\");\n await tx.execute(\n `INSERT OR REPLACE INTO ${cfg.table} (${cols.join(\",\")}) VALUES (${placeholders})`,\n cols.map((c) => row[c]!),\n );\n }\n\n if (delta.deleted.length > 0) {\n const placeholders = delta.deleted.map(() => \"?\").join(\",\");\n const guard = cfg.guardLocal ? \" AND is_local = 0\" : \"\";\n await tx.execute(\n `DELETE FROM ${cfg.table} WHERE ${idColumn} IN (${placeholders})${guard}`,\n delta.deleted,\n );\n }\n });\n }\n\n // -------------------------------------------------------------------------\n // التنسيق العام\n // -------------------------------------------------------------------------\n\n /** رفع ثم تنزيل — للزر اليدوي وبعد إعادة الاتصال. أخطاء الـ pull الشبكية بتتبلع. */\n async syncNow(): Promise<void> {\n await this.push();\n try {\n await this.pull();\n } catch (err) {\n if (!(err instanceof SyncNetworkError)) throw err;\n this.onError(err, \"pull\");\n }\n }\n\n /** بدء التشغيل: استرجاع + مزامنة فورية + pull دوري كل fiveMin. */\n start(): void {\n this.stopped = false;\n this.status.running = true;\n this.emit();\n\n void this.recover()\n .then(() => this.syncNow())\n .catch((err) => this.onError(err, \"start\"));\n\n this.pullTimer = setInterval(() => {\n void this.pull().catch((err) => {\n if (!(err instanceof SyncNetworkError)) this.onError(err, \"pull-interval\");\n });\n }, this.pullIntervalMs);\n }\n\n /** إيقاف: بيوقف الـ timer وبيخلّي أي push/backoff جاري يخرج عند أقرب نقطة. */\n stop(): void {\n this.stopped = true;\n this.status.running = false;\n if (this.pullTimer) {\n clearInterval(this.pullTimer);\n this.pullTimer = null;\n }\n this.emit();\n }\n}\n","/**\n * assertions صغيرة مستقلة عن أي test runner — علشان نفس الـ conformance cases\n * تشتغل تحت vitest (Node) و Playwright (المتصفح، لـ wa-sqlite) من غير تغيير.\n * الفشل = throw.\n */\nexport function assert(cond: unknown, msg: string): asserts cond {\n if (!cond) throw new Error(`conformance: ${msg}`);\n}\n\nexport function assertEqual(actual: unknown, expected: unknown, msg: string): void {\n const a = JSON.stringify(actual);\n const e = JSON.stringify(expected);\n if (a !== e) {\n throw new Error(`conformance: ${msg} — المتوقع ${e} لكن جه ${a}`);\n }\n}\n\nexport function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n\n/** يتأكد إن fn رمت (للتحقق من الـ rollback / إعادة الرمي). */\nexport async function assertThrows(\n fn: () => Promise<unknown>,\n msg: string,\n): Promise<void> {\n let threw = false;\n try {\n await fn();\n } catch {\n threw = true;\n }\n assert(threw, msg);\n}\n","import type { StorageAdapter } from \"../ports/StorageAdapter\";\nimport { assert, assertEqual, assertThrows, bytesEqual } from \"./assert\";\n\n/** بيرجّع adapter جديد فاضي (مفضّل :memory:) لكل حالة. */\nexport type MakeAdapter = () => Promise<StorageAdapter> | StorageAdapter;\n\nexport interface ConformanceCase {\n name: string;\n run(make: MakeAdapter): Promise<void>;\n}\n\n/** helper: يفتح adapter، ينفّذ الجسم، ويقفل مهما حصل. */\nasync function withAdapter(\n make: MakeAdapter,\n body: (a: StorageAdapter) => Promise<void>,\n): Promise<void> {\n const adapter = await make();\n try {\n await body(adapter);\n } finally {\n await adapter.close();\n }\n}\n\n/**\n * بطارية العقد اللي أي StorageAdapter لازم يعدّيها قبل الدمج. بتختبر عقد الـ\n * adapter نفسه (execute/query/params/transaction/close) — مش الـ repositories.\n */\nexport const CONFORMANCE_CASES: ConformanceCase[] = [\n {\n name: \"execute + query: إنشاء وإدراج وقراءة\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\"CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)\");\n await a.execute(\"INSERT INTO t (id, name) VALUES (?, ?)\", [1, \"قهوة\"]);\n const rows = await a.query<{ id: number; name: string }>(\n \"SELECT id, name FROM t\",\n );\n assertEqual(rows, [{ id: 1, name: \"قهوة\" }], \"صف واحد بالقيم الصح\");\n }),\n },\n\n {\n name: \"المعاملات: string / number / null / blob تتربط وترجع صح\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\n \"CREATE TABLE t (id INTEGER, s TEXT, n REAL, z TEXT, b BLOB)\",\n );\n const blob = new Uint8Array([0, 255, 16, 200]);\n await a.execute(\"INSERT INTO t (id, s, n, z, b) VALUES (?, ?, ?, ?, ?)\", [\n 7,\n \"نص\",\n 12.5,\n null,\n blob,\n ]);\n const rows = await a.query<{\n id: number;\n s: string;\n n: number;\n z: string | null;\n b: Uint8Array;\n }>(\"SELECT id, s, n, z, b FROM t WHERE id = ?\", [7]);\n assert(rows.length === 1, \"صف واحد\");\n const r = rows[0]!;\n assertEqual(\n { id: r.id, s: r.s, n: r.n, z: r.z },\n { id: 7, s: \"نص\", n: 12.5, z: null },\n \"القيم غير الـ blob\",\n );\n assert(\n bytesEqual(new Uint8Array(r.b), blob),\n \"الـ blob يرجع بنفس البايتات\",\n );\n }),\n },\n\n {\n name: \"execute من غير params ينفّذ أكتر من statement (DDL/migrations)\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(`\n CREATE TABLE a (id INTEGER);\n CREATE TABLE b (id INTEGER);\n INSERT INTO a (id) VALUES (1);\n INSERT INTO b (id) VALUES (2);\n `);\n const ra = await a.query<{ id: number }>(\"SELECT id FROM a\");\n const rb = await a.query<{ id: number }>(\"SELECT id FROM b\");\n assertEqual([ra, rb], [[{ id: 1 }], [{ id: 2 }]], \"الجدولين اتعملوا\");\n }),\n },\n\n {\n name: \"transaction بتعمل commit عند النجاح\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\"CREATE TABLE t (id INTEGER)\");\n await a.transaction(async (tx) => {\n await tx.execute(\"INSERT INTO t (id) VALUES (1)\");\n await tx.execute(\"INSERT INTO t (id) VALUES (2)\");\n });\n const rows = await a.query<{ id: number }>(\"SELECT id FROM t ORDER BY id\");\n assertEqual(rows, [{ id: 1 }, { id: 2 }], \"الصفين اتثبتوا بعد الـ commit\");\n }),\n },\n\n {\n name: \"transaction بتعمل rollback عند أي throw (atomic) وتعيد الرمي\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\"CREATE TABLE t (id INTEGER)\");\n await assertThrows(\n () =>\n a.transaction(async (tx) => {\n await tx.execute(\"INSERT INTO t (id) VALUES (1)\");\n throw new Error(\"فشل مقصود وسط الـ transaction\");\n }),\n \"الـ transaction بترمي الخطأ بره\",\n );\n const rows = await a.query<{ id: number }>(\"SELECT id FROM t\");\n assertEqual(rows, [], \"مفيش أي صف اتكتب — اتعمل rollback للكل\");\n }),\n },\n\n {\n name: \"transaction بترجّع قيمة الـ callback\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\"CREATE TABLE t (id INTEGER)\");\n const value = await a.transaction(async (tx) => {\n await tx.execute(\"INSERT INTO t (id) VALUES (42)\");\n const rows = await tx.query<{ id: number }>(\"SELECT id FROM t\");\n return rows[0]!.id;\n });\n assertEqual(value, 42, \"القيمة الراجعة من الـ callback\");\n }),\n },\n\n {\n name: \"read-your-writes: الـ tx بيشوف كتاباته قبل الـ commit\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\"CREATE TABLE t (id INTEGER)\");\n await a.transaction(async (tx) => {\n await tx.execute(\"INSERT INTO t (id) VALUES (5)\");\n const rows = await tx.query<{ id: number }>(\"SELECT id FROM t\");\n assertEqual(rows, [{ id: 5 }], \"الاستعلام جوه الـ tx بيشوف الإدراج\");\n });\n }),\n },\n\n {\n name: \"INSERT OR REPLACE: upsert (يستخدمه الـ pull)\",\n run: (make) =>\n withAdapter(make, async (a) => {\n await a.execute(\"CREATE TABLE t (id INTEGER PRIMARY KEY, v TEXT)\");\n await a.execute(\"INSERT OR REPLACE INTO t (id, v) VALUES (?, ?)\", [1, \"أول\"]);\n await a.execute(\"INSERT OR REPLACE INTO t (id, v) VALUES (?, ?)\", [1, \"تاني\"]);\n const rows = await a.query<{ id: number; v: string }>(\"SELECT id, v FROM t\");\n assertEqual(rows, [{ id: 1, v: \"تاني\" }], \"الصف اتستبدل مش اتكرّر\");\n }),\n },\n];\n","import { CONFORMANCE_CASES, type MakeAdapter } from \"./cases\";\n\nexport { CONFORMANCE_CASES } from \"./cases\";\nexport type { ConformanceCase, MakeAdapter } from \"./cases\";\nexport { assert, assertEqual, assertThrows, bytesEqual } from \"./assert\";\n\n/**\n * ربط الـ conformance battery بـ vitest. أي adapter جديد (op-sqlite / wa-sqlite)\n * لازم يعدّي دي كلها قبل الدمج:\n *\n * import { runAdapterConformance } from \"qumra-pos-storage/conformance\";\n * runAdapterConformance(\"better-sqlite3\", () => BetterSqlite3Adapter.open());\n *\n * الـ describe/it بتتحقن — علشان نفضل مستقلين عن الـ runner (Playwright يقدر\n * يمرّر test.describe/test بتوعه لتشغيل نفس الحالات في المتصفح لـ wa-sqlite).\n */\nexport interface TestHarness {\n describe(name: string, fn: () => void): void;\n it(name: string, fn: () => void | Promise<void>): void;\n}\n\nexport function runAdapterConformance(\n label: string,\n make: MakeAdapter,\n harness: TestHarness,\n): void {\n harness.describe(`StorageAdapter conformance — ${label}`, () => {\n for (const c of CONFORMANCE_CASES) {\n harness.it(c.name, () => c.run(make));\n }\n });\n}\n"]}
|