@teincfood/core 0.1.1 → 0.1.3
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/adapters/auth.js +2 -6
- package/dist/adapters/business.js +2 -6
- package/dist/adapters/connectivity.js +6 -14
- package/dist/adapters/devices.js +2 -6
- package/dist/adapters/http.js +4 -10
- package/dist/adapters/image-cache.d.ts +9 -3
- package/dist/adapters/image-cache.js +12 -8
- package/dist/adapters/kv-types.js +1 -2
- package/dist/adapters/kv.js +11 -24
- package/dist/adapters/local-node.js +3 -7
- package/dist/adapters/pending-orders.js +1 -4
- package/dist/adapters/query-keys.js +4 -7
- package/dist/adapters/services.js +9 -14
- package/dist/adapters/sqlite.js +3 -8
- package/dist/db/connection.js +15 -20
- package/dist/db/migrations.js +1 -4
- package/dist/db/operations.js +19 -36
- package/dist/index.d.ts +3 -0
- package/dist/index.js +43 -93
- package/dist/reference/api.js +7 -12
- package/dist/reference/events.js +25 -33
- package/dist/reference/operations.js +6 -14
- package/dist/reference/service.js +36 -39
- package/dist/reference/types.js +1 -2
- package/dist/repositories/order.repository.js +15 -18
- package/dist/repositories/pos.repository.js +6 -9
- package/dist/sync/command-builder.js +8 -12
- package/dist/sync/command-queue.service.js +35 -38
- package/dist/sync/engine.js +38 -42
- package/dist/sync/order-number.js +6 -11
- package/dist/sync/order-number.test.d.ts +1 -0
- package/dist/sync/order-number.test.js +30 -0
- package/dist/sync/order-snapshots.service.js +19 -22
- package/dist/sync/pending-orders.service.js +27 -33
- package/dist/sync/transport-local-node.js +16 -20
- package/dist/sync/transport-rest.js +18 -22
- package/dist/sync/types.js +1 -2
- package/dist/sync/use-sync-reconciliation.js +37 -40
- package/dist/types/api/auth.api.js +1 -2
- package/dist/types/api/business.api.js +1 -2
- package/dist/types/api/conversation.api.js +1 -2
- package/dist/types/api/error.api.js +1 -2
- package/dist/types/api/fleet.api.js +1 -2
- package/dist/types/api/index.js +11 -27
- package/dist/types/api/kiosk.api.js +1 -2
- package/dist/types/api/menu.api.js +1 -2
- package/dist/types/api/pagination.js +1 -2
- package/dist/types/api/rider.api.js +1 -2
- package/dist/types/api/seller.api.js +1 -2
- package/dist/types/api/wallet.api.js +1 -2
- package/dist/types/pos.types.js +1 -2
- package/dist/utils/constants.js +24 -27
- package/dist/utils/copyToClipBoard.js +2 -7
- package/dist/utils/currency.js +8 -16
- package/dist/utils/currency.test.d.ts +1 -0
- package/dist/utils/currency.test.js +17 -0
- package/dist/utils/error.js +4 -11
- package/dist/utils/formatCurrency.js +1 -4
- package/dist/utils/formatDate.js +2 -6
- package/dist/utils/phone.js +6 -13
- package/dist/utils/phone.test.d.ts +1 -0
- package/dist/utils/phone.test.js +19 -0
- package/dist/utils/responsive.js +1 -4
- package/dist/utils/storage.js +14 -28
- package/dist/utils/sync-logger.js +1 -4
- package/dist/utils/uuid.js +4 -10
- package/dist/utils/uuid.test.d.ts +1 -0
- package/dist/utils/uuid.test.js +13 -0
- package/dist/utils/validation.js +11 -24
- package/dist/utils/validation.test.d.ts +1 -0
- package/dist/utils/validation.test.js +23 -0
- package/package.json +16 -1
package/dist/db/operations.js
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Low-level SQLite operations for the command outbox and event journal.
|
|
4
3
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.getPendingCommands = getPendingCommands;
|
|
8
|
-
exports.updateCommandStatus = updateCommandStatus;
|
|
9
|
-
exports.markCommandInFlight = markCommandInFlight;
|
|
10
|
-
exports.deleteCommand = deleteCommand;
|
|
11
|
-
exports.clearCompletedCommands = clearCompletedCommands;
|
|
12
|
-
exports.insertEvent = insertEvent;
|
|
13
|
-
exports.getEventsForEntity = getEventsForEntity;
|
|
14
|
-
exports.getUnsyncedEvents = getUnsyncedEvents;
|
|
15
|
-
exports.markEventsSynced = markEventsSynced;
|
|
16
|
-
exports.upsertEntitySnapshot = upsertEntitySnapshot;
|
|
17
|
-
exports.getEntitySnapshot = getEntitySnapshot;
|
|
18
|
-
exports.getEntitySnapshotsByType = getEntitySnapshotsByType;
|
|
19
|
-
exports.deleteEntitySnapshot = deleteEntitySnapshot;
|
|
20
|
-
exports.pruneEntitySnapshots = pruneEntitySnapshots;
|
|
21
|
-
const sync_logger_1 = require("../utils/sync-logger");
|
|
22
|
-
async function insertCommand(db, input) {
|
|
4
|
+
import { syncLogger } from "../utils/sync-logger";
|
|
5
|
+
export async function insertCommand(db, input) {
|
|
23
6
|
const { command, status = "pending" } = input;
|
|
24
7
|
const now = new Date().toISOString();
|
|
25
8
|
const payload = JSON.stringify(command.payload);
|
|
@@ -38,10 +21,10 @@ async function insertCommand(db, input) {
|
|
|
38
21
|
if (!row) {
|
|
39
22
|
throw new Error(`Failed to insert command ${command.command_id}`);
|
|
40
23
|
}
|
|
41
|
-
|
|
24
|
+
syncLogger.command(command, "queued");
|
|
42
25
|
return rowToPersistedCommand(row);
|
|
43
26
|
}
|
|
44
|
-
async function getPendingCommands(db, limit = 100) {
|
|
27
|
+
export async function getPendingCommands(db, limit = 100) {
|
|
45
28
|
const rows = await db.getAllAsync(`
|
|
46
29
|
SELECT * FROM commands
|
|
47
30
|
WHERE status IN ('pending', 'failed')
|
|
@@ -50,7 +33,7 @@ async function getPendingCommands(db, limit = 100) {
|
|
|
50
33
|
`, limit);
|
|
51
34
|
return rows.map(rowToPersistedCommand);
|
|
52
35
|
}
|
|
53
|
-
async function updateCommandStatus(db, commandId, status, error) {
|
|
36
|
+
export async function updateCommandStatus(db, commandId, status, error) {
|
|
54
37
|
const now = new Date().toISOString();
|
|
55
38
|
if (status === "failed") {
|
|
56
39
|
await db.runAsync(`
|
|
@@ -66,9 +49,9 @@ async function updateCommandStatus(db, commandId, status, error) {
|
|
|
66
49
|
else {
|
|
67
50
|
await db.runAsync("UPDATE commands SET status = ?, error = ?, updated_at = ? WHERE command_id = ?;", status, error ?? null, now, commandId);
|
|
68
51
|
}
|
|
69
|
-
|
|
52
|
+
syncLogger.debug("CommandOutbox", "Status updated", { commandId, status });
|
|
70
53
|
}
|
|
71
|
-
async function markCommandInFlight(db, commandId) {
|
|
54
|
+
export async function markCommandInFlight(db, commandId) {
|
|
72
55
|
const now = new Date().toISOString();
|
|
73
56
|
await db.runAsync(`
|
|
74
57
|
UPDATE commands
|
|
@@ -76,14 +59,14 @@ async function markCommandInFlight(db, commandId) {
|
|
|
76
59
|
WHERE command_id = ?;
|
|
77
60
|
`, now, now, commandId);
|
|
78
61
|
}
|
|
79
|
-
async function deleteCommand(db, commandId) {
|
|
62
|
+
export async function deleteCommand(db, commandId) {
|
|
80
63
|
await db.runAsync("DELETE FROM commands WHERE command_id = ?;", commandId);
|
|
81
64
|
}
|
|
82
|
-
async function clearCompletedCommands(db, olderThanHours = 24) {
|
|
65
|
+
export async function clearCompletedCommands(db, olderThanHours = 24) {
|
|
83
66
|
const cutoff = new Date(Date.now() - olderThanHours * 60 * 60 * 1000).toISOString();
|
|
84
67
|
await db.runAsync("DELETE FROM commands WHERE status = 'completed' AND updated_at < ?;", cutoff);
|
|
85
68
|
}
|
|
86
|
-
async function insertEvent(db, input) {
|
|
69
|
+
export async function insertEvent(db, input) {
|
|
87
70
|
const { event, origin, syncedToCloud = false } = input;
|
|
88
71
|
await db.runAsync(`
|
|
89
72
|
INSERT INTO events (
|
|
@@ -92,9 +75,9 @@ async function insertEvent(db, input) {
|
|
|
92
75
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
93
76
|
ON CONFLICT(event_id) DO NOTHING;
|
|
94
77
|
`, event.event_id, event.event_type, event.event_version, event.entity_id, event.user_id, event.device_id, JSON.stringify(event.payload), origin, syncedToCloud ? 1 : 0, event.timestamp, new Date().toISOString());
|
|
95
|
-
|
|
78
|
+
syncLogger.event(event, "persisted", { origin, syncedToCloud });
|
|
96
79
|
}
|
|
97
|
-
async function getEventsForEntity(db, entityId, limit = 100) {
|
|
80
|
+
export async function getEventsForEntity(db, entityId, limit = 100) {
|
|
98
81
|
const rows = await db.getAllAsync(`
|
|
99
82
|
SELECT * FROM events
|
|
100
83
|
WHERE entity_id = ?
|
|
@@ -103,7 +86,7 @@ async function getEventsForEntity(db, entityId, limit = 100) {
|
|
|
103
86
|
`, entityId, limit);
|
|
104
87
|
return rows.map(rowToDomainEvent);
|
|
105
88
|
}
|
|
106
|
-
async function getUnsyncedEvents(db, origin = "local", limit = 100) {
|
|
89
|
+
export async function getUnsyncedEvents(db, origin = "local", limit = 100) {
|
|
107
90
|
const rows = await db.getAllAsync(`
|
|
108
91
|
SELECT * FROM events
|
|
109
92
|
WHERE origin = ? AND synced_to_cloud = 0
|
|
@@ -112,7 +95,7 @@ async function getUnsyncedEvents(db, origin = "local", limit = 100) {
|
|
|
112
95
|
`, origin, limit);
|
|
113
96
|
return rows.map(rowToDomainEvent);
|
|
114
97
|
}
|
|
115
|
-
async function markEventsSynced(db, eventIds) {
|
|
98
|
+
export async function markEventsSynced(db, eventIds) {
|
|
116
99
|
if (eventIds.length === 0)
|
|
117
100
|
return;
|
|
118
101
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
@@ -128,7 +111,7 @@ function rowToEntitySnapshot(row) {
|
|
|
128
111
|
payload: JSON.parse(row.payload),
|
|
129
112
|
};
|
|
130
113
|
}
|
|
131
|
-
async function upsertEntitySnapshot(db, input) {
|
|
114
|
+
export async function upsertEntitySnapshot(db, input) {
|
|
132
115
|
const { entityType, entityId, businessId = null, lastEventId, lastEventTimestamp, payload, } = input;
|
|
133
116
|
const existing = await db.getFirstAsync("SELECT last_event_timestamp FROM entity_snapshots WHERE entity_type = ? AND entity_id = ?;", entityType, entityId);
|
|
134
117
|
if (existing && existing.last_event_timestamp > lastEventTimestamp) {
|
|
@@ -144,18 +127,18 @@ async function upsertEntitySnapshot(db, input) {
|
|
|
144
127
|
payload = excluded.payload;
|
|
145
128
|
`, entityType, entityId, businessId, lastEventId, lastEventTimestamp, JSON.stringify(payload));
|
|
146
129
|
}
|
|
147
|
-
async function getEntitySnapshot(db, entityType, entityId) {
|
|
130
|
+
export async function getEntitySnapshot(db, entityType, entityId) {
|
|
148
131
|
const row = await db.getFirstAsync("SELECT * FROM entity_snapshots WHERE entity_type = ? AND entity_id = ?;", entityType, entityId);
|
|
149
132
|
return row ? rowToEntitySnapshot(row) : null;
|
|
150
133
|
}
|
|
151
|
-
async function getEntitySnapshotsByType(db, entityType) {
|
|
134
|
+
export async function getEntitySnapshotsByType(db, entityType) {
|
|
152
135
|
const rows = await db.getAllAsync("SELECT * FROM entity_snapshots WHERE entity_type = ? ORDER BY last_event_timestamp DESC;", entityType);
|
|
153
136
|
return rows.map(rowToEntitySnapshot);
|
|
154
137
|
}
|
|
155
|
-
async function deleteEntitySnapshot(db, entityType, entityId) {
|
|
138
|
+
export async function deleteEntitySnapshot(db, entityType, entityId) {
|
|
156
139
|
await db.runAsync("DELETE FROM entity_snapshots WHERE entity_type = ? AND entity_id = ?;", entityType, entityId);
|
|
157
140
|
}
|
|
158
|
-
async function pruneEntitySnapshots(db, entityType, cutoffIso) {
|
|
141
|
+
export async function pruneEntitySnapshots(db, entityType, cutoffIso) {
|
|
159
142
|
await db.runAsync("DELETE FROM entity_snapshots WHERE entity_type = ? AND last_event_timestamp < ?;", entityType, cutoffIso);
|
|
160
143
|
}
|
|
161
144
|
function rowToPersistedCommand(row) {
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,9 @@ export * from "./adapters/kv";
|
|
|
30
30
|
export * from "./adapters/connectivity";
|
|
31
31
|
export * from "./adapters/http";
|
|
32
32
|
export * from "./adapters/local-node";
|
|
33
|
+
export * from "./adapters/services";
|
|
34
|
+
export * from "./adapters/devices";
|
|
35
|
+
export * from "./adapters/image-cache";
|
|
33
36
|
import { type SqliteDriver } from "./adapters/sqlite";
|
|
34
37
|
import { type KVDriver } from "./adapters/kv";
|
|
35
38
|
import { type HttpClient } from "./adapters/http";
|
package/dist/index.js
CHANGED
|
@@ -1,117 +1,67 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @teincfood/core — shared offline-first backbone
|
|
4
3
|
*
|
|
5
4
|
* Entry point. Re-exports types, sync engine, DB, reference service, repos and adapters.
|
|
6
5
|
* Host apps call `createTeincCore` once at bootstrap to wire platform adapters.
|
|
7
6
|
*/
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
25
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
26
|
-
};
|
|
27
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
-
var ownKeys = function(o) {
|
|
29
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
-
var ar = [];
|
|
31
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
-
return ar;
|
|
33
|
-
};
|
|
34
|
-
return ownKeys(o);
|
|
35
|
-
};
|
|
36
|
-
return function (mod) {
|
|
37
|
-
if (mod && mod.__esModule) return mod;
|
|
38
|
-
var result = {};
|
|
39
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
-
__setModuleDefault(result, mod);
|
|
41
|
-
return result;
|
|
42
|
-
};
|
|
43
|
-
})();
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.referenceSyncService = exports.posRepository = exports.orderRepository = exports.orderSnapshotsService = exports.isLocalOrderNumber = exports.generateLocalCalloutNumber = exports.generateLocalOrderNumber = exports.buildCommand = exports.commandQueueService = exports.SyncEngine = exports.getSyncDatabase = exports.openSyncDatabase = exports.dbOps = void 0;
|
|
46
|
-
exports.createTeincCore = createTeincCore;
|
|
47
|
-
exports.getCoreEngine = getCoreEngine;
|
|
48
7
|
// ── Types ──
|
|
49
|
-
|
|
50
|
-
|
|
8
|
+
export * from "./types/api";
|
|
9
|
+
export * from "./types/pos.types";
|
|
51
10
|
// ── Utils ──
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
11
|
+
export * from "./utils/constants";
|
|
12
|
+
export * from "./utils/currency";
|
|
13
|
+
export * from "./utils/error";
|
|
14
|
+
export * from "./utils/uuid";
|
|
15
|
+
export * from "./utils/sync-logger";
|
|
57
16
|
// ── DB ──
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Object.defineProperty(exports, "openSyncDatabase", { enumerable: true, get: function () { return connection_1.openSyncDatabase; } });
|
|
62
|
-
Object.defineProperty(exports, "getSyncDatabase", { enumerable: true, get: function () { return connection_1.getSyncDatabase; } });
|
|
17
|
+
export * from "./db/migrations";
|
|
18
|
+
export * as dbOps from "./db/operations";
|
|
19
|
+
export { openSyncDatabase, getSyncDatabase } from "./db/connection";
|
|
63
20
|
// ── Sync ──
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
var order_number_1 = require("./sync/order-number");
|
|
72
|
-
Object.defineProperty(exports, "generateLocalOrderNumber", { enumerable: true, get: function () { return order_number_1.generateLocalOrderNumber; } });
|
|
73
|
-
Object.defineProperty(exports, "generateLocalCalloutNumber", { enumerable: true, get: function () { return order_number_1.generateLocalCalloutNumber; } });
|
|
74
|
-
Object.defineProperty(exports, "isLocalOrderNumber", { enumerable: true, get: function () { return order_number_1.isLocalOrderNumber; } });
|
|
75
|
-
var order_snapshots_service_1 = require("./sync/order-snapshots.service");
|
|
76
|
-
Object.defineProperty(exports, "orderSnapshotsService", { enumerable: true, get: function () { return order_snapshots_service_1.orderSnapshotsService; } });
|
|
77
|
-
__exportStar(require("./sync/pending-orders.service"), exports);
|
|
21
|
+
export * from "./sync/types";
|
|
22
|
+
export { SyncEngine } from "./sync/engine";
|
|
23
|
+
export { commandQueueService } from "./sync/command-queue.service";
|
|
24
|
+
export { buildCommand } from "./sync/command-builder";
|
|
25
|
+
export { generateLocalOrderNumber, generateLocalCalloutNumber, isLocalOrderNumber } from "./sync/order-number";
|
|
26
|
+
export { orderSnapshotsService } from "./sync/order-snapshots.service";
|
|
27
|
+
export * from "./sync/pending-orders.service";
|
|
78
28
|
// ── Repositories ──
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
var pos_repository_1 = require("./repositories/pos.repository");
|
|
82
|
-
Object.defineProperty(exports, "posRepository", { enumerable: true, get: function () { return pos_repository_1.posRepository; } });
|
|
29
|
+
export { orderRepository } from "./repositories/order.repository";
|
|
30
|
+
export { posRepository } from "./repositories/pos.repository";
|
|
83
31
|
// ── Reference ──
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Object.defineProperty(exports, "referenceSyncService", { enumerable: true, get: function () { return service_1.referenceSyncService; } });
|
|
32
|
+
export * from "./reference/types";
|
|
33
|
+
export { referenceSyncService } from "./reference/service";
|
|
87
34
|
// ── Adapters (for host apps to supply) ──
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
35
|
+
export * from "./adapters/sqlite";
|
|
36
|
+
export * from "./adapters/kv";
|
|
37
|
+
export * from "./adapters/connectivity";
|
|
38
|
+
export * from "./adapters/http";
|
|
39
|
+
export * from "./adapters/local-node";
|
|
40
|
+
export * from "./adapters/services";
|
|
41
|
+
export * from "./adapters/devices";
|
|
42
|
+
export * from "./adapters/image-cache";
|
|
93
43
|
// ── Init helper ──
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
44
|
+
import { setSqliteDriver } from "./adapters/sqlite";
|
|
45
|
+
import { setKVDriver } from "./adapters/kv";
|
|
46
|
+
import { setConnectivityState } from "./adapters/connectivity";
|
|
47
|
+
import { setHttpClient } from "./adapters/http";
|
|
48
|
+
import { SyncEngine } from "./sync/engine";
|
|
49
|
+
import { restTransport } from "./sync/transport-rest";
|
|
50
|
+
import { localNodeTransport } from "./sync/transport-local-node";
|
|
101
51
|
let engine = null;
|
|
102
|
-
function createTeincCore(config = {}) {
|
|
52
|
+
export function createTeincCore(config = {}) {
|
|
103
53
|
if (config.sqliteDriver)
|
|
104
|
-
|
|
54
|
+
setSqliteDriver(config.sqliteDriver);
|
|
105
55
|
if (config.kvDriver)
|
|
106
|
-
|
|
56
|
+
setKVDriver(config.kvDriver);
|
|
107
57
|
if (config.httpClient)
|
|
108
|
-
|
|
58
|
+
setHttpClient(config.httpClient);
|
|
109
59
|
if (config.initialConnectivity)
|
|
110
|
-
|
|
111
|
-
engine = new
|
|
60
|
+
setConnectivityState(config.initialConnectivity);
|
|
61
|
+
engine = new SyncEngine({ transports: [restTransport, localNodeTransport] });
|
|
112
62
|
return { engine };
|
|
113
63
|
}
|
|
114
|
-
function getCoreEngine() {
|
|
64
|
+
export function getCoreEngine() {
|
|
115
65
|
if (!engine)
|
|
116
66
|
throw new Error("TeincFood core not initialised. Call createTeincCore() first.");
|
|
117
67
|
return engine;
|
package/dist/reference/api.js
CHANGED
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* API service for reference data synchronization.
|
|
4
3
|
*
|
|
5
4
|
* These endpoints are expected on the backend. If they are not available,
|
|
6
5
|
* the ReferenceSyncService falls back to legacy menu endpoints.
|
|
7
6
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
exports.fetchReferenceChanges = fetchReferenceChanges;
|
|
12
|
-
const http_1 = require("../adapters/http");
|
|
13
|
-
async function fetchReferenceVersions(businessId) {
|
|
14
|
-
const response = await http_1.api.get(`/businesses/${businessId}/reference-versions`);
|
|
7
|
+
import { api } from "../adapters/http";
|
|
8
|
+
export async function fetchReferenceVersions(businessId) {
|
|
9
|
+
const response = await api.get(`/businesses/${businessId}/reference-versions`);
|
|
15
10
|
return response.data.data;
|
|
16
11
|
}
|
|
17
|
-
async function fetchReferenceData(businessId, keys) {
|
|
18
|
-
const response = await
|
|
12
|
+
export async function fetchReferenceData(businessId, keys) {
|
|
13
|
+
const response = await api.get(`/businesses/${businessId}/reference-data`, { params: { keys: keys.join(",") } });
|
|
19
14
|
return response.data.data;
|
|
20
15
|
}
|
|
21
|
-
async function fetchReferenceChanges(businessId, key, fromVersion) {
|
|
22
|
-
const response = await
|
|
16
|
+
export async function fetchReferenceChanges(businessId, key, fromVersion) {
|
|
17
|
+
const response = await api.get(`/businesses/${businessId}/reference-changes`, { params: { key, from_version: fromVersion } });
|
|
23
18
|
return response.data.data;
|
|
24
19
|
}
|
package/dist/reference/events.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Reference data change events.
|
|
4
3
|
*
|
|
@@ -17,24 +16,17 @@
|
|
|
17
16
|
* `local-node/service.ts` can depend on this module without creating an
|
|
18
17
|
* import cycle (engine → transport → local-node/service → reference/events).
|
|
19
18
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const auth_1 = require("../adapters/auth");
|
|
28
|
-
const business_1 = require("../adapters/business");
|
|
29
|
-
const devices_1 = require("../adapters/devices");
|
|
30
|
-
const uuid_1 = require("../utils/uuid");
|
|
31
|
-
const sync_logger_1 = require("../utils/sync-logger");
|
|
32
|
-
const service_1 = require("./service");
|
|
33
|
-
exports.REFERENCE_CHANGED_EVENT_TYPE = "reference_data.changed";
|
|
19
|
+
import { useAuthStore } from "../adapters/auth";
|
|
20
|
+
import { useBusinessStore } from "../adapters/business";
|
|
21
|
+
import { getAppInstanceId } from "../adapters/devices";
|
|
22
|
+
import { generateEventId } from "../utils/uuid";
|
|
23
|
+
import { syncLogger } from "../utils/sync-logger";
|
|
24
|
+
import { referenceSyncService } from "./service";
|
|
25
|
+
export const REFERENCE_CHANGED_EVENT_TYPE = "reference_data.changed";
|
|
34
26
|
/** Injected Sync Engine singleton (set by the reconciliation bridge). */
|
|
35
27
|
let engine = null;
|
|
36
28
|
/** Register the Sync Engine used to publish reference change events. */
|
|
37
|
-
function registerReferenceEventEngine(syncEngine) {
|
|
29
|
+
export function registerReferenceEventEngine(syncEngine) {
|
|
38
30
|
engine = syncEngine;
|
|
39
31
|
}
|
|
40
32
|
/** Invalidate TanStack Query caches after reference data is re-synced. */
|
|
@@ -44,7 +36,7 @@ let invalidator = null;
|
|
|
44
36
|
* data changes. Returns an unregister function. Mirrors
|
|
45
37
|
* `registerPendingOrdersInvalidator`.
|
|
46
38
|
*/
|
|
47
|
-
function registerReferenceInvalidator(fn) {
|
|
39
|
+
export function registerReferenceInvalidator(fn) {
|
|
48
40
|
invalidator = fn;
|
|
49
41
|
return () => {
|
|
50
42
|
if (invalidator === fn)
|
|
@@ -56,18 +48,18 @@ function registerReferenceInvalidator(fn) {
|
|
|
56
48
|
* one) re-syncs the affected keys. Called after a successful mutation of a
|
|
57
49
|
* reference-backed entity.
|
|
58
50
|
*/
|
|
59
|
-
function emitReferenceChanged(businessId, keys) {
|
|
51
|
+
export function emitReferenceChanged(businessId, keys) {
|
|
60
52
|
if (!businessId || keys.length === 0)
|
|
61
53
|
return;
|
|
62
54
|
if (!engine)
|
|
63
55
|
return;
|
|
64
|
-
const user =
|
|
56
|
+
const user = useAuthStore.getState().user;
|
|
65
57
|
const event = {
|
|
66
|
-
event_id:
|
|
67
|
-
event_type:
|
|
58
|
+
event_id: generateEventId(),
|
|
59
|
+
event_type: REFERENCE_CHANGED_EVENT_TYPE,
|
|
68
60
|
event_version: "1.0",
|
|
69
61
|
timestamp: new Date().toISOString(),
|
|
70
|
-
device_id:
|
|
62
|
+
device_id: getAppInstanceId(),
|
|
71
63
|
user_id: user?.id ?? "anonymous",
|
|
72
64
|
entity_id: businessId,
|
|
73
65
|
payload: { business_id: businessId, keys },
|
|
@@ -81,27 +73,27 @@ function emitReferenceChanged(businessId, keys) {
|
|
|
81
73
|
* by a single-flight flag. Errors are logged, never thrown, so a failed
|
|
82
74
|
* reference sync can never crash the LAN event loop.
|
|
83
75
|
*/
|
|
84
|
-
async function applyReferenceChangeEvent(event, origin = "local") {
|
|
76
|
+
export async function applyReferenceChangeEvent(event, origin = "local") {
|
|
85
77
|
try {
|
|
86
|
-
if (event.event_type !==
|
|
78
|
+
if (event.event_type !== REFERENCE_CHANGED_EVENT_TYPE)
|
|
87
79
|
return;
|
|
88
80
|
const payload = event.payload;
|
|
89
81
|
const businessId = payload?.business_id;
|
|
90
82
|
const keys = payload?.keys;
|
|
91
83
|
if (!businessId || !keys || keys.length === 0)
|
|
92
84
|
return;
|
|
93
|
-
|
|
85
|
+
syncLogger.info("ReferenceChange", "Reference data changed", {
|
|
94
86
|
origin,
|
|
95
87
|
business_id: businessId,
|
|
96
88
|
keys,
|
|
97
89
|
});
|
|
98
|
-
const result = await
|
|
90
|
+
const result = await referenceSyncService.sync({
|
|
99
91
|
businessId,
|
|
100
92
|
keys,
|
|
101
93
|
incremental: true,
|
|
102
94
|
});
|
|
103
95
|
if (result.failed.length > 0) {
|
|
104
|
-
|
|
96
|
+
syncLogger.warn("ReferenceChange", "Reference sync had failures", {
|
|
105
97
|
origin,
|
|
106
98
|
failed: result.failed,
|
|
107
99
|
errors: result.errors,
|
|
@@ -110,7 +102,7 @@ async function applyReferenceChangeEvent(event, origin = "local") {
|
|
|
110
102
|
invalidator?.();
|
|
111
103
|
}
|
|
112
104
|
catch (error) {
|
|
113
|
-
|
|
105
|
+
syncLogger.error("ReferenceChange", "Failed to apply reference change event", {
|
|
114
106
|
error: String(error),
|
|
115
107
|
event_type: event.event_type,
|
|
116
108
|
});
|
|
@@ -121,23 +113,23 @@ async function applyReferenceChangeEvent(event, origin = "local") {
|
|
|
121
113
|
* that missed the change event (offline, not on the LAN) — the next time they
|
|
122
114
|
* get internet they attempt to re-sync all default reference keys.
|
|
123
115
|
*/
|
|
124
|
-
async function syncReferenceDataOnReconnect() {
|
|
125
|
-
const businessId =
|
|
116
|
+
export async function syncReferenceDataOnReconnect() {
|
|
117
|
+
const businessId = useBusinessStore.getState().activeBusiness?.id;
|
|
126
118
|
if (!businessId)
|
|
127
119
|
return;
|
|
128
120
|
try {
|
|
129
|
-
const result = await
|
|
121
|
+
const result = await referenceSyncService.sync({
|
|
130
122
|
businessId,
|
|
131
123
|
incremental: true,
|
|
132
124
|
});
|
|
133
125
|
if (result.failed.length > 0) {
|
|
134
|
-
|
|
126
|
+
syncLogger.warn("ReferenceChange", "Reconnect sync had failures", {
|
|
135
127
|
failed: result.failed,
|
|
136
128
|
});
|
|
137
129
|
}
|
|
138
130
|
}
|
|
139
131
|
catch (error) {
|
|
140
|
-
|
|
132
|
+
syncLogger.error("ReferenceChange", "Reconnect sync failed", {
|
|
141
133
|
error: String(error),
|
|
142
134
|
});
|
|
143
135
|
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* SQLite operations for the business-scoped reference data cache.
|
|
4
3
|
*/
|
|
5
|
-
|
|
6
|
-
exports.getReferenceData = getReferenceData;
|
|
7
|
-
exports.getReferenceVersion = getReferenceVersion;
|
|
8
|
-
exports.setReferenceData = setReferenceData;
|
|
9
|
-
exports.deleteReferenceData = deleteReferenceData;
|
|
10
|
-
exports.deleteReferenceDataForBusiness = deleteReferenceDataForBusiness;
|
|
11
|
-
exports.getAllReferenceDataKeys = getAllReferenceDataKeys;
|
|
12
|
-
async function getReferenceData(db, businessId, key) {
|
|
4
|
+
export async function getReferenceData(db, businessId, key) {
|
|
13
5
|
const row = await db.getFirstAsync("SELECT * FROM reference_data WHERE business_id = ? AND key = ?;", businessId, key);
|
|
14
6
|
if (!row)
|
|
15
7
|
return null;
|
|
@@ -20,11 +12,11 @@ async function getReferenceData(db, businessId, key) {
|
|
|
20
12
|
downloadedAt: row.downloaded_at,
|
|
21
13
|
};
|
|
22
14
|
}
|
|
23
|
-
async function getReferenceVersion(db, businessId, key) {
|
|
15
|
+
export async function getReferenceVersion(db, businessId, key) {
|
|
24
16
|
const row = await db.getFirstAsync("SELECT version FROM reference_data WHERE business_id = ? AND key = ?;", businessId, key);
|
|
25
17
|
return row?.version ?? null;
|
|
26
18
|
}
|
|
27
|
-
async function setReferenceData(db, businessId, record) {
|
|
19
|
+
export async function setReferenceData(db, businessId, record) {
|
|
28
20
|
await db.runAsync(`
|
|
29
21
|
INSERT INTO reference_data (business_id, key, version, payload, downloaded_at)
|
|
30
22
|
VALUES (?, ?, ?, ?, ?)
|
|
@@ -34,13 +26,13 @@ async function setReferenceData(db, businessId, record) {
|
|
|
34
26
|
downloaded_at = excluded.downloaded_at;
|
|
35
27
|
`, businessId, record.key, record.version, JSON.stringify(record.payload), record.downloadedAt);
|
|
36
28
|
}
|
|
37
|
-
async function deleteReferenceData(db, businessId, key) {
|
|
29
|
+
export async function deleteReferenceData(db, businessId, key) {
|
|
38
30
|
await db.runAsync("DELETE FROM reference_data WHERE business_id = ? AND key = ?;", businessId, key);
|
|
39
31
|
}
|
|
40
|
-
async function deleteReferenceDataForBusiness(db, businessId) {
|
|
32
|
+
export async function deleteReferenceDataForBusiness(db, businessId) {
|
|
41
33
|
await db.runAsync("DELETE FROM reference_data WHERE business_id = ?;", businessId);
|
|
42
34
|
}
|
|
43
|
-
async function getAllReferenceDataKeys(db, businessId) {
|
|
35
|
+
export async function getAllReferenceDataKeys(db, businessId) {
|
|
44
36
|
const rows = await db.getAllAsync("SELECT key FROM reference_data WHERE business_id = ? ORDER BY key;", businessId);
|
|
45
37
|
return rows.map((r) => r.key);
|
|
46
38
|
}
|