@noy-db/in-vue 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noy-db/in-vue",
3
- "version": "0.2.0-pre.9",
3
+ "version": "0.3.0-pre.2",
4
4
  "description": "Vue 3 / Nuxt composables for noy-db — reactive useNoydb, useCollection, useSync, and biometric plugin",
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
- "import": {
21
- "types": "./dist/index.d.ts",
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": ">=18.0.0"
32
+ "node": ">=22.0.0"
40
33
  },
41
34
  "peerDependencies": {
42
35
  "vue": "^3.0.0",
43
- "@noy-db/hub": "0.2.0-pre.9"
36
+ "@noy-db/hub": "0.3.0-pre.2"
44
37
  },
45
38
  "devDependencies": {
46
39
  "vue": "^3.5.32",
47
- "@noy-db/hub": "0.2.0-pre.9"
40
+ "@noy-db/hub": "0.3.0-pre.2"
48
41
  },
49
42
  "keywords": [
50
43
  "noy-db",
package/dist/index.cjs DELETED
@@ -1,228 +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
- NoydbKey: () => NoydbKey,
24
- NoydbPlugin: () => NoydbPlugin,
25
- useBlobURL: () => useBlobURL,
26
- useCollection: () => useCollection,
27
- useMigrationState: () => useMigrationState,
28
- useNoydb: () => useNoydb,
29
- useSync: () => useSync
30
- });
31
- module.exports = __toCommonJS(index_exports);
32
-
33
- // src/plugin.ts
34
- var NoydbKey = /* @__PURE__ */ Symbol("noydb");
35
- var NoydbPlugin = {
36
- install(app, options) {
37
- app.provide(NoydbKey, options.instance);
38
- }
39
- };
40
-
41
- // src/useNoydb.ts
42
- var import_vue = require("vue");
43
- function useNoydb() {
44
- const db = (0, import_vue.inject)(NoydbKey);
45
- if (!db) {
46
- throw new Error(
47
- "NOYDB instance not found. Did you install the NoydbPlugin?\nExample: app.use(NoydbPlugin, { instance: db })"
48
- );
49
- }
50
- return db;
51
- }
52
-
53
- // src/useCollection.ts
54
- var import_vue2 = require("vue");
55
- function useCollection(db, compartmentName, collectionName) {
56
- const data = (0, import_vue2.ref)([]);
57
- const loading = (0, import_vue2.ref)(true);
58
- const error = (0, import_vue2.ref)(null);
59
- let compartmentPromise = null;
60
- async function refresh() {
61
- try {
62
- if (!compartmentPromise) {
63
- compartmentPromise = db.openVault(compartmentName);
64
- }
65
- const comp = await compartmentPromise;
66
- const coll = comp.collection(collectionName);
67
- data.value = await coll.list();
68
- error.value = null;
69
- } catch (err) {
70
- error.value = err instanceof Error ? err : new Error(String(err));
71
- } finally {
72
- loading.value = false;
73
- }
74
- }
75
- const handler = (event) => {
76
- if (event.collection === collectionName) {
77
- void refresh();
78
- }
79
- };
80
- db.on("change", handler);
81
- (0, import_vue2.onUnmounted)(() => {
82
- db.off("change", handler);
83
- });
84
- void refresh();
85
- return { data, loading, error, refresh };
86
- }
87
-
88
- // src/useSync.ts
89
- var import_vue3 = require("vue");
90
- function useSync(db, compartmentName) {
91
- const status = (0, import_vue3.ref)({
92
- dirty: 0,
93
- lastPush: null,
94
- lastPull: null,
95
- online: true
96
- });
97
- const syncing = (0, import_vue3.ref)(false);
98
- function refreshStatus() {
99
- status.value = db.syncStatus(compartmentName);
100
- }
101
- const onPush = () => refreshStatus();
102
- const onPull = () => refreshStatus();
103
- db.on("sync:push", onPush);
104
- db.on("sync:pull", onPull);
105
- (0, import_vue3.onUnmounted)(() => {
106
- db.off("sync:push", onPush);
107
- db.off("sync:pull", onPull);
108
- });
109
- async function push() {
110
- syncing.value = true;
111
- try {
112
- const result = await db.push(compartmentName);
113
- refreshStatus();
114
- return result;
115
- } finally {
116
- syncing.value = false;
117
- }
118
- }
119
- async function pull() {
120
- syncing.value = true;
121
- try {
122
- const result = await db.pull(compartmentName);
123
- refreshStatus();
124
- return result;
125
- } finally {
126
- syncing.value = false;
127
- }
128
- }
129
- async function sync() {
130
- syncing.value = true;
131
- try {
132
- await db.sync(compartmentName);
133
- refreshStatus();
134
- } finally {
135
- syncing.value = false;
136
- }
137
- }
138
- refreshStatus();
139
- return { status, syncing, push, pull, sync };
140
- }
141
-
142
- // src/useBlobURL.ts
143
- var import_vue4 = require("vue");
144
- function useBlobURL(collection, idGetter, options = {}) {
145
- const url = (0, import_vue4.ref)(null);
146
- const slot = options.slot ?? "default";
147
- const browserAware = typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
148
- let revokeCurrent = null;
149
- let stopped = false;
150
- let loadToken = 0;
151
- const revoke = () => {
152
- if (revokeCurrent) {
153
- revokeCurrent();
154
- revokeCurrent = null;
155
- }
156
- };
157
- async function load(id) {
158
- revoke();
159
- url.value = null;
160
- if (!browserAware || stopped || !id) return;
161
- const myToken = ++loadToken;
162
- const mimeType = typeof options.mimeType === "function" ? options.mimeType() : options.mimeType;
163
- const built = await collection.blob(id).objectURL(slot, mimeType !== void 0 ? { mimeType } : {});
164
- if (myToken !== loadToken || stopped) {
165
- built?.revoke();
166
- return;
167
- }
168
- if (!built) return;
169
- revokeCurrent = built.revoke;
170
- url.value = built.url;
171
- }
172
- (0, import_vue4.watch)(idGetter, (next) => {
173
- void load(next);
174
- }, { immediate: true });
175
- if ((0, import_vue4.getCurrentScope)()) {
176
- (0, import_vue4.onScopeDispose)(() => {
177
- stopped = true;
178
- revoke();
179
- url.value = null;
180
- });
181
- }
182
- return url;
183
- }
184
-
185
- // src/useMigrationState.ts
186
- var import_vue5 = require("vue");
187
- function useMigrationState(dbOrVault, maybeVault) {
188
- const db = typeof dbOrVault === "object" ? dbOrVault : useNoydb();
189
- const vaultName = typeof dbOrVault === "string" ? dbOrVault : maybeVault;
190
- const fenceState = (0, import_vue5.ref)("normal");
191
- const schemaVersion = (0, import_vue5.ref)(0);
192
- if (vaultName !== void 0) {
193
- try {
194
- void db.vault(vaultName).schemaFenceState().then(
195
- (s) => {
196
- fenceState.value = s.fenceState;
197
- schemaVersion.value = s.currentSchemaVersion;
198
- },
199
- () => {
200
- }
201
- );
202
- } catch {
203
- }
204
- }
205
- const handler = (e) => {
206
- if (vaultName !== void 0 && e.vault !== vaultName) return;
207
- fenceState.value = e.fenceState;
208
- schemaVersion.value = e.currentSchemaVersion;
209
- };
210
- db.on("schema:fence-changed", handler);
211
- if ((0, import_vue5.getCurrentScope)()) {
212
- (0, import_vue5.onScopeDispose)(() => {
213
- db.off("schema:fence-changed", handler);
214
- });
215
- }
216
- return { fenceState, schemaVersion };
217
- }
218
- // Annotate the CommonJS export names for ESM import in node:
219
- 0 && (module.exports = {
220
- NoydbKey,
221
- NoydbPlugin,
222
- useBlobURL,
223
- useCollection,
224
- useMigrationState,
225
- useNoydb,
226
- useSync
227
- });
228
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/useNoydb.ts","../src/useCollection.ts","../src/useSync.ts","../src/useBlobURL.ts","../src/useMigrationState.ts"],"sourcesContent":["export { NoydbPlugin, NoydbKey } from './plugin.js'\nexport type { NoydbPluginOptions } from './plugin.js'\n\nexport { useNoydb } from './useNoydb.js'\nexport { useCollection } from './useCollection.js'\nexport type { UseCollectionReturn } from './useCollection.js'\nexport { useSync } from './useSync.js'\nexport type { UseSyncReturn } from './useSync.js'\nexport { useBlobURL } from './useBlobURL.js'\nexport type { UseBlobURLOptions } from './useBlobURL.js'\nexport { useMigrationState } from './useMigrationState.js'\nexport type { UseMigrationStateReturn } from './useMigrationState.js'\n","import type { App, InjectionKey } from 'vue'\nimport type { Noydb } from '@noy-db/hub'\n\n/**\n * Vue injection key for the NOYDB instance provided by `NoydbPlugin`.\n * Use with `inject(NoydbKey)` inside any component under the plugin's scope.\n */\nexport const NoydbKey: InjectionKey<Noydb> = Symbol('noydb')\n\n/**\n * Options passed to `app.use(NoydbPlugin, options)` when registering\n * the NOYDB Vue plugin.\n */\nexport interface NoydbPluginOptions {\n /** The NOYDB instance to provide to all components. */\n instance: Noydb\n}\n\n/** Vue plugin that provides a NOYDB instance to all components. */\nexport const NoydbPlugin = {\n install(app: App, options: NoydbPluginOptions): void {\n app.provide(NoydbKey, options.instance)\n },\n}\n","import { inject } from 'vue'\nimport type { Noydb } from '@noy-db/hub'\nimport { NoydbKey } from './plugin.js'\n\n/** Composable to access the injected NOYDB instance. */\nexport function useNoydb(): Noydb {\n const db = inject(NoydbKey)\n if (!db) {\n throw new Error(\n 'NOYDB instance not found. Did you install the NoydbPlugin?\\n' +\n 'Example: app.use(NoydbPlugin, { instance: db })',\n )\n }\n return db\n}\n","import { ref, onUnmounted, type Ref } from 'vue'\nimport type { Noydb, ChangeEvent } from '@noy-db/hub'\n\n/**\n * Return value of `useCollection<T>()`.\n *\n * All `Ref` values are reactive — bind them directly to Vue templates.\n * The collection subscribes to NOYDB change events and auto-refreshes\n * `data` when the underlying collection is mutated by any code path.\n */\nexport interface UseCollectionReturn<T> {\n /** Reactive list of all records in the collection. */\n data: Ref<T[]>\n /** Loading state — true during initial hydration. */\n loading: Ref<boolean>\n /** Error state — set if hydration or refresh fails. */\n error: Ref<Error | null>\n /** Manually refresh data from the adapter. */\n refresh: () => Promise<void>\n}\n\n/**\n * Composable for reactive collection data.\n * Auto-refreshes when the collection changes (via NOYDB change events).\n */\nexport function useCollection<T>(\n db: Noydb,\n compartmentName: string,\n collectionName: string,\n): UseCollectionReturn<T> {\n const data = ref<T[]>([]) as Ref<T[]>\n const loading = ref(true)\n const error = ref<Error | null>(null)\n\n let compartmentPromise: ReturnType<Noydb['openVault']> | null = null\n\n async function refresh(): Promise<void> {\n try {\n if (!compartmentPromise) {\n compartmentPromise = db.openVault(compartmentName)\n }\n const comp = await compartmentPromise\n const coll = comp.collection<T>(collectionName)\n data.value = await coll.list()\n error.value = null\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err))\n } finally {\n loading.value = false\n }\n }\n\n // Listen for changes to auto-refresh\n const handler = (event: ChangeEvent) => {\n if (event.collection === collectionName) {\n void refresh()\n }\n }\n db.on('change', handler)\n\n onUnmounted(() => {\n db.off('change', handler)\n })\n\n // Initial load\n void refresh()\n\n return { data, loading, error, refresh }\n}\n","import { ref, onUnmounted, type Ref } from 'vue'\nimport type { Noydb, SyncStatus, PushResult, PullResult } from '@noy-db/hub'\n\n/**\n * Return value of `useSync()`.\n *\n * Wraps the NOYDB sync engine in reactive Vue refs. `status` updates\n * automatically as sync operations progress, so binding it to a\n * status indicator (e.g. a toolbar sync icon) requires no manual polling.\n */\nexport interface UseSyncReturn {\n /** Reactive sync status. */\n status: Ref<SyncStatus>\n /** Whether a sync operation is in progress. */\n syncing: Ref<boolean>\n /** Push local changes to remote. */\n push: () => Promise<PushResult>\n /** Pull remote changes to local. */\n pull: () => Promise<PullResult>\n /** Bidirectional sync (pull then push). */\n sync: () => Promise<void>\n}\n\n/**\n * Composable for reactive sync status and controls.\n */\nexport function useSync(db: Noydb, compartmentName: string): UseSyncReturn {\n const status = ref<SyncStatus>({\n dirty: 0,\n lastPush: null,\n lastPull: null,\n online: true,\n }) as Ref<SyncStatus>\n const syncing = ref(false)\n\n function refreshStatus(): void {\n status.value = db.syncStatus(compartmentName)\n }\n\n // Listen for sync events to auto-refresh status\n const onPush = () => refreshStatus()\n const onPull = () => refreshStatus()\n db.on('sync:push', onPush)\n db.on('sync:pull', onPull)\n\n onUnmounted(() => {\n db.off('sync:push', onPush)\n db.off('sync:pull', onPull)\n })\n\n async function push(): Promise<PushResult> {\n syncing.value = true\n try {\n const result = await db.push(compartmentName)\n refreshStatus()\n return result\n } finally {\n syncing.value = false\n }\n }\n\n async function pull(): Promise<PullResult> {\n syncing.value = true\n try {\n const result = await db.pull(compartmentName)\n refreshStatus()\n return result\n } finally {\n syncing.value = false\n }\n }\n\n async function sync(): Promise<void> {\n syncing.value = true\n try {\n await db.sync(compartmentName)\n refreshStatus()\n } finally {\n syncing.value = false\n }\n }\n\n // Initial status\n refreshStatus()\n\n return { status, syncing, push, pull, sync }\n}\n","/**\n * `useBlobURL` — Vue composable that decrypts an encrypted blob slot\n * and surfaces a browser ObjectURL ready to feed into `<img src>`,\n * `<a href>`, etc. Auto-revokes the prior URL when the reactive id\n * changes and on scope dispose, so long-lived pages (attachment\n * viewers, image grids) cannot leak ObjectURLs.\n *\n * SSR-safe: when `URL.createObjectURL` is unavailable (Node without\n * DOM, restricted workers), the ref stays at `null` instead of\n * throwing.\n *\n * @module\n */\n\nimport {\n ref,\n watch,\n getCurrentScope,\n onScopeDispose,\n type Ref,\n} from 'vue'\nimport type { Collection } from '@noy-db/hub'\n\n/** Options accepted by {@link useBlobURL}. */\nexport interface UseBlobURLOptions {\n /**\n * Slot name within the record's blob set. Defaults to `'default'`.\n * Pass an explicit name when records carry multiple attachments.\n */\n readonly slot?: string\n /**\n * MIME type override. Either a static string or a function called\n * each time a fresh URL is built. When omitted, the slot's stored\n * `mimeType` (set at upload time) is used.\n */\n readonly mimeType?: string | (() => string | undefined)\n}\n\n/**\n * Build a reactive ObjectURL for a blob slot on a record. The URL is\n * recomputed whenever the id getter's return value changes; the prior\n * URL is revoked **before** the new one is created, so consumers\n * never see two live URLs for the same composable instance.\n *\n * @example\n * ```ts\n * const recordId = ref('inv-001')\n * const url = useBlobURL(invoiceCollection, () => recordId.value, {\n * slot: 'pdf',\n * mimeType: 'application/pdf',\n * })\n * ```\n *\n * @param collection - Hub collection that owns the record.\n * @param idGetter - Function returning the current record id (or\n * `null` / `undefined` to clear the URL).\n * @param options - Optional slot name and mimeType override.\n * @returns A `Ref<string | null>` — `null` while loading, after a\n * stop, or when no slot is found.\n */\nexport function useBlobURL<T>(\n collection: Collection<T>,\n idGetter: () => string | null | undefined,\n options: UseBlobURLOptions = {},\n): Ref<string | null> {\n const url = ref<string | null>(null)\n const slot = options.slot ?? 'default'\n\n // SSR / non-DOM hosts: bail out, leave url at null. The hub layer\n // would throw here, but the composable's contract is \"stay quiet so\n // server-rendered output is empty.\"\n const browserAware =\n typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function'\n\n let revokeCurrent: (() => void) | null = null\n let stopped = false\n let loadToken = 0\n\n const revoke = (): void => {\n if (revokeCurrent) {\n revokeCurrent()\n revokeCurrent = null\n }\n }\n\n async function load(id: string | null | undefined): Promise<void> {\n // Revoke FIRST — the spec is explicit that the prior URL is\n // released before the next one is created, even if the next\n // create fails or the id resolves to null.\n revoke()\n url.value = null\n if (!browserAware || stopped || !id) return\n\n // Token-guard against stale resolutions: if the id changes again\n // before this call's awaits settle, the older promise's result\n // must be discarded so we don't strand an URL that no upstream\n // ref points at.\n const myToken = ++loadToken\n const mimeType =\n typeof options.mimeType === 'function'\n ? options.mimeType()\n : options.mimeType\n const built = await collection\n .blob(id)\n .objectURL(slot, mimeType !== undefined ? { mimeType } : {})\n if (myToken !== loadToken || stopped) {\n // A newer load won the race or the scope was disposed mid-flight.\n // Drop this URL on the floor.\n built?.revoke()\n return\n }\n if (!built) return\n revokeCurrent = built.revoke\n url.value = built.url\n }\n\n // watch with `immediate: true` covers the initial load — no separate\n // `load(idGetter())` call needed, and watch automatically tracks\n // reactive deps inside the getter.\n watch(idGetter, (next) => {\n void load(next)\n }, { immediate: true })\n\n if (getCurrentScope()) {\n onScopeDispose(() => {\n stopped = true\n revoke()\n url.value = null\n })\n }\n\n return url\n}\n","import { ref, getCurrentScope, onScopeDispose, type Ref } from 'vue'\nimport type { Noydb, FenceState } from '@noy-db/hub'\nimport { useNoydb } from './useNoydb.js'\n\nexport interface UseMigrationStateReturn {\n /** Live cutover fence state for the watched vault. */\n readonly fenceState: Ref<FenceState>\n /** Live schema generation counter for the watched vault. */\n readonly schemaVersion: Ref<number>\n}\n\n/**\n * Reactive schema-cutover state. Seeds from the current fence on\n * mount, then updates on every `schema:fence-changed` event for `vaultName`\n * (or any vault when omitted). Pass `db` explicitly, or rely on the injected\n * instance (`NoydbPlugin`).\n */\nexport function useMigrationState(vaultName?: string): UseMigrationStateReturn\nexport function useMigrationState(db: Noydb, vaultName?: string): UseMigrationStateReturn\nexport function useMigrationState(\n dbOrVault?: Noydb | string,\n maybeVault?: string,\n): UseMigrationStateReturn {\n const db: Noydb = typeof dbOrVault === 'object' ? dbOrVault : useNoydb()\n const vaultName: string | undefined = typeof dbOrVault === 'string' ? dbOrVault : maybeVault\n\n const fenceState = ref<FenceState>('normal')\n const schemaVersion = ref(0)\n\n // Seed from the live fence (the event fires on change, not on mount).\n if (vaultName !== undefined) {\n try {\n void db.vault(vaultName).schemaFenceState().then(\n (s) => { fenceState.value = s.fenceState; schemaVersion.value = s.currentSchemaVersion },\n () => { /* no fence yet → keep defaults */ },\n )\n } catch {\n /* db.vault() throws if the vault isn't open yet → keep defaults; events catch up */\n }\n }\n\n const handler = (e: { vault: string; currentSchemaVersion: number; fenceState: FenceState }) => {\n if (vaultName !== undefined && e.vault !== vaultName) return\n fenceState.value = e.fenceState\n schemaVersion.value = e.currentSchemaVersion\n }\n db.on('schema:fence-changed', handler)\n\n if (getCurrentScope()) {\n onScopeDispose(() => { db.off('schema:fence-changed', handler) })\n }\n\n return { fenceState, schemaVersion }\n}\n"],"mappings":"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","names":["import_vue","import_vue","import_vue","import_vue"]}
package/dist/index.d.cts DELETED
@@ -1,139 +0,0 @@
1
- import { InjectionKey, App, Ref } from 'vue';
2
- import { Noydb, SyncStatus, PushResult, PullResult, Collection, FenceState } from '@noy-db/hub';
3
-
4
- /**
5
- * Vue injection key for the NOYDB instance provided by `NoydbPlugin`.
6
- * Use with `inject(NoydbKey)` inside any component under the plugin's scope.
7
- */
8
- declare const NoydbKey: InjectionKey<Noydb>;
9
- /**
10
- * Options passed to `app.use(NoydbPlugin, options)` when registering
11
- * the NOYDB Vue plugin.
12
- */
13
- interface NoydbPluginOptions {
14
- /** The NOYDB instance to provide to all components. */
15
- instance: Noydb;
16
- }
17
- /** Vue plugin that provides a NOYDB instance to all components. */
18
- declare const NoydbPlugin: {
19
- install(app: App, options: NoydbPluginOptions): void;
20
- };
21
-
22
- /** Composable to access the injected NOYDB instance. */
23
- declare function useNoydb(): Noydb;
24
-
25
- /**
26
- * Return value of `useCollection<T>()`.
27
- *
28
- * All `Ref` values are reactive — bind them directly to Vue templates.
29
- * The collection subscribes to NOYDB change events and auto-refreshes
30
- * `data` when the underlying collection is mutated by any code path.
31
- */
32
- interface UseCollectionReturn<T> {
33
- /** Reactive list of all records in the collection. */
34
- data: Ref<T[]>;
35
- /** Loading state — true during initial hydration. */
36
- loading: Ref<boolean>;
37
- /** Error state — set if hydration or refresh fails. */
38
- error: Ref<Error | null>;
39
- /** Manually refresh data from the adapter. */
40
- refresh: () => Promise<void>;
41
- }
42
- /**
43
- * Composable for reactive collection data.
44
- * Auto-refreshes when the collection changes (via NOYDB change events).
45
- */
46
- declare function useCollection<T>(db: Noydb, compartmentName: string, collectionName: string): UseCollectionReturn<T>;
47
-
48
- /**
49
- * Return value of `useSync()`.
50
- *
51
- * Wraps the NOYDB sync engine in reactive Vue refs. `status` updates
52
- * automatically as sync operations progress, so binding it to a
53
- * status indicator (e.g. a toolbar sync icon) requires no manual polling.
54
- */
55
- interface UseSyncReturn {
56
- /** Reactive sync status. */
57
- status: Ref<SyncStatus>;
58
- /** Whether a sync operation is in progress. */
59
- syncing: Ref<boolean>;
60
- /** Push local changes to remote. */
61
- push: () => Promise<PushResult>;
62
- /** Pull remote changes to local. */
63
- pull: () => Promise<PullResult>;
64
- /** Bidirectional sync (pull then push). */
65
- sync: () => Promise<void>;
66
- }
67
- /**
68
- * Composable for reactive sync status and controls.
69
- */
70
- declare function useSync(db: Noydb, compartmentName: string): UseSyncReturn;
71
-
72
- /**
73
- * `useBlobURL` — Vue composable that decrypts an encrypted blob slot
74
- * and surfaces a browser ObjectURL ready to feed into `<img src>`,
75
- * `<a href>`, etc. Auto-revokes the prior URL when the reactive id
76
- * changes and on scope dispose, so long-lived pages (attachment
77
- * viewers, image grids) cannot leak ObjectURLs.
78
- *
79
- * SSR-safe: when `URL.createObjectURL` is unavailable (Node without
80
- * DOM, restricted workers), the ref stays at `null` instead of
81
- * throwing.
82
- *
83
- * @module
84
- */
85
-
86
- /** Options accepted by {@link useBlobURL}. */
87
- interface UseBlobURLOptions {
88
- /**
89
- * Slot name within the record's blob set. Defaults to `'default'`.
90
- * Pass an explicit name when records carry multiple attachments.
91
- */
92
- readonly slot?: string;
93
- /**
94
- * MIME type override. Either a static string or a function called
95
- * each time a fresh URL is built. When omitted, the slot's stored
96
- * `mimeType` (set at upload time) is used.
97
- */
98
- readonly mimeType?: string | (() => string | undefined);
99
- }
100
- /**
101
- * Build a reactive ObjectURL for a blob slot on a record. The URL is
102
- * recomputed whenever the id getter's return value changes; the prior
103
- * URL is revoked **before** the new one is created, so consumers
104
- * never see two live URLs for the same composable instance.
105
- *
106
- * @example
107
- * ```ts
108
- * const recordId = ref('inv-001')
109
- * const url = useBlobURL(invoiceCollection, () => recordId.value, {
110
- * slot: 'pdf',
111
- * mimeType: 'application/pdf',
112
- * })
113
- * ```
114
- *
115
- * @param collection - Hub collection that owns the record.
116
- * @param idGetter - Function returning the current record id (or
117
- * `null` / `undefined` to clear the URL).
118
- * @param options - Optional slot name and mimeType override.
119
- * @returns A `Ref<string | null>` — `null` while loading, after a
120
- * stop, or when no slot is found.
121
- */
122
- declare function useBlobURL<T>(collection: Collection<T>, idGetter: () => string | null | undefined, options?: UseBlobURLOptions): Ref<string | null>;
123
-
124
- interface UseMigrationStateReturn {
125
- /** Live cutover fence state for the watched vault. */
126
- readonly fenceState: Ref<FenceState>;
127
- /** Live schema generation counter for the watched vault. */
128
- readonly schemaVersion: Ref<number>;
129
- }
130
- /**
131
- * Reactive schema-cutover state. Seeds from the current fence on
132
- * mount, then updates on every `schema:fence-changed` event for `vaultName`
133
- * (or any vault when omitted). Pass `db` explicitly, or rely on the injected
134
- * instance (`NoydbPlugin`).
135
- */
136
- declare function useMigrationState(vaultName?: string): UseMigrationStateReturn;
137
- declare function useMigrationState(db: Noydb, vaultName?: string): UseMigrationStateReturn;
138
-
139
- export { NoydbKey, NoydbPlugin, type NoydbPluginOptions, type UseBlobURLOptions, type UseCollectionReturn, type UseMigrationStateReturn, type UseSyncReturn, useBlobURL, useCollection, useMigrationState, useNoydb, useSync };