@korajs/svelte 0.5.0 → 0.6.0

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,13 +20,50 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ applyPresence: () => applyPresence,
24
+ createCollaboratorsStore: () => createCollaboratorsStore,
25
+ createMutation: () => createMutation,
26
+ createQueryStore: () => createQueryStore,
27
+ createRichTextBinding: () => createRichTextBinding,
28
+ createSyncStatusStore: () => createSyncStatusStore,
29
+ getApp: () => getApp,
30
+ getCollection: () => getCollection,
23
31
  getKoraApp: () => getKoraApp,
24
- setKoraAppContext: () => setKoraAppContext
32
+ getKoraContext: () => getKoraContext,
33
+ initKoraProvider: () => initKoraProvider,
34
+ setKoraAppContext: () => setKoraAppContext,
35
+ setKoraContext: () => setKoraContext,
36
+ useApp: () => useApp,
37
+ useCollaborators: () => useCollaborators,
38
+ useCollection: () => useCollection,
39
+ useMutation: () => useMutation,
40
+ usePresence: () => usePresence,
41
+ useQuery: () => useQuery,
42
+ useRichText: () => useRichText,
43
+ useSyncStatus: () => useSyncStatus
25
44
  });
26
45
  module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/context.ts
27
48
  var import_core = require("@korajs/core");
49
+ var import_store = require("@korajs/store");
28
50
  var import_svelte = require("svelte");
51
+ var koraContextKey = /* @__PURE__ */ Symbol("korajs-context");
29
52
  var koraAppContextKey = /* @__PURE__ */ Symbol("korajs-app");
53
+ function setKoraContext(value) {
54
+ (0, import_svelte.setContext)(koraContextKey, value);
55
+ }
56
+ function getKoraContext() {
57
+ const context = (0, import_svelte.getContext)(koraContextKey);
58
+ if (!context) {
59
+ throw new import_core.KoraError(
60
+ "Kora context missing. Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.",
61
+ "KORA_NOT_PROVIDED",
62
+ { fix: "Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>." }
63
+ );
64
+ }
65
+ return context;
66
+ }
30
67
  function setKoraAppContext(koraApp) {
31
68
  (0, import_svelte.setContext)(koraAppContextKey, koraApp);
32
69
  }
@@ -34,18 +71,278 @@ function getKoraApp() {
34
71
  const app = (0, import_svelte.getContext)(koraAppContextKey);
35
72
  if (!app) {
36
73
  throw new import_core.KoraError(
37
- "getKoraApp() requires setKoraAppContext(koraApp) on an ancestor component.",
38
- "KORA_NOT_PROVIDED",
39
- {
40
- fix: "In +layout.svelte: setKoraAppContext(kora); await kora.ready before queries."
41
- }
74
+ "getKoraApp() requires setKoraAppContext(koraApp) on an ancestor.",
75
+ "KORA_NOT_PROVIDED"
42
76
  );
43
77
  }
44
78
  return app;
45
79
  }
