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

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
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AuthBoundKoraProvider: () => AuthBoundKoraProvider,
23
24
  KoraProvider: () => KoraProvider,
24
25
  useApp: () => useApp,
25
26
  useCollaborators: () => useCollaborators,
@@ -120,6 +121,91 @@ function useKoraContext() {
120
121
  return context;
121
122
  }
122
123
 
124
+ // src/context/auth-bound-kora-provider.ts
125
+ var import_react2 = require("react");
126
+ function AuthBoundKoraProvider({
127
+ authClient,
128
+ createApp,
129
+ signedOut = null,
130
+ fallback = null,
131
+ children
132
+ }) {
133
+ const [app, setApp] = (0, import_react2.useState)(null);
134
+ const [state, setState] = (0, import_react2.useState)({ state: "loading" });
135
+ const [initError, setInitError] = (0, import_react2.useState)(null);
136
+ const active = (0, import_react2.useRef)(null);
137
+ const createAppRef = (0, import_react2.useRef)(createApp);
138
+ createAppRef.current = createApp;
139
+ const activeUserId = (0, import_react2.useRef)(null);
140
+ const generation = (0, import_react2.useRef)(0);
141
+ const transition = (0, import_react2.useRef)(Promise.resolve());
142
+ (0, import_react2.useEffect)(() => {
143
+ let disposed = false;
144
+ const reconcile = () => {
145
+ const currentGeneration = ++generation.current;
146
+ transition.current = transition.current.catch(() => {
147
+ }).then(async () => {
148
+ setInitError(null);
149
+ const next = await authClient.resolveSyncState?.() ?? { state: "signed-out", mayConnectAnonymously: false };
150
+ if (disposed || currentGeneration !== generation.current) return;
151
+ const previous = active.current;
152
+ if (next.state === "authenticated" && next.userId === activeUserId.current && previous) {
153
+ setState(next);
154
+ return;
155
+ }
156
+ setApp(null);
157
+ active.current = null;
158
+ activeUserId.current = null;
159
+ if (previous) await previous.close();
160
+ if (disposed || currentGeneration !== generation.current) return;
161
+ setState(next);
162
+ if (next.state !== "authenticated") return;
163
+ const created = createAppRef.current(next);
164
+ try {
165
+ await created.ready;
166
+ } catch (error) {
167
+ await created.close();
168
+ throw error;
169
+ }
170
+ if (disposed || currentGeneration !== generation.current) {
171
+ await created.close();
172
+ return;
173
+ }
174
+ active.current = created;
175
+ activeUserId.current = next.userId;
176
+ setApp(created);
177
+ }).catch((error) => {
178
+ if (!disposed && currentGeneration === generation.current) {
179
+ setInitError(error instanceof Error ? error : new Error(String(error)));
180
+ }
181
+ });
182
+ };
183
+ reconcile();
184
+ const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
185
+ });
186
+ return () => {
187
+ disposed = true;
188
+ generation.current++;
189
+ unsubscribe();
190
+ const previous = active.current;
191
+ active.current = null;
192
+ activeUserId.current = null;
193
+ if (previous) void previous.close();
194
+ };
195
+ }, [authClient]);
196
+ if (initError) {
197
+ return (0, import_react2.createElement)(
198
+ "div",
199
+ { style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
200
+ (0, import_react2.createElement)("strong", null, "Kora initialization error: "),
201
+ initError.message
202
+ );
203
+ }
204
+ if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
205
+ if (!app) return fallback;
206
+ return (0, import_react2.createElement)(KoraProvider, { app, fallback }, children);
207
+ }
208
+
123
209
  // src/hooks/use-app.ts
