@abloatai/ablo 0.28.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/Database.js +9 -6
- package/dist/SyncClient.d.ts +2 -2
- package/dist/SyncClient.js +22 -10
- package/dist/adapters/inMemoryStorage.js +18 -14
- package/dist/ai-sdk/coordinatedTool.d.ts +15 -2
- package/dist/auth/schemas.d.ts +6 -0
- package/dist/auth/schemas.js +7 -0
- package/dist/cli.cjs +815 -400
- package/dist/client/Ablo.d.ts +29 -23
- package/dist/client/Ablo.js +8 -196
- package/dist/client/claimHeartbeatLoop.d.ts +1 -1
- package/dist/client/claimHeartbeatLoop.js +1 -1
- package/dist/client/createInternalComponents.d.ts +4 -2
- package/dist/client/createInternalComponents.js +3 -1
- package/dist/client/durableWrites.d.ts +21 -0
- package/dist/client/durableWrites.js +46 -0
- package/dist/client/httpClient.d.ts +19 -45
- package/dist/client/httpClient.js +104 -26
- package/dist/client/httpTransport.d.ts +8 -0
- package/dist/client/{ApiClient.js → httpTransport.js} +78 -291
- package/dist/client/options.d.ts +43 -19
- package/dist/client/options.js +3 -2
- package/dist/client/resourceTypes.d.ts +9 -85
- package/dist/client/resourceTypes.js +1 -1
- package/dist/client/sessionMint.d.ts +5 -6
- package/dist/client/sessionMint.js +4 -5
- package/dist/client/validateAbloOptions.js +3 -3
- package/dist/coordination/schema.d.ts +30 -0
- package/dist/coordination/schema.js +14 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/errors.d.ts +4 -40
- package/dist/errors.js +5 -5
- package/dist/index.d.ts +14 -8
- package/dist/index.js +7 -5
- package/dist/interfaces/index.d.ts +3 -0
- package/dist/mutators/defineMutators.d.ts +18 -0
- package/dist/mutators/defineMutators.js +4 -8
- package/dist/react/index.d.ts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/select.d.ts +15 -0
- package/dist/schema/select.js +27 -3
- package/dist/source/connector.d.ts +3 -3
- package/dist/source/factory.d.ts +4 -6
- package/dist/source/factory.js +4 -7
- package/dist/source/index.d.ts +4 -4
- package/dist/source/index.js +2 -2
- package/dist/source/signing.d.ts +0 -3
- package/dist/source/types.d.ts +0 -26
- package/dist/stores/ObjectStore.js +8 -8
- package/dist/surface.d.ts +1 -1
- package/dist/surface.js +1 -0
- package/dist/sync/BootstrapFetcher.d.ts +10 -0
- package/dist/sync/BootstrapFetcher.js +27 -4
- package/dist/sync/createClaimStream.d.ts +11 -2
- package/dist/sync/createClaimStream.js +4 -3
- package/dist/testing/mocks/FakeDatabase.d.ts +1 -1
- package/dist/transactions/TransactionQueue.d.ts +2 -2
- package/dist/transactions/TransactionQueue.js +3 -3
- package/dist/transactions/commitEnvelope.d.ts +1 -1
- package/dist/transactions/commitEnvelope.js +2 -2
- package/dist/transactions/commitOutboxStore.d.ts +19 -19
- package/dist/transactions/durableWriteStore.d.ts +123 -0
- package/dist/transactions/durableWriteStore.js +30 -0
- package/dist/transactions/httpCommitEnvelope.d.ts +1 -0
- package/dist/transactions/httpCommitEnvelope.js +14 -12
- package/dist/transactions/idempotencyKey.d.ts +10 -0
- package/dist/transactions/idempotencyKey.js +9 -0
- package/dist/types/global.d.ts +10 -29
- package/dist/types/global.js +4 -7
- package/dist/types/streams.d.ts +2 -28
- package/dist/wire/frames.d.ts +6 -257
- package/dist/wire/frames.js +4 -25
- package/dist/wire/index.d.ts +4 -3
- package/dist/wire/index.js +2 -2
- package/dist/wire/protocolVersion.d.ts +30 -17
- package/dist/wire/protocolVersion.js +34 -18
- package/docs/agents.md +8 -3
- package/docs/api.md +6 -4
- package/docs/client-behavior.md +6 -3
- package/docs/coordination.md +2 -3
- package/docs/data-sources.md +5 -8
- package/docs/guarantees.md +21 -0
- package/docs/integration-guide.md +1 -0
- package/docs/migration.md +21 -1
- package/docs/quickstart.md +11 -0
- package/docs/react.md +0 -46
- package/examples/README.md +6 -5
- package/llms.txt +15 -15
- package/package.json +2 -7
- package/dist/client/ApiClient.d.ts +0 -177
- package/dist/commit/contract.d.ts +0 -493
- package/dist/commit/contract.js +0 -187
- package/dist/commit/index.d.ts +0 -6
- package/dist/commit/index.js +0 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared resource types for the typed clients and private HTTP transport.
|
|
3
3
|
* the commit and claim shapes, the session-mint params and resource, and the
|
|
4
4
|
* {@link HttpClaimApi} derivation. This module holds only types and has no runtime
|
|
5
5
|
* imports.
|
|
@@ -10,8 +10,7 @@ export type { ModelTarget, ModelClaim };
|
|
|
10
10
|
import type { SchemaRecord } from '../schema/schema.js';
|
|
11
11
|
import type { SyncGroupInput } from '../schema/roles.js';
|
|
12
12
|
import type { Claim, ClaimStream, ClaimWaitOptions, Duration, HeldClaim } from '../types/streams.js';
|
|
13
|
-
import type {
|
|
14
|
-
import type { ClaimOptions, ClaimParams, ClaimReadApi, AwaitedClaimMethod, ServerReadOptions } from './createModelProxy.js';
|
|
13
|
+
import type { ClaimOptions, ClaimParams, ClaimReadApi, AwaitedClaimMethod } from './createModelProxy.js';
|
|
15
14
|
/**
|
|
16
15
|
* The operations available on each model in the sync engine:
|
|
17
16
|
* `retrieve({ id })` — an async single-row server read
|
|
@@ -23,24 +22,13 @@ import type { ClaimOptions, ClaimParams, ClaimReadApi, AwaitedClaimMethod, Serve
|
|
|
23
22
|
export type { LocalCountOptions, LocalReadOptions, ModelListScope, ServerReadOptions, ModelRetrieveParams, ModelCreateParams, ModelUpdateParams, ModelDeleteParams, ClaimOptions, ClaimParams, ClaimLookupParams, ClaimReorderParams, Claim, ClaimHeartbeat, ClaimHeartbeatOptions, HeldClaim, ModelOperations, } from './createModelProxy.js';
|
|
24
23
|
export type ModelOperationAction = 'create' | 'update' | 'delete' | 'archive' | 'unarchive';
|
|
25
24
|
export type CommitWait = 'queued' | 'confirmed';
|
|
26
|
-
export interface ModelRead<T = Record<string, unknown>> {
|
|
27
|
-
/**
|
|
28
|
-
* The row, or `undefined` when no row matched the id (or it's outside the
|
|
29
|
-
* caller's scope). A miss is data-absence, not an error — `retrieve` never
|
|
30
|
-
* throws "not found", mirroring the WebSocket client's `T | undefined`.
|
|
31
|
-
* Branch on it: `const deal = (await ablo.deals.retrieve({ id })).data; if (!deal) …`.
|
|
32
|
-
*/
|
|
33
|
-
readonly data: T | undefined;
|
|
34
|
-
readonly stamp: number;
|
|
35
|
-
readonly claims: readonly ModelClaim[];
|
|
36
|
-
}
|
|
37
25
|
export type IfClaimedPolicy = 'return' | 'fail';
|
|
38
26
|
export interface ClaimedOptions {
|
|
39
27
|
/**
|
|
40
|
-
* What to do when another participant has claimed the target: `return`
|
|
41
|
-
*
|
|
42
|
-
* `
|
|
43
|
-
*
|
|
28
|
+
* What to do when another participant has claimed the target: `return` lets
|
|
29
|
+
* the read proceed; `fail` throws `AbloClaimedError`. Inspect claim state via
|
|
30
|
+
* `ablo.<model>.claim.state({ id })`. Waiting is a claim-side concern — take
|
|
31
|
+
* `ablo.<model>.claim({ id })` (it queues fairly); reads never block.
|
|
44
32
|
*/
|
|
45
33
|
readonly ifClaimed?: IfClaimedPolicy;
|
|
46
34
|
}
|
|
@@ -73,8 +61,7 @@ export interface ClaimCreateOptions {
|
|
|
73
61
|
export interface CommitOperationInput {
|
|
74
62
|
readonly action: ModelOperationAction;
|
|
75
63
|
/** The model name — matches `ablo.<model>` and the schema's `model()`. */
|
|
76
|
-
readonly model
|
|
77
|
-
readonly target?: ModelTarget;
|
|
64
|
+
readonly model: string;
|
|
78
65
|
readonly id?: string | null;
|
|
79
66
|
readonly data?: Record<string, unknown> | null;
|
|
80
67
|
readonly transactionId?: string | null;
|
|
@@ -82,9 +69,6 @@ export interface CommitOperationInput {
|
|
|
82
69
|
readonly onStale?: 'reject' | 'overwrite' | 'notify' | null;
|
|
83
70
|
}
|
|
84
71
|
export interface CommitCreateOptions {
|
|
85
|
-
readonly claimRef?: string | {
|
|
86
|
-
readonly id: string;
|
|
87
|
-
} | null;
|
|
88
72
|
readonly idempotencyKey?: string | null;
|
|
89
73
|
readonly readAt?: number | null;
|
|
90
74
|
readonly onStale?: 'reject' | 'overwrite' | 'notify' | null;
|
|
@@ -97,8 +81,8 @@ export interface CommitCreateOptions {
|
|
|
97
81
|
* Explicit `readAt`/`onStale` on the options win.
|
|
98
82
|
*/
|
|
99
83
|
readonly claim?: Claim | null;
|
|
100
|
-
|
|
101
|
-
readonly operations
|
|
84
|
+
/** One atomic batch. Use a one-element array for a single operation. */
|
|
85
|
+
readonly operations: readonly CommitOperationInput[];
|
|
102
86
|
readonly wait?: CommitWait;
|
|
103
87
|
/**
|
|
104
88
|
* Batch-level read dependencies — the "did anything I looked at change?" guard.
|
|
@@ -167,66 +151,6 @@ export interface ModelMutationOptions extends ClaimedOptions {
|
|
|
167
151
|
export type HttpClaimApi<T = Record<string, unknown>> = ((params: ClaimParams<T>) => Promise<HeldClaim<T>>) & {
|
|
168
152
|
[K in keyof ClaimReadApi<T>]: AwaitedClaimMethod<ClaimReadApi<T>[K]>;
|
|
169
153
|
};
|
|
170
|
-
export interface ModelClient<T = Record<string, unknown>> {
|
|
171
|
-
/**
|
|
172
|
-
* Single-row read over HTTP. **Returns an envelope, not the bare row** — the
|
|
173
|
-
* row is on `.data`, alongside the `.stamp` watermark (for stale-context
|
|
174
|
-
* guards on the following write) and any active `.claims`. A stateless HTTP
|
|
175
|
-
* client can't synthesize the watermark from a local snapshot, so the
|
|
176
|
-
* envelope is load-bearing here (the WebSocket client's `retrieve` returns
|
|
177
|
-
* `T | undefined` because it reads from its local cache).
|
|
178
|
-
*
|
|
179
|
-
* ```ts
|
|
180
|
-
* const deal = await ablo.deals.retrieve({ id });
|
|
181
|
-
* deal.data?.recommendation; // ← the row is on .data
|
|
182
|
-
* deal.stamp; // watermark — pass to the next write's readAt
|
|
183
|
-
* ```
|
|
184
|
-
*/
|
|
185
|
-
retrieve(params: ModelReadOptions & {
|
|
186
|
-
readonly id: string;
|
|
187
|
-
}): Promise<ModelRead<T>>;
|
|
188
|
-
/**
|
|
189
|
-
* Collection read over HTTP (server round-trip). Equality `where`, `orderBy`,
|
|
190
|
-
* `limit`. Present on the stateless protocol client; the store-backed
|
|
191
|
-
* `.model(name)` accessor omits it (use the typed `ablo.<model>.list` there).
|
|
192
|
-
*/
|
|
193
|
-
list?(options?: ServerReadOptions<T>): Promise<T[]>;
|
|
194
|
-
/**
|
|
195
|
-
* Creates a row and returns the confirmed server row, including framework
|
|
196
|
-
* defaults such as `createdAt` and `createdBy`. Matches the stateful client's
|
|
197
|
-
* `create`. Passing an id that already exists is idempotent: the existing row is
|
|
198
|
-
* returned, not the input.
|
|
199
|
-
*/
|
|
200
|
-
create(params: ModelMutationOptions & {
|
|
201
|
-
readonly data: Record<string, unknown>;
|
|
202
|
-
readonly id?: string | null;
|
|
203
|
-
}): Promise<T>;
|
|
204
|
-
update(params: ModelMutationOptions & {
|
|
205
|
-
readonly id: string;
|
|
206
|
-
readonly data: Record<string, unknown>;
|
|
207
|
-
}): Promise<CommitReceipt>;
|
|
208
|
-
/**
|
|
209
|
-
* Update under contention with a function of the latest state —
|
|
210
|
-
* `update(id, current => next)`, the `setState(prev => next)` of the data
|
|
211
|
-
* layer. The SDK reads the freshest row, runs your updater, writes it as a
|
|
212
|
-
* compare-and-swap against the row's watermark, and re-reads + re-runs on any
|
|
213
|
-
* concurrent write. No claim, no identity, no conflict codes surface: the
|
|
214
|
-
* write either lands or throws {@link AbloContentionError} once its reconcile
|
|
215
|
-
* budget is spent. Return `null`/`undefined` from the updater to skip the
|
|
216
|
-
* write (resolves to `undefined`).
|
|
217
|
-
*/
|
|
218
|
-
update(id: string, updater: ModelUpdater<T>, options?: ContentionOptions): Promise<CommitReceipt | undefined>;
|
|
219
|
-
delete(params: ModelMutationOptions & {
|
|
220
|
-
readonly id: string;
|
|
221
|
-
}): Promise<CommitReceipt>;
|
|
222
|
-
/**
|
|
223
|
-
* Durable lease + FIFO wait-line over HTTP — coordination without a socket.
|
|
224
|
-
* Present on the stateless protocol client (`Ablo({ schema: null })` /
|
|
225
|
-
* `createAbloHttpClient`); the store-backed `.model(name)` accessor omits it
|
|
226
|
-
* (the typed `ablo.<model>.claim` proxy is the full reactive namespace there).
|
|
227
|
-
*/
|
|
228
|
-
claim?: HttpClaimApi<T>;
|
|
229
|
-
}
|
|
230
154
|
/** A single data operation a scoped **agent** session may perform on a model. */
|
|
231
155
|
export type SessionOperation = 'read' | 'create' | 'update' | 'delete';
|
|
232
156
|
/** Parameters for minting an end-user session — full data authority within the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared resource types for the typed clients and private HTTP transport.
|
|
3
3
|
* the commit and claim shapes, the session-mint params and resource, and the
|
|
4
4
|
* {@link HttpClaimApi} derivation. This module holds only types and has no runtime
|
|
5
5
|
* imports.
|
|
@@ -10,14 +10,13 @@ export interface MintSessionContext {
|
|
|
10
10
|
readonly baseUrl: string;
|
|
11
11
|
readonly fetch?: typeof fetch;
|
|
12
12
|
/**
|
|
13
|
-
* Maps each schema key to its wire type name.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Maps each schema key to its wire type name. Every public client supplies
|
|
14
|
+
* this; it stays optional only for isolated private-transport use. A
|
|
15
|
+
* capability is scoped by the lowercased type name the server checks, but
|
|
16
|
+
* `can` is keyed by schema key — so
|
|
16
17
|
* `can: { documents: ['update'] }` on a model whose type name is overridden
|
|
17
18
|
* to `Document` must mint `document.update`, not `documents.update`, or the
|
|
18
|
-
* server denies the write with `capability_scope_denied`.
|
|
19
|
-
* client omits this map, because there the `can` key is already the wire
|
|
20
|
-
* token and needs no translation.
|
|
19
|
+
* server denies the write with `capability_scope_denied`.
|
|
21
20
|
*/
|
|
22
21
|
readonly modelTypenames?: Readonly<Record<string, string>>;
|
|
23
22
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Mints a session token. This is the single implementation behind
|
|
3
|
-
* `sessions.create`, shared by the
|
|
4
|
-
*
|
|
3
|
+
* `sessions.create`, shared by the WebSocket and HTTP clients so the two never
|
|
4
|
+
* disagree on how a token is produced.
|
|
5
5
|
*
|
|
6
6
|
* Minting is a plain control-plane HTTP call — no socket, no synced data. A
|
|
7
7
|
* backend holding a secret key (`sk_`) exchanges it for a short-lived, scoped
|
|
@@ -60,9 +60,8 @@ export async function mintSession(params, ctx) {
|
|
|
60
60
|
}
|
|
61
61
|
const operations = Object.entries(params.can).flatMap(([model, ops]) => {
|
|
62
62
|
// Translate the schema key the developer used in `can` into the wire type
|
|
63
|
-
// name the server checks — see `modelTypenames` above.
|
|
64
|
-
//
|
|
65
|
-
// absent from it.
|
|
63
|
+
// name the server checks — see `modelTypenames` above. The key fallback is
|
|
64
|
+
// private transport tolerance; every public client supplies the schema map.
|
|
66
65
|
const ns = ctx.modelTypenames?.[model] ?? model;
|
|
67
66
|
return (ops ?? []).map((op) => `${ns.toLowerCase()}.${op}`);
|
|
68
67
|
});
|
|
@@ -17,9 +17,9 @@ export function validateAbloOptions(input) {
|
|
|
17
17
|
return new AbloValidationError('Ablo: `url` is required. Pass the sync server URL, e.g. ' +
|
|
18
18
|
`Ablo({ baseURL: 'wss://api.abloatai.com', schema, user })`, { code: 'base_url_missing' });
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
if (!options.schema?.models) {
|
|
21
|
+
return new AbloValidationError('Ablo: `schema` is required. Define it once and access models as `ablo.<model>`.', { code: 'invalid_options', param: 'schema' });
|
|
22
|
+
}
|
|
23
23
|
if (!configuredApiKey &&
|
|
24
24
|
!configuredAuthToken &&
|
|
25
25
|
!options.capabilityToken &&
|
|
@@ -157,6 +157,9 @@ export type StaleNotification = z.infer<typeof staleNotificationSchema>;
|
|
|
157
157
|
* • Group — `{ group, readAt }`: did anything in this sync group change?
|
|
158
158
|
* `group` is a sync-group key such as `deck:abc` or `slide:s1`, the
|
|
159
159
|
* same unit a participant watches and claims.
|
|
160
|
+
*
|
|
161
|
+
* See `packages/sync-engine/docs/concurrency-convention.md` (§4) for the
|
|
162
|
+
* governing convention and the receive → reconcile loop.
|
|
160
163
|
*/
|
|
161
164
|
export declare const readDependencySchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
162
165
|
model: z.ZodString;
|
|
@@ -304,6 +307,33 @@ export declare const claimRejectionSchema: z.ZodObject<{
|
|
|
304
307
|
policyReason: z.ZodOptional<z.ZodString>;
|
|
305
308
|
}, z.core.$strip>;
|
|
306
309
|
export type ClaimRejection = z.infer<typeof claimRejectionSchema>;
|
|
310
|
+
/**
|
|
311
|
+
* The point-to-point notification sent to a holder whose lease ended without
|
|
312
|
+
* a successful commit. This remains a wire-shaped target because it arrives
|
|
313
|
+
* directly from the WebSocket; the schema is the single validation boundary
|
|
314
|
+
* before the event reaches public `claims.onLost` listeners.
|
|
315
|
+
*/
|
|
316
|
+
export declare const claimLostSchema: z.ZodObject<{
|
|
317
|
+
claimId: z.ZodString;
|
|
318
|
+
reason: z.ZodEnum<{
|
|
319
|
+
expired: "expired";
|
|
320
|
+
preempted: "preempted";
|
|
321
|
+
}>;
|
|
322
|
+
target: z.ZodObject<{
|
|
323
|
+
entityType: z.ZodString;
|
|
324
|
+
entityId: z.ZodString;
|
|
325
|
+
path: z.ZodOptional<z.ZodString>;
|
|
326
|
+
range: z.ZodOptional<z.ZodObject<{
|
|
327
|
+
startLine: z.ZodNumber;
|
|
328
|
+
endLine: z.ZodNumber;
|
|
329
|
+
startColumn: z.ZodOptional<z.ZodNumber>;
|
|
330
|
+
endColumn: z.ZodOptional<z.ZodNumber>;
|
|
331
|
+
}, z.core.$strip>>;
|
|
332
|
+
field: z.ZodOptional<z.ZodString>;
|
|
333
|
+
meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
334
|
+
}, z.core.$strip>;
|
|
335
|
+
}, z.core.$strip>;
|
|
336
|
+
export type ClaimLost = z.infer<typeof claimLostSchema>;
|
|
307
337
|
/**
|
|
308
338
|
* What a {@link ModelClaim} points at — the target locator as SDK callers see
|
|
309
339
|
* it, keyed by `model` and `id` rather than the wire schema's `entityType` and
|
|
@@ -165,6 +165,9 @@ export const staleNotificationSchema = z.object({
|
|
|
165
165
|
* • Group — `{ group, readAt }`: did anything in this sync group change?
|
|
166
166
|
* `group` is a sync-group key such as `deck:abc` or `slide:s1`, the
|
|
167
167
|
* same unit a participant watches and claims.
|
|
168
|
+
*
|
|
169
|
+
* See `packages/sync-engine/docs/concurrency-convention.md` (§4) for the
|
|
170
|
+
* governing convention and the receive → reconcile loop.
|
|
168
171
|
*/
|
|
169
172
|
export const readDependencySchema = z.union([
|
|
170
173
|
z.object({
|
|
@@ -249,6 +252,17 @@ export const claimRejectionSchema = z.object({
|
|
|
249
252
|
heldByClaim: wireClaimSummarySchema.optional(),
|
|
250
253
|
policyReason: z.string().optional(),
|
|
251
254
|
});
|
|
255
|
+
/**
|
|
256
|
+
* The point-to-point notification sent to a holder whose lease ended without
|
|
257
|
+
* a successful commit. This remains a wire-shaped target because it arrives
|
|
258
|
+
* directly from the WebSocket; the schema is the single validation boundary
|
|
259
|
+
* before the event reaches public `claims.onLost` listeners.
|
|
260
|
+
*/
|
|
261
|
+
export const claimLostSchema = z.object({
|
|
262
|
+
claimId: z.string(),
|
|
263
|
+
reason: z.enum(['expired', 'preempted']),
|
|
264
|
+
target: targetRefSchema,
|
|
265
|
+
});
|
|
252
266
|
/**
|
|
253
267
|
* What a {@link ModelClaim} points at — the target locator as SDK callers see
|
|
254
268
|
* it, keyed by `model` and `id` rather than the wire schema's `entityType` and
|
package/dist/core/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export { Model } from '../Model.js';
|
|
|
21
21
|
export { LazyReferenceCollection, type LazyCollectionOptions, } from '../LazyReferenceCollection.js';
|
|
22
22
|
export { ModelRegistry, getActiveRegistry, } from '../ModelRegistry.js';
|
|
23
23
|
export { postQuery, type PostQueryOptions } from '../query/client.js';
|
|
24
|
-
export { computeFKDepthPriority
|
|
24
|
+
export { computeFKDepthPriority } from '../client/Ablo.js';
|
|
25
25
|
export type { SyncLogger, SyncObservabilityProvider, MutationExecutor, SessionErrorDetector, OnlineStatusProvider, CommitResult, MutationOperation, } from '../interfaces/index.js';
|
|
26
26
|
export { SyncWebSocket, type SyncDelta, type SyncWebSocketOptions, } from '../sync/SyncWebSocket.js';
|
|
27
27
|
export { BootstrapFetcher } from '../sync/BootstrapFetcher.js';
|
package/dist/errors.d.ts
CHANGED
|
@@ -131,10 +131,10 @@ export declare class AbloValidationError extends AbloError {
|
|
|
131
131
|
}
|
|
132
132
|
/**
|
|
133
133
|
* An update or delete addressed a row that does not exist, or lies outside the
|
|
134
|
-
* caller's organization (HTTP 404).
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
134
|
+
* caller's organization (HTTP 404). Raw commit responses may report those
|
|
135
|
+
* targets as `missingIds`; typed model methods raise this error instead of
|
|
136
|
+
* returning a successful result for a write that quietly matched zero rows.
|
|
137
|
+
* The absent ids are carried on {@link missingIds}.
|
|
138
138
|
*/
|
|
139
139
|
export declare class AbloNotFoundError extends AbloError {
|
|
140
140
|
readonly type: "AbloNotFoundError";
|
|
@@ -292,42 +292,6 @@ export interface RequiredCapability {
|
|
|
292
292
|
* capability. */
|
|
293
293
|
readonly nonce?: string;
|
|
294
294
|
}
|
|
295
|
-
/**
|
|
296
|
-
* The receipt returned for every commit, whether it succeeded or was rejected,
|
|
297
|
-
* and regardless of how it was sent — the WebSocket `mutation_result` payload,
|
|
298
|
-
* the HTTP `/v1/commits` response body, and an agent job's result all use this
|
|
299
|
-
* one shape. It is a correlation receipt, carrying the ids and outcome needed to
|
|
300
|
-
* reconcile a commit rather than a cryptographic proof.
|
|
301
|
-
*/
|
|
302
|
-
export interface CommitReceipt {
|
|
303
|
-
readonly object: 'commit_receipt';
|
|
304
|
-
/** Client-issued idempotency handle. Echoed verbatim. */
|
|
305
|
-
readonly clientTxId: string;
|
|
306
|
-
/** Server-issued opaque commit id — typically `String(lastSyncId)`. */
|
|
307
|
-
readonly serverTxId: string;
|
|
308
|
-
/** A convenience boolean, equal to `status === 'confirmed'`. */
|
|
309
|
-
readonly success: boolean;
|
|
310
|
-
/** `'confirmed'` on apply, `'rejected'` on any failure. */
|
|
311
|
-
readonly status: 'confirmed' | 'rejected';
|
|
312
|
-
/** Last syncId visible after this commit (or high-water mark on
|
|
313
|
-
* rejection). */
|
|
314
|
-
readonly lastSyncId?: number;
|
|
315
|
-
/** Number of operations metered. Reported on both success and
|
|
316
|
-
* rejection so quota systems see attempted work. */
|
|
317
|
-
readonly ops?: number;
|
|
318
|
-
/** Ids of update or delete targets that matched no row. Present and non-empty
|
|
319
|
-
* only when a write missed; the typed resource methods raise
|
|
320
|
-
* {@link AbloNotFoundError} from it. */
|
|
321
|
-
readonly missingIds?: readonly string[];
|
|
322
|
-
/** Present on rejection. When set, `requiredCapability` carries the structured
|
|
323
|
-
* hint describing what would let the request succeed on retry. */
|
|
324
|
-
readonly error?: {
|
|
325
|
-
readonly code: string;
|
|
326
|
-
readonly message: string;
|
|
327
|
-
readonly field?: string;
|
|
328
|
-
readonly requiredCapability?: RequiredCapability;
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
295
|
/**
|
|
332
296
|
* A scoped credential was denied, either because the key is unknown, revoked, or
|
|
333
297
|
* expired (`capability_invalid`), or because the connection's scope does not
|
package/dist/errors.js
CHANGED
|
@@ -150,10 +150,10 @@ export class AbloValidationError extends AbloError {
|
|
|
150
150
|
}
|
|
151
151
|
/**
|
|
152
152
|
* An update or delete addressed a row that does not exist, or lies outside the
|
|
153
|
-
* caller's organization (HTTP 404).
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
153
|
+
* caller's organization (HTTP 404). Raw commit responses may report those
|
|
154
|
+
* targets as `missingIds`; typed model methods raise this error instead of
|
|
155
|
+
* returning a successful result for a write that quietly matched zero rows.
|
|
156
|
+
* The absent ids are carried on {@link missingIds}.
|
|
157
157
|
*/
|
|
158
158
|
export class AbloNotFoundError extends AbloError {
|
|
159
159
|
type = 'AbloNotFoundError';
|
|
@@ -442,7 +442,7 @@ const ErrorFieldSchema = z
|
|
|
442
442
|
const ErrorBodyShapeSchema = z
|
|
443
443
|
.object({
|
|
444
444
|
/** The `error` field may be a flat code string, as some endpoints return,
|
|
445
|
-
* or a nested error object, as
|
|
445
|
+
* or a nested error object, as commit endpoints return on rejection. */
|
|
446
446
|
error: ErrorFieldSchema,
|
|
447
447
|
code: OptionalWireStringSchema,
|
|
448
448
|
reason: OptionalWireStringSchema,
|
package/dist/index.d.ts
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
* type Entry = Ablo.Peer;
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
|
-
* `Ablo({ schema, apiKey })` returns typed model clients.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* `Ablo({ schema, apiKey })` returns typed model clients. Server-side agents,
|
|
18
|
+
* MCP route handlers, and workers select `transport: 'http'`; both transports
|
|
19
|
+
* keep the same `ablo.<model>` application surface.
|
|
20
20
|
*
|
|
21
21
|
* The whole package reaches you through one name: `Ablo` is at once a factory
|
|
22
22
|
* function, a type, and a namespace. You call model clients with dot access on
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
*
|
|
46
46
|
* A handful of exports are for advanced use and are marked "Advanced" at their
|
|
47
47
|
* declaration below, each with the one situation it is for:
|
|
48
|
-
* • `dataSource`
|
|
48
|
+
* • `dataSource` — when your own database stays canonical.
|
|
49
49
|
* • `defaultPolicy` — when you customize conflict resolution.
|
|
50
50
|
* • `defineMutators` / `createTransaction` — when you write custom mutators.
|
|
51
51
|
* If you don't recognize one of these, you don't need it.
|
|
@@ -54,12 +54,18 @@ export { Ablo } from './client/Ablo.js';
|
|
|
54
54
|
export type { MutationExecutor } from './interfaces/index.js';
|
|
55
55
|
export type { ModelUpdater, ContentionOptions } from './client/functionalUpdate.js';
|
|
56
56
|
export { DEFAULT_CONTENTION_RETRIES } from './client/functionalUpdate.js';
|
|
57
|
-
export type { HttpClaimApi, InternalAbloOptions } from './client/Ablo.js';
|
|
58
57
|
export type { AbloReads } from './client/Ablo.js';
|
|
59
58
|
export { type AbloHttpClientOptions, type AbloHttpClient, type HttpModelClient, } from './client/httpClient.js';
|
|
60
59
|
export { ABLO_DEFAULT_BASE_URL, ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, normalizeAbloHostedBaseUrl, } from './client/auth.js';
|
|
61
|
-
export type { AbloOptions, LocalCountOptions, LocalReadOptions, ModelListScope, ServerReadOptions, ModelRetrieveParams, ModelCreateParams, ModelUpdateParams, ModelDeleteParams,
|
|
60
|
+
export type { AbloOptions, LocalCountOptions, LocalReadOptions, ModelListScope, ServerReadOptions, ModelRetrieveParams, ModelCreateParams, ModelUpdateParams, ModelDeleteParams, } from './client/Ablo.js';
|
|
61
|
+
/**
|
|
62
|
+
* @deprecated Use `Ablo.Claim.Held`. This compatibility export remains until
|
|
63
|
+
* the next major release because it was explicitly documented in 0.20.1.
|
|
64
|
+
*/
|
|
65
|
+
export type { HeldClaim } from './client/Ablo.js';
|
|
62
66
|
export type { AbloPersistence } from './client/persistence.js';
|
|
67
|
+
export { durableWritesConfigSchema, durableWriteStoreSchema, pendingWriteSchema, } from './transactions/durableWriteStore.js';
|
|
68
|
+
export type { DurableWritesConfig, DurableWriteStore, PendingWrite, } from './transactions/durableWriteStore.js';
|
|
63
69
|
export type { CommitOutboxRecord, CommitOutboxStore, } from './transactions/commitOutboxStore.js';
|
|
64
70
|
export { durableCommitEnvelopeSchema, } from './transactions/commitEnvelope.js';
|
|
65
71
|
export type { CommitOutboxScope, DurableCommitEnvelope, } from './transactions/commitEnvelope.js';
|
|
@@ -67,11 +73,11 @@ export { durableHttpCommitEnvelopeSchema, } from './transactions/httpCommitEnvel
|
|
|
67
73
|
export type { DurableHttpCommitEnvelope, } from './transactions/httpCommitEnvelope.js';
|
|
68
74
|
import { Ablo } from './client/Ablo.js';
|
|
69
75
|
export default Ablo;
|
|
70
|
-
export { dataSource,
|
|
76
|
+
export { dataSource, sourceEventForOperation, signAbloSourceRequest, verifyAbloSourceRequest, } from './source/index.js';
|
|
71
77
|
export { createSourceConnector, type SourceConnector, type SourceConnectorOptions, type ConnectorStatus, } from './source/connector.js';
|
|
72
78
|
export { defaultPolicy, capabilityPreemptPolicy, interpretConflictAxis } from './policy/index.js';
|
|
73
79
|
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloNotFoundError, AbloServerError, AbloStaleContextError, AbloClaimedError, AbloContentionError, CapabilityError, translateHttpError, hasWireCode, errorFromWire, toAbloError, ERROR_CODES, ERROR_CONTRACT_VERSION, errorCodeSpec, isRetryableCode, classifyRecovery, recoveryClassSchema, RECOVERY_CLASSES, } from './errors.js';
|
|
74
|
-
export type {
|
|
80
|
+
export type { RequiredCapability } from './errors.js';
|
|
75
81
|
export type { ErrorCode, WireErrorCode, ErrorCategory, ErrorCodeSpec, RecoveryClass } from './errors.js';
|
|
76
82
|
export { errorEnvelope, statusForType } from './wire/errorEnvelope.js';
|
|
77
83
|
export type { ErrorEnvelope } from './wire/errorEnvelope.js';
|
package/dist/index.js
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
* type Entry = Ablo.Peer;
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
|
-
* `Ablo({ schema, apiKey })` returns typed model clients.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* `Ablo({ schema, apiKey })` returns typed model clients. Server-side agents,
|
|
18
|
+
* MCP route handlers, and workers select `transport: 'http'`; both transports
|
|
19
|
+
* keep the same `ablo.<model>` application surface.
|
|
20
20
|
*
|
|
21
21
|
* The whole package reaches you through one name: `Ablo` is at once a factory
|
|
22
22
|
* function, a type, and a namespace. You call model clients with dot access on
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
*
|
|
46
46
|
* A handful of exports are for advanced use and are marked "Advanced" at their
|
|
47
47
|
* declaration below, each with the one situation it is for:
|
|
48
|
-
* • `dataSource`
|
|
48
|
+
* • `dataSource` — when your own database stays canonical.
|
|
49
49
|
* • `defaultPolicy` — when you customize conflict resolution.
|
|
50
50
|
* • `defineMutators` / `createTransaction` — when you write custom mutators.
|
|
51
51
|
* If you don't recognize one of these, you don't need it.
|
|
@@ -63,6 +63,8 @@ export { DEFAULT_CONTENTION_RETRIES } from './client/functionalUpdate.js';
|
|
|
63
63
|
// `AbloHttpClient` type, which is the return type of that call.
|
|
64
64
|
export {} from './client/httpClient.js';
|
|
65
65
|
export { ABLO_DEFAULT_BASE_URL, ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, normalizeAbloHostedBaseUrl, } from './client/auth.js';
|
|
66
|
+
export { durableWritesConfigSchema, durableWriteStoreSchema, pendingWriteSchema, } from './transactions/durableWriteStore.js';
|
|
67
|
+
/* eslint-enable @typescript-eslint/no-deprecated */
|
|
66
68
|
export { durableCommitEnvelopeSchema, } from './transactions/commitEnvelope.js';
|
|
67
69
|
export { durableHttpCommitEnvelopeSchema, } from './transactions/httpCommitEnvelope.js';
|
|
68
70
|
// Participant types live under `Ablo.Participant.*` —
|
|
@@ -76,7 +78,7 @@ export default Ablo;
|
|
|
76
78
|
// database. The default is Ablo-managed storage; reach for this only when you
|
|
77
79
|
// have deliberately chosen to keep your database canonical. The matching types
|
|
78
80
|
// live under `Ablo.Source.*` (`Ablo.Source.Operation`, `Ablo.Source.Commit.Params`).
|
|
79
|
-
export { dataSource,
|
|
81
|
+
export { dataSource, sourceEventForOperation, signAbloSourceRequest, verifyAbloSourceRequest, } from './source/index.js';
|
|
80
82
|
// Serves the Data Source `commit`, `load`, and `list` operations over an
|
|
81
83
|
// outbound WebSocket, so a database with no public inbound URL (running on a
|
|
82
84
|
// developer's machine or inside a locked-down network) can still be reached by
|
|
@@ -230,6 +230,9 @@ export interface MutationOptions {
|
|
|
230
230
|
* checks that none of them moved since their `readAt` and applies the entry's
|
|
231
231
|
* `onStale` behavior to the whole batch. This is distinct from the per-operation
|
|
232
232
|
* `readAt`, which guards only the row being written.
|
|
233
|
+
*
|
|
234
|
+
* See `packages/sync-engine/docs/concurrency-convention.md` (§3 the two
|
|
235
|
+
* footprints, §4 the read-set) for the governing convention.
|
|
233
236
|
*/
|
|
234
237
|
reads?: ReadDependency[] | null;
|
|
235
238
|
}
|
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { Schema } from '../schema/schema.js';
|
|
15
15
|
import type { Transaction } from './Transaction.js';
|
|
16
|
+
import type { ResolveSchema } from '../types/global.js';
|
|
17
|
+
/**
|
|
18
|
+
* `ResolveSchema` narrowed to satisfy the `Schema` bound — mirrors
|
|
19
|
+
* {@link Ablo.RegisteredSchema}. When nothing is registered, `ResolveSchema`
|
|
20
|
+
* is a loose `{ models }` shape that doesn't extend `Schema`, so we fall back
|
|
21
|
+
* to `Schema` to keep the mutator tree typed rather than collapsing.
|
|
22
|
+
*/
|
|
23
|
+
type RegisteredSchema = ResolveSchema extends Schema ? ResolveSchema : Schema;
|
|
16
24
|
/**
|
|
17
25
|
* The signature of a single custom mutator. The engine supplies `tx`; you control
|
|
18
26
|
* `args`, in whatever shape you like, and the resolved return value. `TArgs` and
|
|
@@ -40,3 +48,13 @@ export type MutatorDefs<S extends Schema> = {
|
|
|
40
48
|
* work here; the function exists purely as a place for type inference to anchor.
|
|
41
49
|
*/
|
|
42
50
|
export declare function defineMutators<S extends Schema, const M extends MutatorDefs<S>>(_schema: S, mutators: M): M;
|
|
51
|
+
/**
|
|
52
|
+
* Register-anchored overload: omit the schema value and the tree is typed
|
|
53
|
+
* against `ResolveSchema` (this app's registered schema). Shared product code
|
|
54
|
+
* used across apps that bind different schemas should use this form — it moves
|
|
55
|
+
* with each app's `Register` instead of pinning one concrete schema, so the
|
|
56
|
+
* mutator tree stays assignable at every consumer (which reads the same
|
|
57
|
+
* `Register`). See docs/plans/per-product-schema-projections.md.
|
|
58
|
+
*/
|
|
59
|
+
export declare function defineMutators<const M extends MutatorDefs<RegisteredSchema>>(mutators: M): M;
|
|
60
|
+
export {};
|
|
@@ -11,12 +11,8 @@
|
|
|
11
11
|
* `typeof mutators` carries every mutator's precise `args` and result types
|
|
12
12
|
* through to wherever they are invoked.
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* work here; the function exists purely as a place for type inference to anchor.
|
|
19
|
-
*/
|
|
20
|
-
export function defineMutators(_schema, mutators) {
|
|
21
|
-
return mutators;
|
|
14
|
+
export function defineMutators(schemaOrMutators, maybeMutators) {
|
|
15
|
+
// The schema argument is a type anchor only — never read at runtime. With one
|
|
16
|
+
// argument the mutator tree is in the first slot; with two it's in the second.
|
|
17
|
+
return (maybeMutators ?? schemaOrMutators);
|
|
22
18
|
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
* useAblo((ablo) => ablo.<model>.claim.state(...)) — reactive coordination reads
|
|
44
44
|
* useWatch({ scope }) — join a scope to get its peers and claims
|
|
45
45
|
*/
|
|
46
|
-
export type { DefaultSyncShape, ResolveSchema,
|
|
46
|
+
export type { DefaultSyncShape, ResolveSchema, ResolveUserMeta, ResolveModelKey, } from '../types/global.js';
|
|
47
47
|
export { AbloProvider, useWatch, usePeers, useSync, useSyncStore, type AbloProviderProps, type ParticipantScope, type ParticipantStatus, type UseWatchOptions, type UseWatchReturn, type MeshParticipantStatus, } from './AbloProvider.js';
|
|
48
48
|
export { ClientSideSuspense, type ClientSideSuspenseProps, } from './ClientSideSuspense.js';
|
|
49
49
|
export { DefaultFallback } from './DefaultFallback.js';
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export { coordination, humansOverwrite, humansReject, humansNotify, agentsOverwr
|
|
|
32
32
|
export { mutable, readOnly, type SugarOptions } from './sugar.js';
|
|
33
33
|
export { defineSchema, composeIdentitySyncGroups, type Schema, type SchemaRecord, type Model, type Row, type InferModel, type InferCreate, type InferRow, type InferModelNames, type BaseModelFields, type InsertValue, type UpsertValue, type UpdateValue, type DeleteId, type DefineSchemaOptions, type Casing, type CasingConvention, type CasingFn, composeEntitySyncGroups, intersectRequestedWithAllowed, type IdentityRole, type IdentityContext, type IdentityRoleSource, type EntityRole, type EntityContext, type EntityRoleSource, type RoleSource, type RoleContext, type SyncGroup, type SyncGroupInput, identityRole, entityRole, extractIdentityIds, extractEntityIds, syncGroup, syncGroupSchema, syncGroupInputSchema, isSyncGroupInput, identityRoleSchema, entityRoleSchema, roleSchema, roleSourceSchema, scopeSchema, grantsRefSchema, groupsInputSchema, type GroupsInput, } from './schema.js';
|
|
34
34
|
export { serializeSchema, parseSchema, toSchemaJSON, fromSchemaJSON, schemaHash, type SchemaJSON, type ModelJSON, type RelationJSON, } from './serialize.js';
|
|
35
|
-
export { selectModels } from './select.js';
|
|
35
|
+
export { selectModels, omitModels } from './select.js';
|
|
36
36
|
export { generateProvisionPlan, generateMigrationPlan, appSchemaName, camelToSnake, snakeToCamel, q, sqlType, type ProvisionPlan, type MigrationPlan, } from './ddl.js';
|
|
37
37
|
export { PG_LOCK_NOT_AVAILABLE, resolveDdlLockTimeout, resolveDdlMaxLockAttempts, ddlLockRetryBackoffMs, type DdlLockEnv, } from './ddlLock.js';
|
|
38
38
|
export { diffSchema, classifyMigration, classifyCast, isAutoApplicable, isBlockerResolved, unresolvedBlockers, type BackfillValue, type MigrationStep, type FieldChanges, type FieldColumnChange, type FieldTypeChange, type NullabilityChange, type EnumValuesChange, type IndexChange, type CastSafety, type FieldType, type RenameHints, type MigrationSignal, type MigrationClassification, type WarningCode, type BlockerCode, } from './diff.js';
|
package/dist/schema/index.js
CHANGED
|
@@ -57,7 +57,7 @@ export { defineSchema, composeIdentitySyncGroups, composeEntitySyncGroups, inter
|
|
|
57
57
|
// Schema ⇄ JSON — serialize a schema for transport and rebuild it on the far side.
|
|
58
58
|
export { serializeSchema, parseSchema, toSchemaJSON, fromSchemaJSON, schemaHash, } from './serialize.js';
|
|
59
59
|
// Schema projection — derive an app's subset from one canonical schema.
|
|
60
|
-
export { selectModels } from './select.js';
|
|
60
|
+
export { selectModels, omitModels } from './select.js';
|
|
61
61
|
// Schema → Postgres DDL — shared by the host implementation and the command-line tools.
|
|
62
62
|
export { generateProvisionPlan, generateMigrationPlan, appSchemaName, camelToSnake, snakeToCamel, q, sqlType, } from './ddl.js';
|
|
63
63
|
// Safe-DDL locking knobs (lock_timeout plus a bounded retry on lock contention),
|
package/dist/schema/select.d.ts
CHANGED
|
@@ -23,3 +23,18 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import type { Schema, SchemaRecord } from './schema.js';
|
|
25
25
|
export declare function selectModels<S extends SchemaRecord, K extends keyof S & string>(schema: Schema<S>, keys: readonly K[]): Schema<Pick<S, K>>;
|
|
26
|
+
/**
|
|
27
|
+
* `omitModels` is `selectModels` from the other side: keep every model EXCEPT
|
|
28
|
+
* the named ones. Use it when an app is the general case and another product
|
|
29
|
+
* owns the omitted models — e.g. the product suite shell drops the standalone
|
|
30
|
+
* Mail store, which `@ablo/mail-schema` selects for the mail app:
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* export const schema = omitModels(full, ['mailMailboxes', 'mailThreads']);
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Same validation as `selectModels`: relations into the omitted set are
|
|
37
|
+
* dropped, and a dropped `parent` edge throws — so a model whose scope routes
|
|
38
|
+
* through an omitted parent cannot be silently kept.
|
|
39
|
+
*/
|
|
40
|
+
export declare function omitModels<S extends SchemaRecord, K extends keyof S & string>(schema: Schema<S>, keys: readonly K[]): Schema<Omit<S, K>>;
|