@bayonai/offline 0.8.0 → 0.10.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/CHANGELOG.md +39 -1
- package/README.md +107 -16
- package/RECOVERY.md +64 -0
- package/dist/browserFallbackRecovery.d.ts +10 -9
- package/dist/browserFallbackRecovery.js +100 -28
- package/dist/browserRecovery.d.ts +2 -2
- package/dist/durableCommandStore.d.ts +1 -1
- package/dist/idbDriver.d.ts +3 -1
- package/dist/idbDriver.js +29 -14
- package/dist/index.d.ts +10 -7
- package/dist/index.js +3 -0
- package/dist/pendingWriteSupersession.d.ts +11 -0
- package/dist/pendingWriteSupersession.js +25 -0
- package/dist/pendingWrites.d.ts +6 -2
- package/dist/pendingWrites.js +45 -11
- package/dist/readBoundary.d.ts +13 -0
- package/dist/readBoundary.js +23 -0
- package/dist/readCache.d.ts +26 -5
- package/dist/readCache.js +113 -19
- package/dist/recoveryPolicy.d.ts +20 -0
- package/dist/recoveryPolicy.js +73 -0
- package/dist-cjs/browserCoordination.d.ts +23 -0
- package/dist-cjs/browserFallbackRecovery.d.ts +33 -0
- package/dist-cjs/browserFallbackRecovery.js +100 -28
- package/dist-cjs/browserRecovery.d.ts +42 -0
- package/dist-cjs/durableCommandStore.d.ts +49 -0
- package/dist-cjs/idbDriver.d.ts +28 -0
- package/dist-cjs/idbDriver.js +29 -14
- package/dist-cjs/index.d.ts +10 -0
- package/dist-cjs/index.js +3 -0
- package/dist-cjs/pendingWriteSupersession.d.ts +11 -0
- package/dist-cjs/pendingWriteSupersession.js +28 -0
- package/dist-cjs/pendingWrites.d.ts +179 -0
- package/dist-cjs/pendingWrites.js +45 -11
- package/dist-cjs/readBoundary.d.ts +13 -0
- package/dist-cjs/readBoundary.js +26 -0
- package/dist-cjs/readCache.d.ts +112 -0
- package/dist-cjs/readCache.js +113 -19
- package/dist-cjs/recoveryPolicy.d.ts +20 -0
- package/dist-cjs/recoveryPolicy.js +78 -0
- package/package.json +16 -7
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Shared product decision: recovery is application work, never a retry prompt. */
|
|
2
|
+
export declare const offlineRecoveryCopy: {
|
|
3
|
+
readonly reload: "Reload";
|
|
4
|
+
readonly reloading: "Reconnecting…";
|
|
5
|
+
readonly preservedChanges: "Some changes could not be saved. Your edits are preserved.";
|
|
6
|
+
};
|
|
7
|
+
export type PendingChangesGuidanceState = {
|
|
8
|
+
hasReadyChanges: boolean;
|
|
9
|
+
hasDrafts: boolean;
|
|
10
|
+
hasErrors: boolean;
|
|
11
|
+
isOffline: boolean;
|
|
12
|
+
};
|
|
13
|
+
/** Hosts project domain records to flags; payloads never enter shared guidance. */
|
|
14
|
+
export declare function getPendingChangesGuidance({ hasReadyChanges, hasDrafts, hasErrors, isOffline, }: PendingChangesGuidanceState): string;
|
|
15
|
+
/**
|
|
16
|
+
* Recognize known transient transport/service failures without a provider SDK.
|
|
17
|
+
* Hosts still own domain validation, idempotency, account scope and replay selection.
|
|
18
|
+
* Unknown failures are not permission to blindly repeat a mutation.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isTransientOfflineError(error: unknown): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.offlineRecoveryCopy = void 0;
|
|
4
|
+
exports.getPendingChangesGuidance = getPendingChangesGuidance;
|
|
5
|
+
exports.isTransientOfflineError = isTransientOfflineError;
|
|
6
|
+
/** Shared product decision: recovery is application work, never a retry prompt. */
|
|
7
|
+
exports.offlineRecoveryCopy = {
|
|
8
|
+
reload: "Reload",
|
|
9
|
+
reloading: "Reconnecting…",
|
|
10
|
+
preservedChanges: "Some changes could not be saved. Your edits are preserved.",
|
|
11
|
+
};
|
|
12
|
+
/** Hosts project domain records to flags; payloads never enter shared guidance. */
|
|
13
|
+
function getPendingChangesGuidance({ hasReadyChanges, hasDrafts, hasErrors, isOffline, }) {
|
|
14
|
+
if (!hasReadyChanges)
|
|
15
|
+
return hasDrafts
|
|
16
|
+
? "Finish editing these drafts to save them."
|
|
17
|
+
: exports.offlineRecoveryCopy.preservedChanges;
|
|
18
|
+
if (!hasDrafts && !hasErrors)
|
|
19
|
+
return isOffline
|
|
20
|
+
? "We’ll sync when you’re back online."
|
|
21
|
+
: "We’ll sync automatically.";
|
|
22
|
+
const sync = isOffline
|
|
23
|
+
? "Changes ready to send will sync when you’re back online."
|
|
24
|
+
: "Changes ready to send will sync automatically.";
|
|
25
|
+
return hasDrafts ? `${sync} Finish editing drafts to save them.` : sync;
|
|
26
|
+
}
|
|
27
|
+
const terminalCodes = new Set([
|
|
28
|
+
"unauthenticated",
|
|
29
|
+
"permission-denied",
|
|
30
|
+
"resource-exhausted",
|
|
31
|
+
"invalid-argument",
|
|
32
|
+
"failed-precondition",
|
|
33
|
+
"not-found",
|
|
34
|
+
"already-exists",
|
|
35
|
+
]);
|
|
36
|
+
const transientCodes = new Set([
|
|
37
|
+
"unavailable",
|
|
38
|
+
"deadline-exceeded",
|
|
39
|
+
"cancelled",
|
|
40
|
+
"network-request-failed",
|
|
41
|
+
"internal",
|
|
42
|
+
"aborted",
|
|
43
|
+
]);
|
|
44
|
+
// Exact transport diagnostics are safe fallbacks only when no structured code
|
|
45
|
+
// exists. Domain messages mentioning a network/offline setting are not signals.
|
|
46
|
+
const connectivityMessages = new Set([
|
|
47
|
+
"failed to fetch",
|
|
48
|
+
"fetch failed",
|
|
49
|
+
"network request failed",
|
|
50
|
+
"load failed",
|
|
51
|
+
"offline",
|
|
52
|
+
"network unavailable",
|
|
53
|
+
"failed to get documents from server. these documents may exist in the local cache",
|
|
54
|
+
"failed to get document because the client is offline",
|
|
55
|
+
]);
|
|
56
|
+
/**
|
|
57
|
+
* Recognize known transient transport/service failures without a provider SDK.
|
|
58
|
+
* Hosts still own domain validation, idempotency, account scope and replay selection.
|
|
59
|
+
* Unknown failures are not permission to blindly repeat a mutation.
|
|
60
|
+
*/
|
|
61
|
+
function isTransientOfflineError(error) {
|
|
62
|
+
const record = error && typeof error === "object" ? error : {};
|
|
63
|
+
const rawCode = "code" in record ? record.code : undefined;
|
|
64
|
+
const code = typeof rawCode === "string" ? rawCode.toLowerCase().split("/").at(-1) : "";
|
|
65
|
+
if (terminalCodes.has(code))
|
|
66
|
+
return false;
|
|
67
|
+
if (transientCodes.has(code))
|
|
68
|
+
return true;
|
|
69
|
+
if (code)
|
|
70
|
+
return false;
|
|
71
|
+
const rawMessage = typeof error === "string"
|
|
72
|
+
? error
|
|
73
|
+
: "message" in record
|
|
74
|
+
? record.message
|
|
75
|
+
: undefined;
|
|
76
|
+
const message = typeof rawMessage === "string" ? rawMessage.toLowerCase() : "";
|
|
77
|
+
return connectivityMessages.has(message.trim().replace(/[.!]$/, ""));
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bayonai/offline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Reusable offline read-cache, pending-write, and silent recovery primitives.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bayon AI",
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"idb",
|
|
22
22
|
"typescript"
|
|
23
23
|
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22"
|
|
26
|
+
},
|
|
24
27
|
"sideEffects": false,
|
|
25
28
|
"type": "module",
|
|
26
29
|
"main": "./dist-cjs/index.js",
|
|
@@ -28,9 +31,14 @@
|
|
|
28
31
|
"types": "./dist/index.d.ts",
|
|
29
32
|
"exports": {
|
|
30
33
|
".": {
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"default": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"require": {
|
|
39
|
+
"types": "./dist-cjs/index.d.ts",
|
|
40
|
+
"default": "./dist-cjs/index.js"
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
43
|
},
|
|
36
44
|
"files": [
|
|
@@ -38,13 +46,14 @@
|
|
|
38
46
|
"dist-cjs",
|
|
39
47
|
"CHANGELOG.md",
|
|
40
48
|
"LICENSE",
|
|
41
|
-
"README.md"
|
|
49
|
+
"README.md",
|
|
50
|
+
"RECOVERY.md"
|
|
42
51
|
],
|
|
43
52
|
"publishConfig": {
|
|
44
53
|
"access": "public"
|
|
45
54
|
},
|
|
46
55
|
"scripts": {
|
|
47
|
-
"build": "tsc -p tsconfig.json && node scripts/write-esm-extensions.mjs && tsc -p tsconfig.cjs.json && node scripts/write-cjs.mjs",
|
|
56
|
+
"build": "tsc -p tsconfig.json && node scripts/write-esm-extensions.mjs && tsc -p tsconfig.cjs.json && node scripts/write-cjs.mjs && node scripts/verify-dist.mjs",
|
|
48
57
|
"lint": "tsc --noEmit -p tsconfig.json",
|
|
49
58
|
"pack:smoke": "corepack pnpm run build && npm pack --dry-run --access public",
|
|
50
59
|
"prepack": "corepack pnpm run build",
|
|
@@ -55,7 +64,7 @@
|
|
|
55
64
|
"idb": "^8.0.3"
|
|
56
65
|
},
|
|
57
66
|
"devDependencies": {
|
|
58
|
-
"fake-indexeddb": "^6.2.
|
|
67
|
+
"fake-indexeddb": "^6.2.6",
|
|
59
68
|
"typescript": "^6.0.3",
|
|
60
69
|
"vitest": "^5.0.1"
|
|
61
70
|
}
|