@korajs/react 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +81 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +75 -43
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -166,74 +166,102 @@ function useQuery(query, options) {
|
|
|
166
166
|
|
|
167
167
|
// src/hooks/use-mutation.ts
|
|
168
168
|
var import_bindings = require("@korajs/core/bindings");
|
|
169
|
+
var import_react4 = require("react");
|
|
170
|
+
|
|
171
|
+
// src/hooks/use-controller.ts
|
|
169
172
|
var import_react3 = require("react");
|
|
173
|
+
function useController(create, destroy, deps) {
|
|
174
|
+
const controllerRef = (0, import_react3.useRef)(null);
|
|
175
|
+
const createRef = (0, import_react3.useRef)(create);
|
|
176
|
+
createRef.current = create;
|
|
177
|
+
const [, forceRender] = (0, import_react3.useReducer)((count) => count + 1, 0);
|
|
178
|
+
const getController = (0, import_react3.useRef)(() => {
|
|
179
|
+
if (controllerRef.current === null) {
|
|
180
|
+
controllerRef.current = createRef.current();
|
|
181
|
+
}
|
|
182
|
+
return controllerRef.current;
|
|
183
|
+
}).current;
|
|
184
|
+
(0, import_react3.useEffect)(() => {
|
|
185
|
+
if (controllerRef.current === null) {
|
|
186
|
+
controllerRef.current = createRef.current();
|
|
187
|
+
forceRender();
|
|
188
|
+
}
|
|
189
|
+
return () => {
|
|
190
|
+
const controller = controllerRef.current;
|
|
191
|
+
controllerRef.current = null;
|
|
192
|
+
if (controller !== null) {
|
|
193
|
+
destroy(controller);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}, deps);
|
|
197
|
+
return getController;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// src/hooks/use-mutation.ts
|
|
170
201
|
function useMutation(mutationFn, options) {
|
|
171
|
-
const fnRef = (0,
|
|
202
|
+
const fnRef = (0, import_react4.useRef)(mutationFn);
|
|
172
203
|
fnRef.current = mutationFn;
|
|
173
|
-
const optionsRef = (0,
|
|
204
|
+
const optionsRef = (0, import_react4.useRef)(options);
|
|
174
205
|
optionsRef.current = options;
|
|
175
|
-
const
|
|
206
|
+
const getController = useController(
|
|
176
207
|
() => (0, import_bindings.createMutationController)({
|
|
177
208
|
mutationFn: (...args) => fnRef.current(...args),
|
|
178
209
|
resolveOptions: () => optionsRef.current
|
|
179
210
|
}),
|
|
211
|
+
(controller) => controller.destroy(),
|
|
180
212
|
[]
|
|
181
213
|
);
|
|
182
|
-
(0,
|
|
183
|
-
|
|
184
|
-
(
|
|
185
|
-
() =>
|
|
186
|
-
() => controller.getSnapshot()
|
|
214
|
+
const state = (0, import_react4.useSyncExternalStore)(
|
|
215
|
+
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
216
|
+
() => getController().getSnapshot(),
|
|
217
|
+
() => getController().getSnapshot()
|
|
187
218
|
);
|
|
188
219
|
return {
|
|
189
|
-
mutate: (...args) =>
|
|
190
|
-
mutateAsync: (...args) =>
|
|
220
|
+
mutate: (...args) => getController().mutate(...args),
|
|
221
|
+
mutateAsync: (...args) => getController().mutateAsync(...args),
|
|
191
222
|
isLoading: state.isLoading,
|
|
192
223
|
error: state.error,
|
|
193
|
-
reset: () =>
|
|
224
|
+
reset: () => getController().reset()
|
|
194
225
|
};
|
|
195
226
|
}
|
|
196
227
|
|
|
197
228
|
// src/hooks/use-sync-status.ts
|
|
198
229
|
var import_sync = require("@korajs/sync");
|
|
199
|
-
var
|
|
230
|
+
var import_react5 = require("react");
|
|
200
231
|
function useSyncStatus() {
|
|
201
232
|
const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
|
|
202
|
-
const
|
|
233
|
+
const getController = useController(
|
|
203
234
|
() => (0, import_sync.createSyncStatusController)({
|
|
204
235
|
syncEngine,
|
|
205
236
|
subscribeSyncStatus,
|
|
206
237
|
events: subscribeSyncStatus ? null : events
|
|
207
238
|
}),
|
|
239
|
+
(controller) => controller.destroy(),
|
|
208
240
|
[syncEngine, subscribeSyncStatus, events]
|
|
209
241
|
);
|
|
210
|
-
(0,
|
|
211
|
-
|
|
212
|
-
(
|
|
213
|
-
() =>
|
|
214
|
-
() => controller.getSnapshot()
|
|
242
|
+
return (0, import_react5.useSyncExternalStore)(
|
|
243
|
+
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
244
|
+
() => getController().getSnapshot(),
|
|
245
|
+
() => getController().getSnapshot()
|
|
215
246
|
);
|
|
216
247
|
}
|
|
217
248
|
|
|
218
249
|
// src/hooks/use-collection.ts
|
|
219
|
-
var
|
|
250
|
+
var import_react6 = require("react");
|
|
220
251
|
function useCollection(name) {
|
|
221
252
|
const { store } = useKoraContext();
|
|
222
|
-
return (0,
|
|
253
|
+
return (0, import_react6.useMemo)(() => {
|
|
223
254
|
return store.collection(name);
|
|
224
255
|
}, [store, name]);
|
|
225
256
|
}
|
|
226
257
|
|
|
227
258
|
// src/hooks/use-rich-text.ts
|
|
228
259
|
var import_store3 = require("@korajs/store");
|
|
229
|
-
var
|
|
260
|
+
var import_react7 = require("react");
|
|
230
261
|
function useRichText(collectionName, recordId, fieldName, options) {
|
|
231
262
|
const { store, syncEngine } = useKoraContext();
|
|
232
|
-
const collection = (0,
|
|
233
|
-
|
|
234
|
-
[store, collectionName]
|
|
235
|
-
);
|
|
236
|
-
const controller = (0, import_react6.useMemo)(
|
|
263
|
+
const collection = (0, import_react7.useMemo)(() => store.collection(collectionName), [store, collectionName]);
|
|
264
|
+
const getController = useController(
|
|
237
265
|
() => (0, import_store3.createRichTextController)({
|
|
238
266
|
collection,
|
|
239
267
|
collectionName,
|
|
@@ -244,25 +272,29 @@ function useRichText(collectionName, recordId, fieldName, options) {
|
|
|
244
272
|
useDocChannel: options?.useDocChannel,
|
|
245
273
|
user: options?.user
|
|
246
274
|
}),
|
|
275
|
+
(controller) => controller.destroy(),
|
|
247
276
|
[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
|
|
248
277
|
);
|
|
249
|
-
(0,
|
|
250
|
-
|
|
251
|
-
}, [
|
|
252
|
-
(0,
|
|
253
|
-
|
|
254
|
-
(
|
|
255
|
-
() =>
|
|
256
|
-
() => controller.getSnapshot()
|
|
278
|
+
(0, import_react7.useEffect)(() => {
|
|
279
|
+
getController().setUser(options?.user);
|
|
280
|
+
}, [getController, options?.user]);
|
|
281
|
+
const snapshot = (0, import_react7.useSyncExternalStore)(
|
|
282
|
+
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
283
|
+
() => getController().getSnapshot(),
|
|
284
|
+
() => getController().getSnapshot()
|
|
257
285
|
);
|
|
258
|
-
const undo = (0,
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
286
|
+
const undo = (0, import_react7.useCallback)(() => {
|
|
287
|
+
getController().undo();
|
|
288
|
+
}, [getController]);
|
|
289
|
+
const redo = (0, import_react7.useCallback)(() => {
|
|
290
|
+
getController().redo();
|
|
291
|
+
}, [getController]);
|
|
292
|
+
const setCursor = (0, import_react7.useCallback)(
|
|
293
|
+
(anchor, head) => getController().setCursor(anchor, head),
|
|
294
|
+
[getController]
|
|
263
295
|
);
|
|
264
|
-
const clearCursor = (0,
|
|
265
|
-
return buildResult(
|
|
296
|
+
const clearCursor = (0, import_react7.useCallback)(() => getController().clearCursor(), [getController]);
|
|
297
|
+
return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
|
|
266
298
|
}
|
|
267
299
|
function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
|
|
268
300
|
return {
|
|
@@ -281,13 +313,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
|
|
|
281
313
|
}
|
|
282
314
|
|
|
283
315
|
// src/hooks/use-presence.ts
|
|
284
|
-
var
|
|
316
|
+
var import_react8 = require("react");
|
|
285
317
|
function usePresence(user) {
|
|
286
318
|
const { syncEngine } = useKoraContext();
|
|
287
319
|
const name = user?.name ?? null;
|
|
288
320
|
const color = user?.color ?? null;
|
|
289
321
|
const avatar = user?.avatar ?? null;
|
|
290
|
-
(0,
|
|
322
|
+
(0, import_react8.useEffect)(() => {
|
|
291
323
|
if (!syncEngine || !name || !color) return;
|
|
292
324
|
const awareness = syncEngine.getAwarenessManager();
|
|
293
325
|
awareness.setLocalState({
|
|
@@ -301,12 +333,12 @@ function usePresence(user) {
|
|
|
301
333
|
|
|
302
334
|
// src/hooks/use-collaborators.ts
|
|
303
335
|
var import_sync2 = require("@korajs/sync");
|
|
304
|
-
var
|
|
336
|
+
var import_react9 = require("react");
|
|
305
337
|
var EMPTY_ARRAY2 = [];
|
|
306
338
|
function useCollaborators() {
|
|
307
339
|
const { syncEngine } = useKoraContext();
|
|
308
|
-
const snapshotRef = (0,
|
|
309
|
-
const subscribe = (0,
|
|
340
|
+
const snapshotRef = (0, import_react9.useRef)(EMPTY_ARRAY2);
|
|
341
|
+
const subscribe = (0, import_react9.useCallback)(
|
|
310
342
|
(onStoreChange) => {
|
|
311
343
|
if (!syncEngine) {
|
|
312
344
|
snapshotRef.current = EMPTY_ARRAY2;
|
|
@@ -321,13 +353,13 @@ function useCollaborators() {
|
|
|
321
353
|
},
|
|
322
354
|
[syncEngine]
|
|
323
355
|
);
|
|
324
|
-
const getSnapshot = (0,
|
|
325
|
-
(0,
|
|
356
|
+
const getSnapshot = (0, import_react9.useCallback)(() => snapshotRef.current, []);
|
|
357
|
+
(0, import_react9.useEffect)(() => {
|
|
326
358
|
if (!syncEngine) {
|
|
327
359
|
snapshotRef.current = EMPTY_ARRAY2;
|
|
328
360
|
}
|
|
329
361
|
}, [syncEngine]);
|
|
330
|
-
return (0,
|
|
362
|
+
return (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot);
|
|
331
363
|
}
|
|
332
364
|
// Annotate the CommonJS export names for ESM import in node:
|
|
333
365
|
0 && (module.exports = {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/context/kora-context.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["// @korajs/react — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tKoraAppLike,\n\tKoraContextValue,\n\tKoraProviderProps,\n\tUseQueryOptions,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseRichTextResult,\n} from './types'\n\n// === Context ===\nexport { KoraProvider } from './context/kora-context'\n\n// === Hooks ===\nexport { useApp } from './hooks/use-app'\nexport { useQuery } from './hooks/use-query'\nexport { useMutation } from './hooks/use-mutation'\nexport { useSyncStatus } from './hooks/use-sync-status'\nexport { useCollection } from './hooks/use-collection'\nexport { useRichText } from './hooks/use-rich-text'\nexport type { UseRichTextOptions } from './hooks/use-rich-text'\nexport { usePresence } from './hooks/use-presence'\nexport { useCollaborators } from './hooks/use-collaborators'\n","import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current!,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires KoraProvider to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * React hook for performing mutations against the local Kora store.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst controller = useMemo(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t[],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => controller.reset(),\n\t}\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\tconst controller = useMemo(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst collection = useMemo(\n\t\t() => store.collection(collectionName),\n\t\t[store, collectionName],\n\t)\n\n\tconst controller = useMemo(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tcontroller.setUser(options?.user)\n\t}, [controller, options?.user])\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => controller.undo(), [controller])\n\tconst redo = useCallback(() => controller.redo(), [controller])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\t[controller],\n\t)\n\tconst clearCursor = useCallback(() => controller.clearCursor(), [controller])\n\n\treturn buildResult(controller, snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["import_store","import_react","import_react","import_react","import_react","import_store","import_react","import_react","import_sync","import_react","EMPTY_ARRAY"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/context/kora-context.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["// @korajs/react — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tKoraAppLike,\n\tKoraContextValue,\n\tKoraProviderProps,\n\tUseQueryOptions,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseRichTextResult,\n} from './types'\n\n// === Context ===\nexport { KoraProvider } from './context/kora-context'\n\n// === Hooks ===\nexport { useApp } from './hooks/use-app'\nexport { useQuery } from './hooks/use-query'\nexport { useMutation } from './hooks/use-mutation'\nexport { useSyncStatus } from './hooks/use-sync-status'\nexport { useCollection } from './hooks/use-collection'\nexport { useRichText } from './hooks/use-rich-text'\nexport type { UseRichTextOptions } from './hooks/use-rich-text'\nexport { usePresence } from './hooks/use-presence'\nexport { useCollaborators } from './hooks/use-collaborators'\n","import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current!,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires KoraProvider to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["import_store","import_react","import_react","import_react","import_react","import_react","import_store","import_react","import_react","import_sync","import_react","EMPTY_ARRAY"]}
|
package/dist/index.js
CHANGED
|
@@ -132,74 +132,102 @@ function useQuery(query, options) {
|
|
|
132
132
|
|
|
133
133
|
// src/hooks/use-mutation.ts
|
|
134
134
|
import { createMutationController } from "@korajs/core/bindings";
|
|
135
|
-
import {
|
|
135
|
+
import { useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
136
|
+
|
|
137
|
+
// src/hooks/use-controller.ts
|
|
138
|
+
import { useEffect as useEffect3, useReducer, useRef as useRef3 } from "react";
|
|
139
|
+
function useController(create, destroy, deps) {
|
|
140
|
+
const controllerRef = useRef3(null);
|
|
141
|
+
const createRef = useRef3(create);
|
|
142
|
+
createRef.current = create;
|
|
143
|
+
const [, forceRender] = useReducer((count) => count + 1, 0);
|
|
144
|
+
const getController = useRef3(() => {
|
|
145
|
+
if (controllerRef.current === null) {
|
|
146
|
+
controllerRef.current = createRef.current();
|
|
147
|
+
}
|
|
148
|
+
return controllerRef.current;
|
|
149
|
+
}).current;
|
|
150
|
+
useEffect3(() => {
|
|
151
|
+
if (controllerRef.current === null) {
|
|
152
|
+
controllerRef.current = createRef.current();
|
|
153
|
+
forceRender();
|
|
154
|
+
}
|
|
155
|
+
return () => {
|
|
156
|
+
const controller = controllerRef.current;
|
|
157
|
+
controllerRef.current = null;
|
|
158
|
+
if (controller !== null) {
|
|
159
|
+
destroy(controller);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}, deps);
|
|
163
|
+
return getController;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/hooks/use-mutation.ts
|
|
136
167
|
function useMutation(mutationFn, options) {
|
|
137
|
-
const fnRef =
|
|
168
|
+
const fnRef = useRef4(mutationFn);
|
|
138
169
|
fnRef.current = mutationFn;
|
|
139
|
-
const optionsRef =
|
|
170
|
+
const optionsRef = useRef4(options);
|
|
140
171
|
optionsRef.current = options;
|
|
141
|
-
const
|
|
172
|
+
const getController = useController(
|
|
142
173
|
() => createMutationController({
|
|
143
174
|
mutationFn: (...args) => fnRef.current(...args),
|
|
144
175
|
resolveOptions: () => optionsRef.current
|
|
145
176
|
}),
|
|
177
|
+
(controller) => controller.destroy(),
|
|
146
178
|
[]
|
|
147
179
|
);
|
|
148
|
-
useEffect3(() => () => controller.destroy(), [controller]);
|
|
149
180
|
const state = useSyncExternalStore2(
|
|
150
|
-
(onStoreChange) =>
|
|
151
|
-
() =>
|
|
152
|
-
() =>
|
|
181
|
+
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
182
|
+
() => getController().getSnapshot(),
|
|
183
|
+
() => getController().getSnapshot()
|
|
153
184
|
);
|
|
154
185
|
return {
|
|
155
|
-
mutate: (...args) =>
|
|
156
|
-
mutateAsync: (...args) =>
|
|
186
|
+
mutate: (...args) => getController().mutate(...args),
|
|
187
|
+
mutateAsync: (...args) => getController().mutateAsync(...args),
|
|
157
188
|
isLoading: state.isLoading,
|
|
158
189
|
error: state.error,
|
|
159
|
-
reset: () =>
|
|
190
|
+
reset: () => getController().reset()
|
|
160
191
|
};
|
|
161
192
|
}
|
|
162
193
|
|
|
163
194
|
// src/hooks/use-sync-status.ts
|
|
164
195
|
import { createSyncStatusController } from "@korajs/sync";
|
|
165
|
-
import {
|
|
196
|
+
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
166
197
|
function useSyncStatus() {
|
|
167
198
|
const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
|
|
168
|
-
const
|
|
199
|
+
const getController = useController(
|
|
169
200
|
() => createSyncStatusController({
|
|
170
201
|
syncEngine,
|
|
171
202
|
subscribeSyncStatus,
|
|
172
203
|
events: subscribeSyncStatus ? null : events
|
|
173
204
|
}),
|
|
205
|
+
(controller) => controller.destroy(),
|
|
174
206
|
[syncEngine, subscribeSyncStatus, events]
|
|
175
207
|
);
|
|
176
|
-
useEffect4(() => () => controller.destroy(), [controller]);
|
|
177
208
|
return useSyncExternalStore3(
|
|
178
|
-
(onStoreChange) =>
|
|
179
|
-
() =>
|
|
180
|
-
() =>
|
|
209
|
+
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
210
|
+
() => getController().getSnapshot(),
|
|
211
|
+
() => getController().getSnapshot()
|
|
181
212
|
);
|
|
182
213
|
}
|
|
183
214
|
|
|
184
215
|
// src/hooks/use-collection.ts
|
|
185
|
-
import { useMemo as
|
|
216
|
+
import { useMemo as useMemo2 } from "react";
|
|
186
217
|
function useCollection(name) {
|
|
187
218
|
const { store } = useKoraContext();
|
|
188
|
-
return
|
|
219
|
+
return useMemo2(() => {
|
|
189
220
|
return store.collection(name);
|
|
190
221
|
}, [store, name]);
|
|
191
222
|
}
|
|
192
223
|
|
|
193
224
|
// src/hooks/use-rich-text.ts
|
|
194
225
|
import { asRichTextSyncEngine, createRichTextController } from "@korajs/store";
|
|
195
|
-
import { useCallback, useEffect as
|
|
226
|
+
import { useCallback, useEffect as useEffect4, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
196
227
|
function useRichText(collectionName, recordId, fieldName, options) {
|
|
197
228
|
const { store, syncEngine } = useKoraContext();
|
|
198
|
-
const collection =
|
|
199
|
-
|
|
200
|
-
[store, collectionName]
|
|
201
|
-
);
|
|
202
|
-
const controller = useMemo5(
|
|
229
|
+
const collection = useMemo3(() => store.collection(collectionName), [store, collectionName]);
|
|
230
|
+
const getController = useController(
|
|
203
231
|
() => createRichTextController({
|
|
204
232
|
collection,
|
|
205
233
|
collectionName,
|
|
@@ -210,25 +238,29 @@ function useRichText(collectionName, recordId, fieldName, options) {
|
|
|
210
238
|
useDocChannel: options?.useDocChannel,
|
|
211
239
|
user: options?.user
|
|
212
240
|
}),
|
|
241
|
+
(controller) => controller.destroy(),
|
|
213
242
|
[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
|
|
214
243
|
);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}, [
|
|
218
|
-
useEffect5(() => () => controller.destroy(), [controller]);
|
|
244
|
+
useEffect4(() => {
|
|
245
|
+
getController().setUser(options?.user);
|
|
246
|
+
}, [getController, options?.user]);
|
|
219
247
|
const snapshot = useSyncExternalStore4(
|
|
220
|
-
(onStoreChange) =>
|
|
221
|
-
() =>
|
|
222
|
-
() =>
|
|
248
|
+
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
249
|
+
() => getController().getSnapshot(),
|
|
250
|
+
() => getController().getSnapshot()
|
|
223
251
|
);
|
|
224
|
-
const undo = useCallback(() =>
|
|
225
|
-
|
|
252
|
+
const undo = useCallback(() => {
|
|
253
|
+
getController().undo();
|
|
254
|
+
}, [getController]);
|
|
255
|
+
const redo = useCallback(() => {
|
|
256
|
+
getController().redo();
|
|
257
|
+
}, [getController]);
|
|
226
258
|
const setCursor = useCallback(
|
|
227
|
-
(anchor, head) =>
|
|
228
|
-
[
|
|
259
|
+
(anchor, head) => getController().setCursor(anchor, head),
|
|
260
|
+
[getController]
|
|
229
261
|
);
|
|
230
|
-
const clearCursor = useCallback(() =>
|
|
231
|
-
return buildResult(
|
|
262
|
+
const clearCursor = useCallback(() => getController().clearCursor(), [getController]);
|
|
263
|
+
return buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor);
|
|
232
264
|
}
|
|
233
265
|
function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
|
|
234
266
|
return {
|
|
@@ -247,13 +279,13 @@ function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
|
|
|
247
279
|
}
|
|
248
280
|
|
|
249
281
|
// src/hooks/use-presence.ts
|
|
250
|
-
import { useEffect as
|
|
282
|
+
import { useEffect as useEffect5 } from "react";
|
|
251
283
|
function usePresence(user) {
|
|
252
284
|
const { syncEngine } = useKoraContext();
|
|
253
285
|
const name = user?.name ?? null;
|
|
254
286
|
const color = user?.color ?? null;
|
|
255
287
|
const avatar = user?.avatar ?? null;
|
|
256
|
-
|
|
288
|
+
useEffect5(() => {
|
|
257
289
|
if (!syncEngine || !name || !color) return;
|
|
258
290
|
const awareness = syncEngine.getAwarenessManager();
|
|
259
291
|
awareness.setLocalState({
|
|
@@ -267,11 +299,11 @@ function usePresence(user) {
|
|
|
267
299
|
|
|
268
300
|
// src/hooks/use-collaborators.ts
|
|
269
301
|
import { subscribeRemoteAwarenessStates } from "@korajs/sync";
|
|
270
|
-
import { useCallback as useCallback2, useEffect as
|
|
302
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
271
303
|
var EMPTY_ARRAY2 = [];
|
|
272
304
|
function useCollaborators() {
|
|
273
305
|
const { syncEngine } = useKoraContext();
|
|
274
|
-
const snapshotRef =
|
|
306
|
+
const snapshotRef = useRef5(EMPTY_ARRAY2);
|
|
275
307
|
const subscribe = useCallback2(
|
|
276
308
|
(onStoreChange) => {
|
|
277
309
|
if (!syncEngine) {
|
|
@@ -288,7 +320,7 @@ function useCollaborators() {
|
|
|
288
320
|
[syncEngine]
|
|
289
321
|
);
|
|
290
322
|
const getSnapshot = useCallback2(() => snapshotRef.current, []);
|
|
291
|
-
|
|
323
|
+
useEffect6(() => {
|
|
292
324
|
if (!syncEngine) {
|
|
293
325
|
snapshotRef.current = EMPTY_ARRAY2;
|
|
294
326
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/kora-context.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current!,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires KoraProvider to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * React hook for performing mutations against the local Kora store.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst controller = useMemo(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t[],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => controller.reset(),\n\t}\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\tconst controller = useMemo(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst collection = useMemo(\n\t\t() => store.collection(collectionName),\n\t\t[store, collectionName],\n\t)\n\n\tconst controller = useMemo(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tcontroller.setUser(options?.user)\n\t}, [controller, options?.user])\n\n\tuseEffect(() => () => controller.destroy(), [controller])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => controller.subscribe(onStoreChange),\n\t\t() => controller.getSnapshot(),\n\t\t() => controller.getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => controller.undo(), [controller])\n\tconst redo = useCallback(() => controller.redo(), [controller])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\t[controller],\n\t)\n\tconst clearCursor = useCallback(() => controller.clearCursor(), [controller])\n\n\treturn buildResult(controller, snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useRef","useState","useEffect","useEffect","useMemo","useRef","useSyncExternalStore","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useMemo","useMemo","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
|
|
1
|
+
{"version":3,"sources":["../src/context/kora-context.ts","../src/hooks/use-app.ts","../src/hooks/use-query.ts","../src/hooks/use-mutation.ts","../src/hooks/use-controller.ts","../src/hooks/use-sync-status.ts","../src/hooks/use-collection.ts","../src/hooks/use-rich-text.ts","../src/hooks/use-presence.ts","../src/hooks/use-collaborators.ts"],"sourcesContent":["import type { Store } from '@korajs/store'\nimport { QueryStoreCache } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport { createContext, createElement, useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { KoraContextValue, KoraProviderProps } from '../types'\n\nconst KoraContext = createContext<KoraContextValue | null>(null)\n\n/**\n * Provides Kora store and optional sync engine to all child components.\n * Must wrap any component that uses Kora hooks (useQuery, useMutation, etc.).\n */\nfunction KoraProvider({\n\tapp,\n\tstore,\n\tsyncEngine,\n\tfallback,\n\tchildren,\n}: KoraProviderProps): ReactNode {\n\tconst [resolvedStore, setResolvedStore] = useState<Store | null>(store ?? null)\n\tconst [resolvedSync, setResolvedSync] = useState<SyncEngine | null>(syncEngine ?? null)\n\tconst [ready, setReady] = useState(!app)\n\tconst [initError, setInitError] = useState<Error | null>(null)\n\tconst fallbackQueryStoreCache = useRef<QueryStoreCache | null>(null)\n\n\tif (!fallbackQueryStoreCache.current) {\n\t\tfallbackQueryStoreCache.current = new QueryStoreCache()\n\t}\n\n\tuseEffect(() => {\n\t\tif (!app) return\n\t\tlet cancelled = false\n\t\tapp.ready\n\t\t\t.then(() => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tsetResolvedStore(app.getStore())\n\t\t\t\tsetResolvedSync(app.getSyncEngine())\n\t\t\t\tsetReady(true)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tconsole.error('[Kora] Initialization failed:', err)\n\t\t\t\tsetInitError(err)\n\t\t\t})\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [app])\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (!app) {\n\t\t\t\tfallbackQueryStoreCache.current?.clear()\n\t\t\t}\n\t\t}\n\t}, [app])\n\n\tconst contextValue = useMemo<KoraContextValue | null>(() => {\n\t\tif (!resolvedStore) {\n\t\t\treturn null\n\t\t}\n\t\treturn {\n\t\t\tstore: resolvedStore,\n\t\t\tsyncEngine: resolvedSync,\n\t\t\tapp: app ?? null,\n\t\t\tevents: app?.events ?? null,\n\t\t\tsubscribeSyncStatus: app?.sync?.subscribeStatus ?? null,\n\t\t\tqueryStoreCache:\n\t\t\t\tapp && typeof app.getQueryStoreCache === 'function'\n\t\t\t\t\t? app.getQueryStoreCache()\n\t\t\t\t\t: fallbackQueryStoreCache.current!,\n\t\t}\n\t}, [resolvedStore, resolvedSync, app])\n\n\tif (initError) {\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{ style: { color: 'red', padding: '1rem', fontFamily: 'monospace' } },\n\t\t\tcreateElement('strong', null, 'Kora initialization error: '),\n\t\t\tinitError.message,\n\t\t)\n\t}\n\n\tif (!ready) {\n\t\treturn (fallback ?? null) as ReactNode\n\t}\n\n\tif (!contextValue) {\n\t\tthrow new Error(\n\t\t\t'KoraProvider requires either an \"app\" or \"store\" prop. ' +\n\t\t\t\t'Pass a KoraApp from createApp() or a Store instance.',\n\t\t)\n\t}\n\n\treturn createElement(KoraContext.Provider, { value: contextValue }, children)\n}\n\nfunction useKoraContext(): KoraContextValue {\n\tconst context = useContext(KoraContext)\n\tif (context === null) {\n\t\tthrow new Error(\n\t\t\t'useKoraContext must be used within a <KoraProvider>. ' +\n\t\t\t\t'Wrap your component tree with <KoraProvider store={store}>.',\n\t\t)\n\t}\n\treturn context\n}\n\nexport { KoraProvider, useKoraContext }\n","import { useKoraContext } from '../context/kora-context'\nimport type { KoraAppLike } from '../types'\n\n/**\n * React hook that returns the Kora app instance from context.\n *\n * Use the generic parameter to cast to your typed app for full type inference:\n *\n * ```typescript\n * // In your app setup:\n * export const app = createApp({ schema: mySchema })\n * export type App = typeof app\n *\n * // In components:\n * const app = useApp<App>()\n * app.todos.insert({ title: 'Hello' }) // fully typed\n * const todos = useQuery(app.todos.where({ completed: false }))\n * ```\n *\n * Requires `KoraProvider` to be initialized with the `app` prop.\n * Throws if used outside of `KoraProvider` or without an `app` prop.\n *\n * @returns The KoraApp instance, typed as `T`\n */\nexport function useApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = useKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'useApp() requires KoraProvider to be initialized with an \"app\" prop. ' +\n\t\t\t\t'Pass your createApp() result to <KoraProvider app={app}>.',\n\t\t)\n\t}\n\treturn app as T\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\nconst noopSubscribe = (_onStoreChange: () => void): (() => void) => {\n\treturn () => {}\n}\n\n/**\n * React hook for reactive queries against the local Kora store.\n */\nexport function useQuery<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): readonly T[] {\n\tconst { queryStoreCache } = useKoraContext()\n\tconst enabled = options?.enabled !== false\n\tconst descriptorKey = JSON.stringify(query.getDescriptor())\n\tconst queryRef = useRef(query)\n\tqueryRef.current = query\n\n\tconst [queryStore, setQueryStore] = useState<import('@korajs/store').QueryStore<T> | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetQueryStore(null)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentQuery = queryRef.current\n\t\tassertQueryReady(currentQuery)\n\t\tconst store = queryStoreCache.getOrCreate(currentQuery)\n\t\tsetQueryStore(store)\n\n\t\treturn () => {\n\t\t\tqueryStoreCache.release(currentQuery as QueryBuilder<unknown>)\n\t\t\tsetQueryStore(null)\n\t\t}\n\t}, [descriptorKey, enabled, queryStoreCache])\n\n\tconst disabledGetSnapshot = (): readonly T[] => EMPTY_ARRAY as readonly T[]\n\n\treturn useSyncExternalStore(\n\t\tqueryStore ? queryStore.subscribe : noopSubscribe,\n\t\tqueryStore ? queryStore.getSnapshot : disabledGetSnapshot,\n\t)\n}\n","import { createMutationController } from '@korajs/core/bindings'\nimport { useRef, useSyncExternalStore } from 'react'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\nimport { useController } from './use-controller'\n\n/**\n * React hook for performing mutations against the local Kora store.\n */\nexport function useMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst fnRef = useRef(mutationFn)\n\tfnRef.current = mutationFn\n\n\tconst optionsRef = useRef(options)\n\toptionsRef.current = options\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateMutationController<TData, TArgs, TContext>({\n\t\t\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\t\t\tresolveOptions: () => optionsRef.current,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[],\n\t)\n\n\tconst state = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\treturn {\n\t\tmutate: (...args: TArgs) => getController().mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => getController().mutateAsync(...args),\n\t\tisLoading: state.isLoading,\n\t\terror: state.error,\n\t\treset: () => getController().reset(),\n\t}\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\n/**\n * Manages the lifecycle of an external controller in a StrictMode-safe way.\n *\n * React 18+ StrictMode mounts, unmounts, and remounts components in development.\n * The previous pattern (create in `useMemo`, destroy in effect cleanup) permanently\n * destroyed the memoized controller on the simulated unmount, leaving every\n * subsequent interaction against a disposed controller.\n *\n * This hook instead keeps the controller in a ref and recreates it lazily\n * whenever it has been destroyed, so the effect cleanup / re-run cycle is safe.\n *\n * Returns a getter so subscribe/getSnapshot closures always reach a live controller.\n */\nexport function useController<C>(\n\tcreate: () => C,\n\tdestroy: (controller: C) => void,\n\tdeps: readonly unknown[],\n): () => C {\n\tconst controllerRef = useRef<C | null>(null)\n\tconst createRef = useRef(create)\n\tcreateRef.current = create\n\n\tconst [, forceRender] = useReducer((count: number) => count + 1, 0)\n\n\tconst getController = useRef((): C => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t}\n\t\treturn controllerRef.current\n\t}).current\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: deps are the caller's create() inputs\n\tuseEffect(() => {\n\t\tif (controllerRef.current === null) {\n\t\t\tcontrollerRef.current = createRef.current()\n\t\t\t// A destroyed controller was recreated (StrictMode remount or deps\n\t\t\t// change): re-render so useSyncExternalStore rebinds to the new one.\n\t\t\tforceRender()\n\t\t}\n\t\treturn () => {\n\t\t\tconst controller = controllerRef.current\n\t\t\tcontrollerRef.current = null\n\t\t\tif (controller !== null) {\n\t\t\t\tdestroy(controller)\n\t\t\t}\n\t\t}\n\t}, deps)\n\n\treturn getController\n}\n","import type { SyncStatusInfo } from '@korajs/sync'\nimport { createSyncStatusController } from '@korajs/sync'\nimport { useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport { useController } from './use-controller'\n\n/**\n * React hook for monitoring the sync engine's connection status.\n */\nexport function useSyncStatus(): SyncStatusInfo {\n\tconst { syncEngine, subscribeSyncStatus, events } = useKoraContext()\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateSyncStatusController({\n\t\t\t\tsyncEngine,\n\t\t\t\tsubscribeSyncStatus,\n\t\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[syncEngine, subscribeSyncStatus, events],\n\t)\n\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n}\n","import type { CollectionAccessor } from '@korajs/store'\nimport { useMemo } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * React hook that returns a CollectionAccessor for the given collection name.\n * Convenience hook for accessing a collection without going through the store directly.\n *\n * @param name - The collection name (must match a collection in the schema)\n * @returns CollectionAccessor with insert, findById, update, delete, and where methods\n *\n * @example\n * ```typescript\n * const todos = useCollection('todos')\n * await todos.insert({ title: 'New todo' })\n * ```\n */\nexport function useCollection(name: string): CollectionAccessor {\n\tconst { store } = useKoraContext()\n\n\treturn useMemo(() => {\n\t\treturn store.collection(name)\n\t}, [store, name])\n}\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { RichTextControllerSnapshot } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { useCallback, useEffect, useMemo, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\nimport type { UseRichTextResult } from '../types'\nimport { useController } from './use-controller'\n\nexport interface UseRichTextOptions {\n\tuser?: AwarenessUser\n\tuseDocChannel?: boolean\n}\n\n/**\n * Binds a richtext field to a shared Yjs document for editor integration.\n */\nexport function useRichText(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult {\n\tconst { store, syncEngine } = useKoraContext()\n\tconst collection = useMemo(() => store.collection(collectionName), [store, collectionName])\n\n\tconst getController = useController(\n\t\t() =>\n\t\t\tcreateRichTextController({\n\t\t\t\tcollection,\n\t\t\t\tcollectionName,\n\t\t\t\trecordId,\n\t\t\t\tfieldName,\n\t\t\t\tstore,\n\t\t\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\t\t\tuseDocChannel: options?.useDocChannel,\n\t\t\t\tuser: options?.user,\n\t\t\t}),\n\t\t(controller) => controller.destroy(),\n\t\t[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine],\n\t)\n\n\tuseEffect(() => {\n\t\tgetController().setUser(options?.user)\n\t}, [getController, options?.user])\n\n\tconst snapshot = useSyncExternalStore(\n\t\t(onStoreChange) => getController().subscribe(onStoreChange),\n\t\t() => getController().getSnapshot(),\n\t\t() => getController().getSnapshot(),\n\t)\n\n\tconst undo = useCallback(() => {\n\t\tgetController().undo()\n\t}, [getController])\n\tconst redo = useCallback(() => {\n\t\tgetController().redo()\n\t}, [getController])\n\tconst setCursor = useCallback(\n\t\t(anchor: number, head: number) => getController().setCursor(anchor, head),\n\t\t[getController],\n\t)\n\tconst clearCursor = useCallback(() => getController().clearCursor(), [getController])\n\n\treturn buildResult(getController(), snapshot, undo, redo, setCursor, clearCursor)\n}\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n\tsnapshot: RichTextControllerSnapshot,\n\tundo: () => void,\n\tredo: () => void,\n\tsetCursor: (anchor: number, head: number) => void,\n\tclearCursor: () => void,\n): UseRichTextResult {\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo,\n\t\tredo,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor,\n\t\tclearCursor,\n\t}\n}\n","import { useEffect } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\n/**\n * Sets the local user's collaborative presence state.\n *\n * Automatically cleans up presence on unmount.\n */\nexport function usePresence(user: { name: string; color: string; avatar?: string } | null): void {\n\tconst { syncEngine } = useKoraContext()\n\tconst name = user?.name ?? null\n\tconst color = user?.color ?? null\n\tconst avatar = user?.avatar ?? null\n\n\tuseEffect(() => {\n\t\tif (!syncEngine || !name || !color) return\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawareness.setLocalState({\n\t\t\tuser: { name, color, avatar: avatar ?? undefined },\n\t\t})\n\n\t\treturn () => {\n\t\t\tawareness.setLocalState(null)\n\t\t}\n\t}, [syncEngine, name, color, avatar])\n}\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useKoraContext } from '../context/kora-context'\n\nconst EMPTY_ARRAY: AwarenessState[] = []\n\n/**\n * Returns all currently connected collaborators' awareness states.\n *\n * Excludes the local user — only returns remote peers.\n */\nexport function useCollaborators(): AwarenessState[] {\n\tconst { syncEngine } = useKoraContext()\n\n\tconst snapshotRef = useRef<AwarenessState[]>(EMPTY_ARRAY)\n\n\tconst subscribe = useCallback(\n\t\t(onStoreChange: () => void): (() => void) => {\n\t\t\tif (!syncEngine) {\n\t\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t\t\treturn () => {}\n\t\t\t}\n\n\t\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\t\treturn subscribeRemoteAwarenessStates(awareness, (states) => {\n\t\t\t\tsnapshotRef.current = states\n\t\t\t\tonStoreChange()\n\t\t\t})\n\t\t},\n\t\t[syncEngine],\n\t)\n\n\tconst getSnapshot = useCallback((): AwarenessState[] => snapshotRef.current, [])\n\n\tuseEffect(() => {\n\t\tif (!syncEngine) {\n\t\t\tsnapshotRef.current = EMPTY_ARRAY\n\t\t}\n\t}, [syncEngine])\n\n\treturn useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"mappings":";AACA,SAAS,uBAAuB;AAEhC,SAAS,eAAe,eAAe,YAAY,WAAW,SAAS,QAAQ,gBAAgB;AAI/F,IAAM,cAAc,cAAuC,IAAI;AAM/D,SAAS,aAAa;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAiC;AAChC,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAuB,SAAS,IAAI;AAC9E,QAAM,CAAC,cAAc,eAAe,IAAI,SAA4B,cAAc,IAAI;AACtF,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC,GAAG;AACvC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAuB,IAAI;AAC7D,QAAM,0BAA0B,OAA+B,IAAI;AAEnE,MAAI,CAAC,wBAAwB,SAAS;AACrC,4BAAwB,UAAU,IAAI,gBAAgB;AAAA,EACvD;AAEA,YAAU,MAAM;AACf,QAAI,CAAC,IAAK;AACV,QAAI,YAAY;AAChB,QAAI,MACF,KAAK,MAAM;AACX,UAAI,UAAW;AACf,uBAAiB,IAAI,SAAS,CAAC;AAC/B,sBAAgB,IAAI,cAAc,CAAC;AACnC,eAAS,IAAI;AAAA,IACd,CAAC,EACA,MAAM,CAAC,UAAmB;AAC1B,UAAI,UAAW;AACf,YAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACpE,cAAQ,MAAM,iCAAiC,GAAG;AAClD,mBAAa,GAAG;AAAA,IACjB,CAAC;AACF,WAAO,MAAM;AACZ,kBAAY;AAAA,IACb;AAAA,EACD,GAAG,CAAC,GAAG,CAAC;AAER,YAAU,MAAM;AACf,WAAO,MAAM;AACZ,UAAI,CAAC,KAAK;AACT,gCAAwB,SAAS,MAAM;AAAA,MACxC;AAAA,IACD;AAAA,EACD,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,eAAe,QAAiC,MAAM;AAC3D,QAAI,CAAC,eAAe;AACnB,aAAO;AAAA,IACR;AACA,WAAO;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,KAAK,OAAO;AAAA,MACZ,QAAQ,KAAK,UAAU;AAAA,MACvB,qBAAqB,KAAK,MAAM,mBAAmB;AAAA,MACnD,iBACC,OAAO,OAAO,IAAI,uBAAuB,aACtC,IAAI,mBAAmB,IACvB,wBAAwB;AAAA,IAC7B;AAAA,EACD,GAAG,CAAC,eAAe,cAAc,GAAG,CAAC;AAErC,MAAI,WAAW;AACd,WAAO;AAAA,MACN;AAAA,MACA,EAAE,OAAO,EAAE,OAAO,OAAO,SAAS,QAAQ,YAAY,YAAY,EAAE;AAAA,MACpE,cAAc,UAAU,MAAM,6BAA6B;AAAA,MAC3D,UAAU;AAAA,IACX;AAAA,EACD;AAEA,MAAI,CAAC,OAAO;AACX,WAAQ,YAAY;AAAA,EACrB;AAEA,MAAI,CAAC,cAAc;AAClB,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AAEA,SAAO,cAAc,YAAY,UAAU,EAAE,OAAO,aAAa,GAAG,QAAQ;AAC7E;AAEA,SAAS,iBAAmC;AAC3C,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,YAAY,MAAM;AACrB,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AACA,SAAO;AACR;;;ACpFO,SAAS,SAAiD;AAChE,QAAM,EAAE,IAAI,IAAI,eAAe;AAC/B,MAAI,CAAC,KAAK;AACT,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AACA,SAAO;AACR;;;AChCA,SAAS,wBAAwB;AACjC,SAAS,aAAAA,YAAW,UAAAC,SAAQ,YAAAC,WAAU,4BAA4B;AAIlE,IAAM,cAAkC,OAAO,OAAO,CAAC,CAAC;AAExD,IAAM,gBAAgB,CAAC,mBAA6C;AACnE,SAAO,MAAM;AAAA,EAAC;AACf;AAKO,SAAS,SACf,OACA,SACe;AACf,QAAM,EAAE,gBAAgB,IAAI,eAAe;AAC3C,QAAM,UAAU,SAAS,YAAY;AACrC,QAAM,gBAAgB,KAAK,UAAU,MAAM,cAAc,CAAC;AAC1D,QAAM,WAAWC,QAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,QAAM,CAAC,YAAY,aAAa,IAAIC,UAAuD,IAAI;AAE/F,EAAAC,WAAU,MAAM;AACf,QAAI,CAAC,SAAS;AACb,oBAAc,IAAI;AAClB;AAAA,IACD;AAEA,UAAM,eAAe,SAAS;AAC9B,qBAAiB,YAAY;AAC7B,UAAM,QAAQ,gBAAgB,YAAY,YAAY;AACtD,kBAAc,KAAK;AAEnB,WAAO,MAAM;AACZ,sBAAgB,QAAQ,YAAqC;AAC7D,oBAAc,IAAI;AAAA,IACnB;AAAA,EACD,GAAG,CAAC,eAAe,SAAS,eAAe,CAAC;AAE5C,QAAM,sBAAsB,MAAoB;AAEhD,SAAO;AAAA,IACN,aAAa,WAAW,YAAY;AAAA,IACpC,aAAa,WAAW,cAAc;AAAA,EACvC;AACD;;;AClDA,SAAS,gCAAgC;AACzC,SAAS,UAAAC,SAAQ,wBAAAC,6BAA4B;;;ACD7C,SAAS,aAAAC,YAAW,YAAY,UAAAC,eAAc;AAevC,SAAS,cACf,QACA,SACA,MACU;AACV,QAAM,gBAAgBA,QAAiB,IAAI;AAC3C,QAAM,YAAYA,QAAO,MAAM;AAC/B,YAAU,UAAU;AAEpB,QAAM,CAAC,EAAE,WAAW,IAAI,WAAW,CAAC,UAAkB,QAAQ,GAAG,CAAC;AAElE,QAAM,gBAAgBA,QAAO,MAAS;AACrC,QAAI,cAAc,YAAY,MAAM;AACnC,oBAAc,UAAU,UAAU,QAAQ;AAAA,IAC3C;AACA,WAAO,cAAc;AAAA,EACtB,CAAC,EAAE;AAGH,EAAAD,WAAU,MAAM;AACf,QAAI,cAAc,YAAY,MAAM;AACnC,oBAAc,UAAU,UAAU,QAAQ;AAG1C,kBAAY;AAAA,IACb;AACA,WAAO,MAAM;AACZ,YAAM,aAAa,cAAc;AACjC,oBAAc,UAAU;AACxB,UAAI,eAAe,MAAM;AACxB,gBAAQ,UAAU;AAAA,MACnB;AAAA,IACD;AAAA,EACD,GAAG,IAAI;AAEP,SAAO;AACR;;;AD3CO,SAAS,YACf,YACA,SACkC;AAClC,QAAM,QAAQE,QAAO,UAAU;AAC/B,QAAM,UAAU;AAEhB,QAAM,aAAaA,QAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,gBAAgB;AAAA,IACrB,MACC,yBAAiD;AAAA,MAChD,YAAY,IAAI,SAAS,MAAM,QAAQ,GAAG,IAAI;AAAA,MAC9C,gBAAgB,MAAM,WAAW;AAAA,IAClC,CAAC;AAAA,IACF,CAAC,eAAe,WAAW,QAAQ;AAAA,IACnC,CAAC;AAAA,EACF;AAEA,QAAM,QAAQC;AAAA,IACb,CAAC,kBAAkB,cAAc,EAAE,UAAU,aAAa;AAAA,IAC1D,MAAM,cAAc,EAAE,YAAY;AAAA,IAClC,MAAM,cAAc,EAAE,YAAY;AAAA,EACnC;AAEA,SAAO;AAAA,IACN,QAAQ,IAAI,SAAgB,cAAc,EAAE,OAAO,GAAG,IAAI;AAAA,IAC1D,aAAa,IAAI,SAAgB,cAAc,EAAE,YAAY,GAAG,IAAI;AAAA,IACpE,WAAW,MAAM;AAAA,IACjB,OAAO,MAAM;AAAA,IACb,OAAO,MAAM,cAAc,EAAE,MAAM;AAAA,EACpC;AACD;;;AExCA,SAAS,kCAAkC;AAC3C,SAAS,wBAAAC,6BAA4B;AAO9B,SAAS,gBAAgC;AAC/C,QAAM,EAAE,YAAY,qBAAqB,OAAO,IAAI,eAAe;AAEnE,QAAM,gBAAgB;AAAA,IACrB,MACC,2BAA2B;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,QAAQ,sBAAsB,OAAO;AAAA,IACtC,CAAC;AAAA,IACF,CAAC,eAAe,WAAW,QAAQ;AAAA,IACnC,CAAC,YAAY,qBAAqB,MAAM;AAAA,EACzC;AAEA,SAAOC;AAAA,IACN,CAAC,kBAAkB,cAAc,EAAE,UAAU,aAAa;AAAA,IAC1D,MAAM,cAAc,EAAE,YAAY;AAAA,IAClC,MAAM,cAAc,EAAE,YAAY;AAAA,EACnC;AACD;;;AC3BA,SAAS,WAAAC,gBAAe;AAgBjB,SAAS,cAAc,MAAkC;AAC/D,QAAM,EAAE,MAAM,IAAI,eAAe;AAEjC,SAAOC,SAAQ,MAAM;AACpB,WAAO,MAAM,WAAW,IAAI;AAAA,EAC7B,GAAG,CAAC,OAAO,IAAI,CAAC;AACjB;;;ACvBA,SAAS,sBAAsB,gCAAgC;AAG/D,SAAS,aAAa,aAAAC,YAAW,WAAAC,UAAS,wBAAAC,6BAA4B;AAa/D,SAAS,YACf,gBACA,UACA,WACA,SACoB;AACpB,QAAM,EAAE,OAAO,WAAW,IAAI,eAAe;AAC7C,QAAM,aAAaC,SAAQ,MAAM,MAAM,WAAW,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC;AAE1F,QAAM,gBAAgB;AAAA,IACrB,MACC,yBAAyB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,qBAAqB,UAAU;AAAA,MAC3C,eAAe,SAAS;AAAA,MACxB,MAAM,SAAS;AAAA,IAChB,CAAC;AAAA,IACF,CAAC,eAAe,WAAW,QAAQ;AAAA,IACnC,CAAC,YAAY,gBAAgB,WAAW,SAAS,eAAe,UAAU,OAAO,UAAU;AAAA,EAC5F;AAEA,EAAAC,WAAU,MAAM;AACf,kBAAc,EAAE,QAAQ,SAAS,IAAI;AAAA,EACtC,GAAG,CAAC,eAAe,SAAS,IAAI,CAAC;AAEjC,QAAM,WAAWC;AAAA,IAChB,CAAC,kBAAkB,cAAc,EAAE,UAAU,aAAa;AAAA,IAC1D,MAAM,cAAc,EAAE,YAAY;AAAA,IAClC,MAAM,cAAc,EAAE,YAAY;AAAA,EACnC;AAEA,QAAM,OAAO,YAAY,MAAM;AAC9B,kBAAc,EAAE,KAAK;AAAA,EACtB,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,OAAO,YAAY,MAAM;AAC9B,kBAAc,EAAE,KAAK;AAAA,EACtB,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,YAAY;AAAA,IACjB,CAAC,QAAgB,SAAiB,cAAc,EAAE,UAAU,QAAQ,IAAI;AAAA,IACxE,CAAC,aAAa;AAAA,EACf;AACA,QAAM,cAAc,YAAY,MAAM,cAAc,EAAE,YAAY,GAAG,CAAC,aAAa,CAAC;AAEpF,SAAO,YAAY,cAAc,GAAG,UAAU,MAAM,MAAM,WAAW,WAAW;AACjF;AAEA,SAAS,YACR,YACA,UACA,MACA,MACA,WACA,aACoB;AACpB,SAAO;AAAA,IACN,KAAK,WAAW;AAAA,IAChB,MAAM,WAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,SAAS,CAAC,GAAG,SAAS,OAAO;AAAA,IAC7B;AAAA,IACA;AAAA,EACD;AACD;;;ACvFA,SAAS,aAAAC,kBAAiB;AAQnB,SAAS,YAAY,MAAqE;AAChG,QAAM,EAAE,WAAW,IAAI,eAAe;AACtC,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,QAAQ,MAAM,SAAS;AAC7B,QAAM,SAAS,MAAM,UAAU;AAE/B,EAAAC,WAAU,MAAM;AACf,QAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAO;AAEpC,UAAM,YAAY,WAAW,oBAAoB;AACjD,cAAU,cAAc;AAAA,MACvB,MAAM,EAAE,MAAM,OAAO,QAAQ,UAAU,OAAU;AAAA,IAClD,CAAC;AAED,WAAO,MAAM;AACZ,gBAAU,cAAc,IAAI;AAAA,IAC7B;AAAA,EACD,GAAG,CAAC,YAAY,MAAM,OAAO,MAAM,CAAC;AACrC;;;ACzBA,SAAS,sCAAsC;AAC/C,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,wBAAAC,6BAA4B;AAGrE,IAAMC,eAAgC,CAAC;AAOhC,SAAS,mBAAqC;AACpD,QAAM,EAAE,WAAW,IAAI,eAAe;AAEtC,QAAM,cAAcC,QAAyBD,YAAW;AAExD,QAAM,YAAYE;AAAA,IACjB,CAAC,kBAA4C;AAC5C,UAAI,CAAC,YAAY;AAChB,oBAAY,UAAUF;AACtB,eAAO,MAAM;AAAA,QAAC;AAAA,MACf;AAEA,YAAM,YAAY,WAAW,oBAAoB;AACjD,aAAO,+BAA+B,WAAW,CAAC,WAAW;AAC5D,oBAAY,UAAU;AACtB,sBAAc;AAAA,MACf,CAAC;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACZ;AAEA,QAAM,cAAcE,aAAY,MAAwB,YAAY,SAAS,CAAC,CAAC;AAE/E,EAAAC,WAAU,MAAM;AACf,QAAI,CAAC,YAAY;AAChB,kBAAY,UAAUH;AAAA,IACvB;AAAA,EACD,GAAG,CAAC,UAAU,CAAC;AAEf,SAAOI,sBAAqB,WAAW,WAAW;AACnD;","names":["useEffect","useRef","useState","useRef","useState","useEffect","useRef","useSyncExternalStore","useEffect","useRef","useRef","useSyncExternalStore","useSyncExternalStore","useSyncExternalStore","useMemo","useMemo","useEffect","useMemo","useSyncExternalStore","useMemo","useEffect","useSyncExternalStore","useEffect","useEffect","useCallback","useEffect","useRef","useSyncExternalStore","EMPTY_ARRAY","useRef","useCallback","useEffect","useSyncExternalStore"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@korajs/react",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Kora.js React hooks and bindings for offline-first applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"yjs": "^13.6.30",
|
|
34
34
|
"@korajs/core": "0.6.0",
|
|
35
|
-
"@korajs/sync": "0.6.
|
|
35
|
+
"@korajs/sync": "0.6.1",
|
|
36
36
|
"@korajs/store": "0.6.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|