@noy-db/in-zustand 0.2.0-pre.9 → 0.3.0-pre.2
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 +1 -1
- package/package.json +6 -13
- package/dist/index.cjs +0 -95
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -60
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ See the [main repository](https://github.com/vLannaAi/noy-db#readme) for setup,
|
|
|
26
26
|
|
|
27
27
|
- Source — [`packages/in-zustand`](https://github.com/vLannaAi/noy-db/tree/main/packages/in-zustand)
|
|
28
28
|
- Issues — [github.com/vLannaAi/noy-db/issues](https://github.com/vLannaAi/noy-db/issues)
|
|
29
|
-
- Spec — [`SPEC.md`](https://github.com/vLannaAi/noy-db/blob/main/SPEC.md)
|
|
29
|
+
- Spec — [`SPEC.md`](https://github.com/vLannaAi/noy-db-docs/blob/main/SPEC.md)
|
|
30
30
|
|
|
31
31
|
## License
|
|
32
32
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noy-db/in-zustand",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-pre.2",
|
|
4
4
|
"description": "Zustand adapter for noy-db — factory that mirrors defineNoydbStore for Zustand users, auto-syncs state from noy-db change events, and supports optimistic mutations.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vLannaAi <vicio@lanna.ai>",
|
|
@@ -17,17 +17,10 @@
|
|
|
17
17
|
"sideEffects": false,
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
"default": "./dist/index.js"
|
|
23
|
-
},
|
|
24
|
-
"require": {
|
|
25
|
-
"types": "./dist/index.d.cts",
|
|
26
|
-
"default": "./dist/index.cjs"
|
|
27
|
-
}
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
28
22
|
}
|
|
29
23
|
},
|
|
30
|
-
"main": "./dist/index.cjs",
|
|
31
24
|
"module": "./dist/index.js",
|
|
32
25
|
"types": "./dist/index.d.ts",
|
|
33
26
|
"files": [
|
|
@@ -36,15 +29,15 @@
|
|
|
36
29
|
"LICENSE"
|
|
37
30
|
],
|
|
38
31
|
"engines": {
|
|
39
|
-
"node": ">=
|
|
32
|
+
"node": ">=22.0.0"
|
|
40
33
|
},
|
|
41
34
|
"peerDependencies": {
|
|
42
35
|
"zustand": "^4.0.0 || ^5.0.0",
|
|
43
|
-
"@noy-db/hub": "0.
|
|
36
|
+
"@noy-db/hub": "0.3.0-pre.2"
|
|
44
37
|
},
|
|
45
38
|
"devDependencies": {
|
|
46
39
|
"zustand": "^5.0.0",
|
|
47
|
-
"@noy-db/hub": "0.
|
|
40
|
+
"@noy-db/hub": "0.3.0-pre.2"
|
|
48
41
|
},
|
|
49
42
|
"keywords": [
|
|
50
43
|
"noy-db",
|
package/dist/index.cjs
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
createNoydbStore: () => createNoydbStore
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(index_exports);
|
|
26
|
-
function createNoydbStore(getCollection) {
|
|
27
|
-
return (set, get) => {
|
|
28
|
-
let subscribed = false;
|
|
29
|
-
let unsubscribe = null;
|
|
30
|
-
async function ensureSubscribed(coll) {
|
|
31
|
-
if (subscribed) return;
|
|
32
|
-
subscribed = true;
|
|
33
|
-
unsubscribe = coll.subscribe(() => {
|
|
34
|
-
void get().refresh();
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
async function load() {
|
|
38
|
-
try {
|
|
39
|
-
const coll = await Promise.resolve(getCollection());
|
|
40
|
-
await ensureSubscribed(coll);
|
|
41
|
-
const list = await coll.list();
|
|
42
|
-
const ids = await coll.list().then((rows) => rows.map((_r, i) => String(i)));
|
|
43
|
-
const records = {};
|
|
44
|
-
list.forEach((rec, idx) => {
|
|
45
|
-
const maybeId = rec.id;
|
|
46
|
-
records[maybeId ?? ids[idx]] = rec;
|
|
47
|
-
});
|
|
48
|
-
set({ records, loading: false, error: null });
|
|
49
|
-
} catch (err) {
|
|
50
|
-
set({ records: {}, loading: false, error: err });
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
void load();
|
|
54
|
-
return {
|
|
55
|
-
records: {},
|
|
56
|
-
loading: true,
|
|
57
|
-
error: null,
|
|
58
|
-
async put(id, value) {
|
|
59
|
-
try {
|
|
60
|
-
const coll = await Promise.resolve(getCollection());
|
|
61
|
-
await coll.put(id, value);
|
|
62
|
-
} catch (err) {
|
|
63
|
-
set({ error: err });
|
|
64
|
-
throw err;
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
async remove(id) {
|
|
68
|
-
try {
|
|
69
|
-
const coll = await Promise.resolve(getCollection());
|
|
70
|
-
await coll.delete(id);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
set({ error: err });
|
|
73
|
-
throw err;
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
async refresh() {
|
|
77
|
-
await load();
|
|
78
|
-
},
|
|
79
|
-
// Internal cleanup helper — Zustand stores don't have a native
|
|
80
|
-
// unmount hook, so framework bindings can call this when
|
|
81
|
-
// tearing down.
|
|
82
|
-
...{
|
|
83
|
-
_unsubscribe() {
|
|
84
|
-
unsubscribe?.();
|
|
85
|
-
subscribed = false;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
92
|
-
0 && (module.exports = {
|
|
93
|
-
createNoydbStore
|
|
94
|
-
});
|
|
95
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * **@noy-db/in-zustand** — Zustand adapter for noy-db.\n *\n * Factory that creates a Zustand store backed by a noy-db\n * `Collection<T>`. Reads hydrate from the collection on first access\n * and auto-refresh on every change event; writes go through the\n * collection (and are therefore encrypted + replicated by the sync\n * engine).\n *\n * ```ts\n * import { create } from 'zustand'\n * import { createNoydbStore } from '@noy-db/in-zustand'\n *\n * const useInvoices = create(createNoydbStore(() => db.vault('acme').collection<Invoice>('invoices')))\n * ```\n *\n * The returned state slice shape:\n *\n * ```ts\n * {\n * records: Record<string, T>\n * loading: boolean\n * error: Error | null\n * put: (id, value) => Promise<void>\n * remove: (id) => Promise<void>\n * refresh: () => Promise<void>\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { StateCreator } from 'zustand'\nimport type { Collection } from '@noy-db/hub'\n\nexport interface NoydbZustandSlice<T> {\n /** Current records keyed by id. */\n records: Record<string, T>\n /** True during the initial hydration. */\n loading: boolean\n /** Error from hydration or a mutation. */\n error: Error | null\n /** Put a record — encrypts + writes + fires the auto-refresh. */\n put(id: string, value: T): Promise<void>\n /** Delete a record. */\n remove(id: string): Promise<void>\n /** Re-hydrate from the underlying collection. */\n refresh(): Promise<void>\n}\n\n/**\n * Produce a Zustand `StateCreator` backed by a noy-db collection.\n *\n * The `getCollection` factory is called lazily on first access so\n * consumers can wire the store while the `Noydb` instance is still\n * being opened asynchronously — the first `refresh()` waits for the\n * factory to succeed before hydrating.\n */\nexport function createNoydbStore<T>(\n getCollection: () => Collection<T> | Promise<Collection<T>>,\n): StateCreator<NoydbZustandSlice<T>> {\n return (set, get) => {\n let subscribed = false\n let unsubscribe: (() => void) | null = null\n\n async function ensureSubscribed(coll: Collection<T>): Promise<void> {\n if (subscribed) return\n subscribed = true\n unsubscribe = coll.subscribe(() => {\n void get().refresh()\n })\n }\n\n async function load(): Promise<void> {\n try {\n const coll = await Promise.resolve(getCollection())\n await ensureSubscribed(coll)\n const list = await coll.list()\n const ids = await coll.list().then(rows => rows.map((_r, i) => String(i)))\n // Derive an id map. list() returns records; get the id via the envelope round-trip.\n // Fallback: use each record's own `id` field when present; else use string index.\n const records: Record<string, T> = {}\n list.forEach((rec, idx) => {\n const maybeId = (rec as unknown as { id?: string }).id\n records[maybeId ?? ids[idx]!] = rec\n })\n set({ records, loading: false, error: null })\n } catch (err) {\n set({ records: {}, loading: false, error: err as Error })\n }\n }\n\n // Trigger initial load on first read.\n void load()\n\n return {\n records: {},\n loading: true,\n error: null,\n\n async put(id, value) {\n try {\n const coll = await Promise.resolve(getCollection())\n await coll.put(id, value)\n // `subscribe()` will trigger refresh; no manual state update needed here.\n } catch (err) {\n set({ error: err as Error })\n throw err\n }\n },\n\n async remove(id) {\n try {\n const coll = await Promise.resolve(getCollection())\n await coll.delete(id)\n } catch (err) {\n set({ error: err as Error })\n throw err\n }\n },\n\n async refresh() {\n await load()\n },\n\n // Internal cleanup helper — Zustand stores don't have a native\n // unmount hook, so framework bindings can call this when\n // tearing down.\n ...({\n _unsubscribe(): void {\n unsubscribe?.()\n subscribed = false\n },\n } as Record<string, () => void>),\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0DO,SAAS,iBACd,eACoC;AACpC,SAAO,CAAC,KAAK,QAAQ;AACnB,QAAI,aAAa;AACjB,QAAI,cAAmC;AAEvC,mBAAe,iBAAiB,MAAoC;AAClE,UAAI,WAAY;AAChB,mBAAa;AACb,oBAAc,KAAK,UAAU,MAAM;AACjC,aAAK,IAAI,EAAE,QAAQ;AAAA,MACrB,CAAC;AAAA,IACH;AAEA,mBAAe,OAAsB;AACnC,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,QAAQ,cAAc,CAAC;AAClD,cAAM,iBAAiB,IAAI;AAC3B,cAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,cAAM,MAAM,MAAM,KAAK,KAAK,EAAE,KAAK,UAAQ,KAAK,IAAI,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AAGzE,cAAM,UAA6B,CAAC;AACpC,aAAK,QAAQ,CAAC,KAAK,QAAQ;AACzB,gBAAM,UAAW,IAAmC;AACpD,kBAAQ,WAAW,IAAI,GAAG,CAAE,IAAI;AAAA,QAClC,CAAC;AACD,YAAI,EAAE,SAAS,SAAS,OAAO,OAAO,KAAK,CAAC;AAAA,MAC9C,SAAS,KAAK;AACZ,YAAI,EAAE,SAAS,CAAC,GAAG,SAAS,OAAO,OAAO,IAAa,CAAC;AAAA,MAC1D;AAAA,IACF;AAGA,SAAK,KAAK;AAEV,WAAO;AAAA,MACL,SAAS,CAAC;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MAEP,MAAM,IAAI,IAAI,OAAO;AACnB,YAAI;AACF,gBAAM,OAAO,MAAM,QAAQ,QAAQ,cAAc,CAAC;AAClD,gBAAM,KAAK,IAAI,IAAI,KAAK;AAAA,QAE1B,SAAS,KAAK;AACZ,cAAI,EAAE,OAAO,IAAa,CAAC;AAC3B,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,MAAM,OAAO,IAAI;AACf,YAAI;AACF,gBAAM,OAAO,MAAM,QAAQ,QAAQ,cAAc,CAAC;AAClD,gBAAM,KAAK,OAAO,EAAE;AAAA,QACtB,SAAS,KAAK;AACZ,cAAI,EAAE,OAAO,IAAa,CAAC;AAC3B,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,MAAM,UAAU;AACd,cAAM,KAAK;AAAA,MACb;AAAA;AAAA;AAAA;AAAA,MAKA,GAAI;AAAA,QACF,eAAqB;AACnB,wBAAc;AACd,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/index.d.cts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { StateCreator } from 'zustand';
|
|
2
|
-
import { Collection } from '@noy-db/hub';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* **@noy-db/in-zustand** — Zustand adapter for noy-db.
|
|
6
|
-
*
|
|
7
|
-
* Factory that creates a Zustand store backed by a noy-db
|
|
8
|
-
* `Collection<T>`. Reads hydrate from the collection on first access
|
|
9
|
-
* and auto-refresh on every change event; writes go through the
|
|
10
|
-
* collection (and are therefore encrypted + replicated by the sync
|
|
11
|
-
* engine).
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* import { create } from 'zustand'
|
|
15
|
-
* import { createNoydbStore } from '@noy-db/in-zustand'
|
|
16
|
-
*
|
|
17
|
-
* const useInvoices = create(createNoydbStore(() => db.vault('acme').collection<Invoice>('invoices')))
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* The returned state slice shape:
|
|
21
|
-
*
|
|
22
|
-
* ```ts
|
|
23
|
-
* {
|
|
24
|
-
* records: Record<string, T>
|
|
25
|
-
* loading: boolean
|
|
26
|
-
* error: Error | null
|
|
27
|
-
* put: (id, value) => Promise<void>
|
|
28
|
-
* remove: (id) => Promise<void>
|
|
29
|
-
* refresh: () => Promise<void>
|
|
30
|
-
* }
|
|
31
|
-
* ```
|
|
32
|
-
*
|
|
33
|
-
* @packageDocumentation
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
interface NoydbZustandSlice<T> {
|
|
37
|
-
/** Current records keyed by id. */
|
|
38
|
-
records: Record<string, T>;
|
|
39
|
-
/** True during the initial hydration. */
|
|
40
|
-
loading: boolean;
|
|
41
|
-
/** Error from hydration or a mutation. */
|
|
42
|
-
error: Error | null;
|
|
43
|
-
/** Put a record — encrypts + writes + fires the auto-refresh. */
|
|
44
|
-
put(id: string, value: T): Promise<void>;
|
|
45
|
-
/** Delete a record. */
|
|
46
|
-
remove(id: string): Promise<void>;
|
|
47
|
-
/** Re-hydrate from the underlying collection. */
|
|
48
|
-
refresh(): Promise<void>;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Produce a Zustand `StateCreator` backed by a noy-db collection.
|
|
52
|
-
*
|
|
53
|
-
* The `getCollection` factory is called lazily on first access so
|
|
54
|
-
* consumers can wire the store while the `Noydb` instance is still
|
|
55
|
-
* being opened asynchronously — the first `refresh()` waits for the
|
|
56
|
-
* factory to succeed before hydrating.
|
|
57
|
-
*/
|
|
58
|
-
declare function createNoydbStore<T>(getCollection: () => Collection<T> | Promise<Collection<T>>): StateCreator<NoydbZustandSlice<T>>;
|
|
59
|
-
|
|
60
|
-
export { type NoydbZustandSlice, createNoydbStore };
|