80
+ async function initKoraProvider(app) {
81
+ await app.ready;
82
+ const queryStoreCache = typeof app.getQueryStoreCache === "function" ? app.getQueryStoreCache() : new import_store.QueryStoreCache();
83
+ const value = {
84
+ store: app.getStore(),
85
+ syncEngine: app.getSyncEngine(),
86
+ app,
87
+ events: app.events ?? null,
88
+ subscribeSyncStatus: app.sync?.subscribeStatus ?? null,
89
+ queryStoreCache
90
+ };
91
+ setKoraContext(value);
92
+ setKoraAppContext(app);
93
+ return value;
94
+ }
95
+
96
+ // src/stores/query-store.ts
97
+ var import_store2 = require("@korajs/store");
98
+ var import_store3 = require("svelte/store");
99
+ var EMPTY_ARRAY = Object.freeze([]);
100
+ function createQueryStore(query, options) {
101
+ const { queryStoreCache } = getKoraContext();
102
+ const enabled = options?.enabled !== false;
103
+ return (0, import_store3.readable)(EMPTY_ARRAY, (set) => {
104
+ if (!enabled) {
105
+ set(EMPTY_ARRAY);
106
+ return () => {
107
+ };
108
+ }
109
+ (0, import_store2.assertQueryReady)(query);
110
+ const queryStore = queryStoreCache.getOrCreate(query);
111
+ const unsubscribe = queryStore.subscribe(() => {
112
+ set(queryStore.getSnapshot());
113
+ });
114
+ set(queryStore.getSnapshot());
115
+ return () => {
116
+ unsubscribe();
117
+ queryStoreCache.release(query);
118
+ };
119
+ });
120
+ }
121
+ var useQuery = createQueryStore;
122
+
123
+ // src/composables/use-mutation.ts
124
+ var import_bindings = require("@korajs/core/bindings");
125
+ function createMutation(mutationFn, options) {
126
+ const optionsRef = { current: options };
127
+ optionsRef.current = options;
128
+ const fnRef = { current: mutationFn };
129
+ fnRef.current = mutationFn;
130
+ const controller = (0, import_bindings.createMutationController)({
131
+ mutationFn: (...args) => fnRef.current(...args),
132
+ resolveOptions: () => optionsRef.current
133
+ });
134
+ const loadingListeners = /* @__PURE__ */ new Set();
135
+ const errorListeners = /* @__PURE__ */ new Set();
136
+ controller.subscribe(() => {
137
+ const snapshot = controller.getSnapshot();
138
+ for (const listener of loadingListeners) {
139
+ listener(snapshot.isLoading);
140
+ }
141
+ for (const listener of errorListeners) {
142
+ listener(snapshot.error);
143
+ }
144
+ });
145
+ return {
146
+ mutate: (...args) => controller.mutate(...args),
147
+ mutateAsync: (...args) => controller.mutateAsync(...args),
148
+ subscribeLoading: (fn) => {
149
+ loadingListeners.add(fn);
150
+ fn(controller.getSnapshot().isLoading);
151
+ return () => loadingListeners.delete(fn);
152
+ },
153
+ subscribeError: (fn) => {
154
+ errorListeners.add(fn);
155
+ fn(controller.getSnapshot().error);
156
+ return () => errorListeners.delete(fn);
157
+ },
158
+ get loading() {
159
+ return controller.getSnapshot().isLoading;
160
+ },
161
+ get isLoading() {
162
+ return controller.getSnapshot().isLoading;
163
+ },
164
+ get error() {
165
+ return controller.getSnapshot().error;
166
+ },
167
+ reset: () => controller.reset()
168
+ };
169
+ }
170
+ var useMutation = createMutation;
171
+
172
+ // src/composables/use-sync-status.ts
173
+ var import_sync = require("@korajs/sync");
174
+ var import_store4 = require("svelte/store");
175
+ function createSyncStatusStore() {
176
+ const { syncEngine, subscribeSyncStatus, events } = getKoraContext();
177
+ return (0, import_store4.readable)(import_sync.OFFLINE_SYNC_STATUS, (set) => {
178
+ const controller = (0, import_sync.createSyncStatusController)({
179
+ syncEngine,
180
+ subscribeSyncStatus,
181
+ events: subscribeSyncStatus ? null : events
182
+ });
183
+ set(controller.getSnapshot());
184
+ const unsubscribe = controller.subscribe(() => {
185
+ set(controller.getSnapshot());
186
+ });
187
+ return () => {
188
+ unsubscribe();
189
+ controller.destroy();
190
+ };
191
+ });
192
+ }
193
+ var useSyncStatus = createSyncStatusStore;
194
+
195
+ // src/composables/use-app.ts
196
+ function getApp() {
197
+ const { app } = getKoraContext();
198
+ if (!app) {
199
+ throw new Error(
200
+ "getApp() requires <KoraProvider app={kora}> or <KoraStoreProvider store={store}> with a createApp() instance."
201
+ );
202
+ }
203
+ return app;
204
+ }
205
+ var useApp = getApp;
206
+
207
+ // src/composables/use-collection.ts
208
+ function getCollection(name) {
209
+ const { store } = getKoraContext();
210
+ return store.collection(name);
211
+ }
212
+ var useCollection = getCollection;
213
+
214
+ // src/composables/use-rich-text.ts
215
+ var import_store5 = require("@korajs/store");
216
+ var import_svelte2 = require("svelte");
217
+ var import_store6 = require("svelte/store");
218
+ function createRichTextBinding(collectionName, recordId, fieldName, options) {
219
+ const { store, syncEngine } = getKoraContext();
220
+ const controller = (0, import_store5.createRichTextController)({
221
+ collection: store.collection(collectionName),
222
+ collectionName,
223
+ recordId,
224
+ fieldName,
225
+ store,
226
+ syncEngine: (0, import_store5.asRichTextSyncEngine)(syncEngine),
227
+ useDocChannel: options?.useDocChannel,
228
+ user: options?.user
229
+ });
230
+ (0, import_svelte2.onDestroy)(() => {
231
+ controller.destroy();
232
+ });
233
+ const resultStore = (0, import_store6.readable)(buildResult(controller), (set) => {
234
+ const sync = () => {
235
+ set(buildResult(controller));
236
+ };
237
+ sync();
238
+ return controller.subscribe(sync);
239
+ });
240
+ return {
241
+ get doc() {
242
+ return controller.doc;
243
+ },
244
+ get text() {
245
+ return controller.text;
246
+ },
247
+ undo: () => controller.undo(),
248
+ redo: () => controller.redo(),
249
+ get ready() {
250
+ return (0, import_store6.get)(resultStore).ready;
251
+ },
252
+ get error() {
253
+ return (0, import_store6.get)(resultStore).error;
254
+ },
255
+ get canUndo() {
256
+ return (0, import_store6.get)(resultStore).canUndo;
257
+ },
258
+ get canRedo() {
259
+ return (0, import_store6.get)(resultStore).canRedo;
260
+ },
261
+ get cursors() {
262
+ return (0, import_store6.get)(resultStore).cursors;
263
+ },
264
+ setCursor: (anchor, head) => controller.setCursor(anchor, head),
265
+ clearCursor: () => controller.clearCursor(),
266
+ subscribe: resultStore.subscribe
267
+ };
268
+ }
269
+ var useRichText = createRichTextBinding;
270
+ function buildResult(controller) {
271
+ const snapshot = controller.getSnapshot();
272
+ return {
273
+ doc: controller.doc,
274
+ text: controller.text,
275
+ undo: () => controller.undo(),
276
+ redo: () => controller.redo(),
277
+ ready: snapshot.ready,
278
+ error: snapshot.error,
279
+ canUndo: snapshot.canUndo,
280
+ canRedo: snapshot.canRedo,
281
+ cursors: [...snapshot.cursors],
282
+ setCursor: (anchor, head) => controller.setCursor(anchor, head),
283
+ clearCursor: () => controller.clearCursor()
284
+ };
285
+ }
286
+
287
+ // src/composables/use-presence.ts
288
+ function applyPresence(user) {
289
+ const { syncEngine } = getKoraContext();
290
+ if (!syncEngine || !user?.name || !user?.color) {
291
+ return () => {
292
+ };
293
+ }
294
+ const awareness = syncEngine.getAwarenessManager();
295
+ awareness.setLocalState({
296
+ user: {
297
+ name: user.name,
298
+ color: user.color,
299
+ avatar: user.avatar
300
+ }
301
+ });
302
+ return () => {
303
+ awareness.setLocalState(null);
304
+ };
305
+ }
306
+ var usePresence = applyPresence;
307
+
308
+ // src/composables/use-collaborators.ts
309
+ var import_sync2 = require("@korajs/sync");
310
+ var import_store7 = require("svelte/store");
311
+ function createCollaboratorsStore() {
312
+ const { syncEngine } = getKoraContext();
313
+ return (0, import_store7.readable)([], (set) => {
314
+ if (!syncEngine) {
315
+ set([]);
316
+ return () => {
317
+ };
318
+ }
319
+ const awareness = syncEngine.getAwarenessManager();
320
+ return (0, import_sync2.subscribeRemoteAwarenessStates)(awareness, set);
321
+ });
322
+ }
323
+ var useCollaborators = createCollaboratorsStore;
46
324
  // Annotate the CommonJS export names for ESM import in node:
