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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -20,7 +20,9 @@ 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,
25
+ classifyKoraInitializationError: () => classifyKoraInitializationError,
24
26
  useApp: () => useApp,
25
27
  useCollaborators: () => useCollaborators,
26
28
  useCollection: () => useCollection,
@@ -120,6 +122,132 @@ function useKoraContext() {
120
122
  return context;
121
123
  }
122
124
 
125
+ // src/context/auth-bound-kora-provider.ts
126
+ var import_react2 = require("react");
127
+ var SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i;
128
+ function classifyKoraInitializationError(error) {
129
+ const candidate = error;
130
+ const message = typeof candidate?.message === "string" ? candidate.message : String(error);
131
+ const name = typeof candidate?.name === "string" ? candidate.name : "Error";
132
+ const cause = new Error(message);
133
+ cause.name = name;
134
+ if (typeof candidate?.stack === "string") cause.stack = candidate.stack;
135
+ let code = typeof candidate?.code === "string" ? candidate.code : "INITIALIZATION_FAILED";
136
+ if (code === "INITIALIZATION_FAILED" && cause.name === "QuotaExceededError") {
137
+ code = "STORAGE_QUOTA_EXCEEDED";
138
+ }
139
+ const metadata = {};
140
+ if (candidate?.context && typeof candidate.context === "object") {
141
+ for (const [key, value] of Object.entries(candidate.context)) {
142
+ if (SENSITIVE_METADATA_KEY.test(key)) continue;
143
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
144
+ metadata[key] = value;
145
+ }
146
+ }
147
+ }
148
+ return { code, name: cause.name, message: cause.message, metadata, cause };
149
+ }
150
+ function AuthBoundKoraProvider({
151
+ authClient,
152
+ createApp,
153
+ signedOut = null,
154
+ fallback = null,
155
+ error: renderError,
156
+ children
157
+ }) {
158
+ const [app, setApp] = (0, import_react2.useState)(null);
159
+ const [state, setState] = (0, import_react2.useState)({ state: "loading" });
160
+ const [initError, setInitError] = (0, import_react2.useState)(null);
161
+ const active = (0, import_react2.useRef)(null);
162
+ const createAppRef = (0, import_react2.useRef)(createApp);
163
+ createAppRef.current = createApp;
164
+ const activeUserId = (0, import_react2.useRef)(null);
165
+ const generation = (0, import_react2.useRef)(0);
166
+ const transition = (0, import_react2.useRef)(Promise.resolve());
167
+ const reconcileRef = (0, import_react2.useRef)(() => {
168
+ });
169
+ (0, import_react2.useEffect)(() => {
170
+ let disposed = false;
171
+ const reconcile = () => {
172
+ const currentGeneration = ++generation.current;
173
+ transition.current = transition.current.catch(() => {
174
+ }).then(async () => {
175
+ setInitError(null);
176
+ const next = await authClient.resolveSyncState?.() ?? { state: "signed-out", mayConnectAnonymously: false };
177
+ if (disposed || currentGeneration !== generation.current) return;
178
+ const previous = active.current;
179
+ if (next.state === "authenticated" && next.userId === activeUserId.current && previous) {
180
+ setState(next);
181
+ return;
182
+ }
183
+ setApp(null);
184
+ active.current = null;
185
+ activeUserId.current = null;
186
+ if (previous) await previous.close();
187
+ if (disposed || currentGeneration !== generation.current) return;
188
+ setState(next);
189
+ if (next.state !== "authenticated") return;
190
+ const created = createAppRef.current(next);
191
+ try {
192
+ await created.ready;
193
+ } catch (error) {
194
+ await created.close();
195
+ throw error;
196
+ }
197
+ if (disposed || currentGeneration !== generation.current) {
198
+ await created.close();
199
+ return;
200
+ }
201
+ active.current = created;
202
+ activeUserId.current = next.userId;
203
+ setApp(created);
204
+ }).catch((error) => {
205
+ if (!disposed && currentGeneration === generation.current) {
206
+ void authClient.resolveSyncState?.().then((failedSession) => {
207
+ if (!disposed && currentGeneration === generation.current && failedSession?.state === "authenticated") {
208
+ setInitError({
209
+ error: classifyKoraInitializationError(error),
210
+ session: { userId: failedSession.userId }
211
+ });
212
+ }
213
+ });
214
+ }
215
+ });
216
+ };
217
+ reconcileRef.current = reconcile;
218
+ reconcile();
219
+ const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
220
+ });
221
+ return () => {
222
+ disposed = true;
223
+ generation.current++;
224
+ unsubscribe();
225
+ const previous = active.current;
226
+ active.current = null;
227
+ activeUserId.current = null;
228
+ if (previous) void previous.close();
229
+ };
230
+ }, [authClient]);
231
+ if (initError) {
232
+ if (renderError) {
233
+ return renderError({
234
+ error: initError.error,
235
+ session: initError.session,
236
+ retry: () => reconcileRef.current()
237
+ });
238
+ }
239
+ return (0, import_react2.createElement)(
240
+ "div",
241
+ { style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
242
+ (0, import_react2.createElement)("strong", null, "Kora initialization error: "),
243
+ initError.error.message
244
+ );
245
+ }
246
+ if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
247
+ if (!app) return fallback;
248
+ return (0, import_react2.createElement)(KoraProvider, { app, fallback }, children);
249
+ }
250
+
123
251
  // src/hooks/use-app.ts
