syncorejs 0.2.2 → 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/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +8 -5
- package/dist/_vendor/cli/app.mjs.map +1 -1
- package/dist/_vendor/cli/context.mjs.map +1 -1
- package/dist/_vendor/cli/dev-session.mjs.map +1 -1
- package/dist/_vendor/cli/doctor.mjs.map +1 -1
- package/dist/_vendor/cli/errors.mjs.map +1 -1
- package/dist/_vendor/cli/help.mjs.map +1 -1
- package/dist/_vendor/cli/index.mjs +9 -2
- package/dist/_vendor/cli/index.mjs.map +1 -1
- package/dist/_vendor/cli/messages.mjs.map +1 -1
- package/dist/_vendor/cli/preflight.mjs.map +1 -1
- package/dist/_vendor/cli/project.mjs +20 -20
- package/dist/_vendor/cli/project.mjs.map +1 -1
- package/dist/_vendor/cli/render.mjs.map +1 -1
- package/dist/_vendor/cli/targets.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts +8 -2
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +510 -71
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/devtools-auth.mjs.map +1 -1
- package/dist/_vendor/core/index.d.mts +3 -3
- package/dist/_vendor/core/runtime/components.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/components.mjs.map +1 -1
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +261 -23
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +388 -6
- package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs +72 -1
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/id.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +12 -6
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +123 -20
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +56 -8
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +49 -14
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +4 -7
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +81 -2
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +100 -13
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +42 -7
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +4 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +1100 -12
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +63 -0
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts +2 -0
- package/dist/_vendor/core/transport.d.mts.map +1 -1
- package/dist/_vendor/core/transport.mjs +61 -27
- package/dist/_vendor/core/transport.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +223 -4
- 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/config.d.ts +3 -4
- package/dist/_vendor/next/config.d.ts.map +1 -1
- package/dist/_vendor/next/config.js +37 -19
- package/dist/_vendor/next/config.js.map +1 -1
- package/dist/_vendor/next/index.d.ts +109 -29
- package/dist/_vendor/next/index.d.ts.map +1 -1
- package/dist/_vendor/next/index.js +86 -18
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +146 -27
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +81 -10
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-expo/react.js.map +1 -1
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-node/index.d.mts +174 -9
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +251 -95
- 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-node/ipc.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +41 -0
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
- package/dist/_vendor/platform-web/external-change.js +30 -0
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +312 -37
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +247 -25
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
- package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.js +10 -0
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.d.ts +16 -1
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +41 -3
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +85 -1
- package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
- package/dist/_vendor/platform-web/persistence.js +15 -0
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.d.ts +1 -2
- package/dist/_vendor/platform-web/react.d.ts.map +1 -1
- package/dist/_vendor/platform-web/react.js +11 -5
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/platform-web/sqljs.js +10 -1
- package/dist/_vendor/platform-web/sqljs.js.map +1 -1
- package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
- package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-web/worker.d.ts +60 -9
- package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
- package/dist/_vendor/platform-web/worker.js +37 -4
- package/dist/_vendor/platform-web/worker.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +197 -13
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +209 -17
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/schema/definition.d.ts +129 -0
- package/dist/_vendor/schema/definition.d.ts.map +1 -1
- package/dist/_vendor/schema/definition.js +99 -0
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/planner.d.ts.map +1 -1
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.d.ts +180 -4
- package/dist/_vendor/schema/validators.d.ts.map +1 -1
- package/dist/_vendor/schema/validators.js +35 -1
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +207 -7
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +201 -6
- package/dist/_vendor/svelte/index.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +24 -21
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { FunctionArgs, FunctionArgsFromDefinition, FunctionKindFromDefinition, FunctionReference, FunctionResultFromDefinition, MisfirePolicy, RecurringJobDefinition, RecurringSchedule, SyncoreFunctionKind } from "./functions.mjs";
|
|
2
2
|
import { ResolvedSyncoreComponent, SyncoreComponentFunctionMetadata } from "./components.mjs";
|
|
3
3
|
import { AnyTableDefinition, InferDocument, InferTableInput, SyncoreSchemaDefinition, TableIndexFields, TableIndexNames, TableSearchIndexConfig, TableSearchIndexNames, Validator } from "../../schema/index.d.ts";
|
|
4
|
-
import { SyncoreActiveQueryInfo, SyncoreDevtoolsEvent, SyncoreDevtoolsEventOrigin, SyncoreRuntimeSummary } from "../../devtools-protocol/index.d.ts";
|
|
4
|
+
import { DocumentChangePreview, StorageEntry, SyncoreActiveQueryInfo, SyncoreDevtoolsEvent, SyncoreDevtoolsEventOrigin, SyncoreRuntimeSummary } from "../../devtools-protocol/index.d.ts";
|
|
5
5
|
|
|
6
6
|
//#region src/runtime/runtime.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* A registered Syncore function ready for execution by the runtime.
|
|
9
|
+
*
|
|
10
|
+
* This is the shape stored in the function registry after Syncore processes a
|
|
11
|
+
* definition exported from `syncore/functions/`. You rarely interact with this
|
|
12
|
+
* directly — prefer the generated `api` object and the high-level function
|
|
13
|
+
* builders ({@link query}, {@link mutation}, {@link action}).
|
|
14
|
+
*/
|
|
7
15
|
interface RegisteredSyncoreFunction {
|
|
8
16
|
kind: SyncoreFunctionKind;
|
|
9
17
|
argsValidator: Validator<unknown, unknown, string>;
|
|
@@ -11,19 +19,44 @@ interface RegisteredSyncoreFunction {
|
|
|
11
19
|
handler: RegisteredSyncoreHandler;
|
|
12
20
|
__syncoreComponent?: SyncoreComponentFunctionMetadata;
|
|
13
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* A map from function path strings (e.g. `"tasks/create"`) to their registered
|
|
24
|
+
* definitions.
|
|
25
|
+
*
|
|
26
|
+
* This is the type of the second argument to {@link SyncoreRuntimeOptions} and
|
|
27
|
+
* is produced by `npx syncorejs codegen` in `syncore/_generated/functions.ts`.
|
|
28
|
+
* You should not need to implement this interface manually.
|
|
29
|
+
*/
|
|
14
30
|
interface SyncoreFunctionRegistry {
|
|
15
31
|
readonly [name: string]: RegisteredSyncoreFunction | undefined;
|
|
16
32
|
}
|
|
33
|
+
/** @internal Bivariant function handler type used to avoid TypeScript strictness issues with contravariant function parameters. */
|
|
17
34
|
type RegisteredSyncoreHandler = {
|
|
18
35
|
bivarianceHack(ctx: unknown, args: unknown): unknown;
|
|
19
36
|
}["bivarianceHack"];
|
|
37
|
+
/** A plain JSON-serialisable object. Used for function arguments and scheduler payloads. */
|
|
20
38
|
type JsonObject = Record<string, unknown>;
|
|
39
|
+
/** A SQL-style comparison operator used when building index range queries. */
|
|
21
40
|
type ComparisonOperator = "=" | ">" | ">=" | "<" | "<=";
|
|
41
|
+
/**
|
|
42
|
+
* A single field comparison used inside a query filter or index range.
|
|
43
|
+
*
|
|
44
|
+
* You typically get `QueryCondition` values from the builder callbacks passed
|
|
45
|
+
* to {@link IndexRangeBuilder} or {@link FilterBuilder} — you do not construct
|
|
46
|
+
* them manually.
|
|
47
|
+
*/
|
|
22
48
|
type QueryCondition = {
|
|
23
49
|
field: string;
|
|
24
50
|
operator: ComparisonOperator;
|
|
25
51
|
value: unknown;
|
|
26
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* A composable predicate tree used by {@link FilterBuilder}.
|
|
55
|
+
*
|
|
56
|
+
* Leaf nodes are single {@link QueryCondition} values; branch nodes combine
|
|
57
|
+
* conditions with `and` / `or` semantics. The runtime evaluates these trees
|
|
58
|
+
* against documents during a query scan.
|
|
59
|
+
*/
|
|
27
60
|
type QueryExpression = {
|
|
28
61
|
type: "condition";
|
|
29
62
|
condition: QueryCondition;
|
|
@@ -34,27 +67,71 @@ type QueryExpression = {
|
|
|
34
67
|
type: "or";
|
|
35
68
|
expressions: QueryExpression[];
|
|
36
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* The arguments Syncore passes to its SQLite FTS5 full-text search layer when
|
|
72
|
+
* a query uses `.withSearchIndex()`.
|
|
73
|
+
*/
|
|
37
74
|
type SearchQuery = {
|
|
38
75
|
searchField: string;
|
|
39
76
|
searchText: string;
|
|
40
77
|
filters: QueryCondition[];
|
|
41
78
|
};
|
|
79
|
+
/**
|
|
80
|
+
* Result metadata returned by a single SQL `run` call.
|
|
81
|
+
*
|
|
82
|
+
* Wraps the driver's raw result so callers get consistent change-count and
|
|
83
|
+
* last-insert-rowid values regardless of the underlying SQLite binding.
|
|
84
|
+
*/
|
|
42
85
|
interface RunResult {
|
|
86
|
+
/** Number of rows affected by the statement. */
|
|
43
87
|
changes: number;
|
|
88
|
+
/** The rowid of the last inserted row, if applicable. */
|
|
44
89
|
lastInsertRowid?: number | string;
|
|
45
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Describes an optional runtime capability that functions can read from `ctx.capabilities`.
|
|
93
|
+
*
|
|
94
|
+
* Capabilities let platform adapters expose platform-specific services (e.g.
|
|
95
|
+
* push notifications, biometrics) to Syncore functions in a portable way. The
|
|
96
|
+
* runtime validates capabilities against their descriptors at start-up.
|
|
97
|
+
*/
|
|
46
98
|
interface CapabilityDescriptor {
|
|
99
|
+
/** Unique capability name. Must match the key used in `SyncoreCapabilities`. */
|
|
47
100
|
name: string;
|
|
101
|
+
/** Semantic version number for the capability’s interface contract. */
|
|
48
102
|
version: number;
|
|
103
|
+
/** Optional feature flags exposed by this capability. */
|
|
49
104
|
features?: string[];
|
|
105
|
+
/** Arbitrary metadata for introspection or devtools display. */
|
|
50
106
|
metadata?: Record<string, unknown>;
|
|
107
|
+
/**
|
|
108
|
+
* When `true`, the runtime starts even if the capability is absent. Useful
|
|
109
|
+
* for progressively-enhanced features that degrade gracefully.
|
|
110
|
+
*/
|
|
51
111
|
optional?: boolean;
|
|
52
112
|
}
|
|
53
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Identifies a subset of the runtime state that a query depends on or that a
|
|
115
|
+
* mutation has changed.
|
|
116
|
+
*
|
|
117
|
+
* The reactivity engine uses impact scopes to efficiently determine which
|
|
118
|
+
* active queries need to be re-executed after a mutation commits. Scopes are
|
|
119
|
+
* additive: a query subscribed to `"table:tasks"` will be invalidated by any
|
|
120
|
+
* mutation that writes to the `tasks` table.
|
|
121
|
+
*
|
|
122
|
+
* - `"runtime.summary"` / `"runtime.activeQueries"` / `"schema.tables"` /
|
|
123
|
+
* `"scheduler.jobs"` / `"storage.objects"` - runtime-level state consumed by devtools.
|
|
124
|
+
* - `table:${string}` - every document in a specific table.
|
|
125
|
+
* - `row:${string}:${string}` - a single document (table + id).
|
|
126
|
+
* - `storage:${string}` - a specific storage object.
|
|
127
|
+
*/
|
|
128
|
+
type ImpactScope = "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | "storage.objects" | `table:${string}` | `row:${string}:${string}` | `storage:${string}`;
|
|
129
|
+
/** A frozen set of {@link ImpactScope} values. */
|
|
54
130
|
type ImpactSet = ReadonlySet<ImpactScope>;
|
|
55
131
|
interface ExecutionResult<TResult = unknown> {
|
|
56
132
|
result: TResult;
|
|
57
133
|
changedTables: Set<string>;
|
|
134
|
+
documentChanges: DocumentChangePreview[];
|
|
58
135
|
storageChanges: Array<{
|
|
59
136
|
storageId: string;
|
|
60
137
|
reason: Extract<SyncoreExternalChangeReason, "storage-put" | "storage-delete">;
|
|
@@ -67,32 +144,134 @@ interface ExecutionResult<TResult = unknown> {
|
|
|
67
144
|
changedScopes: ImpactScope[];
|
|
68
145
|
}>;
|
|
69
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Low-level interface that Syncore uses to communicate with a SQLite database.
|
|
149
|
+
*
|
|
150
|
+
* The runtime ships concrete implementations for every supported environment
|
|
151
|
+
* (`NodeSqliteDriver`, `SqlJsDriver`, `ExpoSqliteDriver`). Implement this
|
|
152
|
+
* interface only if you need to integrate a custom SQLite binding.
|
|
153
|
+
*
|
|
154
|
+
* All methods must be safe to call concurrently — the runtime serialises
|
|
155
|
+
* concurrent writes through the driver’s own transaction mechanism.
|
|
156
|
+
*/
|
|
70
157
|
interface SyncoreSqlDriver {
|
|
158
|
+
/**
|
|
159
|
+
* Execute one or more SQL statements that produce no result rows (e.g.
|
|
160
|
+
* `CREATE TABLE`, `PRAGMA journal_mode = WAL`).
|
|
161
|
+
*/
|
|
71
162
|
exec(sql: string): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Execute a single parameterised statement and return change metadata.
|
|
165
|
+
* Typically used for `INSERT`, `UPDATE`, and `DELETE`.
|
|
166
|
+
*/
|
|
72
167
|
run(sql: string, params?: unknown[]): Promise<RunResult>;
|
|
168
|
+
/**
|
|
169
|
+
* Execute a query and return the first row, or `undefined` if there are no
|
|
170
|
+
* results. Useful for `SELECT … LIMIT 1` lookups.
|
|
171
|
+
*/
|
|
73
172
|
get<T>(sql: string, params?: unknown[]): Promise<T | undefined>;
|
|
173
|
+
/**
|
|
174
|
+
* Execute a query and return all matching rows as an array. Returns an empty
|
|
175
|
+
* array when there are no results.
|
|
176
|
+
*/
|
|
74
177
|
all<T>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
178
|
+
/**
|
|
179
|
+
* Run `callback` inside an atomic SQLite transaction.
|
|
180
|
+
*
|
|
181
|
+
* If the callback throws, the transaction is rolled back automatically.
|
|
182
|
+
* Implementations should support nested calls by using `SAVEPOINT`.
|
|
183
|
+
*/
|
|
75
184
|
withTransaction<T>(callback: () => Promise<T>): Promise<T>;
|
|
185
|
+
/**
|
|
186
|
+
* Run `callback` inside a named SQLite savepoint, allowing partial rollback
|
|
187
|
+
* within an outer transaction.
|
|
188
|
+
*/
|
|
76
189
|
withSavepoint<T>(name: string, callback: () => Promise<T>): Promise<T>;
|
|
190
|
+
/**
|
|
191
|
+
* Release the underlying database handle. Called by the runtime during
|
|
192
|
+
* shutdown. Implementations that hold no persistent resources may omit this.
|
|
193
|
+
*/
|
|
77
194
|
close?(): Promise<void>;
|
|
78
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Identifies which category of local state an external change event affects.
|
|
198
|
+
*
|
|
199
|
+
* - `"database"` — One or more SQLite tables were written by an external
|
|
200
|
+
* source (e.g. another Syncore instance sharing the same database file).
|
|
201
|
+
* - `"storage"` — One or more blob/file storage objects were added or removed.
|
|
202
|
+
* - `"all"` — Both the database and storage should be treated as changed.
|
|
203
|
+
*/
|
|
79
204
|
type SyncoreExternalChangeScope = "database" | "storage" | "all";
|
|
205
|
+
/**
|
|
206
|
+
* Why an external change event was emitted.
|
|
207
|
+
*
|
|
208
|
+
* - `"commit"` — A write transaction was committed by another runtime instance.
|
|
209
|
+
* - `"storage-put"` — A new storage object was written.
|
|
210
|
+
* - `"storage-delete"` — A storage object was removed.
|
|
211
|
+
* - `"reconcile"` — The runtime is re-synchronising with the underlying store
|
|
212
|
+
* after a reconnect or restart.
|
|
213
|
+
*/
|
|
80
214
|
type SyncoreExternalChangeReason = "commit" | "storage-put" | "storage-delete" | "reconcile";
|
|
215
|
+
/**
|
|
216
|
+
* A message that notifies a Syncore runtime that state has changed in a source
|
|
217
|
+
* it does not own — for example, a write made by a shared Node process that
|
|
218
|
+
* the browser tab needs to reflect.
|
|
219
|
+
*
|
|
220
|
+
* The runtime subscribes to these events through a
|
|
221
|
+
* {@link SyncoreExternalChangeSignal} and uses them to invalidate and refresh
|
|
222
|
+
* affected queries without polling.
|
|
223
|
+
*/
|
|
81
224
|
interface SyncoreExternalChangeEvent {
|
|
225
|
+
/** Identifies the runtime instance that published this event. */
|
|
82
226
|
sourceId: string;
|
|
227
|
+
/** Which category of state changed. */
|
|
83
228
|
scope: SyncoreExternalChangeScope;
|
|
229
|
+
/** Why the change occurred. */
|
|
84
230
|
reason: SyncoreExternalChangeReason;
|
|
231
|
+
/** Unix timestamp (milliseconds) when the change was published. */
|
|
85
232
|
timestamp: number;
|
|
233
|
+
/** Optional opaque string used to detect duplicate or out-of-order events. */
|
|
86
234
|
revision?: string;
|
|
235
|
+
/** Specific impact scopes that were affected (subset of `scope`). */
|
|
87
236
|
changedScopes?: ImpactScope[];
|
|
237
|
+
/** Table names that were written to, when `scope` includes `"database"`. */
|
|
88
238
|
changedTables?: string[];
|
|
239
|
+
/** Storage object IDs that were affected, when `scope` includes `"storage"`. */
|
|
89
240
|
storageIds?: string[];
|
|
90
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* A pub/sub channel for cross-instance change notifications.
|
|
244
|
+
*
|
|
245
|
+
* Provide an implementation to `SyncoreRuntimeOptions.externalChangeSignal`
|
|
246
|
+
* when multiple Syncore runtimes share the same underlying database (e.g. an
|
|
247
|
+
* Electron main process and renderer, or multiple browser tabs). The runtime
|
|
248
|
+
* will publish events after its own commits and react to events published by
|
|
249
|
+
* other instances.
|
|
250
|
+
*
|
|
251
|
+
* Platform adapters ship ready-made implementations:
|
|
252
|
+
* - `BroadcastChannelExternalChangeSignal` (browser, shared workers)
|
|
253
|
+
* - Node IPC signal (Electron main ↔ renderer)
|
|
254
|
+
*/
|
|
91
255
|
interface SyncoreExternalChangeSignal {
|
|
256
|
+
/**
|
|
257
|
+
* Register a listener for incoming change events.
|
|
258
|
+
* @returns A cleanup function that removes the listener when called.
|
|
259
|
+
*/
|
|
92
260
|
subscribe(listener: (event: SyncoreExternalChangeEvent) => void): () => void;
|
|
261
|
+
/** Publish an outgoing change event to other subscribers. */
|
|
93
262
|
publish(event: SyncoreExternalChangeEvent): void | Promise<void>;
|
|
263
|
+
/** Optional cleanup called when the runtime shuts down. */
|
|
94
264
|
close?(): void | Promise<void>;
|
|
95
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* Applies an incoming {@link SyncoreExternalChangeEvent} to a local SQL
|
|
268
|
+
* driver, reconciling the local state with a remote source.
|
|
269
|
+
*
|
|
270
|
+
* Typically provided by the same adapter that supplies
|
|
271
|
+
* {@link SyncoreExternalChangeSignal} (e.g. `SqlJsExternalChangeApplier` for
|
|
272
|
+
* browser runtimes). Only necessary when the local driver needs to pull in
|
|
273
|
+
* changes made to the database file on disk by another process.
|
|
274
|
+
*/
|
|
96
275
|
interface SyncoreExternalChangeApplier {
|
|
97
276
|
applyExternalChange(event: SyncoreExternalChangeEvent): Promise<{
|
|
98
277
|
databaseChanged: boolean;
|
|
@@ -102,30 +281,128 @@ interface SyncoreExternalChangeApplier {
|
|
|
102
281
|
}
|
|
103
282
|
/**
|
|
104
283
|
* The payload used when writing a new object through Syncore storage APIs.
|
|
284
|
+
*
|
|
285
|
+
* Pass this to `ctx.storage.put()` inside a mutation or action to persist a
|
|
286
|
+
* binary blob alongside your database documents.
|
|
287
|
+
*
|
|
288
|
+
* ```ts
|
|
289
|
+
* const id = await ctx.storage.put({
|
|
290
|
+
* data: new Uint8Array(imageBytes),
|
|
291
|
+
* contentType: "image/png",
|
|
292
|
+
* fileName: "avatar.png",
|
|
293
|
+
* });
|
|
294
|
+
* // Store `id` in the database to reference the object later.
|
|
295
|
+
* ```
|
|
105
296
|
*/
|
|
106
297
|
interface StorageWriteInput {
|
|
298
|
+
/**
|
|
299
|
+
* The raw data to store. Accepts `Uint8Array`, `ArrayBuffer`, or a UTF-8
|
|
300
|
+
* string (the string is encoded to bytes automatically).
|
|
301
|
+
*/
|
|
107
302
|
data: Uint8Array | ArrayBuffer | string;
|
|
303
|
+
/**
|
|
304
|
+
* MIME type hint stored alongside the object (e.g. `"image/png"`,
|
|
305
|
+
* `"application/pdf"`). Not validated or enforced by Syncore; purely
|
|
306
|
+
* informational for downstream consumers.
|
|
307
|
+
*/
|
|
108
308
|
contentType?: string;
|
|
309
|
+
/**
|
|
310
|
+
* Optional human-readable filename hint. Stored as metadata and surfaced in
|
|
311
|
+
* devtools but not used for addressing the object (the auto-generated `id` is
|
|
312
|
+
* used for that).
|
|
313
|
+
*/
|
|
109
314
|
fileName?: string;
|
|
110
315
|
}
|
|
111
316
|
/**
|
|
112
317
|
* Metadata describing a stored object managed by the Syncore storage adapter.
|
|
318
|
+
*
|
|
319
|
+
* Returned by `ctx.storage.get()` and `SyncoreStorageAdapter.list()`. The
|
|
320
|
+
* `id` field is the opaque string you store in the database to reference this
|
|
321
|
+
* object; use it with `ctx.storage.read()` to fetch the bytes.
|
|
113
322
|
*/
|
|
114
323
|
interface StorageObject {
|
|
324
|
+
/** Opaque identifier. Store this in a database document to reference the object. */
|
|
115
325
|
id: string;
|
|
326
|
+
/** Absolute path or key used by the storage backend (filesystem path, OPFS key, etc.). */
|
|
116
327
|
path: string;
|
|
328
|
+
/** Size of the stored data in bytes. */
|
|
117
329
|
size: number;
|
|
330
|
+
/** MIME type provided at write time, or `null` if none was specified. */
|
|
118
331
|
contentType: string | null;
|
|
119
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Low-level interface for persisting and retrieving binary blobs alongside the
|
|
335
|
+
* Syncore database.
|
|
336
|
+
*
|
|
337
|
+
* The runtime ships concrete implementations for every supported environment
|
|
338
|
+
* (`NodeFileStorageAdapter`, `BrowserFileStorageAdapter`,
|
|
339
|
+
* `ExpoFileStorageAdapter`). Implement this interface only if you need a custom
|
|
340
|
+
* storage backend (e.g. an in-memory store for tests or an S3-compatible
|
|
341
|
+
* remote).
|
|
342
|
+
*/
|
|
120
343
|
interface SyncoreStorageAdapter {
|
|
344
|
+
/**
|
|
345
|
+
* Write a blob and return its metadata.
|
|
346
|
+
*
|
|
347
|
+
* @param id - The opaque identifier Syncore assigns to this object. Use
|
|
348
|
+
* the same value to retrieve or delete the object later.
|
|
349
|
+
* @param input - The data and optional metadata to persist.
|
|
350
|
+
*/
|
|
121
351
|
put(id: string, input: StorageWriteInput): Promise<StorageObject>;
|
|
352
|
+
/**
|
|
353
|
+
* Return the metadata for a stored object, or `null` if it does not exist.
|
|
354
|
+
* Does **not** return the raw bytes — use {@link read} for that.
|
|
355
|
+
*/
|
|
122
356
|
get(id: string): Promise<StorageObject | null>;
|
|
357
|
+
/**
|
|
358
|
+
* Return the raw bytes of a stored object, or `null` if it does not exist.
|
|
359
|
+
*/
|
|
123
360
|
read(id: string): Promise<Uint8Array | null>;
|
|
361
|
+
/**
|
|
362
|
+
* Return a byte range for a stored object, or `null` if it does not exist.
|
|
363
|
+
*
|
|
364
|
+
* Adapters that can seek without loading the whole object should implement
|
|
365
|
+
* this so devtools preview and download endpoints can stream large files.
|
|
366
|
+
*/
|
|
367
|
+
readRange?(id: string, offset: number, length: number): Promise<Uint8Array | null>;
|
|
368
|
+
/**
|
|
369
|
+
* Return `false` when `readRange` is intentionally unavailable for this
|
|
370
|
+
* adapter instance.
|
|
371
|
+
*/
|
|
372
|
+
supportsRange?(): boolean;
|
|
373
|
+
/**
|
|
374
|
+
* Permanently remove a stored object. A no-op if the object does not exist.
|
|
375
|
+
*/
|
|
124
376
|
delete(id: string): Promise<void>;
|
|
377
|
+
/**
|
|
378
|
+
* Enumerate all stored objects. Used by devtools and migration tooling.
|
|
379
|
+
* Optional — omit for backends that don’t support listing.
|
|
380
|
+
*/
|
|
125
381
|
list?(): Promise<StorageObject[]>;
|
|
126
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* Receives structured devtools events emitted by the runtime.
|
|
385
|
+
*
|
|
386
|
+
* In development the platform adapters automatically connect a WebSocket sink
|
|
387
|
+
* that forwards events to the Syncore devtools dashboard. You can also supply
|
|
388
|
+
* a custom sink for testing, logging, or building your own observability layer:
|
|
389
|
+
*
|
|
390
|
+
* ```ts
|
|
391
|
+
* const sink: DevtoolsSink = {
|
|
392
|
+
* emit(event) { console.log("[syncore]", event.type); },
|
|
393
|
+
* };
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* Pass `devtools: false` to the runtime options to disable devtools entirely
|
|
397
|
+
* (recommended for production builds).
|
|
398
|
+
*/
|
|
127
399
|
interface DevtoolsSink {
|
|
400
|
+
/** Called synchronously every time the runtime emits a new event. */
|
|
128
401
|
emit(event: SyncoreDevtoolsEvent): void;
|
|
402
|
+
/**
|
|
403
|
+
* Optional hook called once after the runtime is constructed so the sink can
|
|
404
|
+
* hold a reference to it (e.g. to call `runtime.getAdmin()`).
|
|
405
|
+
*/
|
|
129
406
|
attachRuntime?(runtime: SyncoreRuntime<SyncoreDataModel>): void;
|
|
130
407
|
}
|
|
131
408
|
interface DevtoolsLiveQuerySnapshot {
|
|
@@ -150,65 +427,314 @@ interface DevtoolsLiveQuerySnapshot {
|
|
|
150
427
|
documentCount: number;
|
|
151
428
|
}>;
|
|
152
429
|
}
|
|
153
|
-
type DevtoolsLiveQueryScope = "all" | "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | `table:${string}` | `storage:${string}`;
|
|
430
|
+
type DevtoolsLiveQueryScope = "all" | "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | "storage.objects" | `table:${string}` | `storage:${string}`;
|
|
431
|
+
/**
|
|
432
|
+
* Configuration for the Syncore built-in scheduler.
|
|
433
|
+
*
|
|
434
|
+
* Pass this to `SyncoreRuntimeOptions.scheduler` to enable background job
|
|
435
|
+
* processing. The scheduler polls for pending one-off jobs (created via
|
|
436
|
+
* `ctx.scheduler.runAfter` / `ctx.scheduler.runAt`) and for recurring jobs
|
|
437
|
+
* defined with {@link CronJobs}.
|
|
438
|
+
*
|
|
439
|
+
* ```ts
|
|
440
|
+
* import crons from "./syncore/crons";
|
|
441
|
+
*
|
|
442
|
+
* createNodeSyncoreRuntime({
|
|
443
|
+
* ...,
|
|
444
|
+
* scheduler: {
|
|
445
|
+
* pollIntervalMs: 500,
|
|
446
|
+
* recurringJobs: crons.jobs,
|
|
447
|
+
* },
|
|
448
|
+
* });
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
154
451
|
interface SchedulerOptions {
|
|
452
|
+
/**
|
|
453
|
+
* How often the scheduler checks for jobs that are due, in milliseconds.
|
|
454
|
+
* Defaults to `1000` (1 second). Lower values increase responsiveness at
|
|
455
|
+
* the cost of more frequent SQLite reads.
|
|
456
|
+
*/
|
|
155
457
|
pollIntervalMs?: number;
|
|
458
|
+
/**
|
|
459
|
+
* Static list of recurring job definitions to register when the runtime
|
|
460
|
+
* starts. Build this with the {@link CronJobs} helper and a call to
|
|
461
|
+
* {@link cronJobs}.
|
|
462
|
+
*/
|
|
156
463
|
recurringJobs?: RecurringJobDefinition[];
|
|
157
464
|
}
|
|
158
465
|
type SyncoreResolvedComponents = readonly ResolvedSyncoreComponent[];
|
|
159
466
|
interface UpdateScheduledJobOptions {
|
|
160
467
|
id: string;
|
|
161
|
-
schedule
|
|
468
|
+
schedule?: RecurringSchedule;
|
|
162
469
|
args: JsonObject;
|
|
163
|
-
misfirePolicy
|
|
470
|
+
misfirePolicy?: MisfirePolicy;
|
|
164
471
|
runAt?: number;
|
|
165
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* An open-ended bag of platform-specific capabilities exposed to Syncore
|
|
475
|
+
* function handlers via `ctx.capabilities`.
|
|
476
|
+
*
|
|
477
|
+
* Use capabilities to inject platform services (push notifications, camera
|
|
478
|
+
* access, native storage, etc.) that should be available inside your
|
|
479
|
+
* functions without hard-coding platform imports:
|
|
480
|
+
*
|
|
481
|
+
* ```ts
|
|
482
|
+
* // Runtime setup (platform-specific)
|
|
483
|
+
* createExpoSyncoreRuntime({
|
|
484
|
+
* ...,
|
|
485
|
+
* capabilities: { pushNotifications: Notifications },
|
|
486
|
+
* });
|
|
487
|
+
*
|
|
488
|
+
* // Inside a mutation
|
|
489
|
+
* export const notify = mutation({
|
|
490
|
+
* args: { message: s.string() },
|
|
491
|
+
* handler: async (ctx, { message }) => {
|
|
492
|
+
* await ctx.capabilities?.pushNotifications?.scheduleAsync({ body: message });
|
|
493
|
+
* },
|
|
494
|
+
* });
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
166
497
|
interface SyncoreCapabilities {
|
|
167
498
|
[name: string]: unknown;
|
|
168
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* The typed data model that backs a Syncore runtime.
|
|
502
|
+
*
|
|
503
|
+
* `SyncoreDataModel` is the shape of the value returned by
|
|
504
|
+
* {@link defineSchema}. It is the type parameter you see on
|
|
505
|
+
* {@link SyncoreRuntime}, {@link QueryCtx}, {@link MutationCtx}, and the
|
|
506
|
+
* generated server context types. Application code typically gets this from
|
|
507
|
+
* the schema file rather than constructing it directly:
|
|
508
|
+
*
|
|
509
|
+
* ```ts
|
|
510
|
+
* import schema from "../syncore/schema";
|
|
511
|
+
* type MySchema = typeof schema;
|
|
512
|
+
* ```
|
|
513
|
+
*/
|
|
169
514
|
interface SyncoreDataModel<TTables extends SyncoreSchemaDefinition = SyncoreSchemaDefinition> {
|
|
170
515
|
readonly tables: TTables;
|
|
171
516
|
getTable(tableName: Extract<keyof TTables, string>): TTables[Extract<keyof TTables, string>];
|
|
172
517
|
tableNames(): Array<Extract<keyof TTables, string>>;
|
|
173
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* Low-level options for constructing a {@link SyncoreRuntime} directly.
|
|
521
|
+
*
|
|
522
|
+
* Most applications should use a platform-specific factory function instead
|
|
523
|
+
* (`createNodeSyncoreRuntime`, `createWebSyncoreRuntime`,
|
|
524
|
+
* `createExpoSyncoreRuntime`, etc.), which fill in sensible defaults for the
|
|
525
|
+
* driver, storage adapter, and devtools connection.
|
|
526
|
+
*
|
|
527
|
+
* Only reach for `SyncoreRuntimeOptions` when you need full control over the
|
|
528
|
+
* underlying SQLite driver or storage backend.
|
|
529
|
+
*/
|
|
174
530
|
interface SyncoreRuntimeOptions<TSchema extends SyncoreDataModel> {
|
|
531
|
+
/** The data model that defines the available tables, indexes, and schemas. */
|
|
175
532
|
schema: TSchema;
|
|
533
|
+
/**
|
|
534
|
+
* The registered functions Syncore can invoke. In practice this is always
|
|
535
|
+
* the generated `functions` export from `syncore/_generated/functions.ts`.
|
|
536
|
+
*/
|
|
176
537
|
functions: SyncoreFunctionRegistry;
|
|
538
|
+
/**
|
|
539
|
+
* Resolved Syncore component instances to mount alongside the root app
|
|
540
|
+
* functions. Only required when your app installs Syncore components.
|
|
541
|
+
*/
|
|
177
542
|
components?: SyncoreResolvedComponents;
|
|
543
|
+
/**
|
|
544
|
+
* The SQLite driver Syncore will use for all database operations.
|
|
545
|
+
*
|
|
546
|
+
* Use one of the platform-specific drivers shipped by Syncore
|
|
547
|
+
* (`NodeSqliteDriver`, `SqlJsDriver`, `ExpoSqliteDriver`) or provide a
|
|
548
|
+
* custom implementation of {@link SyncoreSqlDriver}.
|
|
549
|
+
*/
|
|
178
550
|
driver: SyncoreSqlDriver;
|
|
551
|
+
/**
|
|
552
|
+
* The blob storage adapter used for `ctx.storage.put()` and related APIs.
|
|
553
|
+
*
|
|
554
|
+
* Use one of the platform-specific adapters
|
|
555
|
+
* (`NodeFileStorageAdapter`, `BrowserFileStorageAdapter`,
|
|
556
|
+
* `ExpoFileStorageAdapter`) or a custom implementation of
|
|
557
|
+
* {@link SyncoreStorageAdapter}.
|
|
558
|
+
*/
|
|
179
559
|
storage: SyncoreStorageAdapter;
|
|
560
|
+
/**
|
|
561
|
+
* A pub/sub channel that lets this runtime receive change notifications
|
|
562
|
+
* published by other Syncore instances sharing the same data source.
|
|
563
|
+
*
|
|
564
|
+
* Required when running Syncore across multiple contexts that share a
|
|
565
|
+
* database (e.g. Electron main + renderer, or multiple browser tabs).
|
|
566
|
+
* Platform adapters provide ready-made implementations.
|
|
567
|
+
*/
|
|
180
568
|
externalChangeSignal?: SyncoreExternalChangeSignal;
|
|
569
|
+
/**
|
|
570
|
+
* Applies incoming external change events to the local SQLite driver,
|
|
571
|
+
* reconciling the local state with changes written by another process.
|
|
572
|
+
*
|
|
573
|
+
* Usually paired with `externalChangeSignal`. Only required for drivers
|
|
574
|
+
* that hold an in-memory copy of the database (e.g. SQL.js in the browser).
|
|
575
|
+
*/
|
|
181
576
|
externalChangeApplier?: SyncoreExternalChangeApplier;
|
|
577
|
+
/**
|
|
578
|
+
* Platform-specific capabilities injected into `ctx.capabilities` inside
|
|
579
|
+
* every function handler. See {@link SyncoreCapabilities}.
|
|
580
|
+
*/
|
|
182
581
|
capabilities?: SyncoreCapabilities;
|
|
582
|
+
/**
|
|
583
|
+
* Capabilities exposed to clients through `watchRuntimeStatus()`.
|
|
584
|
+
*
|
|
585
|
+
* Platform adapters fill this with feature availability that app UIs should
|
|
586
|
+
* honor, such as whether `ctx.storage` is usable in the current environment.
|
|
587
|
+
*/
|
|
588
|
+
runtimeCapabilities?: SyncoreRuntimeCapabilities;
|
|
589
|
+
/** Structured capability descriptors validated at start-up. */
|
|
183
590
|
capabilityDescriptors?: CapabilityDescriptor[];
|
|
591
|
+
/**
|
|
592
|
+
* Label reported to devtools to identify the runtime’s environment
|
|
593
|
+
* (e.g. `"node"`, `"browser"`, `"expo"`, `"electron-main"`).
|
|
594
|
+
*/
|
|
184
595
|
platform?: string;
|
|
596
|
+
/**
|
|
597
|
+
* Devtools event sink used during development.
|
|
598
|
+
*
|
|
599
|
+
* Pass `false` to disable devtools entirely (recommended for production).
|
|
600
|
+
* Omit to use the platform adapter’s default auto-connect behaviour.
|
|
601
|
+
*/
|
|
185
602
|
devtools?: DevtoolsSink;
|
|
603
|
+
/** Scheduler configuration for background and recurring jobs. */
|
|
186
604
|
scheduler?: SchedulerOptions;
|
|
187
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Arguments for a paginated Syncore query.
|
|
608
|
+
*
|
|
609
|
+
* Add `paginationOpts: s.object({ cursor: s.nullable(s.string()), numItems: s.number() })`
|
|
610
|
+
* to your query’s `args` schema, then accept a `PaginationOptions` value in the
|
|
611
|
+
* handler to enable cursor-based pagination:
|
|
612
|
+
*
|
|
613
|
+
* ```ts
|
|
614
|
+
* export const listTasks = query({
|
|
615
|
+
* args: {
|
|
616
|
+
* paginationOpts: s.object({
|
|
617
|
+
* cursor: s.nullable(s.string()),
|
|
618
|
+
* numItems: s.number(),
|
|
619
|
+
* }),
|
|
620
|
+
* },
|
|
621
|
+
* handler: async (ctx, { paginationOpts }) =>
|
|
622
|
+
* ctx.db.query("tasks").paginate(paginationOpts),
|
|
623
|
+
* });
|
|
624
|
+
* ```
|
|
625
|
+
*
|
|
626
|
+
* In React, use {@link usePaginatedQuery} which manages the cursor for you.
|
|
627
|
+
*/
|
|
188
628
|
interface PaginationOptions {
|
|
629
|
+
/**
|
|
630
|
+
* The cursor returned by the previous page, or `null` / `undefined` for the
|
|
631
|
+
* first page.
|
|
632
|
+
*/
|
|
189
633
|
cursor?: string | null;
|
|
634
|
+
/** Maximum number of items to return in this page. */
|
|
190
635
|
numItems: number;
|
|
191
636
|
}
|
|
637
|
+
/**
|
|
638
|
+
* The value returned by `ctx.db.query(…).paginate()`.
|
|
639
|
+
*
|
|
640
|
+
* Store the `cursor` field and pass it back in the next call to fetch the
|
|
641
|
+
* following page. `isDone` is `true` when there are no more results.
|
|
642
|
+
*/
|
|
192
643
|
interface PaginationResult<TItem> {
|
|
644
|
+
/** The items in this page. May be fewer than `numItems` if `isDone` is `true`. */
|
|
193
645
|
page: TItem[];
|
|
646
|
+
/**
|
|
647
|
+
* Opaque cursor to pass as `PaginationOptions.cursor` in the next call.
|
|
648
|
+
* `null` when `isDone` is `true`.
|
|
649
|
+
*/
|
|
194
650
|
cursor: string | null;
|
|
651
|
+
/** `true` when this is the last page and no more results exist. */
|
|
195
652
|
isDone: boolean;
|
|
196
653
|
}
|
|
654
|
+
/**
|
|
655
|
+
* Coarse lifecycle phase of a Syncore runtime.
|
|
656
|
+
*
|
|
657
|
+
* - `"starting"` — The runtime is initialising (applying schema, loading driver).
|
|
658
|
+
* - `"ready"` — The runtime is fully started and accepting function calls.
|
|
659
|
+
* - `"recovering"` — A transient error occurred; the runtime is attempting recovery.
|
|
660
|
+
* - `"unavailable"` — The runtime is unreachable (worker not started, IPC down, etc.).
|
|
661
|
+
* - `"error"` — The runtime encountered an unrecoverable error.
|
|
662
|
+
*/
|
|
197
663
|
type SyncoreRuntimeStatusKind = "starting" | "ready" | "recovering" | "unavailable" | "error";
|
|
664
|
+
/**
|
|
665
|
+
* Explains why the runtime entered its current non-`"ready"` state.
|
|
666
|
+
*
|
|
667
|
+
* Useful for rendering descriptive loading or error messages in the UI.
|
|
668
|
+
*/
|
|
198
669
|
type SyncoreRuntimeStatusReason = "booting" | "rehydrating" | "worker-restarting" | "worker-unavailable" | "ipc-unavailable" | "runtime-unavailable" | "disposed";
|
|
670
|
+
/** Runtime-visible storage capability for app UIs and adapters. */
|
|
671
|
+
interface SyncoreRuntimeStorageCapability {
|
|
672
|
+
/** Whether `ctx.storage` can read/write objects in this runtime. */
|
|
673
|
+
available: boolean;
|
|
674
|
+
/** Short reason to show when storage is unavailable. */
|
|
675
|
+
reason?: string;
|
|
676
|
+
/** Storage protocol used by the adapter, such as `"file"` or `"opfs"`. */
|
|
677
|
+
protocol?: string;
|
|
678
|
+
/** Whether the adapter can read byte ranges without loading the full object. */
|
|
679
|
+
supportsRange?: boolean;
|
|
680
|
+
}
|
|
681
|
+
/** Runtime capabilities exposed through `watchRuntimeStatus()`. */
|
|
682
|
+
interface SyncoreRuntimeCapabilities {
|
|
683
|
+
storage: SyncoreRuntimeStorageCapability;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Snapshot of the runtime’s current lifecycle state.
|
|
687
|
+
*
|
|
688
|
+
* Subscribe to changes with `client.watchRuntimeStatus()` or the
|
|
689
|
+
* `useSyncoreStatus()` React hook to adapt the UI while the runtime is
|
|
690
|
+
* starting up or recovering.
|
|
691
|
+
*
|
|
692
|
+
* ```ts
|
|
693
|
+
* const status = useSyncoreStatus();
|
|
694
|
+
* if (status.kind !== "ready") return <LoadingSpinner />;
|
|
695
|
+
* ```
|
|
696
|
+
*/
|
|
199
697
|
interface SyncoreRuntimeStatus {
|
|
698
|
+
/** Coarse lifecycle phase. */
|
|
200
699
|
kind: SyncoreRuntimeStatusKind;
|
|
700
|
+
/** Machine-readable reason for a non-`"ready"` state. */
|
|
201
701
|
reason?: SyncoreRuntimeStatusReason;
|
|
702
|
+
/** The underlying error when `kind` is `"error"`. */
|
|
202
703
|
error?: Error;
|
|
704
|
+
/** Runtime capabilities that app UIs can use to enable or hide affordances. */
|
|
705
|
+
capabilities?: SyncoreRuntimeCapabilities;
|
|
203
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Lifecycle status of an individual reactive query subscription.
|
|
709
|
+
*
|
|
710
|
+
* - `"loading"` — The query has never produced a result (first load).
|
|
711
|
+
* - `"success"` — The query has data and no error.
|
|
712
|
+
* - `"error"` — The last execution threw an error. `data` may still hold a
|
|
713
|
+
* stale value from a prior successful run.
|
|
714
|
+
* - `"skipped"` — The subscription was suppressed with the `skip` sentinel.
|
|
715
|
+
*/
|
|
204
716
|
type SyncoreQueryStatus = "loading" | "success" | "error" | "skipped";
|
|
717
|
+
/**
|
|
718
|
+
* The full reactive state of a Syncore query subscription.
|
|
719
|
+
*
|
|
720
|
+
* Returned by {@link useQueryState} and Svelte’s `createQueryStore`. For most
|
|
721
|
+
* components you only need the `data` field — use {@link useQuery} for that
|
|
722
|
+
* simpler shape.
|
|
723
|
+
*/
|
|
205
724
|
interface SyncoreQueryState<TData> {
|
|
725
|
+
/** The most recent result from the query, or `undefined` while loading. */
|
|
206
726
|
data: TData | undefined;
|
|
727
|
+
/** The error thrown by the last execution, or `undefined` on success. */
|
|
207
728
|
error: Error | undefined;
|
|
729
|
+
/** Fine-grained subscription lifecycle status. */
|
|
208
730
|
status: SyncoreQueryStatus;
|
|
731
|
+
/** Current lifecycle status of the underlying runtime. */
|
|
209
732
|
runtimeStatus: SyncoreRuntimeStatus;
|
|
733
|
+
/** `true` while waiting for the first result. Equivalent to `status === "loading"`. */
|
|
210
734
|
isLoading: boolean;
|
|
735
|
+
/** `true` when the last execution threw an error. */
|
|
211
736
|
isError: boolean;
|
|
737
|
+
/** `true` when `data` is available and the runtime is ready. */
|
|
212
738
|
isReady: boolean;
|
|
213
739
|
}
|
|
214
740
|
type SyncoreQueryRequest<TReference extends FunctionReference<"query"> = FunctionReference<"query">> = (Record<never, never> extends FunctionArgs<TReference> ? {
|
|
@@ -221,23 +747,90 @@ type SyncoreQueryRequest<TReference extends FunctionReference<"query"> = Functio
|
|
|
221
747
|
skip?: boolean;
|
|
222
748
|
};
|
|
223
749
|
type SyncoreQueriesRequest = Record<string, SyncoreQueryRequest>;
|
|
750
|
+
/**
|
|
751
|
+
* Lifecycle status of a paginated Syncore query subscription.
|
|
752
|
+
*
|
|
753
|
+
* - `"loading"` — Waiting for the first page to arrive.
|
|
754
|
+
* - `"ready"` — At least one page has loaded and more pages are available.
|
|
755
|
+
* - `"loadingMore"` — A `loadMore()` call is in progress.
|
|
756
|
+
* - `"exhausted"` — All pages have been loaded (`isDone` is `true` on the
|
|
757
|
+
* last page). `loadMore()` is a no-op in this state.
|
|
758
|
+
* - `"error"` — The last page load failed. `error` contains the thrown error.
|
|
759
|
+
*/
|
|
224
760
|
type SyncorePaginatedQueryStatus = "loading" | "ready" | "loadingMore" | "exhausted" | "error";
|
|
761
|
+
/**
|
|
762
|
+
* The result object returned by {@link usePaginatedQuery} and
|
|
763
|
+
* `createPaginatedQueryStore`.
|
|
764
|
+
*
|
|
765
|
+
* Contains the accumulated items, pagination metadata, and a `loadMore`
|
|
766
|
+
* callback for fetching the next page.
|
|
767
|
+
*/
|
|
225
768
|
interface UsePaginatedQueryResult<TItem> {
|
|
769
|
+
/** All items loaded so far, across all fetched pages. */
|
|
226
770
|
results: TItem[];
|
|
771
|
+
/** Raw page results in order, one entry per fetched page. */
|
|
227
772
|
pages: PaginationResult<TItem>[];
|
|
773
|
+
/** Current lifecycle phase of the paginated query. */
|
|
228
774
|
status: SyncorePaginatedQueryStatus;
|
|
775
|
+
/** The error thrown by the last failed page load, or `undefined`. */
|
|
229
776
|
error: Error | undefined;
|
|
777
|
+
/** `true` while waiting for the first page. */
|
|
230
778
|
isLoading: boolean;
|
|
779
|
+
/** `true` while a `loadMore()` request is in progress. */
|
|
231
780
|
isLoadingMore: boolean;
|
|
781
|
+
/** `true` when there is a next page available to load. */
|
|
232
782
|
hasMore: boolean;
|
|
783
|
+
/** Cursor to pass to the next page request. `null` when `isDone` is `true`. */
|
|
233
784
|
cursor: string | null;
|
|
785
|
+
/** Current lifecycle status of the underlying runtime. */
|
|
234
786
|
runtimeStatus: SyncoreRuntimeStatus;
|
|
787
|
+
/**
|
|
788
|
+
* Fetch the next page of results.
|
|
789
|
+
*
|
|
790
|
+
* @param numItems - Number of items to request. Defaults to `initialNumItems`.
|
|
791
|
+
* A no-op when `hasMore` is `false`, `isLoadingMore` is `true`, or an error
|
|
792
|
+
* occurred.
|
|
793
|
+
*/
|
|
235
794
|
loadMore(numItems?: number): Promise<void> | void;
|
|
236
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* A live, cancellable subscription to a reactive Syncore value.
|
|
798
|
+
*
|
|
799
|
+
* The runtime keeps the watched value up-to-date by re-running the underlying
|
|
800
|
+
* query whenever its data dependencies change. `onUpdate` is called each time a
|
|
801
|
+
* fresh result is available so the subscriber can read the new value with
|
|
802
|
+
* `localQueryResult()`.
|
|
803
|
+
*
|
|
804
|
+
* React’s `useQuery` and Svelte’s `createQueryStore` are built on top of this
|
|
805
|
+
* interface — you only need `SyncoreWatch` directly when integrating with
|
|
806
|
+
* frameworks outside the first-party adapters.
|
|
807
|
+
*
|
|
808
|
+
* ```ts
|
|
809
|
+
* const watch = client.watchQuery(api.tasks.list);
|
|
810
|
+
* const unsubscribe = watch.onUpdate(() => {
|
|
811
|
+
* console.log(watch.localQueryResult());
|
|
812
|
+
* });
|
|
813
|
+
* // Later:
|
|
814
|
+
* unsubscribe();
|
|
815
|
+
* watch.dispose?.();
|
|
816
|
+
* ```
|
|
817
|
+
*/
|
|
237
818
|
interface SyncoreWatch<TValue> {
|
|
819
|
+
/**
|
|
820
|
+
* Register a callback to be called whenever the watched value changes.
|
|
821
|
+
* @returns An `unsubscribe` function; call it to stop receiving updates.
|
|
822
|
+
*/
|
|
238
823
|
onUpdate(callback: () => void): () => void;
|
|
824
|
+
/** Return the latest available query result, or `undefined` if not yet loaded. */
|
|
239
825
|
localQueryResult(): TValue | undefined;
|
|
826
|
+
/** Return the error from the last failed execution, or `undefined` on success. */
|
|
240
827
|
localQueryError(): Error | undefined;
|
|
828
|
+
/**
|
|
829
|
+
* Release all resources held by this watch handle.
|
|
830
|
+
*
|
|
831
|
+
* Call this when the subscriber is unmounted or the watch is no longer needed
|
|
832
|
+
* to prevent memory leaks. Framework adapters call this automatically.
|
|
833
|
+
*/
|
|
241
834
|
dispose?(): void;
|
|
242
835
|
}
|
|
243
836
|
interface FilterBuilder {
|
|
@@ -269,72 +862,399 @@ type OptionalPropertyNames<TValue> = TValue extends object ? { [TKey in keyof TV
|
|
|
269
862
|
type PatchValue<TValue> = TValue extends object ? { [TKey in keyof TValue]?: TKey extends OptionalPropertyNames<TValue> ? TValue[TKey] | undefined : TValue[TKey] } : never;
|
|
270
863
|
type PatchValueForTable<TSchema extends SyncoreDataModel, TTableName extends TableNames<TSchema>> = PatchValue<InsertValueForTable<TSchema, TTableName>>;
|
|
271
864
|
type OptionalArgsTuple<TArgs> = Record<never, never> extends TArgs ? [args?: TArgs] : [args: TArgs];
|
|
865
|
+
/**
|
|
866
|
+
* Read-only database API available inside Syncore query (and mutation/action)
|
|
867
|
+
* handlers via `ctx.db`.
|
|
868
|
+
*
|
|
869
|
+
* All methods are fully typed against your schema — the table names and
|
|
870
|
+
* returned document shapes are inferred from the `TSchema` type parameter:
|
|
871
|
+
*
|
|
872
|
+
* ```ts
|
|
873
|
+
* // Fetch by ID
|
|
874
|
+
* const task = await ctx.db.get("tasks", taskId);
|
|
875
|
+
*
|
|
876
|
+
* // Chainable query builder
|
|
877
|
+
* const todos = await ctx.db
|
|
878
|
+
* .query("tasks")
|
|
879
|
+
* .withIndex("by_status", (q) => q.eq("status", "todo"))
|
|
880
|
+
* .order("asc")
|
|
881
|
+
* .take(20);
|
|
882
|
+
*
|
|
883
|
+
* // Raw SQL escape hatch (use sparingly — bypasses type safety)
|
|
884
|
+
* const rows = await ctx.db.raw<{ count: number }>(
|
|
885
|
+
* "SELECT COUNT(*) AS count FROM tasks"
|
|
886
|
+
* );
|
|
887
|
+
* ```
|
|
888
|
+
*/
|
|
272
889
|
interface SyncoreDatabaseReader<TSchema extends SyncoreDataModel = SyncoreDataModel> {
|
|
890
|
+
/**
|
|
891
|
+
* Fetch a single document by its `_id`, or `null` if it does not exist.
|
|
892
|
+
*
|
|
893
|
+
* @param table - The table to look in.
|
|
894
|
+
* @param id - The document’s `_id` string.
|
|
895
|
+
*/
|
|
273
896
|
get<TTableName extends TableNames<TSchema>>(table: TTableName, id: string): Promise<DocumentForTable<TSchema, TTableName> | null>;
|
|
897
|
+
/**
|
|
898
|
+
* Start a chainable {@link QueryBuilder} for the given table.
|
|
899
|
+
*
|
|
900
|
+
* Chain `.withIndex()` or `.withSearchIndex()` to use an index, `.filter()`
|
|
901
|
+
* for additional predicates, `.order()` to control direction, and then a
|
|
902
|
+
* terminal method (`.collect()`, `.first()`, `.take()`, `.paginate()`).
|
|
903
|
+
*/
|
|
274
904
|
query<TTableName extends TableNames<TSchema>>(table: TTableName): QueryBuilder<TSchema["tables"][TTableName], DocumentForTable<TSchema, TTableName>>;
|
|
905
|
+
/**
|
|
906
|
+
* Execute a raw SQL `SELECT` statement and return the results.
|
|
907
|
+
*
|
|
908
|
+
* Prefer the typed query builder whenever possible. Use `raw` as an escape
|
|
909
|
+
* hatch for complex aggregations or joins that the builder cannot express.
|
|
910
|
+
*/
|
|
275
911
|
raw<TValue = unknown>(sql: string, params?: unknown[]): Promise<TValue[]>;
|
|
276
912
|
}
|
|
913
|
+
/**
|
|
914
|
+
* Read-write database API available inside Syncore mutation handlers via
|
|
915
|
+
* `ctx.db`. Extends {@link SyncoreDatabaseReader} with write methods that
|
|
916
|
+
* execute atomically within the mutation’s transaction.
|
|
917
|
+
*
|
|
918
|
+
* ```ts
|
|
919
|
+
* // Insert a new document and get its generated _id
|
|
920
|
+
* const id = await ctx.db.insert("tasks", { title: "Buy milk", status: "todo", projectId: null });
|
|
921
|
+
*
|
|
922
|
+
* // Merge a partial update (other fields are preserved)
|
|
923
|
+
* await ctx.db.patch("tasks", id, { status: "done" });
|
|
924
|
+
*
|
|
925
|
+
* // Replace the entire document (all fields must be provided)
|
|
926
|
+
* await ctx.db.replace("tasks", id, { title: "Buy oat milk", status: "todo", projectId: null });
|
|
927
|
+
*
|
|
928
|
+
* // Delete a document
|
|
929
|
+
* await ctx.db.delete("tasks", id);
|
|
930
|
+
* ```
|
|
931
|
+
*/
|
|
277
932
|
interface SyncoreDatabaseWriter<TSchema extends SyncoreDataModel = SyncoreDataModel> extends SyncoreDatabaseReader<TSchema> {
|
|
933
|
+
/**
|
|
934
|
+
* Insert a new document and return its generated `_id`.
|
|
935
|
+
*
|
|
936
|
+
* The value must satisfy the table’s validator schema. System fields
|
|
937
|
+
* (`_id`, `_creationTime`) are set automatically.
|
|
938
|
+
*/
|
|
278
939
|
insert<TTableName extends TableNames<TSchema>>(table: TTableName, value: InsertValueForTable<TSchema, TTableName>): Promise<string>;
|
|
940
|
+
/**
|
|
941
|
+
* Merge `value` into the existing document at `id`.
|
|
942
|
+
*
|
|
943
|
+
* Only the keys present in `value` are updated; all other fields retain their
|
|
944
|
+
* current values. Equivalent to a SQL `UPDATE … SET …` for specific columns.
|
|
945
|
+
*/
|
|
279
946
|
patch<TTableName extends TableNames<TSchema>>(table: TTableName, id: string, value: PatchValueForTable<TSchema, TTableName>): Promise<void>;
|
|
947
|
+
/**
|
|
948
|
+
* Overwrite the entire document at `id` with `value`.
|
|
949
|
+
*
|
|
950
|
+
* The `_id` and `_creationTime` system fields are preserved; all other
|
|
951
|
+
* fields are replaced. Use `patch` when you only want to change a subset of
|
|
952
|
+
* fields.
|
|
953
|
+
*/
|
|
280
954
|
replace<TTableName extends TableNames<TSchema>>(table: TTableName, id: string, value: InsertValueForTable<TSchema, TTableName>): Promise<void>;
|
|
955
|
+
/**
|
|
956
|
+
* Permanently delete the document with the given `id`.
|
|
957
|
+
*
|
|
958
|
+
* A no-op if the document does not exist.
|
|
959
|
+
*/
|
|
281
960
|
delete<TTableName extends TableNames<TSchema>>(table: TTableName, id: string): Promise<void>;
|
|
282
961
|
}
|
|
283
962
|
/**
|
|
284
|
-
*
|
|
963
|
+
* Blob storage operations exposed to Syncore function handlers via
|
|
964
|
+
* `ctx.storage`.
|
|
965
|
+
*
|
|
966
|
+
* Store large binary objects (images, PDFs, audio files) separately from the
|
|
967
|
+
* SQLite database. Each object gets an opaque `id` that you can persist in a
|
|
968
|
+
* document field for later retrieval.
|
|
969
|
+
*
|
|
970
|
+
* ```ts
|
|
971
|
+
* // In a mutation
|
|
972
|
+
* const id = await ctx.storage.put({
|
|
973
|
+
* data: imageBuffer,
|
|
974
|
+
* contentType: "image/png",
|
|
975
|
+
* });
|
|
976
|
+
* await ctx.db.patch("users", userId, { avatarId: id });
|
|
977
|
+
*
|
|
978
|
+
* // In a query
|
|
979
|
+
* const bytes = await ctx.storage.read(user.avatarId);
|
|
980
|
+
* ```
|
|
285
981
|
*/
|
|
286
982
|
interface SyncoreStorageApi {
|
|
983
|
+
/**
|
|
984
|
+
* Persist a binary blob and return its auto-generated opaque `id`.
|
|
985
|
+
*
|
|
986
|
+
* Store the returned `id` in a database document to reference the object.
|
|
987
|
+
*/
|
|
287
988
|
put(input: StorageWriteInput): Promise<string>;
|
|
989
|
+
/**
|
|
990
|
+
* Return metadata for the stored object, or `null` if it does not exist.
|
|
991
|
+
* Does not fetch the raw bytes — use `read` for that.
|
|
992
|
+
*/
|
|
288
993
|
get(id: string): Promise<StorageObject | null>;
|
|
994
|
+
/**
|
|
995
|
+
* Return the raw bytes of the stored object, or `null` if it does not exist.
|
|
996
|
+
*/
|
|
289
997
|
read(id: string): Promise<Uint8Array | null>;
|
|
998
|
+
/**
|
|
999
|
+
* Permanently delete the stored object. A no-op if the object does not exist.
|
|
1000
|
+
*/
|
|
290
1001
|
delete(id: string): Promise<void>;
|
|
291
1002
|
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Job scheduling API available to mutation and action handlers via
|
|
1005
|
+
* `ctx.scheduler`.
|
|
1006
|
+
*
|
|
1007
|
+
* Use `runAfter` and `runAt` to enqueue a mutation or action that runs outside
|
|
1008
|
+
* the current transaction — ideal for sending notifications, retrying
|
|
1009
|
+
* failed operations, or breaking long workflows into steps.
|
|
1010
|
+
*
|
|
1011
|
+
* ```ts
|
|
1012
|
+
* // Run a cleanup job 24 hours from now
|
|
1013
|
+
* await ctx.scheduler.runAfter(
|
|
1014
|
+
* 24 * 60 * 60_000,
|
|
1015
|
+
* api.cleanup.deleteExpiredSessions,
|
|
1016
|
+
* );
|
|
1017
|
+
*
|
|
1018
|
+
* // Run at a specific timestamp
|
|
1019
|
+
* const tomorrow = Date.now() + 86_400_000;
|
|
1020
|
+
* const jobId = await ctx.scheduler.runAt(tomorrow, api.email.sendDigest, { userId });
|
|
1021
|
+
*
|
|
1022
|
+
* // Cancel if the user opts out before the job fires
|
|
1023
|
+
* await ctx.scheduler.cancel(jobId);
|
|
1024
|
+
* ```
|
|
1025
|
+
*/
|
|
292
1026
|
interface SchedulerApi {
|
|
1027
|
+
/**
|
|
1028
|
+
* Enqueue a mutation or action to run after `delayMs` milliseconds.
|
|
1029
|
+
*
|
|
1030
|
+
* @param delayMs - Delay from now in milliseconds.
|
|
1031
|
+
* @param functionReference - The mutation or action to execute.
|
|
1032
|
+
* @param args - Arguments forwarded to the function.
|
|
1033
|
+
* @param misfirePolicy - Optional policy for missed executions.
|
|
1034
|
+
* @returns An opaque job `id` you can pass to `cancel`.
|
|
1035
|
+
*/
|
|
293
1036
|
runAfter<TArgs, TResult>(delayMs: number, functionReference: FunctionReference<"mutation" | "action", TArgs, TResult>, ...args: [...OptionalArgsTuple<TArgs>, misfirePolicy?: MisfirePolicy]): Promise<string>;
|
|
1037
|
+
/**
|
|
1038
|
+
* Enqueue a mutation or action to run at a specific Unix timestamp (or
|
|
1039
|
+
* `Date` object).
|
|
1040
|
+
*
|
|
1041
|
+
* @param timestamp - When to run the job (ms since epoch, or a Date).
|
|
1042
|
+
* @param functionReference - The mutation or action to execute.
|
|
1043
|
+
* @param args - Arguments forwarded to the function.
|
|
1044
|
+
* @param misfirePolicy - Optional policy for missed executions.
|
|
1045
|
+
* @returns An opaque job `id` you can pass to `cancel`.
|
|
1046
|
+
*/
|
|
294
1047
|
runAt<TArgs, TResult>(timestamp: number | Date, functionReference: FunctionReference<"mutation" | "action", TArgs, TResult>, ...args: [...OptionalArgsTuple<TArgs>, misfirePolicy?: MisfirePolicy]): Promise<string>;
|
|
1048
|
+
/**
|
|
1049
|
+
* Cancel a pending scheduled job by its `id`.
|
|
1050
|
+
*
|
|
1051
|
+
* A no-op if the job has already executed or was already cancelled.
|
|
1052
|
+
*/
|
|
295
1053
|
cancel(id: string): Promise<void>;
|
|
296
1054
|
}
|
|
297
1055
|
/**
|
|
298
|
-
*
|
|
1056
|
+
* Execution context injected into every Syncore **query** handler.
|
|
1057
|
+
*
|
|
1058
|
+
* `ctx` is the first argument of every `query()` handler. It provides
|
|
1059
|
+
* read-only database access, storage access, platform capabilities, and the
|
|
1060
|
+
* ability to call other queries. The type is generic over the app schema so
|
|
1061
|
+
* that `ctx.db` is fully typed against your tables.
|
|
1062
|
+
*
|
|
1063
|
+
* The generated `QueryCtx` in `syncore/_generated/server.ts` is always
|
|
1064
|
+
* preferred over the base type because it is pre-bound to your app schema:
|
|
1065
|
+
*
|
|
1066
|
+
* ```ts
|
|
1067
|
+
* import type { QueryCtx } from "../_generated/server";
|
|
1068
|
+
*
|
|
1069
|
+
* export const list = query({
|
|
1070
|
+
* args: { projectId: s.optional(s.id("projects")) },
|
|
1071
|
+
* handler: async (ctx: QueryCtx, { projectId }) => {
|
|
1072
|
+
* return ctx.db
|
|
1073
|
+
* .query("tasks")
|
|
1074
|
+
* .withIndex("by_project", (q) =>
|
|
1075
|
+
* projectId ? q.eq("projectId", projectId) : q
|
|
1076
|
+
* )
|
|
1077
|
+
* .collect();
|
|
1078
|
+
* },
|
|
1079
|
+
* });
|
|
1080
|
+
* ```
|
|
299
1081
|
*/
|
|
300
1082
|
interface QueryCtx<TSchema extends SyncoreDataModel = SyncoreDataModel> {
|
|
1083
|
+
/** Read-only access to the local SQLite database. */
|
|
301
1084
|
db: SyncoreDatabaseReader<TSchema>;
|
|
1085
|
+
/** Blob storage access for reading files and images. */
|
|
302
1086
|
storage: SyncoreStorageApi;
|
|
1087
|
+
/**
|
|
1088
|
+
* Platform capabilities injected at runtime setup (e.g. push notifications,
|
|
1089
|
+
* biometrics). `undefined` when no capabilities were configured.
|
|
1090
|
+
*/
|
|
303
1091
|
capabilities?: Readonly<SyncoreCapabilities>;
|
|
1092
|
+
/** Structured descriptors for the registered capabilities. */
|
|
304
1093
|
capabilityDescriptors?: ReadonlyArray<CapabilityDescriptor>;
|
|
1094
|
+
/**
|
|
1095
|
+
* Metadata about the Syncore component this function belongs to, if it was
|
|
1096
|
+
* installed as part of a component package rather than the root app.
|
|
1097
|
+
*/
|
|
305
1098
|
component?: {
|
|
306
1099
|
path: string;
|
|
307
1100
|
name: string;
|
|
308
1101
|
version: string;
|
|
309
1102
|
capabilities: readonly string[];
|
|
310
1103
|
};
|
|
1104
|
+
/**
|
|
1105
|
+
* Call another Syncore query inside this handler.
|
|
1106
|
+
*
|
|
1107
|
+
* The callee’s read-set is merged into the current query’s dependencies, so
|
|
1108
|
+
* any change that would invalidate the callee also invalidates this query.
|
|
1109
|
+
*/
|
|
311
1110
|
runQuery<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
312
1111
|
}
|
|
313
1112
|
/**
|
|
314
|
-
*
|
|
1113
|
+
* Execution context injected into every Syncore **mutation** handler.
|
|
1114
|
+
*
|
|
1115
|
+
* Extends {@link QueryCtx} with a writable database (`ctx.db`), a scheduler,
|
|
1116
|
+
* and the ability to call mutations or actions. Everything runs inside a single
|
|
1117
|
+
* atomic SQLite transaction that is committed when the handler returns or
|
|
1118
|
+
* rolled back if it throws.
|
|
1119
|
+
*
|
|
1120
|
+
* Use the generated `MutationCtx` from `syncore/_generated/server.ts` so that
|
|
1121
|
+
* `ctx.db` is typed to your specific schema:
|
|
1122
|
+
*
|
|
1123
|
+
* ```ts
|
|
1124
|
+
* import type { MutationCtx } from "../_generated/server";
|
|
1125
|
+
*
|
|
1126
|
+
* export const create = mutation({
|
|
1127
|
+
* args: { title: s.string() },
|
|
1128
|
+
* handler: async (ctx: MutationCtx, { title }) => {
|
|
1129
|
+
* const id = await ctx.db.insert("tasks", {
|
|
1130
|
+
* title,
|
|
1131
|
+
* status: "todo",
|
|
1132
|
+
* projectId: null,
|
|
1133
|
+
* });
|
|
1134
|
+
* // Schedule a follow-up action without blocking the transaction
|
|
1135
|
+
* await ctx.scheduler.runAfter(0, api.tasks.notifyCreated, { id });
|
|
1136
|
+
* return id;
|
|
1137
|
+
* },
|
|
1138
|
+
* });
|
|
1139
|
+
* ```
|
|
315
1140
|
*/
|
|
316
1141
|
interface MutationCtx<TSchema extends SyncoreDataModel = SyncoreDataModel> extends QueryCtx<TSchema> {
|
|
1142
|
+
/** Read-write database access. Changes are committed atomically on handler return. */
|
|
317
1143
|
db: SyncoreDatabaseWriter<TSchema>;
|
|
1144
|
+
/** Schedule mutations and actions to run outside the current transaction. */
|
|
318
1145
|
scheduler: SchedulerApi;
|
|
1146
|
+
/**
|
|
1147
|
+
* Call another mutation inside this handler’s transaction.
|
|
1148
|
+
*
|
|
1149
|
+
* The callee shares the current transaction context, so its writes are part
|
|
1150
|
+
* of the same atomic commit.
|
|
1151
|
+
*/
|
|
319
1152
|
runMutation<TArgs, TResult>(reference: FunctionReference<"mutation", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
1153
|
+
/**
|
|
1154
|
+
* Launch an action from within a mutation. The action runs asynchronously
|
|
1155
|
+
* in a separate context **after** the mutation commits.
|
|
1156
|
+
*/
|
|
320
1157
|
runAction<TArgs, TResult>(reference: FunctionReference<"action", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
321
1158
|
}
|
|
322
1159
|
/**
|
|
323
|
-
*
|
|
1160
|
+
* Execution context injected into every Syncore **action** handler.
|
|
1161
|
+
*
|
|
1162
|
+
* Extends {@link QueryCtx} with a scheduler and the ability to call mutations
|
|
1163
|
+
* and other actions. Unlike mutations, actions run **outside** of any
|
|
1164
|
+
* transaction, so they can perform long-running or async work (HTTP requests,
|
|
1165
|
+
* file I/O, etc.) and delegate writes to mutations.
|
|
1166
|
+
*
|
|
1167
|
+
* Use the generated `ActionCtx` from `syncore/_generated/server.ts` so the
|
|
1168
|
+
* types are bound to your app schema:
|
|
1169
|
+
*
|
|
1170
|
+
* ```ts
|
|
1171
|
+
* import type { ActionCtx } from "../_generated/server";
|
|
1172
|
+
*
|
|
1173
|
+
* export const importFromApi = action({
|
|
1174
|
+
* args: { projectId: s.id("projects") },
|
|
1175
|
+
* handler: async (ctx: ActionCtx, { projectId }) => {
|
|
1176
|
+
* const data = await fetch("https://api.example.com/tasks").then((r) => r.json());
|
|
1177
|
+
* for (const item of data) {
|
|
1178
|
+
* await ctx.runMutation(api.tasks.create, { title: item.title });
|
|
1179
|
+
* }
|
|
1180
|
+
* },
|
|
1181
|
+
* });
|
|
1182
|
+
* ```
|
|
324
1183
|
*/
|
|
325
1184
|
interface ActionCtx<TSchema extends SyncoreDataModel = SyncoreDataModel> extends QueryCtx<TSchema> {
|
|
1185
|
+
/** Schedule mutations and actions to run at a later time. */
|
|
326
1186
|
scheduler: SchedulerApi;
|
|
1187
|
+
/**
|
|
1188
|
+
* Call a mutation from within this action.
|
|
1189
|
+
*
|
|
1190
|
+
* Because actions are non-transactional, each `runMutation` call creates its
|
|
1191
|
+
* own transaction. If the action fails partway through, earlier mutations are
|
|
1192
|
+
* **not** rolled back automatically — design accordingly.
|
|
1193
|
+
*/
|
|
327
1194
|
runMutation<TArgs, TResult>(reference: FunctionReference<"mutation", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
1195
|
+
/** Call another action from within this action. */
|
|
328
1196
|
runAction<TArgs, TResult>(reference: FunctionReference<"action", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
329
1197
|
}
|
|
330
1198
|
/**
|
|
331
|
-
*
|
|
1199
|
+
* The client-facing API for calling Syncore functions and subscribing to
|
|
1200
|
+
* reactive query results.
|
|
1201
|
+
*
|
|
1202
|
+
* You obtain a `SyncoreClient` by calling `runtime.createClient()` or, for
|
|
1203
|
+
* worker-based browser setups, via the platform adapter’s
|
|
1204
|
+
* `createWebWorkerClient()` / `createManagedWebWorkerClient()` helpers.
|
|
1205
|
+
*
|
|
1206
|
+
* In React, the client is provided to the component tree via
|
|
1207
|
+
* {@link SyncoreProvider} and consumed through hooks (`useQuery`,
|
|
1208
|
+
* `useMutation`, etc.) — you rarely call these methods directly.
|
|
1209
|
+
*
|
|
1210
|
+
* ```ts
|
|
1211
|
+
* const client = runtime.createClient();
|
|
1212
|
+
*
|
|
1213
|
+
* // One-shot query
|
|
1214
|
+
* const tasks = await client.query(api.tasks.list);
|
|
1215
|
+
*
|
|
1216
|
+
* // One-shot mutation
|
|
1217
|
+
* await client.mutation(api.tasks.create, { title: "Buy milk" });
|
|
1218
|
+
*
|
|
1219
|
+
* // Reactive subscription
|
|
1220
|
+
* const watch = client.watchQuery(api.tasks.list);
|
|
1221
|
+
* watch.onUpdate(() => console.log(watch.localQueryResult()));
|
|
1222
|
+
* ```
|
|
332
1223
|
*/
|
|
333
1224
|
interface SyncoreClient {
|
|
1225
|
+
/**
|
|
1226
|
+
* Execute a query and return its result.
|
|
1227
|
+
*
|
|
1228
|
+
* Unlike a reactive subscription, this is a one-shot call that does not
|
|
1229
|
+
* stay up to date. Use `watchQuery` or the `useQuery` hook for live data.
|
|
1230
|
+
*/
|
|
334
1231
|
query<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
1232
|
+
/**
|
|
1233
|
+
* Execute a mutation and return its result.
|
|
1234
|
+
*
|
|
1235
|
+
* The mutation runs atomically and all affected queries are automatically
|
|
1236
|
+
* re-executed after the commit.
|
|
1237
|
+
*/
|
|
335
1238
|
mutation<TArgs, TResult>(reference: FunctionReference<"mutation", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
1239
|
+
/**
|
|
1240
|
+
* Execute an action and return its result.
|
|
1241
|
+
*
|
|
1242
|
+
* Actions are non-transactional and may take arbitrarily long to complete.
|
|
1243
|
+
*/
|
|
336
1244
|
action<TArgs, TResult>(reference: FunctionReference<"action", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): Promise<TResult>;
|
|
1245
|
+
/**
|
|
1246
|
+
* Subscribe to a reactive query and return a {@link SyncoreWatch} handle.
|
|
1247
|
+
*
|
|
1248
|
+
* The watch delivers a new result every time the underlying data changes.
|
|
1249
|
+
* Call `watch.onUpdate()` to listen and `watch.dispose()` when done.
|
|
1250
|
+
*/
|
|
337
1251
|
watchQuery<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, ...args: OptionalArgsTuple<TArgs>): SyncoreWatch<TResult>;
|
|
1252
|
+
/**
|
|
1253
|
+
* Subscribe to the runtime’s lifecycle status.
|
|
1254
|
+
*
|
|
1255
|
+
* Useful for showing loading or error states in the UI while the runtime is
|
|
1256
|
+
* starting or recovering.
|
|
1257
|
+
*/
|
|
338
1258
|
watchRuntimeStatus(): SyncoreWatch<SyncoreRuntimeStatus>;
|
|
339
1259
|
}
|
|
340
1260
|
interface SyncoreRuntimeAdmin<TSchema extends SyncoreDataModel = SyncoreDataModel> {
|
|
@@ -354,37 +1274,205 @@ interface SyncoreRuntimeAdmin<TSchema extends SyncoreDataModel = SyncoreDataMode
|
|
|
354
1274
|
subscribeToDevtoolsInvalidations(listener: (scopes: Set<DevtoolsLiveQueryScope>) => void): () => void;
|
|
355
1275
|
notifyDevtoolsScopes(scopes: Iterable<DevtoolsLiveQueryScope>): void;
|
|
356
1276
|
forceRefreshDevtools(reason: string, scopes?: Iterable<ImpactScope>, meta?: DevtoolsEventMeta): Promise<void>;
|
|
1277
|
+
listStorageObjects(options?: {
|
|
1278
|
+
limit?: number;
|
|
1279
|
+
offset?: number;
|
|
1280
|
+
search?: string;
|
|
1281
|
+
}): Promise<{
|
|
1282
|
+
entries: StorageEntry[];
|
|
1283
|
+
totalCount: number;
|
|
1284
|
+
}>;
|
|
1285
|
+
getStorageObjectAccessInfo(id: string): Promise<{
|
|
1286
|
+
entry: StorageEntry;
|
|
1287
|
+
supportsRange: boolean;
|
|
1288
|
+
} | null>;
|
|
1289
|
+
readStorageObjectRange(id: string, offset: number, length: number): Promise<{
|
|
1290
|
+
entry: StorageEntry;
|
|
1291
|
+
bytes: Uint8Array;
|
|
1292
|
+
offset: number;
|
|
1293
|
+
bytesRead: number;
|
|
1294
|
+
done: boolean;
|
|
1295
|
+
supportsRange: boolean;
|
|
1296
|
+
} | null>;
|
|
1297
|
+
deleteStorageObject(id: string, meta?: DevtoolsEventMeta): Promise<boolean>;
|
|
357
1298
|
cancelScheduledJob(id: string): Promise<boolean>;
|
|
358
1299
|
updateScheduledJob(options: UpdateScheduledJobOptions): Promise<boolean>;
|
|
359
1300
|
}
|
|
360
1301
|
type DevtoolsEventMeta = {
|
|
361
1302
|
origin?: SyncoreDevtoolsEventOrigin;
|
|
1303
|
+
executionId?: string;
|
|
1304
|
+
parentExecutionId?: string;
|
|
1305
|
+
schedulerJobId?: string;
|
|
1306
|
+
schedulerRun?: boolean;
|
|
362
1307
|
};
|
|
363
1308
|
/**
|
|
364
|
-
* Chainable query builder returned by `ctx.db.query(
|
|
1309
|
+
* Chainable query builder returned by `ctx.db.query(tableName)`.
|
|
1310
|
+
*
|
|
1311
|
+
* Chain methods in this order to build up a query:
|
|
1312
|
+
*
|
|
1313
|
+
* 1. **Optional** — `.withIndex()` or `.withSearchIndex()` to use an index.
|
|
1314
|
+
* 2. **Optional** — `.filter()` to add arbitrary field predicates.
|
|
1315
|
+
* 3. **Optional** — `.order()` to control sort direction (defaults to `"asc"`).
|
|
1316
|
+
* 4. **Required terminal** — `.collect()`, `.take()`, `.first()`, `.unique()`,
|
|
1317
|
+
* or `.paginate()`.
|
|
1318
|
+
*
|
|
1319
|
+
* ```ts
|
|
1320
|
+
* // Fetch all tasks in a project, newest first, limited to 10
|
|
1321
|
+
* const tasks = await ctx.db
|
|
1322
|
+
* .query("tasks")
|
|
1323
|
+
* .withIndex("by_project", (q) => q.eq("projectId", id))
|
|
1324
|
+
* .order("desc")
|
|
1325
|
+
* .take(10);
|
|
1326
|
+
*
|
|
1327
|
+
* // Full-text search with a filter
|
|
1328
|
+
* const results = await ctx.db
|
|
1329
|
+
* .query("tasks")
|
|
1330
|
+
* .withSearchIndex("search_title", (q) =>
|
|
1331
|
+
* q.search("title", searchText).eq("status", "todo")
|
|
1332
|
+
* )
|
|
1333
|
+
* .collect();
|
|
1334
|
+
* ```
|
|
365
1335
|
*/
|
|
366
1336
|
interface QueryBuilder<TTable extends AnyTableDefinition, TDocument = InferDocument<TTable>> {
|
|
1337
|
+
/**
|
|
1338
|
+
* Restrict the query to documents matching an index range.
|
|
1339
|
+
*
|
|
1340
|
+
* @param indexName - The name of the index to use (must be registered via `defineTable().index()`).
|
|
1341
|
+
* @param builder - Optional callback that receives an `IndexRangeBuilder` and returns it
|
|
1342
|
+
* after chaining `eq`, `gt`, `gte`, `lt`, `lte` calls. Omit to return all documents in
|
|
1343
|
+
* index order.
|
|
1344
|
+
*/
|
|
367
1345
|
withIndex<TIndexName extends TableIndexNames<TTable>>(indexName: TIndexName, builder?: (range: IndexRangeBuilder<TableIndexFields<TTable, TIndexName>[number]>) => IndexRangeBuilder<TableIndexFields<TTable, TIndexName>[number]>): this;
|
|
1346
|
+
/**
|
|
1347
|
+
* Restrict the query to documents matching a full-text search index.
|
|
1348
|
+
*
|
|
1349
|
+
* @param indexName - The name of the search index (must be registered via `defineTable().searchIndex()`).
|
|
1350
|
+
* @param builder - Callback that calls `.search(field, text)` and optionally chains
|
|
1351
|
+
* `.eq(filterField, value)` conditions.
|
|
1352
|
+
*/
|
|
368
1353
|
withSearchIndex<TIndexName extends TableSearchIndexNames<TTable>>(indexName: TIndexName, builder: (search: SearchIndexBuilder<TableSearchIndexConfig<TTable, TIndexName>["searchField"], TableSearchIndexConfig<TTable, TIndexName>["filterFields"]>) => SearchIndexBuilder<TableSearchIndexConfig<TTable, TIndexName>["searchField"], TableSearchIndexConfig<TTable, TIndexName>["filterFields"]>): this;
|
|
1354
|
+
/**
|
|
1355
|
+
* Set the iteration order for this query. Defaults to `"asc"`.
|
|
1356
|
+
*
|
|
1357
|
+
* When used with `withIndex`, the order applies to the index's primary sort key.
|
|
1358
|
+
* When used without an index (full table scan), `"asc"` and `"desc"` refer to
|
|
1359
|
+
* insertion order.
|
|
1360
|
+
*/
|
|
369
1361
|
order(order: "asc" | "desc"): this;
|
|
1362
|
+
/**
|
|
1363
|
+
* Add an additional in-memory predicate that is applied after index
|
|
1364
|
+
* evaluation.
|
|
1365
|
+
*
|
|
1366
|
+
* Use this for conditions that cannot be expressed as an index range (e.g.
|
|
1367
|
+
* checking a field not covered by the active index). Heavy use of `filter`
|
|
1368
|
+
* on large tables causes a full index scan — prefer dedicated indexes for
|
|
1369
|
+
* frequently filtered fields.
|
|
1370
|
+
*/
|
|
370
1371
|
filter(builder: (filter: FilterBuilder) => QueryExpression): this;
|
|
1372
|
+
/** Execute the query and return all matching documents as an array. */
|
|
371
1373
|
collect(): Promise<TDocument[]>;
|
|
1374
|
+
/**
|
|
1375
|
+
* Execute the query and return at most `count` documents.
|
|
1376
|
+
*
|
|
1377
|
+
* More efficient than `collect()` when you only need a limited number of
|
|
1378
|
+
* results.
|
|
1379
|
+
*/
|
|
372
1380
|
take(count: number): Promise<TDocument[]>;
|
|
1381
|
+
/**
|
|
1382
|
+
* Execute the query and return the first matching document, or `null` if
|
|
1383
|
+
* there are no results.
|
|
1384
|
+
*/
|
|
373
1385
|
first(): Promise<TDocument | null>;
|
|
1386
|
+
/**
|
|
1387
|
+
* Execute the query and return the single matching document, or `null` if
|
|
1388
|
+
* there are no results. Throws if more than one document matches.
|
|
1389
|
+
*
|
|
1390
|
+
* Use when you expect exactly zero or one result (e.g. a unique index
|
|
1391
|
+
* lookup).
|
|
1392
|
+
*/
|
|
374
1393
|
unique(): Promise<TDocument | null>;
|
|
1394
|
+
/**
|
|
1395
|
+
* Execute the query with cursor-based pagination.
|
|
1396
|
+
*
|
|
1397
|
+
* Pass `PaginationOptions` (a `cursor` and `numItems`) to fetch one page at
|
|
1398
|
+
* a time. The returned `PaginationResult` contains the page items, the next
|
|
1399
|
+
* cursor, and an `isDone` flag.
|
|
1400
|
+
*/
|
|
375
1401
|
paginate(options: PaginationOptions): Promise<PaginationResult<TDocument>>;
|
|
376
1402
|
}
|
|
377
1403
|
/**
|
|
378
1404
|
* Local-first Syncore runtime that hosts your schema, functions, and storage.
|
|
1405
|
+
*
|
|
1406
|
+
* `SyncoreRuntime` is the central engine of every Syncore app. It owns the
|
|
1407
|
+
* SQLite driver, the storage adapter, the reactivity engine, and the
|
|
1408
|
+
* background scheduler. Platform-specific factory functions
|
|
1409
|
+
* (`createNodeSyncoreRuntime`, `createWebSyncoreRuntime`, etc.) wrap it with
|
|
1410
|
+
* environment-appropriate defaults so you rarely need to instantiate it
|
|
1411
|
+
* directly.
|
|
1412
|
+
*
|
|
1413
|
+
* **Lifecycle**
|
|
1414
|
+
* 1. Construct the runtime (schema migration is deferred until first use).
|
|
1415
|
+
* 2. Call `await runtime.start()` to apply the schema, start the scheduler,
|
|
1416
|
+
* and connect to devtools. The runtime emits `"runtime.connected"` when ready.
|
|
1417
|
+
* 3. Call `runtime.createClient()` to get a {@link SyncoreClient} for
|
|
1418
|
+
* invoking functions and subscribing to reactive queries.
|
|
1419
|
+
* 4. Call `await runtime.stop()` on shutdown to flush pending jobs and close
|
|
1420
|
+
* the database.
|
|
1421
|
+
*
|
|
1422
|
+
* ```ts
|
|
1423
|
+
* const runtime = new SyncoreRuntime({
|
|
1424
|
+
* schema,
|
|
1425
|
+
* functions,
|
|
1426
|
+
* driver: new NodeSqliteDriver("./db.sqlite"),
|
|
1427
|
+
* storage: new NodeFileStorageAdapter("./storage"),
|
|
1428
|
+
* });
|
|
1429
|
+
* await runtime.start();
|
|
1430
|
+
* const client = runtime.createClient();
|
|
1431
|
+
* ```
|
|
379
1432
|
*/
|
|
380
1433
|
declare class SyncoreRuntime<TSchema extends SyncoreDataModel> {
|
|
381
1434
|
private readonly options;
|
|
382
1435
|
private readonly kernel;
|
|
383
1436
|
constructor(options: SyncoreRuntimeOptions<TSchema>);
|
|
1437
|
+
/**
|
|
1438
|
+
* Start the runtime: apply the schema migration, initialise the scheduler,
|
|
1439
|
+
* and connect to devtools (if configured).
|
|
1440
|
+
*
|
|
1441
|
+
* Must be called and awaited before using the client. Calling `start()`
|
|
1442
|
+
* a second time is a no-op.
|
|
1443
|
+
*/
|
|
384
1444
|
start(): Promise<void>;
|
|
1445
|
+
/**
|
|
1446
|
+
* Prepare the runtime for direct (synchronous) access patterns used by
|
|
1447
|
+
* devtools and migration tooling.
|
|
1448
|
+
*
|
|
1449
|
+
* You do not need to call this in normal application code.
|
|
1450
|
+
*/
|
|
385
1451
|
prepareForDirectAccess(): Promise<void>;
|
|
1452
|
+
/**
|
|
1453
|
+
* Stop the runtime gracefully.
|
|
1454
|
+
*
|
|
1455
|
+
* Flushes any pending scheduler jobs, closes the SQLite driver, and
|
|
1456
|
+
* disconnects from devtools. Call this when your application is shutting
|
|
1457
|
+
* down to avoid database file corruption.
|
|
1458
|
+
*/
|
|
386
1459
|
stop(): Promise<void>;
|
|
1460
|
+
/**
|
|
1461
|
+
* Create a new {@link SyncoreClient} bound to this runtime.
|
|
1462
|
+
*
|
|
1463
|
+
* Multiple clients can be created from the same runtime — they all share
|
|
1464
|
+
* the same underlying database and reactivity engine. Usually you only need
|
|
1465
|
+
* one client per runtime instance.
|
|
1466
|
+
*/
|
|
387
1467
|
createClient(): SyncoreClient;
|
|
1468
|
+
/**
|
|
1469
|
+
* Return the low-level admin API.
|
|
1470
|
+
*
|
|
1471
|
+
* The admin API exposes devtools introspection, direct query/mutation
|
|
1472
|
+
* execution, and scheduler management. It is used by the devtools
|
|
1473
|
+
* dashboard and integration tooling — most application code should use
|
|
1474
|
+
* the regular `SyncoreClient` instead.
|
|
1475
|
+
*/
|
|
388
1476
|
getAdmin(): SyncoreRuntimeAdmin<TSchema>;
|
|
389
1477
|
runQuery<TArgs, TResult>(reference: FunctionReference<"query", TArgs, TResult>, args?: JsonObject, meta?: DevtoolsEventMeta): Promise<TResult>;
|
|
390
1478
|
runMutation<TArgs, TResult>(reference: FunctionReference<"mutation", TArgs, TResult>, args?: JsonObject, meta?: DevtoolsEventMeta): Promise<TResult>;
|
|
@@ -402,5 +1490,5 @@ declare function createFunctionReferenceFor<TDefinition extends {
|
|
|
402
1490
|
returnsValidator?: Validator<unknown, unknown, string>;
|
|
403
1491
|
}>(kind: FunctionKindFromDefinition<TDefinition>, name: string): FunctionReference<FunctionKindFromDefinition<TDefinition>, FunctionArgsFromDefinition<TDefinition>, FunctionResultFromDefinition<TDefinition>>;
|
|
404
1492
|
//#endregion
|
|
405
|
-
export { ActionCtx, CapabilityDescriptor, ComparisonOperator, DevtoolsLiveQueryScope, DevtoolsLiveQuerySnapshot, DevtoolsSink, DocumentForTable, ExecutionResult, FilterBuilder, ImpactScope, ImpactSet, IndexRangeBuilder, InsertValueForTable, JsonObject, MutationCtx, PaginationOptions, PaginationResult, PatchValueForTable, QueryBuilder, QueryCondition, QueryCtx, QueryExpression, RegisteredSyncoreFunction, RegisteredSyncoreHandler, RunResult, SchedulerApi, SchedulerOptions, SearchIndexBuilder, SearchQuery, StorageObject, StorageWriteInput, SyncoreCapabilities, SyncoreClient, SyncoreDataModel, SyncoreDatabaseReader, SyncoreDatabaseWriter, SyncoreExternalChangeApplier, SyncoreExternalChangeEvent, SyncoreExternalChangeReason, SyncoreExternalChangeScope, SyncoreExternalChangeSignal, SyncoreFunctionRegistry, SyncorePaginatedQueryStatus, SyncoreQueriesRequest, SyncoreQueryRequest, SyncoreQueryState, SyncoreQueryStatus, SyncoreResolvedComponents, SyncoreRuntime, SyncoreRuntimeAdmin, SyncoreRuntimeOptions, SyncoreRuntimeStatus, SyncoreRuntimeStatusKind, SyncoreRuntimeStatusReason, SyncoreSqlDriver, SyncoreStorageAdapter, SyncoreStorageApi, SyncoreWatch, TableNames, UpdateScheduledJobOptions, UsePaginatedQueryResult, createFunctionReference, createFunctionReferenceFor };
|
|
1493
|
+
export { ActionCtx, CapabilityDescriptor, ComparisonOperator, DevtoolsLiveQueryScope, DevtoolsLiveQuerySnapshot, DevtoolsSink, DocumentForTable, ExecutionResult, FilterBuilder, ImpactScope, ImpactSet, IndexRangeBuilder, InsertValueForTable, JsonObject, MutationCtx, PaginationOptions, PaginationResult, PatchValueForTable, QueryBuilder, QueryCondition, QueryCtx, QueryExpression, RegisteredSyncoreFunction, RegisteredSyncoreHandler, RunResult, SchedulerApi, SchedulerOptions, SearchIndexBuilder, SearchQuery, StorageObject, StorageWriteInput, SyncoreCapabilities, SyncoreClient, SyncoreDataModel, SyncoreDatabaseReader, SyncoreDatabaseWriter, SyncoreExternalChangeApplier, SyncoreExternalChangeEvent, SyncoreExternalChangeReason, SyncoreExternalChangeScope, SyncoreExternalChangeSignal, SyncoreFunctionRegistry, SyncorePaginatedQueryStatus, SyncoreQueriesRequest, SyncoreQueryRequest, SyncoreQueryState, SyncoreQueryStatus, SyncoreResolvedComponents, SyncoreRuntime, SyncoreRuntimeAdmin, SyncoreRuntimeCapabilities, SyncoreRuntimeOptions, SyncoreRuntimeStatus, SyncoreRuntimeStatusKind, SyncoreRuntimeStatusReason, SyncoreRuntimeStorageCapability, SyncoreSqlDriver, SyncoreStorageAdapter, SyncoreStorageApi, SyncoreWatch, TableNames, UpdateScheduledJobOptions, UsePaginatedQueryResult, createFunctionReference, createFunctionReferenceFor };
|
|
406
1494
|
//# sourceMappingURL=runtime.d.mts.map
|