@teincfood/core 0.7.9 → 0.8.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 +26 -21
- package/dist/adapters/auth.d.ts +8 -0
- package/dist/adapters/auth.js +36 -0
- package/dist/adapters/devices.d.ts +3 -1
- package/dist/adapters/devices.js +187 -3
- package/dist/adapters/filesystem.d.ts +4 -0
- package/dist/adapters/kv.d.ts +10 -0
- package/dist/adapters/kv.js +23 -7
- package/dist/adapters/local-node.d.ts +4 -6
- package/dist/adapters/local-node.js +9 -32
- package/dist/adapters/notify.d.ts +12 -0
- package/dist/adapters/notify.js +33 -0
- package/dist/adapters/query-keys.d.ts +4 -0
- package/dist/adapters/query-keys.js +4 -0
- package/dist/adapters/services.d.ts +96 -15
- package/dist/adapters/services.js +241 -4
- package/dist/auth/session.d.ts +66 -0
- package/dist/auth/session.js +172 -0
- package/dist/catalog/hooks.d.ts +10 -0
- package/dist/catalog/hooks.js +82 -11
- package/dist/db/migrations.js +274 -0
- package/dist/db/operations.d.ts +53 -2
- package/dist/db/operations.js +177 -8
- package/dist/domain/business/index.d.ts +5 -0
- package/dist/domain/business/index.js +5 -0
- package/dist/domain/orders/lifecycle.d.ts +6 -0
- package/dist/domain/orders/lifecycle.js +6 -0
- package/dist/domain/orders/service.d.ts +24 -0
- package/dist/domain/orders/service.js +242 -0
- package/dist/domain/payments/index.d.ts +6 -0
- package/dist/domain/payments/index.js +5 -0
- package/dist/domain/reference/index.d.ts +8 -0
- package/dist/domain/reference/index.js +8 -0
- package/dist/e2e/harness.d.ts +1 -0
- package/dist/e2e/harness.js +61 -0
- package/dist/hooks/analytics.hooks.d.ts +25 -0
- package/dist/hooks/analytics.hooks.js +214 -0
- package/dist/hooks/business-hours.hooks.d.ts +8 -0
- package/dist/hooks/business-hours.hooks.js +45 -0
- package/dist/hooks/dashboard.hooks.d.ts +30 -0
- package/dist/hooks/dashboard.hooks.js +132 -0
- package/dist/hooks/delivery.hooks.d.ts +225 -0
- package/dist/hooks/delivery.hooks.js +80 -0
- package/dist/hooks/fleet.hooks.d.ts +37 -0
- package/dist/hooks/fleet.hooks.js +229 -0
- package/dist/hooks/image.hooks.d.ts +20 -0
- package/dist/hooks/image.hooks.js +62 -0
- package/dist/hooks/kiosk.hooks.d.ts +22 -5
- package/dist/hooks/kiosk.hooks.js +74 -5
- package/dist/hooks/members.hooks.d.ts +48 -0
- package/dist/hooks/members.hooks.js +302 -0
- package/dist/hooks/offline-orders.hooks.d.ts +9 -0
- package/dist/hooks/offline-orders.hooks.js +51 -0
- package/dist/hooks/orders.hooks.d.ts +18 -39
- package/dist/hooks/orders.hooks.js +124 -343
- package/dist/hooks/places.hooks.d.ts +21 -0
- package/dist/hooks/places.hooks.js +112 -0
- package/dist/hooks/realtime-stubs.d.ts +28 -0
- package/dist/hooks/realtime-stubs.js +85 -0
- package/dist/hooks/rider.hooks.d.ts +470 -0
- package/dist/hooks/rider.hooks.js +373 -0
- package/dist/hooks/use-infinite-list.d.ts +243 -0
- package/dist/hooks/use-infinite-list.js +58 -0
- package/dist/hooks/wallet.hooks.d.ts +219 -0
- package/dist/hooks/wallet.hooks.js +56 -0
- package/dist/image-cache/service.d.ts +8 -0
- package/dist/image-cache/service.js +15 -3
- package/dist/index.d.ts +56 -6
- package/dist/index.js +73 -6
- package/dist/local-node/adapters.d.ts +87 -0
- package/dist/local-node/adapters.js +4 -0
- package/dist/local-node/index.d.ts +5 -0
- package/dist/local-node/index.js +5 -0
- package/dist/local-node/security.d.ts +25 -0
- package/dist/local-node/security.js +149 -0
- package/dist/local-node/service.d.ts +83 -0
- package/dist/local-node/service.js +706 -0
- package/dist/local-node/store.d.ts +50 -0
- package/dist/local-node/store.js +284 -0
- package/dist/local-node/types.d.ts +92 -0
- package/dist/local-node/types.js +4 -0
- package/dist/printer/receipt.d.ts +4 -0
- package/dist/printer/receipt.js +75 -0
- package/dist/printer/service.js +1 -1
- package/dist/providers/query-client.d.ts +13 -0
- package/dist/providers/query-client.js +58 -0
- package/dist/realtime/phoenix-socket.js +30 -1
- package/dist/realtime/useEventsConnection.js +11 -2
- package/dist/reference/api.d.ts +2 -0
- package/dist/reference/api.js +2 -0
- package/dist/reference/capabilities.d.ts +12 -7
- package/dist/reference/capabilities.js +27 -13
- package/dist/reference/hooks.d.ts +34 -0
- package/dist/reference/hooks.js +124 -0
- package/dist/reference/menu-apply.d.ts +29 -0
- package/dist/reference/menu-apply.js +289 -0
- package/dist/reference/menu-record.d.ts +69 -0
- package/dist/reference/menu-record.js +163 -0
- package/dist/reference/operations.d.ts +3 -0
- package/dist/reference/operations.js +35 -1
- package/dist/reference/service.js +36 -9
- package/dist/reference/types.d.ts +1 -1
- package/dist/repositories/order.repository.d.ts +7 -0
- package/dist/repositories/order.repository.js +15 -2
- package/dist/repositories/pos.repository.d.ts +4 -0
- package/dist/repositories/pos.repository.js +4 -0
- package/dist/sync/backoff.d.ts +21 -0
- package/dist/sync/backoff.js +42 -0
- package/dist/sync/command-builder.js +10 -2
- package/dist/sync/command-queue.service.d.ts +12 -0
- package/dist/sync/command-queue.service.js +81 -16
- package/dist/sync/device-lease.service.d.ts +3 -3
- package/dist/sync/device-lease.service.js +80 -20
- package/dist/sync/engine.d.ts +3 -1
- package/dist/sync/engine.js +44 -4
- package/dist/sync/full-sync.d.ts +6 -0
- package/dist/sync/full-sync.js +72 -0
- package/dist/sync/health-probe.d.ts +24 -0
- package/dist/sync/health-probe.js +138 -0
- package/dist/sync/offline-capable.js +25 -0
- package/dist/sync/online-gates.d.ts +17 -0
- package/dist/sync/online-gates.js +55 -0
- package/dist/sync/order-number.d.ts +4 -4
- package/dist/sync/order-number.js +33 -13
- package/dist/sync/order-snapshots.service.js +18 -3
- package/dist/sync/pending-orders.service.d.ts +18 -0
- package/dist/sync/pending-orders.service.js +67 -1
- package/dist/sync/reconciliation/index.d.ts +5 -0
- package/dist/sync/reconciliation/index.js +5 -0
- package/dist/sync/snapshots/entity.d.ts +6 -0
- package/dist/sync/snapshots/entity.js +6 -0
- package/dist/sync/sync-jobs.service.d.ts +18 -0
- package/dist/sync/sync-jobs.service.js +539 -0
- package/dist/sync/transition-endpoints.d.ts +11 -0
- package/dist/sync/transition-endpoints.js +30 -0
- package/dist/sync/transport-local-node.js +3 -2
- package/dist/sync/transport-rest.d.ts +7 -0
- package/dist/sync/transport-rest.js +84 -26
- package/dist/sync/use-sync-reconciliation.js +15 -1
- package/dist/test-helpers/memory-driver.js +182 -4
- package/dist/test-helpers/seed-hours.d.ts +1 -0
- package/dist/test-helpers/seed-hours.js +23 -0
- package/dist/types/api/business.api.d.ts +42 -0
- package/dist/types/api/menu.api.d.ts +15 -0
- package/dist/types/api/seller.api.d.ts +20 -0
- package/dist/types/places.d.ts +19 -0
- package/dist/types/places.js +2 -0
- package/dist/types/rider.d.ts +67 -0
- package/dist/types/rider.js +2 -0
- package/dist/utils/attempt-stats.d.ts +23 -0
- package/dist/utils/attempt-stats.js +61 -0
- package/dist/utils/business-hours.d.ts +37 -0
- package/dist/utils/business-hours.js +96 -0
- package/dist/utils/debug-log.d.ts +23 -0
- package/dist/utils/debug-log.js +153 -0
- package/dist/utils/order-filter.d.ts +1 -1
- package/dist/utils/order-filter.js +1 -1
- package/dist/utils/order-transitions.d.ts +30 -0
- package/dist/utils/order-transitions.js +185 -0
- package/dist/utils/sync-logger.js +5 -4
- package/dist/validation/offline.d.ts +46 -0
- package/dist/validation/offline.js +79 -0
- package/package.json +6 -1
- package/dist/pricing/engine.test.d.ts +0 -1
- package/dist/pricing/engine.test.js +0 -142
- package/dist/reference/lww.test.d.ts +0 -1
- package/dist/reference/lww.test.js +0 -23
- package/dist/reference/operations.test.d.ts +0 -1
- package/dist/reference/operations.test.js +0 -66
- package/dist/standalone.integration.test.d.ts +0 -1
- package/dist/standalone.integration.test.js +0 -235
- package/dist/sync/device-lease.test.d.ts +0 -1
- package/dist/sync/device-lease.test.js +0 -38
- package/dist/sync/offline-integration.test.d.ts +0 -1
- package/dist/sync/offline-integration.test.js +0 -52
- package/dist/sync/order-number.test.d.ts +0 -1
- package/dist/sync/order-number.test.js +0 -51
- package/dist/sync/perms.test.d.ts +0 -1
- package/dist/sync/perms.test.js +0 -15
- package/dist/utils/currency.test.d.ts +0 -1
- package/dist/utils/currency.test.js +0 -17
- package/dist/utils/hlc.test.d.ts +0 -1
- package/dist/utils/hlc.test.js +0 -29
- package/dist/utils/phone.test.d.ts +0 -1
- package/dist/utils/phone.test.js +0 -19
- package/dist/utils/responsive.d.ts +0 -13
- package/dist/utils/responsive.js +0 -18
- package/dist/utils/uuid.test.d.ts +0 -1
- package/dist/utils/uuid.test.js +0 -13
- package/dist/utils/validation.test.d.ts +0 -1
- package/dist/utils/validation.test.js +0 -23
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Places search hooks — single source for both apps (previously verbatim
|
|
3
|
+
* copies). Pure React + injected placesService; storage-backed caching lives
|
|
4
|
+
* in the host service implementations.
|
|
5
|
+
*/
|
|
6
|
+
import { useState, useEffect, useRef, useCallback } from "react";
|
|
7
|
+
import { useSyncExternalStore } from "react";
|
|
8
|
+
import { getConnectivityState, subscribeConnectivity } from "../adapters/connectivity";
|
|
9
|
+
import { placesService } from "../adapters/services";
|
|
10
|
+
export function usePlacesSearch(debounceMs = 300) {
|
|
11
|
+
const [query, setQuery] = useState("");
|
|
12
|
+
const [suggestions, setSuggestions] = useState([]);
|
|
13
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
14
|
+
const debounceRef = useRef(undefined);
|
|
15
|
+
// Place search has no offline index — don't fire while unreachable.
|
|
16
|
+
const connectivity = useSyncExternalStore(subscribeConnectivity, getConnectivityState, getConnectivityState);
|
|
17
|
+
const online = connectivity.isOnline && connectivity.isCloudReachable !== "unreachable";
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let cancelled = false;
|
|
20
|
+
if (debounceRef.current) {
|
|
21
|
+
clearTimeout(debounceRef.current);
|
|
22
|
+
}
|
|
23
|
+
if (!query || query.length < 3 || !online) {
|
|
24
|
+
setSuggestions([]);
|
|
25
|
+
setIsLoading(false);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setIsLoading(true);
|
|
29
|
+
debounceRef.current = setTimeout(async () => {
|
|
30
|
+
try {
|
|
31
|
+
const results = await placesService.searchPlaces(query);
|
|
32
|
+
if (!cancelled) {
|
|
33
|
+
setSuggestions(results);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
try {
|
|
38
|
+
console.error("Places search error:", error);
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
if (!cancelled) {
|
|
42
|
+
setSuggestions([]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
if (!cancelled) {
|
|
47
|
+
setIsLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, debounceMs);
|
|
51
|
+
return () => {
|
|
52
|
+
cancelled = true;
|
|
53
|
+
if (debounceRef.current) {
|
|
54
|
+
clearTimeout(debounceRef.current);
|
|
55
|
+
}
|
|
56
|
+
setIsLoading(false);
|
|
57
|
+
};
|
|
58
|
+
}, [query, debounceMs]);
|
|
59
|
+
const clearSearch = useCallback(() => {
|
|
60
|
+
setQuery("");
|
|
61
|
+
setSuggestions([]);
|
|
62
|
+
}, []);
|
|
63
|
+
const clearAll = useCallback(() => {
|
|
64
|
+
setQuery("");
|
|
65
|
+
setSuggestions([]);
|
|
66
|
+
setIsLoading(false);
|
|
67
|
+
}, []);
|
|
68
|
+
return {
|
|
69
|
+
query,
|
|
70
|
+
setQuery,
|
|
71
|
+
suggestions,
|
|
72
|
+
isLoading,
|
|
73
|
+
clearSearch,
|
|
74
|
+
clearAll,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function usePlaceDetails(placeId) {
|
|
78
|
+
const [details, setDetails] = useState(null);
|
|
79
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
80
|
+
const connectivity = useSyncExternalStore(subscribeConnectivity, getConnectivityState, getConnectivityState);
|
|
81
|
+
const online = connectivity.isOnline && connectivity.isCloudReachable !== "unreachable";
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!placeId || !online) {
|
|
84
|
+
setDetails(null);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
let cancelled = false;
|
|
88
|
+
setIsLoading(true);
|
|
89
|
+
placesService.getPlaceDetails(placeId).then((result) => {
|
|
90
|
+
if (!cancelled && result) {
|
|
91
|
+
setDetails(result);
|
|
92
|
+
}
|
|
93
|
+
setIsLoading(false);
|
|
94
|
+
});
|
|
95
|
+
return () => {
|
|
96
|
+
cancelled = true;
|
|
97
|
+
};
|
|
98
|
+
}, [placeId]);
|
|
99
|
+
return { details, isLoading };
|
|
100
|
+
}
|
|
101
|
+
export function clearPlacesCache() {
|
|
102
|
+
void placesService.clearCache();
|
|
103
|
+
}
|
|
104
|
+
/** Generic debounced-value hook for search/filter inputs. */
|
|
105
|
+
export function useDebouncedValue(value, delayMs = 400) {
|
|
106
|
+
const [debounced, setDebounced] = useState(value);
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
const t = setTimeout(() => setDebounced(value), delayMs);
|
|
109
|
+
return () => clearTimeout(t);
|
|
110
|
+
}, [value, delayMs]);
|
|
111
|
+
return debounced;
|
|
112
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realtime invalidation hooks — bridge Phoenix WebSocket events into the
|
|
3
|
+
* Sync Engine so useSyncReconciliation fires and React Query caches refresh.
|
|
4
|
+
*
|
|
5
|
+
* Both hooks are idempotent-safe and can be called from multiple screens.
|
|
6
|
+
* Invalidations are debounced: a reconnect/replay burst can deliver dozens
|
|
7
|
+
* of events at once, and an immediate invalidate-per-event forces repeated
|
|
8
|
+
* full re-renders of boards/grids — a major CPU spike source on low-power
|
|
9
|
+
* POS hardware. Coalescing into one invalidation per ~400ms window keeps
|
|
10
|
+
* the UI fresh without the render storm.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Subscribe to real-time order events and invalidate all queries under the
|
|
14
|
+
* given root key prefix (e.g. ['seller'], ['pos'], ['kiosk']).
|
|
15
|
+
*
|
|
16
|
+
* Each event is also persisted to the durable offline read model so order
|
|
17
|
+
* history and states survive a restart while offline, and published through
|
|
18
|
+
* the Sync Engine so useSyncReconciliation + LAN relay fire without polling.
|
|
19
|
+
*
|
|
20
|
+
* Call once per screen that needs live updates (POS, Orders, Kitchen, etc.).
|
|
21
|
+
*/
|
|
22
|
+
export declare function useOrderRealtimeUpdates(rootKey: readonly string[]): void;
|
|
23
|
+
/**
|
|
24
|
+
* Global realtime invalidation — currently handled entirely by
|
|
25
|
+
* useOrderRealtimeUpdates + useSyncReconciliation. Kept as a no-op for
|
|
26
|
+
* backward compatibility with any lingering call sites.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useRealtimeInvalidation(): void;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realtime invalidation hooks — bridge Phoenix WebSocket events into the
|
|
3
|
+
* Sync Engine so useSyncReconciliation fires and React Query caches refresh.
|
|
4
|
+
*
|
|
5
|
+
* Both hooks are idempotent-safe and can be called from multiple screens.
|
|
6
|
+
* Invalidations are debounced: a reconnect/replay burst can deliver dozens
|
|
7
|
+
* of events at once, and an immediate invalidate-per-event forces repeated
|
|
8
|
+
* full re-renders of boards/grids — a major CPU spike source on low-power
|
|
9
|
+
* POS hardware. Coalescing into one invalidation per ~400ms window keeps
|
|
10
|
+
* the UI fresh without the render storm.
|
|
11
|
+
*/
|
|
12
|
+
import { useEffect } from "react";
|
|
13
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
14
|
+
import { orderEventsService } from "../realtime/order-events.service";
|
|
15
|
+
import { orderSnapshotsService } from "../sync/order-snapshots.service";
|
|
16
|
+
import { syncEngine } from "../sync/engine";
|
|
17
|
+
import { generateEventId } from "../utils/uuid";
|
|
18
|
+
import { getAppInstanceId } from "../adapters/devices";
|
|
19
|
+
const INVALIDATE_DEBOUNCE_MS = 400;
|
|
20
|
+
/**
|
|
21
|
+
* Subscribe to real-time order events and invalidate all queries under the
|
|
22
|
+
* given root key prefix (e.g. ['seller'], ['pos'], ['kiosk']).
|
|
23
|
+
*
|
|
24
|
+
* Each event is also persisted to the durable offline read model so order
|
|
25
|
+
* history and states survive a restart while offline, and published through
|
|
26
|
+
* the Sync Engine so useSyncReconciliation + LAN relay fire without polling.
|
|
27
|
+
*
|
|
28
|
+
* Call once per screen that needs live updates (POS, Orders, Kitchen, etc.).
|
|
29
|
+
*/
|
|
30
|
+
export function useOrderRealtimeUpdates(rootKey) {
|
|
31
|
+
const queryClient = useQueryClient();
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
let timer;
|
|
34
|
+
const pendingOrderIds = new Set();
|
|
35
|
+
const pending = { rootKey: false };
|
|
36
|
+
const ownDeviceId = getAppInstanceId();
|
|
37
|
+
const flush = () => {
|
|
38
|
+
timer = undefined;
|
|
39
|
+
if (pending.rootKey)
|
|
40
|
+
queryClient.invalidateQueries({ queryKey: rootKey });
|
|
41
|
+
for (const oid of pendingOrderIds) {
|
|
42
|
+
queryClient.invalidateQueries({ queryKey: [...rootKey, "order", oid] });
|
|
43
|
+
}
|
|
44
|
+
pendingOrderIds.clear();
|
|
45
|
+
pending.rootKey = false;
|
|
46
|
+
};
|
|
47
|
+
const unsub = orderEventsService.onOrderUpdates((event) => {
|
|
48
|
+
pending.rootKey = true;
|
|
49
|
+
if (event.order_id)
|
|
50
|
+
pendingOrderIds.add(event.order_id);
|
|
51
|
+
const payload = { ...event };
|
|
52
|
+
const domainEvent = {
|
|
53
|
+
event_id: payload.event_id ?? generateEventId(),
|
|
54
|
+
event_type: event.type,
|
|
55
|
+
event_version: payload.event_version ?? "1.0",
|
|
56
|
+
timestamp: payload.timestamp ?? new Date().toISOString(),
|
|
57
|
+
device_id: payload.device_id ?? ownDeviceId,
|
|
58
|
+
user_id: payload.user_id ?? "system",
|
|
59
|
+
entity_id: event.order_id ?? "",
|
|
60
|
+
payload,
|
|
61
|
+
};
|
|
62
|
+
// Persist to durable offline read model (entity_snapshots table).
|
|
63
|
+
orderSnapshotsService.persistOrderEvent(domainEvent, "cloud").catch(() => { });
|
|
64
|
+
// Publish through the Sync Engine so useSyncReconciliation + LAN relay
|
|
65
|
+
// fire without waiting for the next poll.
|
|
66
|
+
try {
|
|
67
|
+
syncEngine.publish(domainEvent);
|
|
68
|
+
}
|
|
69
|
+
catch { }
|
|
70
|
+
if (!timer)
|
|
71
|
+
timer = setTimeout(flush, INVALIDATE_DEBOUNCE_MS);
|
|
72
|
+
});
|
|
73
|
+
return () => {
|
|
74
|
+
if (timer)
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
unsub();
|
|
77
|
+
};
|
|
78
|
+
}, [queryClient, rootKey]);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Global realtime invalidation — currently handled entirely by
|
|
82
|
+
* useOrderRealtimeUpdates + useSyncReconciliation. Kept as a no-op for
|
|
83
|
+
* backward compatibility with any lingering call sites.
|
|
84
|
+
*/
|
|
85
|
+
export function useRealtimeInvalidation() { }
|