47
325
  0 && (module.exports = {
326
+ applyPresence,
327
+ createCollaboratorsStore,
328
+ createMutation,
329
+ createQueryStore,
330
+ createRichTextBinding,
331
+ createSyncStatusStore,
332
+ getApp,
333
+ getCollection,
48
334
  getKoraApp,
49
- setKoraAppContext
335
+ getKoraContext,
336
+ initKoraProvider,
337
+ setKoraAppContext,
338
+ setKoraContext,
339
+ useApp,
340
+ useCollaborators,
341
+ useCollection,
342
+ useMutation,
343
+ usePresence,
344
+ useQuery,
345
+ useRichText,
346
+ useSyncStatus
50
347
  });
51
348
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { KoraError } from '@korajs/core'\nimport { getContext, setContext } from 'svelte'\nimport type { KoraAppHandle } from './types'\n\nexport type { KoraAppHandle } from './types'\n\nconst koraAppContextKey = Symbol('korajs-app')\n\n/**\n * Set the Kora app in Svelte context (call from a root layout or `+layout.svelte`).\n */\nexport function setKoraAppContext(koraApp: KoraAppHandle): void {\n\tsetContext(koraAppContextKey, koraApp)\n}\n\n/**\n * Read the Kora app from Svelte context in child components.\n */\nexport function getKoraApp(): KoraAppHandle {\n\tconst app = getContext<KoraAppHandle | undefined>(koraAppContextKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'getKoraApp() requires setKoraAppContext(koraApp) on an ancestor component.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{\n\t\t\t\tfix: 'In +layout.svelte: setKoraAppContext(kora); await kora.ready before queries.',\n\t\t\t},\n\t\t)\n\t}\n\treturn app\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA0B;AAC1B,oBAAuC;AAKvC,IAAM,oBAAoB,uBAAO,YAAY;AAKtC,SAAS,kBAAkB,SAA8B;AAC/D,gCAAW,mBAAmB,OAAO;AACtC;AAKO,SAAS,aAA4B;AAC3C,QAAM,UAAM,0BAAsC,iBAAiB;AACnE,MAAI,CAAC,KAAK;AACT,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,QACC,KAAK;AAAA,MACN;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context.ts","../src/stores/query-store.ts","../src/composables/use-mutation.ts","../src/composables/use-sync-status.ts","../src/composables/use-app.ts","../src/composables/use-collection.ts","../src/composables/use-rich-text.ts","../src/composables/use-presence.ts","../src/composables/use-collaborators.ts"],"sourcesContent":["export type {\n\tKoraAppHandle,\n\tKoraAppLike,\n\tKoraContextValue,\n\tUseMutationOptions,\n\tUseMutationResult,\n\tUseQueryOptions,\n\tUseRichTextResult,\n} from './types'\n\nexport {\n\tgetKoraApp,\n\tgetKoraContext,\n\tinitKoraProvider,\n\tsetKoraAppContext,\n\tsetKoraContext,\n} from './context'\n\nexport { createQueryStore, useQuery } from './stores/query-store'\nexport { createMutation, useMutation } from './composables/use-mutation'\nexport { createSyncStatusStore, useSyncStatus } from './composables/use-sync-status'\nexport { getApp, useApp } from './composables/use-app'\nexport { getCollection, useCollection } from './composables/use-collection'\nexport { createRichTextBinding, useRichText } from './composables/use-rich-text'\nexport type { UseRichTextOptions } from './composables/use-rich-text'\nexport { applyPresence, usePresence } from './composables/use-presence'\nexport { createCollaboratorsStore, useCollaborators } from './composables/use-collaborators'\n","import { KoraError } from '@korajs/core'\nimport { QueryStoreCache } from '@korajs/store'\nimport { getContext, setContext } from 'svelte'\nimport type { KoraAppLike, KoraContextValue } from './types'\n\nconst koraContextKey = Symbol('korajs-context')\nconst koraAppContextKey = Symbol('korajs-app')\n\nexport function setKoraContext(value: KoraContextValue): void {\n\tsetContext(koraContextKey, value)\n}\n\nexport function getKoraContext(): KoraContextValue {\n\tconst context = getContext<KoraContextValue | undefined>(koraContextKey)\n\tif (!context) {\n\t\tthrow new KoraError(\n\t\t\t'Kora context missing. Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t\t{ fix: 'Wrap your app with <KoraProvider app={kora}> or <KoraStoreProvider store={store}>.' },\n\t\t)\n\t}\n\treturn context\n}\n\n/** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */\nexport function setKoraAppContext(koraApp: KoraAppLike): void {\n\tsetContext(koraAppContextKey, koraApp)\n}\n\n/** @deprecated Use {@link getKoraContext} and {@link getApp}. */\nexport function getKoraApp(): KoraAppLike {\n\tconst app = getContext<KoraAppLike | undefined>(koraAppContextKey)\n\tif (!app) {\n\t\tthrow new KoraError(\n\t\t\t'getKoraApp() requires setKoraAppContext(koraApp) on an ancestor.',\n\t\t\t'KORA_NOT_PROVIDED',\n\t\t)\n\t}\n\treturn app\n}\n\n/**\n * Initialize Kora provider context after `app.ready`.\n *\n * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.\n */\nexport async function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue> {\n\tawait app.ready\n\tconst queryStoreCache =\n\t\ttypeof app.getQueryStoreCache === 'function'\n\t\t\t? app.getQueryStoreCache()\n\t\t\t: new QueryStoreCache()\n\tconst value: KoraContextValue = {\n\t\tstore: app.getStore(),\n\t\tsyncEngine: app.getSyncEngine(),\n\t\tapp,\n\t\tevents: app.events ?? null,\n\t\tsubscribeSyncStatus: app.sync?.subscribeStatus ?? null,\n\t\tqueryStoreCache,\n\t}\n\tsetKoraContext(value)\n\tsetKoraAppContext(app)\n\treturn value\n}\n","import type { CollectionRecord, QueryBuilder } from '@korajs/store'\nimport { assertQueryReady } from '@korajs/store'\nimport { readable, type Readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\nimport type { UseQueryOptions } from '../types'\n\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/**\n * Create a Svelte readable store for a static Kora query.\n *\n * For reactive filter changes, use {@link KoraQuery} which re-subscribes when the\n * query descriptor changes.\n */\nexport function createQueryStore<T = CollectionRecord>(\n\tquery: QueryBuilder<T>,\n\toptions?: UseQueryOptions,\n): Readable<readonly T[]> {\n\tconst { queryStoreCache } = getKoraContext()\n\tconst enabled = options?.enabled !== false\n\n\treturn readable<readonly T[]>(EMPTY_ARRAY as readonly T[], (set) => {\n\t\tif (!enabled) {\n\t\t\tset(EMPTY_ARRAY as readonly T[])\n\t\t\treturn () => {}\n\t\t}\n\n\t\tassertQueryReady(query as QueryBuilder<unknown>)\n\t\tconst queryStore = queryStoreCache.getOrCreate(query)\n\t\tconst unsubscribe = queryStore.subscribe(() => {\n\t\t\tset(queryStore.getSnapshot())\n\t\t})\n\t\tset(queryStore.getSnapshot())\n\n\t\treturn () => {\n\t\t\tunsubscribe()\n\t\t\tqueryStoreCache.release(query as QueryBuilder<unknown>)\n\t\t}\n\t})\n}\n\n/** Alias for {@link createQueryStore}. */\nexport const useQuery = createQueryStore\n","import { createMutationController } from '@korajs/core/bindings'\nimport type { UseMutationOptions, UseMutationResult } from '../types'\n\n/**\n * Create a mutation controller with optimistic update hooks.\n */\nexport function createMutation<TData, TArgs extends unknown[], TContext = void>(\n\tmutationFn: (...args: TArgs) => Promise<TData>,\n\toptions?: UseMutationOptions<TData, TArgs, TContext>,\n): UseMutationResult<TData, TArgs> {\n\tconst optionsRef = { current: options }\n\toptionsRef.current = options\n\n\tconst fnRef = { current: mutationFn }\n\tfnRef.current = mutationFn\n\n\tconst controller = createMutationController<TData, TArgs, TContext>({\n\t\tmutationFn: (...args) => fnRef.current(...args),\n\t\tresolveOptions: () => optionsRef.current,\n\t})\n\n\tconst loadingListeners = new Set<(value: boolean) => void>()\n\tconst errorListeners = new Set<(value: Error | null) => void>()\n\n\tcontroller.subscribe(() => {\n\t\tconst snapshot = controller.getSnapshot()\n\t\tfor (const listener of loadingListeners) {\n\t\t\tlistener(snapshot.isLoading)\n\t\t}\n\t\tfor (const listener of errorListeners) {\n\t\t\tlistener(snapshot.error)\n\t\t}\n\t})\n\n\treturn {\n\t\tmutate: (...args: TArgs) => controller.mutate(...args),\n\t\tmutateAsync: (...args: TArgs) => controller.mutateAsync(...args),\n\t\tsubscribeLoading: (fn) => {\n\t\t\tloadingListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().isLoading)\n\t\t\treturn () => loadingListeners.delete(fn)\n\t\t},\n\t\tsubscribeError: (fn) => {\n\t\t\terrorListeners.add(fn)\n\t\t\tfn(controller.getSnapshot().error)\n\t\t\treturn () => errorListeners.delete(fn)\n\t\t},\n\t\tget loading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget isLoading() {\n\t\t\treturn controller.getSnapshot().isLoading\n\t\t},\n\t\tget error() {\n\t\t\treturn controller.getSnapshot().error\n\t\t},\n\t\treset: () => controller.reset(),\n\t}\n}\n\n/** Alias for {@link createMutation}. */\nexport const useMutation = createMutation\n","import { OFFLINE_SYNC_STATUS, createSyncStatusController } from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { readable, type Readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of sync engine status.\n */\nexport function createSyncStatusStore(): Readable<SyncStatusInfo> {\n\tconst { syncEngine, subscribeSyncStatus, events } = getKoraContext()\n\n\treturn readable<SyncStatusInfo>(OFFLINE_SYNC_STATUS, (set) => {\n\t\tconst controller = createSyncStatusController({\n\t\t\tsyncEngine,\n\t\t\tsubscribeSyncStatus,\n\t\t\tevents: subscribeSyncStatus ? null : events,\n\t\t})\n\t\tset(controller.getSnapshot())\n\t\tconst unsubscribe = controller.subscribe(() => {\n\t\t\tset(controller.getSnapshot())\n\t\t})\n\t\treturn () => {\n\t\t\tunsubscribe()\n\t\t\tcontroller.destroy()\n\t\t}\n\t})\n}\n\n/** Alias for {@link createSyncStatusStore}. */\nexport const useSyncStatus = createSyncStatusStore\n","import { getKoraContext } from '../context'\nimport type { KoraAppLike } from '../types'\n\nexport function getApp<T extends KoraAppLike = KoraAppLike>(): T {\n\tconst { app } = getKoraContext()\n\tif (!app) {\n\t\tthrow new Error(\n\t\t\t'getApp() requires <KoraProvider app={kora}> or <KoraStoreProvider store={store}> with a createApp() instance.',\n\t\t)\n\t}\n\treturn app as T\n}\n\n/** Alias for {@link getApp}. */\nexport const useApp = getApp\n","import type { CollectionAccessor } from '@korajs/store'\nimport { getKoraContext } from '../context'\n\nexport function getCollection(name: string): CollectionAccessor {\n\tconst { store } = getKoraContext()\n\treturn store.collection(name)\n}\n\n/** Alias for {@link getCollection}. */\nexport const useCollection = getCollection\n","import { asRichTextSyncEngine, createRichTextController } from '@korajs/store'\nimport type { AwarenessUser } from '@korajs/sync'\nimport { onDestroy } from 'svelte'\nimport { get, readable, type Readable } from 'svelte/store'\nimport { getKoraContext } from '../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 *\n * Must be called during component initialization. For reactive target changes,\n * use {@link KoraRichText} instead.\n */\nexport function createRichTextBinding(\n\tcollectionName: string,\n\trecordId: string,\n\tfieldName: string,\n\toptions?: UseRichTextOptions,\n): UseRichTextResult & { subscribe: Readable<UseRichTextResult>['subscribe'] } {\n\tconst { store, syncEngine } = getKoraContext()\n\n\tconst controller = createRichTextController({\n\t\tcollection: store.collection(collectionName),\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine: asRichTextSyncEngine(syncEngine),\n\t\tuseDocChannel: options?.useDocChannel,\n\t\tuser: options?.user,\n\t})\n\n\tonDestroy(() => {\n\t\tcontroller.destroy()\n\t})\n\n\tconst resultStore = readable<UseRichTextResult>(buildResult(controller), (set) => {\n\t\tconst sync = (): void => {\n\t\t\tset(buildResult(controller))\n\t\t}\n\t\tsync()\n\t\treturn controller.subscribe(sync)\n\t})\n\n\treturn {\n\t\tget doc() {\n\t\t\treturn controller.doc\n\t\t},\n\t\tget text() {\n\t\t\treturn controller.text\n\t\t},\n\t\tundo: () => controller.undo(),\n\t\tredo: () => controller.redo(),\n\t\tget ready() {\n\t\t\treturn get(resultStore).ready\n\t\t},\n\t\tget error() {\n\t\t\treturn get(resultStore).error\n\t\t},\n\t\tget canUndo() {\n\t\t\treturn get(resultStore).canUndo\n\t\t},\n\t\tget canRedo() {\n\t\t\treturn get(resultStore).canRedo\n\t\t},\n\t\tget cursors() {\n\t\t\treturn get(resultStore).cursors\n\t\t},\n\t\tsetCursor: (anchor: number, head: number) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t\tsubscribe: resultStore.subscribe,\n\t}\n}\n\n/** @alias createRichTextBinding */\nexport const useRichText = createRichTextBinding\n\nfunction buildResult(\n\tcontroller: ReturnType<typeof createRichTextController>,\n): UseRichTextResult {\n\tconst snapshot = controller.getSnapshot()\n\treturn {\n\t\tdoc: controller.doc,\n\t\ttext: controller.text,\n\t\tundo: () => controller.undo(),\n\t\tredo: () => controller.redo(),\n\t\tready: snapshot.ready,\n\t\terror: snapshot.error,\n\t\tcanUndo: snapshot.canUndo,\n\t\tcanRedo: snapshot.canRedo,\n\t\tcursors: [...snapshot.cursors],\n\t\tsetCursor: (anchor, head) => controller.setCursor(anchor, head),\n\t\tclearCursor: () => controller.clearCursor(),\n\t}\n}\n","import { getKoraContext } from '../context'\n\n/**\n * Applies local collaborative presence. Returns a cleanup function.\n *\n * In Svelte components, call from an effect:\n * `$effect(() => applyPresence(user))`\n */\nexport function applyPresence(\n\tuser: { name: string; color: string; avatar?: string } | null,\n): () => void {\n\tconst { syncEngine } = getKoraContext()\n\tif (!syncEngine || !user?.name || !user?.color) {\n\t\treturn () => {}\n\t}\n\n\tconst awareness = syncEngine.getAwarenessManager()\n\tawareness.setLocalState({\n\t\tuser: {\n\t\t\tname: user.name,\n\t\t\tcolor: user.color,\n\t\t\tavatar: user.avatar,\n\t\t},\n\t})\n\n\treturn () => {\n\t\tawareness.setLocalState(null)\n\t}\n}\n\n/** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */\nexport const usePresence = applyPresence\n","import type { AwarenessState } from '@korajs/sync'\nimport { subscribeRemoteAwarenessStates } from '@korajs/sync'\nimport { readable, type Readable } from 'svelte/store'\nimport { getKoraContext } from '../context'\n\n/**\n * Readable store of remote collaborators' awareness states.\n */\nexport function createCollaboratorsStore(): Readable<AwarenessState[]> {\n\tconst { syncEngine } = getKoraContext()\n\n\treturn readable<AwarenessState[]>([], (set) => {\n\t\tif (!syncEngine) {\n\t\t\tset([])\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\treturn subscribeRemoteAwarenessStates(awareness, set)\n\t})\n}\n\n/** Alias for {@link createCollaboratorsStore}. */\nexport const useCollaborators = createCollaboratorsStore\n"],"mappings":"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","names":["import_store","import_store","import_store","import_svelte","import_sync","import_store"]}
package/dist/index.d.cts CHANGED
@@ -1,25 +1,116 @@
1
- import { KoraEventEmitter } from '@korajs/core';
2
- import { Store } from '@korajs/store';
1
+ import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1 } from '@korajs/core/bindings';
2
+ import { Store, QueryStoreCache, CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
3
+ import { SyncEngine, CursorInfo, SyncStatusInfo, AwarenessUser, AwarenessState } from '@korajs/sync';
4
+ import * as Y from 'yjs';
5
+ import { Readable } from 'svelte/store';
6
+
7
+ type KoraAppLike = KoraAppLike$1<Store, SyncEngine, QueryStoreCache>;
8
+ type KoraContextValue = KoraContextValue$1<Store, SyncEngine, QueryStoreCache>;
9
+ type UseQueryOptions = UseQueryOptions$1;
10
+ type UseMutationOptions<TData, TArgs extends unknown[], TContext = void> = UseMutationOptions$1<TData, TArgs, TContext>;
11
+ interface UseMutationResult<TData, TArgs extends unknown[]> extends UseMutationResultBase<TData, TArgs> {
12
+ subscribeLoading: (fn: (value: boolean) => void) => () => void;
13
+ subscribeError: (fn: (value: Error | null) => void) => () => void;
14
+ readonly loading: boolean;
15
+ readonly isLoading: boolean;
16
+ readonly error: Error | null;
17
+ }
18
+ /** @deprecated Use {@link KoraAppLike}. */
19
+ type KoraAppHandle = KoraAppLike;
20
+ interface UseRichTextResult {
21
+ doc: Y.Doc;
22
+ text: Y.Text;
23
+ undo: () => void;
24
+ redo: () => void;
25
+ canUndo: boolean;
26
+ canRedo: boolean;
27
+ ready: boolean;
28
+ error: Error | null;
29
+ cursors: CursorInfo[];
30
+ setCursor: (anchor: number, head: number) => void;
31
+ clearCursor: () => void;
32
+ }
33
+
34
+ declare function setKoraContext(value: KoraContextValue): void;
35
+ declare function getKoraContext(): KoraContextValue;
36
+ /** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */
37
+ declare function setKoraAppContext(koraApp: KoraAppLike): void;
38
+ /** @deprecated Use {@link getKoraContext} and {@link getApp}. */
39
+ declare function getKoraApp(): KoraAppLike;
40
+ /**
41
+ * Initialize Kora provider context after `app.ready`.
42
+ *
43
+ * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.
44
+ */
45
+ declare function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue>;
46
+
47
+ /**
48
+ * Create a Svelte readable store for a static Kora query.
49
+ *
50
+ * For reactive filter changes, use {@link KoraQuery} which re-subscribes when the
51
+ * query descriptor changes.
52
+ */
53
+ declare function createQueryStore<T = CollectionRecord>(query: QueryBuilder<T>, options?: UseQueryOptions): Readable<readonly T[]>;
54
+ /** Alias for {@link createQueryStore}. */
55
+ declare const useQuery: typeof createQueryStore;
3
56
 
4
57
  /**
5
- * Minimal app handle type for Svelte context (matches `createApp()` from korajs).
58
+ * Create a mutation controller with optimistic update hooks.
6
59
  */
7
- interface KoraAppHandle {
8
- readonly ready: Promise<void>;
9
- readonly events: KoraEventEmitter;
10
- readonly sync: unknown;
11
- close(): Promise<void>;
12
- getStore(): Store;
13
- [collection: string]: unknown;
60
+ declare function createMutation<TData, TArgs extends unknown[], TContext = void>(mutationFn: (...args: TArgs) => Promise<TData>, options?: UseMutationOptions<TData, TArgs, TContext>): UseMutationResult<TData, TArgs>;
61
+ /** Alias for {@link createMutation}. */
62
+ declare const useMutation: typeof createMutation;
63
+
64
+ /**
65
+ * Readable store of sync engine status.
66
+ */
67
+ declare function createSyncStatusStore(): Readable<SyncStatusInfo>;
68
+ /** Alias for {@link createSyncStatusStore}. */
69
+ declare const useSyncStatus: typeof createSyncStatusStore;
70
+
71
+ declare function getApp<T extends KoraAppLike = KoraAppLike>(): T;
72
+ /** Alias for {@link getApp}. */
73
+ declare const useApp: typeof getApp;
74
+
75
+ declare function getCollection(name: string): CollectionAccessor;
76
+ /** Alias for {@link getCollection}. */
77
+ declare const useCollection: typeof getCollection;
78
+
79
+ interface UseRichTextOptions {
80
+ user?: AwarenessUser;
81
+ useDocChannel?: boolean;
14
82
  }
83
+ /**
84
+ * Binds a richtext field to a shared Yjs document for editor integration.
85
+ *
86
+ * Must be called during component initialization. For reactive target changes,
87
+ * use {@link KoraRichText} instead.
88
+ */
89
+ declare function createRichTextBinding(collectionName: string, recordId: string, fieldName: string, options?: UseRichTextOptions): UseRichTextResult & {
90
+ subscribe: Readable<UseRichTextResult>['subscribe'];
91
+ };
92
+ /** @alias createRichTextBinding */
93
+ declare const useRichText: typeof createRichTextBinding;
15
94
 
16
95
  /**
17
- * Set the Kora app in Svelte context (call from a root layout or `+layout.svelte`).
96
+ * Applies local collaborative presence. Returns a cleanup function.
97
+ *
98
+ * In Svelte components, call from an effect:
99
+ * `$effect(() => applyPresence(user))`
18
100
  */
19
- declare function setKoraAppContext(koraApp: KoraAppHandle): void;
101
+ declare function applyPresence(user: {
102
+ name: string;
103
+ color: string;
104
+ avatar?: string;
105
+ } | null): () => void;
106
+ /** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */
107
+ declare const usePresence: typeof applyPresence;
108
+
20
109
  /**
21
- * Read the Kora app from Svelte context in child components.
110
+ * Readable store of remote collaborators' awareness states.
22
111
  */
23
- declare function getKoraApp(): KoraAppHandle;
112
+ declare function createCollaboratorsStore(): Readable<AwarenessState[]>;
113
+ /** Alias for {@link createCollaboratorsStore}. */
114
+ declare const useCollaborators: typeof createCollaboratorsStore;
24
115
 
25
- export { type KoraAppHandle, getKoraApp, setKoraAppContext };
116
+ export { type KoraAppHandle, type KoraAppLike, type KoraContextValue, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, applyPresence, createCollaboratorsStore, createMutation, createQueryStore, createRichTextBinding, createSyncStatusStore, getApp, getCollection, getKoraApp, getKoraContext, initKoraProvider, setKoraAppContext, setKoraContext, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };
package/dist/index.d.ts CHANGED
@@ -1,25 +1,116 @@
1
- import { KoraEventEmitter } from '@korajs/core';
2
- import { Store } from '@korajs/store';
1
+ import { KoraAppLike as KoraAppLike$1, KoraContextValue as KoraContextValue$1, UseMutationOptions as UseMutationOptions$1, UseMutationResultBase, UseQueryOptions as UseQueryOptions$1 } from '@korajs/core/bindings';
2
+ import { Store, QueryStoreCache, CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
3
+ import { SyncEngine, CursorInfo, SyncStatusInfo, AwarenessUser, AwarenessState } from '@korajs/sync';
4
+ import * as Y from 'yjs';
5
+ import { Readable } from 'svelte/store';
6
+
7
+ type KoraAppLike = KoraAppLike$1<Store, SyncEngine, QueryStoreCache>;
8
+ type KoraContextValue = KoraContextValue$1<Store, SyncEngine, QueryStoreCache>;
9
+ type UseQueryOptions = UseQueryOptions$1;
10
+ type UseMutationOptions<TData, TArgs extends unknown[], TContext = void> = UseMutationOptions$1<TData, TArgs, TContext>;
11
+ interface UseMutationResult<TData, TArgs extends unknown[]> extends UseMutationResultBase<TData, TArgs> {
12
+ subscribeLoading: (fn: (value: boolean) => void) => () => void;
13
+ subscribeError: (fn: (value: Error | null) => void) => () => void;
14
+ readonly loading: boolean;
15
+ readonly isLoading: boolean;
16
+ readonly error: Error | null;
17
+ }
18
+ /** @deprecated Use {@link KoraAppLike}. */
19
+ type KoraAppHandle = KoraAppLike;
20
+ interface UseRichTextResult {
21
+ doc: Y.Doc;
22
+ text: Y.Text;
23
+ undo: () => void;
24
+ redo: () => void;
25
+ canUndo: boolean;
26
+ canRedo: boolean;
27
+ ready: boolean;
28
+ error: Error | null;
29
+ cursors: CursorInfo[];
30
+ setCursor: (anchor: number, head: number) => void;
31
+ clearCursor: () => void;
32
+ }
33
+
34
+ declare function setKoraContext(value: KoraContextValue): void;
35
+ declare function getKoraContext(): KoraContextValue;
36
+ /** @deprecated Use {@link setKoraContext} via {@link KoraProvider} or {@link KoraStoreProvider}. */
37
+ declare function setKoraAppContext(koraApp: KoraAppLike): void;
38
+ /** @deprecated Use {@link getKoraContext} and {@link getApp}. */
39
+ declare function getKoraApp(): KoraAppLike;
40
+ /**
41
+ * Initialize Kora provider context after `app.ready`.
42
+ *
43
+ * @deprecated Prefer {@link KoraProvider} or {@link KoraStoreProvider} in root layout.
44
+ */
45
+ declare function initKoraProvider(app: KoraAppLike): Promise<KoraContextValue>;
46
+
47
+ /**
48
+ * Create a Svelte readable store for a static Kora query.
49
+ *
50
+ * For reactive filter changes, use {@link KoraQuery} which re-subscribes when the
51
+ * query descriptor changes.
52
+ */
53
+ declare function createQueryStore<T = CollectionRecord>(query: QueryBuilder<T>, options?: UseQueryOptions): Readable<readonly T[]>;
54
+ /** Alias for {@link createQueryStore}. */
55
+ declare const useQuery: typeof createQueryStore;
3
56
 
4
57
  /**
5
- * Minimal app handle type for Svelte context (matches `createApp()` from korajs).
58
+ * Create a mutation controller with optimistic update hooks.
6
59
  */
7
- interface KoraAppHandle {
8
- readonly ready: Promise<void>;
9
- readonly events: KoraEventEmitter;
10
- readonly sync: unknown;
11
- close(): Promise<void>;
12
- getStore(): Store;
13
- [collection: string]: unknown;
60
+ declare function createMutation<TData, TArgs extends unknown[], TContext = void>(mutationFn: (...args: TArgs) => Promise<TData>, options?: UseMutationOptions<TData, TArgs, TContext>): UseMutationResult<TData, TArgs>;
61
+ /** Alias for {@link createMutation}. */
62
+ declare const useMutation: typeof createMutation;
63
+
64
+ /**
65
+ * Readable store of sync engine status.
66
+ */
67
+ declare function createSyncStatusStore(): Readable<SyncStatusInfo>;
68
+ /** Alias for {@link createSyncStatusStore}. */
69
+ declare const useSyncStatus: typeof createSyncStatusStore;
70
+
71
+ declare function getApp<T extends KoraAppLike = KoraAppLike>(): T;
72
+ /** Alias for {@link getApp}. */
73
+ declare const useApp: typeof getApp;
74
+
75
+ declare function getCollection(name: string): CollectionAccessor;
76
+ /** Alias for {@link getCollection}. */
77
+ declare const useCollection: typeof getCollection;
78
+
79
+ interface UseRichTextOptions {
80
+ user?: AwarenessUser;
81
+ useDocChannel?: boolean;
14
82
  }
83
+ /**
84
+ * Binds a richtext field to a shared Yjs document for editor integration.
85
+ *
86
+ * Must be called during component initialization. For reactive target changes,
87
+ * use {@link KoraRichText} instead.
88
+ */
89
+ declare function createRichTextBinding(collectionName: string, recordId: string, fieldName: string, options?: UseRichTextOptions): UseRichTextResult & {
90
+ subscribe: Readable<UseRichTextResult>['subscribe'];
91
+ };
92
+ /** @alias createRichTextBinding */
93
+ declare const useRichText: typeof createRichTextBinding;
15
94
 
16
95
  /**
17
- * Set the Kora app in Svelte context (call from a root layout or `+layout.svelte`).
96
+ * Applies local collaborative presence. Returns a cleanup function.
97
+ *
98
+ * In Svelte components, call from an effect:
99
+ * `$effect(() => applyPresence(user))`
18
100
  */
19
- declare function setKoraAppContext(koraApp: KoraAppHandle): void;
101
+ declare function applyPresence(user: {
102
+ name: string;
103
+ color: string;
104
+ avatar?: string;
105
+ } | null): () => void;
106
+ /** Alias for {@link applyPresence} — use inside `$effect()` in `.svelte` files. */
107
+ declare const usePresence: typeof applyPresence;
108
+
20
109
  /**
21
- * Read the Kora app from Svelte context in child components.
110
+ * Readable store of remote collaborators' awareness states.
22
111
  */
23
- declare function getKoraApp(): KoraAppHandle;
112
+ declare function createCollaboratorsStore(): Readable<AwarenessState[]>;
113
+ /** Alias for {@link createCollaboratorsStore}. */
114
+ declare const useCollaborators: typeof createCollaboratorsStore;
24
115
 
25
- export { type KoraAppHandle, getKoraApp, setKoraAppContext };
116
+ export { type KoraAppHandle, type KoraAppLike, type KoraContextValue, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseRichTextOptions, type UseRichTextResult, applyPresence, createCollaboratorsStore, createMutation, createQueryStore, createRichTextBinding, createSyncStatusStore, getApp, getCollection, getKoraApp, getKoraContext, initKoraProvider, setKoraAppContext, setKoraContext, useApp, useCollaborators, useCollection, useMutation, usePresence, useQuery, useRichText, useSyncStatus };