@korajs/react 1.0.0-beta.11 → 1.0.0-beta.12

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
@@ -22,6 +22,7 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AuthBoundKoraProvider: () => AuthBoundKoraProvider,
24
24
  KoraProvider: () => KoraProvider,
25
+ classifyKoraInitializationError: () => classifyKoraInitializationError,
25
26
  useApp: () => useApp,
26
27
  useCollaborators: () => useCollaborators,
27
28
  useCollection: () => useCollection,
@@ -123,11 +124,35 @@ function useKoraContext() {
123
124
 
124
125
  // src/context/auth-bound-kora-provider.ts
125
126
  var import_react2 = require("react");
127
+ var SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i;
128
+ function classifyKoraInitializationError(error) {
129
+ const candidate = error;
130
+ const message = typeof candidate?.message === "string" ? candidate.message : String(error);
131
+ const name = typeof candidate?.name === "string" ? candidate.name : "Error";
132
+ const cause = new Error(message);
133
+ cause.name = name;
134
+ if (typeof candidate?.stack === "string") cause.stack = candidate.stack;
135
+ let code = typeof candidate?.code === "string" ? candidate.code : "INITIALIZATION_FAILED";
136
+ if (code === "INITIALIZATION_FAILED" && cause.name === "QuotaExceededError") {
137
+ code = "STORAGE_QUOTA_EXCEEDED";
138
+ }
139
+ const metadata = {};
140
+ if (candidate?.context && typeof candidate.context === "object") {
141
+ for (const [key, value] of Object.entries(candidate.context)) {
142
+ if (SENSITIVE_METADATA_KEY.test(key)) continue;
143
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
144
+ metadata[key] = value;
145
+ }
146
+ }
147
+ }
148
+ return { code, name: cause.name, message: cause.message, metadata, cause };
149
+ }
126
150
  function AuthBoundKoraProvider({
127
151
  authClient,
128
152
  createApp,
129
153
  signedOut = null,
130
154
  fallback = null,
155
+ error: renderError,
131
156
  children
132
157
  }) {
133
158
  const [app, setApp] = (0, import_react2.useState)(null);
@@ -139,6 +164,8 @@ function AuthBoundKoraProvider({
139
164
  const activeUserId = (0, import_react2.useRef)(null);
140
165
  const generation = (0, import_react2.useRef)(0);
141
166
  const transition = (0, import_react2.useRef)(Promise.resolve());
167
+ const reconcileRef = (0, import_react2.useRef)(() => {
168
+ });
142
169
  (0, import_react2.useEffect)(() => {
143
170
  let disposed = false;
144
171
  const reconcile = () => {
@@ -176,10 +203,18 @@ function AuthBoundKoraProvider({
176
203
  setApp(created);
177
204
  }).catch((error) => {
178
205
  if (!disposed && currentGeneration === generation.current) {
179
- setInitError(error instanceof Error ? error : new Error(String(error)));
206
+ void authClient.resolveSyncState?.().then((failedSession) => {
207
+ if (!disposed && currentGeneration === generation.current && failedSession?.state === "authenticated") {
208
+ setInitError({
209
+ error: classifyKoraInitializationError(error),
210
+ session: { userId: failedSession.userId }
211
+ });
212
+ }
213
+ });
180
214
  }
181
215
  });
182
216
  };
217
+ reconcileRef.current = reconcile;
183
218
  reconcile();
184
219
  const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
185
220
  });
@@ -194,11 +229,18 @@ function AuthBoundKoraProvider({
194
229
  };
195
230
  }, [authClient]);
196
231
  if (initError) {
232
+ if (renderError) {
233
+ return renderError({
234
+ error: initError.error,
235
+ session: initError.session,
236
+ retry: () => reconcileRef.current()
237
+ });
238
+ }
197
239
  return (0, import_react2.createElement)(
198
240
  "div",
199
241
  { style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
200
242
  (0, import_react2.createElement)("strong", null, "Kora initialization error: "),
201
- initError.message
243
+ initError.error.message
202
244
  );
203
245
  }
204
246
  if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
@@ -465,6 +507,7 @@ function useCollaborators() {
465
507
  0 && (module.exports = {
466
508
  AuthBoundKoraProvider,
467
509
  KoraProvider,
510
+ classifyKoraInitializationError,
468
511
  useApp,
469
512
  useCollaborators,
470
513
  useCollection,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context/kora-context.ts","../src/context/auth-bound-kora-provider.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["// @korajs/react — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tKoraAppLike,\n\tKoraContextValue,\n\tKoraProviderProps,\n\tUseQueryOptions,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseRichTextResult,\n} from './types'\n\n// === Context ===\nexport { KoraProvider } from './context/kora-context'\nexport { AuthBoundKoraProvider } from './context/auth-bound-kora-provider'\nexport type { AuthBoundKoraProviderProps } from './context/auth-bound-kora-provider'\n\n// === Hooks ===\nexport { useApp } from './hooks/use-app'\nexport { useQuery } from './hooks/use-query'\nexport { useMutation } from './hooks/use-mutation'\nexport { useSyncStatus } from './hooks/use-sync-status'\nexport { useCollection } from './hooks/use-collection'\nexport { useRichText } from './hooks/use-rich-text'\nexport type { UseRichTextOptions } from './hooks/use-rich-text'\nexport { usePresence } from './hooks/use-presence'\nexport { useCollaborators } from './hooks/use-collaborators'\n","import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\tcreateContext,\n\tcreateElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\tif (fallbackQueryStoreCache.current === null) {\n\t\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import type { AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraAppLike } from '../types'\nimport { KoraProvider } from './kora-context'\n\nexport interface AuthBoundKoraProviderProps {\n\tauthClient: AuthSyncBinding\n\tcreateApp: (\n\t\tsession: Extract<AuthSyncState, { state: 'authenticated' }>,\n\t) => KoraAppLike & { close(): Promise<void> }\n\tsignedOut?: ReactNode\n\tfallback?: ReactNode\n\tchildren?: ReactNode\n}\n\n/**\n * Owns the security-sensitive app lifetime for shared-browser applications.\n * The previous app is fully closed before a different user's app is created,\n * and no stale provider tree is rendered across that boundary.\n */\nexport function AuthBoundKoraProvider({\n\tauthClient,\n\tcreateApp,\n\tsignedOut = null,\n\tfallback = null,\n\tchildren,\n}: AuthBoundKoraProviderProps): ReactNode {\n\tconst [app, setApp] = useState<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst [state, setState] = useState<AuthSyncState>({ state: 'loading' })\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst active = useRef<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst createAppRef = useRef(createApp)\n\tcreateAppRef.current = createApp\n\tconst activeUserId = useRef<string | null>(null)\n\tconst generation = useRef(0)\n\tconst transition = useRef(Promise.resolve())\n\n\tuseEffect(() => {\n\t\tlet disposed = false\n\t\tconst reconcile = (): void => {\n\t\t\tconst currentGeneration = ++generation.current\n\t\t\ttransition.current = transition.current\n\t\t\t\t.catch(() => {})\n\t\t\t\t.then(async () => {\n\t\t\t\t\tsetInitError(null)\n\t\t\t\t\tconst next =\n\t\t\t\t\t\t(await authClient.resolveSyncState?.()) ??\n\t\t\t\t\t\t({ state: 'signed-out', mayConnectAnonymously: false } as const)\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tconst previous = active.current\n\t\t\t\t\t// Same-user token/role refreshes stay on the same database and app instance.\n\t\t\t\t\tif (next.state === 'authenticated' && next.userId === activeUserId.current && previous) {\n\t\t\t\t\t\tsetState(next)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetApp(null)\n\t\t\t\t\tactive.current = null\n\t\t\t\t\tactiveUserId.current = null\n\t\t\t\t\tif (previous) await previous.close()\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tsetState(next)\n\t\t\t\t\tif (next.state !== 'authenticated') return\n\t\t\t\t\tconst created = createAppRef.current(next)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait created.ready\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tactive.current = created\n\t\t\t\t\tactiveUserId.current = next.userId\n\t\t\t\t\tsetApp(created)\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tif (!disposed && currentGeneration === generation.current) {\n\t\t\t\t\t\tsetInitError(error instanceof Error ? error : new Error(String(error)))\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t\treconcile()\n\t\tconst unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {})\n\t\treturn () => {\n\t\t\tdisposed = true\n\t\t\tgeneration.current++\n\t\t\tunsubscribe()\n\t\t\tconst previous = active.current\n\t\t\tactive.current = null\n\t\t\tactiveUserId.current = null\n\t\t\tif (previous) void previous.close()\n\t\t}\n\t}, [authClient])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\tif (state.state === 'signed-out' || state.state === 'anonymous') return signedOut\n\tif (!app) return fallback\n\treturn createElement(KoraProvider, { app, fallback }, children)\n}\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\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 to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\tconst lastSnapshotRef = useRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: descriptorKey intentionally re-runs the effect when the query descriptor changes, even though the effect reads the query via queryRef\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst getSnapshot = useCallback((): readonly T[] => {\n\t\tif (!enabled) {\n\t\t\tlastSnapshotRef.current = EMPTY_ARRAY as readonly T[]\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore.hasSnapshot()) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tconst snapshot = queryStore.getSnapshot()\n\t\tlastSnapshotRef.current = snapshot\n\t\treturn snapshot\n\t}, [enabled, queryStore])\n\n\treturn useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\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 = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\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 collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["import_react","import_store","import_react","import_react","import_react","import_react","import_react","import_store","import_react","import_react","import_sync","import_react","EMPTY_ARRAY"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context/kora-context.ts","../src/context/auth-bound-kora-provider.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["// @korajs/react — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tKoraAppLike,\n\tKoraContextValue,\n\tKoraProviderProps,\n\tUseQueryOptions,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseRichTextResult,\n} from './types'\n\n// === Context ===\nexport { KoraProvider } from './context/kora-context'\nexport {\n\tAuthBoundKoraProvider,\n\tclassifyKoraInitializationError,\n} from './context/auth-bound-kora-provider'\nexport type {\n\tAuthBoundKoraErrorContext,\n\tAuthBoundKoraInitializationError,\n\tAuthBoundKoraProviderProps,\n\tAuthBoundKoraSession,\n} from './context/auth-bound-kora-provider'\n\n// === Hooks ===\nexport { useApp } from './hooks/use-app'\nexport { useQuery } from './hooks/use-query'\nexport { useMutation } from './hooks/use-mutation'\nexport { useSyncStatus } from './hooks/use-sync-status'\nexport { useCollection } from './hooks/use-collection'\nexport { useRichText } from './hooks/use-rich-text'\nexport type { UseRichTextOptions } from './hooks/use-rich-text'\nexport { usePresence } from './hooks/use-presence'\nexport { useCollaborators } from './hooks/use-collaborators'\n","import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\tcreateContext,\n\tcreateElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\tif (fallbackQueryStoreCache.current === null) {\n\t\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import type { AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraAppLike } from '../types'\nimport { KoraProvider } from './kora-context'\n\nexport interface AuthBoundKoraProviderProps {\n\tauthClient: AuthSyncBinding\n\tcreateApp: (\n\t\tsession: Extract<AuthSyncState, { state: 'authenticated' }>,\n\t) => KoraAppLike & { close(): Promise<void> }\n\tsignedOut?: ReactNode\n\tfallback?: ReactNode\n\terror?: (context: AuthBoundKoraErrorContext) => ReactNode\n\tchildren?: ReactNode\n}\n\nexport interface AuthBoundKoraSession {\n\t/** The authenticated identity only. Access tokens are deliberately omitted. */\n\tuserId: string\n}\n\nexport interface AuthBoundKoraInitializationError {\n\t/** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */\n\tcode: string\n\tname: string\n\tmessage: string\n\t/** Sanitized primitive metadata. Credential-shaped keys are always removed. */\n\tmetadata: Readonly<Record<string, string | number | boolean | null>>\n\t/** Sanitized Error for logging; custom credential-bearing properties are omitted. */\n\tcause: Error\n}\n\nexport interface AuthBoundKoraErrorContext {\n\terror: AuthBoundKoraInitializationError\n\tretry(): void\n\tsession: AuthBoundKoraSession\n}\n\nconst SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i\n\n/** Classify initialization failures without requiring applications to parse copy. */\nexport function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError {\n\tconst candidate = error as {\n\t\tcode?: unknown\n\t\tcontext?: unknown\n\t\tmessage?: unknown\n\t\tname?: unknown\n\t\tstack?: unknown\n\t}\n\tconst message = typeof candidate?.message === 'string' ? candidate.message : String(error)\n\tconst name = typeof candidate?.name === 'string' ? candidate.name : 'Error'\n\tconst cause = new Error(message)\n\tcause.name = name\n\tif (typeof candidate?.stack === 'string') cause.stack = candidate.stack\n\tlet code = typeof candidate?.code === 'string' ? candidate.code : 'INITIALIZATION_FAILED'\n\tif (code === 'INITIALIZATION_FAILED' && cause.name === 'QuotaExceededError') {\n\t\tcode = 'STORAGE_QUOTA_EXCEEDED'\n\t}\n\tconst metadata: Record<string, string | number | boolean | null> = {}\n\tif (candidate?.context && typeof candidate.context === 'object') {\n\t\tfor (const [key, value] of Object.entries(candidate.context)) {\n\t\t\tif (SENSITIVE_METADATA_KEY.test(key)) continue\n\t\t\tif (\n\t\t\t\ttypeof value === 'string' ||\n\t\t\t\ttypeof value === 'number' ||\n\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\tvalue === null\n\t\t\t) {\n\t\t\t\tmetadata[key] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn { code, name: cause.name, message: cause.message, metadata, cause }\n}\n\n/**\n * Owns the security-sensitive app lifetime for shared-browser applications.\n * The previous app is fully closed before a different user's app is created,\n * and no stale provider tree is rendered across that boundary.\n */\nexport function AuthBoundKoraProvider({\n\tauthClient,\n\tcreateApp,\n\tsignedOut = null,\n\tfallback = null,\n\terror: renderError,\n\tchildren,\n}: AuthBoundKoraProviderProps): ReactNode {\n\tconst [app, setApp] = useState<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst [state, setState] = useState<AuthSyncState>({ state: 'loading' })\n\tconst [initError, setInitError] = useState<{\n\t\terror: AuthBoundKoraInitializationError\n\t\tsession: AuthBoundKoraSession\n\t} | null>(null)\n\tconst active = useRef<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst createAppRef = useRef(createApp)\n\tcreateAppRef.current = createApp\n\tconst activeUserId = useRef<string | null>(null)\n\tconst generation = useRef(0)\n\tconst transition = useRef(Promise.resolve())\n\tconst reconcileRef = useRef<() => void>(() => {})\n\n\tuseEffect(() => {\n\t\tlet disposed = false\n\t\tconst reconcile = (): void => {\n\t\t\tconst currentGeneration = ++generation.current\n\t\t\ttransition.current = transition.current\n\t\t\t\t.catch(() => {})\n\t\t\t\t.then(async () => {\n\t\t\t\t\tsetInitError(null)\n\t\t\t\t\tconst next =\n\t\t\t\t\t\t(await authClient.resolveSyncState?.()) ??\n\t\t\t\t\t\t({ state: 'signed-out', mayConnectAnonymously: false } as const)\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tconst previous = active.current\n\t\t\t\t\t// Same-user token/role refreshes stay on the same database and app instance.\n\t\t\t\t\tif (next.state === 'authenticated' && next.userId === activeUserId.current && previous) {\n\t\t\t\t\t\tsetState(next)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetApp(null)\n\t\t\t\t\tactive.current = null\n\t\t\t\t\tactiveUserId.current = null\n\t\t\t\t\tif (previous) await previous.close()\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tsetState(next)\n\t\t\t\t\tif (next.state !== 'authenticated') return\n\t\t\t\t\tconst created = createAppRef.current(next)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait created.ready\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tactive.current = created\n\t\t\t\t\tactiveUserId.current = next.userId\n\t\t\t\t\tsetApp(created)\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tif (!disposed && currentGeneration === generation.current) {\n\t\t\t\t\t\tvoid authClient.resolveSyncState?.().then((failedSession) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!disposed &&\n\t\t\t\t\t\t\t\tcurrentGeneration === generation.current &&\n\t\t\t\t\t\t\t\tfailedSession?.state === 'authenticated'\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tsetInitError({\n\t\t\t\t\t\t\t\t\terror: classifyKoraInitializationError(error),\n\t\t\t\t\t\t\t\t\tsession: { userId: failedSession.userId },\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t\treconcileRef.current = reconcile\n\t\treconcile()\n\t\tconst unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {})\n\t\treturn () => {\n\t\t\tdisposed = true\n\t\t\tgeneration.current++\n\t\t\tunsubscribe()\n\t\t\tconst previous = active.current\n\t\t\tactive.current = null\n\t\t\tactiveUserId.current = null\n\t\t\tif (previous) void previous.close()\n\t\t}\n\t}, [authClient])\n\n\tif (initError) {\n\t\tif (renderError) {\n\t\t\treturn renderError({\n\t\t\t\terror: initError.error,\n\t\t\t\tsession: initError.session,\n\t\t\t\tretry: () => reconcileRef.current(),\n\t\t\t})\n\t\t}\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.error.message,\n\t\t)\n\t}\n\tif (state.state === 'signed-out' || state.state === 'anonymous') return signedOut\n\tif (!app) return fallback\n\treturn createElement(KoraProvider, { app, fallback }, children)\n}\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\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 to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\tconst lastSnapshotRef = useRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: descriptorKey intentionally re-runs the effect when the query descriptor changes, even though the effect reads the query via queryRef\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst getSnapshot = useCallback((): readonly T[] => {\n\t\tif (!enabled) {\n\t\t\tlastSnapshotRef.current = EMPTY_ARRAY as readonly T[]\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore.hasSnapshot()) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tconst snapshot = queryStore.getSnapshot()\n\t\tlastSnapshotRef.current = snapshot\n\t\treturn snapshot\n\t}, [enabled, queryStore])\n\n\treturn useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\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 = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\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 collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["import_react","import_store","import_react","import_react","import_react","import_react","import_react","import_store","import_react","import_react","import_sync","import_react","EMPTY_ARRAY"]}
package/dist/index.d.cts CHANGED
@@ -54,14 +54,36 @@ interface AuthBoundKoraProviderProps {
54
54
  };
55
55
  signedOut?: ReactNode;
56
56
  fallback?: ReactNode;
57
+ error?: (context: AuthBoundKoraErrorContext) => ReactNode;
57
58
  children?: ReactNode;
58
59
  }
60
+ interface AuthBoundKoraSession {
61
+ /** The authenticated identity only. Access tokens are deliberately omitted. */
62
+ userId: string;
63
+ }
64
+ interface AuthBoundKoraInitializationError {
65
+ /** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */
66
+ code: string;
67
+ name: string;
68
+ message: string;
69
+ /** Sanitized primitive metadata. Credential-shaped keys are always removed. */
70
+ metadata: Readonly<Record<string, string | number | boolean | null>>;
71
+ /** Sanitized Error for logging; custom credential-bearing properties are omitted. */
72
+ cause: Error;
73
+ }
74
+ interface AuthBoundKoraErrorContext {
75
+ error: AuthBoundKoraInitializationError;
76
+ retry(): void;
77
+ session: AuthBoundKoraSession;
78
+ }
79
+ /** Classify initialization failures without requiring applications to parse copy. */
80
+ declare function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError;
59
81
  /**
60
82
  * Owns the security-sensitive app lifetime for shared-browser applications.
61
83
  * The previous app is fully closed before a different user's app is created,
62
84
  * and no stale provider tree is rendered across that boundary.
63
85
  */
64
- declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, children, }: AuthBoundKoraProviderProps): ReactNode;
86
+ declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, error: renderError, children, }: AuthBoundKoraProviderProps): ReactNode;
65
87
 
66
88
  /**
67
89
  * React hook that returns the Kora app instance from context.
@@ -143,4 +165,4 @@ declare function usePresence(user: {
143
165
  */
144
166
  declare function useCollaborators(): AwarenessState[];
145
167
 
146
- export { AuthBoundKoraProvider, type AuthBoundKoraProviderProps, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
168
+ export { type AuthBoundKoraErrorContext, type AuthBoundKoraInitializationError, AuthBoundKoraProvider, type AuthBoundKoraProviderProps, type AuthBoundKoraSession, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, classifyKoraInitializationError, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
package/dist/index.d.ts CHANGED
@@ -54,14 +54,36 @@ interface AuthBoundKoraProviderProps {
54
54
  };
55
55
  signedOut?: ReactNode;
56
56
  fallback?: ReactNode;
57
+ error?: (context: AuthBoundKoraErrorContext) => ReactNode;
57
58
  children?: ReactNode;
58
59
  }
60
+ interface AuthBoundKoraSession {
61
+ /** The authenticated identity only. Access tokens are deliberately omitted. */
62
+ userId: string;
63
+ }
64
+ interface AuthBoundKoraInitializationError {
65
+ /** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */
66
+ code: string;
67
+ name: string;
68
+ message: string;
69
+ /** Sanitized primitive metadata. Credential-shaped keys are always removed. */
70
+ metadata: Readonly<Record<string, string | number | boolean | null>>;
71
+ /** Sanitized Error for logging; custom credential-bearing properties are omitted. */
72
+ cause: Error;
73
+ }
74
+ interface AuthBoundKoraErrorContext {
75
+ error: AuthBoundKoraInitializationError;
76
+ retry(): void;
77
+ session: AuthBoundKoraSession;
78
+ }
79
+ /** Classify initialization failures without requiring applications to parse copy. */
80
+ declare function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError;
59
81
  /**
60
82
  * Owns the security-sensitive app lifetime for shared-browser applications.
61
83
  * The previous app is fully closed before a different user's app is created,
62
84
  * and no stale provider tree is rendered across that boundary.
63
85
  */
64
- declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, children, }: AuthBoundKoraProviderProps): ReactNode;
86
+ declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, error: renderError, children, }: AuthBoundKoraProviderProps): ReactNode;
65
87
 
