syncorejs 0.2.3 → 0.2.4
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/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +272 -7
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/index.d.mts +3 -3
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +131 -0
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +3 -3
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +5 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +99 -13
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +38 -4
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +65 -8
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts.map +1 -1
- package/dist/_vendor/core/transport.mjs +30 -5
- package/dist/_vendor/core/transport.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +75 -1
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- package/dist/_vendor/devtools-protocol/index.js.map +1 -1
- package/dist/_vendor/next/index.js +9 -1
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +1 -1
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +6 -1
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-node/index.d.mts +2 -1
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +27 -2
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs +4 -0
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +2 -2
- package/dist/_vendor/platform-web/external-change.js +2 -2
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +13 -10
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +66 -10
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.d.ts +3 -3
- package/dist/_vendor/platform-web/indexeddb.js +3 -3
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.d.ts +3 -1
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +29 -3
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +31 -1
- package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.d.ts.map +1 -1
- package/dist/_vendor/platform-web/react.js +9 -1
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +6 -5
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +6 -5
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +8 -6
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +7 -5
- package/dist/_vendor/svelte/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.js","names":[],"sources":["../src/persistence.ts"],"sourcesContent":["import { SyncoreIndexedDbPersistence } from \"./indexeddb.js\";\nimport { SyncoreOpfsPersistence } from \"./opfs.js\";\n\n/**\n * A binary file record stored in web persistence (OPFS or IndexedDB).\n * Returned by `SyncoreWebPersistence.getFile` and `listFiles`.\n */\nexport interface StoredWebFile {\n /** Unique file identifier within its namespace. */\n id: string;\n /** Raw file bytes. */\n bytes: Uint8Array;\n /** MIME type, or `null` if none was recorded at write time. */\n contentType: string | null;\n /** File size in bytes. */\n size: number;\n}\n\n/**\n * Abstraction over browser storage backends (OPFS or IndexedDB).\n *\n * Handles both the SQLite database blob and binary file objects. All\n * implementations must persist data across page reloads.\n *\n * The concrete implementation is chosen by `createWebPersistence` based on\n * browser capabilities and the requested `WebPersistenceMode`.\n */\nexport interface SyncoreWebPersistence {\n /** The storage protocol used: `\"opfs\"` (Origin Private File System) or `\"idb\"` (IndexedDB). */\n readonly storageProtocol: \"idb\" | \"opfs\";\n /** Load the serialized SQLite database for `key`, or `null` if none has been saved yet. */\n loadDatabase(key: string): Promise<Uint8Array | null>;\n /** Persist the serialized SQLite database bytes for `key`. */\n saveDatabase(key: string, bytes: Uint8Array): Promise<void>;\n /** Retrieve a stored file from `namespace` by `id`, or `null` if not found. */\n getFile(namespace: string, id: string): Promise<StoredWebFile | null>;\n /** Write a file into `namespace` under `id`, replacing any existing entry. */\n putFile(\n namespace: string,\n id: string,\n bytes: Uint8Array,\n contentType: string | null\n ): Promise<void>;\n /** Delete a file from `namespace` by `id`. No-op if the file does not exist. */\n deleteFile(namespace: string, id: string): Promise<void>;\n /** List all stored files in `namespace`. */\n listFiles(namespace: string): Promise<StoredWebFile[]>;\n}\n\n/**\n * Which browser storage backend Syncore should use for SQLite persistence.\n *\n * - `\"opfs\"` — Origin Private File System. Fastest option; available in\n * Chrome 102+, Safari 15.2+, and modern Firefox. **Required** for\n * multi-tab coordination using `SharedArrayBuffer`.\n * - `\"indexeddb\"` — Falls back to IndexedDB for browsers without OPFS.\n * Slower due to serialization overhead but universally available.\n * - `\"auto\"` *(default)* — Picks `\"opfs\"` when available, otherwise\n * `\"indexeddb\"`.\n */\nexport type WebPersistenceMode = \"auto\" | \"indexeddb\" | \"opfs\";\n\n/** Options for {@link createWebPersistence}. */\nexport interface CreateWebPersistenceOptions {\n /** Persistence backend to use. Defaults to `\"auto\"`. */\n mode?: WebPersistenceMode;\n /** Custom IndexedDB database name. Defaults to the Syncore database name. */\n indexedDbDatabaseName?: string;\n /** Root directory name inside the OPFS bucket. Defaults to the Syncore database name. */\n opfsRootDirectoryName?: string;\n}\n\n/**\n * Create the appropriate web persistence backend based on browser capabilities\n * and the requested mode.\n *\n * Call this if you need a `SyncoreWebPersistence` instance outside of\n * `createWebSyncoreRuntime` (e.g. in the Expo adapter). In a standard\n * browser setup, `createWebSyncoreRuntime` calls this automatically.\n */\nexport async function createWebPersistence(\n options: CreateWebPersistenceOptions = {}\n): Promise<SyncoreWebPersistence> {\n const mode = options.mode ?? \"auto\";\n\n if (mode === \"opfs\") {\n if (!isOpfsAvailable()) {\n throw new Error(\"OPFS is not available in this environment.\");\n }\n return new SyncoreOpfsPersistence(\n options.opfsRootDirectoryName\n ? { rootDirectoryName: options.opfsRootDirectoryName }\n : undefined\n );\n }\n\n if (mode === \"auto\" && isOpfsAvailable()) {\n return new SyncoreOpfsPersistence(\n options.opfsRootDirectoryName\n ? { rootDirectoryName: options.opfsRootDirectoryName }\n : undefined\n );\n }\n\n return new SyncoreIndexedDbPersistence(\n options.indexedDbDatabaseName\n ? { databaseName: options.indexedDbDatabaseName }\n : undefined\n );\n}\n\n/**\n * Return `true` if the Origin Private File System API is available in the\n * current browser context.\n *\n * Used internally to decide whether to prefer OPFS over IndexedDB in `\"auto\"`\n * mode. Also useful in application code for displaying conditional UI.\n */\nexport function isOpfsAvailable(): boolean {\n return Boolean(getOpfsStorageManager()?.getDirectory);\n}\n\ntype OpfsStorageManager = StorageManager & {\n getDirectory?: () => Promise<FileSystemDirectoryHandle>;\n};\n\nfunction getOpfsStorageManager(): OpfsStorageManager | undefined {\n if (typeof navigator === \"undefined\") {\n return undefined;\n }\n return navigator.storage as OpfsStorageManager | undefined;\n}\n"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"persistence.js","names":[],"sources":["../src/persistence.ts"],"sourcesContent":["import { SyncoreIndexedDbPersistence } from \"./indexeddb.js\";\nimport { SyncoreOpfsPersistence } from \"./opfs.js\";\n\n/**\n * A binary file record stored in web persistence (OPFS or IndexedDB).\n * Returned by `SyncoreWebPersistence.getFile` and `listFiles`.\n */\nexport interface StoredWebFile {\n /** Unique file identifier within its namespace. */\n id: string;\n /** Raw file bytes. */\n bytes: Uint8Array;\n /** MIME type, or `null` if none was recorded at write time. */\n contentType: string | null;\n /** File size in bytes. */\n size: number;\n}\n\n/**\n * A byte range from a web persistence file, plus total object metadata.\n */\nexport interface StoredWebFileRange {\n /** Unique file identifier within its namespace. */\n id: string;\n /** Raw bytes for the requested range. */\n bytes: Uint8Array;\n /** MIME type, or `null` if none was recorded at write time. */\n contentType: string | null;\n /** Total file size in bytes. */\n size: number;\n /** Offset used for this range. */\n offset: number;\n}\n\n/**\n * Metadata for a web persistence file without the raw bytes.\n */\nexport interface StoredWebFileMetadata {\n /** Unique file identifier within its namespace. */\n id: string;\n /** MIME type, or `null` if none was recorded at write time. */\n contentType: string | null;\n /** Total file size in bytes. */\n size: number;\n}\n\n/**\n * Abstraction over browser storage backends (OPFS or IndexedDB).\n *\n * Handles both the SQLite database blob and binary file objects. All\n * implementations must persist data across page reloads.\n *\n * The concrete implementation is chosen by `createWebPersistence` based on\n * browser capabilities and the requested `WebPersistenceMode`.\n */\nexport interface SyncoreWebPersistence {\n /** The storage protocol used: `\"opfs\"` (Origin Private File System) or `\"idb\"` (IndexedDB). */\n readonly storageProtocol: \"idb\" | \"opfs\";\n /** Load the serialized SQLite database for `key`, or `null` if none has been saved yet. */\n loadDatabase(key: string): Promise<Uint8Array | null>;\n /** Persist the serialized SQLite database bytes for `key`. */\n saveDatabase(key: string, bytes: Uint8Array): Promise<void>;\n /** Retrieve a stored file from `namespace` by `id`, or `null` if not found. */\n getFile(namespace: string, id: string): Promise<StoredWebFile | null>;\n /** Retrieve a byte range without loading the whole file when supported. */\n getFileRange?(\n namespace: string,\n id: string,\n offset: number,\n length: number\n ): Promise<StoredWebFileRange | null>;\n /** Write a file into `namespace` under `id`, replacing any existing entry. */\n putFile(\n namespace: string,\n id: string,\n bytes: Uint8Array,\n contentType: string | null\n ): Promise<void>;\n /** Delete a file from `namespace` by `id`. No-op if the file does not exist. */\n deleteFile(namespace: string, id: string): Promise<void>;\n /** List all stored files in `namespace`. */\n listFiles(namespace: string): Promise<StoredWebFile[]>;\n /** List stored file metadata without loading file bytes when supported. */\n listFileMetadata?(namespace: string): Promise<StoredWebFileMetadata[]>;\n}\n\n/**\n * Which browser storage backend Syncore should use for SQLite persistence.\n *\n * - `\"opfs\"` — Origin Private File System. Fastest option; available in\n * Chrome 102+, Safari 15.2+, and modern Firefox. **Required** for\n * multi-tab coordination using `SharedArrayBuffer`.\n * - `\"indexeddb\"` — Falls back to IndexedDB for browsers without OPFS.\n * Slower due to serialization overhead but universally available.\n * - `\"auto\"` *(default)* — Picks `\"opfs\"` when available, otherwise\n * `\"indexeddb\"`.\n */\nexport type WebPersistenceMode = \"auto\" | \"indexeddb\" | \"opfs\";\n\n/** Options for {@link createWebPersistence}. */\nexport interface CreateWebPersistenceOptions {\n /** Persistence backend to use. Defaults to `\"auto\"`. */\n mode?: WebPersistenceMode;\n /** Custom IndexedDB database name. Defaults to the Syncore database name. */\n indexedDbDatabaseName?: string;\n /** Root directory name inside the OPFS bucket. Defaults to the Syncore database name. */\n opfsRootDirectoryName?: string;\n}\n\n/**\n * Create the appropriate web persistence backend based on browser capabilities\n * and the requested mode.\n *\n * Call this if you need a `SyncoreWebPersistence` instance outside of\n * `createWebSyncoreRuntime` (e.g. in the Expo adapter). In a standard\n * browser setup, `createWebSyncoreRuntime` calls this automatically.\n */\nexport async function createWebPersistence(\n options: CreateWebPersistenceOptions = {}\n): Promise<SyncoreWebPersistence> {\n const mode = options.mode ?? \"auto\";\n\n if (mode === \"opfs\") {\n if (!isOpfsAvailable()) {\n throw new Error(\"OPFS is not available in this environment.\");\n }\n return new SyncoreOpfsPersistence(\n options.opfsRootDirectoryName\n ? { rootDirectoryName: options.opfsRootDirectoryName }\n : undefined\n );\n }\n\n if (mode === \"auto\" && isOpfsAvailable()) {\n return new SyncoreOpfsPersistence(\n options.opfsRootDirectoryName\n ? { rootDirectoryName: options.opfsRootDirectoryName }\n : undefined\n );\n }\n\n return new SyncoreIndexedDbPersistence(\n options.indexedDbDatabaseName\n ? { databaseName: options.indexedDbDatabaseName }\n : undefined\n );\n}\n\n/**\n * Return `true` if the Origin Private File System API is available in the\n * current browser context.\n *\n * Used internally to decide whether to prefer OPFS over IndexedDB in `\"auto\"`\n * mode. Also useful in application code for displaying conditional UI.\n */\nexport function isOpfsAvailable(): boolean {\n return Boolean(getOpfsStorageManager()?.getDirectory);\n}\n\ntype OpfsStorageManager = StorageManager & {\n getDirectory?: () => Promise<FileSystemDirectoryHandle>;\n};\n\nfunction getOpfsStorageManager(): OpfsStorageManager | undefined {\n if (typeof navigator === \"undefined\") {\n return undefined;\n }\n return navigator.storage as OpfsStorageManager | undefined;\n}\n"],"mappings":";;;;;;;;;;;AAqHA,eAAsB,qBACpB,UAAuC,CAAC,GACR;CAChC,MAAM,OAAO,QAAQ,QAAQ;CAE7B,IAAI,SAAS,QAAQ;EACnB,IAAI,CAAC,gBAAgB,GACnB,MAAM,IAAI,MAAM,4CAA4C;EAE9D,OAAO,IAAI,uBACT,QAAQ,wBACJ,EAAE,mBAAmB,QAAQ,sBAAsB,IACnD,KAAA,CACN;CACF;CAEA,IAAI,SAAS,UAAU,gBAAgB,GACrC,OAAO,IAAI,uBACT,QAAQ,wBACJ,EAAE,mBAAmB,QAAQ,sBAAsB,IACnD,KAAA,CACN;CAGF,OAAO,IAAI,4BACT,QAAQ,wBACJ,EAAE,cAAc,QAAQ,sBAAsB,IAC9C,KAAA,CACN;AACF;;;;;;;;AASA,SAAgB,kBAA2B;CACzC,OAAO,QAAQ,sBAAsB,GAAG,YAAY;AACtD;AAMA,SAAS,wBAAwD;CAC/D,IAAI,OAAO,cAAc,aACvB;CAEF,OAAO,UAAU;AACnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","names":[],"sources":["../src/react.tsx"],"mappings":";;;;;;AAgBA;UAAiB,uBAAA,SAAgC,oCAAA;;EAE/C,QAAA,EAAU,SAAA;EAGC;EAAX,QAAA,GAAW,SAAA;AAAA;;;;KAMD,2BAAA,GAA8B,uBAAuB;;;;iBAKjD,kBAAA,CAAA;EACd,QAAA;EACA,SAAA;EACA,UAAA;EACA,UAAA;EACA;AAAA,GACC,uBAAA,GAA0B,SAAA;AAX7B;;;AAAA,
|
|
1
|
+
{"version":3,"file":"react.d.ts","names":[],"sources":["../src/react.tsx"],"mappings":";;;;;;AAgBA;UAAiB,uBAAA,SAAgC,oCAAA;;EAE/C,QAAA,EAAU,SAAA;EAGC;EAAX,QAAA,GAAW,SAAA;AAAA;;;;KAMD,2BAAA,GAA8B,uBAAuB;;;;iBAKjD,kBAAA,CAAA;EACd,QAAA;EACA,SAAA;EACA,UAAA;EACA,UAAA;EACA;AAAA,GACC,uBAAA,GAA0B,SAAA;AAX7B;;;AAAA,iBAoEgB,sBAAA,CAAuB,KAAA,EAAO,2BAA2B,+BAAA,GAAA,CAAA,OAAA"}
|
|
@@ -10,7 +10,11 @@ import { jsx } from "react/jsx-runtime";
|
|
|
10
10
|
function SyncoreWebProvider({ children, workerUrl, workerType, workerName, fallback = null }) {
|
|
11
11
|
const bootingClient = useMemo(() => createUnavailableSyncoreClient({
|
|
12
12
|
kind: "starting",
|
|
13
|
-
reason: "booting"
|
|
13
|
+
reason: "booting",
|
|
14
|
+
capabilities: { storage: {
|
|
15
|
+
available: false,
|
|
16
|
+
reason: "Syncore worker is booting."
|
|
17
|
+
} }
|
|
14
18
|
}), []);
|
|
15
19
|
const [client, setClient] = useState(bootingClient);
|
|
16
20
|
useEffect(() => {
|
|
@@ -27,6 +31,10 @@ function SyncoreWebProvider({ children, workerUrl, workerType, workerName, fallb
|
|
|
27
31
|
setClient(createUnavailableSyncoreClient({
|
|
28
32
|
kind: "unavailable",
|
|
29
33
|
reason: "worker-unavailable",
|
|
34
|
+
capabilities: { storage: {
|
|
35
|
+
available: false,
|
|
36
|
+
reason: "Syncore worker is unavailable."
|
|
37
|
+
} },
|
|
30
38
|
...error instanceof Error ? { error } : {}
|
|
31
39
|
}));
|
|
32
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import {\n createUnavailableSyncoreClient,\n type SyncoreClient\n} from \"@syncore/core\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { SyncoreProvider } from \"@syncore/react\";\nimport {\n createSyncoreWebWorkerClient,\n type CreateWebWorkerClientProviderOptions,\n type ManagedWebWorkerClient\n} from \"./worker.js\";\n\n/**\n * Props for {@link SyncoreWebProvider}.\n */\nexport interface SyncoreWebProviderProps extends CreateWebWorkerClientProviderOptions {\n /** The React subtree that should receive the Syncore client. */\n children: ReactNode;\n\n /** Optional fallback content rendered before the worker client is ready. */\n fallback?: ReactNode;\n}\n\n/**\n * Props for {@link SyncoreBrowserProvider}.\n */\nexport type SyncoreBrowserProviderProps = SyncoreWebProviderProps;\n\n/**\n * Start a worker-backed Syncore client and provide it to React descendants.\n */\nexport function SyncoreWebProvider({\n children,\n workerUrl,\n workerType,\n workerName,\n fallback = null\n}: SyncoreWebProviderProps): ReactNode {\n const bootingClient = useMemo(\n () =>\n createUnavailableSyncoreClient({\n kind: \"starting\",\n reason: \"booting\"\n }),\n []\n );\n const [client, setClient] = useState<SyncoreClient>(bootingClient);\n\n useEffect(() => {\n let managedClient: ManagedWebWorkerClient | undefined;\n\n setClient(bootingClient);\n\n try {\n managedClient = createSyncoreWebWorkerClient({\n workerUrl,\n ...(workerType ? { workerType } : {}),\n ...(workerName ? { workerName } : {})\n });\n setClient(managedClient.client);\n } catch (error) {\n setClient(\n createUnavailableSyncoreClient({\n kind: \"unavailable\",\n reason: \"worker-unavailable\",\n ...(error instanceof Error ? { error } : {})\n })\n );\n }\n\n return () => {\n managedClient?.dispose();\n };\n }, [bootingClient, workerName, workerType, workerUrl]);\n\n return (\n <SyncoreProvider client={client}>\n {children ?? fallback}\n </SyncoreProvider>\n );\n}\n\n/**\n * Start a worker-backed Syncore client and provide it to React descendants.\n */\nexport function SyncoreBrowserProvider(props: SyncoreBrowserProviderProps) {\n return <SyncoreWebProvider {...props} />;\n}\n"],"mappings":";;;;;;;;;AAgCA,SAAgB,mBAAmB,EACjC,UACA,WACA,YACA,YACA,WAAW,QAC0B;CACrC,MAAM,gBAAgB,cAElB,+BAA+B;EAC7B,MAAM;EACN,QAAQ;
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import {\n createUnavailableSyncoreClient,\n type SyncoreClient\n} from \"@syncore/core\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { SyncoreProvider } from \"@syncore/react\";\nimport {\n createSyncoreWebWorkerClient,\n type CreateWebWorkerClientProviderOptions,\n type ManagedWebWorkerClient\n} from \"./worker.js\";\n\n/**\n * Props for {@link SyncoreWebProvider}.\n */\nexport interface SyncoreWebProviderProps extends CreateWebWorkerClientProviderOptions {\n /** The React subtree that should receive the Syncore client. */\n children: ReactNode;\n\n /** Optional fallback content rendered before the worker client is ready. */\n fallback?: ReactNode;\n}\n\n/**\n * Props for {@link SyncoreBrowserProvider}.\n */\nexport type SyncoreBrowserProviderProps = SyncoreWebProviderProps;\n\n/**\n * Start a worker-backed Syncore client and provide it to React descendants.\n */\nexport function SyncoreWebProvider({\n children,\n workerUrl,\n workerType,\n workerName,\n fallback = null\n}: SyncoreWebProviderProps): ReactNode {\n const bootingClient = useMemo(\n () =>\n createUnavailableSyncoreClient({\n kind: \"starting\",\n reason: \"booting\",\n capabilities: {\n storage: { available: false, reason: \"Syncore worker is booting.\" }\n }\n }),\n []\n );\n const [client, setClient] = useState<SyncoreClient>(bootingClient);\n\n useEffect(() => {\n let managedClient: ManagedWebWorkerClient | undefined;\n\n setClient(bootingClient);\n\n try {\n managedClient = createSyncoreWebWorkerClient({\n workerUrl,\n ...(workerType ? { workerType } : {}),\n ...(workerName ? { workerName } : {})\n });\n setClient(managedClient.client);\n } catch (error) {\n setClient(\n createUnavailableSyncoreClient({\n kind: \"unavailable\",\n reason: \"worker-unavailable\",\n capabilities: {\n storage: {\n available: false,\n reason: \"Syncore worker is unavailable.\"\n }\n },\n ...(error instanceof Error ? { error } : {})\n })\n );\n }\n\n return () => {\n managedClient?.dispose();\n };\n }, [bootingClient, workerName, workerType, workerUrl]);\n\n return (\n <SyncoreProvider client={client}>\n {children ?? fallback}\n </SyncoreProvider>\n );\n}\n\n/**\n * Start a worker-backed Syncore client and provide it to React descendants.\n */\nexport function SyncoreBrowserProvider(props: SyncoreBrowserProviderProps) {\n return <SyncoreWebProvider {...props} />;\n}\n"],"mappings":";;;;;;;;;AAgCA,SAAgB,mBAAmB,EACjC,UACA,WACA,YACA,YACA,WAAW,QAC0B;CACrC,MAAM,gBAAgB,cAElB,+BAA+B;EAC7B,MAAM;EACN,QAAQ;EACR,cAAc,EACZ,SAAS;GAAE,WAAW;GAAO,QAAQ;EAA6B,EACpE;CACF,CAAC,GACH,CAAC,CACH;CACA,MAAM,CAAC,QAAQ,aAAa,SAAwB,aAAa;CAEjE,gBAAgB;EACd,IAAI;EAEJ,UAAU,aAAa;EAEvB,IAAI;GACF,gBAAgB,6BAA6B;IAC3C;IACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;IACnC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;GACrC,CAAC;GACD,UAAU,cAAc,MAAM;EAChC,SAAS,OAAO;GACd,UACE,+BAA+B;IAC7B,MAAM;IACN,QAAQ;IACR,cAAc,EACZ,SAAS;KACP,WAAW;KACX,QAAQ;IACV,EACF;IACA,GAAI,iBAAiB,QAAQ,EAAE,MAAM,IAAI,CAAC;GAC5C,CAAC,CACH;EACF;EAEA,aAAa;GACX,eAAe,QAAQ;EACzB;CACF,GAAG;EAAC;EAAe;EAAY;EAAY;CAAS,CAAC;CAErD,OACE,oBAAC,iBAAD;EAAyB;YACtB,YAAY;CACE,CAAA;AAErB;;;;AAKA,SAAgB,uBAAuB,OAAoC;CACzE,OAAO,oBAAC,oBAAD,EAAoB,GAAI,MAAQ,CAAA;AACzC"}
|
|
@@ -84,7 +84,7 @@ declare function useSyncore(): SyncoreClient;
|
|
|
84
84
|
/**
|
|
85
85
|
* Subscribe to the runtime’s lifecycle status.
|
|
86
86
|
*
|
|
87
|
-
* Returns a
|
|
87
|
+
* Returns a SyncoreRuntimeStatus that updates whenever the underlying
|
|
88
88
|
* runtime changes state (e.g. starting, ready, error). Use it to gate your UI
|
|
89
89
|
* on the runtime being ready or to display an error boundary:
|
|
90
90
|
*
|
|
@@ -127,7 +127,7 @@ declare function useSyncoreStatus(): SyncoreRuntimeStatus;
|
|
|
127
127
|
declare function useQuery<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs> | [Skip]): TResult | undefined;
|
|
128
128
|
/**
|
|
129
129
|
* Subscribe to a reactive Syncore query and return the full
|
|
130
|
-
*
|
|
130
|
+
* SyncoreQueryState including loading, error, and runtime status.
|
|
131
131
|
*
|
|
132
132
|
* Use this instead of {@link useQuery} when you need to:
|
|
133
133
|
* - Differentiate between `undefined` data and an error.
|
|
@@ -206,7 +206,7 @@ declare function useAction<TArgs, TResult>(reference: FunctionReference<"action"
|
|
|
206
206
|
*
|
|
207
207
|
* @param entries - A record of named query requests. Each entry can include
|
|
208
208
|
* `args: skip` to suppress that specific subscription.
|
|
209
|
-
* @returns A record with the same keys, each holding a
|
|
209
|
+
* @returns A record with the same keys, each holding a SyncoreQueryState.
|
|
210
210
|
*/
|
|
211
211
|
declare function useQueries<TEntries extends QueriesRequestInput>(entries: TEntries): UseQueriesResult<TEntries>;
|
|
212
212
|
/**
|
|
@@ -245,8 +245,9 @@ declare function useQueries<TEntries extends QueriesRequestInput>(entries: TEntr
|
|
|
245
245
|
* `ctx.db.query(…).paginate(paginationOpts)`.
|
|
246
246
|
* @param args - Arguments for the query (excluding
|
|
247
247
|
* `paginationOpts`, which is managed internally), or `skip`.
|
|
248
|
-
* @param options
|
|
249
|
-
*
|
|
248
|
+
* @param options - Pagination options. `initialNumItems` controls the number
|
|
249
|
+
* of items to load on the first page.
|
|
250
|
+
* @returns A UsePaginatedQueryResult with the accumulated results and
|
|
250
251
|
* a `loadMore` callback.
|
|
251
252
|
*/
|
|
252
253
|
declare function usePaginatedQuery<TReference extends PaginatedQueryReference>(reference: TReference, args: PaginatedQueryArgs<TReference> | Skip, options: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":";;;;KA0BK,iBAAA,UACH,MAAA,uBAA6B,KAAA,IAAS,IAAA,GAAO,KAAA,KAAU,IAAA,EAAM,KAAA;AAAA,KAE1D,iBAAA,oBACgB,iBAAA,YAA6B,iBAAA,aAC9C,MAAA,uBAA6B,YAAA,CAAa,UAAA;EAExC,KAAA,EAAO,UAAA;EACP,IAAA,GAAO,YAAA,CAAa,UAAA,IAAc,IAAA;AAAA;EAGlC,KAAA,EAAO,UAAA;EACP,IAAA,EAAM,YAAA,CAAa,UAAA,IAAc,IAAA;AAAA;AAAA,KAGlC,mBAAA,GAAsB,MAAM,SAAS,iBAAA;AAAA,KAErC,kBAAA,WAA6B,MAAA,SAAe,iBAAA,qBAG7C,iBAAA,CAAkB,cAAA,CAAe,UAAA;AAAA,KAGzB,gBAAA,kBAAkC,mBAAA,qBAC7B,QAAA,GAAW,kBAAA,CAAmB,QAAA,CAAS,IAAA;AAAA,KAGnD,uBAAA,GAA0B,iBAAA,UAE7B,MAAA,mBACA,gBAAA;AAAA,KAGG,kBAAA,oBAAsC,iBAAA,aACzC,YAAA,CAAa,UAAA;EAAsB,cAAA,EAAgB,iBAAA;AAAA,IAC/C,IAAA,CAAK,YAAA,CAAa,UAAA;AAAA,KAGnB,kBAAA,oBAAsC,iBAAA,aACzC,cAAA,CAAe,UAAA,UAAoB,gBAAA,gBAC/B,KAAA;;AAvC8D;AAAA;;;;;;;;;;;;;;cAuFvD,IAAA;AAAA,KACR,IAAA,UAAc,IAAI;;;;;;;;;;;;;;;;;;;;;;AA7EoB;AAAA;;iBA8G3B,eAAA,CAAA;EACd,MAAA;EACA;AAAA;EAEA,MAAA,EAAQ,aAAA;EACR,QAAA,EAAU,SAAA;AAAA,gCACX,GAAA,CAAA,OAAA;;;;;;;;;;;;;;iBAmBe,UAAA,CAAA,GAAc,aAAa;;;;AA/HI;AAG/C;;;;;;;;;;;;;;;iBAuJgB,gBAAA,CAAA,GAAoB,oBAAoB;;;AAtJI;AAC1D;;;;;;;;;;;;AAKgB;AAAA;;;;;;;iBAmMF,QAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,OAAA;;;;;;;;;;;;;;;AAjM+B;AAAA;;iBA0NlB,aAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,iBAAA,CAAkB,OAAA;;;;;;;;;;;;;;;AAxNV;AAgDX;;;;AAAmC;AAAC;iBA4NpB,WAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,aAA8B,KAAA,EAAO,OAAA,QAC3C,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;;AA7N3B;AAiCvB;;;;;;;;;;;;;;;;;;iBAsNgB,SAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,WAA4B,KAAA,EAAO,OAAA,QACzC,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;AAlNjD;AAmBD;;;;AAA2C;AA2B3C;;;;AAAwD;AAmDxD;;;;;;;;;iBA2IgB,UAAA,kBAA4B,mBAAA,CAAA,CAC1C,OAAA,EAAS,QAAA,GACR,gBAAA,CAAiB,QAAA;;;;;;;;;;;;;;;AA1IV;AAyBV
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":";;;;KA0BK,iBAAA,UACH,MAAA,uBAA6B,KAAA,IAAS,IAAA,GAAO,KAAA,KAAU,IAAA,EAAM,KAAA;AAAA,KAE1D,iBAAA,oBACgB,iBAAA,YAA6B,iBAAA,aAC9C,MAAA,uBAA6B,YAAA,CAAa,UAAA;EAExC,KAAA,EAAO,UAAA;EACP,IAAA,GAAO,YAAA,CAAa,UAAA,IAAc,IAAA;AAAA;EAGlC,KAAA,EAAO,UAAA;EACP,IAAA,EAAM,YAAA,CAAa,UAAA,IAAc,IAAA;AAAA;AAAA,KAGlC,mBAAA,GAAsB,MAAM,SAAS,iBAAA;AAAA,KAErC,kBAAA,WAA6B,MAAA,SAAe,iBAAA,qBAG7C,iBAAA,CAAkB,cAAA,CAAe,UAAA;AAAA,KAGzB,gBAAA,kBAAkC,mBAAA,qBAC7B,QAAA,GAAW,kBAAA,CAAmB,QAAA,CAAS,IAAA;AAAA,KAGnD,uBAAA,GAA0B,iBAAA,UAE7B,MAAA,mBACA,gBAAA;AAAA,KAGG,kBAAA,oBAAsC,iBAAA,aACzC,YAAA,CAAa,UAAA;EAAsB,cAAA,EAAgB,iBAAA;AAAA,IAC/C,IAAA,CAAK,YAAA,CAAa,UAAA;AAAA,KAGnB,kBAAA,oBAAsC,iBAAA,aACzC,cAAA,CAAe,UAAA,UAAoB,gBAAA,gBAC/B,KAAA;;AAvC8D;AAAA;;;;;;;;;;;;;;cAuFvD,IAAA;AAAA,KACR,IAAA,UAAc,IAAI;;;;;;;;;;;;;;;;;;;;;;AA7EoB;AAAA;;iBA8G3B,eAAA,CAAA;EACd,MAAA;EACA;AAAA;EAEA,MAAA,EAAQ,aAAA;EACR,QAAA,EAAU,SAAA;AAAA,gCACX,GAAA,CAAA,OAAA;;;;;;;;;;;;;;iBAmBe,UAAA,CAAA,GAAc,aAAa;;;;AA/HI;AAG/C;;;;;;;;;;;;;;;iBAuJgB,gBAAA,CAAA,GAAoB,oBAAoB;;;AAtJI;AAC1D;;;;;;;;;;;;AAKgB;AAAA;;;;;;;iBAmMF,QAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,OAAA;;;;;;;;;;;;;;;AAjM+B;AAAA;;iBA0NlB,aAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,UAA2B,KAAA,EAAO,OAAA,MAC1C,IAAA,EAAM,iBAAA,CAAkB,KAAA,KAAU,IAAA,IACpC,iBAAA,CAAkB,OAAA;;;;;;;;;;;;;;;AAxNV;AAgDX;;;;AAAmC;AAAC;iBA4NpB,WAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,aAA8B,KAAA,EAAO,OAAA,QAC3C,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;;AA7N3B;AAiCvB;;;;;;;;;;;;;;;;;;iBAsNgB,SAAA,gBAAA,CACd,SAAA,EAAW,iBAAA,WAA4B,KAAA,EAAO,OAAA,QACzC,IAAA,EAAM,iBAAA,CAAkB,KAAA,MAAW,OAAA,CAAQ,OAAA;;AAlNjD;AAmBD;;;;AAA2C;AA2B3C;;;;AAAwD;AAmDxD;;;;;;;;;iBA2IgB,UAAA,kBAA4B,mBAAA,CAAA,CAC1C,OAAA,EAAS,QAAA,GACR,gBAAA,CAAiB,QAAA;;;;;;;;;;;;;;;AA1IV;AAyBV;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+MgB,iBAAA,oBAAqC,uBAAA,CAAA,CACnD,SAAA,EAAW,UAAA,EACX,IAAA,EAAM,kBAAA,CAAmB,UAAA,IAAc,IAAA,EACvC,OAAA;EACE,eAAA;AAAA,IAED,uBAAA,CAAwB,kBAAA,CAAmB,UAAA"}
|
|
@@ -74,7 +74,7 @@ function useSyncore() {
|
|
|
74
74
|
/**
|
|
75
75
|
* Subscribe to the runtime’s lifecycle status.
|
|
76
76
|
*
|
|
77
|
-
* Returns a
|
|
77
|
+
* Returns a SyncoreRuntimeStatus that updates whenever the underlying
|
|
78
78
|
* runtime changes state (e.g. starting, ready, error). Use it to gate your UI
|
|
79
79
|
* on the runtime being ready or to display an error boundary:
|
|
80
80
|
*
|
|
@@ -136,7 +136,7 @@ function useQuery(reference, ...args) {
|
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
138
|
* Subscribe to a reactive Syncore query and return the full
|
|
139
|
-
*
|
|
139
|
+
* SyncoreQueryState including loading, error, and runtime status.
|
|
140
140
|
*
|
|
141
141
|
* Use this instead of {@link useQuery} when you need to:
|
|
142
142
|
* - Differentiate between `undefined` data and an error.
|
|
@@ -239,7 +239,7 @@ function useAction(reference) {
|
|
|
239
239
|
*
|
|
240
240
|
* @param entries - A record of named query requests. Each entry can include
|
|
241
241
|
* `args: skip` to suppress that specific subscription.
|
|
242
|
-
* @returns A record with the same keys, each holding a
|
|
242
|
+
* @returns A record with the same keys, each holding a SyncoreQueryState.
|
|
243
243
|
*/
|
|
244
244
|
function useQueries(entries) {
|
|
245
245
|
const client = useSyncore();
|
|
@@ -307,8 +307,9 @@ function useQueries(entries) {
|
|
|
307
307
|
* `ctx.db.query(…).paginate(paginationOpts)`.
|
|
308
308
|
* @param args - Arguments for the query (excluding
|
|
309
309
|
* `paginationOpts`, which is managed internally), or `skip`.
|
|
310
|
-
* @param options
|
|
311
|
-
*
|
|
310
|
+
* @param options - Pagination options. `initialNumItems` controls the number
|
|
311
|
+
* of items to load on the first page.
|
|
312
|
+
* @returns A UsePaginatedQueryResult with the accumulated results and
|
|
312
313
|
* a `loadMore` callback.
|
|
313
314
|
*/
|
|
314
315
|
function usePaginatedQuery(reference, args, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.tsx"],"sourcesContent":["import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState\n} from \"react\";\nimport type {\n FunctionArgs,\n FunctionReference,\n FunctionResult,\n PaginationOptions,\n PaginationResult,\n SyncoreClient,\n SyncorePaginatedQueryStatus,\n SyncoreQueryState,\n SyncoreRuntimeStatus,\n SyncoreWatch,\n UsePaginatedQueryResult\n} from \"@syncore/core\";\n\ntype ManagedSyncoreWatch<TResult> = SyncoreWatch<TResult> & {\n dispose?: () => void;\n};\n\ntype OptionalArgsTuple<TArgs> =\n Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];\n\ntype QueryRequestInput<\n TReference extends FunctionReference<\"query\"> = FunctionReference<\"query\">\n> = Record<never, never> extends FunctionArgs<TReference>\n ? {\n query: TReference;\n args?: FunctionArgs<TReference> | Skip;\n }\n : {\n query: TReference;\n args: FunctionArgs<TReference> | Skip;\n };\n\ntype QueriesRequestInput = Record<string, QueryRequestInput>;\n\ntype QueryStateForEntry<TEntry> = TEntry extends QueryRequestInput<\n infer TReference\n>\n ? SyncoreQueryState<FunctionResult<TReference>>\n : never;\n\nexport type UseQueriesResult<TEntries extends QueriesRequestInput> = {\n [TKey in keyof TEntries]: QueryStateForEntry<TEntries[TKey]>;\n};\n\ntype PaginatedQueryReference = FunctionReference<\n \"query\",\n Record<string, unknown>,\n PaginationResult<unknown>\n>;\n\ntype PaginatedQueryArgs<TReference extends FunctionReference<\"query\">> =\n FunctionArgs<TReference> extends { paginationOpts: PaginationOptions }\n ? Omit<FunctionArgs<TReference>, \"paginationOpts\">\n : never;\n\ntype PaginatedQueryItem<TReference extends FunctionReference<\"query\">> =\n FunctionResult<TReference> extends PaginationResult<infer TItem>\n ? TItem\n : never;\n\ntype QuerySnapshot<TResult> = {\n data: TResult | undefined;\n error: Error | undefined;\n};\n\ntype NormalizedQueryEntry = {\n key: string;\n referenceName: string;\n args: Record<string, unknown>;\n skipped: boolean;\n};\n\ntype PaginatedQueryInternalState = {\n requestKey: string;\n nextPageKey: number;\n pages: Array<{\n key: string;\n cursor: string | null;\n numItems: number;\n }>;\n};\n\ntype QueryObserverRecord = {\n requestKey: string;\n snapshot: QuerySnapshot<unknown>;\n unsubscribe: () => void;\n watch?: ManagedSyncoreWatch<unknown>;\n};\n\n/**\n * Pass `skip` as the `args` argument to any Syncore React hook to suppress\n * that subscription entirely.\n *\n * Useful when the query arguments depend on state that is not yet available\n * (e.g. a selected item ID) — instead of conditionally calling the hook\n * (which violates the Rules of Hooks), pass `skip` to deactivate it:\n *\n * ```tsx\n * const task = useQuery(api.tasks.get, selectedId ? { id: selectedId } : skip);\n * // task is `undefined` while selectedId is null/undefined\n * ```\n *\n * Skipped queries return `undefined` for `data`, `\"skipped\"` for `status`,\n * and `false` for `isLoading`.\n */\nexport const skip = \"skip\" as const;\ntype Skip = typeof skip;\n\nconst defaultRuntimeStatus: SyncoreRuntimeStatus = {\n kind: \"starting\",\n reason: \"booting\"\n};\n\nconst SyncoreContext = createContext<SyncoreClient | null>(null);\n\n/**\n * Provides a Syncore client to all React descendants via context.\n *\n * Wrap your app (or any subtree that uses Syncore hooks) with\n * `SyncoreProvider`. All `useQuery`, `useMutation`, `useAction`, and\n * `useQueries` calls inside the tree will automatically use the client you\n * supply.\n *\n * ```tsx\n * // For a browser worker setup\n * const client = createBrowserWorkerClient();\n *\n * function App() {\n * return (\n * <SyncoreProvider client={client}>\n * <TaskList />\n * </SyncoreProvider>\n * );\n * }\n * ```\n *\n * For Next.js apps use `SyncoreNextProvider` which also handles service worker\n * and worker URL configuration.\n */\nexport function SyncoreProvider({\n client,\n children\n}: {\n client: SyncoreClient;\n children: ReactNode;\n}) {\n return (\n <SyncoreContext.Provider value={client}>{children}</SyncoreContext.Provider>\n );\n}\n\n/**\n * Returns the active `SyncoreClient` from the nearest {@link SyncoreProvider}\n * in the React tree.\n *\n * Throws if called outside of a `SyncoreProvider`. Prefer the higher-level\n * hooks (`useQuery`, `useMutation`, etc.) for common operations — use\n * `useSyncore` only when you need direct access to the client object.\n *\n * ```ts\n * const client = useSyncore();\n * const tasks = await client.query(api.tasks.list);\n * ```\n */\nexport function useSyncore(): SyncoreClient {\n const client = useContext(SyncoreContext);\n if (!client) {\n throw new Error(\"SyncoreProvider is missing from the React tree.\");\n }\n return client;\n}\n\n/**\n * Subscribe to the runtime’s lifecycle status.\n *\n * Returns a {@link SyncoreRuntimeStatus} that updates whenever the underlying\n * runtime changes state (e.g. starting, ready, error). Use it to gate your UI\n * on the runtime being ready or to display an error boundary:\n *\n * ```tsx\n * function TaskList() {\n * const status = useSyncoreStatus();\n * if (status.kind === \"starting\") return <Spinner />;\n * if (status.kind === \"error\") return <ErrorScreen error={status.error} />;\n * return <Tasks />;\n * }\n * ```\n *\n * Most components do not need this — `useQuery` already incorporates runtime\n * status into the `SyncoreQueryState.runtimeStatus` field.\n */\nexport function useSyncoreStatus(): SyncoreRuntimeStatus {\n const client = useSyncore();\n const watch = useMemo(\n () => client.watchRuntimeStatus() as ManagedSyncoreWatch<SyncoreRuntimeStatus>,\n [client]\n );\n const [status, setStatus] = useState<SyncoreRuntimeStatus>(() =>\n readRuntimeStatusSnapshot(watch)\n );\n\n useEffect(() => {\n const sync = () => {\n setStatus(readRuntimeStatusSnapshot(watch));\n };\n sync();\n return watch.onUpdate(sync);\n }, [watch]);\n\n useEffect(\n () => () => {\n watch.dispose?.();\n },\n [watch]\n );\n\n return status;\n}\n\n/**\n * Subscribe to a reactive Syncore query and return the current data.\n *\n * The component re-renders automatically whenever the query result changes.\n * If the query throws, `useQuery` re-throws the error so a React error\n * boundary can catch it — use {@link useQueryState} if you need to handle\n * errors inline.\n *\n * ```tsx\n * // Basic usage\n * const tasks = useQuery(api.tasks.list);\n *\n * // With arguments\n * const task = useQuery(api.tasks.get, { id: taskId });\n *\n * // Conditionally skip when arguments are not yet available\n * const task = useQuery(api.tasks.get, taskId ? { id: taskId } : skip);\n * ```\n *\n * @param reference - A typed function reference (from the generated `api` object).\n * @param args - The query’s arguments, or `skip` to suppress the subscription.\n * @returns The current query result, or `undefined` while loading.\n */\nexport function useQuery<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs> | [Skip]\n): TResult | undefined {\n const state = useQueryState(reference, ...(args as OptionalArgsTuple<TArgs> | [Skip]));\n if (state.error) {\n throw state.error;\n }\n return state.data;\n}\n\n/**\n * Subscribe to a reactive Syncore query and return the full\n * {@link SyncoreQueryState} including loading, error, and runtime status.\n *\n * Use this instead of {@link useQuery} when you need to:\n * - Differentiate between `undefined` data and an error.\n * - React to `isLoading` / `isError` without relying on error boundaries.\n * - Inspect `runtimeStatus` for the underlying runtime’s health.\n *\n * ```tsx\n * const { data, isLoading, isError, error } = useQueryState(api.tasks.list);\n *\n * if (isLoading) return <Spinner />;\n * if (isError) return <ErrorBanner message={error.message} />;\n * return <TaskList tasks={data} />;\n * ```\n */\nexport function useQueryState<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs> | [Skip]\n): SyncoreQueryState<TResult> {\n const isSkipped = args[0] === skip;\n const client = useSyncore();\n const runtimeStatus = useSyncoreStatus();\n const watch = useManagedQueryWatch(\n client,\n reference,\n isSkipped\n ? undefined\n : normalizeOptionalArgs(args as OptionalArgsTuple<TArgs>),\n isSkipped\n );\n const [snapshot, setSnapshot] = useState<QuerySnapshot<TResult>>(() =>\n isSkipped ? noOpSnapshot : readWatchSnapshot(watch)\n );\n\n useEffect(() => {\n if (isSkipped) {\n setSnapshot(noOpSnapshot);\n return;\n }\n const sync = () => {\n setSnapshot(readWatchSnapshot(watch));\n };\n sync();\n return watch.onUpdate(sync);\n }, [watch, isSkipped]);\n\n return toQueryState(snapshot, runtimeStatus, isSkipped);\n}\n\n/**\n * Returns a stable callback for executing a Syncore mutation.\n *\n * The returned function is type-safe: its parameter types are inferred from\n * the mutation definition and remain stable across re-renders (no need to\n * wrap in `useCallback`).\n *\n * ```tsx\n * const createTask = useMutation(api.tasks.create);\n *\n * return (\n * <button onClick={() => createTask({ title: \"New task\" })}>\n * Add task\n * </button>\n * );\n * ```\n *\n * @param reference - A typed mutation reference from the generated `api` object.\n * @returns A function that, when called, executes the mutation and returns a\n * promise that resolves to the mutation’s return value.\n */\nexport function useMutation<TArgs, TResult>(\n reference: FunctionReference<\"mutation\", TArgs, TResult>\n): (...args: OptionalArgsTuple<TArgs>) => Promise<TResult> {\n const client = useSyncore();\n return (...args) => client.mutation(reference, normalizeOptionalArgs(args));\n}\n\n/**\n * Returns a stable callback for executing a Syncore action.\n *\n * Identical to {@link useMutation} but for actions. Use this when the work you\n * need to do cannot run inside a transaction (external API calls, long-running\n * tasks, etc.).\n *\n * ```tsx\n * const importTasks = useAction(api.tasks.importFromCsv);\n *\n * return (\n * <button onClick={() => importTasks({ url: csvUrl })}>\n * Import\n * </button>\n * );\n * ```\n *\n * @param reference - A typed action reference from the generated `api` object.\n * @returns A function that, when called, executes the action and returns a\n * promise that resolves to the action’s return value.\n */\nexport function useAction<TArgs, TResult>(\n reference: FunctionReference<\"action\", TArgs, TResult>\n): (...args: OptionalArgsTuple<TArgs>) => Promise<TResult> {\n const client = useSyncore();\n return (...args) => client.action(reference, normalizeOptionalArgs(args));\n}\n\n/**\n * Subscribe to multiple Syncore queries simultaneously and receive per-entry\n * state objects in a single hook call.\n *\n * More efficient than calling `useQuery` in a loop when the set of queries is\n * known at component render time. The hook maintains only one subscription per\n * unique `(reference, args)` combination even if entries are duplicated.\n *\n * ```tsx\n * const { header, sidebar } = useQueries({\n * header: { query: api.layout.header },\n * sidebar: { query: api.layout.sidebar, args: { userId } },\n * });\n *\n * if (header.isLoading || sidebar.isLoading) return <Spinner />;\n * ```\n *\n * @param entries - A record of named query requests. Each entry can include\n * `args: skip` to suppress that specific subscription.\n * @returns A record with the same keys, each holding a {@link SyncoreQueryState}.\n */\nexport function useQueries<TEntries extends QueriesRequestInput>(\n entries: TEntries\n): UseQueriesResult<TEntries> {\n const client = useSyncore();\n const runtimeStatus = useSyncoreStatus();\n const entriesKey = stableStringify(\n Object.entries(entries)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => ({\n key,\n referenceName: entry.query.name,\n skipped: entry.args === skip,\n args:\n entry.args === skip\n ? {}\n : normalizeOptionalArgs([entry.args ?? {}] as [] | [unknown])\n }))\n );\n const normalizedEntries = useMemo(\n () => JSON.parse(entriesKey) as NormalizedQueryEntry[],\n [entriesKey]\n );\n const [observer] = useState(() => new ReactQueriesObserver(client));\n const [, setVersion] = useState(0);\n\n if (observer.client !== client) {\n observer.replaceClient(client);\n }\n\n useEffect(() => () => observer.destroy(), [observer]);\n\n useEffect(() => {\n observer.setEntries(normalizedEntries);\n setVersion((value) => value + 1);\n return observer.subscribe(() => {\n setVersion((value) => value + 1);\n });\n }, [normalizedEntries, observer]);\n\n const snapshot = observer.getSnapshot(normalizedEntries);\n\n return useMemo(() => {\n return Object.fromEntries(\n normalizedEntries.map((entry) => [\n entry.key,\n toQueryState(\n snapshot[entry.key] ?? noOpSnapshot,\n runtimeStatus,\n entry.skipped\n )\n ])\n ) as UseQueriesResult<TEntries>;\n }, [normalizedEntries, runtimeStatus, snapshot]);\n}\n\n/**\n * Subscribe to a paginated Syncore query, incrementally loading more pages.\n *\n * The query must accept a `paginationOpts` argument and return a\n * `PaginationResult`. The hook manages cursors automatically — call the\n * returned `loadMore` function to append the next page to the results.\n *\n * ```tsx\n * const { results, status, loadMore, hasMore } = usePaginatedQuery(\n * api.tasks.list,\n * { projectId },\n * { initialNumItems: 20 },\n * );\n *\n * return (\n * <>\n * {results.map((t) => <TaskRow key={t._id} task={t} />)}\n * {hasMore && (\n * <button\n * onClick={() => loadMore(20)}\n * disabled={status === \"loadingMore\"}\n * >\n * Load more\n * </button>\n * )}\n * </>\n * );\n * ```\n *\n * Pass `skip` as `args` to suppress the subscription until arguments are\n * ready.\n *\n * @param reference - A typed query reference whose handler calls\n * `ctx.db.query(…).paginate(paginationOpts)`.\n * @param args - Arguments for the query (excluding\n * `paginationOpts`, which is managed internally), or `skip`.\n * @param options.initialNumItems - Number of items to load on the first page.\n * @returns A {@link UsePaginatedQueryResult} with the accumulated results and\n * a `loadMore` callback.\n */\nexport function usePaginatedQuery<TReference extends PaginatedQueryReference>(\n reference: TReference,\n args: PaginatedQueryArgs<TReference> | Skip,\n options: {\n initialNumItems: number;\n }\n): UsePaginatedQueryResult<PaginatedQueryItem<TReference>> {\n if (\n typeof options.initialNumItems !== \"number\" ||\n options.initialNumItems <= 0\n ) {\n throw new Error(\n `options.initialNumItems must be a positive number. Received ${String(\n options.initialNumItems\n )}.`\n );\n }\n\n const runtimeStatus = useSyncoreStatus();\n const isSkipped = args === skip;\n const normalizedArgs = isSkipped ? {} : (args ?? {});\n const requestKey = stableStringify({\n referenceName: reference.name,\n args: normalizedArgs,\n initialNumItems: options.initialNumItems,\n skipped: isSkipped\n });\n const createInitialState = useMemo(\n () => () =>\n ({\n requestKey,\n nextPageKey: 1,\n pages: isSkipped\n ? []\n : [\n {\n key: \"0\",\n cursor: null,\n numItems: options.initialNumItems\n }\n ]\n }) satisfies PaginatedQueryInternalState,\n [isSkipped, options.initialNumItems, requestKey]\n );\n const [state, setState] = useState<PaginatedQueryInternalState>(\n createInitialState\n );\n\n let currentState = state;\n if (currentState.requestKey !== requestKey) {\n currentState = createInitialState();\n setState(currentState);\n }\n\n const pageQueries = useMemo(() => {\n const requests: Record<string, QueryRequestInput> = {};\n for (const page of currentState.pages) {\n requests[page.key] = {\n query: reference,\n args: {\n ...(normalizedArgs as Record<string, unknown>),\n paginationOpts: {\n cursor: page.cursor,\n numItems: page.numItems\n }\n }\n };\n }\n return requests;\n }, [currentState.pages, normalizedArgs, reference]);\n const pageStates = useQueries(pageQueries);\n\n const derived = useMemo(() => {\n const pages: Array<PaginationResult<PaginatedQueryItem<TReference>>> = [];\n let error: Error | undefined;\n\n for (const page of currentState.pages) {\n const pageState =\n pageStates[page.key as keyof typeof pageStates] as\n | SyncoreQueryState<PaginationResult<PaginatedQueryItem<TReference>>>\n | undefined;\n if (!pageState || pageState.status === \"loading\") {\n break;\n }\n if (pageState.status === \"error\") {\n error = pageState.error;\n break;\n }\n if (pageState.data) {\n pages.push(pageState.data);\n }\n }\n\n const results = pages.flatMap((page) => page.page);\n const lastLoadedPage = pages.at(-1);\n const lastRequestedKey = currentState.pages.at(-1)?.key;\n const lastRequestedState = lastRequestedKey\n ? (pageStates[lastRequestedKey as keyof typeof pageStates] as\n | SyncoreQueryState<PaginationResult<PaginatedQueryItem<TReference>>>\n | undefined)\n : undefined;\n const isLoading = !isSkipped && pages.length === 0 && !error;\n const isLoadingMore =\n currentState.pages.length > pages.length ||\n (!!lastRequestedState && lastRequestedState.status === \"loading\" && pages.length > 0);\n const hasMore = !!lastLoadedPage && !lastLoadedPage.isDone;\n const status: SyncorePaginatedQueryStatus = error\n ? \"error\"\n : isSkipped\n ? \"ready\"\n : isLoading\n ? \"loading\"\n : isLoadingMore\n ? \"loadingMore\"\n : hasMore\n ? \"ready\"\n : \"exhausted\";\n\n return {\n pages,\n results,\n error,\n isLoading,\n isLoadingMore,\n hasMore,\n cursor: lastLoadedPage?.cursor ?? null,\n status\n };\n }, [currentState.pages, isSkipped, pageStates]);\n\n return {\n ...derived,\n runtimeStatus,\n loadMore(numItems = options.initialNumItems) {\n if (\n isSkipped ||\n derived.error ||\n derived.isLoadingMore ||\n !derived.hasMore ||\n !derived.cursor\n ) {\n return;\n }\n\n setState((previous) => ({\n ...previous,\n nextPageKey: previous.nextPageKey + 1,\n pages: [\n ...previous.pages,\n {\n key: String(previous.nextPageKey),\n cursor: derived.cursor,\n numItems\n }\n ]\n }));\n }\n };\n}\n\nconst noOpSnapshot: QuerySnapshot<never> = {\n data: undefined,\n error: undefined\n};\n\nconst noOpWatch: ManagedSyncoreWatch<never> = {\n onUpdate: () => () => undefined,\n localQueryResult: () => undefined,\n localQueryError: () => undefined\n};\n\nfunction useManagedQueryWatch<TArgs, TResult>(\n client: SyncoreClient,\n reference: FunctionReference<\"query\", TArgs, TResult>,\n args?: TArgs,\n isSkipped = false\n): ManagedSyncoreWatch<TResult> {\n const argsKey = isSkipped ? skip : stableStringify(args ?? {});\n const [watch, setWatch] = useState<ManagedSyncoreWatch<TResult>>(\n () => noOpWatch\n );\n\n useEffect(() => {\n if (isSkipped) {\n setWatch(noOpWatch);\n return;\n }\n\n const nextWatch = client.watchQuery(\n reference,\n JSON.parse(argsKey) as TArgs\n ) as ManagedSyncoreWatch<TResult>;\n setWatch(nextWatch);\n\n return () => {\n nextWatch.dispose?.();\n };\n }, [argsKey, client, isSkipped, reference]);\n\n return watch;\n}\n\nfunction normalizeOptionalArgs<TArgs>(\n args: [] | [TArgs] | readonly unknown[]\n): TArgs {\n return (args[0] ?? {}) as TArgs;\n}\n\nfunction readWatchSnapshot<TResult>(\n watch: SyncoreWatch<TResult>\n): QuerySnapshot<TResult> {\n return {\n data: watch.localQueryResult(),\n error: watch.localQueryError()\n };\n}\n\nfunction readQueriesSnapshot(\n records: Array<{\n key: string;\n snapshot: QuerySnapshot<unknown>;\n }>\n): Record<string, QuerySnapshot<unknown>> {\n return Object.fromEntries(\n records.map((entry) => [entry.key, entry.snapshot])\n );\n}\n\nfunction readRuntimeStatusSnapshot(\n watch: SyncoreWatch<SyncoreRuntimeStatus>\n): SyncoreRuntimeStatus {\n return watch.localQueryResult() ?? defaultRuntimeStatus;\n}\n\nfunction toQueryState<TResult>(\n snapshot: QuerySnapshot<TResult>,\n runtimeStatus: SyncoreRuntimeStatus,\n isSkipped: boolean\n): SyncoreQueryState<TResult> {\n if (isSkipped) {\n return {\n data: undefined,\n error: undefined,\n status: \"skipped\",\n runtimeStatus,\n isLoading: false,\n isError: false,\n isReady: false\n };\n }\n\n const status =\n snapshot.error !== undefined\n ? \"error\"\n : snapshot.data === undefined\n ? \"loading\"\n : \"success\";\n\n return {\n data: snapshot.data,\n error: snapshot.error,\n status,\n runtimeStatus,\n isLoading: status === \"loading\",\n isError: status === \"error\",\n isReady: status === \"success\"\n };\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortValue);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, sortValue(nested)])\n );\n }\n return value;\n}\n\nclass ReactQueriesObserver {\n readonly client: SyncoreClient;\n private readonly listeners = new Set<() => void>();\n private readonly records = new Map<string, QueryObserverRecord>();\n\n constructor(client: SyncoreClient) {\n this.client = client;\n }\n\n replaceClient(client: SyncoreClient): void {\n this.destroy();\n (this as { client: SyncoreClient }).client = client;\n }\n\n setEntries(entries: NormalizedQueryEntry[]): void {\n const activeKeys = new Set(entries.map((entry) => entry.key));\n\n for (const entry of entries) {\n const requestKey = `${entry.referenceName}:${stableStringify(entry.args)}:${String(\n entry.skipped\n )}`;\n const current = this.records.get(entry.key);\n if (current?.requestKey === requestKey) {\n continue;\n }\n\n current?.unsubscribe();\n current?.watch?.dispose?.();\n\n if (entry.skipped) {\n this.records.set(entry.key, {\n requestKey,\n snapshot: noOpSnapshot,\n unsubscribe: () => undefined\n });\n continue;\n }\n\n const watch = this.client.watchQuery(\n { kind: \"query\", name: entry.referenceName },\n entry.args\n ) as ManagedSyncoreWatch<unknown>;\n const record: QueryObserverRecord = {\n requestKey,\n snapshot: readWatchSnapshot(watch),\n unsubscribe: () => undefined,\n watch\n };\n record.unsubscribe = watch.onUpdate(() => {\n record.snapshot = readWatchSnapshot(watch);\n this.notify();\n });\n this.records.set(entry.key, record);\n }\n\n for (const [key, record] of this.records.entries()) {\n if (activeKeys.has(key)) {\n continue;\n }\n record.unsubscribe();\n record.watch?.dispose?.();\n this.records.delete(key);\n }\n }\n\n getSnapshot(entries: NormalizedQueryEntry[]): Record<string, QuerySnapshot<unknown>> {\n return readQueriesSnapshot(\n entries.map((entry) => ({\n key: entry.key,\n snapshot: this.records.get(entry.key)?.snapshot ?? noOpSnapshot\n }))\n );\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n destroy(): void {\n for (const record of this.records.values()) {\n record.unsubscribe();\n record.watch?.dispose?.();\n }\n this.records.clear();\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.tsx"],"sourcesContent":["import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState\n} from \"react\";\nimport type {\n FunctionArgs,\n FunctionReference,\n FunctionResult,\n PaginationOptions,\n PaginationResult,\n SyncoreClient,\n SyncorePaginatedQueryStatus,\n SyncoreQueryState,\n SyncoreRuntimeStatus,\n SyncoreWatch,\n UsePaginatedQueryResult\n} from \"@syncore/core\";\n\ntype ManagedSyncoreWatch<TResult> = SyncoreWatch<TResult> & {\n dispose?: () => void;\n};\n\ntype OptionalArgsTuple<TArgs> =\n Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];\n\ntype QueryRequestInput<\n TReference extends FunctionReference<\"query\"> = FunctionReference<\"query\">\n> = Record<never, never> extends FunctionArgs<TReference>\n ? {\n query: TReference;\n args?: FunctionArgs<TReference> | Skip;\n }\n : {\n query: TReference;\n args: FunctionArgs<TReference> | Skip;\n };\n\ntype QueriesRequestInput = Record<string, QueryRequestInput>;\n\ntype QueryStateForEntry<TEntry> = TEntry extends QueryRequestInput<\n infer TReference\n>\n ? SyncoreQueryState<FunctionResult<TReference>>\n : never;\n\nexport type UseQueriesResult<TEntries extends QueriesRequestInput> = {\n [TKey in keyof TEntries]: QueryStateForEntry<TEntries[TKey]>;\n};\n\ntype PaginatedQueryReference = FunctionReference<\n \"query\",\n Record<string, unknown>,\n PaginationResult<unknown>\n>;\n\ntype PaginatedQueryArgs<TReference extends FunctionReference<\"query\">> =\n FunctionArgs<TReference> extends { paginationOpts: PaginationOptions }\n ? Omit<FunctionArgs<TReference>, \"paginationOpts\">\n : never;\n\ntype PaginatedQueryItem<TReference extends FunctionReference<\"query\">> =\n FunctionResult<TReference> extends PaginationResult<infer TItem>\n ? TItem\n : never;\n\ntype QuerySnapshot<TResult> = {\n data: TResult | undefined;\n error: Error | undefined;\n};\n\ntype NormalizedQueryEntry = {\n key: string;\n referenceName: string;\n args: Record<string, unknown>;\n skipped: boolean;\n};\n\ntype PaginatedQueryInternalState = {\n requestKey: string;\n nextPageKey: number;\n pages: Array<{\n key: string;\n cursor: string | null;\n numItems: number;\n }>;\n};\n\ntype QueryObserverRecord = {\n requestKey: string;\n snapshot: QuerySnapshot<unknown>;\n unsubscribe: () => void;\n watch?: ManagedSyncoreWatch<unknown>;\n};\n\n/**\n * Pass `skip` as the `args` argument to any Syncore React hook to suppress\n * that subscription entirely.\n *\n * Useful when the query arguments depend on state that is not yet available\n * (e.g. a selected item ID) — instead of conditionally calling the hook\n * (which violates the Rules of Hooks), pass `skip` to deactivate it:\n *\n * ```tsx\n * const task = useQuery(api.tasks.get, selectedId ? { id: selectedId } : skip);\n * // task is `undefined` while selectedId is null/undefined\n * ```\n *\n * Skipped queries return `undefined` for `data`, `\"skipped\"` for `status`,\n * and `false` for `isLoading`.\n */\nexport const skip = \"skip\" as const;\ntype Skip = typeof skip;\n\nconst defaultRuntimeStatus: SyncoreRuntimeStatus = {\n kind: \"starting\",\n reason: \"booting\"\n};\n\nconst SyncoreContext = createContext<SyncoreClient | null>(null);\n\n/**\n * Provides a Syncore client to all React descendants via context.\n *\n * Wrap your app (or any subtree that uses Syncore hooks) with\n * `SyncoreProvider`. All `useQuery`, `useMutation`, `useAction`, and\n * `useQueries` calls inside the tree will automatically use the client you\n * supply.\n *\n * ```tsx\n * // For a browser worker setup\n * const client = createBrowserWorkerClient();\n *\n * function App() {\n * return (\n * <SyncoreProvider client={client}>\n * <TaskList />\n * </SyncoreProvider>\n * );\n * }\n * ```\n *\n * For Next.js apps use `SyncoreNextProvider` which also handles service worker\n * and worker URL configuration.\n */\nexport function SyncoreProvider({\n client,\n children\n}: {\n client: SyncoreClient;\n children: ReactNode;\n}) {\n return (\n <SyncoreContext.Provider value={client}>{children}</SyncoreContext.Provider>\n );\n}\n\n/**\n * Returns the active `SyncoreClient` from the nearest {@link SyncoreProvider}\n * in the React tree.\n *\n * Throws if called outside of a `SyncoreProvider`. Prefer the higher-level\n * hooks (`useQuery`, `useMutation`, etc.) for common operations — use\n * `useSyncore` only when you need direct access to the client object.\n *\n * ```ts\n * const client = useSyncore();\n * const tasks = await client.query(api.tasks.list);\n * ```\n */\nexport function useSyncore(): SyncoreClient {\n const client = useContext(SyncoreContext);\n if (!client) {\n throw new Error(\"SyncoreProvider is missing from the React tree.\");\n }\n return client;\n}\n\n/**\n * Subscribe to the runtime’s lifecycle status.\n *\n * Returns a SyncoreRuntimeStatus that updates whenever the underlying\n * runtime changes state (e.g. starting, ready, error). Use it to gate your UI\n * on the runtime being ready or to display an error boundary:\n *\n * ```tsx\n * function TaskList() {\n * const status = useSyncoreStatus();\n * if (status.kind === \"starting\") return <Spinner />;\n * if (status.kind === \"error\") return <ErrorScreen error={status.error} />;\n * return <Tasks />;\n * }\n * ```\n *\n * Most components do not need this — `useQuery` already incorporates runtime\n * status into the `SyncoreQueryState.runtimeStatus` field.\n */\nexport function useSyncoreStatus(): SyncoreRuntimeStatus {\n const client = useSyncore();\n const watch = useMemo(\n () => client.watchRuntimeStatus() as ManagedSyncoreWatch<SyncoreRuntimeStatus>,\n [client]\n );\n const [status, setStatus] = useState<SyncoreRuntimeStatus>(() =>\n readRuntimeStatusSnapshot(watch)\n );\n\n useEffect(() => {\n const sync = () => {\n setStatus(readRuntimeStatusSnapshot(watch));\n };\n sync();\n return watch.onUpdate(sync);\n }, [watch]);\n\n useEffect(\n () => () => {\n watch.dispose?.();\n },\n [watch]\n );\n\n return status;\n}\n\n/**\n * Subscribe to a reactive Syncore query and return the current data.\n *\n * The component re-renders automatically whenever the query result changes.\n * If the query throws, `useQuery` re-throws the error so a React error\n * boundary can catch it — use {@link useQueryState} if you need to handle\n * errors inline.\n *\n * ```tsx\n * // Basic usage\n * const tasks = useQuery(api.tasks.list);\n *\n * // With arguments\n * const task = useQuery(api.tasks.get, { id: taskId });\n *\n * // Conditionally skip when arguments are not yet available\n * const task = useQuery(api.tasks.get, taskId ? { id: taskId } : skip);\n * ```\n *\n * @param reference - A typed function reference (from the generated `api` object).\n * @param args - The query’s arguments, or `skip` to suppress the subscription.\n * @returns The current query result, or `undefined` while loading.\n */\nexport function useQuery<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs> | [Skip]\n): TResult | undefined {\n const state = useQueryState(reference, ...(args as OptionalArgsTuple<TArgs> | [Skip]));\n if (state.error) {\n throw state.error;\n }\n return state.data;\n}\n\n/**\n * Subscribe to a reactive Syncore query and return the full\n * SyncoreQueryState including loading, error, and runtime status.\n *\n * Use this instead of {@link useQuery} when you need to:\n * - Differentiate between `undefined` data and an error.\n * - React to `isLoading` / `isError` without relying on error boundaries.\n * - Inspect `runtimeStatus` for the underlying runtime’s health.\n *\n * ```tsx\n * const { data, isLoading, isError, error } = useQueryState(api.tasks.list);\n *\n * if (isLoading) return <Spinner />;\n * if (isError) return <ErrorBanner message={error.message} />;\n * return <TaskList tasks={data} />;\n * ```\n */\nexport function useQueryState<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n ...args: OptionalArgsTuple<TArgs> | [Skip]\n): SyncoreQueryState<TResult> {\n const isSkipped = args[0] === skip;\n const client = useSyncore();\n const runtimeStatus = useSyncoreStatus();\n const watch = useManagedQueryWatch(\n client,\n reference,\n isSkipped\n ? undefined\n : normalizeOptionalArgs(args as OptionalArgsTuple<TArgs>),\n isSkipped\n );\n const [snapshot, setSnapshot] = useState<QuerySnapshot<TResult>>(() =>\n isSkipped ? noOpSnapshot : readWatchSnapshot(watch)\n );\n\n useEffect(() => {\n if (isSkipped) {\n setSnapshot(noOpSnapshot);\n return;\n }\n const sync = () => {\n setSnapshot(readWatchSnapshot(watch));\n };\n sync();\n return watch.onUpdate(sync);\n }, [watch, isSkipped]);\n\n return toQueryState(snapshot, runtimeStatus, isSkipped);\n}\n\n/**\n * Returns a stable callback for executing a Syncore mutation.\n *\n * The returned function is type-safe: its parameter types are inferred from\n * the mutation definition and remain stable across re-renders (no need to\n * wrap in `useCallback`).\n *\n * ```tsx\n * const createTask = useMutation(api.tasks.create);\n *\n * return (\n * <button onClick={() => createTask({ title: \"New task\" })}>\n * Add task\n * </button>\n * );\n * ```\n *\n * @param reference - A typed mutation reference from the generated `api` object.\n * @returns A function that, when called, executes the mutation and returns a\n * promise that resolves to the mutation’s return value.\n */\nexport function useMutation<TArgs, TResult>(\n reference: FunctionReference<\"mutation\", TArgs, TResult>\n): (...args: OptionalArgsTuple<TArgs>) => Promise<TResult> {\n const client = useSyncore();\n return (...args) => client.mutation(reference, normalizeOptionalArgs(args));\n}\n\n/**\n * Returns a stable callback for executing a Syncore action.\n *\n * Identical to {@link useMutation} but for actions. Use this when the work you\n * need to do cannot run inside a transaction (external API calls, long-running\n * tasks, etc.).\n *\n * ```tsx\n * const importTasks = useAction(api.tasks.importFromCsv);\n *\n * return (\n * <button onClick={() => importTasks({ url: csvUrl })}>\n * Import\n * </button>\n * );\n * ```\n *\n * @param reference - A typed action reference from the generated `api` object.\n * @returns A function that, when called, executes the action and returns a\n * promise that resolves to the action’s return value.\n */\nexport function useAction<TArgs, TResult>(\n reference: FunctionReference<\"action\", TArgs, TResult>\n): (...args: OptionalArgsTuple<TArgs>) => Promise<TResult> {\n const client = useSyncore();\n return (...args) => client.action(reference, normalizeOptionalArgs(args));\n}\n\n/**\n * Subscribe to multiple Syncore queries simultaneously and receive per-entry\n * state objects in a single hook call.\n *\n * More efficient than calling `useQuery` in a loop when the set of queries is\n * known at component render time. The hook maintains only one subscription per\n * unique `(reference, args)` combination even if entries are duplicated.\n *\n * ```tsx\n * const { header, sidebar } = useQueries({\n * header: { query: api.layout.header },\n * sidebar: { query: api.layout.sidebar, args: { userId } },\n * });\n *\n * if (header.isLoading || sidebar.isLoading) return <Spinner />;\n * ```\n *\n * @param entries - A record of named query requests. Each entry can include\n * `args: skip` to suppress that specific subscription.\n * @returns A record with the same keys, each holding a SyncoreQueryState.\n */\nexport function useQueries<TEntries extends QueriesRequestInput>(\n entries: TEntries\n): UseQueriesResult<TEntries> {\n const client = useSyncore();\n const runtimeStatus = useSyncoreStatus();\n const entriesKey = stableStringify(\n Object.entries(entries)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => ({\n key,\n referenceName: entry.query.name,\n skipped: entry.args === skip,\n args:\n entry.args === skip\n ? {}\n : normalizeOptionalArgs([entry.args ?? {}] as [] | [unknown])\n }))\n );\n const normalizedEntries = useMemo(\n () => JSON.parse(entriesKey) as NormalizedQueryEntry[],\n [entriesKey]\n );\n const [observer] = useState(() => new ReactQueriesObserver(client));\n const [, setVersion] = useState(0);\n\n if (observer.client !== client) {\n observer.replaceClient(client);\n }\n\n useEffect(() => () => observer.destroy(), [observer]);\n\n useEffect(() => {\n observer.setEntries(normalizedEntries);\n setVersion((value) => value + 1);\n return observer.subscribe(() => {\n setVersion((value) => value + 1);\n });\n }, [normalizedEntries, observer]);\n\n const snapshot = observer.getSnapshot(normalizedEntries);\n\n return useMemo(() => {\n return Object.fromEntries(\n normalizedEntries.map((entry) => [\n entry.key,\n toQueryState(\n snapshot[entry.key] ?? noOpSnapshot,\n runtimeStatus,\n entry.skipped\n )\n ])\n ) as UseQueriesResult<TEntries>;\n }, [normalizedEntries, runtimeStatus, snapshot]);\n}\n\n/**\n * Subscribe to a paginated Syncore query, incrementally loading more pages.\n *\n * The query must accept a `paginationOpts` argument and return a\n * `PaginationResult`. The hook manages cursors automatically — call the\n * returned `loadMore` function to append the next page to the results.\n *\n * ```tsx\n * const { results, status, loadMore, hasMore } = usePaginatedQuery(\n * api.tasks.list,\n * { projectId },\n * { initialNumItems: 20 },\n * );\n *\n * return (\n * <>\n * {results.map((t) => <TaskRow key={t._id} task={t} />)}\n * {hasMore && (\n * <button\n * onClick={() => loadMore(20)}\n * disabled={status === \"loadingMore\"}\n * >\n * Load more\n * </button>\n * )}\n * </>\n * );\n * ```\n *\n * Pass `skip` as `args` to suppress the subscription until arguments are\n * ready.\n *\n * @param reference - A typed query reference whose handler calls\n * `ctx.db.query(…).paginate(paginationOpts)`.\n * @param args - Arguments for the query (excluding\n * `paginationOpts`, which is managed internally), or `skip`.\n * @param options - Pagination options. `initialNumItems` controls the number\n * of items to load on the first page.\n * @returns A UsePaginatedQueryResult with the accumulated results and\n * a `loadMore` callback.\n */\nexport function usePaginatedQuery<TReference extends PaginatedQueryReference>(\n reference: TReference,\n args: PaginatedQueryArgs<TReference> | Skip,\n options: {\n initialNumItems: number;\n }\n): UsePaginatedQueryResult<PaginatedQueryItem<TReference>> {\n if (\n typeof options.initialNumItems !== \"number\" ||\n options.initialNumItems <= 0\n ) {\n throw new Error(\n `options.initialNumItems must be a positive number. Received ${String(\n options.initialNumItems\n )}.`\n );\n }\n\n const runtimeStatus = useSyncoreStatus();\n const isSkipped = args === skip;\n const normalizedArgs = isSkipped ? {} : (args ?? {});\n const requestKey = stableStringify({\n referenceName: reference.name,\n args: normalizedArgs,\n initialNumItems: options.initialNumItems,\n skipped: isSkipped\n });\n const createInitialState = useMemo(\n () => () =>\n ({\n requestKey,\n nextPageKey: 1,\n pages: isSkipped\n ? []\n : [\n {\n key: \"0\",\n cursor: null,\n numItems: options.initialNumItems\n }\n ]\n }) satisfies PaginatedQueryInternalState,\n [isSkipped, options.initialNumItems, requestKey]\n );\n const [state, setState] = useState<PaginatedQueryInternalState>(\n createInitialState\n );\n\n let currentState = state;\n if (currentState.requestKey !== requestKey) {\n currentState = createInitialState();\n setState(currentState);\n }\n\n const pageQueries = useMemo(() => {\n const requests: Record<string, QueryRequestInput> = {};\n for (const page of currentState.pages) {\n requests[page.key] = {\n query: reference,\n args: {\n ...(normalizedArgs as Record<string, unknown>),\n paginationOpts: {\n cursor: page.cursor,\n numItems: page.numItems\n }\n }\n };\n }\n return requests;\n }, [currentState.pages, normalizedArgs, reference]);\n const pageStates = useQueries(pageQueries);\n\n const derived = useMemo(() => {\n const pages: Array<PaginationResult<PaginatedQueryItem<TReference>>> = [];\n let error: Error | undefined;\n\n for (const page of currentState.pages) {\n const pageState =\n pageStates[page.key as keyof typeof pageStates] as\n | SyncoreQueryState<PaginationResult<PaginatedQueryItem<TReference>>>\n | undefined;\n if (!pageState || pageState.status === \"loading\") {\n break;\n }\n if (pageState.status === \"error\") {\n error = pageState.error;\n break;\n }\n if (pageState.data) {\n pages.push(pageState.data);\n }\n }\n\n const results = pages.flatMap((page) => page.page);\n const lastLoadedPage = pages.at(-1);\n const lastRequestedKey = currentState.pages.at(-1)?.key;\n const lastRequestedState = lastRequestedKey\n ? (pageStates[lastRequestedKey as keyof typeof pageStates] as\n | SyncoreQueryState<PaginationResult<PaginatedQueryItem<TReference>>>\n | undefined)\n : undefined;\n const isLoading = !isSkipped && pages.length === 0 && !error;\n const isLoadingMore =\n currentState.pages.length > pages.length ||\n (!!lastRequestedState && lastRequestedState.status === \"loading\" && pages.length > 0);\n const hasMore = !!lastLoadedPage && !lastLoadedPage.isDone;\n const status: SyncorePaginatedQueryStatus = error\n ? \"error\"\n : isSkipped\n ? \"ready\"\n : isLoading\n ? \"loading\"\n : isLoadingMore\n ? \"loadingMore\"\n : hasMore\n ? \"ready\"\n : \"exhausted\";\n\n return {\n pages,\n results,\n error,\n isLoading,\n isLoadingMore,\n hasMore,\n cursor: lastLoadedPage?.cursor ?? null,\n status\n };\n }, [currentState.pages, isSkipped, pageStates]);\n\n return {\n ...derived,\n runtimeStatus,\n loadMore(numItems = options.initialNumItems) {\n if (\n isSkipped ||\n derived.error ||\n derived.isLoadingMore ||\n !derived.hasMore ||\n !derived.cursor\n ) {\n return;\n }\n\n setState((previous) => ({\n ...previous,\n nextPageKey: previous.nextPageKey + 1,\n pages: [\n ...previous.pages,\n {\n key: String(previous.nextPageKey),\n cursor: derived.cursor,\n numItems\n }\n ]\n }));\n }\n };\n}\n\nconst noOpSnapshot: QuerySnapshot<never> = {\n data: undefined,\n error: undefined\n};\n\nconst noOpWatch: ManagedSyncoreWatch<never> = {\n onUpdate: () => () => undefined,\n localQueryResult: () => undefined,\n localQueryError: () => undefined\n};\n\nfunction useManagedQueryWatch<TArgs, TResult>(\n client: SyncoreClient,\n reference: FunctionReference<\"query\", TArgs, TResult>,\n args?: TArgs,\n isSkipped = false\n): ManagedSyncoreWatch<TResult> {\n const argsKey = isSkipped ? skip : stableStringify(args ?? {});\n const [watch, setWatch] = useState<ManagedSyncoreWatch<TResult>>(\n () => noOpWatch\n );\n\n useEffect(() => {\n if (isSkipped) {\n setWatch(noOpWatch);\n return;\n }\n\n const nextWatch = client.watchQuery(\n reference,\n JSON.parse(argsKey) as TArgs\n ) as ManagedSyncoreWatch<TResult>;\n setWatch(nextWatch);\n\n return () => {\n nextWatch.dispose?.();\n };\n }, [argsKey, client, isSkipped, reference]);\n\n return watch;\n}\n\nfunction normalizeOptionalArgs<TArgs>(\n args: [] | [TArgs] | readonly unknown[]\n): TArgs {\n return (args[0] ?? {}) as TArgs;\n}\n\nfunction readWatchSnapshot<TResult>(\n watch: SyncoreWatch<TResult>\n): QuerySnapshot<TResult> {\n return {\n data: watch.localQueryResult(),\n error: watch.localQueryError()\n };\n}\n\nfunction readQueriesSnapshot(\n records: Array<{\n key: string;\n snapshot: QuerySnapshot<unknown>;\n }>\n): Record<string, QuerySnapshot<unknown>> {\n return Object.fromEntries(\n records.map((entry) => [entry.key, entry.snapshot])\n );\n}\n\nfunction readRuntimeStatusSnapshot(\n watch: SyncoreWatch<SyncoreRuntimeStatus>\n): SyncoreRuntimeStatus {\n return watch.localQueryResult() ?? defaultRuntimeStatus;\n}\n\nfunction toQueryState<TResult>(\n snapshot: QuerySnapshot<TResult>,\n runtimeStatus: SyncoreRuntimeStatus,\n isSkipped: boolean\n): SyncoreQueryState<TResult> {\n if (isSkipped) {\n return {\n data: undefined,\n error: undefined,\n status: \"skipped\",\n runtimeStatus,\n isLoading: false,\n isError: false,\n isReady: false\n };\n }\n\n const status =\n snapshot.error !== undefined\n ? \"error\"\n : snapshot.data === undefined\n ? \"loading\"\n : \"success\";\n\n return {\n data: snapshot.data,\n error: snapshot.error,\n status,\n runtimeStatus,\n isLoading: status === \"loading\",\n isError: status === \"error\",\n isReady: status === \"success\"\n };\n}\n\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortValue);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, sortValue(nested)])\n );\n }\n return value;\n}\n\nclass ReactQueriesObserver {\n readonly client: SyncoreClient;\n private readonly listeners = new Set<() => void>();\n private readonly records = new Map<string, QueryObserverRecord>();\n\n constructor(client: SyncoreClient) {\n this.client = client;\n }\n\n replaceClient(client: SyncoreClient): void {\n this.destroy();\n (this as { client: SyncoreClient }).client = client;\n }\n\n setEntries(entries: NormalizedQueryEntry[]): void {\n const activeKeys = new Set(entries.map((entry) => entry.key));\n\n for (const entry of entries) {\n const requestKey = `${entry.referenceName}:${stableStringify(entry.args)}:${String(\n entry.skipped\n )}`;\n const current = this.records.get(entry.key);\n if (current?.requestKey === requestKey) {\n continue;\n }\n\n current?.unsubscribe();\n current?.watch?.dispose?.();\n\n if (entry.skipped) {\n this.records.set(entry.key, {\n requestKey,\n snapshot: noOpSnapshot,\n unsubscribe: () => undefined\n });\n continue;\n }\n\n const watch = this.client.watchQuery(\n { kind: \"query\", name: entry.referenceName },\n entry.args\n ) as ManagedSyncoreWatch<unknown>;\n const record: QueryObserverRecord = {\n requestKey,\n snapshot: readWatchSnapshot(watch),\n unsubscribe: () => undefined,\n watch\n };\n record.unsubscribe = watch.onUpdate(() => {\n record.snapshot = readWatchSnapshot(watch);\n this.notify();\n });\n this.records.set(entry.key, record);\n }\n\n for (const [key, record] of this.records.entries()) {\n if (activeKeys.has(key)) {\n continue;\n }\n record.unsubscribe();\n record.watch?.dispose?.();\n this.records.delete(key);\n }\n }\n\n getSnapshot(entries: NormalizedQueryEntry[]): Record<string, QuerySnapshot<unknown>> {\n return readQueriesSnapshot(\n entries.map((entry) => ({\n key: entry.key,\n snapshot: this.records.get(entry.key)?.snapshot ?? noOpSnapshot\n }))\n );\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n destroy(): void {\n for (const record of this.records.values()) {\n record.unsubscribe();\n record.watch?.dispose?.();\n }\n this.records.clear();\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkHA,MAAa,OAAO;AAGpB,MAAM,uBAA6C;CACjD,MAAM;CACN,QAAQ;AACV;AAEA,MAAM,iBAAiB,cAAoC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;AA0B/D,SAAgB,gBAAgB,EAC9B,QACA,YAIC;CACD,OACE,oBAAC,eAAe,UAAhB;EAAyB,OAAO;EAAS;CAAkC,CAAA;AAE/E;;;;;;;;;;;;;;AAeA,SAAgB,aAA4B;CAC1C,MAAM,SAAS,WAAW,cAAc;CACxC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,iDAAiD;CAEnE,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,mBAAyC;CACvD,MAAM,SAAS,WAAW;CAC1B,MAAM,QAAQ,cACN,OAAO,mBAAmB,GAChC,CAAC,MAAM,CACT;CACA,MAAM,CAAC,QAAQ,aAAa,eAC1B,0BAA0B,KAAK,CACjC;CAEA,gBAAgB;EACd,MAAM,aAAa;GACjB,UAAU,0BAA0B,KAAK,CAAC;EAC5C;EACA,KAAK;EACL,OAAO,MAAM,SAAS,IAAI;CAC5B,GAAG,CAAC,KAAK,CAAC;CAEV,sBACc;EACV,MAAM,UAAU;CAClB,GACA,CAAC,KAAK,CACR;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,SACd,WACA,GAAG,MACkB;CACrB,MAAM,QAAQ,cAAc,WAAW,GAAI,IAA0C;CACrF,IAAI,MAAM,OACR,MAAM,MAAM;CAEd,OAAO,MAAM;AACf;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,cACd,WACA,GAAG,MACyB;CAC5B,MAAM,YAAY,KAAK,OAAO;CAC9B,MAAM,SAAS,WAAW;CAC1B,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,QAAQ,qBACZ,QACA,WACA,YACI,KAAA,IACA,sBAAsB,IAAgC,GAC1D,SACF;CACA,MAAM,CAAC,UAAU,eAAe,eAC9B,YAAY,eAAe,kBAAkB,KAAK,CACpD;CAEA,gBAAgB;EACd,IAAI,WAAW;GACb,YAAY,YAAY;GACxB;EACF;EACA,MAAM,aAAa;GACjB,YAAY,kBAAkB,KAAK,CAAC;EACtC;EACA,KAAK;EACL,OAAO,MAAM,SAAS,IAAI;CAC5B,GAAG,CAAC,OAAO,SAAS,CAAC;CAErB,OAAO,aAAa,UAAU,eAAe,SAAS;AACxD;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,YACd,WACyD;CACzD,MAAM,SAAS,WAAW;CAC1B,QAAQ,GAAG,SAAS,OAAO,SAAS,WAAW,sBAAsB,IAAI,CAAC;AAC5E;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,UACd,WACyD;CACzD,MAAM,SAAS,WAAW;CAC1B,QAAQ,GAAG,SAAS,OAAO,OAAO,WAAW,sBAAsB,IAAI,CAAC;AAC1E;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,WACd,SAC4B;CAC5B,MAAM,SAAS,WAAW;CAC1B,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,aAAa,gBACjB,OAAO,QAAQ,OAAO,EACnB,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,KAAK,CAAC,EACnD,KAAK,CAAC,KAAK,YAAY;EACtB;EACA,eAAe,MAAM,MAAM;EAC3B,SAAS,MAAM,SAAS;EACxB,MACE,MAAM,SAAA,SACF,CAAC,IACD,sBAAsB,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAmB;CAClE,EAAE,CACN;CACA,MAAM,oBAAoB,cAClB,KAAK,MAAM,UAAU,GAC3B,CAAC,UAAU,CACb;CACA,MAAM,CAAC,YAAY,eAAe,IAAI,qBAAqB,MAAM,CAAC;CAClE,MAAM,GAAG,cAAc,SAAS,CAAC;CAEjC,IAAI,SAAS,WAAW,QACtB,SAAS,cAAc,MAAM;CAG/B,sBAAsB,SAAS,QAAQ,GAAG,CAAC,QAAQ,CAAC;CAEpD,gBAAgB;EACd,SAAS,WAAW,iBAAiB;EACrC,YAAY,UAAU,QAAQ,CAAC;EAC/B,OAAO,SAAS,gBAAgB;GAC9B,YAAY,UAAU,QAAQ,CAAC;EACjC,CAAC;CACH,GAAG,CAAC,mBAAmB,QAAQ,CAAC;CAEhC,MAAM,WAAW,SAAS,YAAY,iBAAiB;CAEvD,OAAO,cAAc;EACnB,OAAO,OAAO,YACZ,kBAAkB,KAAK,UAAU,CAC/B,MAAM,KACN,aACE,SAAS,MAAM,QAAQ,cACvB,eACA,MAAM,OACR,CACF,CAAC,CACH;CACF,GAAG;EAAC;EAAmB;EAAe;CAAQ,CAAC;AACjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,SAAgB,kBACd,WACA,MACA,SAGyD;CACzD,IACE,OAAO,QAAQ,oBAAoB,YACnC,QAAQ,mBAAmB,GAE3B,MAAM,IAAI,MACR,+DAA+D,OAC7D,QAAQ,eACV,EAAE,EACJ;CAGF,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,YAAY,SAAS;CAC3B,MAAM,iBAAiB,YAAY,CAAC,IAAK,QAAQ,CAAC;CAClD,MAAM,aAAa,gBAAgB;EACjC,eAAe,UAAU;EACzB,MAAM;EACN,iBAAiB,QAAQ;EACzB,SAAS;CACX,CAAC;CACD,MAAM,qBAAqB,qBAEtB;EACC;EACA,aAAa;EACb,OAAO,YACH,CAAC,IACD,CACE;GACE,KAAK;GACL,QAAQ;GACR,UAAU,QAAQ;EACpB,CACF;CACN,IACF;EAAC;EAAW,QAAQ;EAAiB;CAAU,CACjD;CACA,MAAM,CAAC,OAAO,YAAY,SACxB,kBACF;CAEA,IAAI,eAAe;CACnB,IAAI,aAAa,eAAe,YAAY;EAC1C,eAAe,mBAAmB;EAClC,SAAS,YAAY;CACvB;CAkBA,MAAM,aAAa,WAhBC,cAAc;EAChC,MAAM,WAA8C,CAAC;EACrD,KAAK,MAAM,QAAQ,aAAa,OAC9B,SAAS,KAAK,OAAO;GACnB,OAAO;GACP,MAAM;IACJ,GAAI;IACJ,gBAAgB;KACd,QAAQ,KAAK;KACb,UAAU,KAAK;IACjB;GACF;EACF;EAEF,OAAO;CACT,GAAG;EAAC,aAAa;EAAO;EAAgB;CAAS,CACT,CAAC;CAEzC,MAAM,UAAU,cAAc;EAC5B,MAAM,QAAiE,CAAC;EACxE,IAAI;EAEJ,KAAK,MAAM,QAAQ,aAAa,OAAO;GACrC,MAAM,YACJ,WAAW,KAAK;GAGlB,IAAI,CAAC,aAAa,UAAU,WAAW,WACrC;GAEF,IAAI,UAAU,WAAW,SAAS;IAChC,QAAQ,UAAU;IAClB;GACF;GACA,IAAI,UAAU,MACZ,MAAM,KAAK,UAAU,IAAI;EAE7B;EAEA,MAAM,UAAU,MAAM,SAAS,SAAS,KAAK,IAAI;EACjD,MAAM,iBAAiB,MAAM,GAAG,EAAE;EAClC,MAAM,mBAAmB,aAAa,MAAM,GAAG,EAAE,GAAG;EACpD,MAAM,qBAAqB,mBACtB,WAAW,oBAGZ,KAAA;EACJ,MAAM,YAAY,CAAC,aAAa,MAAM,WAAW,KAAK,CAAC;EACvD,MAAM,gBACJ,aAAa,MAAM,SAAS,MAAM,UACjC,CAAC,CAAC,sBAAsB,mBAAmB,WAAW,aAAa,MAAM,SAAS;EACrF,MAAM,UAAU,CAAC,CAAC,kBAAkB,CAAC,eAAe;EACpD,MAAM,SAAsC,QACxC,UACA,YACE,UACA,YACE,YACA,gBACE,gBACA,UACE,UACA;EAEZ,OAAO;GACL;GACA;GACA;GACA;GACA;GACA;GACA,QAAQ,gBAAgB,UAAU;GAClC;EACF;CACF,GAAG;EAAC,aAAa;EAAO;EAAW;CAAU,CAAC;CAE9C,OAAO;EACL,GAAG;EACH;EACA,SAAS,WAAW,QAAQ,iBAAiB;GAC3C,IACE,aACA,QAAQ,SACR,QAAQ,iBACR,CAAC,QAAQ,WACT,CAAC,QAAQ,QAET;GAGF,UAAU,cAAc;IACtB,GAAG;IACH,aAAa,SAAS,cAAc;IACpC,OAAO,CACL,GAAG,SAAS,OACZ;KACE,KAAK,OAAO,SAAS,WAAW;KAChC,QAAQ,QAAQ;KAChB;IACF,CACF;GACF,EAAE;EACJ;CACF;AACF;AAEA,MAAM,eAAqC;CACzC,MAAM,KAAA;CACN,OAAO,KAAA;AACT;AAEA,MAAM,YAAwC;CAC5C,sBAAsB,KAAA;CACtB,wBAAwB,KAAA;CACxB,uBAAuB,KAAA;AACzB;AAEA,SAAS,qBACP,QACA,WACA,MACA,YAAY,OACkB;CAC9B,MAAM,UAAU,YAAY,OAAO,gBAAgB,QAAQ,CAAC,CAAC;CAC7D,MAAM,CAAC,OAAO,YAAY,eAClB,SACR;CAEA,gBAAgB;EACd,IAAI,WAAW;GACb,SAAS,SAAS;GAClB;EACF;EAEA,MAAM,YAAY,OAAO,WACvB,WACA,KAAK,MAAM,OAAO,CACpB;EACA,SAAS,SAAS;EAElB,aAAa;GACX,UAAU,UAAU;EACtB;CACF,GAAG;EAAC;EAAS;EAAQ;EAAW;CAAS,CAAC;CAE1C,OAAO;AACT;AAEA,SAAS,sBACP,MACO;CACP,OAAQ,KAAK,MAAM,CAAC;AACtB;AAEA,SAAS,kBACP,OACwB;CACxB,OAAO;EACL,MAAM,MAAM,iBAAiB;EAC7B,OAAO,MAAM,gBAAgB;CAC/B;AACF;AAEA,SAAS,oBACP,SAIwC;CACxC,OAAO,OAAO,YACZ,QAAQ,KAAK,UAAU,CAAC,MAAM,KAAK,MAAM,QAAQ,CAAC,CACpD;AACF;AAEA,SAAS,0BACP,OACsB;CACtB,OAAO,MAAM,iBAAiB,KAAK;AACrC;AAEA,SAAS,aACP,UACA,eACA,WAC4B;CAC5B,IAAI,WACF,OAAO;EACL,MAAM,KAAA;EACN,OAAO,KAAA;EACP,QAAQ;EACR;EACA,WAAW;EACX,SAAS;EACT,SAAS;CACX;CAGF,MAAM,SACJ,SAAS,UAAU,KAAA,IACf,UACA,SAAS,SAAS,KAAA,IAChB,YACA;CAER,OAAO;EACL,MAAM,SAAS;EACf,OAAO,SAAS;EAChB;EACA;EACA,WAAW,WAAW;EACtB,SAAS,WAAW;EACpB,SAAS,WAAW;CACtB;AACF;AAEA,SAAS,gBAAgB,OAAwB;CAC/C,OAAO,KAAK,UAAU,UAAU,KAAK,CAAC;AACxC;AAEA,SAAS,UAAU,OAAyB;CAC1C,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,IAAI,SAAS;CAE5B,IAAI,SAAS,OAAO,UAAU,UAC5B,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAgC,EAC5C,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,KAAK,CAAC,EACnD,KAAK,CAAC,KAAK,YAAY,CAAC,KAAK,UAAU,MAAM,CAAC,CAAC,CACpD;CAEF,OAAO;AACT;AAEA,IAAM,uBAAN,MAA2B;CACzB;CACA,4BAA6B,IAAI,IAAgB;CACjD,0BAA2B,IAAI,IAAiC;CAEhE,YAAY,QAAuB;EACjC,KAAK,SAAS;CAChB;CAEA,cAAc,QAA6B;EACzC,KAAK,QAAQ;EACb,KAAoC,SAAS;CAC/C;CAEA,WAAW,SAAuC;EAChD,MAAM,aAAa,IAAI,IAAI,QAAQ,KAAK,UAAU,MAAM,GAAG,CAAC;EAE5D,KAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,aAAa,GAAG,MAAM,cAAc,GAAG,gBAAgB,MAAM,IAAI,EAAE,GAAG,OAC1E,MAAM,OACR;GACA,MAAM,UAAU,KAAK,QAAQ,IAAI,MAAM,GAAG;GAC1C,IAAI,SAAS,eAAe,YAC1B;GAGF,SAAS,YAAY;GACrB,SAAS,OAAO,UAAU;GAE1B,IAAI,MAAM,SAAS;IACjB,KAAK,QAAQ,IAAI,MAAM,KAAK;KAC1B;KACA,UAAU;KACV,mBAAmB,KAAA;IACrB,CAAC;IACD;GACF;GAEA,MAAM,QAAQ,KAAK,OAAO,WACxB;IAAE,MAAM;IAAS,MAAM,MAAM;GAAc,GAC3C,MAAM,IACR;GACA,MAAM,SAA8B;IAClC;IACA,UAAU,kBAAkB,KAAK;IACjC,mBAAmB,KAAA;IACnB;GACF;GACA,OAAO,cAAc,MAAM,eAAe;IACxC,OAAO,WAAW,kBAAkB,KAAK;IACzC,KAAK,OAAO;GACd,CAAC;GACD,KAAK,QAAQ,IAAI,MAAM,KAAK,MAAM;EACpC;EAEA,KAAK,MAAM,CAAC,KAAK,WAAW,KAAK,QAAQ,QAAQ,GAAG;GAClD,IAAI,WAAW,IAAI,GAAG,GACpB;GAEF,OAAO,YAAY;GACnB,OAAO,OAAO,UAAU;GACxB,KAAK,QAAQ,OAAO,GAAG;EACzB;CACF;CAEA,YAAY,SAAyE;EACnF,OAAO,oBACL,QAAQ,KAAK,WAAW;GACtB,KAAK,MAAM;GACX,UAAU,KAAK,QAAQ,IAAI,MAAM,GAAG,GAAG,YAAY;EACrD,EAAE,CACJ;CACF;CAEA,UAAU,UAAkC;EAC1C,KAAK,UAAU,IAAI,QAAQ;EAC3B,aAAa;GACX,KAAK,UAAU,OAAO,QAAQ;EAChC;CACF;CAEA,UAAgB;EACd,KAAK,MAAM,UAAU,KAAK,QAAQ,OAAO,GAAG;GAC1C,OAAO,YAAY;GACnB,OAAO,OAAO,UAAU;EAC1B;EACA,KAAK,QAAQ,MAAM;CACrB;CAEA,SAAuB;EACrB,KAAK,MAAM,YAAY,KAAK,WAC1B,SAAS;CAEb;AACF"}
|
|
@@ -21,7 +21,7 @@ type PaginatedQueryItem<TReference extends FunctionReference<"query">> = Functio
|
|
|
21
21
|
/**
|
|
22
22
|
* The reactive query state shape emitted by Syncore's Svelte store factories.
|
|
23
23
|
*
|
|
24
|
-
* Extends
|
|
24
|
+
* Extends SyncoreQueryState with the same fields (`data`, `error`,
|
|
25
25
|
* `status`, `runtimeStatus`, `isLoading`, `isError`, `isReady`). Returned as
|
|
26
26
|
* the value of stores created by {@link createQueryStore} and
|
|
27
27
|
* {@link createClientQueryStore}.
|
|
@@ -145,7 +145,7 @@ declare function createQueryValueStore<TReference extends FunctionReference<"que
|
|
|
145
145
|
*/
|
|
146
146
|
declare function createClientQueryValueStore<TReference extends FunctionReference<"query">>(client: SyncoreClient, reference: TReference, ...args: OptionalArgsTuple<FunctionArgs<TReference>> | [Skip]): Readable<FunctionResult<TReference> | undefined>;
|
|
147
147
|
/**
|
|
148
|
-
* Create a reactive Svelte store that emits the full
|
|
148
|
+
* Create a reactive Svelte store that emits the full SyncoreQueryState
|
|
149
149
|
* for a query, including `data`, `error`, `status`, and `isPending`.
|
|
150
150
|
*
|
|
151
151
|
* Uses the client from Svelte context (set via {@link setSyncoreClient}).
|
|
@@ -169,7 +169,7 @@ declare function createClientQueryValueStore<TReference extends FunctionReferenc
|
|
|
169
169
|
*/
|
|
170
170
|
declare function createQueryStore<TReference extends FunctionReference<"query">>(reference: TReference, ...args: OptionalArgsTuple<FunctionArgs<TReference>> | [Skip]): Readable<SyncoreQueryStoreState<FunctionResult<TReference>>>;
|
|
171
171
|
/**
|
|
172
|
-
* Create a reactive Svelte store that emits the full
|
|
172
|
+
* Create a reactive Svelte store that emits the full SyncoreQueryState
|
|
173
173
|
* for a query, including `data`, `error`, `status`, and `isPending`.
|
|
174
174
|
*
|
|
175
175
|
* Accepts an explicit `client` instead of reading from Svelte context.
|
|
@@ -216,7 +216,7 @@ declare function createClientQueriesStore<TEntries extends QueriesRequestInput>(
|
|
|
216
216
|
* can implement “Load More” UIs without manual cursor management.
|
|
217
217
|
*
|
|
218
218
|
* The query referenced by `reference` must accept a `paginationOpts`
|
|
219
|
-
* argument and return a
|
|
219
|
+
* argument and return a PaginationResult.
|
|
220
220
|
*
|
|
221
221
|
* ```svelte
|
|
222
222
|
* <script>
|
|
@@ -238,7 +238,8 @@ declare function createClientQueriesStore<TEntries extends QueriesRequestInput>(
|
|
|
238
238
|
*
|
|
239
239
|
* @param reference - A paginated query function reference.
|
|
240
240
|
* @param args - Query arguments excluding `paginationOpts`, or `skip`.
|
|
241
|
-
* @param options
|
|
241
|
+
* @param options - Pagination options. `initialNumItems` controls the number
|
|
242
|
+
* of items to fetch on the first page.
|
|
242
243
|
*/
|
|
243
244
|
declare function createPaginatedQueryStore<TReference extends PaginatedQueryReference>(reference: TReference, args: PaginatedQueryArgs<TReference> | Skip, options: {
|
|
244
245
|
initialNumItems: number;
|
|
@@ -251,7 +252,8 @@ declare function createPaginatedQueryStore<TReference extends PaginatedQueryRefe
|
|
|
251
252
|
* @param client - The Syncore client to query against.
|
|
252
253
|
* @param reference - A paginated query function reference.
|
|
253
254
|
* @param args - Query arguments excluding `paginationOpts`, or `skip`.
|
|
254
|
-
* @param options
|
|
255
|
+
* @param options - Pagination options. `initialNumItems` controls the number
|
|
256
|
+
* of items to fetch on the first page.
|
|
255
257
|
*/
|
|
256
258
|
declare function createClientPaginatedQueryStore<TReference extends PaginatedQueryReference>(client: SyncoreClient, reference: TReference, args: PaginatedQueryArgs<TReference> | Skip, options: {
|
|
257
259
|
initialNumItems: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
|
|
@@ -138,7 +138,7 @@ function createClientQueryValueStore(client, reference, ...args) {
|
|
|
138
138
|
return derived(createClientQueryStore(client, reference, ...args), ($state) => $state.data);
|
|
139
139
|
}
|
|
140
140
|
/**
|
|
141
|
-
* Create a reactive Svelte store that emits the full
|
|
141
|
+
* Create a reactive Svelte store that emits the full SyncoreQueryState
|
|
142
142
|
* for a query, including `data`, `error`, `status`, and `isPending`.
|
|
143
143
|
*
|
|
144
144
|
* Uses the client from Svelte context (set via {@link setSyncoreClient}).
|
|
@@ -164,7 +164,7 @@ function createQueryStore(reference, ...args) {
|
|
|
164
164
|
return createClientQueryStore(getSyncoreClient(), reference, ...args);
|
|
165
165
|
}
|
|
166
166
|
/**
|
|
167
|
-
* Create a reactive Svelte store that emits the full
|
|
167
|
+
* Create a reactive Svelte store that emits the full SyncoreQueryState
|
|
168
168
|
* for a query, including `data`, `error`, `status`, and `isPending`.
|
|
169
169
|
*
|
|
170
170
|
* Accepts an explicit `client` instead of reading from Svelte context.
|
|
@@ -249,7 +249,7 @@ function createClientQueriesStore(client, entries) {
|
|
|
249
249
|
* can implement “Load More” UIs without manual cursor management.
|
|
250
250
|
*
|
|
251
251
|
* The query referenced by `reference` must accept a `paginationOpts`
|
|
252
|
-
* argument and return a
|
|
252
|
+
* argument and return a PaginationResult.
|
|
253
253
|
*
|
|
254
254
|
* ```svelte
|
|
255
255
|
* <script>
|
|
@@ -271,7 +271,8 @@ function createClientQueriesStore(client, entries) {
|
|
|
271
271
|
*
|
|
272
272
|
* @param reference - A paginated query function reference.
|
|
273
273
|
* @param args - Query arguments excluding `paginationOpts`, or `skip`.
|
|
274
|
-
* @param options
|
|
274
|
+
* @param options - Pagination options. `initialNumItems` controls the number
|
|
275
|
+
* of items to fetch on the first page.
|
|
275
276
|
*/
|
|
276
277
|
function createPaginatedQueryStore(reference, args, options) {
|
|
277
278
|
return createClientPaginatedQueryStore(getSyncoreClient(), reference, args, options);
|
|
@@ -284,7 +285,8 @@ function createPaginatedQueryStore(reference, args, options) {
|
|
|
284
285
|
* @param client - The Syncore client to query against.
|
|
285
286
|
* @param reference - A paginated query function reference.
|
|
286
287
|
* @param args - Query arguments excluding `paginationOpts`, or `skip`.
|
|
287
|
-
* @param options
|
|
288
|
+
* @param options - Pagination options. `initialNumItems` controls the number
|
|
289
|
+
* of items to fetch on the first page.
|
|
288
290
|
*/
|
|
289
291
|
function createClientPaginatedQueryStore(client, reference, args, options) {
|
|
290
292
|
if (typeof options.initialNumItems !== "number" || options.initialNumItems <= 0) throw new Error(`options.initialNumItems must be a positive number. Received ${String(options.initialNumItems)}.`);
|