124
252
  function useApp() {
125
253
  const { app } = useKoraContext();
@@ -133,7 +261,7 @@ function useApp() {
133
261
 
134
262
  // src/hooks/use-query.ts
135
263
  var import_store2 = require("@korajs/store");
136
- var import_react2 = require("react");
264
+ var import_react3 = require("react");
137
265
  var EMPTY_ARRAY = Object.freeze([]);
138
266
  var noopSubscribe = (_onStoreChange) => {
139
267
  return () => {
@@ -143,11 +271,11 @@ function useQuery(query, options) {
143
271
  const { queryStoreCache } = useKoraContext();
144
272
  const enabled = options?.enabled !== false;
145
273
  const descriptorKey = JSON.stringify(query.getDescriptor());
146
- const queryRef = (0, import_react2.useRef)(query);
274
+ const queryRef = (0, import_react3.useRef)(query);
147
275
  queryRef.current = query;
148
- const lastSnapshotRef = (0, import_react2.useRef)(EMPTY_ARRAY);
149
- const [queryStore, setQueryStore] = (0, import_react2.useState)(null);
150
- (0, import_react2.useEffect)(() => {
276
+ const lastSnapshotRef = (0, import_react3.useRef)(EMPTY_ARRAY);
277
+ const [queryStore, setQueryStore] = (0, import_react3.useState)(null);
278
+ (0, import_react3.useEffect)(() => {
151
279
  if (!enabled) {
152
280
  setQueryStore(null);
153
281
  return;
@@ -160,7 +288,7 @@ function useQuery(query, options) {
160
288
  queryStoreCache.release(currentQuery);
161
289
  };
162
290
  }, [descriptorKey, enabled, queryStoreCache]);
163
- const getSnapshot = (0, import_react2.useCallback)(() => {
291
+ const getSnapshot = (0, import_react3.useCallback)(() => {
164
292
  if (!enabled) {
165
293
  lastSnapshotRef.current = EMPTY_ARRAY;
166
294
  return lastSnapshotRef.current;
@@ -175,27 +303,27 @@ function useQuery(query, options) {
175
303
  lastSnapshotRef.current = snapshot;
176
304
  return snapshot;
177
305
  }, [enabled, queryStore]);
178
- return (0, import_react2.useSyncExternalStore)(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot);
306
+ return (0, import_react3.useSyncExternalStore)(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot);
179
307
  }
180
308
 
181
309
  // src/hooks/use-mutation.ts
182
310
  var import_bindings = require("@korajs/core/bindings");
183
- var import_react4 = require("react");
311
+ var import_react5 = require("react");
184
312
 
185
313
  // src/hooks/use-controller.ts
186
- var import_react3 = require("react");
314
+ var import_react4 = require("react");
187
315
  function useController(create, destroy, deps) {
188
- const controllerRef = (0, import_react3.useRef)(null);
189
- const createRef = (0, import_react3.useRef)(create);
316
+ const controllerRef = (0, import_react4.useRef)(null);
317
+ const createRef = (0, import_react4.useRef)(create);
190
318
  createRef.current = create;
191
- const [, forceRender] = (0, import_react3.useReducer)((count) => count + 1, 0);
192
- const getController = (0, import_react3.useRef)(() => {
319
+ const [, forceRender] = (0, import_react4.useReducer)((count) => count + 1, 0);
320
+ const getController = (0, import_react4.useRef)(() => {
193
321
  if (controllerRef.current === null) {
194
322
  controllerRef.current = createRef.current();
195
323
  }
196
324
  return controllerRef.current;
197
325
  }).current;
198
- (0, import_react3.useEffect)(() => {
326
+ (0, import_react4.useEffect)(() => {
199
327
  if (controllerRef.current === null) {
200
328
  controllerRef.current = createRef.current();
201
329
  forceRender();
@@ -213,9 +341,9 @@ function useController(create, destroy, deps) {
213
341
 
214
342
  // src/hooks/use-mutation.ts
215
343
  function useMutation(mutationFn, options) {
216
- const fnRef = (0, import_react4.useRef)(mutationFn);
344
+ const fnRef = (0, import_react5.useRef)(mutationFn);
217
345
  fnRef.current = mutationFn;
218
- const optionsRef = (0, import_react4.useRef)(options);
346
+ const optionsRef = (0, import_react5.useRef)(options);
219
347
  optionsRef.current = options;
220
348
  const getController = useController(
221
349
  () => (0, import_bindings.createMutationController)({
@@ -225,7 +353,7 @@ function useMutation(mutationFn, options) {
225
353
  (controller) => controller.destroy(),
226
354
  []
227
355
  );
228
- const state = (0, import_react4.useSyncExternalStore)(
356
+ const state = (0, import_react5.useSyncExternalStore)(
229
357
  (onStoreChange) => getController().subscribe(onStoreChange),
230
358
  () => getController().getSnapshot(),
231
359
  () => getController().getSnapshot()
@@ -241,7 +369,7 @@ function useMutation(mutationFn, options) {
241
369
 
242
370
  // src/hooks/use-sync-status.ts
243
371
  var import_sync = require("@korajs/sync");
244
- var import_react5 = require("react");
372
+ var import_react6 = require("react");
245
373
  function useSyncStatus() {
246
374
  const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
247
375
  const getController = useController(
@@ -253,7 +381,7 @@ function useSyncStatus() {
253
381
  (controller) => controller.destroy(),
254
382
  [syncEngine, subscribeSyncStatus, events]
255
383
  );
256
- return (0, import_react5.useSyncExternalStore)(
384
+ return (0, import_react6.useSyncExternalStore)(
257
385
  (onStoreChange) => getController().subscribe(onStoreChange),
258
386
  () => getController().getSnapshot(),
259
387
  () => getController().getSnapshot()
@@ -261,20 +389,20 @@ function useSyncStatus() {
261
389
  }
262
390
 
263
391
  // src/hooks/use-collection.ts
264
- var import_react6 = require("react");
392
+ var import_react7 = require("react");
265
393
  function useCollection(name) {
266
394
  const { store } = useKoraContext();
267
- return (0, import_react6.useMemo)(() => {
395
+ return (0, import_react7.useMemo)(() => {
268
396
  return store.collection(name);
269
397
  }, [store, name]);
270
398
  }
271
399
 
272
400
  // src/hooks/use-rich-text.ts
273
401
  var import_store3 = require("@korajs/store");
274
- var import_react7 = require("react");
402
+ var import_react8 = require("react");
275
403
  function useRichText(collectionName, recordId, fieldName, options) {
276
404
  const { store, syncEngine } = useKoraContext();
277
- const collection = (0, import_react7.useMemo)(() => store.collection(collectionName), [store, collectionName]);
405
+ const collection = (0, import_react8.useMemo)(() => store.collection(collectionName), [store, collectionName]);
278
406
  const getController = useController(
279
407
  () => (0, import_store3.createRichTextController)({
280
408
  collection,
@@ -289,25 +417,25 @@ function useRichText(collectionName, recordId, fieldName, options) {
289
417
  (controller) => controller.destroy(),
290
418
  [collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
291
419
  );
292
- (0, import_react7.useEffect)(() => {
420
+ (0, import_react8.useEffect)(() => {
293
421
  getController().setUser(options?.user);
294
422
  }, [getController, options?.user]);
295
- const snapshot = (0, import_react7.useSyncExternalStore)(
423
+ const snapshot = (0, import_react8.useSyncExternalStore)(
296
424
  (onStoreChange) => getController().subscribe(onStoreChange),
297
425
  () => getController().getSnapshot(),
298
426
  () => getController().getSnapshot()
299
427
  );
300
- const undo = (0, import_react7.useCallback)(() => {
428
+ const undo = (0, import_react8.useCallback)(() => {
301
429
  getController().undo();
302
430
  }, [getController]);
303
- const redo = (0, import_react7.useCallback)(() => {
431
+ const redo = (0, import_react8.useCallback)(() => {
304
432
  getController().redo();
305
433
  }, [getController]);
306
- const setCursor = (0, import_react7.useCallback)(
434
+ const setCursor = (0, import_react8.useCallback)(
307
435
  (anchor, head) => getController().setCursor(anchor, head),
308
436
  [getController]
309
437
  );
310
- const clearCursor = (0, import_react7.useCallback)(() => getController().clearCursor(), [getController]);
438
+ const clearCursor = (0, import_react8.useCallback)(() => getController().clearCursor(), [getController]);
311
439
  return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
312
440
  }
313
441
  function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
@@ -327,13 +455,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
327
455
  }
328
456
 
329
457
  // src/hooks/use-presence.ts
330
- var import_react8 = require("react");
458
+ var import_react9 = require("react");
331
459
  function usePresence(user) {
332
460
  const { syncEngine } = useKoraContext();
333
461
  const name = user?.name ?? null;
334
462
  const color = user?.color ?? null;
335
463
  const avatar = user?.avatar ?? null;
336
- (0, import_react8.useEffect)(() => {
464
+ (0, import_react9.useEffect)(() => {
337
465
  if (!syncEngine || !name || !color) return;
338
466
  const awareness = syncEngine.getAwarenessManager();
339
467
  awareness.setLocalState({
@@ -347,12 +475,12 @@ function usePresence(user) {
347
475
 
348
476
  // src/hooks/use-collaborators.ts
349
477
  var import_sync2 = require("@korajs/sync");
350
- var import_react9 = require("react");
478
+ var import_react10 = require("react");
351
479
  var EMPTY_ARRAY2 = [];
352
480
  function useCollaborators() {
353
481
  const { syncEngine } = useKoraContext();
354
- const snapshotRef = (0, import_react9.useRef)(EMPTY_ARRAY2);
355
- const subscribe = (0, import_react9.useCallback)(
482
+ const snapshotRef = (0, import_react10.useRef)(EMPTY_ARRAY2);
483
+ const subscribe = (0, import_react10.useCallback)(
356
484
  (onStoreChange) => {
357
485
  if (!syncEngine) {
358
486
  snapshotRef.current = EMPTY_ARRAY2;
@@ -367,17 +495,19 @@ function useCollaborators() {
367
495
  },
368
496
  [syncEngine]
369
497
  );
370
- const getSnapshot = (0, import_react9.useCallback)(() => snapshotRef.current, []);
371
- (0, import_react9.useEffect)(() => {
498
+ const getSnapshot = (0, import_react10.useCallback)(() => snapshotRef.current, []);
499
+ (0, import_react10.useEffect)(() => {
372
500
  if (!syncEngine) {
373
501
  snapshotRef.current = EMPTY_ARRAY2;
374
502
  }
375
503
  }, [syncEngine]);
376
- return (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot);
504
+ return (0, import_react10.useSyncExternalStore)(subscribe, getSnapshot);
377
505
  }
378
506
  // Annotate the CommonJS export names for ESM import in node:
379
507
  0 && (module.exports = {
508
+ AuthBoundKoraProvider,
380
509
  KoraProvider,
510
+ classifyKoraInitializationError,
381
511
  useApp,
382
512
  useCollaborators,
383
513
  useCollection,
@@ -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 { 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_store","import_react","import_react","import_react","import_react","import_react","import_store","import_react","import_react","import_sync","import_react","EMPTY_ARRAY"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context/kora-context.ts","../src/context/auth-bound-kora-provider.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["// @korajs/react — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tKoraAppLike,\n\tKoraContextValue,\n\tKoraProviderProps,\n\tUseQueryOptions,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseRichTextResult,\n} from './types'\n\n// === Context ===\nexport { KoraProvider } from './context/kora-context'\nexport {\n\tAuthBoundKoraProvider,\n\tclassifyKoraInitializationError,\n} from './context/auth-bound-kora-provider'\nexport type {\n\tAuthBoundKoraErrorContext,\n\tAuthBoundKoraInitializationError,\n\tAuthBoundKoraProviderProps,\n\tAuthBoundKoraSession,\n} from './context/auth-bound-kora-provider'\n\n// === Hooks ===\nexport { useApp } from './hooks/use-app'\nexport { useQuery } from './hooks/use-query'\nexport { useMutation } from './hooks/use-mutation'\nexport { useSyncStatus } from './hooks/use-sync-status'\nexport { useCollection } from './hooks/use-collection'\nexport { useRichText } from './hooks/use-rich-text'\nexport type { UseRichTextOptions } from './hooks/use-rich-text'\nexport { usePresence } from './hooks/use-presence'\nexport { useCollaborators } from './hooks/use-collaborators'\n","import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\tcreateContext,\n\tcreateElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\tif (fallbackQueryStoreCache.current === null) {\n\t\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import type { AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraAppLike } from '../types'\nimport { KoraProvider } from './kora-context'\n\nexport interface AuthBoundKoraProviderProps {\n\tauthClient: AuthSyncBinding\n\tcreateApp: (\n\t\tsession: Extract<AuthSyncState, { state: 'authenticated' }>,\n\t) => KoraAppLike & { close(): Promise<void> }\n\tsignedOut?: ReactNode\n\tfallback?: ReactNode\n\terror?: (context: AuthBoundKoraErrorContext) => ReactNode\n\tchildren?: ReactNode\n}\n\nexport interface AuthBoundKoraSession {\n\t/** The authenticated identity only. Access tokens are deliberately omitted. */\n\tuserId: string\n}\n\nexport interface AuthBoundKoraInitializationError {\n\t/** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */\n\tcode: string\n\tname: string\n\tmessage: string\n\t/** Sanitized primitive metadata. Credential-shaped keys are always removed. */\n\tmetadata: Readonly<Record<string, string | number | boolean | null>>\n\t/** Sanitized Error for logging; custom credential-bearing properties are omitted. */\n\tcause: Error\n}\n\nexport interface AuthBoundKoraErrorContext {\n\terror: AuthBoundKoraInitializationError\n\tretry(): void\n\tsession: AuthBoundKoraSession\n}\n\nconst SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i\n\n/** Classify initialization failures without requiring applications to parse copy. */\nexport function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError {\n\tconst candidate = error as {\n\t\tcode?: unknown\n\t\tcontext?: unknown\n\t\tmessage?: unknown\n\t\tname?: unknown\n\t\tstack?: unknown\n\t}\n\tconst message = typeof candidate?.message === 'string' ? candidate.message : String(error)\n\tconst name = typeof candidate?.name === 'string' ? candidate.name : 'Error'\n\tconst cause = new Error(message)\n\tcause.name = name\n\tif (typeof candidate?.stack === 'string') cause.stack = candidate.stack\n\tlet code = typeof candidate?.code === 'string' ? candidate.code : 'INITIALIZATION_FAILED'\n\tif (code === 'INITIALIZATION_FAILED' && cause.name === 'QuotaExceededError') {\n\t\tcode = 'STORAGE_QUOTA_EXCEEDED'\n\t}\n\tconst metadata: Record<string, string | number | boolean | null> = {}\n\tif (candidate?.context && typeof candidate.context === 'object') {\n\t\tfor (const [key, value] of Object.entries(candidate.context)) {\n\t\t\tif (SENSITIVE_METADATA_KEY.test(key)) continue\n\t\t\tif (\n\t\t\t\ttypeof value === 'string' ||\n\t\t\t\ttypeof value === 'number' ||\n\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\tvalue === null\n\t\t\t) {\n\t\t\t\tmetadata[key] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn { code, name: cause.name, message: cause.message, metadata, cause }\n}\n\n/**\n * Owns the security-sensitive app lifetime for shared-browser applications.\n * The previous app is fully closed before a different user's app is created,\n * and no stale provider tree is rendered across that boundary.\n */\nexport function AuthBoundKoraProvider({\n\tauthClient,\n\tcreateApp,\n\tsignedOut = null,\n\tfallback = null,\n\terror: renderError,\n\tchildren,\n}: AuthBoundKoraProviderProps): ReactNode {\n\tconst [app, setApp] = useState<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst [state, setState] = useState<AuthSyncState>({ state: 'loading' })\n\tconst [initError, setInitError] = useState<{\n\t\terror: AuthBoundKoraInitializationError\n\t\tsession: AuthBoundKoraSession\n\t} | null>(null)\n\tconst active = useRef<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst createAppRef = useRef(createApp)\n\tcreateAppRef.current = createApp\n\tconst activeUserId = useRef<string | null>(null)\n\tconst generation = useRef(0)\n\tconst transition = useRef(Promise.resolve())\n\tconst reconcileRef = useRef<() => void>(() => {})\n\n\tuseEffect(() => {\n\t\tlet disposed = false\n\t\tconst reconcile = (): void => {\n\t\t\tconst currentGeneration = ++generation.current\n\t\t\ttransition.current = transition.current\n\t\t\t\t.catch(() => {})\n\t\t\t\t.then(async () => {\n\t\t\t\t\tsetInitError(null)\n\t\t\t\t\tconst next =\n\t\t\t\t\t\t(await authClient.resolveSyncState?.()) ??\n\t\t\t\t\t\t({ state: 'signed-out', mayConnectAnonymously: false } as const)\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tconst previous = active.current\n\t\t\t\t\t// Same-user token/role refreshes stay on the same database and app instance.\n\t\t\t\t\tif (next.state === 'authenticated' && next.userId === activeUserId.current && previous) {\n\t\t\t\t\t\tsetState(next)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetApp(null)\n\t\t\t\t\tactive.current = null\n\t\t\t\t\tactiveUserId.current = null\n\t\t\t\t\tif (previous) await previous.close()\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tsetState(next)\n\t\t\t\t\tif (next.state !== 'authenticated') return\n\t\t\t\t\tconst created = createAppRef.current(next)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait created.ready\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tactive.current = created\n\t\t\t\t\tactiveUserId.current = next.userId\n\t\t\t\t\tsetApp(created)\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tif (!disposed && currentGeneration === generation.current) {\n\t\t\t\t\t\tvoid authClient.resolveSyncState?.().then((failedSession) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!disposed &&\n\t\t\t\t\t\t\t\tcurrentGeneration === generation.current &&\n\t\t\t\t\t\t\t\tfailedSession?.state === 'authenticated'\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tsetInitError({\n\t\t\t\t\t\t\t\t\terror: classifyKoraInitializationError(error),\n\t\t\t\t\t\t\t\t\tsession: { userId: failedSession.userId },\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t\treconcileRef.current = reconcile\n\t\treconcile()\n\t\tconst unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {})\n\t\treturn () => {\n\t\t\tdisposed = true\n\t\t\tgeneration.current++\n\t\t\tunsubscribe()\n\t\t\tconst previous = active.current\n\t\t\tactive.current = null\n\t\t\tactiveUserId.current = null\n\t\t\tif (previous) void previous.close()\n\t\t}\n\t}, [authClient])\n\n\tif (initError) {\n\t\tif (renderError) {\n\t\t\treturn renderError({\n\t\t\t\terror: initError.error,\n\t\t\t\tsession: initError.session,\n\t\t\t\tretry: () => reconcileRef.current(),\n\t\t\t})\n\t\t}\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.error.message,\n\t\t)\n\t}\n\tif (state.state === 'signed-out' || state.state === 'anonymous') return signedOut\n\tif (!app) return fallback\n\treturn createElement(KoraProvider, { app, fallback }, children)\n}\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires KoraProvider to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\tconst lastSnapshotRef = useRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: descriptorKey intentionally re-runs the effect when the query descriptor changes, even though the effect reads the query via queryRef\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst getSnapshot = useCallback((): readonly T[] => {\n\t\tif (!enabled) {\n\t\t\tlastSnapshotRef.current = EMPTY_ARRAY as readonly T[]\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore.hasSnapshot()) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tconst snapshot = queryStore.getSnapshot()\n\t\tlastSnapshotRef.current = snapshot\n\t\treturn snapshot\n\t}, [enabled, queryStore])\n\n\treturn useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["import_react","import_store","import_react","import_react","import_react","import_react","import_react","import_store","import_react","import_react","import_sync","import_react","EMPTY_ARRAY"]}
package/dist/index.d.cts CHANGED
@@ -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,46 @@ 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
+ error?: (context: AuthBoundKoraErrorContext) => ReactNode;
58
+ children?: ReactNode;
59
+ }
60
+ interface AuthBoundKoraSession {
61
+ /** The authenticated identity only. Access tokens are deliberately omitted. */
62
+ userId: string;
63
+ }
64
+ interface AuthBoundKoraInitializationError {
65
+ /** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */
66
+ code: string;
67
+ name: string;
68
+ message: string;
69
+ /** Sanitized primitive metadata. Credential-shaped keys are always removed. */
70
+ metadata: Readonly<Record<string, string | number | boolean | null>>;
71
+ /** Sanitized Error for logging; custom credential-bearing properties are omitted. */
72
+ cause: Error;
73
+ }
74
+ interface AuthBoundKoraErrorContext {
75
+ error: AuthBoundKoraInitializationError;
76
+ retry(): void;
77
+ session: AuthBoundKoraSession;
78
+ }
79
+ /** Classify initialization failures without requiring applications to parse copy. */
80
+ declare function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError;
81
+ /**
82
+ * Owns the security-sensitive app lifetime for shared-browser applications.
83
+ * The previous app is fully closed before a different user's app is created,
84
+ * and no stale provider tree is rendered across that boundary.
85
+ */
86
+ declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, error: renderError, children, }: AuthBoundKoraProviderProps): ReactNode;
87
+
48
88
  /**
49
89
  * React hook that returns the Kora app instance from context.
50
90
  *
@@ -125,4 +165,4 @@ declare function usePresence(user: {
125
165
  */
126
166
  declare function useCollaborators(): AwarenessState[];
127
167
 
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 };
168
+ export { type AuthBoundKoraErrorContext, type AuthBoundKoraInitializationError, AuthBoundKoraProvider, type AuthBoundKoraProviderProps, type AuthBoundKoraSession, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, classifyKoraInitializationError, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
package/dist/index.d.ts CHANGED
@@ -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,46 @@ 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
+ error?: (context: AuthBoundKoraErrorContext) => ReactNode;
58
+ children?: ReactNode;
59
+ }
60
+ interface AuthBoundKoraSession {
61
+ /** The authenticated identity only. Access tokens are deliberately omitted. */
62
+ userId: string;
63
+ }
64
+ interface AuthBoundKoraInitializationError {
65
+ /** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */
66
+ code: string;
67
+ name: string;
68
+ message: string;
69
+ /** Sanitized primitive metadata. Credential-shaped keys are always removed. */
70
+ metadata: Readonly<Record<string, string | number | boolean | null>>;
71
+ /** Sanitized Error for logging; custom credential-bearing properties are omitted. */
72
+ cause: Error;
73
+ }
74
+ interface AuthBoundKoraErrorContext {
75
+ error: AuthBoundKoraInitializationError;
76
+ retry(): void;
77
+ session: AuthBoundKoraSession;
78
+ }
79
+ /** Classify initialization failures without requiring applications to parse copy. */
80
+ declare function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError;
81
+ /**
82
+ * Owns the security-sensitive app lifetime for shared-browser applications.
83
+ * The previous app is fully closed before a different user's app is created,
84
+ * and no stale provider tree is rendered across that boundary.
85
+ */
86
+ declare function AuthBoundKoraProvider({ authClient, createApp, signedOut, fallback, error: renderError, children, }: AuthBoundKoraProviderProps): ReactNode;
87
+
48
88
  /**
49
89
  * React hook that returns the Kora app instance from context.
50
90
  *
@@ -125,4 +165,4 @@ declare function usePresence(user: {
125
165
  */
126
166
  declare function useCollaborators(): AwarenessState[];
127
167
 
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 };
168
+ export { type AuthBoundKoraErrorContext, type AuthBoundKoraInitializationError, AuthBoundKoraProvider, type AuthBoundKoraProviderProps, type AuthBoundKoraSession, type KoraAppLike, type KoraContextValue, KoraProvider, type KoraProviderProps, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, classifyKoraInitializationError, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
package/dist/index.js CHANGED
@@ -94,6 +94,132 @@ 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
+ var SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i;
100
+ function classifyKoraInitializationError(error) {
101
+ const candidate = error;
102
+ const message = typeof candidate?.message === "string" ? candidate.message : String(error);
103
+ const name = typeof candidate?.name === "string" ? candidate.name : "Error";
104
+ const cause = new Error(message);
105
+ cause.name = name;
106
+ if (typeof candidate?.stack === "string") cause.stack = candidate.stack;
107
+ let code = typeof candidate?.code === "string" ? candidate.code : "INITIALIZATION_FAILED";
108
+ if (code === "INITIALIZATION_FAILED" && cause.name === "QuotaExceededError") {
109
+ code = "STORAGE_QUOTA_EXCEEDED";
110
+ }
111
+ const metadata = {};
112
+ if (candidate?.context && typeof candidate.context === "object") {
113
+ for (const [key, value] of Object.entries(candidate.context)) {
114
+ if (SENSITIVE_METADATA_KEY.test(key)) continue;
115
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
116
+ metadata[key] = value;
117
+ }
118
+ }
119
+ }
120
+ return { code, name: cause.name, message: cause.message, metadata, cause };
121
+ }
122
+ function AuthBoundKoraProvider({
123
+ authClient,
124
+ createApp,
125
+ signedOut = null,
126
+ fallback = null,
127
+ error: renderError,
128
+ children
129
+ }) {
130
+ const [app, setApp] = useState2(null);
131
+ const [state, setState] = useState2({ state: "loading" });
132
+ const [initError, setInitError] = useState2(null);
133
+ const active = useRef2(null);
134
+ const createAppRef = useRef2(createApp);
135
+ createAppRef.current = createApp;
136
+ const activeUserId = useRef2(null);
137
+ const generation = useRef2(0);
138
+ const transition = useRef2(Promise.resolve());
139
+ const reconcileRef = useRef2(() => {
140
+ });
141
+ useEffect2(() => {
142
+ let disposed = false;
143
+ const reconcile = () => {
144
+ const currentGeneration = ++generation.current;
145
+ transition.current = transition.current.catch(() => {
146
+ }).then(async () => {
147
+ setInitError(null);
148
+ const next = await authClient.resolveSyncState?.() ?? { state: "signed-out", mayConnectAnonymously: false };
149
+ if (disposed || currentGeneration !== generation.current) return;
150
+ const previous = active.current;
151
+ if (next.state === "authenticated" && next.userId === activeUserId.current && previous) {
152
+ setState(next);
153
+ return;
154
+ }
155
+ setApp(null);
156
+ active.current = null;
157
+ activeUserId.current = null;
158
+ if (previous) await previous.close();
159
+ if (disposed || currentGeneration !== generation.current) return;
160
+ setState(next);
161
+ if (next.state !== "authenticated") return;
162
+ const created = createAppRef.current(next);
163
+ try {
164
+ await created.ready;
165
+ } catch (error) {
166
+ await created.close();
167
+ throw error;
168
+ }
169
+ if (disposed || currentGeneration !== generation.current) {
170
+ await created.close();
171
+ return;
172
+ }
173
+ active.current = created;
174
+ activeUserId.current = next.userId;
175
+ setApp(created);
176
+ }).catch((error) => {
177
+ if (!disposed && currentGeneration === generation.current) {
178
+ void authClient.resolveSyncState?.().then((failedSession) => {
179
+ if (!disposed && currentGeneration === generation.current && failedSession?.state === "authenticated") {
180
+ setInitError({
181
+ error: classifyKoraInitializationError(error),
182
+ session: { userId: failedSession.userId }
183
+ });
184
+ }
185
+ });
186
+ }
187
+ });
188
+ };
189
+ reconcileRef.current = reconcile;
190
+ reconcile();
191
+ const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
192
+ });
193
+ return () => {
194
+ disposed = true;
195
+ generation.current++;
196
+ unsubscribe();
197
+ const previous = active.current;
198
+ active.current = null;
199
+ activeUserId.current = null;
200
+ if (previous) void previous.close();
201
+ };
202
+ }, [authClient]);
203
+ if (initError) {
204
+ if (renderError) {
205
+ return renderError({
206
+ error: initError.error,
207
+ session: initError.session,
208
+ retry: () => reconcileRef.current()
209
+ });
210
+ }
211
+ return createElement2(
212
+ "div",
213
+ { style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
214
+ createElement2("strong", null, "Kora initialization error: "),
215
+ initError.error.message
216
+ );
217
+ }
218
+ if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
219
+ if (!app) return fallback;
220
+ return createElement2(KoraProvider, { app, fallback }, children);
221
+ }
222
+
97
223
  // src/hooks/use-app.ts
98
224
  function useApp() {
99
225
  const { app } = useKoraContext();
@@ -107,7 +233,7 @@ function useApp() {
107
233
 
108
234
  // src/hooks/use-query.ts
109
235
  import { assertQueryReady } from "@korajs/store";
110
- import { useCallback, useEffect as useEffect2, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
236
+ import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState3, useSyncExternalStore } from "react";
111
237
  var EMPTY_ARRAY = Object.freeze([]);
112
238
  var noopSubscribe = (_onStoreChange) => {
113
239
  return () => {
@@ -117,11 +243,11 @@ function useQuery(query, options) {
117
243
  const { queryStoreCache } = useKoraContext();
118
244
  const enabled = options?.enabled !== false;
119
245
  const descriptorKey = JSON.stringify(query.getDescriptor());
120
- const queryRef = useRef2(query);
246
+ const queryRef = useRef3(query);
121
247
  queryRef.current = query;
122
- const lastSnapshotRef = useRef2(EMPTY_ARRAY);
123
- const [queryStore, setQueryStore] = useState2(null);
124
- useEffect2(() => {
248
+ const lastSnapshotRef = useRef3(EMPTY_ARRAY);
249
+ const [queryStore, setQueryStore] = useState3(null);
250
+ useEffect3(() => {
125
251
  if (!enabled) {
126
252
  setQueryStore(null);
127
253
  return;
@@ -154,22 +280,22 @@ function useQuery(query, options) {
154
280
 
155
281
  // src/hooks/use-mutation.ts
156
282
  import { createMutationController } from "@korajs/core/bindings";
157
- import { useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
283
+ import { useRef as useRef5, useSyncExternalStore as useSyncExternalStore2 } from "react";
158
284
 
159
285
  // src/hooks/use-controller.ts
160
- import { useEffect as useEffect3, useReducer, useRef as useRef3 } from "react";
286
+ import { useEffect as useEffect4, useReducer, useRef as useRef4 } from "react";
161
287
  function useController(create, destroy, deps) {
162
- const controllerRef = useRef3(null);
163
- const createRef = useRef3(create);
288
+ const controllerRef = useRef4(null);
289
+ const createRef = useRef4(create);
164
290
  createRef.current = create;
165
291
  const [, forceRender] = useReducer((count) => count + 1, 0);
166
- const getController = useRef3(() => {
292
+ const getController = useRef4(() => {
167
293
  if (controllerRef.current === null) {
168
294
  controllerRef.current = createRef.current();
169
295
  }
170
296
  return controllerRef.current;
171
297
  }).current;
172
- useEffect3(() => {
298
+ useEffect4(() => {
173
299
  if (controllerRef.current === null) {
174
300
  controllerRef.current = createRef.current();
175
301
  forceRender();
@@ -187,9 +313,9 @@ function useController(create, destroy, deps) {
187
313
 
188
314
  // src/hooks/use-mutation.ts
189
315
  function useMutation(mutationFn, options) {
190
- const fnRef = useRef4(mutationFn);
316
+ const fnRef = useRef5(mutationFn);
191
317
  fnRef.current = mutationFn;
192
- const optionsRef = useRef4(options);
318
+ const optionsRef = useRef5(options);
193
319
  optionsRef.current = options;
194
320
  const getController = useController(
195
321
  () => createMutationController({
@@ -245,7 +371,7 @@ function useCollection(name) {
245
371
 
246
372
  // src/hooks/use-rich-text.ts
247
373
  import { asRichTextSyncEngine, createRichTextController } from "@korajs/store";
248
- import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
374
+ import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
249
375
  function useRichText(collectionName, recordId, fieldName, options) {
250
376
  const { store, syncEngine } = useKoraContext();
251
377
  const collection = useMemo3(() => store.collection(collectionName), [store, collectionName]);
@@ -263,7 +389,7 @@ function useRichText(collectionName, recordId, fieldName, options) {
263
389
  (controller) => controller.destroy(),
264
390
  [collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
265
391
  );
266
- useEffect4(() => {
392
+ useEffect5(() => {
267
393
  getController().setUser(options?.user);
268
394
  }, [getController, options?.user]);
269
395
  const snapshot = useSyncExternalStore4(
@@ -301,13 +427,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
301
427
  }
302
428
 
303
429
  // src/hooks/use-presence.ts
304
- import { useEffect as useEffect5 } from "react";
430
+ import { useEffect as useEffect6 } from "react";
305
431
  function usePresence(user) {
306
432
  const { syncEngine } = useKoraContext();
307
433
  const name = user?.name ?? null;
308
434
  const color = user?.color ?? null;
309
435
  const avatar = user?.avatar ?? null;
310
- useEffect5(() => {
436
+ useEffect6(() => {
311
437
  if (!syncEngine || !name || !color) return;
312
438
  const awareness = syncEngine.getAwarenessManager();
313
439
  awareness.setLocalState({
@@ -321,11 +447,11 @@ function usePresence(user) {
321
447
 
322
448
  // src/hooks/use-collaborators.ts
323
449
  import { subscribeRemoteAwarenessStates } from "@korajs/sync";
324
- import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
450
+ import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef6, useSyncExternalStore as useSyncExternalStore5 } from "react";
325
451
  var EMPTY_ARRAY2 = [];
326
452
  function useCollaborators() {
327
453
  const { syncEngine } = useKoraContext();
328
- const snapshotRef = useRef5(EMPTY_ARRAY2);
454
+ const snapshotRef = useRef6(EMPTY_ARRAY2);
329
455
  const subscribe = useCallback3(
330
456
  (onStoreChange) => {
331
457
  if (!syncEngine) {
@@ -342,7 +468,7 @@ function useCollaborators() {
342
468
  [syncEngine]
343
469
  );
344
470
  const getSnapshot = useCallback3(() => snapshotRef.current, []);
345
- useEffect6(() => {
471
+ useEffect7(() => {
346
472
  if (!syncEngine) {
347
473
  snapshotRef.current = EMPTY_ARRAY2;
348
474
  }
@@ -350,7 +476,9 @@ function useCollaborators() {
350
476
  return useSyncExternalStore5(subscribe, getSnapshot);
351
477
  }
352
478
  export {
479
+ AuthBoundKoraProvider,
353
480
  KoraProvider,
481
+ classifyKoraInitializationError,
354
482
  useApp,
355
483
  useCollaborators,
356
484
  useCollection,
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 { 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":["useEffect","useRef","useState","useRef","useState","useEffect","useRef","useSyncExternalStore","useEffect","useRef","useRef","useSyncExternalStore","useSyncExternalStore","useSyncExternalStore","useMemo","useMemo","useCallback","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useCallback","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
1
+ {"version":3,"sources":["../src/context/kora-context.ts","../src/context/auth-bound-kora-provider.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport {\n\tcreateContext,\n\tcreateElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\tif (fallbackQueryStoreCache.current === null) {\n\t\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import type { AuthSyncBinding, AuthSyncState } from '@korajs/core/bindings'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraAppLike } from '../types'\nimport { KoraProvider } from './kora-context'\n\nexport interface AuthBoundKoraProviderProps {\n\tauthClient: AuthSyncBinding\n\tcreateApp: (\n\t\tsession: Extract<AuthSyncState, { state: 'authenticated' }>,\n\t) => KoraAppLike & { close(): Promise<void> }\n\tsignedOut?: ReactNode\n\tfallback?: ReactNode\n\terror?: (context: AuthBoundKoraErrorContext) => ReactNode\n\tchildren?: ReactNode\n}\n\nexport interface AuthBoundKoraSession {\n\t/** The authenticated identity only. Access tokens are deliberately omitted. */\n\tuserId: string\n}\n\nexport interface AuthBoundKoraInitializationError {\n\t/** Stable Kora/DOM error code suitable for application-owned copy and recovery UI. */\n\tcode: string\n\tname: string\n\tmessage: string\n\t/** Sanitized primitive metadata. Credential-shaped keys are always removed. */\n\tmetadata: Readonly<Record<string, string | number | boolean | null>>\n\t/** Sanitized Error for logging; custom credential-bearing properties are omitted. */\n\tcause: Error\n}\n\nexport interface AuthBoundKoraErrorContext {\n\terror: AuthBoundKoraInitializationError\n\tretry(): void\n\tsession: AuthBoundKoraSession\n}\n\nconst SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i\n\n/** Classify initialization failures without requiring applications to parse copy. */\nexport function classifyKoraInitializationError(error: unknown): AuthBoundKoraInitializationError {\n\tconst candidate = error as {\n\t\tcode?: unknown\n\t\tcontext?: unknown\n\t\tmessage?: unknown\n\t\tname?: unknown\n\t\tstack?: unknown\n\t}\n\tconst message = typeof candidate?.message === 'string' ? candidate.message : String(error)\n\tconst name = typeof candidate?.name === 'string' ? candidate.name : 'Error'\n\tconst cause = new Error(message)\n\tcause.name = name\n\tif (typeof candidate?.stack === 'string') cause.stack = candidate.stack\n\tlet code = typeof candidate?.code === 'string' ? candidate.code : 'INITIALIZATION_FAILED'\n\tif (code === 'INITIALIZATION_FAILED' && cause.name === 'QuotaExceededError') {\n\t\tcode = 'STORAGE_QUOTA_EXCEEDED'\n\t}\n\tconst metadata: Record<string, string | number | boolean | null> = {}\n\tif (candidate?.context && typeof candidate.context === 'object') {\n\t\tfor (const [key, value] of Object.entries(candidate.context)) {\n\t\t\tif (SENSITIVE_METADATA_KEY.test(key)) continue\n\t\t\tif (\n\t\t\t\ttypeof value === 'string' ||\n\t\t\t\ttypeof value === 'number' ||\n\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\tvalue === null\n\t\t\t) {\n\t\t\t\tmetadata[key] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn { code, name: cause.name, message: cause.message, metadata, cause }\n}\n\n/**\n * Owns the security-sensitive app lifetime for shared-browser applications.\n * The previous app is fully closed before a different user's app is created,\n * and no stale provider tree is rendered across that boundary.\n */\nexport function AuthBoundKoraProvider({\n\tauthClient,\n\tcreateApp,\n\tsignedOut = null,\n\tfallback = null,\n\terror: renderError,\n\tchildren,\n}: AuthBoundKoraProviderProps): ReactNode {\n\tconst [app, setApp] = useState<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst [state, setState] = useState<AuthSyncState>({ state: 'loading' })\n\tconst [initError, setInitError] = useState<{\n\t\terror: AuthBoundKoraInitializationError\n\t\tsession: AuthBoundKoraSession\n\t} | null>(null)\n\tconst active = useRef<(KoraAppLike & { close(): Promise<void> }) | null>(null)\n\tconst createAppRef = useRef(createApp)\n\tcreateAppRef.current = createApp\n\tconst activeUserId = useRef<string | null>(null)\n\tconst generation = useRef(0)\n\tconst transition = useRef(Promise.resolve())\n\tconst reconcileRef = useRef<() => void>(() => {})\n\n\tuseEffect(() => {\n\t\tlet disposed = false\n\t\tconst reconcile = (): void => {\n\t\t\tconst currentGeneration = ++generation.current\n\t\t\ttransition.current = transition.current\n\t\t\t\t.catch(() => {})\n\t\t\t\t.then(async () => {\n\t\t\t\t\tsetInitError(null)\n\t\t\t\t\tconst next =\n\t\t\t\t\t\t(await authClient.resolveSyncState?.()) ??\n\t\t\t\t\t\t({ state: 'signed-out', mayConnectAnonymously: false } as const)\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tconst previous = active.current\n\t\t\t\t\t// Same-user token/role refreshes stay on the same database and app instance.\n\t\t\t\t\tif (next.state === 'authenticated' && next.userId === activeUserId.current && previous) {\n\t\t\t\t\t\tsetState(next)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetApp(null)\n\t\t\t\t\tactive.current = null\n\t\t\t\t\tactiveUserId.current = null\n\t\t\t\t\tif (previous) await previous.close()\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) return\n\t\t\t\t\tsetState(next)\n\t\t\t\t\tif (next.state !== 'authenticated') return\n\t\t\t\t\tconst created = createAppRef.current(next)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait created.ready\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\tif (disposed || currentGeneration !== generation.current) {\n\t\t\t\t\t\tawait created.close()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tactive.current = created\n\t\t\t\t\tactiveUserId.current = next.userId\n\t\t\t\t\tsetApp(created)\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tif (!disposed && currentGeneration === generation.current) {\n\t\t\t\t\t\tvoid authClient.resolveSyncState?.().then((failedSession) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!disposed &&\n\t\t\t\t\t\t\t\tcurrentGeneration === generation.current &&\n\t\t\t\t\t\t\t\tfailedSession?.state === 'authenticated'\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tsetInitError({\n\t\t\t\t\t\t\t\t\terror: classifyKoraInitializationError(error),\n\t\t\t\t\t\t\t\t\tsession: { userId: failedSession.userId },\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t\treconcileRef.current = reconcile\n\t\treconcile()\n\t\tconst unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {})\n\t\treturn () => {\n\t\t\tdisposed = true\n\t\t\tgeneration.current++\n\t\t\tunsubscribe()\n\t\t\tconst previous = active.current\n\t\t\tactive.current = null\n\t\t\tactiveUserId.current = null\n\t\t\tif (previous) void previous.close()\n\t\t}\n\t}, [authClient])\n\n\tif (initError) {\n\t\tif (renderError) {\n\t\t\treturn renderError({\n\t\t\t\terror: initError.error,\n\t\t\t\tsession: initError.session,\n\t\t\t\tretry: () => reconcileRef.current(),\n\t\t\t})\n\t\t}\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.error.message,\n\t\t)\n\t}\n\tif (state.state === 'signed-out' || state.state === 'anonymous') return signedOut\n\tif (!app) return fallback\n\treturn createElement(KoraProvider, { app, fallback }, children)\n}\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires KoraProvider to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\tconst lastSnapshotRef = useRef<readonly T[]>(EMPTY_ARRAY as readonly T[])\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: descriptorKey intentionally re-runs the effect when the query descriptor changes, even though the effect reads the query via queryRef\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst getSnapshot = useCallback((): readonly T[] => {\n\t\tif (!enabled) {\n\t\t\tlastSnapshotRef.current = EMPTY_ARRAY as readonly T[]\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tif (!queryStore.hasSnapshot()) {\n\t\t\treturn lastSnapshotRef.current\n\t\t}\n\t\tconst snapshot = queryStore.getSnapshot()\n\t\tlastSnapshotRef.current = snapshot\n\t\treturn snapshot\n\t}, [enabled, queryStore])\n\n\treturn useSyncExternalStore(queryStore ? queryStore.subscribe : noopSubscribe, getSnapshot)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["createElement","useEffect","useRef","useState","useState","useRef","useEffect","createElement","useEffect","useRef","useState","useRef","useState","useEffect","useRef","useSyncExternalStore","useEffect","useRef","useRef","useSyncExternalStore","useSyncExternalStore","useSyncExternalStore","useMemo","useMemo","useCallback","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useCallback","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korajs/react",
3
- "version": "1.0.0-beta.10",
3
+ "version": "1.0.0-beta.12",
4
4
  "description": "Kora.js React hooks and bindings for offline-first applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -32,9 +32,9 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "yjs": "^13.6.30",
35
- "@korajs/core": "1.0.0-beta.10",
36
- "@korajs/store": "1.0.0-beta.10",
37
- "@korajs/sync": "1.0.0-beta.10"
35
+ "@korajs/core": "1.0.0-beta.12",
36
+ "@korajs/sync": "1.0.0-beta.12",
37
+ "@korajs/store": "1.0.0-beta.12"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/jest-dom": "^6.0.0",