66
88
  /**
67
89
  * React hook that returns the Kora app instance from context.
@@ -143,4 +165,4 @@ declare function usePresence(user: {
143
165
  */
144
166
  declare function useCollaborators(): AwarenessState[];
145
167
 
146
- export { AuthBoundKoraProvider, type AuthBoundKoraProviderProps, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
168
+ export { type AuthBoundKoraErrorContext, type AuthBoundKoraInitializationError, AuthBoundKoraProvider, type AuthBoundKoraProviderProps, type AuthBoundKoraSession, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, classifyKoraInitializationError, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
package/dist/index.js CHANGED
@@ -96,11 +96,35 @@ function useKoraContext() {
96
96
 
97
97
  // src/context/auth-bound-kora-provider.ts
98
98
  import { createElement as createElement2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
99
+ var SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i;
100
+ function classifyKoraInitializationError(error) {
101
+ const candidate = error;
102
+ const message = typeof candidate?.message === "string" ? candidate.message : String(error);
103
+ const name = typeof candidate?.name === "string" ? candidate.name : "Error";
104
+ const cause = new Error(message);
105
+ cause.name = name;
106
+ if (typeof candidate?.stack === "string") cause.stack = candidate.stack;
107
+ let code = typeof candidate?.code === "string" ? candidate.code : "INITIALIZATION_FAILED";
108
+ if (code === "INITIALIZATION_FAILED" && cause.name === "QuotaExceededError") {
109
+ code = "STORAGE_QUOTA_EXCEEDED";
110
+ }
111
+ const metadata = {};
112
+ if (candidate?.context && typeof candidate.context === "object") {
113
+ for (const [key, value] of Object.entries(candidate.context)) {
114
+ if (SENSITIVE_METADATA_KEY.test(key)) continue;
115
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
116
+ metadata[key] = value;
117
+ }
118
+ }
119
+ }
120
+ return { code, name: cause.name, message: cause.message, metadata, cause };
121
+ }
99
122
  function AuthBoundKoraProvider({
100
123
  authClient,
101
124
  createApp,
102
125
  signedOut = null,
103
126
  fallback = null,
127
+ error: renderError,
104
128
  children
105
129
  }) {
106
130
  const [app, setApp] = useState2(null);
@@ -112,6 +136,8 @@ function AuthBoundKoraProvider({
112
136
  const activeUserId = useRef2(null);
113
137
  const generation = useRef2(0);
114
138
  const transition = useRef2(Promise.resolve());
139
+ const reconcileRef = useRef2(() => {
140
+ });
115
141
  useEffect2(() => {
116
142
  let disposed = false;
117
143
  const reconcile = () => {
@@ -149,10 +175,18 @@ function AuthBoundKoraProvider({
149
175
  setApp(created);
150
176
  }).catch((error) => {
151
177
  if (!disposed && currentGeneration === generation.current) {
152
- setInitError(error instanceof Error ? error : new Error(String(error)));
178
+ void authClient.resolveSyncState?.().then((failedSession) => {
179
+ if (!disposed && currentGeneration === generation.current && failedSession?.state === "authenticated") {
180
+ setInitError({
181
+ error: classifyKoraInitializationError(error),
182
+ session: { userId: failedSession.userId }
183
+ });
184
+ }
185
+ });
153
186
  }
154
187
  });
155
188
  };
189
+ reconcileRef.current = reconcile;
156
190
  reconcile();
157
191
  const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
158
192
  });
@@ -167,11 +201,18 @@ function AuthBoundKoraProvider({
167
201
  };
168
202
  }, [authClient]);
169
203
  if (initError) {
204
+ if (renderError) {
205
+ return renderError({
206
+ error: initError.error,
207
+ session: initError.session,
208
+ retry: () => reconcileRef.current()
209
+ });
210
+ }
170
211
  return createElement2(
171
212
  "div",
172
213
  { style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
173
214
  createElement2("strong", null, "Kora initialization error: "),
174
- initError.message
215
+ initError.error.message
175
216
  );
176
217
  }
177
218
  if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
@@ -437,6 +478,7 @@ function useCollaborators() {
437
478
  export {
438
479
  AuthBoundKoraProvider,
439
480
  KoraProvider,
481
+ classifyKoraInitializationError,
440
482
  useApp,
441
483
  useCollaborators,
442
484
  useCollection,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context/kora-context.ts","../src/context/auth-bound-kora-provider.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\tcreateContext,\n\tcreateElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\tif (fallbackQueryStoreCache.current === null) {\n\t\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import type { AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraAppLike } from '../types'\nimport { KoraProvider } from './kora-context'\n\nexport interface AuthBoundKoraProviderProps {\n\tauthClient: AuthSyncBinding\n\tcreateApp: (\n\t\tsession: Extract<AuthSyncState, { state: 'authenticated' }>,\n\t) => KoraAppLike & { close(): Promise<void> }\n\tsignedOut?: ReactNode\n\tfallback?: ReactNode\n\tchildren?: ReactNode\n}\n\n/**\n * Owns the security-sensitive app lifetime for shared-browser applications.\n * The previous app is fully closed before a different user's app is created,\n * and no stale provider tree is rendered across that boundary.\n */\nexport function AuthBoundKoraProvider({\n\tauthClient,\n\tcreateApp,\n\tsignedOut = null,\n\tfallback = null,\n\tchildren,\n}: AuthBoundKoraProviderProps): ReactNode {\n\tconst [app, setApp] = useState<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst [state, setState] = useState<AuthSyncState>({ state: 'loading' })\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst active = useRef<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst createAppRef = useRef(createApp)\n\tcreateAppRef.current = createApp\n\tconst activeUserId = useRef<string | null>(null)\n\tconst generation = useRef(0)\n\tconst transition = useRef(Promise.resolve())\n\n\tuseEffect(() => {\n\t\tlet disposed = false\n\t\tconst reconcile = (): void => {\n\t\t\tconst currentGeneration = ++generation.current\n\t\t\ttransition.current = transition.current\n\t\t\t\t.catch(() => {})\n\t\t\t\t.then(async () => {\n\t\t\t\t\tsetInitError(null)\n\t\t\t\t\tconst next =\n\t\t\t\t\t\t(await authClient.resolveSyncState?.()) ??\n\t\t\t\t\t\t({ state: 'signed-out', mayConnectAnonymously: false } as const)\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tconst previous = active.current\n\t\t\t\t\t// Same-user token/role refreshes stay on the same database and app instance.\n\t\t\t\t\tif (next.state === 'authenticated' && next.userId === activeUserId.current && previous) {\n\t\t\t\t\t\tsetState(next)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetApp(null)\n\t\t\t\t\tactive.current = null\n\t\t\t\t\tactiveUserId.current = null\n\t\t\t\t\tif (previous) await previous.close()\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tsetState(next)\n\t\t\t\t\tif (next.state !== 'authenticated') return\n\t\t\t\t\tconst created = createAppRef.current(next)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait created.ready\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tactive.current = created\n\t\t\t\t\tactiveUserId.current = next.userId\n\t\t\t\t\tsetApp(created)\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tif (!disposed && currentGeneration === generation.current) {\n\t\t\t\t\t\tsetInitError(error instanceof Error ? error : new Error(String(error)))\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t\treconcile()\n\t\tconst unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {})\n\t\treturn () => {\n\t\t\tdisposed = true\n\t\t\tgeneration.current++\n\t\t\tunsubscribe()\n\t\t\tconst previous = active.current\n\t\t\tactive.current = null\n\t\t\tactiveUserId.current = null\n\t\t\tif (previous) void previous.close()\n\t\t}\n\t}, [authClient])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\tif (state.state === 'signed-out' || state.state === 'anonymous') return signedOut\n\tif (!app) return fallback\n\treturn createElement(KoraProvider, { app, fallback }, children)\n}\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\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 to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\tconst lastSnapshotRef = useRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: descriptorKey intentionally re-runs the effect when the query descriptor changes, even though the effect reads the query via queryRef\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst getSnapshot = useCallback((): readonly T[] => {\n\t\tif (!enabled) {\n\t\t\tlastSnapshotRef.current = EMPTY_ARRAY as readonly T[]\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore.hasSnapshot()) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tconst snapshot = queryStore.getSnapshot()\n\t\tlastSnapshotRef.current = snapshot\n\t\treturn snapshot\n\t}, [enabled, queryStore])\n\n\treturn useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\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 = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\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 collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["createElement","useEffect","useRef","useState","useState","useRef","useEffect","createElement","useEffect","useRef","useState","useRef","useState","useEffect","useRef","useSyncExternalStore","useEffect","useRef","useRef","useSyncExternalStore","useSyncExternalStore","useSyncExternalStore","useMemo","useMemo","useCallback","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useCallback","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
1
+ {"version":3,"sources":["../src/context/kora-context.ts","../src/context/auth-bound-kora-provider.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\tcreateContext,\n\tcreateElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\tif (fallbackQueryStoreCache.current === null) {\n\t\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import type { AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraAppLike } from '../types'\nimport { KoraProvider } from './kora-context'\n\nexport interface AuthBoundKoraProviderProps {\n\tauthClient: AuthSyncBinding\n\tcreateApp: (\n\t\tsession: Extract<AuthSyncState, { state: 'authenticated' }>,\n\t) => KoraAppLike & { close(): Promise<void> }\n\tsignedOut?: ReactNode\n\tfallback?: ReactNode\n\terror?: (context: AuthBoundKoraErrorContext) => ReactNode\n\tchildren?: ReactNode\n}\n\nexport interface AuthBoundKoraSession {\n\t/** The authenticated identity only. Access tokens are deliberately omitted. */\n\tuserId: string\n}\n\nexport interface AuthBoundKoraInitializationError {\n\t/** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */\n\tcode: string\n\tname: string\n\tmessage: string\n\t/** Sanitized primitive metadata. Credential-shaped keys are always removed. */\n\tmetadata: Readonly<Record<string, string | number | boolean | null>>\n\t/** Sanitized Error for logging; custom credential-bearing properties are omitted. */\n\tcause: Error\n}\n\nexport interface AuthBoundKoraErrorContext {\n\terror: AuthBoundKoraInitializationError\n\tretry(): void\n\tsession: AuthBoundKoraSession\n}\n\nconst SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i\n\n/** Classify initialization failures without requiring applications to parse copy. */\nexport function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError {\n\tconst candidate = error as {\n\t\tcode?: unknown\n\t\tcontext?: unknown\n\t\tmessage?: unknown\n\t\tname?: unknown\n\t\tstack?: unknown\n\t}\n\tconst message = typeof candidate?.message === 'string' ? candidate.message : String(error)\n\tconst name = typeof candidate?.name === 'string' ? candidate.name : 'Error'\n\tconst cause = new Error(message)\n\tcause.name = name\n\tif (typeof candidate?.stack === 'string') cause.stack = candidate.stack\n\tlet code = typeof candidate?.code === 'string' ? candidate.code : 'INITIALIZATION_FAILED'\n\tif (code === 'INITIALIZATION_FAILED' && cause.name === 'QuotaExceededError') {\n\t\tcode = 'STORAGE_QUOTA_EXCEEDED'\n\t}\n\tconst metadata: Record<string, string | number | boolean | null> = {}\n\tif (candidate?.context && typeof candidate.context === 'object') {\n\t\tfor (const [key, value] of Object.entries(candidate.context)) {\n\t\t\tif (SENSITIVE_METADATA_KEY.test(key)) continue\n\t\t\tif (\n\t\t\t\ttypeof value === 'string' ||\n\t\t\t\ttypeof value === 'number' ||\n\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\tvalue === null\n\t\t\t) {\n\t\t\t\tmetadata[key] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn { code, name: cause.name, message: cause.message, metadata, cause }\n}\n\n/**\n * Owns the security-sensitive app lifetime for shared-browser applications.\n * The previous app is fully closed before a different user's app is created,\n * and no stale provider tree is rendered across that boundary.\n */\nexport function AuthBoundKoraProvider({\n\tauthClient,\n\tcreateApp,\n\tsignedOut = null,\n\tfallback = null,\n\terror: renderError,\n\tchildren,\n}: AuthBoundKoraProviderProps): ReactNode {\n\tconst [app, setApp] = useState<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst [state, setState] = useState<AuthSyncState>({ state: 'loading' })\n\tconst [initError, setInitError] = useState<{\n\t\terror: AuthBoundKoraInitializationError\n\t\tsession: AuthBoundKoraSession\n\t} | null>(null)\n\tconst active = useRef<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst createAppRef = useRef(createApp)\n\tcreateAppRef.current = createApp\n\tconst activeUserId = useRef<string | null>(null)\n\tconst generation = useRef(0)\n\tconst transition = useRef(Promise.resolve())\n\tconst reconcileRef = useRef<() => void>(() => {})\n\n\tuseEffect(() => {\n\t\tlet disposed = false\n\t\tconst reconcile = (): void => {\n\t\t\tconst currentGeneration = ++generation.current\n\t\t\ttransition.current = transition.current\n\t\t\t\t.catch(() => {})\n\t\t\t\t.then(async () => {\n\t\t\t\t\tsetInitError(null)\n\t\t\t\t\tconst next =\n\t\t\t\t\t\t(await authClient.resolveSyncState?.()) ??\n\t\t\t\t\t\t({ state: 'signed-out', mayConnectAnonymously: false } as const)\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tconst previous = active.current\n\t\t\t\t\t// Same-user token/role refreshes stay on the same database and app instance.\n\t\t\t\t\tif (next.state === 'authenticated' && next.userId === activeUserId.current && previous) {\n\t\t\t\t\t\tsetState(next)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetApp(null)\n\t\t\t\t\tactive.current = null\n\t\t\t\t\tactiveUserId.current = null\n\t\t\t\t\tif (previous) await previous.close()\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tsetState(next)\n\t\t\t\t\tif (next.state !== 'authenticated') return\n\t\t\t\t\tconst created = createAppRef.current(next)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait created.ready\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tactive.current = created\n\t\t\t\t\tactiveUserId.current = next.userId\n\t\t\t\t\tsetApp(created)\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tif (!disposed && currentGeneration === generation.current) {\n\t\t\t\t\t\tvoid authClient.resolveSyncState?.().then((failedSession) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!disposed &&\n\t\t\t\t\t\t\t\tcurrentGeneration === generation.current &&\n\t\t\t\t\t\t\t\tfailedSession?.state === 'authenticated'\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tsetInitError({\n\t\t\t\t\t\t\t\t\terror: classifyKoraInitializationError(error),\n\t\t\t\t\t\t\t\t\tsession: { userId: failedSession.userId },\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t\treconcileRef.current = reconcile\n\t\treconcile()\n\t\tconst unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {})\n\t\treturn () => {\n\t\t\tdisposed = true\n\t\t\tgeneration.current++\n\t\t\tunsubscribe()\n\t\t\tconst previous = active.current\n\t\t\tactive.current = null\n\t\t\tactiveUserId.current = null\n\t\t\tif (previous) void previous.close()\n\t\t}\n\t}, [authClient])\n\n\tif (initError) {\n\t\tif (renderError) {\n\t\t\treturn renderError({\n\t\t\t\terror: initError.error,\n\t\t\t\tsession: initError.session,\n\t\t\t\tretry: () => reconcileRef.current(),\n\t\t\t})\n\t\t}\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.error.message,\n\t\t)\n\t}\n\tif (state.state === 'signed-out' || state.state === 'anonymous') return signedOut\n\tif (!app) return fallback\n\treturn createElement(KoraProvider, { app, fallback }, children)\n}\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\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 to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\tconst lastSnapshotRef = useRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: descriptorKey intentionally re-runs the effect when the query descriptor changes, even though the effect reads the query via queryRef\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst getSnapshot = useCallback((): readonly T[] => {\n\t\tif (!enabled) {\n\t\t\tlastSnapshotRef.current = EMPTY_ARRAY as readonly T[]\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore.hasSnapshot()) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tconst snapshot = queryStore.getSnapshot()\n\t\tlastSnapshotRef.current = snapshot\n\t\treturn snapshot\n\t}, [enabled, queryStore])\n\n\treturn useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\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 = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\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 collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["createElement","useEffect","useRef","useState","useState","useRef","useEffect","createElement","useEffect","useRef","useState","useRef","useState","useEffect","useRef","useSyncExternalStore","useEffect","useRef","useRef","useSyncExternalStore","useSyncExternalStore","useSyncExternalStore","useMemo","useMemo","useCallback","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useCallback","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korajs/react",
3
- "version": "1.0.0-beta.11",
3
+ "version": "1.0.0-beta.12",
4
4
  "description": "Kora.js React hooks and bindings for offline-first applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -32,9 +32,9 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "yjs": "^13.6.30",
35
- "@korajs/core": "1.0.0-beta.11",
36
- "@korajs/store": "1.0.0-beta.11",
37
- "@korajs/sync": "1.0.0-beta.11"
35
+ "@korajs/core": "1.0.0-beta.12",
36
+ "@korajs/sync": "1.0.0-beta.12",
37
+ "@korajs/store": "1.0.0-beta.12"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/jest-dom": "^6.0.0",