124
210
  function useApp() {
125
211
  const { app } = useKoraContext();
@@ -133,7 +219,7 @@ function useApp() {
133
219
 
134
220
  // src/hooks/use-query.ts
135
221
  var import_store2 = require("@korajs/store");
136
- var import_react2 = require("react");
222
+ var import_react3 = require("react");
137
223
  var EMPTY_ARRAY = Object.freeze([]);
138
224
  var noopSubscribe = (_onStoreChange) => {
139
225
  return () => {
@@ -143,10 +229,11 @@ function useQuery(query, options) {
143
229
  const { queryStoreCache } = useKoraContext();
144
230
  const enabled = options?.enabled !== false;
145
231
  const descriptorKey = JSON.stringify(query.getDescriptor());
146
- const queryRef = (0, import_react2.useRef)(query);
232
+ const queryRef = (0, import_react3.useRef)(query);
147
233
  queryRef.current = query;
148
- const [queryStore, setQueryStore] = (0, import_react2.useState)(null);
149
- (0, import_react2.useEffect)(() => {
234
+ const lastSnapshotRef = (0, import_react3.useRef)(EMPTY_ARRAY);
235
+ const [queryStore, setQueryStore] = (0, import_react3.useState)(null);
236
+ (0, import_react3.useEffect)(() => {
150
237
  if (!enabled) {
151
238
  setQueryStore(null);
152
239
  return;
@@ -157,34 +244,44 @@ function useQuery(query, options) {
157
244
  setQueryStore(store);
158
245
  return () => {
159
246
  queryStoreCache.release(currentQuery);
160
- setQueryStore(null);
161
247
  };
162
248
  }, [descriptorKey, enabled, queryStoreCache]);
163
- const disabledGetSnapshot = () => EMPTY_ARRAY;
164
- return (0, import_react2.useSyncExternalStore)(
165
- queryStore ? queryStore.subscribe : noopSubscribe,
166
- queryStore ? queryStore.getSnapshot : disabledGetSnapshot
167
- );
249
+ const getSnapshot = (0, import_react3.useCallback)(() => {
250
+ if (!enabled) {
251
+ lastSnapshotRef.current = EMPTY_ARRAY;
252
+ return lastSnapshotRef.current;
253
+ }
254
+ if (!queryStore) {
255
+ return lastSnapshotRef.current;
256
+ }
257
+ if (!queryStore.hasSnapshot()) {
258
+ return lastSnapshotRef.current;
259
+ }
260
+ const snapshot = queryStore.getSnapshot();
261
+ lastSnapshotRef.current = snapshot;
262
+ return snapshot;
263
+ }, [enabled, queryStore]);
264
+ return (0, import_react3.useSyncExternalStore)(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot);
168
265
  }
169
266
 
170
267
  // src/hooks/use-mutation.ts
171
268
  var import_bindings = require("@korajs/core/bindings");
172
- var import_react4 = require("react");
269
+ var import_react5 = require("react");
173
270
 
174
271
  // src/hooks/use-controller.ts
175
- var import_react3 = require("react");
272
+ var import_react4 = require("react");
176
273
  function useController(create, destroy, deps) {
177
- const controllerRef = (0, import_react3.useRef)(null);
178
- const createRef = (0, import_react3.useRef)(create);
274
+ const controllerRef = (0, import_react4.useRef)(null);
275
+ const createRef = (0, import_react4.useRef)(create);
179
276
  createRef.current = create;
180
- const [, forceRender] = (0, import_react3.useReducer)((count) => count + 1, 0);
181
- const getController = (0, import_react3.useRef)(() => {
277
+ const [, forceRender] = (0, import_react4.useReducer)((count) => count + 1, 0);
278
+ const getController = (0, import_react4.useRef)(() => {
182
279
  if (controllerRef.current === null) {
183
280
  controllerRef.current = createRef.current();
184
281
  }
185
282
  return controllerRef.current;
186
283
  }).current;
187
- (0, import_react3.useEffect)(() => {
284
+ (0, import_react4.useEffect)(() => {
188
285
  if (controllerRef.current === null) {
189
286
  controllerRef.current = createRef.current();
190
287
  forceRender();
@@ -202,9 +299,9 @@ function useController(create, destroy, deps) {
202
299
 
203
300
  // src/hooks/use-mutation.ts
204
301
  function useMutation(mutationFn, options) {
205
- const fnRef = (0, import_react4.useRef)(mutationFn);
302
+ const fnRef = (0, import_react5.useRef)(mutationFn);
206
303
  fnRef.current = mutationFn;
207
- const optionsRef = (0, import_react4.useRef)(options);
304
+ const optionsRef = (0, import_react5.useRef)(options);
208
305
  optionsRef.current = options;
209
306
  const getController = useController(
210
307
  () => (0, import_bindings.createMutationController)({
@@ -214,7 +311,7 @@ function useMutation(mutationFn, options) {
214
311
  (controller) => controller.destroy(),
215
312
  []
216
313
  );
217
- const state = (0, import_react4.useSyncExternalStore)(
314
+ const state = (0, import_react5.useSyncExternalStore)(
218
315
  (onStoreChange) => getController().subscribe(onStoreChange),
219
316
  () => getController().getSnapshot(),
220
317
  () => getController().getSnapshot()
@@ -230,7 +327,7 @@ function useMutation(mutationFn, options) {
230
327
 
231
328
  // src/hooks/use-sync-status.ts
232
329
  var import_sync = require("@korajs/sync");
233
- var import_react5 = require("react");
330
+ var import_react6 = require("react");
234
331
  function useSyncStatus() {
235
332
  const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
236
333
  const getController = useController(
@@ -242,7 +339,7 @@ function useSyncStatus() {
242
339
  (controller) => controller.destroy(),
243
340
  [syncEngine, subscribeSyncStatus, events]
244
341
  );
245
- return (0, import_react5.useSyncExternalStore)(
342
+ return (0, import_react6.useSyncExternalStore)(
246
343
  (onStoreChange) => getController().subscribe(onStoreChange),
247
344
  () => getController().getSnapshot(),
248
345
  () => getController().getSnapshot()
@@ -250,20 +347,20 @@ function useSyncStatus() {
250
347
  }
251
348
 
252
349
  // src/hooks/use-collection.ts
253
- var import_react6 = require("react");
350
+ var import_react7 = require("react");
254
351
  function useCollection(name) {
255
352
  const { store } = useKoraContext();
256
- return (0, import_react6.useMemo)(() => {
353
+ return (0, import_react7.useMemo)(() => {
257
354
  return store.collection(name);
258
355
  }, [store, name]);
259
356
  }
260
357
 
261
358
  // src/hooks/use-rich-text.ts
262
359
  var import_store3 = require("@korajs/store");
263
- var import_react7 = require("react");
360
+ var import_react8 = require("react");
264
361
  function useRichText(collectionName, recordId, fieldName, options) {
265
362
  const { store, syncEngine } = useKoraContext();
266
- const collection = (0, import_react7.useMemo)(() => store.collection(collectionName), [store, collectionName]);
363
+ const collection = (0, import_react8.useMemo)(() => store.collection(collectionName), [store, collectionName]);
267
364
  const getController = useController(
268
365
  () => (0, import_store3.createRichTextController)({
269
366
  collection,
@@ -278,25 +375,25 @@ function useRichText(collectionName, recordId, fieldName, options) {
278
375
  (controller) => controller.destroy(),
279
376
  [collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
280
377
  );
281
- (0, import_react7.useEffect)(() => {
378
+ (0, import_react8.useEffect)(() => {
282
379
  getController().setUser(options?.user);
283
380
  }, [getController, options?.user]);
284
- const snapshot = (0, import_react7.useSyncExternalStore)(
381
+ const snapshot = (0, import_react8.useSyncExternalStore)(
285
382
  (onStoreChange) => getController().subscribe(onStoreChange),
286
383
  () => getController().getSnapshot(),
287
384
  () => getController().getSnapshot()
288
385
  );
289
- const undo = (0, import_react7.useCallback)(() => {
386
+ const undo = (0, import_react8.useCallback)(() => {
290
387
  getController().undo();
291
388
  }, [getController]);
292
- const redo = (0, import_react7.useCallback)(() => {
389
+ const redo = (0, import_react8.useCallback)(() => {
293
390
  getController().redo();
294
391
  }, [getController]);
295
- const setCursor = (0, import_react7.useCallback)(
392
+ const setCursor = (0, import_react8.useCallback)(
296
393
  (anchor, head) => getController().setCursor(anchor, head),
297
394
  [getController]
298
395
  );
299
- const clearCursor = (0, import_react7.useCallback)(() => getController().clearCursor(), [getController]);
396
+ const clearCursor = (0, import_react8.useCallback)(() => getController().clearCursor(), [getController]);
300
397
  return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
301
398
  }
302
399
  function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
@@ -316,13 +413,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
316
413
  }
317
414
 
318
415
  // src/hooks/use-presence.ts
319
- var import_react8 = require("react");
416
+ var import_react9 = require("react");
320
417
  function usePresence(user) {
321
418
  const { syncEngine } = useKoraContext();
322
419
  const name = user?.name ?? null;
323
420
  const color = user?.color ?? null;
324
421
  const avatar = user?.avatar ?? null;
325
- (0, import_react8.useEffect)(() => {
422
+ (0, import_react9.useEffect)(() => {
326
423
  if (!syncEngine || !name || !color) return;
327
424
  const awareness = syncEngine.getAwarenessManager();
328
425
  awareness.setLocalState({
@@ -336,12 +433,12 @@ function usePresence(user) {
336
433
 
337
434
  // src/hooks/use-collaborators.ts
338
435
  var import_sync2 = require("@korajs/sync");
339
- var import_react9 = require("react");
436
+ var import_react10 = require("react");
340
437
  var EMPTY_ARRAY2 = [];
341
438
  function useCollaborators() {
342
439
  const { syncEngine } = useKoraContext();
343
- const snapshotRef = (0, import_react9.useRef)(EMPTY_ARRAY2);
344
- const subscribe = (0, import_react9.useCallback)(
440
+ const snapshotRef = (0, import_react10.useRef)(EMPTY_ARRAY2);
441
+ const subscribe = (0, import_react10.useCallback)(
345
442
  (onStoreChange) => {
346
443
  if (!syncEngine) {
347
444
  snapshotRef.current = EMPTY_ARRAY2;
@@ -356,16 +453,17 @@ function useCollaborators() {
356
453
  },
357
454
  [syncEngine]
358
455
  );
359
- const getSnapshot = (0, import_react9.useCallback)(() => snapshotRef.current, []);
360
- (0, import_react9.useEffect)(() => {
456
+ const getSnapshot = (0, import_react10.useCallback)(() => snapshotRef.current, []);
457
+ (0, import_react10.useEffect)(() => {
361
458
  if (!syncEngine) {
362
459
  snapshotRef.current = EMPTY_ARRAY2;
363
460
  }
364
461
  }, [syncEngine]);
365
- return (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot);
462
+ return (0, import_react10.useSyncExternalStore)(subscribe, getSnapshot);
366
463
  }
367
464
  // Annotate the CommonJS export names for ESM import in node:
368
465
  0 && (module.exports = {
466
+ AuthBoundKoraProvider,
369
467
  KoraProvider,
370
468
  useApp,
371
469
  useCollaborators,
@@ -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-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 {\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 { 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\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\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"]}
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"]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1 } from '@korajs/core/bindings';
1
+ import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1, AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings';
2
2
  import { Store, QueryStoreCache, CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
3
3
  import { SyncEngine, CursorInfo, SyncStatusInfo, AwarenessUser, AwarenessState } from '@korajs/sync';
4
4
  import { ReactNode } from 'react';
@@ -45,6 +45,24 @@ interface UseRichTextResult {
45
45
  */
46
46
  declare function KoraProvider({ app, store, syncEngine, fallback, children, }: KoraProviderProps): ReactNode;
47
47
 
48
+ interface AuthBoundKoraProviderProps {
49
+ authClient: AuthSyncBinding;
50
+ createApp: (session: Extract<AuthSyncState, {
51
+ state: 'authenticated';
52
+ }>) => KoraAppLike & {
53
+ close(): Promise<void>;
54
+ };
55
+ signedOut?: ReactNode;
56
+ fallback?: ReactNode;
57
+ children?: ReactNode;
58
+ }
59
+ /**
60
+ * Owns the security-sensitive app lifetime for shared-browser applications.
61
+ * The previous app is fully closed before a different user's app is created,
62
+ * and no stale provider tree is rendered across that boundary.
63
+ */
64
+ declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, children, }: AuthBoundKoraProviderProps): ReactNode;
65
+
48
66
  /**
49
67
  * React hook that returns the Kora app instance from context.
50
68
  *
@@ -125,4 +143,4 @@ declare function usePresence(user: {
125
143
  */
126
144
  declare function useCollaborators(): AwarenessState[];
127
145
 
128
- export { 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 };
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 };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1 } from '@korajs/core/bindings';
1
+ import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1, AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings';
2
2
  import { Store, QueryStoreCache, CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
3
3
  import { SyncEngine, CursorInfo, SyncStatusInfo, AwarenessUser, AwarenessState } from '@korajs/sync';
4
4
  import { ReactNode } from 'react';
@@ -45,6 +45,24 @@ interface UseRichTextResult {
45
45
  */
46
46
  declare function KoraProvider({ app, store, syncEngine, fallback, children, }: KoraProviderProps): ReactNode;
47
47
 
48
+ interface AuthBoundKoraProviderProps {
49
+ authClient: AuthSyncBinding;
50
+ createApp: (session: Extract<AuthSyncState, {
51
+ state: 'authenticated';
52
+ }>) => KoraAppLike & {
53
+ close(): Promise<void>;
54
+ };
55
+ signedOut?: ReactNode;
56
+ fallback?: ReactNode;
57
+ children?: ReactNode;
58
+ }
59
+ /**
60
+ * Owns the security-sensitive app lifetime for shared-browser applications.
61
+ * The previous app is fully closed before a different user's app is created,
62
+ * and no stale provider tree is rendered across that boundary.
63
+ */
64
+ declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, children, }: AuthBoundKoraProviderProps): ReactNode;
65
+
48
66
  /**
49
67
  * React hook that returns the Kora app instance from context.
50
68
  *
@@ -125,4 +143,4 @@ declare function usePresence(user: {
125
143
  */
126
144
  declare function useCollaborators(): AwarenessState[];
127
145
 
128
- export { 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 };
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 };
package/dist/index.js CHANGED
@@ -94,6 +94,91 @@ function useKoraContext() {
94
94
  return context;
95
95
  }
96
96
 
97
+ // src/context/auth-bound-kora-provider.ts
98
+ import { createElement as createElement2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
99
+ function AuthBoundKoraProvider({
100
+ authClient,
101
+ createApp,
102
+ signedOut = null,
103
+ fallback = null,
104
+ children
105
+ }) {
106
+ const [app, setApp] = useState2(null);
107
+ const [state, setState] = useState2({ state: "loading" });
108
+ const [initError, setInitError] = useState2(null);
109
+ const active = useRef2(null);
110
+ const createAppRef = useRef2(createApp);
111
+ createAppRef.current = createApp;
112
+ const activeUserId = useRef2(null);
113
+ const generation = useRef2(0);
114
+ const transition = useRef2(Promise.resolve());
115
+ useEffect2(() => {
116
+ let disposed = false;
117
+ const reconcile = () => {
118
+ const currentGeneration = ++generation.current;
119
+ transition.current = transition.current.catch(() => {
120
+ }).then(async () => {
121
+ setInitError(null);
122
+ const next = await authClient.resolveSyncState?.() ?? { state: "signed-out", mayConnectAnonymously: false };
123
+ if (disposed || currentGeneration !== generation.current) return;
124
+ const previous = active.current;
125
+ if (next.state === "authenticated" && next.userId === activeUserId.current && previous) {
126
+ setState(next);
127
+ return;
128
+ }
129
+ setApp(null);
130
+ active.current = null;
131
+ activeUserId.current = null;
132
+ if (previous) await previous.close();
133
+ if (disposed || currentGeneration !== generation.current) return;
134
+ setState(next);
135
+ if (next.state !== "authenticated") return;
136
+ const created = createAppRef.current(next);
137
+ try {
138
+ await created.ready;
139
+ } catch (error) {
140
+ await created.close();
141
+ throw error;
142
+ }
143
+ if (disposed || currentGeneration !== generation.current) {
144
+ await created.close();
145
+ return;
146
+ }
147
+ active.current = created;
148
+ activeUserId.current = next.userId;
149
+ setApp(created);
150
+ }).catch((error) => {
151
+ if (!disposed && currentGeneration === generation.current) {
152
+ setInitError(error instanceof Error ? error : new Error(String(error)));
153
+ }
154
+ });
155
+ };
156
+ reconcile();
157
+ const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
158
+ });
159
+ return () => {
160
+ disposed = true;
161
+ generation.current++;
162
+ unsubscribe();
163
+ const previous = active.current;
164
+ active.current = null;
165
+ activeUserId.current = null;
166
+ if (previous) void previous.close();
167
+ };
168
+ }, [authClient]);
169
+ if (initError) {
170
+ return createElement2(
171
+ "div",
172
+ { style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
173
+ createElement2("strong", null, "Kora initialization error: "),
174
+ initError.message
175
+ );
176
+ }
177
+ if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
178
+ if (!app) return fallback;
179
+ return createElement2(KoraProvider, { app, fallback }, children);
180
+ }
181
+
97
182
  // src/hooks/use-app.ts
98
183
  function useApp() {
99
184
  const { app } = useKoraContext();
@@ -107,7 +192,7 @@ function useApp() {
107
192
 
108
193
  // src/hooks/use-query.ts
109
194
  import { assertQueryReady } from "@korajs/store";
110
- import { useEffect as useEffect2, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
195
+ import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState3, useSyncExternalStore } from "react";
111
196
  var EMPTY_ARRAY = Object.freeze([]);
112
197
  var noopSubscribe = (_onStoreChange) => {
113
198
  return () => {
@@ -117,10 +202,11 @@ function useQuery(query, options) {
117
202
  const { queryStoreCache } = useKoraContext();
118
203
  const enabled = options?.enabled !== false;
119
204
  const descriptorKey = JSON.stringify(query.getDescriptor());
120
- const queryRef = useRef2(query);
205
+ const queryRef = useRef3(query);
121
206
  queryRef.current = query;
122
- const [queryStore, setQueryStore] = useState2(null);
123
- useEffect2(() => {
207
+ const lastSnapshotRef = useRef3(EMPTY_ARRAY);
208
+ const [queryStore, setQueryStore] = useState3(null);
209
+ useEffect3(() => {
124
210
  if (!enabled) {
125
211
  setQueryStore(null);
126
212
  return;
@@ -131,34 +217,44 @@ function useQuery(query, options) {
131
217
  setQueryStore(store);
132
218
  return () => {
133
219
  queryStoreCache.release(currentQuery);
134
- setQueryStore(null);
135
220
  };
136
221
  }, [descriptorKey, enabled, queryStoreCache]);
137
- const disabledGetSnapshot = () => EMPTY_ARRAY;
138
- return useSyncExternalStore(
139
- queryStore ? queryStore.subscribe : noopSubscribe,
140
- queryStore ? queryStore.getSnapshot : disabledGetSnapshot
141
- );
222
+ const getSnapshot = useCallback(() => {
223
+ if (!enabled) {
224
+ lastSnapshotRef.current = EMPTY_ARRAY;
225
+ return lastSnapshotRef.current;
226
+ }
227
+ if (!queryStore) {
228
+ return lastSnapshotRef.current;
229
+ }
230
+ if (!queryStore.hasSnapshot()) {
231
+ return lastSnapshotRef.current;
232
+ }
233
+ const snapshot = queryStore.getSnapshot();
234
+ lastSnapshotRef.current = snapshot;
235
+ return snapshot;
236
+ }, [enabled, queryStore]);
237
+ return useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot);
142
238
  }
143
239
 
144
240
  // src/hooks/use-mutation.ts
145
241
  import { createMutationController } from "@korajs/core/bindings";
146
- import { useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
242
+ import { useRef as useRef5, useSyncExternalStore as useSyncExternalStore2 } from "react";
147
243
 
148
244
  // src/hooks/use-controller.ts
149
- import { useEffect as useEffect3, useReducer, useRef as useRef3 } from "react";
245
+ import { useEffect as useEffect4, useReducer, useRef as useRef4 } from "react";
150
246
  function useController(create, destroy, deps) {
151
- const controllerRef = useRef3(null);
152
- const createRef = useRef3(create);
247
+ const controllerRef = useRef4(null);
248
+ const createRef = useRef4(create);
153
249
  createRef.current = create;
154
250
  const [, forceRender] = useReducer((count) => count + 1, 0);
155
- const getController = useRef3(() => {
251
+ const getController = useRef4(() => {
156
252
  if (controllerRef.current === null) {
157
253
  controllerRef.current = createRef.current();
158
254
  }
159
255
  return controllerRef.current;
160
256
  }).current;
161
- useEffect3(() => {
257
+ useEffect4(() => {
162
258
  if (controllerRef.current === null) {
163
259
  controllerRef.current = createRef.current();
164
260
  forceRender();
@@ -176,9 +272,9 @@ function useController(create, destroy, deps) {
176
272
 
177
273
  // src/hooks/use-mutation.ts
178
274
  function useMutation(mutationFn, options) {
179
- const fnRef = useRef4(mutationFn);
275
+ const fnRef = useRef5(mutationFn);
180
276
  fnRef.current = mutationFn;
181
- const optionsRef = useRef4(options);
277
+ const optionsRef = useRef5(options);
182
278
  optionsRef.current = options;
183
279
  const getController = useController(
184
280
  () => createMutationController({
@@ -234,7 +330,7 @@ function useCollection(name) {
234
330
 
235
331
  // src/hooks/use-rich-text.ts
236
332
  import { asRichTextSyncEngine, createRichTextController } from "@korajs/store";
237
- import { useCallback, useEffect as useEffect4, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
333
+ import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
238
334
  function useRichText(collectionName, recordId, fieldName, options) {
239
335
  const { store, syncEngine } = useKoraContext();
240
336
  const collection = useMemo3(() => store.collection(collectionName), [store, collectionName]);
@@ -252,7 +348,7 @@ function useRichText(collectionName, recordId, fieldName, options) {
252
348
  (controller) => controller.destroy(),
253
349
  [collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
254
350
  );
255
- useEffect4(() => {
351
+ useEffect5(() => {
256
352
  getController().setUser(options?.user);
257
353
  }, [getController, options?.user]);
258
354
  const snapshot = useSyncExternalStore4(
@@ -260,17 +356,17 @@ function useRichText(collectionName, recordId, fieldName, options) {
260
356
  () => getController().getSnapshot(),
261
357
  () => getController().getSnapshot()
262
358
  );
263
- const undo = useCallback(() => {
359
+ const undo = useCallback2(() => {
264
360
  getController().undo();
265
361
  }, [getController]);
266
- const redo = useCallback(() => {
362
+ const redo = useCallback2(() => {
267
363
  getController().redo();
268
364
  }, [getController]);
269
- const setCursor = useCallback(
365
+ const setCursor = useCallback2(
270
366
  (anchor, head) => getController().setCursor(anchor, head),
271
367
  [getController]
272
368
  );
273
- const clearCursor = useCallback(() => getController().clearCursor(), [getController]);
369
+ const clearCursor = useCallback2(() => getController().clearCursor(), [getController]);
274
370
  return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
275
371
  }
276
372
  function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
@@ -290,13 +386,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
290
386
  }
291
387
 
292
388
  // src/hooks/use-presence.ts
293
- import { useEffect as useEffect5 } from "react";
389
+ import { useEffect as useEffect6 } from "react";
294
390
  function usePresence(user) {
295
391
  const { syncEngine } = useKoraContext();
296
392
  const name = user?.name ?? null;
297
393
  const color = user?.color ?? null;
298
394
  const avatar = user?.avatar ?? null;
299
- useEffect5(() => {
395
+ useEffect6(() => {
300
396
  if (!syncEngine || !name || !color) return;
301
397
  const awareness = syncEngine.getAwarenessManager();
302
398
  awareness.setLocalState({
@@ -310,12 +406,12 @@ function usePresence(user) {
310
406
 
311
407
  // src/hooks/use-collaborators.ts
312
408
  import { subscribeRemoteAwarenessStates } from "@korajs/sync";
313
- import { useCallback as useCallback2, useEffect as useEffect6, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
409
+ import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef6, useSyncExternalStore as useSyncExternalStore5 } from "react";
314
410
  var EMPTY_ARRAY2 = [];
315
411
  function useCollaborators() {
316
412
  const { syncEngine } = useKoraContext();
317
- const snapshotRef = useRef5(EMPTY_ARRAY2);
318
- const subscribe = useCallback2(
413
+ const snapshotRef = useRef6(EMPTY_ARRAY2);
414
+ const subscribe = useCallback3(
319
415
  (onStoreChange) => {
320
416
  if (!syncEngine) {
321
417
  snapshotRef.current = EMPTY_ARRAY2;
@@ -330,8 +426,8 @@ function useCollaborators() {
330
426
  },
331
427
  [syncEngine]
332
428
  );
333
- const getSnapshot = useCallback2(() => snapshotRef.current, []);
334
- useEffect6(() => {
429
+ const getSnapshot = useCallback3(() => snapshotRef.current, []);
430
+ useEffect7(() => {
335
431
  if (!syncEngine) {
336
432
  snapshotRef.current = EMPTY_ARRAY2;
337
433
  }
@@ -339,6 +435,7 @@ function useCollaborators() {
339
435
  return useSyncExternalStore5(subscribe, getSnapshot);
340
436
  }
341
437
  export {
438
+ AuthBoundKoraProvider,
342
439
  KoraProvider,
343
440
  useApp,
344
441
  useCollaborators,
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-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 { 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\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\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":";AACA,SAAS,uBAAuB;AAEhC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAIP,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,QAAI,wBAAwB,YAAY,MAAM;AAC7C,8BAAwB,UAAU,IAAI,gBAAgB;AAAA,IACvD;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;;;AC/FO,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;AAG/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;;;ACnDA,SAAS,gCAAgC;AACzC,SAAS,UAAAC,SAAQ,wBAAAC,6BAA4B;;;ACD7C,SAAS,aAAAC,YAAW,YAAY,UAAAC,eAAc;AAevC,SAAS,cACf,QACA,SACA,MACU;AACV,QAAM,gBAAgBA,QAAiB,IAAI;AAC3C,QAAM,YAAYA,QAAO,MAAM;AAC/B,YAAU,UAAU;AAEpB,QAAM,CAAC,EAAE,WAAW,IAAI,WAAW,CAAC,UAAkB,QAAQ,GAAG,CAAC;AAElE,QAAM,gBAAgBA,QAAO,MAAS;AACrC,QAAI,cAAc,YAAY,MAAM;AACnC,oBAAc,UAAU,UAAU,QAAQ;AAAA,IAC3C;AACA,WAAO,cAAc;AAAA,EACtB,CAAC,EAAE;AAGH,EAAAD,WAAU,MAAM;AACf,QAAI,cAAc,YAAY,MAAM;AACnC,oBAAc,UAAU,UAAU,QAAQ;AAG1C,kBAAY;AAAA,IACb;AACA,WAAO,MAAM;AACZ,YAAM,aAAa,cAAc;AACjC,oBAAc,UAAU;AACxB,UAAI,eAAe,MAAM;AACxB,gBAAQ,UAAU;AAAA,MACnB;AAAA,IACD;AAAA,EACD,GAAG,IAAI;AAEP,SAAO;AACR;;;AD3CO,SAAS,YACf,YACA,SACkC;AAClC,QAAM,QAAQE,QAAO,UAAU;AAC/B,QAAM,UAAU;AAEhB,QAAM,aAAaA,QAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,gBAAgB;AAAA,IACrB,MACC,yBAAiD;AAAA,MAChD,YAAY,IAAI,SAAS,MAAM,QAAQ,GAAG,IAAI;AAAA,MAC9C,gBAAgB,MAAM,WAAW;AAAA,IAClC,CAAC;AAAA,IACF,CAAC,eAAe,WAAW,QAAQ;AAAA,IACnC,CAAC;AAAA,EACF;AAEA,QAAM,QAAQC;AAAA,IACb,CAAC,kBAAkB,cAAc,EAAE,UAAU,aAAa;AAAA,IAC1D,MAAM,cAAc,EAAE,YAAY;AAAA,IAClC,MAAM,cAAc,EAAE,YAAY;AAAA,EACnC;AAEA,SAAO;AAAA,IACN,QAAQ,IAAI,SAAgB,cAAc,EAAE,OAAO,GAAG,IAAI;AAAA,IAC1D,aAAa,IAAI,SAAgB,cAAc,EAAE,YAAY,GAAG,IAAI;AAAA,IACpE,WAAW,MAAM;AAAA,IACjB,OAAO,MAAM;AAAA,IACb,OAAO,MAAM,cAAc,EAAE,MAAM;AAAA,EACpC;AACD;;;AExCA,SAAS,kCAAkC;AAC3C,SAAS,wBAAAC,6BAA4B;AAO9B,SAAS,gBAAgC;AAC/C,QAAM,EAAE,YAAY,qBAAqB,OAAO,IAAI,eAAe;AAEnE,QAAM,gBAAgB;AAAA,IACrB,MACC,2BAA2B;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,QAAQ,sBAAsB,OAAO;AAAA,IACtC,CAAC;AAAA,IACF,CAAC,eAAe,WAAW,QAAQ;AAAA,IACnC,CAAC,YAAY,qBAAqB,MAAM;AAAA,EACzC;AAEA,SAAOC;AAAA,IACN,CAAC,kBAAkB,cAAc,EAAE,UAAU,aAAa;AAAA,IAC1D,MAAM,cAAc,EAAE,YAAY;AAAA,IAClC,MAAM,cAAc,EAAE,YAAY;AAAA,EACnC;AACD;;;AC3BA,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;AAa/D,SAAS,YACf,gBACA,UACA,WACA,SACoB;AACpB,QAAM,EAAE,OAAO,WAAW,IAAI,eAAe;AAC7C,QAAM,aAAaC,SAAQ,MAAM,MAAM,WAAW,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC;AAE1F,QAAM,gBAAgB;AAAA,IACrB,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,eAAe,WAAW,QAAQ;AAAA,IACnC,CAAC,YAAY,gBAAgB,WAAW,SAAS,eAAe,UAAU,OAAO,UAAU;AAAA,EAC5F;AAEA,EAAAC,WAAU,MAAM;AACf,kBAAc,EAAE,QAAQ,SAAS,IAAI;AAAA,EACtC,GAAG,CAAC,eAAe,SAAS,IAAI,CAAC;AAEjC,QAAM,WAAWC;AAAA,IAChB,CAAC,kBAAkB,cAAc,EAAE,UAAU,aAAa;AAAA,IAC1D,MAAM,cAAc,EAAE,YAAY;AAAA,IAClC,MAAM,cAAc,EAAE,YAAY;AAAA,EACnC;AAEA,QAAM,OAAO,YAAY,MAAM;AAC9B,kBAAc,EAAE,KAAK;AAAA,EACtB,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,OAAO,YAAY,MAAM;AAC9B,kBAAc,EAAE,KAAK;AAAA,EACtB,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,YAAY;AAAA,IACjB,CAAC,QAAgB,SAAiB,cAAc,EAAE,UAAU,QAAQ,IAAI;AAAA,IACxE,CAAC,aAAa;AAAA,EACf;AACA,QAAM,cAAc,YAAY,MAAM,cAAc,EAAE,YAAY,GAAG,CAAC,aAAa,CAAC;AAEpF,SAAO,YAAY,cAAc,GAAG,UAAU,MAAM,MAAM,WAAW,WAAW;AACjF;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;;;ACvFA,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","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"]}
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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korajs/react",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.11",
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.1",
36
- "@korajs/store": "1.0.0-beta.1",
37
- "@korajs/sync": "1.0.0-beta.1"
35
+ "@korajs/core": "1.0.0-beta.11",
36
+ "@korajs/store": "1.0.0-beta.11",
37
+ "@korajs/sync": "1.0.0-beta.11"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/jest-dom": "^6.0.0",