@korajs/react 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -166,74 +166,102 @@ function useQuery(query, options) {
166
166
 
167
167
  // src/hooks/use-mutation.ts
168
168
  var import_bindings = require("@korajs/core/bindings");
169
+ var import_react4 = require("react");
170
+
171
+ // src/hooks/use-controller.ts
169
172
  var import_react3 = require("react");
173
+ function useController(create, destroy, deps) {
174
+ const controllerRef = (0, import_react3.useRef)(null);
175
+ const createRef = (0, import_react3.useRef)(create);
176
+ createRef.current = create;
177
+ const [, forceRender] = (0, import_react3.useReducer)((count) => count + 1, 0);
178
+ const getController = (0, import_react3.useRef)(() => {
179
+ if (controllerRef.current === null) {
180
+ controllerRef.current = createRef.current();
181
+ }
182
+ return controllerRef.current;
183
+ }).current;
184
+ (0, import_react3.useEffect)(() => {
185
+ if (controllerRef.current === null) {
186
+ controllerRef.current = createRef.current();
187
+ forceRender();
188
+ }
189
+ return () => {
190
+ const controller = controllerRef.current;
191
+ controllerRef.current = null;
192
+ if (controller !== null) {
193
+ destroy(controller);
194
+ }
195
+ };
196
+ }, deps);
197
+ return getController;
198
+ }
199
+
200
+ // src/hooks/use-mutation.ts
170
201
  function useMutation(mutationFn, options) {
171
- const fnRef = (0, import_react3.useRef)(mutationFn);
202
+ const fnRef = (0, import_react4.useRef)(mutationFn);
172
203
  fnRef.current = mutationFn;
173
- const optionsRef = (0, import_react3.useRef)(options);
204
+ const optionsRef = (0, import_react4.useRef)(options);
174
205
  optionsRef.current = options;
175
- const controller = (0, import_react3.useMemo)(
206
+ const getController = useController(
176
207
  () => (0, import_bindings.createMutationController)({
177
208
  mutationFn: (...args) => fnRef.current(...args),
178
209
  resolveOptions: () => optionsRef.current
179
210
  }),
211
+ (controller) => controller.destroy(),
180
212
  []
181
213
  );
182
- (0, import_react3.useEffect)(() => () => controller.destroy(), [controller]);
183
- const state = (0, import_react3.useSyncExternalStore)(
184
- (onStoreChange) => controller.subscribe(onStoreChange),
185
- () => controller.getSnapshot(),
186
- () => controller.getSnapshot()
214
+ const state = (0, import_react4.useSyncExternalStore)(
215
+ (onStoreChange) => getController().subscribe(onStoreChange),
216
+ () => getController().getSnapshot(),
217
+ () => getController().getSnapshot()
187
218
  );
188
219
  return {
189
- mutate: (...args) => controller.mutate(...args),
190
- mutateAsync: (...args) => controller.mutateAsync(...args),
220
+ mutate: (...args) => getController().mutate(...args),
221
+ mutateAsync: (...args) => getController().mutateAsync(...args),
191
222
  isLoading: state.isLoading,
192
223
  error: state.error,
193
- reset: () => controller.reset()
224
+ reset: () => getController().reset()
194
225
  };
195
226
  }
196
227
 
197
228
  // src/hooks/use-sync-status.ts
198
229
  var import_sync = require("@korajs/sync");
199
- var import_react4 = require("react");
230
+ var import_react5 = require("react");
200
231
  function useSyncStatus() {
201
232
  const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
202
- const controller = (0, import_react4.useMemo)(
233
+ const getController = useController(
203
234
  () => (0, import_sync.createSyncStatusController)({
204
235
  syncEngine,
205
236
  subscribeSyncStatus,
206
237
  events: subscribeSyncStatus ? null : events
207
238
  }),
239
+ (controller) => controller.destroy(),
208
240
  [syncEngine, subscribeSyncStatus, events]
209
241
  );
210
- (0, import_react4.useEffect)(() => () => controller.destroy(), [controller]);
211
- return (0, import_react4.useSyncExternalStore)(
212
- (onStoreChange) => controller.subscribe(onStoreChange),
213
- () => controller.getSnapshot(),
214
- () => controller.getSnapshot()
242
+ return (0, import_react5.useSyncExternalStore)(
243
+ (onStoreChange) => getController().subscribe(onStoreChange),
244
+ () => getController().getSnapshot(),
245
+ () => getController().getSnapshot()
215
246
  );
216
247
  }
217
248
 
218
249
  // src/hooks/use-collection.ts
219
- var import_react5 = require("react");
250
+ var import_react6 = require("react");
220
251
  function useCollection(name) {
221
252
  const { store } = useKoraContext();
222
- return (0, import_react5.useMemo)(() => {
253
+ return (0, import_react6.useMemo)(() => {
223
254
  return store.collection(name);
224
255
  }, [store, name]);
225
256
  }
226
257
 
227
258
  // src/hooks/use-rich-text.ts
228
259
  var import_store3 = require("@korajs/store");
229
- var import_react6 = require("react");
260
+ var import_react7 = require("react");
230
261
  function useRichText(collectionName, recordId, fieldName, options) {
231
262
  const { store, syncEngine } = useKoraContext();
232
- const collection = (0, import_react6.useMemo)(
233
- () => store.collection(collectionName),
234
- [store, collectionName]
235
- );
236
- const controller = (0, import_react6.useMemo)(
263
+ const collection = (0, import_react7.useMemo)(() => store.collection(collectionName), [store, collectionName]);
264
+ const getController = useController(
237
265
  () => (0, import_store3.createRichTextController)({
238
266
  collection,
239
267
  collectionName,
@@ -244,25 +272,29 @@ function useRichText(collectionName, recordId, fieldName, options) {
244
272
  useDocChannel: options?.useDocChannel,
245
273
  user: options?.user
246
274
  }),
275
+ (controller) => controller.destroy(),
247
276
  [collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
248
277
  );
249
- (0, import_react6.useEffect)(() => {
250
- controller.setUser(options?.user);
251
- }, [controller, options?.user]);
252
- (0, import_react6.useEffect)(() => () => controller.destroy(), [controller]);
253
- const snapshot = (0, import_react6.useSyncExternalStore)(
254
- (onStoreChange) => controller.subscribe(onStoreChange),
255
- () => controller.getSnapshot(),
256
- () => controller.getSnapshot()
278
+ (0, import_react7.useEffect)(() => {
279
+ getController().setUser(options?.user);
280
+ }, [getController, options?.user]);
281
+ const snapshot = (0, import_react7.useSyncExternalStore)(
282
+ (onStoreChange) => getController().subscribe(onStoreChange),
283
+ () => getController().getSnapshot(),
284
+ () => getController().getSnapshot()
257
285
  );
258
- const undo = (0, import_react6.useCallback)(() => controller.undo(), [controller]);
259
- const redo = (0, import_react6.useCallback)(() => controller.redo(), [controller]);
260
- const setCursor = (0, import_react6.useCallback)(
261
- (anchor, head) => controller.setCursor(anchor, head),
262
- [controller]
286
+ const undo = (0, import_react7.useCallback)(() => {
287
+ getController().undo();
288
+ }, [getController]);
289
+ const redo = (0, import_react7.useCallback)(() => {
290
+ getController().redo();
291
+ }, [getController]);
292
+ const setCursor = (0, import_react7.useCallback)(
293
+ (anchor, head) => getController().setCursor(anchor, head),
294
+ [getController]
263
295
  );
264
- const clearCursor = (0, import_react6.useCallback)(() => controller.clearCursor(), [controller]);
265
- return buildResult(controller, snapshot, undo, redo, setCursor, clearCursor);
296
+ const clearCursor = (0, import_react7.useCallback)(() => getController().clearCursor(), [getController]);
297
+ return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
266
298
  }
267
299
  function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
268
300
  return {
@@ -281,13 +313,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
281
313
  }
282
314
 
283
315
  // src/hooks/use-presence.ts
284
- var import_react7 = require("react");
316
+ var import_react8 = require("react");
285
317
  function usePresence(user) {
286
318
  const { syncEngine } = useKoraContext();
287
319
  const name = user?.name ?? null;
288
320
  const color = user?.color ?? null;
289
321
  const avatar = user?.avatar ?? null;
290
- (0, import_react7.useEffect)(() => {
322
+ (0, import_react8.useEffect)(() => {
291
323
  if (!syncEngine || !name || !color) return;
292
324
  const awareness = syncEngine.getAwarenessManager();
293
325
  awareness.setLocalState({
@@ -301,12 +333,12 @@ function usePresence(user) {
301
333
 
302
334
  // src/hooks/use-collaborators.ts
303
335
  var import_sync2 = require("@korajs/sync");
304
- var import_react8 = require("react");
336
+ var import_react9 = require("react");
305
337
  var EMPTY_ARRAY2 = [];
306
338
  function useCollaborators() {
307
339
  const { syncEngine } = useKoraContext();
308
- const snapshotRef = (0, import_react8.useRef)(EMPTY_ARRAY2);
309
- const subscribe = (0, import_react8.useCallback)(
340
+ const snapshotRef = (0, import_react9.useRef)(EMPTY_ARRAY2);
341
+ const subscribe = (0, import_react9.useCallback)(
310
342
  (onStoreChange) => {
311
343
  if (!syncEngine) {
312
344
  snapshotRef.current = EMPTY_ARRAY2;
@@ -321,13 +353,13 @@ function useCollaborators() {
321
353
  },
322
354
  [syncEngine]
323
355
  );
324
- const getSnapshot = (0, import_react8.useCallback)(() => snapshotRef.current, []);
325
- (0, import_react8.useEffect)(() => {
356
+ const getSnapshot = (0, import_react9.useCallback)(() => snapshotRef.current, []);
357
+ (0, import_react9.useEffect)(() => {
326
358
  if (!syncEngine) {
327
359
  snapshotRef.current = EMPTY_ARRAY2;
328
360
  }
329
361
  }, [syncEngine]);
330
- return (0, import_react8.useSyncExternalStore)(subscribe, getSnapshot);
362
+ return (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot);
331
363
  }
332
364
  // Annotate the CommonJS export names for ESM import in node:
333
365
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context/kora-context.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.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'\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 { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } 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\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 { 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 { 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\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\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\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\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 controller = useMemo(\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[],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => controller.reset(),\n\t}\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\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\tconst controller = useMemo(\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[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.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'\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(\n\t\t() => store.collection(collectionName),\n\t\t[store, collectionName],\n\t)\n\n\tconst controller = useMemo(\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[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tcontroller.setUser(options?.user)\n\t}, [controller, options?.user])\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => controller.undo(), [controller])\n\tconst redo = useCallback(() => controller.redo(), [controller])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\t[controller],\n\t)\n\tconst clearCursor = useCallback(() => controller.clearCursor(), [controller])\n\n\treturn buildResult(controller, 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_store","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/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'\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 { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } 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\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 { 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 { 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\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\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\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\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_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.js CHANGED
@@ -132,74 +132,102 @@ function useQuery(query, options) {
132
132
 
133
133
  // src/hooks/use-mutation.ts
134
134
  import { createMutationController } from "@korajs/core/bindings";
135
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useSyncExternalStore as useSyncExternalStore2 } from "react";
135
+ import { useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
136
+
137
+ // src/hooks/use-controller.ts
138
+ import { useEffect as useEffect3, useReducer, useRef as useRef3 } from "react";
139
+ function useController(create, destroy, deps) {
140
+ const controllerRef = useRef3(null);
141
+ const createRef = useRef3(create);
142
+ createRef.current = create;
143
+ const [, forceRender] = useReducer((count) => count + 1, 0);
144
+ const getController = useRef3(() => {
145
+ if (controllerRef.current === null) {
146
+ controllerRef.current = createRef.current();
147
+ }
148
+ return controllerRef.current;
149
+ }).current;
150
+ useEffect3(() => {
151
+ if (controllerRef.current === null) {
152
+ controllerRef.current = createRef.current();
153
+ forceRender();
154
+ }
155
+ return () => {
156
+ const controller = controllerRef.current;
157
+ controllerRef.current = null;
158
+ if (controller !== null) {
159
+ destroy(controller);
160
+ }
161
+ };
162
+ }, deps);
163
+ return getController;
164
+ }
165
+
166
+ // src/hooks/use-mutation.ts
136
167
  function useMutation(mutationFn, options) {
137
- const fnRef = useRef3(mutationFn);
168
+ const fnRef = useRef4(mutationFn);
138
169
  fnRef.current = mutationFn;
139
- const optionsRef = useRef3(options);
170
+ const optionsRef = useRef4(options);
140
171
  optionsRef.current = options;
141
- const controller = useMemo2(
172
+ const getController = useController(
142
173
  () => createMutationController({
143
174
  mutationFn: (...args) => fnRef.current(...args),
144
175
  resolveOptions: () => optionsRef.current
145
176
  }),
177
+ (controller) => controller.destroy(),
146
178
  []
147
179
  );
148
- useEffect3(() => () => controller.destroy(), [controller]);
149
180
  const state = useSyncExternalStore2(
150
- (onStoreChange) => controller.subscribe(onStoreChange),
151
- () => controller.getSnapshot(),
152
- () => controller.getSnapshot()
181
+ (onStoreChange) => getController().subscribe(onStoreChange),
182
+ () => getController().getSnapshot(),
183
+ () => getController().getSnapshot()
153
184
  );
154
185
  return {
155
- mutate: (...args) => controller.mutate(...args),
156
- mutateAsync: (...args) => controller.mutateAsync(...args),
186
+ mutate: (...args) => getController().mutate(...args),
187
+ mutateAsync: (...args) => getController().mutateAsync(...args),
157
188
  isLoading: state.isLoading,
158
189
  error: state.error,
159
- reset: () => controller.reset()
190
+ reset: () => getController().reset()
160
191
  };
161
192
  }
162
193
 
163
194
  // src/hooks/use-sync-status.ts
164
195
  import { createSyncStatusController } from "@korajs/sync";
165
- import { useEffect as useEffect4, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore3 } from "react";
196
+ import { useSyncExternalStore as useSyncExternalStore3 } from "react";
166
197
  function useSyncStatus() {
167
198
  const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
168
- const controller = useMemo3(
199
+ const getController = useController(
169
200
  () => createSyncStatusController({
170
201
  syncEngine,
171
202
  subscribeSyncStatus,
172
203
  events: subscribeSyncStatus ? null : events
173
204
  }),
205
+ (controller) => controller.destroy(),
174
206
  [syncEngine, subscribeSyncStatus, events]
175
207
  );
176
- useEffect4(() => () => controller.destroy(), [controller]);
177
208
  return useSyncExternalStore3(
178
- (onStoreChange) => controller.subscribe(onStoreChange),
179
- () => controller.getSnapshot(),
180
- () => controller.getSnapshot()
209
+ (onStoreChange) => getController().subscribe(onStoreChange),
210
+ () => getController().getSnapshot(),
211
+ () => getController().getSnapshot()
181
212
  );
182
213
  }
183
214
 
184
215
  // src/hooks/use-collection.ts
185
- import { useMemo as useMemo4 } from "react";
216
+ import { useMemo as useMemo2 } from "react";
186
217
  function useCollection(name) {
187
218
  const { store } = useKoraContext();
188
- return useMemo4(() => {
219
+ return useMemo2(() => {
189
220
  return store.collection(name);
190
221
  }, [store, name]);
191
222
  }
192
223
 
193
224
  // src/hooks/use-rich-text.ts
194
225
  import { asRichTextSyncEngine, createRichTextController } from "@korajs/store";
195
- import { useCallback, useEffect as useEffect5, useMemo as useMemo5, useSyncExternalStore as useSyncExternalStore4 } from "react";
226
+ import { useCallback, useEffect as useEffect4, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
196
227
  function useRichText(collectionName, recordId, fieldName, options) {
197
228
  const { store, syncEngine } = useKoraContext();
198
- const collection = useMemo5(
199
- () => store.collection(collectionName),
200
- [store, collectionName]
201
- );
202
- const controller = useMemo5(
229
+ const collection = useMemo3(() => store.collection(collectionName), [store, collectionName]);
230
+ const getController = useController(
203
231
  () => createRichTextController({
204
232
  collection,
205
233
  collectionName,
@@ -210,25 +238,29 @@ function useRichText(collectionName, recordId, fieldName, options) {
210
238
  useDocChannel: options?.useDocChannel,
211
239
  user: options?.user
212
240
  }),
241
+ (controller) => controller.destroy(),
213
242
  [collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
214
243
  );
215
- useEffect5(() => {
216
- controller.setUser(options?.user);
217
- }, [controller, options?.user]);
218
- useEffect5(() => () => controller.destroy(), [controller]);
244
+ useEffect4(() => {
245
+ getController().setUser(options?.user);
246
+ }, [getController, options?.user]);
219
247
  const snapshot = useSyncExternalStore4(
220
- (onStoreChange) => controller.subscribe(onStoreChange),
221
- () => controller.getSnapshot(),
222
- () => controller.getSnapshot()
248
+ (onStoreChange) => getController().subscribe(onStoreChange),
249
+ () => getController().getSnapshot(),
250
+ () => getController().getSnapshot()
223
251
  );
224
- const undo = useCallback(() => controller.undo(), [controller]);
225
- const redo = useCallback(() => controller.redo(), [controller]);
252
+ const undo = useCallback(() => {
253
+ getController().undo();
254
+ }, [getController]);
255
+ const redo = useCallback(() => {
256
+ getController().redo();
257
+ }, [getController]);
226
258
  const setCursor = useCallback(
227
- (anchor, head) => controller.setCursor(anchor, head),
228
- [controller]
259
+ (anchor, head) => getController().setCursor(anchor, head),
260
+ [getController]
229
261
  );
230
- const clearCursor = useCallback(() => controller.clearCursor(), [controller]);
231
- return buildResult(controller, snapshot, undo, redo, setCursor, clearCursor);
262
+ const clearCursor = useCallback(() => getController().clearCursor(), [getController]);
263
+ return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
232
264
  }
233
265
  function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
234
266
  return {
@@ -247,13 +279,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
247
279
  }
248
280
 
249
281
  // src/hooks/use-presence.ts
250
- import { useEffect as useEffect6 } from "react";
282
+ import { useEffect as useEffect5 } from "react";
251
283
  function usePresence(user) {
252
284
  const { syncEngine } = useKoraContext();
253
285
  const name = user?.name ?? null;
254
286
  const color = user?.color ?? null;
255
287
  const avatar = user?.avatar ?? null;
256
- useEffect6(() => {
288
+ useEffect5(() => {
257
289
  if (!syncEngine || !name || !color) return;
258
290
  const awareness = syncEngine.getAwarenessManager();
259
291
  awareness.setLocalState({
@@ -267,11 +299,11 @@ function usePresence(user) {
267
299
 
268
300
  // src/hooks/use-collaborators.ts
269
301
  import { subscribeRemoteAwarenessStates } from "@korajs/sync";
270
- import { useCallback as useCallback2, useEffect as useEffect7, useRef as useRef4, useSyncExternalStore as useSyncExternalStore5 } from "react";
302
+ import { useCallback as useCallback2, useEffect as useEffect6, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
271
303
  var EMPTY_ARRAY2 = [];
272
304
  function useCollaborators() {
273
305
  const { syncEngine } = useKoraContext();
274
- const snapshotRef = useRef4(EMPTY_ARRAY2);
306
+ const snapshotRef = useRef5(EMPTY_ARRAY2);
275
307
  const subscribe = useCallback2(
276
308
  (onStoreChange) => {
277
309
  if (!syncEngine) {
@@ -288,7 +320,7 @@ function useCollaborators() {
288
320
  [syncEngine]
289
321
  );
290
322
  const getSnapshot = useCallback2(() => snapshotRef.current, []);
291
- useEffect7(() => {
323
+ useEffect6(() => {
292
324
  if (!syncEngine) {
293
325
  snapshotRef.current = EMPTY_ARRAY2;
294
326
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context/kora-context.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.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 { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } 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\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 { 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 { 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\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\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\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\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 controller = useMemo(\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[],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => controller.reset(),\n\t}\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\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\tconst controller = useMemo(\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[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.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'\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(\n\t\t() => store.collection(collectionName),\n\t\t[store, collectionName],\n\t)\n\n\tconst controller = useMemo(\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[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tcontroller.setUser(options?.user)\n\t}, [controller, options?.user])\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => controller.undo(), [controller])\n\tconst redo = useCallback(() => controller.redo(), [controller])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\t[controller],\n\t)\n\tconst clearCursor = useCallback(() => controller.clearCursor(), [controller])\n\n\treturn buildResult(controller, 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":";AACA,SAAS,uBAAuB;AAEhC,SAAS,eAAe,eAAe,YAAY,WAAW,SAAS,QAAQ,gBAAgB;AAI/F,IAAM,cAAc,cAAuC,IAAI;AAM/D,SAAS,aAAa;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAiC;AAChC,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAuB,SAAS,IAAI;AAC9E,QAAM,CAAC,cAAc,eAAe,IAAI,SAA4B,cAAc,IAAI;AACtF,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC,GAAG;AACvC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAuB,IAAI;AAC7D,QAAM,0BAA0B,OAA+B,IAAI;AAEnE,MAAI,CAAC,wBAAwB,SAAS;AACrC,4BAAwB,UAAU,IAAI,gBAAgB;AAAA,EACvD;AAEA,YAAU,MAAM;AACf,QAAI,CAAC,IAAK;AACV,QAAI,YAAY;AAChB,QAAI,MACF,KAAK,MAAM;AACX,UAAI,UAAW;AACf,uBAAiB,IAAI,SAAS,CAAC;AAC/B,sBAAgB,IAAI,cAAc,CAAC;AACnC,eAAS,IAAI;AAAA,IACd,CAAC,EACA,MAAM,CAAC,UAAmB;AAC1B,UAAI,UAAW;AACf,YAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACpE,cAAQ,MAAM,iCAAiC,GAAG;AAClD,mBAAa,GAAG;AAAA,IACjB,CAAC;AACF,WAAO,MAAM;AACZ,kBAAY;AAAA,IACb;AAAA,EACD,GAAG,CAAC,GAAG,CAAC;AAER,YAAU,MAAM;AACf,WAAO,MAAM;AACZ,UAAI,CAAC,KAAK;AACT,gCAAwB,SAAS,MAAM;AAAA,MACxC;AAAA,IACD;AAAA,EACD,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,eAAe,QAAiC,MAAM;AAC3D,QAAI,CAAC,eAAe;AACnB,aAAO;AAAA,IACR;AACA,WAAO;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,KAAK,OAAO;AAAA,MACZ,QAAQ,KAAK,UAAU;AAAA,MACvB,qBAAqB,KAAK,MAAM,mBAAmB;AAAA,MACnD,iBACC,OAAO,OAAO,IAAI,uBAAuB,aACtC,IAAI,mBAAmB,IACvB,wBAAwB;AAAA,IAC7B;AAAA,EACD,GAAG,CAAC,eAAe,cAAc,GAAG,CAAC;AAErC,MAAI,WAAW;AACd,WAAO;AAAA,MACN;AAAA,MACA,EAAE,OAAO,EAAE,OAAO,OAAO,SAAS,QAAQ,YAAY,YAAY,EAAE;AAAA,MACpE,cAAc,UAAU,MAAM,6BAA6B;AAAA,MAC3D,UAAU;AAAA,IACX;AAAA,EACD;AAEA,MAAI,CAAC,OAAO;AACX,WAAQ,YAAY;AAAA,EACrB;AAEA,MAAI,CAAC,cAAc;AAClB,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AAEA,SAAO,cAAc,YAAY,UAAU,EAAE,OAAO,aAAa,GAAG,QAAQ;AAC7E;AAEA,SAAS,iBAAmC;AAC3C,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,YAAY,MAAM;AACrB,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AACA,SAAO;AACR;;;ACpFO,SAAS,SAAiD;AAChE,QAAM,EAAE,IAAI,IAAI,eAAe;AAC/B,MAAI,CAAC,KAAK;AACT,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AACA,SAAO;AACR;;;AChCA,SAAS,wBAAwB;AACjC,SAAS,aAAAA,YAAW,UAAAC,SAAQ,YAAAC,WAAU,4BAA4B;AAIlE,IAAM,cAAkC,OAAO,OAAO,CAAC,CAAC;AAExD,IAAM,gBAAgB,CAAC,mBAA6C;AACnE,SAAO,MAAM;AAAA,EAAC;AACf;AAKO,SAAS,SACf,OACA,SACe;AACf,QAAM,EAAE,gBAAgB,IAAI,eAAe;AAC3C,QAAM,UAAU,SAAS,YAAY;AACrC,QAAM,gBAAgB,KAAK,UAAU,MAAM,cAAc,CAAC;AAC1D,QAAM,WAAWC,QAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,QAAM,CAAC,YAAY,aAAa,IAAIC,UAAuD,IAAI;AAE/F,EAAAC,WAAU,MAAM;AACf,QAAI,CAAC,SAAS;AACb,oBAAc,IAAI;AAClB;AAAA,IACD;AAEA,UAAM,eAAe,SAAS;AAC9B,qBAAiB,YAAY;AAC7B,UAAM,QAAQ,gBAAgB,YAAY,YAAY;AACtD,kBAAc,KAAK;AAEnB,WAAO,MAAM;AACZ,sBAAgB,QAAQ,YAAqC;AAC7D,oBAAc,IAAI;AAAA,IACnB;AAAA,EACD,GAAG,CAAC,eAAe,SAAS,eAAe,CAAC;AAE5C,QAAM,sBAAsB,MAAoB;AAEhD,SAAO;AAAA,IACN,aAAa,WAAW,YAAY;AAAA,IACpC,aAAa,WAAW,cAAc;AAAA,EACvC;AACD;;;AClDA,SAAS,gCAAgC;AACzC,SAAS,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,wBAAAC,6BAA4B;AAM1D,SAAS,YACf,YACA,SACkC;AAClC,QAAM,QAAQD,QAAO,UAAU;AAC/B,QAAM,UAAU;AAEhB,QAAM,aAAaA,QAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,aAAaD;AAAA,IAClB,MACC,yBAAiD;AAAA,MAChD,YAAY,IAAI,SAAS,MAAM,QAAQ,GAAG,IAAI;AAAA,MAC9C,gBAAgB,MAAM,WAAW;AAAA,IAClC,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AAEA,EAAAD,WAAU,MAAM,MAAM,WAAW,QAAQ,GAAG,CAAC,UAAU,CAAC;AAExD,QAAM,QAAQG;AAAA,IACb,CAAC,kBAAkB,WAAW,UAAU,aAAa;AAAA,IACrD,MAAM,WAAW,YAAY;AAAA,IAC7B,MAAM,WAAW,YAAY;AAAA,EAC9B;AAEA,SAAO;AAAA,IACN,QAAQ,IAAI,SAAgB,WAAW,OAAO,GAAG,IAAI;AAAA,IACrD,aAAa,IAAI,SAAgB,WAAW,YAAY,GAAG,IAAI;AAAA,IAC/D,WAAW,MAAM;AAAA,IACjB,OAAO,MAAM;AAAA,IACb,OAAO,MAAM,WAAW,MAAM;AAAA,EAC/B;AACD;;;ACxCA,SAAS,kCAAkC;AAC3C,SAAS,aAAAC,YAAW,WAAAC,UAAS,wBAAAC,6BAA4B;AAMlD,SAAS,gBAAgC;AAC/C,QAAM,EAAE,YAAY,qBAAqB,OAAO,IAAI,eAAe;AACnE,QAAM,aAAaC;AAAA,IAClB,MACC,2BAA2B;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,QAAQ,sBAAsB,OAAO;AAAA,IACtC,CAAC;AAAA,IACF,CAAC,YAAY,qBAAqB,MAAM;AAAA,EACzC;AAEA,EAAAC,WAAU,MAAM,MAAM,WAAW,QAAQ,GAAG,CAAC,UAAU,CAAC;AAExD,SAAOC;AAAA,IACN,CAAC,kBAAkB,WAAW,UAAU,aAAa;AAAA,IACrD,MAAM,WAAW,YAAY;AAAA,IAC7B,MAAM,WAAW,YAAY;AAAA,EAC9B;AACD;;;AC1BA,SAAS,WAAAC,gBAAe;AAgBjB,SAAS,cAAc,MAAkC;AAC/D,QAAM,EAAE,MAAM,IAAI,eAAe;AAEjC,SAAOC,SAAQ,MAAM;AACpB,WAAO,MAAM,WAAW,IAAI;AAAA,EAC7B,GAAG,CAAC,OAAO,IAAI,CAAC;AACjB;;;ACvBA,SAAS,sBAAsB,gCAAgC;AAG/D,SAAS,aAAa,aAAAC,YAAW,WAAAC,UAAS,wBAAAC,6BAA4B;AAY/D,SAAS,YACf,gBACA,UACA,WACA,SACoB;AACpB,QAAM,EAAE,OAAO,WAAW,IAAI,eAAe;AAC7C,QAAM,aAAaC;AAAA,IAClB,MAAM,MAAM,WAAW,cAAc;AAAA,IACrC,CAAC,OAAO,cAAc;AAAA,EACvB;AAEA,QAAM,aAAaA;AAAA,IAClB,MACC,yBAAyB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,qBAAqB,UAAU;AAAA,MAC3C,eAAe,SAAS;AAAA,MACxB,MAAM,SAAS;AAAA,IAChB,CAAC;AAAA,IACF,CAAC,YAAY,gBAAgB,WAAW,SAAS,eAAe,UAAU,OAAO,UAAU;AAAA,EAC5F;AAEA,EAAAC,WAAU,MAAM;AACf,eAAW,QAAQ,SAAS,IAAI;AAAA,EACjC,GAAG,CAAC,YAAY,SAAS,IAAI,CAAC;AAE9B,EAAAA,WAAU,MAAM,MAAM,WAAW,QAAQ,GAAG,CAAC,UAAU,CAAC;AAExD,QAAM,WAAWC;AAAA,IAChB,CAAC,kBAAkB,WAAW,UAAU,aAAa;AAAA,IACrD,MAAM,WAAW,YAAY;AAAA,IAC7B,MAAM,WAAW,YAAY;AAAA,EAC9B;AAEA,QAAM,OAAO,YAAY,MAAM,WAAW,KAAK,GAAG,CAAC,UAAU,CAAC;AAC9D,QAAM,OAAO,YAAY,MAAM,WAAW,KAAK,GAAG,CAAC,UAAU,CAAC;AAC9D,QAAM,YAAY;AAAA,IACjB,CAAC,QAAgB,SAAiB,WAAW,UAAU,QAAQ,IAAI;AAAA,IACnE,CAAC,UAAU;AAAA,EACZ;AACA,QAAM,cAAc,YAAY,MAAM,WAAW,YAAY,GAAG,CAAC,UAAU,CAAC;AAE5E,SAAO,YAAY,YAAY,UAAU,MAAM,MAAM,WAAW,WAAW;AAC5E;AAEA,SAAS,YACR,YACA,UACA,MACA,MACA,WACA,aACoB;AACpB,SAAO;AAAA,IACN,KAAK,WAAW;AAAA,IAChB,MAAM,WAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,SAAS,CAAC,GAAG,SAAS,OAAO;AAAA,IAC7B;AAAA,IACA;AAAA,EACD;AACD;;;ACtFA,SAAS,aAAAC,kBAAiB;AAQnB,SAAS,YAAY,MAAqE;AAChG,QAAM,EAAE,WAAW,IAAI,eAAe;AACtC,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,QAAQ,MAAM,SAAS;AAC7B,QAAM,SAAS,MAAM,UAAU;AAE/B,EAAAC,WAAU,MAAM;AACf,QAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAO;AAEpC,UAAM,YAAY,WAAW,oBAAoB;AACjD,cAAU,cAAc;AAAA,MACvB,MAAM,EAAE,MAAM,OAAO,QAAQ,UAAU,OAAU;AAAA,IAClD,CAAC;AAED,WAAO,MAAM;AACZ,gBAAU,cAAc,IAAI;AAAA,IAC7B;AAAA,EACD,GAAG,CAAC,YAAY,MAAM,OAAO,MAAM,CAAC;AACrC;;;ACzBA,SAAS,sCAAsC;AAC/C,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,wBAAAC,6BAA4B;AAGrE,IAAMC,eAAgC,CAAC;AAOhC,SAAS,mBAAqC;AACpD,QAAM,EAAE,WAAW,IAAI,eAAe;AAEtC,QAAM,cAAcC,QAAyBD,YAAW;AAExD,QAAM,YAAYE;AAAA,IACjB,CAAC,kBAA4C;AAC5C,UAAI,CAAC,YAAY;AAChB,oBAAY,UAAUF;AACtB,eAAO,MAAM;AAAA,QAAC;AAAA,MACf;AAEA,YAAM,YAAY,WAAW,oBAAoB;AACjD,aAAO,+BAA+B,WAAW,CAAC,WAAW;AAC5D,oBAAY,UAAU;AACtB,sBAAc;AAAA,MACf,CAAC;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACZ;AAEA,QAAM,cAAcE,aAAY,MAAwB,YAAY,SAAS,CAAC,CAAC;AAE/E,EAAAC,WAAU,MAAM;AACf,QAAI,CAAC,YAAY;AAChB,kBAAY,UAAUH;AAAA,IACvB;AAAA,EACD,GAAG,CAAC,UAAU,CAAC;AAEf,SAAOI,sBAAqB,WAAW,WAAW;AACnD;","names":["useEffect","useRef","useState","useRef","useState","useEffect","useEffect","useMemo","useRef","useSyncExternalStore","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useMemo","useMemo","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
1
+ {"version":3,"sources":["../src/context/kora-context.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 { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } 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\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 { 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 { 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\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\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\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\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":["useEffect","useRef","useState","useRef","useState","useEffect","useRef","useSyncExternalStore","useEffect","useRef","useRef","useSyncExternalStore","useSyncExternalStore","useSyncExternalStore","useMemo","useMemo","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","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": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Kora.js React hooks and bindings for offline-first applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "yjs": "^13.6.30",
34
34
  "@korajs/core": "0.6.0",
35
- "@korajs/sync": "0.6.0",
35
+ "@korajs/sync": "0.6.1",
36
36
  "@korajs/store": "0.6.0"
37
37
  },
38
38
  "devDependencies": {