@korajs/svelte 1.0.0-beta.13 → 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/dist/index.cjs CHANGED
@@ -361,6 +361,11 @@ function createRichTextBinding(collectionName, recordId, fieldName, options) {
361
361
  },
362
362
  setCursor: (anchor, head) => controller.setCursor(anchor, head),
363
363
  clearCursor: () => controller.clearCursor(),
364
+ get hasUnsavedChanges() {
365
+ return (0, import_store6.get)(resultStore).hasUnsavedChanges;
366
+ },
367
+ retrySave: () => controller.retrySave(),
368
+ getUnsavedState: () => controller.getUnsavedState(),
364
369
  subscribe: resultStore.subscribe
365
370
  };
366
371
  }
@@ -378,7 +383,10 @@ function buildResult(controller) {
378
383
  canRedo: snapshot.canRedo,
379
384
  cursors: [...snapshot.cursors],
380
385
  setCursor: (anchor, head) => controller.setCursor(anchor, head),
381
- clearCursor: () => controller.clearCursor()
386
+ clearCursor: () => controller.clearCursor(),
387
+ hasUnsavedChanges: snapshot.hasUnsavedChanges,
388
+ retrySave: () => controller.retrySave(),
389
+ getUnsavedState: () => controller.getUnsavedState()
382
390
  };
383
391
  }
