@lunora/client 1.0.0-alpha.2 → 1.0.0-alpha.20
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/LICENSE.md +6 -0
- package/README.md +2 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/index.d.mts +144 -24
- package/dist/index.d.ts +144 -24
- package/dist/index.mjs +9 -8
- package/dist/packem_shared/CONFLICT_ERROR_CODE-B8gQ8tyU.mjs +33 -0
- package/dist/packem_shared/{DEFAULT_MAX_BUFFER-BDkqO5PW.mjs → DEFAULT_MAX_BUFFER-7hFnzNk9.mjs} +6 -3
- package/dist/packem_shared/{LunoraClient-UiULzH_1.mjs → LunoraClient-hrmLXEHd.mjs} +1512 -266
- package/dist/packem_shared/OfflineQueue-GGYJRmhF.mjs +1 -0
- package/dist/packem_shared/SubscriptionRegistry-Cxr70og-.mjs +1 -0
- package/dist/packem_shared/{createInMemoryPersistence-CW82inU5.mjs → createInMemoryPersistence-Ds7z8n8d.mjs} +17 -3
- package/dist/packem_shared/{createInMemoryQueryCache-B1PQ9Twl.mjs → createInMemoryQueryCache-iWtKPrid.mjs} +18 -4
- package/dist/packem_shared/createLocalStore-IOur0jHF.mjs +1 -0
- package/dist/packem_shared/createMutatorRunner-BETvCd0p.mjs +31 -0
- package/dist/packem_shared/{createServerClient-BjZc3gD8.mjs → createServerClient-CKKZrXLc.mjs} +1 -1
- package/dist/packem_shared/local-store-BNgN3Dw3.mjs +111 -0
- package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.mts → lunora-client.d-DVdVtJV8.d.mts} +973 -58
- package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.ts → lunora-client.d-DVdVtJV8.d.ts} +973 -58
- package/dist/packem_shared/{OfflineQueue-D5p_QgF_.mjs → offline-queue-B9vfdSqp.mjs} +49 -6
- package/dist/packem_shared/{preload.d-dSaRMuhL.d.mts → preload.d-BXFvxpiv.d.mts} +1 -1
- package/dist/packem_shared/{preload.d-BoDmFqSG.d.ts → preload.d-Bb69VRgE.d.ts} +1 -1
- package/dist/packem_shared/subscription-DoyO04-2.mjs +65 -0
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/ssr/index.d.mts +3 -3
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.mjs +1 -1
- package/package.json +5 -2
- package/dist/packem_shared/CONFLICT_ERROR_CODE-aUdVbEDw.mjs +0 -4
- package/dist/packem_shared/SubscriptionRegistry-B-Qx_Gux.mjs +0 -26
- package/dist/packem_shared/createLocalStore-DSUfoLqY.mjs +0 -36
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { O as OfflineQueue, n as nextId, r as reportPersistenceError } from './offline-queue-B9vfdSqp.mjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { S as SubscriptionRegistry } from './subscription-DoyO04-2.mjs';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
1
3
|
const createInMemoryPersistence = () => {
|
|
2
4
|
const entries = /* @__PURE__ */ new Map();
|
|
3
5
|
const clone = (mutation) => {
|
|
@@ -25,7 +27,7 @@ const createInMemoryPersistence = () => {
|
|
|
25
27
|
}
|
|
26
28
|
};
|
|
27
29
|
};
|
|
28
|
-
const DEFAULT_DATABASE = "lunora";
|
|
30
|
+
const DEFAULT_DATABASE = "lunora-outbox";
|
|
29
31
|
const DEFAULT_STORE = "offline-mutations";
|
|
30
32
|
const ID_INDEX = "by_id";
|
|
31
33
|
const promisifyRequest = (request) => new Promise((resolve, reject) => {
|
|
@@ -39,7 +41,7 @@ const promisifyRequest = (request) => new Promise((resolve, reject) => {
|
|
|
39
41
|
const createIndexedDbPersistence = (options = {}) => {
|
|
40
42
|
const factory = options.indexedDB ?? (typeof indexedDB === "undefined" ? void 0 : indexedDB);
|
|
41
43
|
if (!factory) {
|
|
42
|
-
throw new
|
|
44
|
+
throw new LunoraError("INTERNAL", "createIndexedDbPersistence: no IndexedDB available — pass `indexedDB` or use createInMemoryPersistence()");
|
|
43
45
|
}
|
|
44
46
|
const databaseName = options.databaseName ?? DEFAULT_DATABASE;
|
|
45
47
|
const storeName = options.storeName ?? DEFAULT_STORE;
|
|
@@ -101,5 +103,17 @@ const createIndexedDbPersistence = (options = {}) => {
|
|
|
101
103
|
}
|
|
102
104
|
};
|
|
103
105
|
};
|
|
106
|
+
const resolvePersistenceAdapter = (option, autoProbe = true) => {
|
|
107
|
+
if (option === false) {
|
|
108
|
+
return void 0;
|
|
109
|
+
}
|
|
110
|
+
if (option) {
|
|
111
|
+
return option;
|
|
112
|
+
}
|
|
113
|
+
if (!autoProbe || typeof indexedDB === "undefined") {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
return createIndexedDbPersistence();
|
|
117
|
+
};
|
|
104
118
|
|
|
105
|
-
export { createInMemoryPersistence, createIndexedDbPersistence };
|
|
119
|
+
export { createInMemoryPersistence, createIndexedDbPersistence, resolvePersistenceAdapter };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
1
3
|
const queryCacheKey = (functionPath, argsKey, shardKey) => `${functionPath}::${argsKey}::${shardKey ?? ""}`;
|
|
2
4
|
const DEFAULT_MAX_ENTRIES = 500;
|
|
3
5
|
const createInMemoryQueryCache = (options = {}) => {
|
|
@@ -35,10 +37,10 @@ const createInMemoryQueryCache = (options = {}) => {
|
|
|
35
37
|
}
|
|
36
38
|
};
|
|
37
39
|
};
|
|
38
|
-
const DEFAULT_DATABASE = "lunora";
|
|
40
|
+
const DEFAULT_DATABASE = "lunora-query-cache";
|
|
39
41
|
const DEFAULT_STORE = "query-cache";
|
|
40
42
|
const TS_INDEX = "by_ts";
|
|
41
|
-
const DATABASE_VERSION =
|
|
43
|
+
const DATABASE_VERSION = 1;
|
|
42
44
|
const promisifyRequest = (request) => new Promise((resolve, reject) => {
|
|
43
45
|
request.addEventListener("success", () => {
|
|
44
46
|
resolve(request.result);
|
|
@@ -50,7 +52,7 @@ const promisifyRequest = (request) => new Promise((resolve, reject) => {
|
|
|
50
52
|
const createIndexedDbQueryCache = (options = {}) => {
|
|
51
53
|
const factory = options.indexedDB ?? (typeof indexedDB === "undefined" ? void 0 : indexedDB);
|
|
52
54
|
if (!factory) {
|
|
53
|
-
throw new
|
|
55
|
+
throw new LunoraError("INTERNAL", "createIndexedDbQueryCache: no IndexedDB available — pass `indexedDB` or use createInMemoryQueryCache()");
|
|
54
56
|
}
|
|
55
57
|
const databaseName = options.databaseName ?? DEFAULT_DATABASE;
|
|
56
58
|
const storeName = options.storeName ?? DEFAULT_STORE;
|
|
@@ -134,5 +136,17 @@ const createIndexedDbQueryCache = (options = {}) => {
|
|
|
134
136
|
}
|
|
135
137
|
};
|
|
136
138
|
};
|
|
139
|
+
const resolveQueryCacheAdapter = (option) => {
|
|
140
|
+
if (option === false) {
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
143
|
+
if (option) {
|
|
144
|
+
return option;
|
|
145
|
+
}
|
|
146
|
+
if (typeof indexedDB === "undefined") {
|
|
147
|
+
return void 0;
|
|
148
|
+
}
|
|
149
|
+
return createIndexedDbQueryCache();
|
|
150
|
+
};
|
|
137
151
|
|
|
138
|
-
export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey };
|
|
152
|
+
export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey, resolveQueryCacheAdapter };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { c as createLocalStore } from './local-store-BNgN3Dw3.mjs';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const createMutatorRunner = (handle, sinks) => {
|
|
2
|
+
let inFlight = 0;
|
|
3
|
+
let latestInvocation = 0;
|
|
4
|
+
const mutate = async (args) => {
|
|
5
|
+
latestInvocation += 1;
|
|
6
|
+
const invocation = latestInvocation;
|
|
7
|
+
inFlight += 1;
|
|
8
|
+
sinks.setPending(true);
|
|
9
|
+
try {
|
|
10
|
+
await handle(args).isPersisted.promise;
|
|
11
|
+
if (invocation === latestInvocation) {
|
|
12
|
+
sinks.setError(void 0);
|
|
13
|
+
}
|
|
14
|
+
} catch (error) {
|
|
15
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
16
|
+
if (invocation === latestInvocation) {
|
|
17
|
+
sinks.setError(normalized);
|
|
18
|
+
}
|
|
19
|
+
throw normalized;
|
|
20
|
+
} finally {
|
|
21
|
+
inFlight -= 1;
|
|
22
|
+
sinks.setPending(inFlight > 0);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const reset = () => {
|
|
26
|
+
sinks.setError(void 0);
|
|
27
|
+
};
|
|
28
|
+
return { mutate, reset };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { createMutatorRunner };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const foldOptimistic = (base, layers) => {
|
|
2
|
+
let value = base;
|
|
3
|
+
for (const layer of layers) {
|
|
4
|
+
try {
|
|
5
|
+
value = layer.transform(value);
|
|
6
|
+
} catch {
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
const notifySubscription = (state, value) => {
|
|
12
|
+
if (value === state.lastValue) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
state.lastValue = value;
|
|
16
|
+
for (const callback of state.callbacks) {
|
|
17
|
+
try {
|
|
18
|
+
callback(value);
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const applyOptimisticLayer = (state, optimistic) => {
|
|
24
|
+
let next;
|
|
25
|
+
try {
|
|
26
|
+
next = optimistic(state.lastValue);
|
|
27
|
+
} catch {
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
const layer = { id: /* @__PURE__ */ Symbol("optimistic"), transform: optimistic };
|
|
31
|
+
state.optimisticLayers.push(layer);
|
|
32
|
+
notifySubscription(state, next);
|
|
33
|
+
const remove = () => {
|
|
34
|
+
const index = state.optimisticLayers.findIndex((entry) => entry.id === layer.id);
|
|
35
|
+
if (index === -1) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
state.optimisticLayers.splice(index, 1);
|
|
39
|
+
return true;
|
|
40
|
+
};
|
|
41
|
+
const refold = () => {
|
|
42
|
+
notifySubscription(state, foldOptimistic(state.serverBase, state.optimisticLayers));
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
confirm: (commitCursor) => {
|
|
46
|
+
if (commitCursor === void 0) {
|
|
47
|
+
remove();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
layer.commitCursor = commitCursor;
|
|
51
|
+
if (state.serverCursor !== void 0 && state.serverCursor >= commitCursor && remove()) {
|
|
52
|
+
refold();
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
rollback: () => {
|
|
56
|
+
if (remove()) {
|
|
57
|
+
refold();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
const dropConfirmedLayers = (state, cursor) => {
|
|
63
|
+
if (cursor === void 0 || state.optimisticLayers.length === 0) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const before = state.optimisticLayers.length;
|
|
67
|
+
state.optimisticLayers = state.optimisticLayers.filter((layer) => layer.commitCursor === void 0 || layer.commitCursor > cursor);
|
|
68
|
+
return state.optimisticLayers.length !== before;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const createLocalStore = (subscriptions, shardKey, stableStringify) => {
|
|
72
|
+
const confirms = [];
|
|
73
|
+
const rollbacks = [];
|
|
74
|
+
const findState = (functionRef, argsKey) => {
|
|
75
|
+
for (const state of subscriptions.all()) {
|
|
76
|
+
if (state.fn.__lunoraRef === functionRef && state.shardKey === shardKey && state.argsKey === argsKey) {
|
|
77
|
+
return state;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return void 0;
|
|
81
|
+
};
|
|
82
|
+
const store = {
|
|
83
|
+
getAllQueries: (function_) => {
|
|
84
|
+
const matches = [];
|
|
85
|
+
for (const state of subscriptions.all()) {
|
|
86
|
+
if (state.fn.__lunoraRef === function_.__lunoraRef && state.shardKey === shardKey) {
|
|
87
|
+
matches.push({ args: state.args, value: state.lastValue });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return matches;
|
|
91
|
+
},
|
|
92
|
+
getQuery: (function_, args) => {
|
|
93
|
+
const state = findState(function_.__lunoraRef, stableStringify(args ?? {}));
|
|
94
|
+
return state?.lastValue;
|
|
95
|
+
},
|
|
96
|
+
setQuery: (function_, args, value) => {
|
|
97
|
+
const state = findState(function_.__lunoraRef, stableStringify(args ?? {}));
|
|
98
|
+
if (!state) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const handle = applyOptimisticLayer(state, () => value);
|
|
102
|
+
if (handle) {
|
|
103
|
+
confirms.push(handle.confirm);
|
|
104
|
+
rollbacks.push(handle.rollback);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
return { confirms, rollbacks, store };
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export { applyOptimisticLayer as a, createLocalStore as c, dropConfirmedLayers as d, foldOptimistic as f, notifySubscription as n };
|