@korajs/vue 1.0.0-beta.12 → 1.0.0-beta.14

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 CHANGED
@@ -1,17 +1,18 @@
1
1
  # @korajs/vue
2
2
 
3
- Vue 3 composables for [Kora.js](https://github.com/ehoneahobed/kora) offline-first applications.
3
+ Vue 3 composables for [Kora.js](https://korajs.dev) offline-first applications.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- pnpm add korajs @korajs/vue
8
+ pnpm add korajs@beta @korajs/vue@beta
9
9
  ```
10
10
 
11
11
  ## Setup
12
12
 
13
13
  Create the Kora app once at module scope, connect sync after `ready`, then wrap your tree with providers (matches the CLI `vue-tailwind-sync` template):
14
14
 
15
+ <!-- docs-check: skip template excerpt: imports the project's own auth and schema modules -->
15
16
  ```typescript
16
17
  import { createKoraAuthSync } from '@korajs/auth'
17
18
  import { AuthProvider } from '@korajs/auth/vue'
@@ -25,7 +26,7 @@ import koraWorkerUrl from './kora-worker.ts?worker&url'
25
26
 
26
27
  const kora = createKoraApp({
27
28
  schema,
28
- sync: { url: 'ws://localhost:3000/kora-sync', authClient: createKoraAuthSync({ authClient, schema }) },
29
+ sync: { url: 'ws://localhost:3001/kora-sync', authClient: createKoraAuthSync({ authClient, schema }) },
29
30
  store: { workerUrl: koraWorkerUrl },
30
31
  })
31
32
 
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ __export(index_exports, {
32
32
  useMutation: () => useMutation,
33
33
  usePresence: () => usePresence,
34
34
  useQuery: () => useQuery,
35
+ useQueryState: () => useQueryState,
35
36
  useRichText: () => useRichText,
36
37
  useSyncStatus: () => useSyncStatus
37
38
  });
@@ -189,31 +190,66 @@ var KoraProvider = (0, import_vue2.defineComponent)({
189
190
  var import_store2 = require("@korajs/store");
190
191
  var import_vue3 = require("vue");
191
192
  var EMPTY_ARRAY = Object.freeze([]);
192
- function useQuery(query, options) {
193
+ function readQueryError(queryStore) {
194
+ const channel = queryStore;
195
+ return typeof channel.getError === "function" ? channel.getError() : null;
196
+ }
197
+ function useQuerySubscription(query, options) {
193
198
  const { queryStoreCache } = useKoraContext();
194
- const enabled = options?.enabled !== false;
195
- const snapshot = (0, import_vue3.shallowRef)(EMPTY_ARRAY);
199
+ const data = (0, import_vue3.shallowRef)(EMPTY_ARRAY);
200
+ const error = (0, import_vue3.shallowRef)(null);
201
+ const ready = (0, import_vue3.shallowRef)(false);
196
202
  (0, import_vue3.watch)(
197
- () => enabled ? JSON.stringify(query.getDescriptor()) : null,
203
+ () => {
204
+ const enabled = (0, import_vue3.toValue)(options?.enabled) !== false;
205
+ const current = enabled ? (0, import_vue3.toValue)(query) : null;
206
+ return current ? (0, import_store2.queryKey)(current.getDescriptor()) : null;
207
+ },
198
208
  (key, _previous, onCleanup) => {
199
- if (!key) {
200
- snapshot.value = EMPTY_ARRAY;
209
+ const current = key ? (0, import_vue3.toValue)(query) : null;
210
+ if (!current) {
211
+ data.value = EMPTY_ARRAY;
212
+ error.value = null;
213
+ ready.value = false;
201
214
  return;
202
215
  }
203
- (0, import_store2.assertQueryReady)(query);
204
- const queryStore = queryStoreCache.getOrCreate(query);
205
- const unsubscribe = queryStore.subscribe(() => {
206
- snapshot.value = queryStore.getSnapshot();
207
- });
208
- snapshot.value = queryStore.getSnapshot();
216
+ (0, import_store2.assertQueryReady)(current);
217
+ const queryStore = queryStoreCache.getOrCreate(current);
218
+ const sync = () => {
219
+ const failure = readQueryError(queryStore);
220
+ if (failure !== error.value) {
221
+ error.value = failure;
222
+ if (failure) options?.onError?.(failure);
223
+ }
224
+ if (queryStore.hasSnapshot()) {
225
+ data.value = queryStore.getSnapshot();
226
+ ready.value = true;
227
+ }
228
+ };
229
+ const unsubscribe = queryStore.subscribe(sync);
230
+ ready.value = false;
231
+ sync();
209
232
  onCleanup(() => {
210
233
  unsubscribe();
211
- queryStoreCache.release(query);
234
+ queryStoreCache.release(current);
212
235
  });
213
236
  },
214
237
  { immediate: true }
215
238
  );
216
- return (0, import_vue3.readonly)(snapshot);
239
+ return { data, error, ready };
240
+ }
241
+ function useQuery(query, options) {
242
+ const reporting = {
243
+ ...options,
244
+ onError: options?.onError ?? ((failure) => {
245
+ console.error("[Kora] useQuery failed:", failure);
246
+ })
247
+ };
248
+ return (0, import_vue3.readonly)(useQuerySubscription(query, reporting).data);
249
+ }
250
+ function useQueryState(query, options) {
251
+ const { data, error, ready } = useQuerySubscription(query, options);
252
+ return { data: (0, import_vue3.readonly)(data), error: (0, import_vue3.readonly)(error), ready: (0, import_vue3.readonly)(ready) };
217
253
  }
218
254
 
219
255
  // src/composables/use-mutation.ts
@@ -305,7 +341,8 @@ function useRichText(collectionName, recordId, fieldName, options) {
305
341
  error: null,
306
342
  canUndo: false,
307
343
  canRedo: false,
308
- cursors: []
344
+ cursors: [],
345
+ hasUnsavedChanges: false
309
346
  });
310
347
  (0, import_vue6.watch)(
311
348
  () => [collectionName, recordId, fieldName, options?.useDocChannel],
@@ -328,6 +365,7 @@ function useRichText(collectionName, recordId, fieldName, options) {
328
365
  state.canUndo = snapshot.canUndo;
329
366
  state.canRedo = snapshot.canRedo;
330
367
  state.cursors = [...snapshot.cursors];
368
+ state.hasUnsavedChanges = snapshot.hasUnsavedChanges;
331
369
  };
332
370
  syncState();
333
371
  const unsubscribe = controller2.subscribe(syncState);
@@ -379,7 +417,12 @@ function useRichText(collectionName, recordId, fieldName, options) {
379
417
  return state.cursors;
380
418
  },
381
419
  setCursor: (anchor, head) => controller().setCursor(anchor, head),
382
- clearCursor: () => controller().clearCursor()
420
+ clearCursor: () => controller().clearCursor(),
421
+ get hasUnsavedChanges() {
422
+ return state.hasUnsavedChanges;
423
+ },
424
+ retrySave: () => controller().retrySave(),
425
+ getUnsavedState: () => controller().getUnsavedState()
383
426
  };
384
427
  }
385
428
 
@@ -456,6 +499,7 @@ function useKoraApp() {
456
499
  useMutation,
457
500
  usePresence,
458
501
  useQuery,
502
+ useQueryState,
459
503
  useRichText,
460
504
  useSyncStatus
461
505
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/components/kora-provider.ts","../src/resolve-query-store-cache.ts","../src/composables/use-query.ts","../src/composables/use-mutation.ts","../src/composables/use-sync-status.ts","../src/composables/use-app.ts","../src/composables/use-collection.ts","../src/composables/use-rich-text.ts","../src/composables/use-presence.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { type App, inject } from 'vue'\nimport { koraAppInjectionKey } from './context'\nimport type { KoraAppLike } from './types'\n\nexport type { KoraAppHandle, KoraAppLike, KoraContextValue, KoraProviderProps } from './types'\nexport type {\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseQueryOptions,\n\tUseRichTextResult,\n} from './types'\n\nexport { koraAppInjectionKey, koraContextKey, useKoraContext } from './context'\nexport { KoraProvider } from './components/kora-provider'\nexport { useQuery } from './composables/use-query'\nexport { useMutation } from './composables/use-mutation'\nexport { useSyncStatus } from './composables/use-sync-status'\nexport { useApp } from './composables/use-app'\nexport { useCollection } from './composables/use-collection'\nexport { useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { usePresence, useCollaborators } from './composables/use-presence'\n\n/**\n * Register a Kora app on a Vue application instance.\n *\n * @deprecated Prefer {@link KoraProvider} — `installKora` does not provide reactive\n * hook context (`useQuery`, `useSyncStatus`, etc.) until you migrate to `KoraProvider`.\n */\nexport function installKora(vueApp: App, koraApp: KoraAppLike): void {\n\tvueApp.provide(koraAppInjectionKey, koraApp)\n}\n\n/**\n * Access the Kora app from a component when using {@link installKora} only.\n * For reactive hooks, use {@link useApp} inside {@link KoraProvider}.\n */\nexport function useKoraApp(): KoraAppLike {\n\tconst app = inject(koraAppInjectionKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraApp() requires installKora(vueApp, koraApp) or <KoraProvider :app=\"app\">.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Use <KoraProvider :app=\"app\"> and useApp() for full bindings.' },\n\t\t)\n\t}\n\treturn app\n}\n","import { KoraError } from '@korajs/core'\nimport { type InjectionKey, type ShallowRef, inject } from 'vue'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\nexport const koraContextKey: InjectionKey<ShallowRef<KoraContextValue | null>> =\n\tSymbol('korajs-context')\n\n/** @deprecated Use {@link koraContextKey} with {@link KoraProvider}. */\nexport const koraAppInjectionKey: InjectionKey<KoraAppLike> = Symbol('korajs-app')\n\nexport function useKoraContext(): KoraContextValue {\n\tconst contextRef = inject(koraContextKey)\n\tif (!contextRef?.value) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraContext() requires <KoraProvider>. Wrap your app root with KoraProvider.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: '<KoraProvider :app=\"app\"><App /></KoraProvider>' },\n\t\t)\n\t}\n\treturn contextRef.value\n}\n","import { QueryStoreCache } from '@korajs/store'\nimport type { Store } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\ttype PropType,\n\ttype VNode,\n\tdefineComponent,\n\th,\n\tonScopeDispose,\n\tprovide,\n\tref,\n\tshallowRef,\n\twatch,\n} from 'vue'\nimport { koraAppInjectionKey, koraContextKey } from '../context'\nimport { resolveQueryStoreCache } from '../resolve-query-store-cache'\nimport type { KoraAppLike, KoraContextValue } from '../types'\n\nexport const KoraProvider = defineComponent({\n\tname: 'KoraProvider',\n\tprops: {\n\t\tapp: {\n\t\t\ttype: Object as PropType<KoraAppLike>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<Store>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tsyncEngine: {\n\t\t\ttype: Object as PropType<SyncEngine | null>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfallback: {\n\t\t\ttype: [Object, String] as PropType<VNode | string | null>,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\tconst resolvedStore = ref<Store | null>(null)\n\t\tconst resolvedSync = ref<SyncEngine | null>(null)\n\t\tconst ready = ref(!props.app && Boolean(props.store))\n\t\tconst initError = ref<Error | null>(null)\n\t\tconst fallbackQueryStoreCache = new QueryStoreCache()\n\t\tconst contextRef = shallowRef<KoraContextValue | null>(null)\n\n\t\tprovide(koraContextKey, contextRef)\n\t\tif (props.app) {\n\t\t\tprovide(koraAppInjectionKey, props.app)\n\t\t}\n\n\t\twatch(\n\t\t\t() => props.app,\n\t\t\t(app, _previous, onCleanup) => {\n\t\t\t\tif (!app) {\n\t\t\t\t\tif (props.store) {\n\t\t\t\t\t\tresolvedStore.value = props.store as Store\n\t\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tready.value = false\n\t\t\t\tinitError.value = null\n\t\t\t\tlet cancelled = false\n\n\t\t\t\tapp.ready\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tresolvedStore.value = app.getStore() as Store\n\t\t\t\t\t\tresolvedSync.value = app.getSyncEngine() as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\t\t\tinitError.value = err\n\t\t\t\t\t})\n\n\t\t\t\tonCleanup(() => {\n\t\t\t\t\tcancelled = true\n\t\t\t\t})\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => props.store,\n\t\t\t(store) => {\n\t\t\t\tif (store && !props.app) {\n\t\t\t\t\tresolvedStore.value = store as Store\n\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\tready.value = true\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => [resolvedStore.value, resolvedSync.value, props.app] as const,\n\t\t\t([store, syncEngine, app]) => {\n\t\t\t\tif (!store) {\n\t\t\t\t\tcontextRef.value = null\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tcontextRef.value = {\n\t\t\t\t\tstore: store as Store,\n\t\t\t\t\tsyncEngine: (syncEngine ?? null) as SyncEngine | null,\n\t\t\t\t\tapp: app ?? null,\n\t\t\t\t\tevents: app?.events ?? null,\n\t\t\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\t\t\tqueryStoreCache: resolveQueryStoreCache(app, fallbackQueryStoreCache),\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\tonScopeDispose(() => {\n\t\t\tif (!props.app) {\n\t\t\t\tfallbackQueryStoreCache.clear()\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tif (initError.value) {\n\t\t\t\treturn h('div', { style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } }, [\n\t\t\t\t\th('strong', null, 'Kora initialization error: '),\n\t\t\t\t\tinitError.value.message,\n\t\t\t\t])\n\t\t\t}\n\n\t\t\tif (!ready.value) {\n\t\t\t\treturn props.fallback ?? null\n\t\t\t}\n\n\t\t\tif (!resolvedStore.value) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. Pass createApp() or a Store instance.',\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn slots.default?.()\n\t\t}\n\t},\n})\n","import type { QueryStoreCache } from '@korajs/store'\nimport type { KoraAppLike } from './types'\n\n/**\n * Resolves the per-app query cache when available, otherwise a provider-local fallback.\n */\nexport function resolveQueryStoreCache(\n\tapp: KoraAppLike | null | undefined,\n\tfallback: QueryStoreCache,\n): QueryStoreCache {\n\tif (app && typeof app.getQueryStoreCache === 'function') {\n\t\treturn app.getQueryStoreCache()\n\t}\n\treturn fallback\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { type DeepReadonly, type ShallowRef, readonly, shallowRef, watch } from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/**\n * Reactive query composable backed by the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): DeepReadonly<ShallowRef<readonly T[]>> {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst snapshot = shallowRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\twatch(\n\t\t() => (enabled ? JSON.stringify(query.getDescriptor()) : null),\n\t\t(key, _previous, onCleanup) => {\n\t\t\tif (!key) {\n\t\t\t\tsnapshot.value = EMPTY_ARRAY as readonly T[]\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tassertQueryReady(query as QueryBuilder<unknown>)\n\t\t\tconst queryStore = queryStoreCache.getOrCreate(query)\n\t\t\tconst unsubscribe = queryStore.subscribe(() => {\n\t\t\t\tsnapshot.value = queryStore.getSnapshot()\n\t\t\t})\n\t\t\tsnapshot.value = queryStore.getSnapshot()\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tqueryStoreCache.release(query as QueryBuilder<unknown>)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\treturn readonly(snapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onScopeDispose, ref, shallowReadonly } from 'vue'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Mutation composable with optional optimistic update and rollback hooks.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst isLoading = ref(false)\n\tconst error = ref<Error | null>(null)\n\tlet mounted = true\n\n\tonScopeDispose(() => {\n\t\tmounted = false\n\t})\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t\tonStateChange: (state) => {\n\t\t\tif (!mounted) return\n\t\t\tisLoading.value = state.isLoading\n\t\t\terror.value = state.error\n\t\t},\n\t})\n\n\tisLoading.value = controller.getSnapshot().isLoading\n\terror.value = controller.getSnapshot().error\n\n\tonScopeDispose(() => {\n\t\tcontroller.destroy()\n\t})\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: shallowReadonly(isLoading),\n\t\terror: shallowReadonly(error),\n\t\treset: () => controller.reset(),\n\t}\n}\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport { onScopeDispose, readonly, shallowRef, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Reactive sync engine status. Updates only when status payload changes.\n */\nexport function useSyncStatus() {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\tconst status = shallowRef(OFFLINE_SYNC_STATUS)\n\n\twatchEffect((onCleanup) => {\n\t\tconst controller = createSyncStatusController({\n\t\t\tsyncEngine,\n\t\t\tsubscribeSyncStatus,\n\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t})\n\t\tstatus.value = controller.getSnapshot()\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tstatus.value = controller.getSnapshot()\n\t\t})\n\t\tonCleanup(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t})\n\n\treturn readonly(status)\n}\n","import { useKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * Returns the typed Kora app from {@link KoraProvider}'s `app` prop.\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires <KoraProvider :app=\"app\">. Pass your createApp() result to the provider.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useKoraContext } from '../context'\n\n/**\n * Returns a collection accessor for the given schema collection name.\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\treturn store.collection(name)\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { reactive, shallowRef, watch } from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseRichTextResult } from '../types'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst controllerRef = shallowRef<ReturnType<typeof createRichTextController> | null>(null)\n\n\tconst state = reactive({\n\t\tready: false,\n\t\terror: null as Error | null,\n\t\tcanUndo: false,\n\t\tcanRedo: false,\n\t\tcursors: [] as UseRichTextResult['cursors'],\n\t})\n\n\twatch(\n\t\t() => [collectionName, recordId, fieldName, options?.useDocChannel] as const,\n\t\t([name, id, field, useDocChannel], _previous, onCleanup) => {\n\t\t\tcontrollerRef.value?.destroy()\n\n\t\t\tconst controller = createRichTextController({\n\t\t\t\tcollection: store.collection(name),\n\t\t\t\tcollectionName: name,\n\t\t\t\trecordId: id,\n\t\t\t\tfieldName: field,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t})\n\n\t\t\tconst syncState = (): void => {\n\t\t\t\tconst snapshot = controller.getSnapshot()\n\t\t\t\tstate.ready = snapshot.ready\n\t\t\t\tstate.error = snapshot.error\n\t\t\t\tstate.canUndo = snapshot.canUndo\n\t\t\t\tstate.canRedo = snapshot.canRedo\n\t\t\t\tstate.cursors = [...snapshot.cursors]\n\t\t\t}\n\n\t\t\tsyncState()\n\t\t\tconst unsubscribe = controller.subscribe(syncState)\n\t\t\tcontrollerRef.value = controller\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tcontroller.destroy()\n\t\t\t\tif (controllerRef.value === controller) {\n\t\t\t\t\tcontrollerRef.value = null\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\twatch(\n\t\t() => options?.user,\n\t\t(user) => {\n\t\t\tcontrollerRef.value?.setUser(user)\n\t\t},\n\t)\n\n\tconst controller = (): NonNullable<typeof controllerRef.value> => {\n\t\tif (!controllerRef.value) {\n\t\t\tthrow new Error('useRichText controller is not initialized')\n\t\t}\n\t\treturn controllerRef.value\n\t}\n\n\treturn {\n\t\tget doc() {\n\t\t\treturn controller().doc\n\t\t},\n\t\tget text() {\n\t\t\treturn controller().text\n\t\t},\n\t\tundo: () => controller().undo(),\n\t\tredo: () => controller().redo(),\n\t\tget ready() {\n\t\t\treturn state.ready\n\t\t},\n\t\tget error() {\n\t\t\treturn state.error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn state.canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn state.canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn state.cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller().setCursor(anchor, head),\n\t\tclearCursor: () => controller().clearCursor(),\n\t}\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type ShallowRef, onScopeDispose, shallowRef, watch, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Sets the local user's collaborative presence state.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\n\twatch(\n\t\t() => [syncEngine, user?.name, user?.color, user?.avatar] as const,\n\t\t([engine, name, color, avatar], _prev, onCleanup) => {\n\t\t\tif (!engine || !name || !color) return\n\n\t\t\tconst awareness = engine.getAwarenessManager()\n\t\t\tawareness.setLocalState({\n\t\t\t\tuser: {\n\t\t\t\t\tname,\n\t\t\t\t\tcolor,\n\t\t\t\t\tavatar,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tonCleanup(() => {\n\t\t\t\tawareness.setLocalState(null)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n}\n\n/**\n * Reactive list of remote collaborators' awareness states.\n */\nexport function useCollaborators(): ShallowRef<AwarenessState[]> {\n\tconst { syncEngine } = useKoraContext()\n\tconst collaborators = shallowRef<AwarenessState[]>([])\n\n\twatchEffect((onCleanup) => {\n\t\tif (!syncEngine) {\n\t\t\tcollaborators.value = []\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst unsubscribe = subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\tcollaborators.value = states\n\t\t})\n\t\tonCleanup(unsubscribe)\n\t})\n\n\tonScopeDispose(() => {\n\t\tcollaborators.value = []\n\t})\n\n\treturn collaborators\n}\n"],"mappings":"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","names":["import_core","import_vue","import_vue","import_store","import_vue","import_vue","import_vue","import_store","import_vue","controller","import_sync","import_vue"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/components/kora-provider.ts","../src/resolve-query-store-cache.ts","../src/composables/use-query.ts","../src/composables/use-mutation.ts","../src/composables/use-sync-status.ts","../src/composables/use-app.ts","../src/composables/use-collection.ts","../src/composables/use-rich-text.ts","../src/composables/use-presence.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { type App, inject } from 'vue'\nimport { koraAppInjectionKey } from './context'\nimport type { KoraAppLike } from './types'\n\nexport type { KoraAppHandle, KoraAppLike, KoraContextValue, KoraProviderProps } from './types'\nexport type {\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseQueryOptions,\n\tUseQueryStateResult,\n\tUseRichTextResult,\n} from './types'\n\nexport { koraAppInjectionKey, koraContextKey, useKoraContext } from './context'\nexport { KoraProvider } from './components/kora-provider'\nexport { useQuery, useQueryState } from './composables/use-query'\nexport type { QueryInput } from './composables/use-query'\nexport { useMutation } from './composables/use-mutation'\nexport { useSyncStatus } from './composables/use-sync-status'\nexport { useApp } from './composables/use-app'\nexport { useCollection } from './composables/use-collection'\nexport { useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { usePresence, useCollaborators } from './composables/use-presence'\n\n/**\n * Register a Kora app on a Vue application instance.\n *\n * @deprecated Prefer {@link KoraProvider} — `installKora` does not provide reactive\n * hook context (`useQuery`, `useSyncStatus`, etc.) until you migrate to `KoraProvider`.\n */\nexport function installKora(vueApp: App, koraApp: KoraAppLike): void {\n\tvueApp.provide(koraAppInjectionKey, koraApp)\n}\n\n/**\n * Access the Kora app from a component when using {@link installKora} only.\n * For reactive hooks, use {@link useApp} inside {@link KoraProvider}.\n */\nexport function useKoraApp(): KoraAppLike {\n\tconst app = inject(koraAppInjectionKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraApp() requires installKora(vueApp, koraApp) or <KoraProvider :app=\"app\">.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Use <KoraProvider :app=\"app\"> and useApp() for full bindings.' },\n\t\t)\n\t}\n\treturn app\n}\n","import { KoraError } from '@korajs/core'\nimport { type InjectionKey, type ShallowRef, inject } from 'vue'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\nexport const koraContextKey: InjectionKey<ShallowRef<KoraContextValue | null>> =\n\tSymbol('korajs-context')\n\n/** @deprecated Use {@link koraContextKey} with {@link KoraProvider}. */\nexport const koraAppInjectionKey: InjectionKey<KoraAppLike> = Symbol('korajs-app')\n\nexport function useKoraContext(): KoraContextValue {\n\tconst contextRef = inject(koraContextKey)\n\tif (!contextRef?.value) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraContext() requires <KoraProvider>. Wrap your app root with KoraProvider.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: '<KoraProvider :app=\"app\"><App /></KoraProvider>' },\n\t\t)\n\t}\n\treturn contextRef.value\n}\n","import { QueryStoreCache } from '@korajs/store'\nimport type { Store } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\ttype PropType,\n\ttype VNode,\n\tdefineComponent,\n\th,\n\tonScopeDispose,\n\tprovide,\n\tref,\n\tshallowRef,\n\twatch,\n} from 'vue'\nimport { koraAppInjectionKey, koraContextKey } from '../context'\nimport { resolveQueryStoreCache } from '../resolve-query-store-cache'\nimport type { KoraAppLike, KoraContextValue } from '../types'\n\nexport const KoraProvider = defineComponent({\n\tname: 'KoraProvider',\n\tprops: {\n\t\tapp: {\n\t\t\ttype: Object as PropType<KoraAppLike>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<Store>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tsyncEngine: {\n\t\t\ttype: Object as PropType<SyncEngine | null>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfallback: {\n\t\t\ttype: [Object, String] as PropType<VNode | string | null>,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\tconst resolvedStore = ref<Store | null>(null)\n\t\tconst resolvedSync = ref<SyncEngine | null>(null)\n\t\tconst ready = ref(!props.app && Boolean(props.store))\n\t\tconst initError = ref<Error | null>(null)\n\t\tconst fallbackQueryStoreCache = new QueryStoreCache()\n\t\tconst contextRef = shallowRef<KoraContextValue | null>(null)\n\n\t\tprovide(koraContextKey, contextRef)\n\t\tif (props.app) {\n\t\t\tprovide(koraAppInjectionKey, props.app)\n\t\t}\n\n\t\twatch(\n\t\t\t() => props.app,\n\t\t\t(app, _previous, onCleanup) => {\n\t\t\t\tif (!app) {\n\t\t\t\t\tif (props.store) {\n\t\t\t\t\t\tresolvedStore.value = props.store as Store\n\t\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tready.value = false\n\t\t\t\tinitError.value = null\n\t\t\t\tlet cancelled = false\n\n\t\t\t\tapp.ready\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tresolvedStore.value = app.getStore() as Store\n\t\t\t\t\t\tresolvedSync.value = app.getSyncEngine() as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\t\t\tinitError.value = err\n\t\t\t\t\t})\n\n\t\t\t\tonCleanup(() => {\n\t\t\t\t\tcancelled = true\n\t\t\t\t})\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => props.store,\n\t\t\t(store) => {\n\t\t\t\tif (store && !props.app) {\n\t\t\t\t\tresolvedStore.value = store as Store\n\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\tready.value = true\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => [resolvedStore.value, resolvedSync.value, props.app] as const,\n\t\t\t([store, syncEngine, app]) => {\n\t\t\t\tif (!store) {\n\t\t\t\t\tcontextRef.value = null\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tcontextRef.value = {\n\t\t\t\t\tstore: store as Store,\n\t\t\t\t\tsyncEngine: (syncEngine ?? null) as SyncEngine | null,\n\t\t\t\t\tapp: app ?? null,\n\t\t\t\t\tevents: app?.events ?? null,\n\t\t\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\t\t\tqueryStoreCache: resolveQueryStoreCache(app, fallbackQueryStoreCache),\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\tonScopeDispose(() => {\n\t\t\tif (!props.app) {\n\t\t\t\tfallbackQueryStoreCache.clear()\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tif (initError.value) {\n\t\t\t\treturn h('div', { style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } }, [\n\t\t\t\t\th('strong', null, 'Kora initialization error: '),\n\t\t\t\t\tinitError.value.message,\n\t\t\t\t])\n\t\t\t}\n\n\t\t\tif (!ready.value) {\n\t\t\t\treturn props.fallback ?? null\n\t\t\t}\n\n\t\t\tif (!resolvedStore.value) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. Pass createApp() or a Store instance.',\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn slots.default?.()\n\t\t}\n\t},\n})\n","import type { QueryStoreCache } from '@korajs/store'\nimport type { KoraAppLike } from './types'\n\n/**\n * Resolves the per-app query cache when available, otherwise a provider-local fallback.\n */\nexport function resolveQueryStoreCache(\n\tapp: KoraAppLike | null | undefined,\n\tfallback: QueryStoreCache,\n): QueryStoreCache {\n\tif (app && typeof app.getQueryStoreCache === 'function') {\n\t\treturn app.getQueryStoreCache()\n\t}\n\treturn fallback\n}\n","import type { CollectionRecord, QueryBuilder, QueryStore } from '@korajs/store'\nimport { assertQueryReady, queryKey } from '@korajs/store'\nimport {\n\ttype DeepReadonly,\n\ttype MaybeRefOrGetter,\n\ttype ShallowRef,\n\treadonly,\n\tshallowRef,\n\ttoValue,\n\twatch,\n} from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseQueryOptions, UseQueryStateResult } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/** A query input: a builder, a ref to one, or a getter (`() => app.todos.where(...)`). */\nexport type QueryInput<T> = MaybeRefOrGetter<QueryBuilder<T> | null | undefined>\n\n/** The STORE-12 error channel of a QueryStore, read structurally (older store builds lack it). */\nfunction readQueryError(queryStore: QueryStore<unknown>): Error | null {\n\tconst channel = queryStore as unknown as { getError?: () => Error | null }\n\treturn typeof channel.getError === 'function' ? channel.getError() : null\n}\n\n/**\n * Shared engine of {@link useQuery} and {@link useQueryState}: tracks the query and\n * `enabled` reactively (refs, getters, props), subscribes to one ref-counted\n * QueryStore per descriptor, and releases it when the descriptor changes or the\n * scope is disposed (DX-7).\n */\nfunction useQuerySubscription<T>(\n\tquery: QueryInput<T>,\n\toptions: UseQueryOptions | undefined,\n): {\n\tdata: ShallowRef<readonly T[]>\n\terror: ShallowRef<Error | null>\n\tready: ShallowRef<boolean>\n} {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst data = shallowRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\tconst error = shallowRef<Error | null>(null)\n\tconst ready = shallowRef(false)\n\n\twatch(\n\t\t() => {\n\t\t\tconst enabled = toValue(options?.enabled) !== false\n\t\t\tconst current = enabled ? toValue(query) : null\n\t\t\treturn current ? queryKey(current.getDescriptor()) : null\n\t\t},\n\t\t(key, _previous, onCleanup) => {\n\t\t\tconst current = key ? toValue(query) : null\n\t\t\tif (!current) {\n\t\t\t\tdata.value = EMPTY_ARRAY as readonly T[]\n\t\t\t\terror.value = null\n\t\t\t\tready.value = false\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tassertQueryReady(current as QueryBuilder<unknown>)\n\t\t\tconst queryStore = queryStoreCache.getOrCreate(current)\n\t\t\tconst sync = (): void => {\n\t\t\t\tconst failure = readQueryError(queryStore as QueryStore<unknown>)\n\t\t\t\tif (failure !== error.value) {\n\t\t\t\t\terror.value = failure\n\t\t\t\t\tif (failure) options?.onError?.(failure)\n\t\t\t\t}\n\t\t\t\tif (queryStore.hasSnapshot()) {\n\t\t\t\t\tdata.value = queryStore.getSnapshot()\n\t\t\t\t\tready.value = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst unsubscribe = queryStore.subscribe(sync)\n\t\t\t// A descriptor switch keeps the previous rows until the new query answers.\n\t\t\tready.value = false\n\t\t\tsync()\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tqueryStoreCache.release(current as QueryBuilder<unknown>)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\treturn { data, error, ready }\n}\n\n/**\n * Reactive query composable backed by the local Kora store.\n *\n * The query and `enabled` may be plain values, refs or getters: pass a getter to\n * follow props or refs, and the composable re-subscribes when the query's descriptor\n * changes (and releases the old subscription). A failed query is reported through\n * `options.onError`, or `console.error` without one; use {@link useQueryState} to\n * render the error.\n *\n * @param query - A query builder, a ref to one, or a getter returning one (null disables)\n * @param options - `enabled` (value, ref or getter; default true) and `onError`\n * @returns A readonly shallow ref of the current rows\n *\n * @example\n * ```ts\n * const props = defineProps<{ done: boolean }>()\n * const todos = useQuery(() => app.todos.where({ completed: props.done }))\n * ```\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): DeepReadonly<ShallowRef<readonly T[]>> {\n\tconst reporting: UseQueryOptions = {\n\t\t...options,\n\t\tonError:\n\t\t\toptions?.onError ??\n\t\t\t((failure: Error) => {\n\t\t\t\t// Never swallowed: without a handler the failure is at least logged.\n\t\t\t\tconsole.error('[Kora] useQuery failed:', failure)\n\t\t\t}),\n\t}\n\treturn readonly(useQuerySubscription(query, reporting).data)\n}\n\n/**\n * Like {@link useQuery}, but also returns the query's error and whether the first\n * result has arrived.\n *\n * @param query - A query builder, a ref to one, or a getter returning one\n * @param options - `enabled` and `onError`\n * @returns `{ data, error, ready }` as readonly refs\n */\nexport function useQueryState<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): UseQueryStateResult<T> {\n\tconst { data, error, ready } = useQuerySubscription(query, options)\n\treturn { data: readonly(data), error: readonly(error), ready: readonly(ready) }\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onScopeDispose, ref, shallowReadonly } from 'vue'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Mutation composable with optional optimistic update and rollback hooks.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst isLoading = ref(false)\n\tconst error = ref<Error | null>(null)\n\tlet mounted = true\n\n\tonScopeDispose(() => {\n\t\tmounted = false\n\t})\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t\tonStateChange: (state) => {\n\t\t\tif (!mounted) return\n\t\t\tisLoading.value = state.isLoading\n\t\t\terror.value = state.error\n\t\t},\n\t})\n\n\tisLoading.value = controller.getSnapshot().isLoading\n\terror.value = controller.getSnapshot().error\n\n\tonScopeDispose(() => {\n\t\tcontroller.destroy()\n\t})\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: shallowReadonly(isLoading),\n\t\terror: shallowReadonly(error),\n\t\treset: () => controller.reset(),\n\t}\n}\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport { onScopeDispose, readonly, shallowRef, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Reactive sync engine status. Updates only when status payload changes.\n */\nexport function useSyncStatus() {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\tconst status = shallowRef(OFFLINE_SYNC_STATUS)\n\n\twatchEffect((onCleanup) => {\n\t\tconst controller = createSyncStatusController({\n\t\t\tsyncEngine,\n\t\t\tsubscribeSyncStatus,\n\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t})\n\t\tstatus.value = controller.getSnapshot()\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tstatus.value = controller.getSnapshot()\n\t\t})\n\t\tonCleanup(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t})\n\n\treturn readonly(status)\n}\n","import { useKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * Returns the typed Kora app from {@link KoraProvider}'s `app` prop.\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires <KoraProvider :app=\"app\">. Pass your createApp() result to the provider.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useKoraContext } from '../context'\n\n/**\n * Returns a collection accessor for the given schema collection name.\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\treturn store.collection(name)\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { reactive, shallowRef, watch } from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseRichTextResult } from '../types'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst controllerRef = shallowRef<ReturnType<typeof createRichTextController> | null>(null)\n\n\tconst state = reactive({\n\t\tready: false,\n\t\terror: null as Error | null,\n\t\tcanUndo: false,\n\t\tcanRedo: false,\n\t\tcursors: [] as UseRichTextResult['cursors'],\n\t\thasUnsavedChanges: false,\n\t})\n\n\twatch(\n\t\t() => [collectionName, recordId, fieldName, options?.useDocChannel] as const,\n\t\t([name, id, field, useDocChannel], _previous, onCleanup) => {\n\t\t\tcontrollerRef.value?.destroy()\n\n\t\t\tconst controller = createRichTextController({\n\t\t\t\tcollection: store.collection(name),\n\t\t\t\tcollectionName: name,\n\t\t\t\trecordId: id,\n\t\t\t\tfieldName: field,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t})\n\n\t\t\tconst syncState = (): void => {\n\t\t\t\tconst snapshot = controller.getSnapshot()\n\t\t\t\tstate.ready = snapshot.ready\n\t\t\t\tstate.error = snapshot.error\n\t\t\t\tstate.canUndo = snapshot.canUndo\n\t\t\t\tstate.canRedo = snapshot.canRedo\n\t\t\t\tstate.cursors = [...snapshot.cursors]\n\t\t\t\tstate.hasUnsavedChanges = snapshot.hasUnsavedChanges\n\t\t\t}\n\n\t\t\tsyncState()\n\t\t\tconst unsubscribe = controller.subscribe(syncState)\n\t\t\tcontrollerRef.value = controller\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tcontroller.destroy()\n\t\t\t\tif (controllerRef.value === controller) {\n\t\t\t\t\tcontrollerRef.value = null\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\twatch(\n\t\t() => options?.user,\n\t\t(user) => {\n\t\t\tcontrollerRef.value?.setUser(user)\n\t\t},\n\t)\n\n\tconst controller = (): NonNullable<typeof controllerRef.value> => {\n\t\tif (!controllerRef.value) {\n\t\t\tthrow new Error('useRichText controller is not initialized')\n\t\t}\n\t\treturn controllerRef.value\n\t}\n\n\treturn {\n\t\tget doc() {\n\t\t\treturn controller().doc\n\t\t},\n\t\tget text() {\n\t\t\treturn controller().text\n\t\t},\n\t\tundo: () => controller().undo(),\n\t\tredo: () => controller().redo(),\n\t\tget ready() {\n\t\t\treturn state.ready\n\t\t},\n\t\tget error() {\n\t\t\treturn state.error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn state.canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn state.canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn state.cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller().setCursor(anchor, head),\n\t\tclearCursor: () => controller().clearCursor(),\n\t\tget hasUnsavedChanges() {\n\t\t\treturn state.hasUnsavedChanges\n\t\t},\n\t\tretrySave: () => controller().retrySave(),\n\t\tgetUnsavedState: () => controller().getUnsavedState(),\n\t}\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type ShallowRef, onScopeDispose, shallowRef, watch, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Sets the local user's collaborative presence state.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\n\twatch(\n\t\t() => [syncEngine, user?.name, user?.color, user?.avatar] as const,\n\t\t([engine, name, color, avatar], _prev, onCleanup) => {\n\t\t\tif (!engine || !name || !color) return\n\n\t\t\tconst awareness = engine.getAwarenessManager()\n\t\t\tawareness.setLocalState({\n\t\t\t\tuser: {\n\t\t\t\t\tname,\n\t\t\t\t\tcolor,\n\t\t\t\t\tavatar,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tonCleanup(() => {\n\t\t\t\tawareness.setLocalState(null)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n}\n\n/**\n * Reactive list of remote collaborators' awareness states.\n */\nexport function useCollaborators(): ShallowRef<AwarenessState[]> {\n\tconst { syncEngine } = useKoraContext()\n\tconst collaborators = shallowRef<AwarenessState[]>([])\n\n\twatchEffect((onCleanup) => {\n\t\tif (!syncEngine) {\n\t\t\tcollaborators.value = []\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst unsubscribe = subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\tcollaborators.value = states\n\t\t})\n\t\tonCleanup(unsubscribe)\n\t})\n\n\tonScopeDispose(() => {\n\t\tcollaborators.value = []\n\t})\n\n\treturn collaborators\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,eAA0B;AAC1B,IAAAC,cAAiC;;;ACDjC,kBAA0B;AAC1B,iBAA2D;AAGpD,IAAM,iBACZ,uBAAO,gBAAgB;AAGjB,IAAM,sBAAiD,uBAAO,YAAY;AAE1E,SAAS,iBAAmC;AAClD,QAAM,iBAAa,mBAAO,cAAc;AACxC,MAAI,CAAC,YAAY,OAAO;AACvB,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA,EAAE,KAAK,kDAAkD;AAAA,IAC1D;AAAA,EACD;AACA,SAAO,WAAW;AACnB;;;ACpBA,mBAAgC;AAGhC,IAAAC,cAUO;;;ACPA,SAAS,uBACf,KACA,UACkB;AAClB,MAAI,OAAO,OAAO,IAAI,uBAAuB,YAAY;AACxD,WAAO,IAAI,mBAAmB;AAAA,EAC/B;AACA,SAAO;AACR;;;ADIO,IAAM,mBAAe,6BAAgB;AAAA,EAC3C,MAAM;AAAA,EACN,OAAO;AAAA,IACN,KAAK;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,IACV;AAAA,IACA,OAAO;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IACV;AAAA,IACA,YAAY;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,IACV;AAAA,IACA,UAAU;AAAA,MACT,MAAM,CAAC,QAAQ,MAAM;AAAA,MACrB,SAAS;AAAA,IACV;AAAA,EACD;AAAA,EACA,MAAM,OAAO,EAAE,MAAM,GAAG;AACvB,UAAM,oBAAgB,iBAAkB,IAAI;AAC5C,UAAM,mBAAe,iBAAuB,IAAI;AAChD,UAAM,YAAQ,iBAAI,CAAC,MAAM,OAAO,QAAQ,MAAM,KAAK,CAAC;AACpD,UAAM,gBAAY,iBAAkB,IAAI;AACxC,UAAM,0BAA0B,IAAI,6BAAgB;AACpD,UAAM,iBAAa,wBAAoC,IAAI;AAE3D,6BAAQ,gBAAgB,UAAU;AAClC,QAAI,MAAM,KAAK;AACd,+BAAQ,qBAAqB,MAAM,GAAG;AAAA,IACvC;AAEA;AAAA,MACC,MAAM,MAAM;AAAA,MACZ,CAAC,KAAK,WAAW,cAAc;AAC9B,YAAI,CAAC,KAAK;AACT,cAAI,MAAM,OAAO;AAChB,0BAAc,QAAQ,MAAM;AAC5B,yBAAa,QAAS,MAAM,cAAc;AAC1C,kBAAM,QAAQ;AAAA,UACf;AACA;AAAA,QACD;AAEA,cAAM,QAAQ;AACd,kBAAU,QAAQ;AAClB,YAAI,YAAY;AAEhB,YAAI,MACF,KAAK,MAAM;AACX,cAAI,UAAW;AACf,wBAAc,QAAQ,IAAI,SAAS;AACnC,uBAAa,QAAQ,IAAI,cAAc;AACvC,gBAAM,QAAQ;AAAA,QACf,CAAC,EACA,MAAM,CAAC,UAAmB;AAC1B,cAAI,UAAW;AACf,gBAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACpE,kBAAQ,MAAM,iCAAiC,GAAG;AAClD,oBAAU,QAAQ;AAAA,QACnB,CAAC;AAEF,kBAAU,MAAM;AACf,sBAAY;AAAA,QACb,CAAC;AAAA,MACF;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACnB;AAEA;AAAA,MACC,MAAM,MAAM;AAAA,MACZ,CAAC,UAAU;AACV,YAAI,SAAS,CAAC,MAAM,KAAK;AACxB,wBAAc,QAAQ;AACtB,uBAAa,QAAS,MAAM,cAAc;AAC1C,gBAAM,QAAQ;AAAA,QACf;AAAA,MACD;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACnB;AAEA;AAAA,MACC,MAAM,CAAC,cAAc,OAAO,aAAa,OAAO,MAAM,GAAG;AAAA,MACzD,CAAC,CAAC,OAAO,YAAY,GAAG,MAAM;AAC7B,YAAI,CAAC,OAAO;AACX,qBAAW,QAAQ;AACnB;AAAA,QACD;AAEA,mBAAW,QAAQ;AAAA,UAClB;AAAA,UACA,YAAa,cAAc;AAAA,UAC3B,KAAK,OAAO;AAAA,UACZ,QAAQ,KAAK,UAAU;AAAA,UACvB,qBAAqB,KAAK,MAAM,mBAAmB;AAAA,UACnD,iBAAiB,uBAAuB,KAAK,uBAAuB;AAAA,QACrE;AAAA,MACD;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACnB;AAEA,oCAAe,MAAM;AACpB,UAAI,CAAC,MAAM,KAAK;AACf,gCAAwB,MAAM;AAAA,MAC/B;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,UAAI,UAAU,OAAO;AACpB,mBAAO,eAAE,OAAO,EAAE,OAAO,EAAE,OAAO,OAAO,SAAS,QAAQ,YAAY,YAAY,EAAE,GAAG;AAAA,cACtF,eAAE,UAAU,MAAM,6BAA6B;AAAA,UAC/C,UAAU,MAAM;AAAA,QACjB,CAAC;AAAA,MACF;AAEA,UAAI,CAAC,MAAM,OAAO;AACjB,eAAO,MAAM,YAAY;AAAA,MAC1B;AAEA,UAAI,CAAC,cAAc,OAAO;AACzB,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD;AAEA,aAAO,MAAM,UAAU;AAAA,IACxB;AAAA,EACD;AACD,CAAC;;;AElJD,IAAAC,gBAA2C;AAC3C,IAAAC,cAQO;AAIP,IAAM,cAAkC,OAAO,OAAO,CAAC,CAAC;AAMxD,SAAS,eAAe,YAA+C;AACtE,QAAM,UAAU;AAChB,SAAO,OAAO,QAAQ,aAAa,aAAa,QAAQ,SAAS,IAAI;AACtE;AAQA,SAAS,qBACR,OACA,SAKC;AACD,QAAM,EAAE,gBAAgB,IAAI,eAAe;AAC3C,QAAM,WAAO,wBAAyB,WAA2B;AACjE,QAAM,YAAQ,wBAAyB,IAAI;AAC3C,QAAM,YAAQ,wBAAW,KAAK;AAE9B;AAAA,IACC,MAAM;AACL,YAAM,cAAU,qBAAQ,SAAS,OAAO,MAAM;AAC9C,YAAM,UAAU,cAAU,qBAAQ,KAAK,IAAI;AAC3C,aAAO,cAAU,wBAAS,QAAQ,cAAc,CAAC,IAAI;AAAA,IACtD;AAAA,IACA,CAAC,KAAK,WAAW,cAAc;AAC9B,YAAM,UAAU,UAAM,qBAAQ,KAAK,IAAI;AACvC,UAAI,CAAC,SAAS;AACb,aAAK,QAAQ;AACb,cAAM,QAAQ;AACd,cAAM,QAAQ;AACd;AAAA,MACD;AAEA,0CAAiB,OAAgC;AACjD,YAAM,aAAa,gBAAgB,YAAY,OAAO;AACtD,YAAM,OAAO,MAAY;AACxB,cAAM,UAAU,eAAe,UAAiC;AAChE,YAAI,YAAY,MAAM,OAAO;AAC5B,gBAAM,QAAQ;AACd,cAAI,QAAS,UAAS,UAAU,OAAO;AAAA,QACxC;AACA,YAAI,WAAW,YAAY,GAAG;AAC7B,eAAK,QAAQ,WAAW,YAAY;AACpC,gBAAM,QAAQ;AAAA,QACf;AAAA,MACD;AACA,YAAM,cAAc,WAAW,UAAU,IAAI;AAE7C,YAAM,QAAQ;AACd,WAAK;AAEL,gBAAU,MAAM;AACf,oBAAY;AACZ,wBAAgB,QAAQ,OAAgC;AAAA,MACzD,CAAC;AAAA,IACF;AAAA,IACA,EAAE,WAAW,KAAK;AAAA,EACnB;AAEA,SAAO,EAAE,MAAM,OAAO,MAAM;AAC7B;AAqBO,SAAS,SACf,OACA,SACyC;AACzC,QAAM,YAA6B;AAAA,IAClC,GAAG;AAAA,IACH,SACC,SAAS,YACR,CAAC,YAAmB;AAEpB,cAAQ,MAAM,2BAA2B,OAAO;AAAA,IACjD;AAAA,EACF;AACA,aAAO,sBAAS,qBAAqB,OAAO,SAAS,EAAE,IAAI;AAC5D;AAUO,SAAS,cACf,OACA,SACyB;AACzB,QAAM,EAAE,MAAM,OAAO,MAAM,IAAI,qBAAqB,OAAO,OAAO;AAClE,SAAO,EAAE,UAAM,sBAAS,IAAI,GAAG,WAAO,sBAAS,KAAK,GAAG,WAAO,sBAAS,KAAK,EAAE;AAC/E;;;ACzIA,sBAAyC;AACzC,IAAAC,cAAqD;AAM9C,SAAS,YACf,YACA,SACkC;AAClC,QAAM,QAAQ,EAAE,SAAS,WAAW;AACpC,QAAM,UAAU;AAEhB,QAAM,aAAa,EAAE,SAAS,QAAQ;AACtC,aAAW,UAAU;AAErB,QAAM,gBAAY,iBAAI,KAAK;AAC3B,QAAM,YAAQ,iBAAkB,IAAI;AACpC,MAAI,UAAU;AAEd,kCAAe,MAAM;AACpB,cAAU;AAAA,EACX,CAAC;AAED,QAAM,iBAAa,0CAAiD;AAAA,IACnE,YAAY,IAAI,SAAS,MAAM,QAAQ,GAAG,IAAI;AAAA,IAC9C,gBAAgB,MAAM,WAAW;AAAA,IACjC,eAAe,CAAC,UAAU;AACzB,UAAI,CAAC,QAAS;AACd,gBAAU,QAAQ,MAAM;AACxB,YAAM,QAAQ,MAAM;AAAA,IACrB;AAAA,EACD,CAAC;AAED,YAAU,QAAQ,WAAW,YAAY,EAAE;AAC3C,QAAM,QAAQ,WAAW,YAAY,EAAE;AAEvC,kCAAe,MAAM;AACpB,eAAW,QAAQ;AAAA,EACpB,CAAC;AAED,SAAO;AAAA,IACN,QAAQ,IAAI,SAAgB,WAAW,OAAO,GAAG,IAAI;AAAA,IACrD,aAAa,IAAI,SAAgB,WAAW,YAAY,GAAG,IAAI;AAAA,IAC/D,eAAW,6BAAgB,SAAS;AAAA,IACpC,WAAO,6BAAgB,KAAK;AAAA,IAC5B,OAAO,MAAM,WAAW,MAAM;AAAA,EAC/B;AACD;;;ACjDA,kBAAgE;AAChE,IAAAC,cAAkE;AAM3D,SAAS,gBAAgB;AAC/B,QAAM,EAAE,YAAY,qBAAqB,OAAO,IAAI,eAAe;AACnE,QAAM,aAAS,wBAAW,+BAAmB;AAE7C,+BAAY,CAAC,cAAc;AAC1B,UAAM,iBAAa,wCAA2B;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,QAAQ,sBAAsB,OAAO;AAAA,IACtC,CAAC;AACD,WAAO,QAAQ,WAAW,YAAY;AACtC,UAAM,cAAc,WAAW,UAAU,MAAM;AAC9C,aAAO,QAAQ,WAAW,YAAY;AAAA,IACvC,CAAC;AACD,cAAU,MAAM;AACf,kBAAY;AACZ,iBAAW,QAAQ;AAAA,IACpB,CAAC;AAAA,EACF,CAAC;AAED,aAAO,sBAAS,MAAM;AACvB;;;ACtBO,SAAS,SAAiD;AAChE,QAAM,EAAE,IAAI,IAAI,eAAe;AAC/B,MAAI,CAAC,KAAK;AACT,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;;;ACRO,SAAS,cAAc,MAAkC;AAC/D,QAAM,EAAE,MAAM,IAAI,eAAe;AACjC,SAAO,MAAM,WAAW,IAAI;AAC7B;;;ACTA,IAAAC,gBAA+D;AAE/D,IAAAC,cAA4C;AAYrC,SAAS,YACf,gBACA,UACA,WACA,SACoB;AACpB,QAAM,EAAE,OAAO,WAAW,IAAI,eAAe;AAC7C,QAAM,oBAAgB,wBAA+D,IAAI;AAEzF,QAAM,YAAQ,sBAAS;AAAA,IACtB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS,CAAC;AAAA,IACV,mBAAmB;AAAA,EACpB,CAAC;AAED;AAAA,IACC,MAAM,CAAC,gBAAgB,UAAU,WAAW,SAAS,aAAa;AAAA,IAClE,CAAC,CAAC,MAAM,IAAI,OAAO,aAAa,GAAG,WAAW,cAAc;AAC3D,oBAAc,OAAO,QAAQ;AAE7B,YAAMC,kBAAa,wCAAyB;AAAA,QAC3C,YAAY,MAAM,WAAW,IAAI;AAAA,QACjC,gBAAgB;AAAA,QAChB,UAAU;AAAA,QACV,WAAW;AAAA,QACX;AAAA,QACA,gBAAY,oCAAqB,UAAU;AAAA,QAC3C;AAAA,QACA,MAAM,SAAS;AAAA,MAChB,CAAC;AAED,YAAM,YAAY,MAAY;AAC7B,cAAM,WAAWA,YAAW,YAAY;AACxC,cAAM,QAAQ,SAAS;AACvB,cAAM,QAAQ,SAAS;AACvB,cAAM,UAAU,SAAS;AACzB,cAAM,UAAU,SAAS;AACzB,cAAM,UAAU,CAAC,GAAG,SAAS,OAAO;AACpC,cAAM,oBAAoB,SAAS;AAAA,MACpC;AAEA,gBAAU;AACV,YAAM,cAAcA,YAAW,UAAU,SAAS;AAClD,oBAAc,QAAQA;AAEtB,gBAAU,MAAM;AACf,oBAAY;AACZ,QAAAA,YAAW,QAAQ;AACnB,YAAI,cAAc,UAAUA,aAAY;AACvC,wBAAc,QAAQ;AAAA,QACvB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,EAAE,WAAW,KAAK;AAAA,EACnB;AAEA;AAAA,IACC,MAAM,SAAS;AAAA,IACf,CAAC,SAAS;AACT,oBAAc,OAAO,QAAQ,IAAI;AAAA,IAClC;AAAA,EACD;AAEA,QAAM,aAAa,MAA+C;AACjE,QAAI,CAAC,cAAc,OAAO;AACzB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC5D;AACA,WAAO,cAAc;AAAA,EACtB;AAEA,SAAO;AAAA,IACN,IAAI,MAAM;AACT,aAAO,WAAW,EAAE;AAAA,IACrB;AAAA,IACA,IAAI,OAAO;AACV,aAAO,WAAW,EAAE;AAAA,IACrB;AAAA,IACA,MAAM,MAAM,WAAW,EAAE,KAAK;AAAA,IAC9B,MAAM,MAAM,WAAW,EAAE,KAAK;AAAA,IAC9B,IAAI,QAAQ;AACX,aAAO,MAAM;AAAA,IACd;AAAA,IACA,IAAI,QAAQ;AACX,aAAO,MAAM;AAAA,IACd;AAAA,IACA,IAAI,UAAU;AACb,aAAO,MAAM;AAAA,IACd;AAAA,IACA,IAAI,UAAU;AACb,aAAO,MAAM;AAAA,IACd;AAAA,IACA,IAAI,UAAU;AACb,aAAO,MAAM;AAAA,IACd;AAAA,IACA,WAAW,CAAC,QAAgB,SAAiB,WAAW,EAAE,UAAU,QAAQ,IAAI;AAAA,IAChF,aAAa,MAAM,WAAW,EAAE,YAAY;AAAA,IAC5C,IAAI,oBAAoB;AACvB,aAAO,MAAM;AAAA,IACd;AAAA,IACA,WAAW,MAAM,WAAW,EAAE,UAAU;AAAA,IACxC,iBAAiB,MAAM,WAAW,EAAE,gBAAgB;AAAA,EACrD;AACD;;;ACtHA,IAAAC,eAA+C;AAC/C,IAAAC,cAAgF;AAMzE,SAAS,YAAY,MAAqE;AAChG,QAAM,EAAE,WAAW,IAAI,eAAe;AAEtC;AAAA,IACC,MAAM,CAAC,YAAY,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM;AAAA,IACxD,CAAC,CAAC,QAAQ,MAAM,OAAO,MAAM,GAAG,OAAO,cAAc;AACpD,UAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAO;AAEhC,YAAM,YAAY,OAAO,oBAAoB;AAC7C,gBAAU,cAAc;AAAA,QACvB,MAAM;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD,CAAC;AAED,gBAAU,MAAM;AACf,kBAAU,cAAc,IAAI;AAAA,MAC7B,CAAC;AAAA,IACF;AAAA,IACA,EAAE,WAAW,KAAK;AAAA,EACnB;AACD;AAKO,SAAS,mBAAiD;AAChE,QAAM,EAAE,WAAW,IAAI,eAAe;AACtC,QAAM,oBAAgB,wBAA6B,CAAC,CAAC;AAErD,+BAAY,CAAC,cAAc;AAC1B,QAAI,CAAC,YAAY;AAChB,oBAAc,QAAQ,CAAC;AACvB;AAAA,IACD;AAEA,UAAM,YAAY,WAAW,oBAAoB;AACjD,UAAM,kBAAc,6CAA+B,WAAW,CAAC,WAAW;AACzE,oBAAc,QAAQ;AAAA,IACvB,CAAC;AACD,cAAU,WAAW;AAAA,EACtB,CAAC;AAED,kCAAe,MAAM;AACpB,kBAAc,QAAQ,CAAC;AAAA,EACxB,CAAC;AAED,SAAO;AACR;;;AV1BO,SAAS,YAAY,QAAa,SAA4B;AACpE,SAAO,QAAQ,qBAAqB,OAAO;AAC5C;AAMO,SAAS,aAA0B;AACzC,QAAM,UAAM,oBAAO,mBAAmB;AACtC,MAAI,CAAC,KAAK;AACT,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA,EAAE,KAAK,gEAAgE;AAAA,IACxE;AAAA,EACD;AACA,SAAO;AACR;","names":["import_core","import_vue","import_vue","import_store","import_vue","import_vue","import_vue","import_store","import_vue","controller","import_sync","import_vue"]}
package/dist/index.d.cts CHANGED
@@ -1,14 +1,29 @@
1
1
  import * as vue from 'vue';
2
- import { VNode, InjectionKey, ShallowRef, PropType, DeepReadonly, App } from 'vue';
2
+ import { VNode, MaybeRefOrGetter, DeepReadonly, ShallowRef, InjectionKey, PropType, App } from 'vue';
3
3
  import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1 } from '@korajs/core/bindings';
4
- import { Store, QueryStoreCache, CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
4
+ import { Store, QueryStoreCache, QueryBuilder, CollectionRecord, CollectionAccessor } from '@korajs/store';
5
5
  import * as _korajs_sync from '@korajs/sync';
6
6
  import { SyncEngine, CursorInfo, AwarenessUser, AwarenessState } from '@korajs/sync';
7
7
  import * as Y from 'yjs';
8
8
 
9
9
  type KoraAppLike = KoraAppLike$1<Store, SyncEngine, QueryStoreCache>;
10
10
  type KoraContextValue = KoraContextValue$1<Store, SyncEngine, QueryStoreCache>;
11
- type UseQueryOptions = UseQueryOptions$1;
11
+ /** Options for `useQuery` and `useQueryState`. */
12
+ interface UseQueryOptions extends Omit<UseQueryOptions$1, 'enabled'> {
13
+ /** When false, the query subscription is disabled. A value, ref or getter. Defaults to true. */
14
+ enabled?: MaybeRefOrGetter<boolean | undefined>;
15
+ /** Called when the query fails (STORE-12). `useQuery` logs to `console.error` without it. */
16
+ onError?: (error: Error) => void;
17
+ }
18
+ /** Result of `useQueryState`. */
19
+ interface UseQueryStateResult<T> {
20
+ /** The current rows (the last good rows while `error` is set). */
21
+ data: DeepReadonly<ShallowRef<readonly T[]>>;
22
+ /** The query's failure, or null. Cleared when results flow again. */
23
+ error: Readonly<ShallowRef<Error | null>>;
24
+ /** False until the first result for the current query arrived. */
25
+ ready: Readonly<ShallowRef<boolean>>;
26
+ }
12
27
  type UseMutationOptions<TData, TArgs extends unknown[], TContext = void> = UseMutationOptions$1<TData, TArgs, TContext>;
13
28
  interface KoraProviderProps {
14
29
  app?: KoraAppLike;
@@ -38,6 +53,15 @@ interface UseRichTextResult {
38
53
  cursors: CursorInfo[];
39
54
  setCursor: (anchor: number, head: number) => void;
40
55
  clearCursor: () => void;
56
+ /**
57
+ * True while local edits are not saved yet (a save pending or refused; see
58
+ * `error`). The edits stay in the document and the next edit saves them again.
59
+ */
60
+ hasUnsavedChanges: boolean;
61
+ /** Save the document now, for example after a refused save. */
62
+ retrySave: () => Promise<void>;
63
+ /** The full document state while edits are unsaved (for a recovery copy), else null. */
64
+ getUnsavedState: () => Uint8Array | null;
41
65
  }
42
66
 
43
67
  declare const koraContextKey: InjectionKey<ShallowRef<KoraContextValue | null>>;
@@ -92,10 +116,37 @@ declare const KoraProvider: vue.DefineComponent<vue.ExtractPropTypes<{
92
116
  }> | null;
93
117
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
94
118
 
119
+ /** A query input: a builder, a ref to one, or a getter (`() => app.todos.where(...)`). */
120
+ type QueryInput<T> = MaybeRefOrGetter<QueryBuilder<T> | null | undefined>;
95
121
  /**
96
122
  * Reactive query composable backed by the local Kora store.
123
+ *
124
+ * The query and `enabled` may be plain values, refs or getters: pass a getter to
125
+ * follow props or refs, and the composable re-subscribes when the query's descriptor
126
+ * changes (and releases the old subscription). A failed query is reported through
127
+ * `options.onError`, or `console.error` without one; use {@link useQueryState} to
128
+ * render the error.
129
+ *
130
+ * @param query - A query builder, a ref to one, or a getter returning one (null disables)
131
+ * @param options - `enabled` (value, ref or getter; default true) and `onError`
132
+ * @returns A readonly shallow ref of the current rows
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * const props = defineProps<{ done: boolean }>()
137
+ * const todos = useQuery(() => app.todos.where({ completed: props.done }))
138
+ * ```
139
+ */
140
+ declare function useQuery<T = CollectionRecord>(query: QueryInput<T>, options?: UseQueryOptions): DeepReadonly<ShallowRef<readonly T[]>>;
141
+ /**
142
+ * Like {@link useQuery}, but also returns the query's error and whether the first
143
+ * result has arrived.
144
+ *
145
+ * @param query - A query builder, a ref to one, or a getter returning one
146
+ * @param options - `enabled` and `onError`
147
+ * @returns `{ data, error, ready }` as readonly refs
97
148
  */
98
- declare function useQuery<T = CollectionRecord>(query: QueryBuilder<T>, options?: UseQueryOptions): DeepReadonly<ShallowRef<readonly T[]>>;
149
+ declare function useQueryState<T = CollectionRecord>(query: QueryInput<T>, options?: UseQueryOptions): UseQueryStateResult<T>;
99
150
 
100
151
  /**
101
152
  * Mutation composable with optional optimistic update and rollback hooks.
@@ -115,6 +166,16 @@ declare function useSyncStatus(): Readonly<vue.Ref<{
115
166
  readonly lastSuccessfulPush: number | null;
116
167
  readonly lastSuccessfulPull: number | null;
117
168
  readonly conflicts: number;
169
+ readonly heldOperations?: number | undefined;
170
+ readonly heldNodes?: readonly {
171
+ readonly nodeId: string;
172
+ readonly operationCount: number;
173
+ readonly reason: _korajs_sync.HeldReason;
174
+ readonly principal: string | null;
175
+ }[] | undefined;
176
+ readonly localDurability?: "durable" | "degraded" | undefined;
177
+ readonly serverProtocolVersion?: number | null | undefined;
178
+ readonly protocolDeprecated?: boolean | undefined;
118
179
  readonly clockSkewMs: number | null;
119
180
  readonly inFlightUploadOperations?: number | undefined;
120
181
  readonly hasInFlightDeliveryBatch?: boolean | undefined;
@@ -148,6 +209,16 @@ declare function useSyncStatus(): Readonly<vue.Ref<{
148
209
  readonly lastSuccessfulPush: number | null;
149
210
  readonly lastSuccessfulPull: number | null;
150
211
  readonly conflicts: number;
212
+ readonly heldOperations?: number | undefined;
213
+ readonly heldNodes?: readonly {
214
+ readonly nodeId: string;
215
+ readonly operationCount: number;
216
+ readonly reason: _korajs_sync.HeldReason;
217
+ readonly principal: string | null;
218
+ }[] | undefined;
219
+ readonly localDurability?: "durable" | "degraded" | undefined;
220
+ readonly serverProtocolVersion?: number | null | undefined;
221
+ readonly protocolDeprecated?: boolean | undefined;
151
222
  readonly clockSkewMs: number | null;
152
223
  readonly inFlightUploadOperations?: number | undefined;
153
224
  readonly hasInFlightDeliveryBatch?: boolean | undefined;
@@ -218,4 +289,4 @@ declare function installKora(vueApp: App, koraApp: KoraAppLike): void;
218
289
  */
219
290
  declare function useKoraApp(): KoraAppLike;
220
291
 
221
- export { type KoraAppHandle, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, installKora, koraAppInjectionKey, koraContextKey, useApp, useCollaborators, useCollection, useKoraApp, useKoraContext, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
292
+ export { type KoraAppHandle, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type QueryInput, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryStateResult, type UseRichTextOptions, type UseRichTextResult, installKora, koraAppInjectionKey, koraContextKey, useApp, useCollaborators, useCollection, useKoraApp, useKoraContext, useMutation, usePresence, useQuery, useQueryState, useRichText, useSyncStatus };
package/dist/index.d.ts CHANGED
@@ -1,14 +1,29 @@
1
1
  import * as vue from 'vue';
2
- import { VNode, InjectionKey, ShallowRef, PropType, DeepReadonly, App } from 'vue';
2
+ import { VNode, MaybeRefOrGetter, DeepReadonly, ShallowRef, InjectionKey, PropType, App } from 'vue';
3
3
  import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1 } from '@korajs/core/bindings';
4
- import { Store, QueryStoreCache, CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
4
+ import { Store, QueryStoreCache, QueryBuilder, CollectionRecord, CollectionAccessor } from '@korajs/store';
5
5
  import * as _korajs_sync from '@korajs/sync';
6
6
  import { SyncEngine, CursorInfo, AwarenessUser, AwarenessState } from '@korajs/sync';
7
7
  import * as Y from 'yjs';
8
8
 
9
9
  type KoraAppLike = KoraAppLike$1<Store, SyncEngine, QueryStoreCache>;
10
10
  type KoraContextValue = KoraContextValue$1<Store, SyncEngine, QueryStoreCache>;
11
- type UseQueryOptions = UseQueryOptions$1;
11
+ /** Options for `useQuery` and `useQueryState`. */
12
+ interface UseQueryOptions extends Omit<UseQueryOptions$1, 'enabled'> {
13
+ /** When false, the query subscription is disabled. A value, ref or getter. Defaults to true. */
14
+ enabled?: MaybeRefOrGetter<boolean | undefined>;
15
+ /** Called when the query fails (STORE-12). `useQuery` logs to `console.error` without it. */
16
+ onError?: (error: Error) => void;
17
+ }
18
+ /** Result of `useQueryState`. */
19
+ interface UseQueryStateResult<T> {
20
+ /** The current rows (the last good rows while `error` is set). */
21
+ data: DeepReadonly<ShallowRef<readonly T[]>>;
22
+ /** The query's failure, or null. Cleared when results flow again. */
23
+ error: Readonly<ShallowRef<Error | null>>;
24
+ /** False until the first result for the current query arrived. */
25
+ ready: Readonly<ShallowRef<boolean>>;
26
+ }
12
27
  type UseMutationOptions<TData, TArgs extends unknown[], TContext = void> = UseMutationOptions$1<TData, TArgs, TContext>;
13
28
  interface KoraProviderProps {
14
29
  app?: KoraAppLike;
@@ -38,6 +53,15 @@ interface UseRichTextResult {
38
53
  cursors: CursorInfo[];
39
54
  setCursor: (anchor: number, head: number) => void;
40
55
  clearCursor: () => void;
56
+ /**
57
+ * True while local edits are not saved yet (a save pending or refused; see
58
+ * `error`). The edits stay in the document and the next edit saves them again.
59
+ */
60
+ hasUnsavedChanges: boolean;
61
+ /** Save the document now, for example after a refused save. */
62
+ retrySave: () => Promise<void>;
63
+ /** The full document state while edits are unsaved (for a recovery copy), else null. */
64
+ getUnsavedState: () => Uint8Array | null;
41
65
  }
42
66
 
43
67
  declare const koraContextKey: InjectionKey<ShallowRef<KoraContextValue | null>>;
@@ -92,10 +116,37 @@ declare const KoraProvider: vue.DefineComponent<vue.ExtractPropTypes<{
92
116
  }> | null;
93
117
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
94
118
 
119
+ /** A query input: a builder, a ref to one, or a getter (`() => app.todos.where(...)`). */
120
+ type QueryInput<T> = MaybeRefOrGetter<QueryBuilder<T> | null | undefined>;
95
121
  /**
96
122
  * Reactive query composable backed by the local Kora store.
123
+ *
124
+ * The query and `enabled` may be plain values, refs or getters: pass a getter to
125
+ * follow props or refs, and the composable re-subscribes when the query's descriptor
126
+ * changes (and releases the old subscription). A failed query is reported through
127
+ * `options.onError`, or `console.error` without one; use {@link useQueryState} to
128
+ * render the error.
129
+ *
130
+ * @param query - A query builder, a ref to one, or a getter returning one (null disables)
131
+ * @param options - `enabled` (value, ref or getter; default true) and `onError`
132
+ * @returns A readonly shallow ref of the current rows
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * const props = defineProps<{ done: boolean }>()
137
+ * const todos = useQuery(() => app.todos.where({ completed: props.done }))
138
+ * ```
139
+ */
140
+ declare function useQuery<T = CollectionRecord>(query: QueryInput<T>, options?: UseQueryOptions): DeepReadonly<ShallowRef<readonly T[]>>;
141
+ /**
142
+ * Like {@link useQuery}, but also returns the query's error and whether the first
143
+ * result has arrived.
144
+ *
145
+ * @param query - A query builder, a ref to one, or a getter returning one
146
+ * @param options - `enabled` and `onError`
147
+ * @returns `{ data, error, ready }` as readonly refs
97
148
  */
98
- declare function useQuery<T = CollectionRecord>(query: QueryBuilder<T>, options?: UseQueryOptions): DeepReadonly<ShallowRef<readonly T[]>>;
149
+ declare function useQueryState<T = CollectionRecord>(query: QueryInput<T>, options?: UseQueryOptions): UseQueryStateResult<T>;
99
150
 
100
151
  /**
101
152
  * Mutation composable with optional optimistic update and rollback hooks.
@@ -115,6 +166,16 @@ declare function useSyncStatus(): Readonly<vue.Ref<{
115
166
  readonly lastSuccessfulPush: number | null;
116
167
  readonly lastSuccessfulPull: number | null;
117
168
  readonly conflicts: number;
169
+ readonly heldOperations?: number | undefined;
170
+ readonly heldNodes?: readonly {
171
+ readonly nodeId: string;
172
+ readonly operationCount: number;
173
+ readonly reason: _korajs_sync.HeldReason;
174
+ readonly principal: string | null;
175
+ }[] | undefined;
176
+ readonly localDurability?: "durable" | "degraded" | undefined;
177
+ readonly serverProtocolVersion?: number | null | undefined;
178
+ readonly protocolDeprecated?: boolean | undefined;
118
179
  readonly clockSkewMs: number | null;
119
180
  readonly inFlightUploadOperations?: number | undefined;
120
181
  readonly hasInFlightDeliveryBatch?: boolean | undefined;
@@ -148,6 +209,16 @@ declare function useSyncStatus(): Readonly<vue.Ref<{
148
209
  readonly lastSuccessfulPush: number | null;
149
210
  readonly lastSuccessfulPull: number | null;
150
211
  readonly conflicts: number;
212
+ readonly heldOperations?: number | undefined;
213
+ readonly heldNodes?: readonly {
214
+ readonly nodeId: string;
215
+ readonly operationCount: number;
216
+ readonly reason: _korajs_sync.HeldReason;
217
+ readonly principal: string | null;
218
+ }[] | undefined;
219
+ readonly localDurability?: "durable" | "degraded" | undefined;
220
+ readonly serverProtocolVersion?: number | null | undefined;
221
+ readonly protocolDeprecated?: boolean | undefined;
151
222
  readonly clockSkewMs: number | null;
152
223
  readonly inFlightUploadOperations?: number | undefined;
153
224
  readonly hasInFlightDeliveryBatch?: boolean | undefined;
@@ -218,4 +289,4 @@ declare function installKora(vueApp: App, koraApp: KoraAppLike): void;
218
289
  */
219
290
  declare function useKoraApp(): KoraAppLike;
220
291
 
221
- export { type KoraAppHandle, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, installKora, koraAppInjectionKey, koraContextKey, useApp, useCollaborators, useCollection, useKoraApp, useKoraContext, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
292
+ export { type KoraAppHandle, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type QueryInput, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryStateResult, type UseRichTextOptions, type UseRichTextResult, installKora, koraAppInjectionKey, koraContextKey, useApp, useCollaborators, useCollection, useKoraApp, useKoraContext, useMutation, usePresence, useQuery, useQueryState, useRichText, useSyncStatus };
package/dist/index.js CHANGED
@@ -157,34 +157,74 @@ var KoraProvider = defineComponent({
157
157
  });
158
158
 
159
159
  // src/composables/use-query.ts
160
- import { assertQueryReady } from "@korajs/store";
161
- import { readonly, shallowRef as shallowRef2, watch as watch2 } from "vue";
160
+ import { assertQueryReady, queryKey } from "@korajs/store";
161
+ import {
162
+ readonly,
163
+ shallowRef as shallowRef2,
164
+ toValue,
165
+ watch as watch2
166
+ } from "vue";
162
167
  var EMPTY_ARRAY = Object.freeze([]);
163
- function useQuery(query, options) {
168
+ function readQueryError(queryStore) {
169
+ const channel = queryStore;
170
+ return typeof channel.getError === "function" ? channel.getError() : null;
171
+ }
172
+ function useQuerySubscription(query, options) {
164
173
  const { queryStoreCache } = useKoraContext();
165
- const enabled = options?.enabled !== false;
166
- const snapshot = shallowRef2(EMPTY_ARRAY);
174
+ const data = shallowRef2(EMPTY_ARRAY);
175
+ const error = shallowRef2(null);
176
+ const ready = shallowRef2(false);
167
177
  watch2(
168
- () => enabled ? JSON.stringify(query.getDescriptor()) : null,
178
+ () => {
179
+ const enabled = toValue(options?.enabled) !== false;
180
+ const current = enabled ? toValue(query) : null;
181
+ return current ? queryKey(current.getDescriptor()) : null;
182
+ },
169
183
  (key, _previous, onCleanup) => {
170
- if (!key) {
171
- snapshot.value = EMPTY_ARRAY;
184
+ const current = key ? toValue(query) : null;
185
+ if (!current) {
186
+ data.value = EMPTY_ARRAY;
187
+ error.value = null;
188
+ ready.value = false;
172
189
  return;
173
190
  }
174
- assertQueryReady(query);
175
- const queryStore = queryStoreCache.getOrCreate(query);
176
- const unsubscribe = queryStore.subscribe(() => {
177
- snapshot.value = queryStore.getSnapshot();
178
- });
179
- snapshot.value = queryStore.getSnapshot();
191
+ assertQueryReady(current);
192
+ const queryStore = queryStoreCache.getOrCreate(current);
193
+ const sync = () => {
194
+ const failure = readQueryError(queryStore);
195
+ if (failure !== error.value) {
196
+ error.value = failure;
197
+ if (failure) options?.onError?.(failure);
198
+ }
199
+ if (queryStore.hasSnapshot()) {
200
+ data.value = queryStore.getSnapshot();
201
+ ready.value = true;
202
+ }
203
+ };
204
+ const unsubscribe = queryStore.subscribe(sync);
205
+ ready.value = false;
206
+ sync();
180
207
  onCleanup(() => {
181
208
  unsubscribe();
182
- queryStoreCache.release(query);
209
+ queryStoreCache.release(current);
183
210
  });
184
211
  },
185
212
  { immediate: true }
186
213
  );
187
- return readonly(snapshot);
214
+ return { data, error, ready };
215
+ }
216
+ function useQuery(query, options) {
217
+ const reporting = {
218
+ ...options,
219
+ onError: options?.onError ?? ((failure) => {
220
+ console.error("[Kora] useQuery failed:", failure);
221
+ })
222
+ };
223
+ return readonly(useQuerySubscription(query, reporting).data);
224
+ }
225
+ function useQueryState(query, options) {
226
+ const { data, error, ready } = useQuerySubscription(query, options);
227
+ return { data: readonly(data), error: readonly(error), ready: readonly(ready) };
188
228
  }
189
229
 
190
230
  // src/composables/use-mutation.ts
@@ -276,7 +316,8 @@ function useRichText(collectionName, recordId, fieldName, options) {
276
316
  error: null,
277
317
  canUndo: false,
278
318
  canRedo: false,
279
- cursors: []
319
+ cursors: [],
320
+ hasUnsavedChanges: false
280
321
  });
281
322
  watch3(
282
323
  () => [collectionName, recordId, fieldName, options?.useDocChannel],
@@ -299,6 +340,7 @@ function useRichText(collectionName, recordId, fieldName, options) {
299
340
  state.canUndo = snapshot.canUndo;
300
341
  state.canRedo = snapshot.canRedo;
301
342
  state.cursors = [...snapshot.cursors];
343
+ state.hasUnsavedChanges = snapshot.hasUnsavedChanges;
302
344
  };
303
345
  syncState();
304
346
  const unsubscribe = controller2.subscribe(syncState);
@@ -350,7 +392,12 @@ function useRichText(collectionName, recordId, fieldName, options) {
350
392
  return state.cursors;
351
393
  },
352
394
  setCursor: (anchor, head) => controller().setCursor(anchor, head),
353
- clearCursor: () => controller().clearCursor()
395
+ clearCursor: () => controller().clearCursor(),
396
+ get hasUnsavedChanges() {
397
+ return state.hasUnsavedChanges;
398
+ },
399
+ retrySave: () => controller().retrySave(),
400
+ getUnsavedState: () => controller().getUnsavedState()
354
401
  };
355
402
  }
356
403
 
@@ -426,6 +473,7 @@ export {
426
473
  useMutation,
427
474
  usePresence,
428
475
  useQuery,
476
+ useQueryState,
429
477
  useRichText,
430
478
  useSyncStatus
431
479
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/components/kora-provider.ts","../src/resolve-query-store-cache.ts","../src/composables/use-query.ts","../src/composables/use-mutation.ts","../src/composables/use-sync-status.ts","../src/composables/use-app.ts","../src/composables/use-collection.ts","../src/composables/use-rich-text.ts","../src/composables/use-presence.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { type App, inject } from 'vue'\nimport { koraAppInjectionKey } from './context'\nimport type { KoraAppLike } from './types'\n\nexport type { KoraAppHandle, KoraAppLike, KoraContextValue, KoraProviderProps } from './types'\nexport type {\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseQueryOptions,\n\tUseRichTextResult,\n} from './types'\n\nexport { koraAppInjectionKey, koraContextKey, useKoraContext } from './context'\nexport { KoraProvider } from './components/kora-provider'\nexport { useQuery } from './composables/use-query'\nexport { useMutation } from './composables/use-mutation'\nexport { useSyncStatus } from './composables/use-sync-status'\nexport { useApp } from './composables/use-app'\nexport { useCollection } from './composables/use-collection'\nexport { useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { usePresence, useCollaborators } from './composables/use-presence'\n\n/**\n * Register a Kora app on a Vue application instance.\n *\n * @deprecated Prefer {@link KoraProvider} — `installKora` does not provide reactive\n * hook context (`useQuery`, `useSyncStatus`, etc.) until you migrate to `KoraProvider`.\n */\nexport function installKora(vueApp: App, koraApp: KoraAppLike): void {\n\tvueApp.provide(koraAppInjectionKey, koraApp)\n}\n\n/**\n * Access the Kora app from a component when using {@link installKora} only.\n * For reactive hooks, use {@link useApp} inside {@link KoraProvider}.\n */\nexport function useKoraApp(): KoraAppLike {\n\tconst app = inject(koraAppInjectionKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraApp() requires installKora(vueApp, koraApp) or <KoraProvider :app=\"app\">.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Use <KoraProvider :app=\"app\"> and useApp() for full bindings.' },\n\t\t)\n\t}\n\treturn app\n}\n","import { KoraError } from '@korajs/core'\nimport { type InjectionKey, type ShallowRef, inject } from 'vue'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\nexport const koraContextKey: InjectionKey<ShallowRef<KoraContextValue | null>> =\n\tSymbol('korajs-context')\n\n/** @deprecated Use {@link koraContextKey} with {@link KoraProvider}. */\nexport const koraAppInjectionKey: InjectionKey<KoraAppLike> = Symbol('korajs-app')\n\nexport function useKoraContext(): KoraContextValue {\n\tconst contextRef = inject(koraContextKey)\n\tif (!contextRef?.value) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraContext() requires <KoraProvider>. Wrap your app root with KoraProvider.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: '<KoraProvider :app=\"app\"><App /></KoraProvider>' },\n\t\t)\n\t}\n\treturn contextRef.value\n}\n","import { QueryStoreCache } from '@korajs/store'\nimport type { Store } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\ttype PropType,\n\ttype VNode,\n\tdefineComponent,\n\th,\n\tonScopeDispose,\n\tprovide,\n\tref,\n\tshallowRef,\n\twatch,\n} from 'vue'\nimport { koraAppInjectionKey, koraContextKey } from '../context'\nimport { resolveQueryStoreCache } from '../resolve-query-store-cache'\nimport type { KoraAppLike, KoraContextValue } from '../types'\n\nexport const KoraProvider = defineComponent({\n\tname: 'KoraProvider',\n\tprops: {\n\t\tapp: {\n\t\t\ttype: Object as PropType<KoraAppLike>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<Store>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tsyncEngine: {\n\t\t\ttype: Object as PropType<SyncEngine | null>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfallback: {\n\t\t\ttype: [Object, String] as PropType<VNode | string | null>,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\tconst resolvedStore = ref<Store | null>(null)\n\t\tconst resolvedSync = ref<SyncEngine | null>(null)\n\t\tconst ready = ref(!props.app && Boolean(props.store))\n\t\tconst initError = ref<Error | null>(null)\n\t\tconst fallbackQueryStoreCache = new QueryStoreCache()\n\t\tconst contextRef = shallowRef<KoraContextValue | null>(null)\n\n\t\tprovide(koraContextKey, contextRef)\n\t\tif (props.app) {\n\t\t\tprovide(koraAppInjectionKey, props.app)\n\t\t}\n\n\t\twatch(\n\t\t\t() => props.app,\n\t\t\t(app, _previous, onCleanup) => {\n\t\t\t\tif (!app) {\n\t\t\t\t\tif (props.store) {\n\t\t\t\t\t\tresolvedStore.value = props.store as Store\n\t\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tready.value = false\n\t\t\t\tinitError.value = null\n\t\t\t\tlet cancelled = false\n\n\t\t\t\tapp.ready\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tresolvedStore.value = app.getStore() as Store\n\t\t\t\t\t\tresolvedSync.value = app.getSyncEngine() as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\t\t\tinitError.value = err\n\t\t\t\t\t})\n\n\t\t\t\tonCleanup(() => {\n\t\t\t\t\tcancelled = true\n\t\t\t\t})\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => props.store,\n\t\t\t(store) => {\n\t\t\t\tif (store && !props.app) {\n\t\t\t\t\tresolvedStore.value = store as Store\n\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\tready.value = true\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => [resolvedStore.value, resolvedSync.value, props.app] as const,\n\t\t\t([store, syncEngine, app]) => {\n\t\t\t\tif (!store) {\n\t\t\t\t\tcontextRef.value = null\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tcontextRef.value = {\n\t\t\t\t\tstore: store as Store,\n\t\t\t\t\tsyncEngine: (syncEngine ?? null) as SyncEngine | null,\n\t\t\t\t\tapp: app ?? null,\n\t\t\t\t\tevents: app?.events ?? null,\n\t\t\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\t\t\tqueryStoreCache: resolveQueryStoreCache(app, fallbackQueryStoreCache),\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\tonScopeDispose(() => {\n\t\t\tif (!props.app) {\n\t\t\t\tfallbackQueryStoreCache.clear()\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tif (initError.value) {\n\t\t\t\treturn h('div', { style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } }, [\n\t\t\t\t\th('strong', null, 'Kora initialization error: '),\n\t\t\t\t\tinitError.value.message,\n\t\t\t\t])\n\t\t\t}\n\n\t\t\tif (!ready.value) {\n\t\t\t\treturn props.fallback ?? null\n\t\t\t}\n\n\t\t\tif (!resolvedStore.value) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. Pass createApp() or a Store instance.',\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn slots.default?.()\n\t\t}\n\t},\n})\n","import type { QueryStoreCache } from '@korajs/store'\nimport type { KoraAppLike } from './types'\n\n/**\n * Resolves the per-app query cache when available, otherwise a provider-local fallback.\n */\nexport function resolveQueryStoreCache(\n\tapp: KoraAppLike | null | undefined,\n\tfallback: QueryStoreCache,\n): QueryStoreCache {\n\tif (app && typeof app.getQueryStoreCache === 'function') {\n\t\treturn app.getQueryStoreCache()\n\t}\n\treturn fallback\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { type DeepReadonly, type ShallowRef, readonly, shallowRef, watch } from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/**\n * Reactive query composable backed by the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): DeepReadonly<ShallowRef<readonly T[]>> {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst snapshot = shallowRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\twatch(\n\t\t() => (enabled ? JSON.stringify(query.getDescriptor()) : null),\n\t\t(key, _previous, onCleanup) => {\n\t\t\tif (!key) {\n\t\t\t\tsnapshot.value = EMPTY_ARRAY as readonly T[]\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tassertQueryReady(query as QueryBuilder<unknown>)\n\t\t\tconst queryStore = queryStoreCache.getOrCreate(query)\n\t\t\tconst unsubscribe = queryStore.subscribe(() => {\n\t\t\t\tsnapshot.value = queryStore.getSnapshot()\n\t\t\t})\n\t\t\tsnapshot.value = queryStore.getSnapshot()\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tqueryStoreCache.release(query as QueryBuilder<unknown>)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\treturn readonly(snapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onScopeDispose, ref, shallowReadonly } from 'vue'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Mutation composable with optional optimistic update and rollback hooks.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst isLoading = ref(false)\n\tconst error = ref<Error | null>(null)\n\tlet mounted = true\n\n\tonScopeDispose(() => {\n\t\tmounted = false\n\t})\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t\tonStateChange: (state) => {\n\t\t\tif (!mounted) return\n\t\t\tisLoading.value = state.isLoading\n\t\t\terror.value = state.error\n\t\t},\n\t})\n\n\tisLoading.value = controller.getSnapshot().isLoading\n\terror.value = controller.getSnapshot().error\n\n\tonScopeDispose(() => {\n\t\tcontroller.destroy()\n\t})\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: shallowReadonly(isLoading),\n\t\terror: shallowReadonly(error),\n\t\treset: () => controller.reset(),\n\t}\n}\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport { onScopeDispose, readonly, shallowRef, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Reactive sync engine status. Updates only when status payload changes.\n */\nexport function useSyncStatus() {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\tconst status = shallowRef(OFFLINE_SYNC_STATUS)\n\n\twatchEffect((onCleanup) => {\n\t\tconst controller = createSyncStatusController({\n\t\t\tsyncEngine,\n\t\t\tsubscribeSyncStatus,\n\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t})\n\t\tstatus.value = controller.getSnapshot()\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tstatus.value = controller.getSnapshot()\n\t\t})\n\t\tonCleanup(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t})\n\n\treturn readonly(status)\n}\n","import { useKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * Returns the typed Kora app from {@link KoraProvider}'s `app` prop.\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires <KoraProvider :app=\"app\">. Pass your createApp() result to the provider.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useKoraContext } from '../context'\n\n/**\n * Returns a collection accessor for the given schema collection name.\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\treturn store.collection(name)\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { reactive, shallowRef, watch } from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseRichTextResult } from '../types'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst controllerRef = shallowRef<ReturnType<typeof createRichTextController> | null>(null)\n\n\tconst state = reactive({\n\t\tready: false,\n\t\terror: null as Error | null,\n\t\tcanUndo: false,\n\t\tcanRedo: false,\n\t\tcursors: [] as UseRichTextResult['cursors'],\n\t})\n\n\twatch(\n\t\t() => [collectionName, recordId, fieldName, options?.useDocChannel] as const,\n\t\t([name, id, field, useDocChannel], _previous, onCleanup) => {\n\t\t\tcontrollerRef.value?.destroy()\n\n\t\t\tconst controller = createRichTextController({\n\t\t\t\tcollection: store.collection(name),\n\t\t\t\tcollectionName: name,\n\t\t\t\trecordId: id,\n\t\t\t\tfieldName: field,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t})\n\n\t\t\tconst syncState = (): void => {\n\t\t\t\tconst snapshot = controller.getSnapshot()\n\t\t\t\tstate.ready = snapshot.ready\n\t\t\t\tstate.error = snapshot.error\n\t\t\t\tstate.canUndo = snapshot.canUndo\n\t\t\t\tstate.canRedo = snapshot.canRedo\n\t\t\t\tstate.cursors = [...snapshot.cursors]\n\t\t\t}\n\n\t\t\tsyncState()\n\t\t\tconst unsubscribe = controller.subscribe(syncState)\n\t\t\tcontrollerRef.value = controller\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tcontroller.destroy()\n\t\t\t\tif (controllerRef.value === controller) {\n\t\t\t\t\tcontrollerRef.value = null\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\twatch(\n\t\t() => options?.user,\n\t\t(user) => {\n\t\t\tcontrollerRef.value?.setUser(user)\n\t\t},\n\t)\n\n\tconst controller = (): NonNullable<typeof controllerRef.value> => {\n\t\tif (!controllerRef.value) {\n\t\t\tthrow new Error('useRichText controller is not initialized')\n\t\t}\n\t\treturn controllerRef.value\n\t}\n\n\treturn {\n\t\tget doc() {\n\t\t\treturn controller().doc\n\t\t},\n\t\tget text() {\n\t\t\treturn controller().text\n\t\t},\n\t\tundo: () => controller().undo(),\n\t\tredo: () => controller().redo(),\n\t\tget ready() {\n\t\t\treturn state.ready\n\t\t},\n\t\tget error() {\n\t\t\treturn state.error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn state.canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn state.canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn state.cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller().setCursor(anchor, head),\n\t\tclearCursor: () => controller().clearCursor(),\n\t}\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type ShallowRef, onScopeDispose, shallowRef, watch, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Sets the local user's collaborative presence state.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\n\twatch(\n\t\t() => [syncEngine, user?.name, user?.color, user?.avatar] as const,\n\t\t([engine, name, color, avatar], _prev, onCleanup) => {\n\t\t\tif (!engine || !name || !color) return\n\n\t\t\tconst awareness = engine.getAwarenessManager()\n\t\t\tawareness.setLocalState({\n\t\t\t\tuser: {\n\t\t\t\t\tname,\n\t\t\t\t\tcolor,\n\t\t\t\t\tavatar,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tonCleanup(() => {\n\t\t\t\tawareness.setLocalState(null)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n}\n\n/**\n * Reactive list of remote collaborators' awareness states.\n */\nexport function useCollaborators(): ShallowRef<AwarenessState[]> {\n\tconst { syncEngine } = useKoraContext()\n\tconst collaborators = shallowRef<AwarenessState[]>([])\n\n\twatchEffect((onCleanup) => {\n\t\tif (!syncEngine) {\n\t\t\tcollaborators.value = []\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst unsubscribe = subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\tcollaborators.value = states\n\t\t})\n\t\tonCleanup(unsubscribe)\n\t})\n\n\tonScopeDispose(() => {\n\t\tcollaborators.value = []\n\t})\n\n\treturn collaborators\n}\n"],"mappings":"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","names":["KoraError","inject","shallowRef","watch","shallowRef","watch","onScopeDispose","ref","readonly","shallowRef","shallowRef","readonly","shallowRef","watch","shallowRef","watch","controller","onScopeDispose","shallowRef","watch","watchEffect","watch","shallowRef","watchEffect","onScopeDispose","inject","KoraError"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/components/kora-provider.ts","../src/resolve-query-store-cache.ts","../src/composables/use-query.ts","../src/composables/use-mutation.ts","../src/composables/use-sync-status.ts","../src/composables/use-app.ts","../src/composables/use-collection.ts","../src/composables/use-rich-text.ts","../src/composables/use-presence.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { type App, inject } from 'vue'\nimport { koraAppInjectionKey } from './context'\nimport type { KoraAppLike } from './types'\n\nexport type { KoraAppHandle, KoraAppLike, KoraContextValue, KoraProviderProps } from './types'\nexport type {\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseQueryOptions,\n\tUseQueryStateResult,\n\tUseRichTextResult,\n} from './types'\n\nexport { koraAppInjectionKey, koraContextKey, useKoraContext } from './context'\nexport { KoraProvider } from './components/kora-provider'\nexport { useQuery, useQueryState } from './composables/use-query'\nexport type { QueryInput } from './composables/use-query'\nexport { useMutation } from './composables/use-mutation'\nexport { useSyncStatus } from './composables/use-sync-status'\nexport { useApp } from './composables/use-app'\nexport { useCollection } from './composables/use-collection'\nexport { useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { usePresence, useCollaborators } from './composables/use-presence'\n\n/**\n * Register a Kora app on a Vue application instance.\n *\n * @deprecated Prefer {@link KoraProvider} — `installKora` does not provide reactive\n * hook context (`useQuery`, `useSyncStatus`, etc.) until you migrate to `KoraProvider`.\n */\nexport function installKora(vueApp: App, koraApp: KoraAppLike): void {\n\tvueApp.provide(koraAppInjectionKey, koraApp)\n}\n\n/**\n * Access the Kora app from a component when using {@link installKora} only.\n * For reactive hooks, use {@link useApp} inside {@link KoraProvider}.\n */\nexport function useKoraApp(): KoraAppLike {\n\tconst app = inject(koraAppInjectionKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraApp() requires installKora(vueApp, koraApp) or <KoraProvider :app=\"app\">.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Use <KoraProvider :app=\"app\"> and useApp() for full bindings.' },\n\t\t)\n\t}\n\treturn app\n}\n","import { KoraError } from '@korajs/core'\nimport { type InjectionKey, type ShallowRef, inject } from 'vue'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\nexport const koraContextKey: InjectionKey<ShallowRef<KoraContextValue | null>> =\n\tSymbol('korajs-context')\n\n/** @deprecated Use {@link koraContextKey} with {@link KoraProvider}. */\nexport const koraAppInjectionKey: InjectionKey<KoraAppLike> = Symbol('korajs-app')\n\nexport function useKoraContext(): KoraContextValue {\n\tconst contextRef = inject(koraContextKey)\n\tif (!contextRef?.value) {\n\t\tthrow new KoraError(\n\t\t\t'useKoraContext() requires <KoraProvider>. Wrap your app root with KoraProvider.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: '<KoraProvider :app=\"app\"><App /></KoraProvider>' },\n\t\t)\n\t}\n\treturn contextRef.value\n}\n","import { QueryStoreCache } from '@korajs/store'\nimport type { Store } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\ttype PropType,\n\ttype VNode,\n\tdefineComponent,\n\th,\n\tonScopeDispose,\n\tprovide,\n\tref,\n\tshallowRef,\n\twatch,\n} from 'vue'\nimport { koraAppInjectionKey, koraContextKey } from '../context'\nimport { resolveQueryStoreCache } from '../resolve-query-store-cache'\nimport type { KoraAppLike, KoraContextValue } from '../types'\n\nexport const KoraProvider = defineComponent({\n\tname: 'KoraProvider',\n\tprops: {\n\t\tapp: {\n\t\t\ttype: Object as PropType<KoraAppLike>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<Store>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tsyncEngine: {\n\t\t\ttype: Object as PropType<SyncEngine | null>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfallback: {\n\t\t\ttype: [Object, String] as PropType<VNode | string | null>,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\tconst resolvedStore = ref<Store | null>(null)\n\t\tconst resolvedSync = ref<SyncEngine | null>(null)\n\t\tconst ready = ref(!props.app && Boolean(props.store))\n\t\tconst initError = ref<Error | null>(null)\n\t\tconst fallbackQueryStoreCache = new QueryStoreCache()\n\t\tconst contextRef = shallowRef<KoraContextValue | null>(null)\n\n\t\tprovide(koraContextKey, contextRef)\n\t\tif (props.app) {\n\t\t\tprovide(koraAppInjectionKey, props.app)\n\t\t}\n\n\t\twatch(\n\t\t\t() => props.app,\n\t\t\t(app, _previous, onCleanup) => {\n\t\t\t\tif (!app) {\n\t\t\t\t\tif (props.store) {\n\t\t\t\t\t\tresolvedStore.value = props.store as Store\n\t\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tready.value = false\n\t\t\t\tinitError.value = null\n\t\t\t\tlet cancelled = false\n\n\t\t\t\tapp.ready\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tresolvedStore.value = app.getStore() as Store\n\t\t\t\t\t\tresolvedSync.value = app.getSyncEngine() as SyncEngine | null\n\t\t\t\t\t\tready.value = true\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (cancelled) return\n\t\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\t\t\tinitError.value = err\n\t\t\t\t\t})\n\n\t\t\t\tonCleanup(() => {\n\t\t\t\t\tcancelled = true\n\t\t\t\t})\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => props.store,\n\t\t\t(store) => {\n\t\t\t\tif (store && !props.app) {\n\t\t\t\t\tresolvedStore.value = store as Store\n\t\t\t\t\tresolvedSync.value = (props.syncEngine ?? null) as SyncEngine | null\n\t\t\t\t\tready.value = true\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\twatch(\n\t\t\t() => [resolvedStore.value, resolvedSync.value, props.app] as const,\n\t\t\t([store, syncEngine, app]) => {\n\t\t\t\tif (!store) {\n\t\t\t\t\tcontextRef.value = null\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tcontextRef.value = {\n\t\t\t\t\tstore: store as Store,\n\t\t\t\t\tsyncEngine: (syncEngine ?? null) as SyncEngine | null,\n\t\t\t\t\tapp: app ?? null,\n\t\t\t\t\tevents: app?.events ?? null,\n\t\t\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\t\t\tqueryStoreCache: resolveQueryStoreCache(app, fallbackQueryStoreCache),\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t)\n\n\t\tonScopeDispose(() => {\n\t\t\tif (!props.app) {\n\t\t\t\tfallbackQueryStoreCache.clear()\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tif (initError.value) {\n\t\t\t\treturn h('div', { style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } }, [\n\t\t\t\t\th('strong', null, 'Kora initialization error: '),\n\t\t\t\t\tinitError.value.message,\n\t\t\t\t])\n\t\t\t}\n\n\t\t\tif (!ready.value) {\n\t\t\t\treturn props.fallback ?? null\n\t\t\t}\n\n\t\t\tif (!resolvedStore.value) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. Pass createApp() or a Store instance.',\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn slots.default?.()\n\t\t}\n\t},\n})\n","import type { QueryStoreCache } from '@korajs/store'\nimport type { KoraAppLike } from './types'\n\n/**\n * Resolves the per-app query cache when available, otherwise a provider-local fallback.\n */\nexport function resolveQueryStoreCache(\n\tapp: KoraAppLike | null | undefined,\n\tfallback: QueryStoreCache,\n): QueryStoreCache {\n\tif (app && typeof app.getQueryStoreCache === 'function') {\n\t\treturn app.getQueryStoreCache()\n\t}\n\treturn fallback\n}\n","import type { CollectionRecord, QueryBuilder, QueryStore } from '@korajs/store'\nimport { assertQueryReady, queryKey } from '@korajs/store'\nimport {\n\ttype DeepReadonly,\n\ttype MaybeRefOrGetter,\n\ttype ShallowRef,\n\treadonly,\n\tshallowRef,\n\ttoValue,\n\twatch,\n} from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseQueryOptions, UseQueryStateResult } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/** A query input: a builder, a ref to one, or a getter (`() => app.todos.where(...)`). */\nexport type QueryInput<T> = MaybeRefOrGetter<QueryBuilder<T> | null | undefined>\n\n/** The STORE-12 error channel of a QueryStore, read structurally (older store builds lack it). */\nfunction readQueryError(queryStore: QueryStore<unknown>): Error | null {\n\tconst channel = queryStore as unknown as { getError?: () => Error | null }\n\treturn typeof channel.getError === 'function' ? channel.getError() : null\n}\n\n/**\n * Shared engine of {@link useQuery} and {@link useQueryState}: tracks the query and\n * `enabled` reactively (refs, getters, props), subscribes to one ref-counted\n * QueryStore per descriptor, and releases it when the descriptor changes or the\n * scope is disposed (DX-7).\n */\nfunction useQuerySubscription<T>(\n\tquery: QueryInput<T>,\n\toptions: UseQueryOptions | undefined,\n): {\n\tdata: ShallowRef<readonly T[]>\n\terror: ShallowRef<Error | null>\n\tready: ShallowRef<boolean>\n} {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst data = shallowRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\tconst error = shallowRef<Error | null>(null)\n\tconst ready = shallowRef(false)\n\n\twatch(\n\t\t() => {\n\t\t\tconst enabled = toValue(options?.enabled) !== false\n\t\t\tconst current = enabled ? toValue(query) : null\n\t\t\treturn current ? queryKey(current.getDescriptor()) : null\n\t\t},\n\t\t(key, _previous, onCleanup) => {\n\t\t\tconst current = key ? toValue(query) : null\n\t\t\tif (!current) {\n\t\t\t\tdata.value = EMPTY_ARRAY as readonly T[]\n\t\t\t\terror.value = null\n\t\t\t\tready.value = false\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tassertQueryReady(current as QueryBuilder<unknown>)\n\t\t\tconst queryStore = queryStoreCache.getOrCreate(current)\n\t\t\tconst sync = (): void => {\n\t\t\t\tconst failure = readQueryError(queryStore as QueryStore<unknown>)\n\t\t\t\tif (failure !== error.value) {\n\t\t\t\t\terror.value = failure\n\t\t\t\t\tif (failure) options?.onError?.(failure)\n\t\t\t\t}\n\t\t\t\tif (queryStore.hasSnapshot()) {\n\t\t\t\t\tdata.value = queryStore.getSnapshot()\n\t\t\t\t\tready.value = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst unsubscribe = queryStore.subscribe(sync)\n\t\t\t// A descriptor switch keeps the previous rows until the new query answers.\n\t\t\tready.value = false\n\t\t\tsync()\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tqueryStoreCache.release(current as QueryBuilder<unknown>)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\treturn { data, error, ready }\n}\n\n/**\n * Reactive query composable backed by the local Kora store.\n *\n * The query and `enabled` may be plain values, refs or getters: pass a getter to\n * follow props or refs, and the composable re-subscribes when the query's descriptor\n * changes (and releases the old subscription). A failed query is reported through\n * `options.onError`, or `console.error` without one; use {@link useQueryState} to\n * render the error.\n *\n * @param query - A query builder, a ref to one, or a getter returning one (null disables)\n * @param options - `enabled` (value, ref or getter; default true) and `onError`\n * @returns A readonly shallow ref of the current rows\n *\n * @example\n * ```ts\n * const props = defineProps<{ done: boolean }>()\n * const todos = useQuery(() => app.todos.where({ completed: props.done }))\n * ```\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): DeepReadonly<ShallowRef<readonly T[]>> {\n\tconst reporting: UseQueryOptions = {\n\t\t...options,\n\t\tonError:\n\t\t\toptions?.onError ??\n\t\t\t((failure: Error) => {\n\t\t\t\t// Never swallowed: without a handler the failure is at least logged.\n\t\t\t\tconsole.error('[Kora] useQuery failed:', failure)\n\t\t\t}),\n\t}\n\treturn readonly(useQuerySubscription(query, reporting).data)\n}\n\n/**\n * Like {@link useQuery}, but also returns the query's error and whether the first\n * result has arrived.\n *\n * @param query - A query builder, a ref to one, or a getter returning one\n * @param options - `enabled` and `onError`\n * @returns `{ data, error, ready }` as readonly refs\n */\nexport function useQueryState<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): UseQueryStateResult<T> {\n\tconst { data, error, ready } = useQuerySubscription(query, options)\n\treturn { data: readonly(data), error: readonly(error), ready: readonly(ready) }\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onScopeDispose, ref, shallowReadonly } from 'vue'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Mutation composable with optional optimistic update and rollback hooks.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst isLoading = ref(false)\n\tconst error = ref<Error | null>(null)\n\tlet mounted = true\n\n\tonScopeDispose(() => {\n\t\tmounted = false\n\t})\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t\tonStateChange: (state) => {\n\t\t\tif (!mounted) return\n\t\t\tisLoading.value = state.isLoading\n\t\t\terror.value = state.error\n\t\t},\n\t})\n\n\tisLoading.value = controller.getSnapshot().isLoading\n\terror.value = controller.getSnapshot().error\n\n\tonScopeDispose(() => {\n\t\tcontroller.destroy()\n\t})\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: shallowReadonly(isLoading),\n\t\terror: shallowReadonly(error),\n\t\treset: () => controller.reset(),\n\t}\n}\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport { onScopeDispose, readonly, shallowRef, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Reactive sync engine status. Updates only when status payload changes.\n */\nexport function useSyncStatus() {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\tconst status = shallowRef(OFFLINE_SYNC_STATUS)\n\n\twatchEffect((onCleanup) => {\n\t\tconst controller = createSyncStatusController({\n\t\t\tsyncEngine,\n\t\t\tsubscribeSyncStatus,\n\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t})\n\t\tstatus.value = controller.getSnapshot()\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tstatus.value = controller.getSnapshot()\n\t\t})\n\t\tonCleanup(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t})\n\n\treturn readonly(status)\n}\n","import { useKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * Returns the typed Kora app from {@link KoraProvider}'s `app` prop.\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires <KoraProvider :app=\"app\">. Pass your createApp() result to the provider.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useKoraContext } from '../context'\n\n/**\n * Returns a collection accessor for the given schema collection name.\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\treturn store.collection(name)\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { reactive, shallowRef, watch } from 'vue'\nimport { useKoraContext } from '../context'\nimport type { UseRichTextResult } from '../types'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst controllerRef = shallowRef<ReturnType<typeof createRichTextController> | null>(null)\n\n\tconst state = reactive({\n\t\tready: false,\n\t\terror: null as Error | null,\n\t\tcanUndo: false,\n\t\tcanRedo: false,\n\t\tcursors: [] as UseRichTextResult['cursors'],\n\t\thasUnsavedChanges: false,\n\t})\n\n\twatch(\n\t\t() => [collectionName, recordId, fieldName, options?.useDocChannel] as const,\n\t\t([name, id, field, useDocChannel], _previous, onCleanup) => {\n\t\t\tcontrollerRef.value?.destroy()\n\n\t\t\tconst controller = createRichTextController({\n\t\t\t\tcollection: store.collection(name),\n\t\t\t\tcollectionName: name,\n\t\t\t\trecordId: id,\n\t\t\t\tfieldName: field,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t})\n\n\t\t\tconst syncState = (): void => {\n\t\t\t\tconst snapshot = controller.getSnapshot()\n\t\t\t\tstate.ready = snapshot.ready\n\t\t\t\tstate.error = snapshot.error\n\t\t\t\tstate.canUndo = snapshot.canUndo\n\t\t\t\tstate.canRedo = snapshot.canRedo\n\t\t\t\tstate.cursors = [...snapshot.cursors]\n\t\t\t\tstate.hasUnsavedChanges = snapshot.hasUnsavedChanges\n\t\t\t}\n\n\t\t\tsyncState()\n\t\t\tconst unsubscribe = controller.subscribe(syncState)\n\t\t\tcontrollerRef.value = controller\n\n\t\t\tonCleanup(() => {\n\t\t\t\tunsubscribe()\n\t\t\t\tcontroller.destroy()\n\t\t\t\tif (controllerRef.value === controller) {\n\t\t\t\t\tcontrollerRef.value = null\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n\n\twatch(\n\t\t() => options?.user,\n\t\t(user) => {\n\t\t\tcontrollerRef.value?.setUser(user)\n\t\t},\n\t)\n\n\tconst controller = (): NonNullable<typeof controllerRef.value> => {\n\t\tif (!controllerRef.value) {\n\t\t\tthrow new Error('useRichText controller is not initialized')\n\t\t}\n\t\treturn controllerRef.value\n\t}\n\n\treturn {\n\t\tget doc() {\n\t\t\treturn controller().doc\n\t\t},\n\t\tget text() {\n\t\t\treturn controller().text\n\t\t},\n\t\tundo: () => controller().undo(),\n\t\tredo: () => controller().redo(),\n\t\tget ready() {\n\t\t\treturn state.ready\n\t\t},\n\t\tget error() {\n\t\t\treturn state.error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn state.canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn state.canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn state.cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller().setCursor(anchor, head),\n\t\tclearCursor: () => controller().clearCursor(),\n\t\tget hasUnsavedChanges() {\n\t\t\treturn state.hasUnsavedChanges\n\t\t},\n\t\tretrySave: () => controller().retrySave(),\n\t\tgetUnsavedState: () => controller().getUnsavedState(),\n\t}\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type ShallowRef, onScopeDispose, shallowRef, watch, watchEffect } from 'vue'\nimport { useKoraContext } from '../context'\n\n/**\n * Sets the local user's collaborative presence state.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\n\twatch(\n\t\t() => [syncEngine, user?.name, user?.color, user?.avatar] as const,\n\t\t([engine, name, color, avatar], _prev, onCleanup) => {\n\t\t\tif (!engine || !name || !color) return\n\n\t\t\tconst awareness = engine.getAwarenessManager()\n\t\t\tawareness.setLocalState({\n\t\t\t\tuser: {\n\t\t\t\t\tname,\n\t\t\t\t\tcolor,\n\t\t\t\t\tavatar,\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tonCleanup(() => {\n\t\t\t\tawareness.setLocalState(null)\n\t\t\t})\n\t\t},\n\t\t{ immediate: true },\n\t)\n}\n\n/**\n * Reactive list of remote collaborators' awareness states.\n */\nexport function useCollaborators(): ShallowRef<AwarenessState[]> {\n\tconst { syncEngine } = useKoraContext()\n\tconst collaborators = shallowRef<AwarenessState[]>([])\n\n\twatchEffect((onCleanup) => {\n\t\tif (!syncEngine) {\n\t\t\tcollaborators.value = []\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst unsubscribe = subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\tcollaborators.value = states\n\t\t})\n\t\tonCleanup(unsubscribe)\n\t})\n\n\tonScopeDispose(() => {\n\t\tcollaborators.value = []\n\t})\n\n\treturn collaborators\n}\n"],"mappings":"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","names":["KoraError","inject","shallowRef","watch","shallowRef","watch","onScopeDispose","ref","readonly","shallowRef","shallowRef","readonly","shallowRef","watch","shallowRef","watch","controller","onScopeDispose","shallowRef","watch","watchEffect","watch","shallowRef","watchEffect","onScopeDispose","inject","KoraError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korajs/vue",
3
- "version": "1.0.0-beta.12",
3
+ "version": "1.0.0-beta.14",
4
4
  "description": "Kora.js Vue 3 composables for offline-first applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "yjs": "^13.6.30",
30
- "@korajs/core": "1.0.0-beta.12",
31
- "@korajs/store": "1.0.0-beta.12",
32
- "@korajs/sync": "1.0.0-beta.12"
30
+ "@korajs/core": "1.0.0-beta.14",
31
+ "@korajs/sync": "1.0.0-beta.14",
32
+ "@korajs/store": "1.0.0-beta.14"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@vue/test-utils": "^2.4.6",