384
392
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/stores/query-store.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","../src/composables/use-collaborators.ts"],"sourcesContent":["export type {\n\tKoraAppHandle,\n\tKoraAppLike,\n\tKoraContextValue,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tQueryState,\n\tUseQueryOptions,\n\tUseRichTextResult,\n} from './types'\n\nexport {\n\tgetKoraApp,\n\tgetKoraContext,\n\tinitKoraProvider,\n\tsetKoraAppContext,\n\tsetKoraContext,\n} from './context'\n\nexport {\n\tcreateQueryStateStore,\n\tcreateQueryStore,\n\tuseQuery,\n\tuseQueryState,\n} from './stores/query-store'\nexport type { QueryInput } from './stores/query-store'\nexport { createMutation, useMutation } from './composables/use-mutation'\nexport { createSyncStatusStore, useSyncStatus } from './composables/use-sync-status'\nexport { getApp, useApp } from './composables/use-app'\nexport { getCollection, useCollection } from './composables/use-collection'\nexport { createRichTextBinding, useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { applyPresence, usePresence } from './composables/use-presence'\nexport { createCollaboratorsStore, useCollaborators } from './composables/use-collaborators'\n","import { KoraError } from '@korajs/core'\nimport { QueryStoreCache } from '@korajs/store'\nimport { getContext, setContext } from 'svelte'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\n// Registered (Symbol.for) keys: the .svelte components are compiled from src/ by the app\n// (the \"svelte\" export condition) while helpers such as getCollection come from dist/, so\n// two copies of this module exist in every app. Module-local Symbol() keys made the\n// provider's context invisible to the helpers (\"Kora context missing\").\nconst koraContextKey = Symbol.for('@korajs/svelte:context')\nconst koraAppContextKey = Symbol.for('@korajs/svelte:app')\n\nexport function setKoraContext(value: KoraContextValue): void {\n\tsetContext(koraContextKey, value)\n}\n\nexport function getKoraContext(): KoraContextValue {\n\tconst context = getContext<KoraContextValue | undefined>(koraContextKey)\n\tif (!context) {\n\t\tthrow new KoraError(\n\t\t\t'Kora context missing. Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.' },\n\t\t)\n\t}\n\treturn context\n}\n\n/** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */\nexport function setKoraAppContext(koraApp: KoraAppLike): void {\n\tsetContext(koraAppContextKey, koraApp)\n}\n\n/** @deprecated Use {@link getKoraContext} and {@link getApp}. */\nexport function getKoraApp(): KoraAppLike {\n\tconst app = getContext<KoraAppLike | undefined>(koraAppContextKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'getKoraApp() requires setKoraAppContext(koraApp) on an ancestor.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t)\n\t}\n\treturn app\n}\n\n/**\n * Initialize Kora provider context after `app.ready`.\n *\n * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.\n */\nexport async function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue> {\n\tawait app.ready\n\tconst queryStoreCache =\n\t\ttypeof app.getQueryStoreCache === 'function' ? app.getQueryStoreCache() : new QueryStoreCache()\n\tconst value: KoraContextValue = {\n\t\tstore: app.getStore(),\n\t\tsyncEngine: app.getSyncEngine(),\n\t\tapp,\n\t\tevents: app.events ?? null,\n\t\tsubscribeSyncStatus: app.sync?.subscribeStatus ?? null,\n\t\tqueryStoreCache,\n\t}\n\tsetKoraContext(value)\n\tsetKoraAppContext(app)\n\treturn value\n}\n","import type { CollectionRecord, QueryBuilder, QueryStore, QueryStoreCache } from '@korajs/store'\nimport { assertQueryReady, queryKey } from '@korajs/store'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\nimport type { QueryState, UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/** A query input: a builder, or a readable store of one (null disables). */\nexport type QueryInput<T> = QueryBuilder<T> | Readable<QueryBuilder<T> | null | undefined>\n\nfunction isQueryBuilder<T>(input: QueryInput<T>): input is QueryBuilder<T> {\n\treturn typeof (input as { getDescriptor?: unknown }).getDescriptor === 'function'\n}\n\nfunction isReadable<V>(input: V | Readable<V>): input is Readable<V> {\n\treturn (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\ttypeof (input as { subscribe?: unknown }).subscribe === 'function'\n\t)\n}\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 * Follows the query and `enabled` inputs (values or readable stores), holding one\n * ref-counted QueryStore per descriptor and switching when the descriptor changes\n * (DX-7). Returns the teardown.\n */\nfunction followQuery<T>(\n\tcache: QueryStoreCache,\n\tquery: QueryInput<T>,\n\toptions: UseQueryOptions | undefined,\n\temit: (state: QueryState<T>) => void,\n): () => void {\n\tlet current: QueryBuilder<T> | null = isQueryBuilder(query) ? query : null\n\tconst enabledInput = options?.enabled\n\tlet enabled = isReadable(enabledInput) ? true : enabledInput !== false\n\tlet activeKey: string | null = null\n\tlet release: (() => void) | null = null\n\tlet state: QueryState<T> = {\n\t\tdata: EMPTY_ARRAY as readonly T[],\n\t\terror: null,\n\t\tready: false,\n\t}\n\n\tconst publish = (next: QueryState<T>): void => {\n\t\tif (next.data === state.data && next.error === state.error && next.ready === state.ready) {\n\t\t\treturn\n\t\t}\n\t\tif (next.error && next.error !== state.error) options?.onError?.(next.error)\n\t\tstate = next\n\t\temit(state)\n\t}\n\n\tconst apply = (): void => {\n\t\tconst key = enabled && current ? queryKey(current.getDescriptor()) : null\n\t\tif (key === activeKey) return\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = key\n\t\tif (!key || !current) {\n\t\t\tpublish({ data: EMPTY_ARRAY as readonly T[], error: null, ready: false })\n\t\t\treturn\n\t\t}\n\t\tconst builder = current\n\t\tassertQueryReady(builder as QueryBuilder<unknown>)\n\t\tconst queryStore = cache.getOrCreate(builder)\n\t\tconst sync = (): void => {\n\t\t\tconst loaded = queryStore.hasSnapshot()\n\t\t\tpublish({\n\t\t\t\t// A descriptor switch keeps the previous rows until the new query answers.\n\t\t\t\tdata: loaded ? queryStore.getSnapshot() : state.data,\n\t\t\t\terror: readQueryError(queryStore as QueryStore<unknown>),\n\t\t\t\tready: loaded,\n\t\t\t})\n\t\t}\n\t\tconst unsubscribe = queryStore.subscribe(sync)\n\t\tsync()\n\t\trelease = () => {\n\t\t\tunsubscribe()\n\t\t\tcache.release(builder as QueryBuilder<unknown>)\n\t\t}\n\t}\n\n\tconst stops: Array<() => void> = []\n\tif (!isQueryBuilder(query)) {\n\t\tstops.push(\n\t\t\tquery.subscribe((next) => {\n\t\t\t\tcurrent = next ?? null\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tif (isReadable(enabledInput)) {\n\t\tstops.push(\n\t\t\tenabledInput.subscribe((next) => {\n\t\t\t\tenabled = next !== false\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tapply()\n\n\treturn () => {\n\t\tfor (const stop of stops) stop()\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = null\n\t}\n}\n\n/**\n * Create a Svelte readable store of a Kora query's rows.\n *\n * The query and `enabled` may be plain values or readable stores: pass a store (for\n * example a `derived` of your filter) and the rows follow it, re-subscribing when the\n * query's descriptor changes. A failed query is reported through `options.onError`,\n * or `console.error` without one; use {@link createQueryStateStore} to render it.\n *\n * @param query - A query builder, or a readable store of one (null disables)\n * @param options - `enabled` (value or readable store; default true) and `onError`\n * @returns A readable store of the current rows\n *\n * @example\n * ```ts\n * const filter = writable(false)\n * const todos = createQueryStore(derived(filter, (done) => app.todos.where({ completed: done })))\n * ```\n */\nexport function createQueryStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<readonly T[]> {\n\tconst { queryStoreCache } = getKoraContext()\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\treportUnhandled(failure)\n\t\t\t}),\n\t}\n\treturn readable<readonly T[]>(EMPTY_ARRAY as readonly T[], (set) =>\n\t\tfollowQuery(queryStoreCache, query, reporting, (state) => set(state.data)),\n\t)\n}\n\n/**\n * Like {@link createQueryStore}, but the store holds `{ data, error, ready }`.\n *\n * @param query - A query builder, or a readable store of one\n * @param options - `enabled` and `onError`\n * @returns A readable store of the query state\n */\nexport function createQueryStateStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<QueryState<T>> {\n\tconst { queryStoreCache } = getKoraContext()\n\tconst initial: QueryState<T> = { data: EMPTY_ARRAY as readonly T[], error: null, ready: false }\n\treturn readable<QueryState<T>>(initial, (set) =>\n\t\tfollowQuery(queryStoreCache, query, options, set),\n\t)\n}\n\n/**\n * Logs a query failure nobody handles. Read through globalThis because this package\n * builds without DOM or Node typings.\n */\nfunction reportUnhandled(failure: Error): void {\n\tconst host = globalThis as { console?: { error(...args: unknown[]): void } }\n\thost.console?.error('[Kora] createQueryStore failed:', failure)\n}\n\n/** Alias for {@link createQueryStore}. */\nexport const useQuery = createQueryStore\n\n/** Alias for {@link createQueryStateStore}. */\nexport const useQueryState = createQueryStateStore\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onDestroy } from 'svelte'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Create a mutation controller with optimistic update hooks.\n */\nexport function createMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t})\n\n\tconst loadingListeners = new Set<(value: boolean) => void>()\n\tconst errorListeners = new Set<(value: Error | null) => void>()\n\n\tconst unsubscribe = controller.subscribe(() => {\n\t\tconst snapshot = controller.getSnapshot()\n\t\tfor (const listener of loadingListeners) {\n\t\t\tlistener(snapshot.isLoading)\n\t\t}\n\t\tfor (const listener of errorListeners) {\n\t\t\tlistener(snapshot.error)\n\t\t}\n\t})\n\n\t// Dispose the controller when the owning component unmounts, matching the\n\t// React (`useController`) and Vue (`onScopeDispose`) lifecycles. Guarded so\n\t// `createMutation()` can still be called outside a component (manual usage),\n\t// where `onDestroy` is unavailable and the caller owns disposal.\n\ttry {\n\t\tonDestroy(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t} catch {\n\t\t// Not inside a component initialization — no lifecycle to hook into.\n\t}\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tsubscribeLoading: (fn) => {\n\t\t\tloadingListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().isLoading)\n\t\t\treturn () => loadingListeners.delete(fn)\n\t\t},\n\t\tsubscribeError: (fn) => {\n\t\t\terrorListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().error)\n\t\t\treturn () => errorListeners.delete(fn)\n\t\t},\n\t\tget loading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget isLoading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget error() {\n\t\t\treturn controller.getSnapshot().error\n\t\t},\n\t\treset: () => controller.reset(),\n\t}\n}\n\n/** Alias for {@link createMutation}. */\nexport const useMutation = createMutation\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of sync engine status.\n */\nexport function createSyncStatusStore(): Readable<SyncStatusInfo> {\n\tconst { syncEngine, subscribeSyncStatus, events } = getKoraContext()\n\n\treturn readable<SyncStatusInfo>(OFFLINE_SYNC_STATUS, (set) => {\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\tset(controller.getSnapshot())\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tset(controller.getSnapshot())\n\t\t})\n\t\treturn () => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t}\n\t})\n}\n\n/** Alias for {@link createSyncStatusStore}. */\nexport const useSyncStatus = createSyncStatusStore\n","import { getKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\nexport function getApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = getKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'getApp() requires <KoraProvider app={kora}> or <KoraStoreProvider store={store}> with a createApp() instance.',\n\t\t)\n\t}\n\treturn app as T\n}\n\n/** Alias for {@link getApp}. */\nexport const useApp = getApp\n","import type { CollectionAccessor } from '@korajs/store'\nimport { getKoraContext } from '../context'\n\nexport function getCollection(name: string): CollectionAccessor {\n\tconst { store } = getKoraContext()\n\treturn store.collection(name)\n}\n\n/** Alias for {@link getCollection}. */\nexport const useCollection = getCollection\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { onDestroy } from 'svelte'\nimport { type Readable, get, readable } from 'svelte/store'\nimport { getKoraContext } 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 *\n * Must be called during component initialization. For reactive target changes,\n * use {@link KoraRichText} instead.\n */\nexport function createRichTextBinding(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult & { subscribe: Readable<UseRichTextResult>['subscribe'] } {\n\tconst { store, syncEngine } = getKoraContext()\n\n\tconst controller = createRichTextController({\n\t\tcollection: store.collection(collectionName),\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\tuseDocChannel: options?.useDocChannel,\n\t\tuser: options?.user,\n\t})\n\n\tonDestroy(() => {\n\t\tcontroller.destroy()\n\t})\n\n\tconst resultStore = readable<UseRichTextResult>(buildResult(controller), (set) => {\n\t\tconst sync = (): void => {\n\t\t\tset(buildResult(controller))\n\t\t}\n\t\tsync()\n\t\treturn controller.subscribe(sync)\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 get(resultStore).ready\n\t\t},\n\t\tget error() {\n\t\t\treturn get(resultStore).error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn get(resultStore).canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn get(resultStore).canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn get(resultStore).cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t\tsubscribe: resultStore.subscribe,\n\t}\n}\n\n/** @alias createRichTextBinding */\nexport const useRichText = createRichTextBinding\n\nfunction buildResult(controller: ReturnType<typeof createRichTextController>): UseRichTextResult {\n\tconst snapshot = controller.getSnapshot()\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo: () => controller.undo(),\n\t\tredo: () => controller.redo(),\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor: (anchor, head) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t}\n}\n","import { getKoraContext } from '../context'\n\n/**\n * Applies local collaborative presence. Returns a cleanup function.\n *\n * In Svelte components, call from an effect:\n * `$effect(() => applyPresence(user))`\n */\nexport function applyPresence(\n\tuser: { name: string; color: string; avatar?: string } | null,\n): () => void {\n\tconst { syncEngine } = getKoraContext()\n\tif (!syncEngine || !user?.name || !user?.color) {\n\t\treturn () => {}\n\t}\n\n\tconst awareness = syncEngine.getAwarenessManager()\n\tawareness.setLocalState({\n\t\tuser: {\n\t\t\tname: user.name,\n\t\t\tcolor: user.color,\n\t\t\tavatar: user.avatar,\n\t\t},\n\t})\n\n\treturn () => {\n\t\tawareness.setLocalState(null)\n\t}\n}\n\n/** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */\nexport const usePresence = applyPresence\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of remote collaborators' awareness states.\n */\nexport function createCollaboratorsStore(): Readable<AwarenessState[]> {\n\tconst { syncEngine } = getKoraContext()\n\n\treturn readable<AwarenessState[]>([], (set) => {\n\t\tif (!syncEngine) {\n\t\t\tset([])\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\treturn subscribeRemoteAwarenessStates(awareness, set)\n\t})\n}\n\n/** Alias for {@link createCollaboratorsStore}. */\nexport const useCollaborators = createCollaboratorsStore\n"],"mappings":"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","names":["import_store","import_svelte","import_store","import_store","import_svelte","import_sync","import_store"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/stores/query-store.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","../src/composables/use-collaborators.ts"],"sourcesContent":["export type {\n\tKoraAppHandle,\n\tKoraAppLike,\n\tKoraContextValue,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tQueryState,\n\tUseQueryOptions,\n\tUseRichTextResult,\n} from './types'\n\nexport {\n\tgetKoraApp,\n\tgetKoraContext,\n\tinitKoraProvider,\n\tsetKoraAppContext,\n\tsetKoraContext,\n} from './context'\n\nexport {\n\tcreateQueryStateStore,\n\tcreateQueryStore,\n\tuseQuery,\n\tuseQueryState,\n} from './stores/query-store'\nexport type { QueryInput } from './stores/query-store'\nexport { createMutation, useMutation } from './composables/use-mutation'\nexport { createSyncStatusStore, useSyncStatus } from './composables/use-sync-status'\nexport { getApp, useApp } from './composables/use-app'\nexport { getCollection, useCollection } from './composables/use-collection'\nexport { createRichTextBinding, useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { applyPresence, usePresence } from './composables/use-presence'\nexport { createCollaboratorsStore, useCollaborators } from './composables/use-collaborators'\n","import { KoraError } from '@korajs/core'\nimport { QueryStoreCache } from '@korajs/store'\nimport { getContext, setContext } from 'svelte'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\n// Registered (Symbol.for) keys: the .svelte components are compiled from src/ by the app\n// (the \"svelte\" export condition) while helpers such as getCollection come from dist/, so\n// two copies of this module exist in every app. Module-local Symbol() keys made the\n// provider's context invisible to the helpers (\"Kora context missing\").\nconst koraContextKey = Symbol.for('@korajs/svelte:context')\nconst koraAppContextKey = Symbol.for('@korajs/svelte:app')\n\nexport function setKoraContext(value: KoraContextValue): void {\n\tsetContext(koraContextKey, value)\n}\n\nexport function getKoraContext(): KoraContextValue {\n\tconst context = getContext<KoraContextValue | undefined>(koraContextKey)\n\tif (!context) {\n\t\tthrow new KoraError(\n\t\t\t'Kora context missing. Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.' },\n\t\t)\n\t}\n\treturn context\n}\n\n/** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */\nexport function setKoraAppContext(koraApp: KoraAppLike): void {\n\tsetContext(koraAppContextKey, koraApp)\n}\n\n/** @deprecated Use {@link getKoraContext} and {@link getApp}. */\nexport function getKoraApp(): KoraAppLike {\n\tconst app = getContext<KoraAppLike | undefined>(koraAppContextKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'getKoraApp() requires setKoraAppContext(koraApp) on an ancestor.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t)\n\t}\n\treturn app\n}\n\n/**\n * Initialize Kora provider context after `app.ready`.\n *\n * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.\n */\nexport async function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue> {\n\tawait app.ready\n\tconst queryStoreCache =\n\t\ttypeof app.getQueryStoreCache === 'function' ? app.getQueryStoreCache() : new QueryStoreCache()\n\tconst value: KoraContextValue = {\n\t\tstore: app.getStore(),\n\t\tsyncEngine: app.getSyncEngine(),\n\t\tapp,\n\t\tevents: app.events ?? null,\n\t\tsubscribeSyncStatus: app.sync?.subscribeStatus ?? null,\n\t\tqueryStoreCache,\n\t}\n\tsetKoraContext(value)\n\tsetKoraAppContext(app)\n\treturn value\n}\n","import type { CollectionRecord, QueryBuilder, QueryStore, QueryStoreCache } from '@korajs/store'\nimport { assertQueryReady, queryKey } from '@korajs/store'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\nimport type { QueryState, UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/** A query input: a builder, or a readable store of one (null disables). */\nexport type QueryInput<T> = QueryBuilder<T> | Readable<QueryBuilder<T> | null | undefined>\n\nfunction isQueryBuilder<T>(input: QueryInput<T>): input is QueryBuilder<T> {\n\treturn typeof (input as { getDescriptor?: unknown }).getDescriptor === 'function'\n}\n\nfunction isReadable<V>(input: V | Readable<V>): input is Readable<V> {\n\treturn (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\ttypeof (input as { subscribe?: unknown }).subscribe === 'function'\n\t)\n}\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 * Follows the query and `enabled` inputs (values or readable stores), holding one\n * ref-counted QueryStore per descriptor and switching when the descriptor changes\n * (DX-7). Returns the teardown.\n */\nfunction followQuery<T>(\n\tcache: QueryStoreCache,\n\tquery: QueryInput<T>,\n\toptions: UseQueryOptions | undefined,\n\temit: (state: QueryState<T>) => void,\n): () => void {\n\tlet current: QueryBuilder<T> | null = isQueryBuilder(query) ? query : null\n\tconst enabledInput = options?.enabled\n\tlet enabled = isReadable(enabledInput) ? true : enabledInput !== false\n\tlet activeKey: string | null = null\n\tlet release: (() => void) | null = null\n\tlet state: QueryState<T> = {\n\t\tdata: EMPTY_ARRAY as readonly T[],\n\t\terror: null,\n\t\tready: false,\n\t}\n\n\tconst publish = (next: QueryState<T>): void => {\n\t\tif (next.data === state.data && next.error === state.error && next.ready === state.ready) {\n\t\t\treturn\n\t\t}\n\t\tif (next.error && next.error !== state.error) options?.onError?.(next.error)\n\t\tstate = next\n\t\temit(state)\n\t}\n\n\tconst apply = (): void => {\n\t\tconst key = enabled && current ? queryKey(current.getDescriptor()) : null\n\t\tif (key === activeKey) return\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = key\n\t\tif (!key || !current) {\n\t\t\tpublish({ data: EMPTY_ARRAY as readonly T[], error: null, ready: false })\n\t\t\treturn\n\t\t}\n\t\tconst builder = current\n\t\tassertQueryReady(builder as QueryBuilder<unknown>)\n\t\tconst queryStore = cache.getOrCreate(builder)\n\t\tconst sync = (): void => {\n\t\t\tconst loaded = queryStore.hasSnapshot()\n\t\t\tpublish({\n\t\t\t\t// A descriptor switch keeps the previous rows until the new query answers.\n\t\t\t\tdata: loaded ? queryStore.getSnapshot() : state.data,\n\t\t\t\terror: readQueryError(queryStore as QueryStore<unknown>),\n\t\t\t\tready: loaded,\n\t\t\t})\n\t\t}\n\t\tconst unsubscribe = queryStore.subscribe(sync)\n\t\tsync()\n\t\trelease = () => {\n\t\t\tunsubscribe()\n\t\t\tcache.release(builder as QueryBuilder<unknown>)\n\t\t}\n\t}\n\n\tconst stops: Array<() => void> = []\n\tif (!isQueryBuilder(query)) {\n\t\tstops.push(\n\t\t\tquery.subscribe((next) => {\n\t\t\t\tcurrent = next ?? null\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tif (isReadable(enabledInput)) {\n\t\tstops.push(\n\t\t\tenabledInput.subscribe((next) => {\n\t\t\t\tenabled = next !== false\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tapply()\n\n\treturn () => {\n\t\tfor (const stop of stops) stop()\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = null\n\t}\n}\n\n/**\n * Create a Svelte readable store of a Kora query's rows.\n *\n * The query and `enabled` may be plain values or readable stores: pass a store (for\n * example a `derived` of your filter) and the rows follow it, re-subscribing when the\n * query's descriptor changes. A failed query is reported through `options.onError`,\n * or `console.error` without one; use {@link createQueryStateStore} to render it.\n *\n * @param query - A query builder, or a readable store of one (null disables)\n * @param options - `enabled` (value or readable store; default true) and `onError`\n * @returns A readable store of the current rows\n *\n * @example\n * ```ts\n * const filter = writable(false)\n * const todos = createQueryStore(derived(filter, (done) => app.todos.where({ completed: done })))\n * ```\n */\nexport function createQueryStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<readonly T[]> {\n\tconst { queryStoreCache } = getKoraContext()\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\treportUnhandled(failure)\n\t\t\t}),\n\t}\n\treturn readable<readonly T[]>(EMPTY_ARRAY as readonly T[], (set) =>\n\t\tfollowQuery(queryStoreCache, query, reporting, (state) => set(state.data)),\n\t)\n}\n\n/**\n * Like {@link createQueryStore}, but the store holds `{ data, error, ready }`.\n *\n * @param query - A query builder, or a readable store of one\n * @param options - `enabled` and `onError`\n * @returns A readable store of the query state\n */\nexport function createQueryStateStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<QueryState<T>> {\n\tconst { queryStoreCache } = getKoraContext()\n\tconst initial: QueryState<T> = { data: EMPTY_ARRAY as readonly T[], error: null, ready: false }\n\treturn readable<QueryState<T>>(initial, (set) =>\n\t\tfollowQuery(queryStoreCache, query, options, set),\n\t)\n}\n\n/**\n * Logs a query failure nobody handles. Read through globalThis because this package\n * builds without DOM or Node typings.\n */\nfunction reportUnhandled(failure: Error): void {\n\tconst host = globalThis as { console?: { error(...args: unknown[]): void } }\n\thost.console?.error('[Kora] createQueryStore failed:', failure)\n}\n\n/** Alias for {@link createQueryStore}. */\nexport const useQuery = createQueryStore\n\n/** Alias for {@link createQueryStateStore}. */\nexport const useQueryState = createQueryStateStore\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onDestroy } from 'svelte'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Create a mutation controller with optimistic update hooks.\n */\nexport function createMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t})\n\n\tconst loadingListeners = new Set<(value: boolean) => void>()\n\tconst errorListeners = new Set<(value: Error | null) => void>()\n\n\tconst unsubscribe = controller.subscribe(() => {\n\t\tconst snapshot = controller.getSnapshot()\n\t\tfor (const listener of loadingListeners) {\n\t\t\tlistener(snapshot.isLoading)\n\t\t}\n\t\tfor (const listener of errorListeners) {\n\t\t\tlistener(snapshot.error)\n\t\t}\n\t})\n\n\t// Dispose the controller when the owning component unmounts, matching the\n\t// React (`useController`) and Vue (`onScopeDispose`) lifecycles. Guarded so\n\t// `createMutation()` can still be called outside a component (manual usage),\n\t// where `onDestroy` is unavailable and the caller owns disposal.\n\ttry {\n\t\tonDestroy(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t} catch {\n\t\t// Not inside a component initialization — no lifecycle to hook into.\n\t}\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tsubscribeLoading: (fn) => {\n\t\t\tloadingListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().isLoading)\n\t\t\treturn () => loadingListeners.delete(fn)\n\t\t},\n\t\tsubscribeError: (fn) => {\n\t\t\terrorListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().error)\n\t\t\treturn () => errorListeners.delete(fn)\n\t\t},\n\t\tget loading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget isLoading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget error() {\n\t\t\treturn controller.getSnapshot().error\n\t\t},\n\t\treset: () => controller.reset(),\n\t}\n}\n\n/** Alias for {@link createMutation}. */\nexport const useMutation = createMutation\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of sync engine status.\n */\nexport function createSyncStatusStore(): Readable<SyncStatusInfo> {\n\tconst { syncEngine, subscribeSyncStatus, events } = getKoraContext()\n\n\treturn readable<SyncStatusInfo>(OFFLINE_SYNC_STATUS, (set) => {\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\tset(controller.getSnapshot())\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tset(controller.getSnapshot())\n\t\t})\n\t\treturn () => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t}\n\t})\n}\n\n/** Alias for {@link createSyncStatusStore}. */\nexport const useSyncStatus = createSyncStatusStore\n","import { getKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\nexport function getApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = getKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'getApp() requires <KoraProvider app={kora}> or <KoraStoreProvider store={store}> with a createApp() instance.',\n\t\t)\n\t}\n\treturn app as T\n}\n\n/** Alias for {@link getApp}. */\nexport const useApp = getApp\n","import type { CollectionAccessor } from '@korajs/store'\nimport { getKoraContext } from '../context'\n\nexport function getCollection(name: string): CollectionAccessor {\n\tconst { store } = getKoraContext()\n\treturn store.collection(name)\n}\n\n/** Alias for {@link getCollection}. */\nexport const useCollection = getCollection\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { onDestroy } from 'svelte'\nimport { type Readable, get, readable } from 'svelte/store'\nimport { getKoraContext } 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 *\n * Must be called during component initialization. For reactive target changes,\n * use {@link KoraRichText} instead.\n */\nexport function createRichTextBinding(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult & { subscribe: Readable<UseRichTextResult>['subscribe'] } {\n\tconst { store, syncEngine } = getKoraContext()\n\n\tconst controller = createRichTextController({\n\t\tcollection: store.collection(collectionName),\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\tuseDocChannel: options?.useDocChannel,\n\t\tuser: options?.user,\n\t})\n\n\tonDestroy(() => {\n\t\tcontroller.destroy()\n\t})\n\n\tconst resultStore = readable<UseRichTextResult>(buildResult(controller), (set) => {\n\t\tconst sync = (): void => {\n\t\t\tset(buildResult(controller))\n\t\t}\n\t\tsync()\n\t\treturn controller.subscribe(sync)\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 get(resultStore).ready\n\t\t},\n\t\tget error() {\n\t\t\treturn get(resultStore).error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn get(resultStore).canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn get(resultStore).canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn get(resultStore).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 get(resultStore).hasUnsavedChanges\n\t\t},\n\t\tretrySave: () => controller.retrySave(),\n\t\tgetUnsavedState: () => controller.getUnsavedState(),\n\t\tsubscribe: resultStore.subscribe,\n\t}\n}\n\n/** @alias createRichTextBinding */\nexport const useRichText = createRichTextBinding\n\nfunction buildResult(controller: ReturnType<typeof createRichTextController>): UseRichTextResult {\n\tconst snapshot = controller.getSnapshot()\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo: () => controller.undo(),\n\t\tredo: () => controller.redo(),\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor: (anchor, head) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t\thasUnsavedChanges: snapshot.hasUnsavedChanges,\n\t\tretrySave: () => controller.retrySave(),\n\t\tgetUnsavedState: () => controller.getUnsavedState(),\n\t}\n}\n","import { getKoraContext } from '../context'\n\n/**\n * Applies local collaborative presence. Returns a cleanup function.\n *\n * In Svelte components, call from an effect:\n * `$effect(() => applyPresence(user))`\n */\nexport function applyPresence(\n\tuser: { name: string; color: string; avatar?: string } | null,\n): () => void {\n\tconst { syncEngine } = getKoraContext()\n\tif (!syncEngine || !user?.name || !user?.color) {\n\t\treturn () => {}\n\t}\n\n\tconst awareness = syncEngine.getAwarenessManager()\n\tawareness.setLocalState({\n\t\tuser: {\n\t\t\tname: user.name,\n\t\t\tcolor: user.color,\n\t\t\tavatar: user.avatar,\n\t\t},\n\t})\n\n\treturn () => {\n\t\tawareness.setLocalState(null)\n\t}\n}\n\n/** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */\nexport const usePresence = applyPresence\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of remote collaborators' awareness states.\n */\nexport function createCollaboratorsStore(): Readable<AwarenessState[]> {\n\tconst { syncEngine } = getKoraContext()\n\n\treturn readable<AwarenessState[]>([], (set) => {\n\t\tif (!syncEngine) {\n\t\t\tset([])\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\treturn subscribeRemoteAwarenessStates(awareness, set)\n\t})\n}\n\n/** Alias for {@link createCollaboratorsStore}. */\nexport const useCollaborators = createCollaboratorsStore\n"],"mappings":"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","names":["import_store","import_svelte","import_store","import_store","import_svelte","import_sync","import_store"]}
package/dist/index.d.cts CHANGED
@@ -44,6 +44,15 @@ interface UseRichTextResult {
44
44
  cursors: CursorInfo[];
45
45
  setCursor: (anchor: number, head: number) => void;
46
46
  clearCursor: () => void;
47
+ /**
48
+ * True while local edits are not saved yet (a save pending or refused; see
49
+ * `error`). The edits stay in the document and the next edit saves them again.
50
+ */
51
+ hasUnsavedChanges: boolean;
52
+ /** Save the document now, for example after a refused save. */
53
+ retrySave: () => Promise<void>;
54
+ /** The full document state while edits are unsaved (for a recovery copy), else null. */
55
+ getUnsavedState: () => Uint8Array | null;
47
56
  }
48
57
 
49
58
  declare function setKoraContext(value: KoraContextValue): void;
package/dist/index.d.ts CHANGED
@@ -44,6 +44,15 @@ interface UseRichTextResult {
44
44
  cursors: CursorInfo[];
45
45
  setCursor: (anchor: number, head: number) => void;
46
46
  clearCursor: () => void;
47
+ /**
48
+ * True while local edits are not saved yet (a save pending or refused; see
49
+ * `error`). The edits stay in the document and the next edit saves them again.
50
+ */
51
+ hasUnsavedChanges: boolean;
52
+ /** Save the document now, for example after a refused save. */
53
+ retrySave: () => Promise<void>;
54
+ /** The full document state while edits are unsaved (for a recovery copy), else null. */
55
+ getUnsavedState: () => Uint8Array | null;
47
56
  }
48
57
 
49
58
  declare function setKoraContext(value: KoraContextValue): void;
package/dist/index.js CHANGED
@@ -313,6 +313,11 @@ function createRichTextBinding(collectionName, recordId, fieldName, options) {
313
313
  },
314
314
  setCursor: (anchor, head) => controller.setCursor(anchor, head),
315
315
  clearCursor: () => controller.clearCursor(),
316
+ get hasUnsavedChanges() {
317
+ return get(resultStore).hasUnsavedChanges;
318
+ },
319
+ retrySave: () => controller.retrySave(),
320
+ getUnsavedState: () => controller.getUnsavedState(),
316
321
  subscribe: resultStore.subscribe
317
322
  };
