@teincfood/core 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 +44 -0
- package/dist/adapters/auth.d.ts +13 -0
- package/dist/adapters/auth.js +14 -0
- package/dist/adapters/business.d.ts +13 -0
- package/dist/adapters/business.js +14 -0
- package/dist/adapters/connectivity.d.ts +17 -0
- package/dist/adapters/connectivity.js +38 -0
- package/dist/adapters/devices.d.ts +5 -0
- package/dist/adapters/devices.js +14 -0
- package/dist/adapters/http.d.ts +30 -0
- package/dist/adapters/http.js +37 -0
- package/dist/adapters/image-cache.d.ts +8 -0
- package/dist/adapters/image-cache.js +12 -0
- package/dist/adapters/kv-types.d.ts +5 -0
- package/dist/adapters/kv-types.js +2 -0
- package/dist/adapters/kv.d.ts +20 -0
- package/dist/adapters/kv.js +81 -0
- package/dist/adapters/local-node.d.ts +34 -0
- package/dist/adapters/local-node.js +40 -0
- package/dist/adapters/pending-orders.d.ts +17 -0
- package/dist/adapters/pending-orders.js +31 -0
- package/dist/adapters/query-keys.d.ts +17 -0
- package/dist/adapters/query-keys.js +20 -0
- package/dist/adapters/services.d.ts +62 -0
- package/dist/adapters/services.js +95 -0
- package/dist/adapters/sqlite.d.ts +20 -0
- package/dist/adapters/sqlite.js +23 -0
- package/dist/db/connection.d.ts +8 -0
- package/dist/db/connection.js +87 -0
- package/dist/db/migrations.d.ts +9 -0
- package/dist/db/migrations.js +106 -0
- package/dist/db/operations.d.ts +45 -0
- package/dist/db/operations.js +192 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +118 -0
- package/dist/reference/api.d.ts +10 -0
- package/dist/reference/api.js +24 -0
- package/dist/reference/events.d.ts +54 -0
- package/dist/reference/events.js +144 -0
- package/dist/reference/operations.d.ts +11 -0
- package/dist/reference/operations.js +46 -0
- package/dist/reference/service.d.ts +27 -0
- package/dist/reference/service.js +270 -0
- package/dist/reference/types.d.ts +47 -0
- package/dist/reference/types.js +12 -0
- package/dist/repositories/order.repository.d.ts +44 -0
- package/dist/repositories/order.repository.js +132 -0
- package/dist/repositories/pos.repository.d.ts +20 -0
- package/dist/repositories/pos.repository.js +28 -0
- package/dist/sync/command-builder.d.ts +17 -0
- package/dist/sync/command-builder.js +30 -0
- package/dist/sync/command-queue.service.d.ts +41 -0
- package/dist/sync/command-queue.service.js +253 -0
- package/dist/sync/engine.d.ts +53 -0
- package/dist/sync/engine.js +216 -0
- package/dist/sync/order-number.d.ts +20 -0
- package/dist/sync/order-number.js +58 -0
- package/dist/sync/order-snapshots.service.d.ts +46 -0
- package/dist/sync/order-snapshots.service.js +151 -0
- package/dist/sync/pending-orders.service.d.ts +45 -0
- package/dist/sync/pending-orders.service.js +163 -0
- package/dist/sync/transport-local-node.d.ts +14 -0
- package/dist/sync/transport-local-node.js +67 -0
- package/dist/sync/transport-rest.d.ts +17 -0
- package/dist/sync/transport-rest.js +112 -0
- package/dist/sync/types.d.ts +102 -0
- package/dist/sync/types.js +13 -0
- package/dist/sync/use-sync-reconciliation.d.ts +10 -0
- package/dist/sync/use-sync-reconciliation.js +106 -0
- package/dist/types/api/auth.api.d.ts +61 -0
- package/dist/types/api/auth.api.js +3 -0
- package/dist/types/api/business.api.d.ts +137 -0
- package/dist/types/api/business.api.js +3 -0
- package/dist/types/api/conversation.api.d.ts +46 -0
- package/dist/types/api/conversation.api.js +2 -0
- package/dist/types/api/error.api.d.ts +8 -0
- package/dist/types/api/error.api.js +2 -0
- package/dist/types/api/fleet.api.d.ts +98 -0
- package/dist/types/api/fleet.api.js +3 -0
- package/dist/types/api/index.d.ts +11 -0
- package/dist/types/api/index.js +27 -0
- package/dist/types/api/kiosk.api.d.ts +4 -0
- package/dist/types/api/kiosk.api.js +2 -0
- package/dist/types/api/menu.api.d.ts +90 -0
- package/dist/types/api/menu.api.js +2 -0
- package/dist/types/api/pagination.d.ts +10 -0
- package/dist/types/api/pagination.js +2 -0
- package/dist/types/api/rider.api.d.ts +179 -0
- package/dist/types/api/rider.api.js +2 -0
- package/dist/types/api/seller.api.d.ts +164 -0
- package/dist/types/api/seller.api.js +2 -0
- package/dist/types/api/wallet.api.d.ts +27 -0
- package/dist/types/api/wallet.api.js +2 -0
- package/dist/types/pos.types.d.ts +33 -0
- package/dist/types/pos.types.js +5 -0
- package/dist/utils/constants.d.ts +85 -0
- package/dist/utils/constants.js +72 -0
- package/dist/utils/copyToClipBoard.d.ts +5 -0
- package/dist/utils/copyToClipBoard.js +23 -0
- package/dist/utils/currency.d.ts +9 -0
- package/dist/utils/currency.js +37 -0
- package/dist/utils/error.d.ts +4 -0
- package/dist/utils/error.js +73 -0
- package/dist/utils/formatCurrency.d.ts +4 -0
- package/dist/utils/formatCurrency.js +16 -0
- package/dist/utils/formatDate.d.ts +8 -0
- package/dist/utils/formatDate.js +42 -0
- package/dist/utils/phone.d.ts +10 -0
- package/dist/utils/phone.js +71 -0
- package/dist/utils/responsive.d.ts +13 -0
- package/dist/utils/responsive.js +21 -0
- package/dist/utils/storage.d.ts +15 -0
- package/dist/utils/storage.js +60 -0
- package/dist/utils/sync-logger.d.ts +22 -0
- package/dist/utils/sync-logger.js +79 -0
- package/dist/utils/uuid.d.ts +7 -0
- package/dist/utils/uuid.js +47 -0
- package/dist/utils/validation.d.ts +31 -0
- package/dist/utils/validation.js +170 -0
- package/package.json +49 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiError = void 0;
|
|
4
|
+
exports.extractFromResponseBody = extractFromResponseBody;
|
|
5
|
+
exports.extractApiErrorMessage = extractApiErrorMessage;
|
|
6
|
+
exports.extractApiErrorCode = extractApiErrorCode;
|
|
7
|
+
function extractFromResponseBody(data) {
|
|
8
|
+
const errorField = data.error;
|
|
9
|
+
if (errorField && typeof errorField === "object") {
|
|
10
|
+
const msg = errorField.message;
|
|
11
|
+
if (typeof msg === "string")
|
|
12
|
+
return msg;
|
|
13
|
+
}
|
|
14
|
+
if (typeof errorField === "string") {
|
|
15
|
+
if (data.message && typeof data.message === "string")
|
|
16
|
+
return data.message;
|
|
17
|
+
return errorField;
|
|
18
|
+
}
|
|
19
|
+
const errorsField = data.errors;
|
|
20
|
+
if (errorsField && typeof errorsField === "object") {
|
|
21
|
+
const detail = errorsField.detail;
|
|
22
|
+
if (typeof detail === "string")
|
|
23
|
+
return detail;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function extractApiErrorMessage(error) {
|
|
28
|
+
if (typeof error === "string")
|
|
29
|
+
return error;
|
|
30
|
+
if (!error || typeof error !== "object")
|
|
31
|
+
return "An unexpected error occurred";
|
|
32
|
+
const err = error;
|
|
33
|
+
const response = err.response;
|
|
34
|
+
if (response?.data && typeof response.data === "object") {
|
|
35
|
+
const msg = extractFromResponseBody(response.data);
|
|
36
|
+
if (msg)
|
|
37
|
+
return msg;
|
|
38
|
+
}
|
|
39
|
+
if (err.message && typeof err.message === "string") {
|
|
40
|
+
return err.message;
|
|
41
|
+
}
|
|
42
|
+
return "An unexpected error occurred";
|
|
43
|
+
}
|
|
44
|
+
function extractApiErrorCode(error) {
|
|
45
|
+
if (!error || typeof error !== "object")
|
|
46
|
+
return undefined;
|
|
47
|
+
const err = error;
|
|
48
|
+
const response = err.response;
|
|
49
|
+
if (response?.data && typeof response.data === "object") {
|
|
50
|
+
const data = response.data;
|
|
51
|
+
const errorField = data.error;
|
|
52
|
+
if (errorField && typeof errorField === "object") {
|
|
53
|
+
const code = errorField.code;
|
|
54
|
+
if (typeof code === "string")
|
|
55
|
+
return code;
|
|
56
|
+
}
|
|
57
|
+
if (typeof errorField === "string")
|
|
58
|
+
return errorField;
|
|
59
|
+
}
|
|
60
|
+
if (err.data && typeof err.data === "object") {
|
|
61
|
+
const data = err.data;
|
|
62
|
+
const errorField = data.error;
|
|
63
|
+
if (errorField && typeof errorField === "object") {
|
|
64
|
+
const code = errorField.code;
|
|
65
|
+
if (typeof code === "string")
|
|
66
|
+
return code;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
// Re-export ApiError from http adapter for compatibility
|
|
72
|
+
var http_1 = require("../adapters/http");
|
|
73
|
+
Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return http_1.ApiError; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Format a number as a currency string.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatCurrency = formatCurrency;
|
|
7
|
+
function formatCurrency(amount, currency = "GHS") {
|
|
8
|
+
const amountMinor = Math.round(amount * 100);
|
|
9
|
+
// Simple region formatting — host apps can inject getRegionConfig via adapter if needed
|
|
10
|
+
const symbolMap = {
|
|
11
|
+
GHS: "GH₵",
|
|
12
|
+
USD: "$",
|
|
13
|
+
};
|
|
14
|
+
const symbol = symbolMap[currency] ?? currency;
|
|
15
|
+
return `${symbol}${(amountMinor / 100).toFixed(2)}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format an ISO date string into a human-readable format.
|
|
3
|
+
*/
|
|
4
|
+
export declare function formatDate(isoString: string, style?: 'short' | 'long'): string;
|
|
5
|
+
/**
|
|
6
|
+
* Format a date as a relative time string (e.g., "20 min ago").
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatRelativeTime(isoString: string): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDate = formatDate;
|
|
4
|
+
exports.formatRelativeTime = formatRelativeTime;
|
|
5
|
+
/**
|
|
6
|
+
* Format an ISO date string into a human-readable format.
|
|
7
|
+
*/
|
|
8
|
+
function formatDate(isoString, style = 'short') {
|
|
9
|
+
const date = new Date(isoString);
|
|
10
|
+
if (style === 'long') {
|
|
11
|
+
return date.toLocaleDateString('en-US', {
|
|
12
|
+
year: 'numeric',
|
|
13
|
+
month: 'long',
|
|
14
|
+
day: 'numeric',
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return date.toLocaleDateString('en-US', {
|
|
18
|
+
day: '2-digit',
|
|
19
|
+
month: '2-digit',
|
|
20
|
+
year: 'numeric',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Format a date as a relative time string (e.g., "20 min ago").
|
|
25
|
+
*/
|
|
26
|
+
function formatRelativeTime(isoString) {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
const then = new Date(isoString).getTime();
|
|
29
|
+
const diffMs = now - then;
|
|
30
|
+
const diffMin = Math.floor(diffMs / 60000);
|
|
31
|
+
if (diffMin < 1)
|
|
32
|
+
return 'Just now';
|
|
33
|
+
if (diffMin < 60)
|
|
34
|
+
return `${diffMin} min ago`;
|
|
35
|
+
const diffHours = Math.floor(diffMin / 60);
|
|
36
|
+
if (diffHours < 24)
|
|
37
|
+
return `${diffHours}h ago`;
|
|
38
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
39
|
+
if (diffDays < 7)
|
|
40
|
+
return `${diffDays}d ago`;
|
|
41
|
+
return formatDate(isoString);
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type PhoneCountryOption = {
|
|
2
|
+
iso: string;
|
|
3
|
+
name: string;
|
|
4
|
+
dialCode: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const PHONE_COUNTRIES: PhoneCountryOption[];
|
|
7
|
+
export declare function getDialCodeFromCountry(countryCode?: string): string | null;
|
|
8
|
+
export declare function getCountryOption(iso?: string): PhoneCountryOption | null;
|
|
9
|
+
export declare function normalizePhoneForCountry(rawPhone: string, countryCode?: string): string | null;
|
|
10
|
+
export declare function isLikelyE164(phone: string): boolean;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PHONE_COUNTRIES = void 0;
|
|
4
|
+
exports.getDialCodeFromCountry = getDialCodeFromCountry;
|
|
5
|
+
exports.getCountryOption = getCountryOption;
|
|
6
|
+
exports.normalizePhoneForCountry = normalizePhoneForCountry;
|
|
7
|
+
exports.isLikelyE164 = isLikelyE164;
|
|
8
|
+
exports.PHONE_COUNTRIES = [
|
|
9
|
+
{ iso: 'GH', name: 'Ghana', dialCode: '+233' },
|
|
10
|
+
{ iso: 'NG', name: 'Nigeria', dialCode: '+234' },
|
|
11
|
+
{ iso: 'KE', name: 'Kenya', dialCode: '+254' },
|
|
12
|
+
{ iso: 'ZA', name: 'South Africa', dialCode: '+27' },
|
|
13
|
+
{ iso: 'US', name: 'United States', dialCode: '+1' },
|
|
14
|
+
{ iso: 'CA', name: 'Canada', dialCode: '+1' },
|
|
15
|
+
{ iso: 'GB', name: 'United Kingdom', dialCode: '+44' },
|
|
16
|
+
{ iso: 'IN', name: 'India', dialCode: '+91' },
|
|
17
|
+
{ iso: 'DE', name: 'Germany', dialCode: '+49' },
|
|
18
|
+
{ iso: 'FR', name: 'France', dialCode: '+33' },
|
|
19
|
+
{ iso: 'IT', name: 'Italy', dialCode: '+39' },
|
|
20
|
+
{ iso: 'ES', name: 'Spain', dialCode: '+34' },
|
|
21
|
+
{ iso: 'AE', name: 'United Arab Emirates', dialCode: '+971' },
|
|
22
|
+
{ iso: 'SA', name: 'Saudi Arabia', dialCode: '+966' },
|
|
23
|
+
];
|
|
24
|
+
const COUNTRY_DIAL_CODE_BY_ISO = {
|
|
25
|
+
GH: '+233',
|
|
26
|
+
US: '+1',
|
|
27
|
+
CA: '+1',
|
|
28
|
+
GB: '+44',
|
|
29
|
+
NG: '+234',
|
|
30
|
+
KE: '+254',
|
|
31
|
+
ZA: '+27',
|
|
32
|
+
IN: '+91',
|
|
33
|
+
DE: '+49',
|
|
34
|
+
FR: '+33',
|
|
35
|
+
IT: '+39',
|
|
36
|
+
ES: '+34',
|
|
37
|
+
AE: '+971',
|
|
38
|
+
SA: '+966',
|
|
39
|
+
};
|
|
40
|
+
function digitsOnly(value) {
|
|
41
|
+
return value.replace(/\D/g, '');
|
|
42
|
+
}
|
|
43
|
+
function getDialCodeFromCountry(countryCode) {
|
|
44
|
+
if (!countryCode)
|
|
45
|
+
return null;
|
|
46
|
+
return COUNTRY_DIAL_CODE_BY_ISO[countryCode.trim().toUpperCase()] || null;
|
|
47
|
+
}
|
|
48
|
+
function getCountryOption(iso) {
|
|
49
|
+
if (!iso)
|
|
50
|
+
return null;
|
|
51
|
+
return exports.PHONE_COUNTRIES.find((country) => country.iso === iso.trim().toUpperCase()) || null;
|
|
52
|
+
}
|
|
53
|
+
function normalizePhoneForCountry(rawPhone, countryCode) {
|
|
54
|
+
const input = rawPhone.trim();
|
|
55
|
+
if (!input)
|
|
56
|
+
return null;
|
|
57
|
+
if (input.startsWith('+')) {
|
|
58
|
+
const normalized = `+${digitsOnly(input)}`;
|
|
59
|
+
return normalized;
|
|
60
|
+
}
|
|
61
|
+
const dialCode = getDialCodeFromCountry(countryCode);
|
|
62
|
+
if (!dialCode)
|
|
63
|
+
return null;
|
|
64
|
+
const localDigits = digitsOnly(input).replace(/^0+/, '');
|
|
65
|
+
if (!localDigits)
|
|
66
|
+
return null;
|
|
67
|
+
return `${dialCode}${localDigits}`;
|
|
68
|
+
}
|
|
69
|
+
function isLikelyE164(phone) {
|
|
70
|
+
return /^\+[1-9]\d{7,14}$/.test(phone);
|
|
71
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Responsive helper — plain, no react-native.
|
|
3
|
+
* Host apps with RN can override via adapter; core provides window-based fallback.
|
|
4
|
+
*/
|
|
5
|
+
export interface ResponsiveState {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
isTablet: boolean;
|
|
9
|
+
isLargeTablet: boolean;
|
|
10
|
+
isLandscape: boolean;
|
|
11
|
+
columns: (minItemWidth: number) => number;
|
|
12
|
+
}
|
|
13
|
+
export declare function useResponsive(): ResponsiveState;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Responsive helper — plain, no react-native.
|
|
4
|
+
* Host apps with RN can override via adapter; core provides window-based fallback.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.useResponsive = useResponsive;
|
|
8
|
+
function getWindowSize() {
|
|
9
|
+
if (typeof window !== "undefined") {
|
|
10
|
+
return { width: window.innerWidth, height: window.innerHeight };
|
|
11
|
+
}
|
|
12
|
+
return { width: 1024, height: 768 };
|
|
13
|
+
}
|
|
14
|
+
function useResponsive() {
|
|
15
|
+
const { width, height } = getWindowSize();
|
|
16
|
+
const isTablet = width >= 768;
|
|
17
|
+
const isLandscape = width > height;
|
|
18
|
+
const isLargeTablet = width >= 1024;
|
|
19
|
+
const columns = (minItemWidth) => Math.max(1, Math.floor(width / minItemWidth));
|
|
20
|
+
return { width, height, isTablet, isLargeTablet, isLandscape, columns };
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage facade — re-exports KV adapter.
|
|
3
|
+
* Provides async JSON helpers and a zustand-compatible storage shim.
|
|
4
|
+
*/
|
|
5
|
+
export { getItem, setItem, removeItem, kvGetItem, kvSetItem, kvRemoveItem, setKVDriver, getKVDriver, } from "../adapters/kv";
|
|
6
|
+
import type { StateStorage } from "../adapters/kv-types";
|
|
7
|
+
export declare const mmkvStorage: {
|
|
8
|
+
getString: (_key: string) => string | null;
|
|
9
|
+
set: (_key: string, _value: string) => void;
|
|
10
|
+
delete: (_key: string) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const zustandStorage: StateStorage;
|
|
13
|
+
export declare function getItemAsync<T>(key: string): Promise<T | null>;
|
|
14
|
+
export declare function setItemAsync<T>(key: string, value: T): Promise<void>;
|
|
15
|
+
export declare function removeItemAsync(key: string): Promise<void>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Storage facade — re-exports KV adapter.
|
|
4
|
+
* Provides async JSON helpers and a zustand-compatible storage shim.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.zustandStorage = exports.mmkvStorage = exports.getKVDriver = exports.setKVDriver = exports.kvRemoveItem = exports.kvSetItem = exports.kvGetItem = exports.removeItem = exports.setItem = exports.getItem = void 0;
|
|
8
|
+
exports.getItemAsync = getItemAsync;
|
|
9
|
+
exports.setItemAsync = setItemAsync;
|
|
10
|
+
exports.removeItemAsync = removeItemAsync;
|
|
11
|
+
var kv_1 = require("../adapters/kv");
|
|
12
|
+
Object.defineProperty(exports, "getItem", { enumerable: true, get: function () { return kv_1.getItem; } });
|
|
13
|
+
Object.defineProperty(exports, "setItem", { enumerable: true, get: function () { return kv_1.setItem; } });
|
|
14
|
+
Object.defineProperty(exports, "removeItem", { enumerable: true, get: function () { return kv_1.removeItem; } });
|
|
15
|
+
Object.defineProperty(exports, "kvGetItem", { enumerable: true, get: function () { return kv_1.kvGetItem; } });
|
|
16
|
+
Object.defineProperty(exports, "kvSetItem", { enumerable: true, get: function () { return kv_1.kvSetItem; } });
|
|
17
|
+
Object.defineProperty(exports, "kvRemoveItem", { enumerable: true, get: function () { return kv_1.kvRemoveItem; } });
|
|
18
|
+
Object.defineProperty(exports, "setKVDriver", { enumerable: true, get: function () { return kv_1.setKVDriver; } });
|
|
19
|
+
Object.defineProperty(exports, "getKVDriver", { enumerable: true, get: function () { return kv_1.getKVDriver; } });
|
|
20
|
+
const kv_2 = require("../adapters/kv");
|
|
21
|
+
const kv_3 = require("../adapters/kv");
|
|
22
|
+
// Keep mmkvStorage export for backwards compat (no-op)
|
|
23
|
+
exports.mmkvStorage = {
|
|
24
|
+
getString: (_key) => null,
|
|
25
|
+
set: (_key, _value) => { },
|
|
26
|
+
delete: (_key) => { },
|
|
27
|
+
};
|
|
28
|
+
exports.zustandStorage = {
|
|
29
|
+
getItem: (name) => {
|
|
30
|
+
const v = (0, kv_3.getItemSync)(name);
|
|
31
|
+
return v ? JSON.stringify(v) : null;
|
|
32
|
+
},
|
|
33
|
+
setItem: (name, value) => {
|
|
34
|
+
try {
|
|
35
|
+
(0, kv_3.setItemSync)(name, JSON.parse(value));
|
|
36
|
+
}
|
|
37
|
+
catch { }
|
|
38
|
+
},
|
|
39
|
+
removeItem: (name) => {
|
|
40
|
+
(0, kv_3.removeItemSync)(name);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
// Async helpers for code that expects promise-based storage (used by order-number, etc.)
|
|
44
|
+
async function getItemAsync(key) {
|
|
45
|
+
const raw = await (0, kv_2.kvGetItem)(key);
|
|
46
|
+
if (raw == null)
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(raw);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function setItemAsync(key, value) {
|
|
56
|
+
await (0, kv_2.kvSetItem)(key, JSON.stringify(value));
|
|
57
|
+
}
|
|
58
|
+
async function removeItemAsync(key) {
|
|
59
|
+
await (0, kv_2.kvRemoveItem)(key);
|
|
60
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for the Sync Engine, commands, events, and transports.
|
|
3
|
+
*
|
|
4
|
+
* Logs are sent to console.debug in debug builds. In production this can be
|
|
5
|
+
* swapped for a crashlytics/analytics sink without changing call sites.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command, DomainEvent, Transport } from "../sync/types";
|
|
8
|
+
declare class SyncLogger {
|
|
9
|
+
private enabled;
|
|
10
|
+
constructor();
|
|
11
|
+
setEnabled(enabled: boolean): void;
|
|
12
|
+
private log;
|
|
13
|
+
debug: (namespace: string, message: string, data?: Record<string, unknown>) => void;
|
|
14
|
+
info: (namespace: string, message: string, data?: Record<string, unknown>) => void;
|
|
15
|
+
warn: (namespace: string, message: string, data?: Record<string, unknown>) => void;
|
|
16
|
+
error: (namespace: string, message: string, data?: Record<string, unknown>) => void;
|
|
17
|
+
command(command: Command, action: "issued" | "queued" | "executing" | "completed" | "failed", data?: Record<string, unknown>): void;
|
|
18
|
+
event(event: DomainEvent, action: "received" | "persisted" | "applied" | "broadcast", data?: Record<string, unknown>): void;
|
|
19
|
+
transport(transport: Pick<Transport, "name">, action: "available" | "unavailable" | "executing" | "completed" | "error", data?: Record<string, unknown>): void;
|
|
20
|
+
}
|
|
21
|
+
export declare const syncLogger: SyncLogger;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Structured logging for the Sync Engine, commands, events, and transports.
|
|
4
|
+
*
|
|
5
|
+
* Logs are sent to console.debug in debug builds. In production this can be
|
|
6
|
+
* swapped for a crashlytics/analytics sink without changing call sites.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.syncLogger = void 0;
|
|
10
|
+
function emit(entry) {
|
|
11
|
+
const { level, namespace, message, data } = entry;
|
|
12
|
+
const tag = `[${namespace}] ${message}`;
|
|
13
|
+
switch (level) {
|
|
14
|
+
case "debug":
|
|
15
|
+
console.debug(tag, data);
|
|
16
|
+
break;
|
|
17
|
+
case "info":
|
|
18
|
+
console.info(tag, data);
|
|
19
|
+
break;
|
|
20
|
+
case "warn":
|
|
21
|
+
console.warn(tag, data);
|
|
22
|
+
break;
|
|
23
|
+
case "error":
|
|
24
|
+
console.error(tag, data);
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
class SyncLogger {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.debug = (namespace, message, data) => this.log("debug", namespace, message, data);
|
|
31
|
+
this.info = (namespace, message, data) => this.log("info", namespace, message, data);
|
|
32
|
+
this.warn = (namespace, message, data) => this.log("warn", namespace, message, data);
|
|
33
|
+
this.error = (namespace, message, data) => this.log("error", namespace, message, data);
|
|
34
|
+
try {
|
|
35
|
+
this.enabled = typeof __DEV__ !== "undefined" ? __DEV__ : process.env.NODE_ENV !== "production";
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
this.enabled = process.env.NODE_ENV !== "production";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
setEnabled(enabled) {
|
|
42
|
+
this.enabled = enabled;
|
|
43
|
+
}
|
|
44
|
+
log(level, namespace, message, data) {
|
|
45
|
+
if (!this.enabled)
|
|
46
|
+
return;
|
|
47
|
+
emit({
|
|
48
|
+
level,
|
|
49
|
+
namespace,
|
|
50
|
+
message,
|
|
51
|
+
data,
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
command(command, action, data) {
|
|
56
|
+
this.debug("SyncEngine:Command", `Command ${action}`, {
|
|
57
|
+
command_id: command.command_id,
|
|
58
|
+
command_type: command.command_type,
|
|
59
|
+
business_id: command.business_id,
|
|
60
|
+
entity_id: command.entity_id,
|
|
61
|
+
...data,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
event(event, action, data) {
|
|
65
|
+
this.debug("SyncEngine:Event", `Event ${action}`, {
|
|
66
|
+
event_id: event.event_id,
|
|
67
|
+
event_type: event.event_type,
|
|
68
|
+
entity_id: event.entity_id,
|
|
69
|
+
...data,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
transport(transport, action, data) {
|
|
73
|
+
this.debug("SyncEngine:Transport", `Transport ${action}`, {
|
|
74
|
+
transport: transport.name,
|
|
75
|
+
...data,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.syncLogger = new SyncLogger();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side UUID generation — plain JS, no expo-crypto.
|
|
3
|
+
*/
|
|
4
|
+
export declare function generateUUID(): string;
|
|
5
|
+
export declare function generateCommandId(): string;
|
|
6
|
+
export declare function generateEventId(): string;
|
|
7
|
+
export declare function generateEntityId(): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Client-side UUID generation — plain JS, no expo-crypto.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateUUID = generateUUID;
|
|
7
|
+
exports.generateCommandId = generateCommandId;
|
|
8
|
+
exports.generateEventId = generateEventId;
|
|
9
|
+
exports.generateEntityId = generateEntityId;
|
|
10
|
+
function randomHex(bytes) {
|
|
11
|
+
const arr = new Uint8Array(bytes);
|
|
12
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
13
|
+
crypto.getRandomValues(arr);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
for (let i = 0; i < bytes; i++)
|
|
17
|
+
arr[i] = Math.floor(Math.random() * 256);
|
|
18
|
+
}
|
|
19
|
+
return Array.from(arr, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
20
|
+
}
|
|
21
|
+
function uuidV4() {
|
|
22
|
+
const hex = randomHex(16);
|
|
23
|
+
// Set version 4 and variant bits per RFC4122
|
|
24
|
+
return (hex.slice(0, 8) +
|
|
25
|
+
"-" +
|
|
26
|
+
hex.slice(8, 12) +
|
|
27
|
+
"-" +
|
|
28
|
+
"4" +
|
|
29
|
+
hex.slice(13, 16) +
|
|
30
|
+
"-" +
|
|
31
|
+
((parseInt(hex[16], 16) & 0x3) | 0x8).toString(16) +
|
|
32
|
+
hex.slice(17, 20) +
|
|
33
|
+
"-" +
|
|
34
|
+
hex.slice(20, 32));
|
|
35
|
+
}
|
|
36
|
+
function generateUUID() {
|
|
37
|
+
return uuidV4();
|
|
38
|
+
}
|
|
39
|
+
function generateCommandId() {
|
|
40
|
+
return `cmd_${uuidV4()}`;
|
|
41
|
+
}
|
|
42
|
+
function generateEventId() {
|
|
43
|
+
return `evt_${uuidV4()}`;
|
|
44
|
+
}
|
|
45
|
+
function generateEntityId() {
|
|
46
|
+
return uuidV4();
|
|
47
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Utilities
|
|
3
|
+
* Provides schema validation for REST/WS/SSE/push payloads
|
|
4
|
+
*/
|
|
5
|
+
export interface ValidationResult {
|
|
6
|
+
valid: boolean;
|
|
7
|
+
errors: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function validateEmail(email: string): ValidationResult;
|
|
10
|
+
export declare function validatePhone(phone: string): ValidationResult;
|
|
11
|
+
export declare function validateUsername(username: string): ValidationResult;
|
|
12
|
+
export declare function validatePassword(password: string): ValidationResult;
|
|
13
|
+
export declare function validateOrderPayload(payload: unknown): ValidationResult;
|
|
14
|
+
export declare function validateChatMessage(payload: unknown): ValidationResult;
|
|
15
|
+
export declare function validateEventEnvelope(payload: unknown): ValidationResult;
|
|
16
|
+
export declare function validatePromoCode(code: string): ValidationResult;
|
|
17
|
+
export declare function validateAddress(address: Record<string, unknown>): ValidationResult;
|
|
18
|
+
export declare function validatePaymentMethod(payment: Record<string, unknown>): ValidationResult;
|
|
19
|
+
export declare const validation: {
|
|
20
|
+
isNotEmpty: (value: string) => boolean;
|
|
21
|
+
isValid: (value: string, validator: (v: string) => ValidationResult) => boolean;
|
|
22
|
+
email: ((v: string) => ValidationResult) & {
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
phone: ((v: string) => ValidationResult) & {
|
|
26
|
+
message: string;
|
|
27
|
+
};
|
|
28
|
+
password: ((v: string) => ValidationResult) & {
|
|
29
|
+
message: string;
|
|
30
|
+
};
|
|
31
|
+
};
|