@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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product-facing persistence contract for writes that must survive a process
|
|
3
|
+
* restart or an ambiguous network response.
|
|
4
|
+
*
|
|
5
|
+
* The engine implements this contract with a transactional outbox internally,
|
|
6
|
+
* but callers should only need to think in terms of pending durable writes.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
/** Every write shape that Ablo may ask an injected store to persist. */
|
|
10
|
+
export declare const pendingWriteSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
type: z.ZodLiteral<"commit_envelope">;
|
|
13
|
+
storageVersion: z.ZodLiteral<1>;
|
|
14
|
+
origin: z.ZodEnum<{
|
|
15
|
+
model_batch: "model_batch";
|
|
16
|
+
atomic_commit: "atomic_commit";
|
|
17
|
+
}>;
|
|
18
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
19
|
+
operations: z.ZodArray<z.ZodObject<{
|
|
20
|
+
type: z.ZodEnum<{
|
|
21
|
+
CREATE: "CREATE";
|
|
22
|
+
UPDATE: "UPDATE";
|
|
23
|
+
DELETE: "DELETE";
|
|
24
|
+
ARCHIVE: "ARCHIVE";
|
|
25
|
+
UNARCHIVE: "UNARCHIVE";
|
|
26
|
+
}>;
|
|
27
|
+
readAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
28
|
+
onStale: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
29
|
+
reject: "reject";
|
|
30
|
+
overwrite: "overwrite";
|
|
31
|
+
notify: "notify";
|
|
32
|
+
}>>>;
|
|
33
|
+
model: z.ZodString;
|
|
34
|
+
id: z.ZodString;
|
|
35
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
36
|
+
transactionId: z.ZodOptional<z.ZodString>;
|
|
37
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
38
|
+
idempotencyKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
39
|
+
label: z.ZodOptional<z.ZodString>;
|
|
40
|
+
}, z.core.$strict>>;
|
|
41
|
+
}, z.core.$strip>>;
|
|
42
|
+
sourceMutationIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
43
|
+
commitOptions: z.ZodDefault<z.ZodObject<{
|
|
44
|
+
causedByTaskId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
45
|
+
reads: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
46
|
+
model: z.ZodString;
|
|
47
|
+
id: z.ZodString;
|
|
48
|
+
readAt: z.ZodNumber;
|
|
49
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
onStale: z.ZodOptional<z.ZodEnum<{
|
|
51
|
+
reject: "reject";
|
|
52
|
+
overwrite: "overwrite";
|
|
53
|
+
notify: "notify";
|
|
54
|
+
}>>;
|
|
55
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
56
|
+
group: z.ZodString;
|
|
57
|
+
readAt: z.ZodNumber;
|
|
58
|
+
onStale: z.ZodOptional<z.ZodEnum<{
|
|
59
|
+
reject: "reject";
|
|
60
|
+
overwrite: "overwrite";
|
|
61
|
+
notify: "notify";
|
|
62
|
+
}>>;
|
|
63
|
+
}, z.core.$strip>]>>>>;
|
|
64
|
+
}, z.core.$strict>>;
|
|
65
|
+
scope: z.ZodOptional<z.ZodObject<{
|
|
66
|
+
organizationId: z.ZodString;
|
|
67
|
+
participantId: z.ZodString;
|
|
68
|
+
namespace: z.ZodString;
|
|
69
|
+
}, z.core.$strict>>;
|
|
70
|
+
createdAt: z.ZodNumber;
|
|
71
|
+
sealedAt: z.ZodNumber;
|
|
72
|
+
sequence: z.ZodOptional<z.ZodNumber>;
|
|
73
|
+
timestamp: z.ZodNumber;
|
|
74
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
75
|
+
id: z.ZodString;
|
|
76
|
+
type: z.ZodLiteral<"http_commit_envelope">;
|
|
77
|
+
storageVersion: z.ZodLiteral<1>;
|
|
78
|
+
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
79
|
+
protocolVersion: z.ZodDefault<z.ZodNumber>;
|
|
80
|
+
request: z.ZodObject<{
|
|
81
|
+
method: z.ZodEnum<{
|
|
82
|
+
DELETE: "DELETE";
|
|
83
|
+
POST: "POST";
|
|
84
|
+
PATCH: "PATCH";
|
|
85
|
+
}>;
|
|
86
|
+
path: z.ZodString;
|
|
87
|
+
body: z.ZodString;
|
|
88
|
+
}, z.core.$strict>;
|
|
89
|
+
scopeNamespace: z.ZodString;
|
|
90
|
+
createdAt: z.ZodNumber;
|
|
91
|
+
sealedAt: z.ZodNumber;
|
|
92
|
+
sequence: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
timestamp: z.ZodNumber;
|
|
94
|
+
}, z.core.$strict>]>;
|
|
95
|
+
export type PendingWrite = z.infer<typeof pendingWriteSchema>;
|
|
96
|
+
/**
|
|
97
|
+
* Persistence port used by `Ablo({ durableWrites })`.
|
|
98
|
+
*
|
|
99
|
+
* `seal` is the durability boundary: it must atomically persist the exact write
|
|
100
|
+
* and consume the staged records that write supersedes. Resolving this promise
|
|
101
|
+
* authorizes Ablo to dispatch the request, so adapters must never report success
|
|
102
|
+
* before the data is durable.
|
|
103
|
+
*/
|
|
104
|
+
export interface DurableWriteStore {
|
|
105
|
+
/**
|
|
106
|
+
* Atomically reserve a pending write and consume the staged records it owns.
|
|
107
|
+
* The same id + same request is idempotent; the same id + a different request
|
|
108
|
+
* must be rejected.
|
|
109
|
+
*/
|
|
110
|
+
seal(write: PendingWrite, consumedRecordIds: readonly string[]): Promise<void>;
|
|
111
|
+
/** Load all unacknowledged writes. Stored data is treated as untrusted. */
|
|
112
|
+
list(): Promise<readonly unknown[]>;
|
|
113
|
+
/** Remove one write only after its outcome is definitive. */
|
|
114
|
+
remove(writeId: string): Promise<void>;
|
|
115
|
+
}
|
|
116
|
+
/** Runtime validation for injected adapters, including JavaScript consumers. */
|
|
117
|
+
export declare const durableWriteStoreSchema: z.ZodCustom<DurableWriteStore, DurableWriteStore>;
|
|
118
|
+
/** Options for crash-durable `create`, `update`, and `delete` calls. */
|
|
119
|
+
export declare const durableWritesConfigSchema: z.ZodObject<{
|
|
120
|
+
store: z.ZodCustom<DurableWriteStore, DurableWriteStore>;
|
|
121
|
+
namespace: z.ZodOptional<z.ZodString>;
|
|
122
|
+
}, z.core.$strict>;
|
|
123
|
+
export type DurableWritesConfig = z.infer<typeof durableWritesConfigSchema>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product-facing persistence contract for writes that must survive a process
|
|
3
|
+
* restart or an ambiguous network response.
|
|
4
|
+
*
|
|
5
|
+
* The engine implements this contract with a transactional outbox internally,
|
|
6
|
+
* but callers should only need to think in terms of pending durable writes.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { durableCommitEnvelopeSchema } from './commitEnvelope.js';
|
|
10
|
+
import { durableHttpCommitEnvelopeSchema } from './httpCommitEnvelope.js';
|
|
11
|
+
/** Every write shape that Ablo may ask an injected store to persist. */
|
|
12
|
+
export const pendingWriteSchema = z.union([
|
|
13
|
+
durableCommitEnvelopeSchema,
|
|
14
|
+
durableHttpCommitEnvelopeSchema,
|
|
15
|
+
]);
|
|
16
|
+
/** Runtime validation for injected adapters, including JavaScript consumers. */
|
|
17
|
+
export const durableWriteStoreSchema = z.custom((value) => {
|
|
18
|
+
if (typeof value !== 'object' || value === null)
|
|
19
|
+
return false;
|
|
20
|
+
const candidate = value;
|
|
21
|
+
return (typeof candidate.seal === 'function' &&
|
|
22
|
+
typeof candidate.list === 'function' &&
|
|
23
|
+
typeof candidate.remove === 'function');
|
|
24
|
+
}, { message: 'store must implement seal(), list(), and remove()' });
|
|
25
|
+
/** Options for crash-durable `create`, `update`, and `delete` calls. */
|
|
26
|
+
export const durableWritesConfigSchema = z.strictObject({
|
|
27
|
+
store: durableWriteStoreSchema,
|
|
28
|
+
/** Separates deployments or workflow lanes that share an authenticated actor. */
|
|
29
|
+
namespace: z.string().trim().min(1).optional(),
|
|
30
|
+
});
|
|
@@ -11,6 +11,7 @@ export declare const durableHttpCommitEnvelopeSchema: z.ZodObject<{
|
|
|
11
11
|
type: z.ZodLiteral<"http_commit_envelope">;
|
|
12
12
|
storageVersion: z.ZodLiteral<1>;
|
|
13
13
|
idempotencyKey: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
14
|
+
protocolVersion: z.ZodDefault<z.ZodNumber>;
|
|
14
15
|
request: z.ZodObject<{
|
|
15
16
|
method: z.ZodEnum<{
|
|
16
17
|
DELETE: "DELETE";
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/** Crash-durable exact HTTP request used by the stateless agent client. */
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { v5 as uuidv5 } from 'uuid';
|
|
4
|
-
import { idempotencyKeySchema } from '../commit/contract.js';
|
|
5
4
|
import { stableStringify } from '../utils/json.js';
|
|
5
|
+
import { PROTOCOL_VERSION } from '../wire/protocolVersion.js';
|
|
6
|
+
import { idempotencyKeySchema } from './idempotencyKey.js';
|
|
6
7
|
export const HTTP_COMMIT_ENVELOPE_VERSION = 1;
|
|
7
8
|
export const HTTP_COMMIT_ENVELOPE_PREFIX = 'http-commit-envelope:';
|
|
8
9
|
/** Stay one hour inside the server's 24-hour idempotency retention window. */
|
|
@@ -45,6 +46,11 @@ export const durableHttpCommitEnvelopeSchema = z
|
|
|
45
46
|
type: z.literal('http_commit_envelope'),
|
|
46
47
|
storageVersion: z.literal(HTTP_COMMIT_ENVELOPE_VERSION),
|
|
47
48
|
idempotencyKey: idempotencyKeySchema,
|
|
49
|
+
/**
|
|
50
|
+
* The wire contract used when this exact request was sealed. Entries from
|
|
51
|
+
* before protocol versioning omitted the field and are v1 by definition.
|
|
52
|
+
*/
|
|
53
|
+
protocolVersion: z.number().int().positive().default(1),
|
|
48
54
|
request: z.strictObject({
|
|
49
55
|
method: z.enum(['POST', 'PATCH', 'DELETE']),
|
|
50
56
|
path: z.string().startsWith('/'),
|
|
@@ -111,21 +117,16 @@ export const durableHttpCommitEnvelopeSchema = z
|
|
|
111
117
|
return;
|
|
112
118
|
}
|
|
113
119
|
const record = body;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
message: 'HTTP body idempotency key must match its envelope',
|
|
119
|
-
});
|
|
120
|
-
}
|
|
120
|
+
// `envelope.idempotencyKey` is replayed as the `Idempotency-Key` header.
|
|
121
|
+
// Older sealed bodies may also carry `idempotencyKey`/`clientTxId`; accept
|
|
122
|
+
// and replay them byte-for-byte, but current requests do not duplicate the
|
|
123
|
+
// key in JSON.
|
|
121
124
|
if (path === '/v1/commits') {
|
|
122
|
-
if (record.
|
|
123
|
-
!Array.isArray(record.operations) ||
|
|
124
|
-
record.operations.length === 0) {
|
|
125
|
+
if (!Array.isArray(record.operations) || record.operations.length === 0) {
|
|
125
126
|
context.addIssue({
|
|
126
127
|
code: 'custom',
|
|
127
128
|
path: ['request', 'body'],
|
|
128
|
-
message: 'Commit-route body must carry
|
|
129
|
+
message: 'Commit-route body must carry operations',
|
|
129
130
|
});
|
|
130
131
|
}
|
|
131
132
|
}
|
|
@@ -162,6 +163,7 @@ export function createDurableHttpCommitEnvelope(input) {
|
|
|
162
163
|
type: 'http_commit_envelope',
|
|
163
164
|
storageVersion: HTTP_COMMIT_ENVELOPE_VERSION,
|
|
164
165
|
idempotencyKey: input.idempotencyKey,
|
|
166
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
165
167
|
request: {
|
|
166
168
|
method: input.request.method,
|
|
167
169
|
path: input.request.path,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity shared by the durable write records.
|
|
3
|
+
*
|
|
4
|
+
* A retry must reuse the same non-empty key so the server can recognize the
|
|
5
|
+
* same logical write. This is a persistence invariant, not a second commit
|
|
6
|
+
* protocol.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
export declare const idempotencyKeySchema: z.core.$ZodBranded<z.ZodString, "IdempotencyKey", "out">;
|
|
10
|
+
export type IdempotencyKey = z.output<typeof idempotencyKeySchema>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity shared by the durable write records.
|
|
3
|
+
*
|
|
4
|
+
* A retry must reuse the same non-empty key so the server can recognize the
|
|
5
|
+
* same logical write. This is a persistence invariant, not a second commit
|
|
6
|
+
* protocol.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
export const idempotencyKeySchema = z.string().min(1).max(255).brand();
|
package/dist/types/global.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The single place where you tell the SDK about your application's types.
|
|
3
3
|
*
|
|
4
|
-
* You register your Schema
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* site.
|
|
4
|
+
* You register your Schema and UserMeta once by augmenting the
|
|
5
|
+
* {@link Register} interface. From then on the typed SDK surface reads its
|
|
6
|
+
* types from that registration, so you never pass a generic or a `schema`
|
|
7
|
+
* argument at a call site.
|
|
9
8
|
*
|
|
10
9
|
* Registration uses TypeScript module augmentation: any file in your project
|
|
11
10
|
* can add an `interface Register` to a `declare module '@abloatai/ablo'`
|
|
@@ -27,8 +26,6 @@
|
|
|
27
26
|
* declare module '@abloatai/ablo' {
|
|
28
27
|
* interface Register {
|
|
29
28
|
* Schema: typeof schema;
|
|
30
|
-
* Presence: { cursor: { x: number; y: number } | null };
|
|
31
|
-
* Claims: { editLayer: { layerId: string } };
|
|
32
29
|
* UserMeta: { id: string; email: string };
|
|
33
30
|
* }
|
|
34
31
|
* }
|
|
@@ -39,18 +36,18 @@
|
|
|
39
36
|
* {@link DefaultSyncShape} — a loose shape that keeps your code compiling
|
|
40
37
|
* without typed results until you opt in.
|
|
41
38
|
*/
|
|
39
|
+
import type { SchemaRecord } from '../schema/schema.js';
|
|
42
40
|
/**
|
|
43
41
|
* The fallback shapes the resolvers use when {@link Register} has not been
|
|
44
42
|
* augmented. `DefaultSyncShape.Schema` is deliberately structural — it carries
|
|
45
|
-
* `{ models:
|
|
46
|
-
*
|
|
43
|
+
* `{ models: SchemaRecord }` so hooks can still check a model-key argument
|
|
44
|
+
* against something (and satisfy the `SchemaRecord` bound), just without a
|
|
45
|
+
* typed entity shape behind it.
|
|
47
46
|
*/
|
|
48
47
|
export interface DefaultSyncShape {
|
|
49
48
|
readonly Schema: {
|
|
50
|
-
readonly models:
|
|
49
|
+
readonly models: SchemaRecord;
|
|
51
50
|
};
|
|
52
|
-
readonly Presence: Record<string, unknown>;
|
|
53
|
-
readonly Claims: Record<string, unknown>;
|
|
54
51
|
readonly UserMeta: {
|
|
55
52
|
readonly id: string;
|
|
56
53
|
};
|
|
@@ -58,7 +55,7 @@ export interface DefaultSyncShape {
|
|
|
58
55
|
/**
|
|
59
56
|
* The registration interface you augment to declare your application's types.
|
|
60
57
|
* Add keys inside a `declare module '@abloatai/ablo'` block — for example
|
|
61
|
-
* `interface Register { Schema: ...;
|
|
58
|
+
* `interface Register { Schema: ...; UserMeta: ...; }`. It is empty by default,
|
|
62
59
|
* so any key you omit falls back to {@link DefaultSyncShape}. It is exported
|
|
63
60
|
* from the package root so your augmentation merges into this declaration.
|
|
64
61
|
*
|
|
@@ -77,22 +74,6 @@ export type ResolveSchema = Register extends {
|
|
|
77
74
|
} ? S extends {
|
|
78
75
|
models: Record<string, unknown>;
|
|
79
76
|
} ? S : DefaultSyncShape['Schema'] : DefaultSyncShape['Schema'];
|
|
80
|
-
/**
|
|
81
|
-
* Your registered presence shape, or the default when none is registered.
|
|
82
|
-
* `usePresence` reads it. The shape is free-form — any JSON-serializable value
|
|
83
|
-
* you broadcast per session.
|
|
84
|
-
*/
|
|
85
|
-
export type ResolvePresence = Register extends {
|
|
86
|
-
Presence: infer P;
|
|
87
|
-
} ? P : DefaultSyncShape['Presence'];
|
|
88
|
-
/**
|
|
89
|
-
* Your registered claim vocabulary, or the default when none is registered.
|
|
90
|
-
* Each key is a claim name and its value is that claim's payload.
|
|
91
|
-
* `useClaim(claimName)` reads it.
|
|
92
|
-
*/
|
|
93
|
-
export type ResolveClaims = Register extends {
|
|
94
|
-
Claims: infer I;
|
|
95
|
-
} ? I : DefaultSyncShape['Claims'];
|
|
96
77
|
/**
|
|
97
78
|
* Your registered user-metadata shape, or the default when none is registered.
|
|
98
79
|
* It carries identity information you trust from your own auth layer; the SDK
|
package/dist/types/global.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The single place where you tell the SDK about your application's types.
|
|
3
3
|
*
|
|
4
|
-
* You register your Schema
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* site.
|
|
4
|
+
* You register your Schema and UserMeta once by augmenting the
|
|
5
|
+
* {@link Register} interface. From then on the typed SDK surface reads its
|
|
6
|
+
* types from that registration, so you never pass a generic or a `schema`
|
|
7
|
+
* argument at a call site.
|
|
9
8
|
*
|
|
10
9
|
* Registration uses TypeScript module augmentation: any file in your project
|
|
11
10
|
* can add an `interface Register` to a `declare module '@abloatai/ablo'`
|
|
@@ -27,8 +26,6 @@
|
|
|
27
26
|
* declare module '@abloatai/ablo' {
|
|
28
27
|
* interface Register {
|
|
29
28
|
* Schema: typeof schema;
|
|
30
|
-
* Presence: { cursor: { x: number; y: number } | null };
|
|
31
|
-
* Claims: { editLayer: { layerId: string } };
|
|
32
29
|
* UserMeta: { id: string; email: string };
|
|
33
30
|
* }
|
|
34
31
|
* }
|
package/dist/types/streams.d.ts
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* layer underneath.
|
|
10
10
|
*/
|
|
11
11
|
import type { InferModel, Schema } from '../schema/schema.js';
|
|
12
|
-
import type { TargetRange, OnStaleMode, WireClaim, ClaimRejection, PresenceKind, ParticipantKind } from '../coordination/schema.js';
|
|
13
|
-
export type { TargetRange, OnStaleMode, WireClaim, ClaimRejection, PresenceKind, ParticipantKind };
|
|
12
|
+
import type { TargetRange, OnStaleMode, WireClaim, ClaimRejection, ClaimLost, PresenceKind, ParticipantKind } from '../coordination/schema.js';
|
|
13
|
+
export type { TargetRange, OnStaleMode, WireClaim, ClaimRejection, ClaimLost, PresenceKind, ParticipantKind, };
|
|
14
14
|
/**
|
|
15
15
|
* Any JSON-serializable value. Used where the SDK accepts free-form metadata
|
|
16
16
|
* that is stored or transported as JSON — more precise than `unknown` while
|
|
@@ -384,32 +384,6 @@ export interface ClaimStream {
|
|
|
384
384
|
*/
|
|
385
385
|
[Symbol.asyncIterator](): AsyncIterableIterator<readonly Claim[]>;
|
|
386
386
|
}
|
|
387
|
-
/**
|
|
388
|
-
* A notification that you lost a claim you were holding — distinct from
|
|
389
|
-
* {@link ClaimRejection}, which is a claim the server refused to grant.
|
|
390
|
-
* Delivered through `onLost`.
|
|
391
|
-
*/
|
|
392
|
-
export interface ClaimLost {
|
|
393
|
-
/** The id of the claim you just lost. */
|
|
394
|
-
readonly claimId: string;
|
|
395
|
-
/**
|
|
396
|
-
* How you lost it. `'preempted'`: a privileged participant (one holding the
|
|
397
|
-
* `claim.preempt` capability) evicted you and took the lease — its work now
|
|
398
|
-
* supersedes yours, so re-plan against the new holder rather than blindly
|
|
399
|
-
* re-claiming. `'expired'`: your TTL lapsed without finishing — re-claim if
|
|
400
|
-
* you still need it.
|
|
401
|
-
*/
|
|
402
|
-
readonly reason: 'expired' | 'preempted';
|
|
403
|
-
/** The target you no longer hold. */
|
|
404
|
-
readonly target: {
|
|
405
|
-
readonly entityType: string;
|
|
406
|
-
readonly entityId: string;
|
|
407
|
-
readonly path?: string;
|
|
408
|
-
readonly range?: TargetRange;
|
|
409
|
-
readonly field?: string;
|
|
410
|
-
readonly meta?: Record<string, unknown>;
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
387
|
/**
|
|
414
388
|
* Every lifecycle state of a claim. `active` is the current holder — the lock
|
|
415
389
|
* itself. `queued` is waiting in line behind the holder and carries a
|