@noy-db/in-svelte 0.2.0-pre.8 → 0.3.0-pre.1
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 -104
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -94
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-svelte`](https://github.com/vLannaAi/noy-db/tree/main/packages/in-svelte)
|
|
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-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-pre.1",
|
|
4
4
|
"description": "Svelte stores for noy-db — collectionStore / queryStore / syncStore backed by noy-db change events. Works with Svelte 4 store contract and Svelte 5 runes (via $store subscription interop).",
|
|
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,13 +29,13 @@
|
|
|
36
29
|
"LICENSE"
|
|
37
30
|
],
|
|
38
31
|
"engines": {
|
|
39
|
-
"node": ">=
|
|
32
|
+
"node": ">=22.0.0"
|
|
40
33
|
},
|
|
41
34
|
"peerDependencies": {
|
|
42
|
-
"@noy-db/hub": "0.
|
|
35
|
+
"@noy-db/hub": "0.3.0-pre.1"
|
|
43
36
|
},
|
|
44
37
|
"devDependencies": {
|
|
45
|
-
"@noy-db/hub": "0.
|
|
38
|
+
"@noy-db/hub": "0.3.0-pre.1"
|
|
46
39
|
},
|
|
47
40
|
"keywords": [
|
|
48
41
|
"noy-db",
|
package/dist/index.cjs
DELETED
|
@@ -1,104 +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
|
-
collectionStore: () => collectionStore,
|
|
24
|
-
queryStore: () => queryStore,
|
|
25
|
-
syncStore: () => syncStore
|
|
26
|
-
});
|
|
27
|
-
module.exports = __toCommonJS(index_exports);
|
|
28
|
-
function writable(initial) {
|
|
29
|
-
let value = initial;
|
|
30
|
-
const subscribers = /* @__PURE__ */ new Set();
|
|
31
|
-
return {
|
|
32
|
-
set(next) {
|
|
33
|
-
value = next;
|
|
34
|
-
for (const s of subscribers) s(next);
|
|
35
|
-
},
|
|
36
|
-
subscribe(run) {
|
|
37
|
-
subscribers.add(run);
|
|
38
|
-
run(value);
|
|
39
|
-
return () => {
|
|
40
|
-
subscribers.delete(run);
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function collectionStore(vault, collectionName) {
|
|
46
|
-
const inner = writable({ records: [], loading: true, error: null });
|
|
47
|
-
const coll = vault.collection(collectionName);
|
|
48
|
-
async function refresh() {
|
|
49
|
-
try {
|
|
50
|
-
const records = await coll.list();
|
|
51
|
-
inner.set({ records, loading: false, error: null });
|
|
52
|
-
} catch (err) {
|
|
53
|
-
inner.set({ records: [], loading: false, error: err });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
void refresh();
|
|
57
|
-
const unsubscribe = coll.subscribe(() => {
|
|
58
|
-
void refresh();
|
|
59
|
-
});
|
|
60
|
-
return {
|
|
61
|
-
subscribe: (run) => inner.subscribe(run),
|
|
62
|
-
refresh,
|
|
63
|
-
stop: unsubscribe
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function queryStore(vault, collectionName, builder) {
|
|
67
|
-
const inner = writable({ data: null, loading: true, error: null });
|
|
68
|
-
const coll = vault.collection(collectionName);
|
|
69
|
-
async function refresh() {
|
|
70
|
-
try {
|
|
71
|
-
const result = await Promise.resolve(builder(coll.query()));
|
|
72
|
-
inner.set({ data: result, loading: false, error: null });
|
|
73
|
-
} catch (err) {
|
|
74
|
-
inner.set({ data: null, loading: false, error: err });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
void refresh();
|
|
78
|
-
const unsubscribe = coll.subscribe(() => {
|
|
79
|
-
void refresh();
|
|
80
|
-
});
|
|
81
|
-
return {
|
|
82
|
-
subscribe: (run) => inner.subscribe(run),
|
|
83
|
-
refresh,
|
|
84
|
-
stop: unsubscribe
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
function syncStore(db) {
|
|
88
|
-
const inner = writable({ lastEvent: null, error: null });
|
|
89
|
-
const handler = (event) => {
|
|
90
|
-
inner.set({ lastEvent: event, error: null });
|
|
91
|
-
};
|
|
92
|
-
db.on("change", handler);
|
|
93
|
-
return {
|
|
94
|
-
subscribe: (run) => inner.subscribe(run),
|
|
95
|
-
stop: () => db.off("change", handler)
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
99
|
-
0 && (module.exports = {
|
|
100
|
-
collectionStore,
|
|
101
|
-
queryStore,
|
|
102
|
-
syncStore
|
|
103
|
-
});
|
|
104
|
-
//# 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-svelte** — Svelte stores for noy-db.\n *\n * Three store factories that conform to Svelte's standard store\n * contract (`subscribe(fn) → unsubscribe`). Works with:\n *\n * - Svelte 4 components via the `$store` auto-subscription syntax\n * - Svelte 5 runes via `$state(await fromStore(s).current)` or a\n * small `fromStore()` shim\n * - Any framework that consumes the Svelte store contract\n * (e.g. `@gradio/client`, non-Svelte integrations)\n *\n * ## Factories\n *\n * - {@link collectionStore} — reactive list of records.\n * - {@link queryStore} — reactive result of a query builder.\n * - {@link syncStore} — reactive Noydb-level change feed.\n *\n * ## Zero dependencies\n *\n * Svelte's store contract is ~10 lines of TypeScript. We re-implement\n * it inline rather than take a `svelte` peer-dep — the contract is\n * stable across Svelte 4/5 and the extra dependency is unnecessary\n * for store-only consumers (e.g. SvelteKit load functions).\n *\n * @packageDocumentation\n */\n\nimport type { Noydb, Vault, ChangeEvent, Query } from '@noy-db/hub'\n\n// ─── Svelte store contract (re-implemented, no svelte peer dep) ─────────\n\ntype Subscriber<T> = (value: T) => void\ntype Unsubscriber = () => void\n\nexport interface Readable<T> {\n subscribe(run: Subscriber<T>): Unsubscriber\n}\n\nfunction writable<T>(initial: T): {\n set(value: T): void\n subscribe(run: Subscriber<T>): Unsubscriber\n} {\n let value = initial\n const subscribers = new Set<Subscriber<T>>()\n return {\n set(next) {\n value = next\n for (const s of subscribers) s(next)\n },\n subscribe(run) {\n subscribers.add(run)\n run(value)\n return () => { subscribers.delete(run) }\n },\n }\n}\n\n// ─── collectionStore ───────────────────────────────────────────────────\n\nexport interface CollectionStoreState<T> {\n readonly records: readonly T[]\n readonly loading: boolean\n readonly error: Error | null\n}\n\n/**\n * Reactive collection records. Re-emits on every change event from\n * the collection (put / delete / sync).\n *\n * ```svelte\n * <script>\n * import { collectionStore } from '@noy-db/in-svelte'\n * const invoices = collectionStore(vault, 'invoices')\n * </script>\n *\n * {#each $invoices.records as invoice}\n * {invoice.id}\n * {/each}\n * ```\n */\nexport function collectionStore<T>(\n vault: Vault,\n collectionName: string,\n): Readable<CollectionStoreState<T>> & { refresh(): Promise<void>; stop(): void } {\n const inner = writable<CollectionStoreState<T>>({ records: [], loading: true, error: null })\n const coll = vault.collection<T>(collectionName)\n\n async function refresh(): Promise<void> {\n try {\n const records = await coll.list()\n inner.set({ records, loading: false, error: null })\n } catch (err) {\n inner.set({ records: [], loading: false, error: err as Error })\n }\n }\n\n void refresh()\n const unsubscribe = coll.subscribe(() => { void refresh() })\n\n return {\n subscribe: (run) => inner.subscribe(run),\n refresh,\n stop: unsubscribe,\n }\n}\n\n// ─── queryStore ────────────────────────────────────────────────────────\n\nexport interface QueryStoreState<R> {\n readonly data: R | null\n readonly loading: boolean\n readonly error: Error | null\n}\n\n/**\n * Reactive result of a query builder. The builder is re-run on every\n * change event — useful for aggregates, joins, and filtered lists.\n *\n * ```svelte\n * <script>\n * import { queryStore } from '@noy-db/in-svelte'\n * const paid = queryStore(vault, 'invoices', q => q.where('status', '==', 'paid').toArray())\n * </script>\n *\n * {#if $paid.loading} Loading… {:else} {$paid.data?.length} paid {/if}\n * ```\n */\nexport function queryStore<T, R>(\n vault: Vault,\n collectionName: string,\n builder: (q: Query<T>) => Promise<R> | R,\n): Readable<QueryStoreState<R>> & { refresh(): Promise<void>; stop(): void } {\n const inner = writable<QueryStoreState<R>>({ data: null, loading: true, error: null })\n const coll = vault.collection<T>(collectionName)\n\n async function refresh(): Promise<void> {\n try {\n const result = await Promise.resolve(builder(coll.query() as unknown as Query<T>))\n inner.set({ data: result, loading: false, error: null })\n } catch (err) {\n inner.set({ data: null, loading: false, error: err as Error })\n }\n }\n\n void refresh()\n const unsubscribe = coll.subscribe(() => { void refresh() })\n\n return {\n subscribe: (run) => inner.subscribe(run),\n refresh,\n stop: unsubscribe,\n }\n}\n\n// ─── syncStore ─────────────────────────────────────────────────────────\n\nexport interface SyncStoreState {\n readonly lastEvent: ChangeEvent | null\n readonly error: Error | null\n}\n\n/**\n * Reactive Noydb-level change feed. Useful for top-level status\n * indicators (last-update-time, \"unsynced changes\", offline banners).\n */\nexport function syncStore(db: Noydb): Readable<SyncStoreState> & { stop(): void } {\n const inner = writable<SyncStoreState>({ lastEvent: null, error: null })\n\n const handler = (event: ChangeEvent): void => {\n inner.set({ lastEvent: event, error: null })\n }\n db.on('change', handler)\n\n return {\n subscribe: (run) => inner.subscribe(run),\n stop: () => db.off('change', handler),\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuCA,SAAS,SAAY,SAGnB;AACA,MAAI,QAAQ;AACZ,QAAM,cAAc,oBAAI,IAAmB;AAC3C,SAAO;AAAA,IACL,IAAI,MAAM;AACR,cAAQ;AACR,iBAAW,KAAK,YAAa,GAAE,IAAI;AAAA,IACrC;AAAA,IACA,UAAU,KAAK;AACb,kBAAY,IAAI,GAAG;AACnB,UAAI,KAAK;AACT,aAAO,MAAM;AAAE,oBAAY,OAAO,GAAG;AAAA,MAAE;AAAA,IACzC;AAAA,EACF;AACF;AAyBO,SAAS,gBACd,OACA,gBACgF;AAChF,QAAM,QAAQ,SAAkC,EAAE,SAAS,CAAC,GAAG,SAAS,MAAM,OAAO,KAAK,CAAC;AAC3F,QAAM,OAAO,MAAM,WAAc,cAAc;AAE/C,iBAAe,UAAyB;AACtC,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,KAAK;AAChC,YAAM,IAAI,EAAE,SAAS,SAAS,OAAO,OAAO,KAAK,CAAC;AAAA,IACpD,SAAS,KAAK;AACZ,YAAM,IAAI,EAAE,SAAS,CAAC,GAAG,SAAS,OAAO,OAAO,IAAa,CAAC;AAAA,IAChE;AAAA,EACF;AAEA,OAAK,QAAQ;AACb,QAAM,cAAc,KAAK,UAAU,MAAM;AAAE,SAAK,QAAQ;AAAA,EAAE,CAAC;AAE3D,SAAO;AAAA,IACL,WAAW,CAAC,QAAQ,MAAM,UAAU,GAAG;AAAA,IACvC;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAuBO,SAAS,WACd,OACA,gBACA,SAC2E;AAC3E,QAAM,QAAQ,SAA6B,EAAE,MAAM,MAAM,SAAS,MAAM,OAAO,KAAK,CAAC;AACrF,QAAM,OAAO,MAAM,WAAc,cAAc;AAE/C,iBAAe,UAAyB;AACtC,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,QAAQ,QAAQ,KAAK,MAAM,CAAwB,CAAC;AACjF,YAAM,IAAI,EAAE,MAAM,QAAQ,SAAS,OAAO,OAAO,KAAK,CAAC;AAAA,IACzD,SAAS,KAAK;AACZ,YAAM,IAAI,EAAE,MAAM,MAAM,SAAS,OAAO,OAAO,IAAa,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,OAAK,QAAQ;AACb,QAAM,cAAc,KAAK,UAAU,MAAM;AAAE,SAAK,QAAQ;AAAA,EAAE,CAAC;AAE3D,SAAO;AAAA,IACL,WAAW,CAAC,QAAQ,MAAM,UAAU,GAAG;AAAA,IACvC;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAaO,SAAS,UAAU,IAAwD;AAChF,QAAM,QAAQ,SAAyB,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAEvE,QAAM,UAAU,CAAC,UAA6B;AAC5C,UAAM,IAAI,EAAE,WAAW,OAAO,OAAO,KAAK,CAAC;AAAA,EAC7C;AACA,KAAG,GAAG,UAAU,OAAO;AAEvB,SAAO;AAAA,IACL,WAAW,CAAC,QAAQ,MAAM,UAAU,GAAG;AAAA,IACvC,MAAM,MAAM,GAAG,IAAI,UAAU,OAAO;AAAA,EACtC;AACF;","names":[]}
|
package/dist/index.d.cts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { ChangeEvent, Vault, Query, Noydb } from '@noy-db/hub';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* **@noy-db/in-svelte** — Svelte stores for noy-db.
|
|
5
|
-
*
|
|
6
|
-
* Three store factories that conform to Svelte's standard store
|
|
7
|
-
* contract (`subscribe(fn) → unsubscribe`). Works with:
|
|
8
|
-
*
|
|
9
|
-
* - Svelte 4 components via the `$store` auto-subscription syntax
|
|
10
|
-
* - Svelte 5 runes via `$state(await fromStore(s).current)` or a
|
|
11
|
-
* small `fromStore()` shim
|
|
12
|
-
* - Any framework that consumes the Svelte store contract
|
|
13
|
-
* (e.g. `@gradio/client`, non-Svelte integrations)
|
|
14
|
-
*
|
|
15
|
-
* ## Factories
|
|
16
|
-
*
|
|
17
|
-
* - {@link collectionStore} — reactive list of records.
|
|
18
|
-
* - {@link queryStore} — reactive result of a query builder.
|
|
19
|
-
* - {@link syncStore} — reactive Noydb-level change feed.
|
|
20
|
-
*
|
|
21
|
-
* ## Zero dependencies
|
|
22
|
-
*
|
|
23
|
-
* Svelte's store contract is ~10 lines of TypeScript. We re-implement
|
|
24
|
-
* it inline rather than take a `svelte` peer-dep — the contract is
|
|
25
|
-
* stable across Svelte 4/5 and the extra dependency is unnecessary
|
|
26
|
-
* for store-only consumers (e.g. SvelteKit load functions).
|
|
27
|
-
*
|
|
28
|
-
* @packageDocumentation
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
type Subscriber<T> = (value: T) => void;
|
|
32
|
-
type Unsubscriber = () => void;
|
|
33
|
-
interface Readable<T> {
|
|
34
|
-
subscribe(run: Subscriber<T>): Unsubscriber;
|
|
35
|
-
}
|
|
36
|
-
interface CollectionStoreState<T> {
|
|
37
|
-
readonly records: readonly T[];
|
|
38
|
-
readonly loading: boolean;
|
|
39
|
-
readonly error: Error | null;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Reactive collection records. Re-emits on every change event from
|
|
43
|
-
* the collection (put / delete / sync).
|
|
44
|
-
*
|
|
45
|
-
* ```svelte
|
|
46
|
-
* <script>
|
|
47
|
-
* import { collectionStore } from '@noy-db/in-svelte'
|
|
48
|
-
* const invoices = collectionStore(vault, 'invoices')
|
|
49
|
-
* </script>
|
|
50
|
-
*
|
|
51
|
-
* {#each $invoices.records as invoice}
|
|
52
|
-
* {invoice.id}
|
|
53
|
-
* {/each}
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
declare function collectionStore<T>(vault: Vault, collectionName: string): Readable<CollectionStoreState<T>> & {
|
|
57
|
-
refresh(): Promise<void>;
|
|
58
|
-
stop(): void;
|
|
59
|
-
};
|
|
60
|
-
interface QueryStoreState<R> {
|
|
61
|
-
readonly data: R | null;
|
|
62
|
-
readonly loading: boolean;
|
|
63
|
-
readonly error: Error | null;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Reactive result of a query builder. The builder is re-run on every
|
|
67
|
-
* change event — useful for aggregates, joins, and filtered lists.
|
|
68
|
-
*
|
|
69
|
-
* ```svelte
|
|
70
|
-
* <script>
|
|
71
|
-
* import { queryStore } from '@noy-db/in-svelte'
|
|
72
|
-
* const paid = queryStore(vault, 'invoices', q => q.where('status', '==', 'paid').toArray())
|
|
73
|
-
* </script>
|
|
74
|
-
*
|
|
75
|
-
* {#if $paid.loading} Loading… {:else} {$paid.data?.length} paid {/if}
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
declare function queryStore<T, R>(vault: Vault, collectionName: string, builder: (q: Query<T>) => Promise<R> | R): Readable<QueryStoreState<R>> & {
|
|
79
|
-
refresh(): Promise<void>;
|
|
80
|
-
stop(): void;
|
|
81
|
-
};
|
|
82
|
-
interface SyncStoreState {
|
|
83
|
-
readonly lastEvent: ChangeEvent | null;
|
|
84
|
-
readonly error: Error | null;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Reactive Noydb-level change feed. Useful for top-level status
|
|
88
|
-
* indicators (last-update-time, "unsynced changes", offline banners).
|
|
89
|
-
*/
|
|
90
|
-
declare function syncStore(db: Noydb): Readable<SyncStoreState> & {
|
|
91
|
-
stop(): void;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export { type CollectionStoreState, type QueryStoreState, type Readable, type SyncStoreState, collectionStore, queryStore, syncStore };
|