318
323
  }
@@ -330,7 +335,10 @@ function buildResult(controller) {
330
335
  canRedo: snapshot.canRedo,
331
336
  cursors: [...snapshot.cursors],
332
337
  setCursor: (anchor, head) => controller.setCursor(anchor, head),
333
- clearCursor: () => controller.clearCursor()
338
+ clearCursor: () => controller.clearCursor(),
339
+ hasUnsavedChanges: snapshot.hasUnsavedChanges,
340
+ retrySave: () => controller.retrySave(),
341
+ getUnsavedState: () => controller.getUnsavedState()
334
342
  };
335
343
  }
336
344
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.ts","../src/stores/query-store.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","../src/composables/use-collaborators.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { QueryStoreCache } from '@korajs/store'\nimport { getContext, setContext } from 'svelte'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\n// Registered (Symbol.for) keys: the .svelte components are compiled from src/ by the app\n// (the \"svelte\" export condition) while helpers such as getCollection come from dist/, so\n// two copies of this module exist in every app. Module-local Symbol() keys made the\n// provider's context invisible to the helpers (\"Kora context missing\").\nconst koraContextKey = Symbol.for('@korajs/svelte:context')\nconst koraAppContextKey = Symbol.for('@korajs/svelte:app')\n\nexport function setKoraContext(value: KoraContextValue): void {\n\tsetContext(koraContextKey, value)\n}\n\nexport function getKoraContext(): KoraContextValue {\n\tconst context = getContext<KoraContextValue | undefined>(koraContextKey)\n\tif (!context) {\n\t\tthrow new KoraError(\n\t\t\t'Kora context missing. Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.' },\n\t\t)\n\t}\n\treturn context\n}\n\n/** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */\nexport function setKoraAppContext(koraApp: KoraAppLike): void {\n\tsetContext(koraAppContextKey, koraApp)\n}\n\n/** @deprecated Use {@link getKoraContext} and {@link getApp}. */\nexport function getKoraApp(): KoraAppLike {\n\tconst app = getContext<KoraAppLike | undefined>(koraAppContextKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'getKoraApp() requires setKoraAppContext(koraApp) on an ancestor.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t)\n\t}\n\treturn app\n}\n\n/**\n * Initialize Kora provider context after `app.ready`.\n *\n * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.\n */\nexport async function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue> {\n\tawait app.ready\n\tconst queryStoreCache =\n\t\ttypeof app.getQueryStoreCache === 'function' ? app.getQueryStoreCache() : new QueryStoreCache()\n\tconst value: KoraContextValue = {\n\t\tstore: app.getStore(),\n\t\tsyncEngine: app.getSyncEngine(),\n\t\tapp,\n\t\tevents: app.events ?? null,\n\t\tsubscribeSyncStatus: app.sync?.subscribeStatus ?? null,\n\t\tqueryStoreCache,\n\t}\n\tsetKoraContext(value)\n\tsetKoraAppContext(app)\n\treturn value\n}\n","import type { CollectionRecord, QueryBuilder, QueryStore, QueryStoreCache } from '@korajs/store'\nimport { assertQueryReady, queryKey } from '@korajs/store'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\nimport type { QueryState, UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/** A query input: a builder, or a readable store of one (null disables). */\nexport type QueryInput<T> = QueryBuilder<T> | Readable<QueryBuilder<T> | null | undefined>\n\nfunction isQueryBuilder<T>(input: QueryInput<T>): input is QueryBuilder<T> {\n\treturn typeof (input as { getDescriptor?: unknown }).getDescriptor === 'function'\n}\n\nfunction isReadable<V>(input: V | Readable<V>): input is Readable<V> {\n\treturn (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\ttypeof (input as { subscribe?: unknown }).subscribe === 'function'\n\t)\n}\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 * Follows the query and `enabled` inputs (values or readable stores), holding one\n * ref-counted QueryStore per descriptor and switching when the descriptor changes\n * (DX-7). Returns the teardown.\n */\nfunction followQuery<T>(\n\tcache: QueryStoreCache,\n\tquery: QueryInput<T>,\n\toptions: UseQueryOptions | undefined,\n\temit: (state: QueryState<T>) => void,\n): () => void {\n\tlet current: QueryBuilder<T> | null = isQueryBuilder(query) ? query : null\n\tconst enabledInput = options?.enabled\n\tlet enabled = isReadable(enabledInput) ? true : enabledInput !== false\n\tlet activeKey: string | null = null\n\tlet release: (() => void) | null = null\n\tlet state: QueryState<T> = {\n\t\tdata: EMPTY_ARRAY as readonly T[],\n\t\terror: null,\n\t\tready: false,\n\t}\n\n\tconst publish = (next: QueryState<T>): void => {\n\t\tif (next.data === state.data && next.error === state.error && next.ready === state.ready) {\n\t\t\treturn\n\t\t}\n\t\tif (next.error && next.error !== state.error) options?.onError?.(next.error)\n\t\tstate = next\n\t\temit(state)\n\t}\n\n\tconst apply = (): void => {\n\t\tconst key = enabled && current ? queryKey(current.getDescriptor()) : null\n\t\tif (key === activeKey) return\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = key\n\t\tif (!key || !current) {\n\t\t\tpublish({ data: EMPTY_ARRAY as readonly T[], error: null, ready: false })\n\t\t\treturn\n\t\t}\n\t\tconst builder = current\n\t\tassertQueryReady(builder as QueryBuilder<unknown>)\n\t\tconst queryStore = cache.getOrCreate(builder)\n\t\tconst sync = (): void => {\n\t\t\tconst loaded = queryStore.hasSnapshot()\n\t\t\tpublish({\n\t\t\t\t// A descriptor switch keeps the previous rows until the new query answers.\n\t\t\t\tdata: loaded ? queryStore.getSnapshot() : state.data,\n\t\t\t\terror: readQueryError(queryStore as QueryStore<unknown>),\n\t\t\t\tready: loaded,\n\t\t\t})\n\t\t}\n\t\tconst unsubscribe = queryStore.subscribe(sync)\n\t\tsync()\n\t\trelease = () => {\n\t\t\tunsubscribe()\n\t\t\tcache.release(builder as QueryBuilder<unknown>)\n\t\t}\n\t}\n\n\tconst stops: Array<() => void> = []\n\tif (!isQueryBuilder(query)) {\n\t\tstops.push(\n\t\t\tquery.subscribe((next) => {\n\t\t\t\tcurrent = next ?? null\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tif (isReadable(enabledInput)) {\n\t\tstops.push(\n\t\t\tenabledInput.subscribe((next) => {\n\t\t\t\tenabled = next !== false\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tapply()\n\n\treturn () => {\n\t\tfor (const stop of stops) stop()\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = null\n\t}\n}\n\n/**\n * Create a Svelte readable store of a Kora query's rows.\n *\n * The query and `enabled` may be plain values or readable stores: pass a store (for\n * example a `derived` of your filter) and the rows follow it, re-subscribing when the\n * query's descriptor changes. A failed query is reported through `options.onError`,\n * or `console.error` without one; use {@link createQueryStateStore} to render it.\n *\n * @param query - A query builder, or a readable store of one (null disables)\n * @param options - `enabled` (value or readable store; default true) and `onError`\n * @returns A readable store of the current rows\n *\n * @example\n * ```ts\n * const filter = writable(false)\n * const todos = createQueryStore(derived(filter, (done) => app.todos.where({ completed: done })))\n * ```\n */\nexport function createQueryStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<readonly T[]> {\n\tconst { queryStoreCache } = getKoraContext()\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\treportUnhandled(failure)\n\t\t\t}),\n\t}\n\treturn readable<readonly T[]>(EMPTY_ARRAY as readonly T[], (set) =>\n\t\tfollowQuery(queryStoreCache, query, reporting, (state) => set(state.data)),\n\t)\n}\n\n/**\n * Like {@link createQueryStore}, but the store holds `{ data, error, ready }`.\n *\n * @param query - A query builder, or a readable store of one\n * @param options - `enabled` and `onError`\n * @returns A readable store of the query state\n */\nexport function createQueryStateStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<QueryState<T>> {\n\tconst { queryStoreCache } = getKoraContext()\n\tconst initial: QueryState<T> = { data: EMPTY_ARRAY as readonly T[], error: null, ready: false }\n\treturn readable<QueryState<T>>(initial, (set) =>\n\t\tfollowQuery(queryStoreCache, query, options, set),\n\t)\n}\n\n/**\n * Logs a query failure nobody handles. Read through globalThis because this package\n * builds without DOM or Node typings.\n */\nfunction reportUnhandled(failure: Error): void {\n\tconst host = globalThis as { console?: { error(...args: unknown[]): void } }\n\thost.console?.error('[Kora] createQueryStore failed:', failure)\n}\n\n/** Alias for {@link createQueryStore}. */\nexport const useQuery = createQueryStore\n\n/** Alias for {@link createQueryStateStore}. */\nexport const useQueryState = createQueryStateStore\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onDestroy } from 'svelte'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Create a mutation controller with optimistic update hooks.\n */\nexport function createMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t})\n\n\tconst loadingListeners = new Set<(value: boolean) => void>()\n\tconst errorListeners = new Set<(value: Error | null) => void>()\n\n\tconst unsubscribe = controller.subscribe(() => {\n\t\tconst snapshot = controller.getSnapshot()\n\t\tfor (const listener of loadingListeners) {\n\t\t\tlistener(snapshot.isLoading)\n\t\t}\n\t\tfor (const listener of errorListeners) {\n\t\t\tlistener(snapshot.error)\n\t\t}\n\t})\n\n\t// Dispose the controller when the owning component unmounts, matching the\n\t// React (`useController`) and Vue (`onScopeDispose`) lifecycles. Guarded so\n\t// `createMutation()` can still be called outside a component (manual usage),\n\t// where `onDestroy` is unavailable and the caller owns disposal.\n\ttry {\n\t\tonDestroy(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t} catch {\n\t\t// Not inside a component initialization — no lifecycle to hook into.\n\t}\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tsubscribeLoading: (fn) => {\n\t\t\tloadingListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().isLoading)\n\t\t\treturn () => loadingListeners.delete(fn)\n\t\t},\n\t\tsubscribeError: (fn) => {\n\t\t\terrorListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().error)\n\t\t\treturn () => errorListeners.delete(fn)\n\t\t},\n\t\tget loading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget isLoading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget error() {\n\t\t\treturn controller.getSnapshot().error\n\t\t},\n\t\treset: () => controller.reset(),\n\t}\n}\n\n/** Alias for {@link createMutation}. */\nexport const useMutation = createMutation\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of sync engine status.\n */\nexport function createSyncStatusStore(): Readable<SyncStatusInfo> {\n\tconst { syncEngine, subscribeSyncStatus, events } = getKoraContext()\n\n\treturn readable<SyncStatusInfo>(OFFLINE_SYNC_STATUS, (set) => {\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\tset(controller.getSnapshot())\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tset(controller.getSnapshot())\n\t\t})\n\t\treturn () => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t}\n\t})\n}\n\n/** Alias for {@link createSyncStatusStore}. */\nexport const useSyncStatus = createSyncStatusStore\n","import { getKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\nexport function getApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = getKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'getApp() requires <KoraProvider app={kora}> or <KoraStoreProvider store={store}> with a createApp() instance.',\n\t\t)\n\t}\n\treturn app as T\n}\n\n/** Alias for {@link getApp}. */\nexport const useApp = getApp\n","import type { CollectionAccessor } from '@korajs/store'\nimport { getKoraContext } from '../context'\n\nexport function getCollection(name: string): CollectionAccessor {\n\tconst { store } = getKoraContext()\n\treturn store.collection(name)\n}\n\n/** Alias for {@link getCollection}. */\nexport const useCollection = getCollection\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { onDestroy } from 'svelte'\nimport { type Readable, get, readable } from 'svelte/store'\nimport { getKoraContext } 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 *\n * Must be called during component initialization. For reactive target changes,\n * use {@link KoraRichText} instead.\n */\nexport function createRichTextBinding(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult & { subscribe: Readable<UseRichTextResult>['subscribe'] } {\n\tconst { store, syncEngine } = getKoraContext()\n\n\tconst controller = createRichTextController({\n\t\tcollection: store.collection(collectionName),\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\tuseDocChannel: options?.useDocChannel,\n\t\tuser: options?.user,\n\t})\n\n\tonDestroy(() => {\n\t\tcontroller.destroy()\n\t})\n\n\tconst resultStore = readable<UseRichTextResult>(buildResult(controller), (set) => {\n\t\tconst sync = (): void => {\n\t\t\tset(buildResult(controller))\n\t\t}\n\t\tsync()\n\t\treturn controller.subscribe(sync)\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 get(resultStore).ready\n\t\t},\n\t\tget error() {\n\t\t\treturn get(resultStore).error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn get(resultStore).canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn get(resultStore).canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn get(resultStore).cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t\tsubscribe: resultStore.subscribe,\n\t}\n}\n\n/** @alias createRichTextBinding */\nexport const useRichText = createRichTextBinding\n\nfunction buildResult(controller: ReturnType<typeof createRichTextController>): UseRichTextResult {\n\tconst snapshot = controller.getSnapshot()\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo: () => controller.undo(),\n\t\tredo: () => controller.redo(),\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor: (anchor, head) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t}\n}\n","import { getKoraContext } from '../context'\n\n/**\n * Applies local collaborative presence. Returns a cleanup function.\n *\n * In Svelte components, call from an effect:\n * `$effect(() => applyPresence(user))`\n */\nexport function applyPresence(\n\tuser: { name: string; color: string; avatar?: string } | null,\n): () => void {\n\tconst { syncEngine } = getKoraContext()\n\tif (!syncEngine || !user?.name || !user?.color) {\n\t\treturn () => {}\n\t}\n\n\tconst awareness = syncEngine.getAwarenessManager()\n\tawareness.setLocalState({\n\t\tuser: {\n\t\t\tname: user.name,\n\t\t\tcolor: user.color,\n\t\t\tavatar: user.avatar,\n\t\t},\n\t})\n\n\treturn () => {\n\t\tawareness.setLocalState(null)\n\t}\n}\n\n/** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */\nexport const usePresence = applyPresence\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of remote collaborators' awareness states.\n */\nexport function createCollaboratorsStore(): Readable<AwarenessState[]> {\n\tconst { syncEngine } = getKoraContext()\n\n\treturn readable<AwarenessState[]>([], (set) => {\n\t\tif (!syncEngine) {\n\t\t\tset([])\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\treturn subscribeRemoteAwarenessStates(awareness, set)\n\t})\n}\n\n/** Alias for {@link createCollaboratorsStore}. */\nexport const useCollaborators = createCollaboratorsStore\n"],"mappings":"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","names":["readable","readable","onDestroy","readable","onDestroy","readable","readable","readable"]}
1
+ {"version":3,"sources":["../src/context.ts","../src/stores/query-store.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","../src/composables/use-collaborators.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { QueryStoreCache } from '@korajs/store'\nimport { getContext, setContext } from 'svelte'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\n// Registered (Symbol.for) keys: the .svelte components are compiled from src/ by the app\n// (the \"svelte\" export condition) while helpers such as getCollection come from dist/, so\n// two copies of this module exist in every app. Module-local Symbol() keys made the\n// provider's context invisible to the helpers (\"Kora context missing\").\nconst koraContextKey = Symbol.for('@korajs/svelte:context')\nconst koraAppContextKey = Symbol.for('@korajs/svelte:app')\n\nexport function setKoraContext(value: KoraContextValue): void {\n\tsetContext(koraContextKey, value)\n}\n\nexport function getKoraContext(): KoraContextValue {\n\tconst context = getContext<KoraContextValue | undefined>(koraContextKey)\n\tif (!context) {\n\t\tthrow new KoraError(\n\t\t\t'Kora context missing. Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.' },\n\t\t)\n\t}\n\treturn context\n}\n\n/** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */\nexport function setKoraAppContext(koraApp: KoraAppLike): void {\n\tsetContext(koraAppContextKey, koraApp)\n}\n\n/** @deprecated Use {@link getKoraContext} and {@link getApp}. */\nexport function getKoraApp(): KoraAppLike {\n\tconst app = getContext<KoraAppLike | undefined>(koraAppContextKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'getKoraApp() requires setKoraAppContext(koraApp) on an ancestor.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t)\n\t}\n\treturn app\n}\n\n/**\n * Initialize Kora provider context after `app.ready`.\n *\n * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.\n */\nexport async function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue> {\n\tawait app.ready\n\tconst queryStoreCache =\n\t\ttypeof app.getQueryStoreCache === 'function' ? app.getQueryStoreCache() : new QueryStoreCache()\n\tconst value: KoraContextValue = {\n\t\tstore: app.getStore(),\n\t\tsyncEngine: app.getSyncEngine(),\n\t\tapp,\n\t\tevents: app.events ?? null,\n\t\tsubscribeSyncStatus: app.sync?.subscribeStatus ?? null,\n\t\tqueryStoreCache,\n\t}\n\tsetKoraContext(value)\n\tsetKoraAppContext(app)\n\treturn value\n}\n","import type { CollectionRecord, QueryBuilder, QueryStore, QueryStoreCache } from '@korajs/store'\nimport { assertQueryReady, queryKey } from '@korajs/store'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\nimport type { QueryState, UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/** A query input: a builder, or a readable store of one (null disables). */\nexport type QueryInput<T> = QueryBuilder<T> | Readable<QueryBuilder<T> | null | undefined>\n\nfunction isQueryBuilder<T>(input: QueryInput<T>): input is QueryBuilder<T> {\n\treturn typeof (input as { getDescriptor?: unknown }).getDescriptor === 'function'\n}\n\nfunction isReadable<V>(input: V | Readable<V>): input is Readable<V> {\n\treturn (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\ttypeof (input as { subscribe?: unknown }).subscribe === 'function'\n\t)\n}\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 * Follows the query and `enabled` inputs (values or readable stores), holding one\n * ref-counted QueryStore per descriptor and switching when the descriptor changes\n * (DX-7). Returns the teardown.\n */\nfunction followQuery<T>(\n\tcache: QueryStoreCache,\n\tquery: QueryInput<T>,\n\toptions: UseQueryOptions | undefined,\n\temit: (state: QueryState<T>) => void,\n): () => void {\n\tlet current: QueryBuilder<T> | null = isQueryBuilder(query) ? query : null\n\tconst enabledInput = options?.enabled\n\tlet enabled = isReadable(enabledInput) ? true : enabledInput !== false\n\tlet activeKey: string | null = null\n\tlet release: (() => void) | null = null\n\tlet state: QueryState<T> = {\n\t\tdata: EMPTY_ARRAY as readonly T[],\n\t\terror: null,\n\t\tready: false,\n\t}\n\n\tconst publish = (next: QueryState<T>): void => {\n\t\tif (next.data === state.data && next.error === state.error && next.ready === state.ready) {\n\t\t\treturn\n\t\t}\n\t\tif (next.error && next.error !== state.error) options?.onError?.(next.error)\n\t\tstate = next\n\t\temit(state)\n\t}\n\n\tconst apply = (): void => {\n\t\tconst key = enabled && current ? queryKey(current.getDescriptor()) : null\n\t\tif (key === activeKey) return\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = key\n\t\tif (!key || !current) {\n\t\t\tpublish({ data: EMPTY_ARRAY as readonly T[], error: null, ready: false })\n\t\t\treturn\n\t\t}\n\t\tconst builder = current\n\t\tassertQueryReady(builder as QueryBuilder<unknown>)\n\t\tconst queryStore = cache.getOrCreate(builder)\n\t\tconst sync = (): void => {\n\t\t\tconst loaded = queryStore.hasSnapshot()\n\t\t\tpublish({\n\t\t\t\t// A descriptor switch keeps the previous rows until the new query answers.\n\t\t\t\tdata: loaded ? queryStore.getSnapshot() : state.data,\n\t\t\t\terror: readQueryError(queryStore as QueryStore<unknown>),\n\t\t\t\tready: loaded,\n\t\t\t})\n\t\t}\n\t\tconst unsubscribe = queryStore.subscribe(sync)\n\t\tsync()\n\t\trelease = () => {\n\t\t\tunsubscribe()\n\t\t\tcache.release(builder as QueryBuilder<unknown>)\n\t\t}\n\t}\n\n\tconst stops: Array<() => void> = []\n\tif (!isQueryBuilder(query)) {\n\t\tstops.push(\n\t\t\tquery.subscribe((next) => {\n\t\t\t\tcurrent = next ?? null\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tif (isReadable(enabledInput)) {\n\t\tstops.push(\n\t\t\tenabledInput.subscribe((next) => {\n\t\t\t\tenabled = next !== false\n\t\t\t\tapply()\n\t\t\t}),\n\t\t)\n\t}\n\tapply()\n\n\treturn () => {\n\t\tfor (const stop of stops) stop()\n\t\trelease?.()\n\t\trelease = null\n\t\tactiveKey = null\n\t}\n}\n\n/**\n * Create a Svelte readable store of a Kora query's rows.\n *\n * The query and `enabled` may be plain values or readable stores: pass a store (for\n * example a `derived` of your filter) and the rows follow it, re-subscribing when the\n * query's descriptor changes. A failed query is reported through `options.onError`,\n * or `console.error` without one; use {@link createQueryStateStore} to render it.\n *\n * @param query - A query builder, or a readable store of one (null disables)\n * @param options - `enabled` (value or readable store; default true) and `onError`\n * @returns A readable store of the current rows\n *\n * @example\n * ```ts\n * const filter = writable(false)\n * const todos = createQueryStore(derived(filter, (done) => app.todos.where({ completed: done })))\n * ```\n */\nexport function createQueryStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<readonly T[]> {\n\tconst { queryStoreCache } = getKoraContext()\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\treportUnhandled(failure)\n\t\t\t}),\n\t}\n\treturn readable<readonly T[]>(EMPTY_ARRAY as readonly T[], (set) =>\n\t\tfollowQuery(queryStoreCache, query, reporting, (state) => set(state.data)),\n\t)\n}\n\n/**\n * Like {@link createQueryStore}, but the store holds `{ data, error, ready }`.\n *\n * @param query - A query builder, or a readable store of one\n * @param options - `enabled` and `onError`\n * @returns A readable store of the query state\n */\nexport function createQueryStateStore<T = CollectionRecord>(\n\tquery: QueryInput<T>,\n\toptions?: UseQueryOptions,\n): Readable<QueryState<T>> {\n\tconst { queryStoreCache } = getKoraContext()\n\tconst initial: QueryState<T> = { data: EMPTY_ARRAY as readonly T[], error: null, ready: false }\n\treturn readable<QueryState<T>>(initial, (set) =>\n\t\tfollowQuery(queryStoreCache, query, options, set),\n\t)\n}\n\n/**\n * Logs a query failure nobody handles. Read through globalThis because this package\n * builds without DOM or Node typings.\n */\nfunction reportUnhandled(failure: Error): void {\n\tconst host = globalThis as { console?: { error(...args: unknown[]): void } }\n\thost.console?.error('[Kora] createQueryStore failed:', failure)\n}\n\n/** Alias for {@link createQueryStore}. */\nexport const useQuery = createQueryStore\n\n/** Alias for {@link createQueryStateStore}. */\nexport const useQueryState = createQueryStateStore\n","import { createMutationController } from '@korajs/core/bindings'\nimport { onDestroy } from 'svelte'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Create a mutation controller with optimistic update hooks.\n */\nexport function createMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t})\n\n\tconst loadingListeners = new Set<(value: boolean) => void>()\n\tconst errorListeners = new Set<(value: Error | null) => void>()\n\n\tconst unsubscribe = controller.subscribe(() => {\n\t\tconst snapshot = controller.getSnapshot()\n\t\tfor (const listener of loadingListeners) {\n\t\t\tlistener(snapshot.isLoading)\n\t\t}\n\t\tfor (const listener of errorListeners) {\n\t\t\tlistener(snapshot.error)\n\t\t}\n\t})\n\n\t// Dispose the controller when the owning component unmounts, matching the\n\t// React (`useController`) and Vue (`onScopeDispose`) lifecycles. Guarded so\n\t// `createMutation()` can still be called outside a component (manual usage),\n\t// where `onDestroy` is unavailable and the caller owns disposal.\n\ttry {\n\t\tonDestroy(() => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t})\n\t} catch {\n\t\t// Not inside a component initialization — no lifecycle to hook into.\n\t}\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tsubscribeLoading: (fn) => {\n\t\t\tloadingListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().isLoading)\n\t\t\treturn () => loadingListeners.delete(fn)\n\t\t},\n\t\tsubscribeError: (fn) => {\n\t\t\terrorListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().error)\n\t\t\treturn () => errorListeners.delete(fn)\n\t\t},\n\t\tget loading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget isLoading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget error() {\n\t\t\treturn controller.getSnapshot().error\n\t\t},\n\t\treset: () => controller.reset(),\n\t}\n}\n\n/** Alias for {@link createMutation}. */\nexport const useMutation = createMutation\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of sync engine status.\n */\nexport function createSyncStatusStore(): Readable<SyncStatusInfo> {\n\tconst { syncEngine, subscribeSyncStatus, events } = getKoraContext()\n\n\treturn readable<SyncStatusInfo>(OFFLINE_SYNC_STATUS, (set) => {\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\tset(controller.getSnapshot())\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tset(controller.getSnapshot())\n\t\t})\n\t\treturn () => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t}\n\t})\n}\n\n/** Alias for {@link createSyncStatusStore}. */\nexport const useSyncStatus = createSyncStatusStore\n","import { getKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\nexport function getApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = getKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'getApp() requires <KoraProvider app={kora}> or <KoraStoreProvider store={store}> with a createApp() instance.',\n\t\t)\n\t}\n\treturn app as T\n}\n\n/** Alias for {@link getApp}. */\nexport const useApp = getApp\n","import type { CollectionAccessor } from '@korajs/store'\nimport { getKoraContext } from '../context'\n\nexport function getCollection(name: string): CollectionAccessor {\n\tconst { store } = getKoraContext()\n\treturn store.collection(name)\n}\n\n/** Alias for {@link getCollection}. */\nexport const useCollection = getCollection\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { onDestroy } from 'svelte'\nimport { type Readable, get, readable } from 'svelte/store'\nimport { getKoraContext } 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 *\n * Must be called during component initialization. For reactive target changes,\n * use {@link KoraRichText} instead.\n */\nexport function createRichTextBinding(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult & { subscribe: Readable<UseRichTextResult>['subscribe'] } {\n\tconst { store, syncEngine } = getKoraContext()\n\n\tconst controller = createRichTextController({\n\t\tcollection: store.collection(collectionName),\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\tuseDocChannel: options?.useDocChannel,\n\t\tuser: options?.user,\n\t})\n\n\tonDestroy(() => {\n\t\tcontroller.destroy()\n\t})\n\n\tconst resultStore = readable<UseRichTextResult>(buildResult(controller), (set) => {\n\t\tconst sync = (): void => {\n\t\t\tset(buildResult(controller))\n\t\t}\n\t\tsync()\n\t\treturn controller.subscribe(sync)\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 get(resultStore).ready\n\t\t},\n\t\tget error() {\n\t\t\treturn get(resultStore).error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn get(resultStore).canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn get(resultStore).canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn get(resultStore).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 get(resultStore).hasUnsavedChanges\n\t\t},\n\t\tretrySave: () => controller.retrySave(),\n\t\tgetUnsavedState: () => controller.getUnsavedState(),\n\t\tsubscribe: resultStore.subscribe,\n\t}\n}\n\n/** @alias createRichTextBinding */\nexport const useRichText = createRichTextBinding\n\nfunction buildResult(controller: ReturnType<typeof createRichTextController>): UseRichTextResult {\n\tconst snapshot = controller.getSnapshot()\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo: () => controller.undo(),\n\t\tredo: () => controller.redo(),\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor: (anchor, head) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t\thasUnsavedChanges: snapshot.hasUnsavedChanges,\n\t\tretrySave: () => controller.retrySave(),\n\t\tgetUnsavedState: () => controller.getUnsavedState(),\n\t}\n}\n","import { getKoraContext } from '../context'\n\n/**\n * Applies local collaborative presence. Returns a cleanup function.\n *\n * In Svelte components, call from an effect:\n * `$effect(() => applyPresence(user))`\n */\nexport function applyPresence(\n\tuser: { name: string; color: string; avatar?: string } | null,\n): () => void {\n\tconst { syncEngine } = getKoraContext()\n\tif (!syncEngine || !user?.name || !user?.color) {\n\t\treturn () => {}\n\t}\n\n\tconst awareness = syncEngine.getAwarenessManager()\n\tawareness.setLocalState({\n\t\tuser: {\n\t\t\tname: user.name,\n\t\t\tcolor: user.color,\n\t\t\tavatar: user.avatar,\n\t\t},\n\t})\n\n\treturn () => {\n\t\tawareness.setLocalState(null)\n\t}\n}\n\n/** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */\nexport const usePresence = applyPresence\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { type Readable, readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of remote collaborators' awareness states.\n */\nexport function createCollaboratorsStore(): Readable<AwarenessState[]> {\n\tconst { syncEngine } = getKoraContext()\n\n\treturn readable<AwarenessState[]>([], (set) => {\n\t\tif (!syncEngine) {\n\t\t\tset([])\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\treturn subscribeRemoteAwarenessStates(awareness, set)\n\t})\n}\n\n/** Alias for {@link createCollaboratorsStore}. */\nexport const useCollaborators = createCollaboratorsStore\n"],"mappings":"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","names":["readable","readable","onDestroy","readable","onDestroy","readable","readable","readable"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korajs/svelte",
3
- "version": "1.0.0-beta.13",
3
+ "version": "1.0.0-beta.14",
4
4
  "description": "Kora.js Svelte bindings for offline-first applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -46,9 +46,9 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "yjs": "^13.6.30",
49
- "@korajs/core": "1.0.0-beta.13",
50
- "@korajs/store": "1.0.0-beta.13",
51
- "@korajs/sync": "1.0.0-beta.13"
49
+ "@korajs/core": "1.0.0-beta.14",
50
+ "@korajs/store": "1.0.0-beta.14",
51
+ "@korajs/sync": "1.0.0-beta.14"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
@@ -73,6 +73,11 @@ export function createRichTextBinding(
73
73
  },
74
74
  setCursor: (anchor: number, head: number) => controller.setCursor(anchor, head),
75
75
  clearCursor: () => controller.clearCursor(),
76
+ get hasUnsavedChanges() {
77
+ return get(resultStore).hasUnsavedChanges
78
+ },
79
+ retrySave: () => controller.retrySave(),
80
+ getUnsavedState: () => controller.getUnsavedState(),
76
81
  subscribe: resultStore.subscribe,
77
82
  }
78
83
  }
@@ -94,5 +99,8 @@ function buildResult(controller: ReturnType<typeof createRichTextController>): U
94
99
  cursors: [...snapshot.cursors],
95
100
  setCursor: (anchor, head) => controller.setCursor(anchor, head),
96
101
  clearCursor: () => controller.clearCursor(),
102
+ hasUnsavedChanges: snapshot.hasUnsavedChanges,
103
+ retrySave: () => controller.retrySave(),
104
+ getUnsavedState: () => controller.getUnsavedState(),
97
105
  }
98
106
  }
package/src/types.ts CHANGED
@@ -59,4 +59,13 @@ export interface UseRichTextResult {
59
59
  cursors: CursorInfo[]
60
60
  setCursor: (anchor: number, head: number) => void
61
61
  clearCursor: () => void
62
+ /**
63
+ * True while local edits are not saved yet (a save pending or refused; see
64
+ * `error`). The edits stay in the document and the next edit saves them again.
65
+ */
66
+ hasUnsavedChanges: boolean
67
+ /** Save the document now, for example after a refused save. */
68
+ retrySave: () => Promise<void>
69
+ /** The full document state while edits are unsaved (for a recovery copy), else null. */
70
+ getUnsavedState: () => Uint8Array | null
62
71
  }