@abloatai/transaction 0.51.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ablo.d.ts +1 -1
- package/dist/ablo.js +1 -1
- package/dist/ai-sdk/updateTool.d.ts +1 -1
- package/dist/ai-sdk/updateTool.js +1 -1
- package/dist/auth/apiKey.d.ts +0 -6
- package/dist/auth/apiKey.d.ts.map +1 -1
- package/dist/auth/apiKey.js +13 -60
- package/dist/auth/apiKey.js.map +1 -1
- package/dist/auth/baseUrl.d.ts +38 -0
- package/dist/auth/baseUrl.d.ts.map +1 -0
- package/dist/auth/baseUrl.js +126 -0
- package/dist/auth/baseUrl.js.map +1 -0
- package/dist/auth/capability.d.ts +2 -2
- package/dist/auth/capability.js +1 -1
- package/dist/auth/index.d.ts +15 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +35 -21
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/schemas.d.ts +24 -1
- package/dist/auth/schemas.d.ts.map +1 -1
- package/dist/auth/schemas.js +8 -2
- package/dist/auth/schemas.js.map +1 -1
- package/dist/auth/sessionIssuanceProtocol.d.ts +41 -0
- package/dist/auth/sessionIssuanceProtocol.d.ts.map +1 -0
- package/dist/auth/sessionIssuanceProtocol.js +48 -0
- package/dist/auth/sessionIssuanceProtocol.js.map +1 -0
- package/dist/auth/sessionMint.js +2 -2
- package/dist/branches.d.ts +34 -33
- package/dist/branches.d.ts.map +1 -1
- package/dist/branches.js +2 -4
- package/dist/branches.js.map +1 -1
- package/dist/coordination/schema.d.ts +3 -2
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +7 -2
- package/dist/coordination/schema.js.map +1 -1
- package/dist/errorCodes.d.ts +7 -3
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +8 -4
- package/dist/errorCodes.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/httpResources.d.ts +35 -2
- package/dist/resources/httpResources.d.ts.map +1 -1
- package/dist/resources/httpResources.js +10 -1
- package/dist/resources/httpResources.js.map +1 -1
- package/dist/resources/modelOperations.d.ts +18 -6
- package/dist/resources/modelOperations.d.ts.map +1 -1
- package/dist/resources/modelOperations.js.map +1 -1
- package/dist/resources/where.d.ts +67 -2
- package/dist/resources/where.d.ts.map +1 -1
- package/dist/resources/where.js +73 -0
- package/dist/resources/where.js.map +1 -1
- package/dist/schema/ddl.d.ts.map +1 -1
- package/dist/schema/ddl.js +9 -12
- package/dist/schema/ddl.js.map +1 -1
- package/dist/schema/field.d.ts +3 -3
- package/dist/schema/field.js +2 -2
- package/dist/schema/fieldRef.d.ts +1 -1
- package/dist/schema/generate.d.ts +2 -3
- package/dist/schema/generate.d.ts.map +1 -1
- package/dist/schema/generate.js +2 -8
- package/dist/schema/generate.js.map +1 -1
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +3 -3
- package/dist/schema/model.d.ts +7 -7
- package/dist/schema/model.js +2 -2
- package/dist/schema/openapi.d.ts.map +1 -1
- package/dist/schema/openapi.js +63 -21
- package/dist/schema/openapi.js.map +1 -1
- package/dist/schema/queries.d.ts +1 -1
- package/dist/schema/queries.js +1 -1
- package/dist/schema/relation.d.ts +8 -8
- package/dist/schema/relation.js +5 -5
- package/dist/schema/schema.d.ts +24 -37
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +15 -28
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/sugar.d.ts +7 -7
- package/dist/schema/sugar.js +5 -5
- package/dist/server/adapter.d.ts +2 -0
- package/dist/server/adapter.d.ts.map +1 -1
- package/dist/server/commit.d.ts +5 -1
- package/dist/server/commit.d.ts.map +1 -1
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/readConfig.d.ts +109 -57
- package/dist/server/readConfig.d.ts.map +1 -1
- package/dist/server/readConfig.js +19 -5
- package/dist/server/readConfig.js.map +1 -1
- package/dist/source/adapters/drizzle.d.ts.map +1 -1
- package/dist/source/adapters/drizzle.js +5 -0
- package/dist/source/adapters/drizzle.js.map +1 -1
- package/dist/source/adapters/kysely.d.ts.map +1 -1
- package/dist/source/adapters/kysely.js +33 -8
- package/dist/source/adapters/kysely.js.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +58 -20
- package/dist/source/adapters/kyselyMutationCore.js.map +1 -1
- package/dist/source/adapters/memory.d.ts.map +1 -1
- package/dist/source/adapters/memory.js +5 -0
- package/dist/source/adapters/memory.js.map +1 -1
- package/dist/source/adapters/prisma.d.ts.map +1 -1
- package/dist/source/adapters/prisma.js +6 -1
- package/dist/source/adapters/prisma.js.map +1 -1
- package/dist/source/conformance.js +21 -21
- package/dist/source/contract.d.ts +17 -0
- package/dist/source/contract.d.ts.map +1 -1
- package/dist/source/contract.js +31 -0
- package/dist/source/contract.js.map +1 -1
- package/dist/source/index.d.ts +1 -1
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/index.js +1 -1
- package/dist/source/index.js.map +1 -1
- package/dist/source/types.d.ts +1 -0
- package/dist/source/types.d.ts.map +1 -1
- package/dist/source/types.js.map +1 -1
- package/dist/transactionLayer.d.ts +3 -3
- package/dist/transactionLayer.js +3 -3
- package/dist/transport/httpClient.d.ts +13 -4
- package/dist/transport/httpClient.d.ts.map +1 -1
- package/dist/transport/httpClient.js +4 -2
- package/dist/transport/httpClient.js.map +1 -1
- package/dist/transport/httpTransport.d.ts +1 -0
- package/dist/transport/httpTransport.d.ts.map +1 -1
- package/dist/transport/httpTransport.js +79 -11
- package/dist/transport/httpTransport.js.map +1 -1
- package/dist/transport/wsFrameHandlers.d.ts.map +1 -1
- package/dist/transport/wsFrameHandlers.js +3 -0
- package/dist/transport/wsFrameHandlers.js.map +1 -1
- package/dist/types/streams.d.ts +2 -2
- package/dist/wire/accountResponses.d.ts +18 -13
- package/dist/wire/accountResponses.d.ts.map +1 -1
- package/dist/wire/accountResponses.js +5 -11
- package/dist/wire/accountResponses.js.map +1 -1
- package/dist/wire/claims.d.ts +1 -0
- package/dist/wire/claims.d.ts.map +1 -1
- package/dist/wire/claims.js +7 -1
- package/dist/wire/claims.js.map +1 -1
- package/dist/wire/commit.d.ts +144 -0
- package/dist/wire/commit.d.ts.map +1 -1
- package/dist/wire/commit.js +22 -1
- package/dist/wire/commit.js.map +1 -1
- package/dist/wire/frames.d.ts +4 -0
- package/dist/wire/frames.d.ts.map +1 -1
- package/dist/wire/inboundFrames.d.ts +22 -0
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/dist/wire/index.d.ts +3 -3
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +2 -2
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/listEnvelope.d.ts +20 -0
- package/dist/wire/listEnvelope.d.ts.map +1 -1
- package/dist/wire/listEnvelope.js +20 -0
- package/dist/wire/listEnvelope.js.map +1 -1
- package/dist/wire/protocol.d.ts +1 -1
- package/dist/wire/protocol.js +1 -1
- package/package.json +1 -1
- package/src/ablo.ts +1 -1
- package/src/ai-sdk/updateTool.ts +1 -1
- package/src/auth/apiKey.ts +13 -61
- package/src/auth/baseUrl.ts +144 -0
- package/src/auth/capability.ts +3 -3
- package/src/auth/index.ts +62 -21
- package/src/auth/schemas.ts +16 -2
- package/src/auth/sessionIssuanceProtocol.ts +57 -0
- package/src/auth/sessionMint.ts +2 -2
- package/src/branches.ts +2 -4
- package/src/coordination/schema.ts +7 -2
- package/src/errorCodes.ts +29 -5
- package/src/errors.ts +1 -1
- package/src/index.ts +2 -0
- package/src/resources/httpResources.ts +45 -2
- package/src/resources/modelOperations.ts +18 -6
- package/src/resources/where.ts +70 -4
- package/src/schema/ddl.ts +9 -13
- package/src/schema/field.ts +3 -3
- package/src/schema/fieldRef.ts +1 -1
- package/src/schema/generate.ts +2 -8
- package/src/schema/index.ts +3 -3
- package/src/schema/model.ts +7 -7
- package/src/schema/openapi.ts +64 -21
- package/src/schema/queries.ts +1 -1
- package/src/schema/relation.ts +8 -8
- package/src/schema/residency.ts +0 -1
- package/src/schema/schema.ts +33 -58
- package/src/schema/sugar.ts +7 -7
- package/src/server/adapter.ts +2 -0
- package/src/server/commit.ts +5 -1
- package/src/server/index.ts +8 -2
- package/src/server/readConfig.ts +111 -57
- package/src/source/adapters/drizzle.ts +5 -0
- package/src/source/adapters/kysely.ts +48 -10
- package/src/source/adapters/kyselyMutationCore.ts +69 -22
- package/src/source/adapters/memory.ts +5 -0
- package/src/source/adapters/prisma.ts +6 -1
- package/src/source/conformance.ts +21 -21
- package/src/source/contract.ts +34 -0
- package/src/source/index.ts +2 -0
- package/src/source/types.ts +1 -0
- package/src/transactionLayer.ts +3 -3
- package/src/transport/httpClient.ts +23 -6
- package/src/transport/httpTransport.ts +88 -11
- package/src/transport/wsFrameHandlers.ts +3 -0
- package/src/types/global.ts +1 -1
- package/src/types/streams.ts +2 -2
- package/src/wire/accountResponses.ts +5 -11
- package/src/wire/claims.ts +7 -1
- package/src/wire/commit.ts +31 -1
- package/src/wire/index.ts +10 -1
- package/src/wire/listEnvelope.ts +23 -0
- package/src/wire/protocol.ts +1 -1
|
@@ -84,6 +84,7 @@ import type {
|
|
|
84
84
|
ModelMutationOptions,
|
|
85
85
|
ModelReadOptions,
|
|
86
86
|
HttpTransportRead,
|
|
87
|
+
HttpTransportList,
|
|
87
88
|
HttpLogsResource,
|
|
88
89
|
ModelTarget,
|
|
89
90
|
CreateSessionParams,
|
|
@@ -151,6 +152,7 @@ import { declaredMeta, wireMeta } from '../coordination/claimMeta.js';
|
|
|
151
152
|
import type { Claim, ClaimHeartbeat, ClaimHeartbeatOptions, HeldClaim } from '../types/streams.js';
|
|
152
153
|
import type { CoordinationObservability } from '../observability.js';
|
|
153
154
|
import { assertWriteOptions } from '../resources/writeOptionsSchema.js';
|
|
155
|
+
import { normalizeWhere } from '../resources/where.js';
|
|
154
156
|
import {
|
|
155
157
|
createDurableHttpCommitEnvelope,
|
|
156
158
|
canonicalHttpCommitBody,
|
|
@@ -203,6 +205,7 @@ const DEFAULT_CLAIM_TTL_MS = 60_000;
|
|
|
203
205
|
export interface HttpTransport {
|
|
204
206
|
ready(): Promise<void>;
|
|
205
207
|
waitForFlush(): Promise<void>;
|
|
208
|
+
/** Drains scheduled commits and active requests. */
|
|
206
209
|
dispose(): Promise<void>;
|
|
207
210
|
purge(): Promise<void>;
|
|
208
211
|
readonly commits: CommitResource;
|
|
@@ -361,6 +364,26 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
361
364
|
let readyPromise: Promise<void> | null = null;
|
|
362
365
|
let effectiveAuthority: EffectiveAuthority | null = null;
|
|
363
366
|
let httpCommitLane: Promise<void> = Promise.resolve();
|
|
367
|
+
let activeRequests = 0;
|
|
368
|
+
let requestIdleWaiters: Array<() => void> = [];
|
|
369
|
+
let disposePromise: Promise<void> | null = null;
|
|
370
|
+
|
|
371
|
+
function requestStarted(): void {
|
|
372
|
+
activeRequests += 1;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function requestFinished(): void {
|
|
376
|
+
activeRequests -= 1;
|
|
377
|
+
if (activeRequests !== 0) return;
|
|
378
|
+
const waiters = requestIdleWaiters;
|
|
379
|
+
requestIdleWaiters = [];
|
|
380
|
+
for (const resolve of waiters) resolve();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function waitForRequestIdle(): Promise<void> {
|
|
384
|
+
if (activeRequests === 0) return Promise.resolve();
|
|
385
|
+
return new Promise((resolve) => requestIdleWaiters.push(resolve));
|
|
386
|
+
}
|
|
364
387
|
|
|
365
388
|
function runInHttpCommitLane<T>(work: () => Promise<T>): Promise<T> {
|
|
366
389
|
const result = httpCommitLane.then(work);
|
|
@@ -475,7 +498,7 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
475
498
|
* the commit paths do with their receipt schema. Everywhere else, go through
|
|
476
499
|
* {@link requestJson}, which will not let a response past unvalidated.
|
|
477
500
|
*/
|
|
478
|
-
async function
|
|
501
|
+
async function performRequest(
|
|
479
502
|
path: string,
|
|
480
503
|
init: RequestInit & {
|
|
481
504
|
readonly idempotencyKey?: string | null;
|
|
@@ -557,6 +580,22 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
557
580
|
return body;
|
|
558
581
|
}
|
|
559
582
|
|
|
583
|
+
async function requestRaw(
|
|
584
|
+
path: string,
|
|
585
|
+
init: RequestInit & {
|
|
586
|
+
readonly idempotencyKey?: string | null;
|
|
587
|
+
readonly sealedProtocolVersion?: number;
|
|
588
|
+
},
|
|
589
|
+
skipReady = false
|
|
590
|
+
): Promise<unknown> {
|
|
591
|
+
requestStarted();
|
|
592
|
+
try {
|
|
593
|
+
return await performRequest(path, init, skipReady);
|
|
594
|
+
} finally {
|
|
595
|
+
requestFinished();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
560
599
|
/**
|
|
561
600
|
* Issues one request and validates its body against the route's schema.
|
|
562
601
|
*
|
|
@@ -729,6 +768,11 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
729
768
|
initial: CommitResponse
|
|
730
769
|
): Promise<CommitResponse> {
|
|
731
770
|
let current = initial;
|
|
771
|
+
const operationResults = initial.operationResults;
|
|
772
|
+
const withOperationResults = (receipt: CommitResponse): CommitResponse =>
|
|
773
|
+
operationResults?.length
|
|
774
|
+
? { ...receipt, operationResults }
|
|
775
|
+
: receipt;
|
|
732
776
|
const correlationId = initial.correlationId;
|
|
733
777
|
const deadlineAt = requestTimeoutMs > 0 ? Date.now() + requestTimeoutMs : null;
|
|
734
778
|
|
|
@@ -780,7 +824,7 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
780
824
|
if (confirmationDeadline) clearTimeout(confirmationDeadline);
|
|
781
825
|
}
|
|
782
826
|
|
|
783
|
-
if (current.status === 'confirmed') return current;
|
|
827
|
+
if (current.status === 'confirmed') return withOperationResults(current);
|
|
784
828
|
const delayMs =
|
|
785
829
|
deadlineAt === null
|
|
786
830
|
? HTTP_CONFIRMATION_POLL_INTERVAL_MS
|
|
@@ -791,7 +835,7 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
791
835
|
});
|
|
792
836
|
}
|
|
793
837
|
}
|
|
794
|
-
return current;
|
|
838
|
+
return withOperationResults(current);
|
|
795
839
|
}
|
|
796
840
|
|
|
797
841
|
async function replayHttpCommitOutbox(): Promise<Map<string, ReplayedHttpCommit>> {
|
|
@@ -1111,6 +1155,7 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
1111
1155
|
model: op.model,
|
|
1112
1156
|
id: op.id ?? null,
|
|
1113
1157
|
data: op.data ?? null,
|
|
1158
|
+
where: op.where ?? null,
|
|
1114
1159
|
transactionId: op.transactionId ?? null,
|
|
1115
1160
|
claimId:
|
|
1116
1161
|
op.claimId ?? claimIdFor(claim?.target, claim?.id, op.model, op.id ?? null),
|
|
@@ -1392,6 +1437,9 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
1392
1437
|
? { notifications: body.notifications }
|
|
1393
1438
|
: {}),
|
|
1394
1439
|
...(body.missingIds && body.missingIds.length > 0 ? { missingIds: body.missingIds } : {}),
|
|
1440
|
+
...(body.operationResults && body.operationResults.length > 0
|
|
1441
|
+
? { operationResults: body.operationResults }
|
|
1442
|
+
: {}),
|
|
1395
1443
|
};
|
|
1396
1444
|
},
|
|
1397
1445
|
get({ id }) {
|
|
@@ -1447,9 +1495,12 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
1447
1495
|
async function listModel<T>(
|
|
1448
1496
|
modelName: string,
|
|
1449
1497
|
options?: ServerReadOptions<T>,
|
|
1450
|
-
): Promise<
|
|
1498
|
+
): Promise<HttpTransportList<T>> {
|
|
1451
1499
|
const params = new URLSearchParams();
|
|
1452
1500
|
if (options?.limit !== undefined) params.set('limit', String(options.limit));
|
|
1501
|
+
if (options?.cursor !== undefined) {
|
|
1502
|
+
params.set('cursor', options.cursor);
|
|
1503
|
+
}
|
|
1453
1504
|
if (options?.orderBy) {
|
|
1454
1505
|
const [col, dir] = Object.entries(options.orderBy)[0] ?? [];
|
|
1455
1506
|
if (col) {
|
|
@@ -1457,12 +1508,27 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
1457
1508
|
if (dir === 'desc') params.set('order', 'desc');
|
|
1458
1509
|
}
|
|
1459
1510
|
}
|
|
1460
|
-
// The
|
|
1461
|
-
//
|
|
1462
|
-
//
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1511
|
+
// The whole filter travels as the canonical clause list, so every operator
|
|
1512
|
+
// the grammar declares survives the trip. The previous encoding walked the
|
|
1513
|
+
// object's own entries and skipped any value that was an object, which
|
|
1514
|
+
// silently discarded `IN` filters and every tuple-form clause: the request
|
|
1515
|
+
// went out unfiltered and the caller read the result as a filtered one.
|
|
1516
|
+
const clauses = normalizeWhere(options?.where);
|
|
1517
|
+
if (clauses.length > 0) {
|
|
1518
|
+
params.set('where', JSON.stringify(clauses));
|
|
1519
|
+
// Plain equality also goes out in the older `?column=value` shorthand.
|
|
1520
|
+
// A server that predates the `where` parameter does not reserve the name
|
|
1521
|
+
// and does not declare it as a column, so it skips it — and a dropped
|
|
1522
|
+
// filter is not an error there, it is a wider answer than the caller
|
|
1523
|
+
// asked for. Sending both means a version skew loses only the operator
|
|
1524
|
+
// filters, which that server could not have honoured anyway. A current
|
|
1525
|
+
// server ignores a shorthand key the clause list already carries.
|
|
1526
|
+
for (const clause of clauses) {
|
|
1527
|
+
const [column] = clause;
|
|
1528
|
+
const value = clause.length === 2 ? clause[1] : clause[2];
|
|
1529
|
+
if (clause.length === 3 && clause[1] !== '=') continue;
|
|
1530
|
+
if (value === null || typeof value === 'object') continue;
|
|
1531
|
+
params.set(column, String(value));
|
|
1466
1532
|
}
|
|
1467
1533
|
}
|
|
1468
1534
|
const qs = params.toString();
|
|
@@ -1477,6 +1543,8 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
1477
1543
|
// the typed facade above, which holds the model's schema.
|
|
1478
1544
|
return {
|
|
1479
1545
|
data: res.data as T[],
|
|
1546
|
+
hasMore: res.has_more,
|
|
1547
|
+
nextCursor: res.next_cursor,
|
|
1480
1548
|
...(res.evidence ? { evidence: res.evidence } : {}),
|
|
1481
1549
|
};
|
|
1482
1550
|
}
|
|
@@ -2053,7 +2121,16 @@ export function createHttpTransport(options: HttpTransportOptions): HttpTranspor
|
|
|
2053
2121
|
const replayed = await replayHttpCommitOutbox();
|
|
2054
2122
|
await confirmReplayedHttpCommits(replayed);
|
|
2055
2123
|
}),
|
|
2056
|
-
|
|
2124
|
+
dispose() {
|
|
2125
|
+
if (!disposePromise) {
|
|
2126
|
+
const scheduledCommits = httpCommitLane;
|
|
2127
|
+
disposePromise = (async () => {
|
|
2128
|
+
await scheduledCommits;
|
|
2129
|
+
await waitForRequestIdle();
|
|
2130
|
+
})();
|
|
2131
|
+
}
|
|
2132
|
+
return disposePromise;
|
|
2133
|
+
},
|
|
2057
2134
|
async purge() {},
|
|
2058
2135
|
commits,
|
|
2059
2136
|
claims,
|
|
@@ -222,6 +222,9 @@ const handleMutationResult: WsFrameHandler = (session, message) => {
|
|
|
222
222
|
...(receipt.missingIds && receipt.missingIds.length > 0
|
|
223
223
|
? { missingIds: receipt.missingIds }
|
|
224
224
|
: {}),
|
|
225
|
+
...(receipt.operationResults && receipt.operationResults.length > 0
|
|
226
|
+
? { operationResults: receipt.operationResults }
|
|
227
|
+
: {}),
|
|
225
228
|
}),
|
|
226
229
|
);
|
|
227
230
|
} else {
|
package/src/types/global.ts
CHANGED
|
@@ -51,7 +51,7 @@ export interface DefaultSyncShape {
|
|
|
51
51
|
// `models` is a `SchemaRecord` (not `Record<string, unknown>`) so that
|
|
52
52
|
// `ResolveSchema['models']` still satisfies the `R extends SchemaRecord`
|
|
53
53
|
// bound on the SDK hooks when no `Register` is present — e.g. a shared
|
|
54
|
-
// package (
|
|
54
|
+
// package (`feature packages`) typechecked standalone, with no
|
|
55
55
|
// app registration in scope. Without this the fallback wouldn't type-check
|
|
56
56
|
// against `useAblo<R>()`/`AbloProvider<R>` and every such package would need
|
|
57
57
|
// its own ambient registration.
|
package/src/types/streams.ts
CHANGED
|
@@ -629,12 +629,12 @@ export interface Claim<T = Record<string, unknown>, M = ResolveClaimMeta> {
|
|
|
629
629
|
revoke?: () => void;
|
|
630
630
|
/**
|
|
631
631
|
* Extend the lease past the liveness window — the "still working" signal
|
|
632
|
-
* for long-running
|
|
632
|
+
* for long-running items. Resolving means the lease is still yours, now
|
|
633
633
|
* good until the returned `expiresAt`; a lease that lapsed (and may have
|
|
634
634
|
* been granted to the next in line) rejects with an
|
|
635
635
|
* {@link ../errors.js AbloClaimedError} carrying code `claim_lost`, so the
|
|
636
636
|
* failed beat doubles as the loss notification. Each beat's extension is
|
|
637
|
-
* clamped server-side — hold a long
|
|
637
|
+
* clamped server-side — hold a long item by beating on a cadence (pass
|
|
638
638
|
* `heartbeat` when claiming to have the SDK do this for you), not by
|
|
639
639
|
* asking once for a huge window. Present only on a claim you hold.
|
|
640
640
|
*/
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { z } from 'zod';
|
|
17
|
+
import { listEnvelopeSchema } from './listEnvelope.js';
|
|
17
18
|
// Composed, never restated: these are the artifact's own shapes, and a
|
|
18
19
|
// hand-written mirror here would be a second copy of the exact record this
|
|
19
20
|
// response exists to stop withholding.
|
|
@@ -45,16 +46,9 @@ export type ProjectResponse = z.infer<typeof projectResponseSchema>;
|
|
|
45
46
|
/**
|
|
46
47
|
* `GET /v1/projects`.
|
|
47
48
|
*
|
|
48
|
-
*
|
|
49
|
-
* are returned whole, so the route emits `data` with no `has_more`/`next_cursor`
|
|
50
|
-
* beside it. That divergence is real and this schema states it rather than
|
|
51
|
-
* describing a pagination the endpoint does not implement — adding the two
|
|
52
|
-
* fields is an API change, not a documentation fix.
|
|
49
|
+
* Uses the canonical paginated list envelope shared by every collection.
|
|
53
50
|
*/
|
|
54
|
-
export const projectListResponseSchema =
|
|
55
|
-
object: z.literal('list'),
|
|
56
|
-
data: z.array(projectResponseSchema).readonly(),
|
|
57
|
-
});
|
|
51
|
+
export const projectListResponseSchema = listEnvelopeSchema(projectResponseSchema);
|
|
58
52
|
export type ProjectListResponse = z.infer<typeof projectListResponseSchema>;
|
|
59
53
|
|
|
60
54
|
/** One minted key, returned exactly once — the plaintext is never readable again. */
|
|
@@ -101,7 +95,7 @@ export const conflictAxisWireSchema = z.object({
|
|
|
101
95
|
|
|
102
96
|
/** One model in the deployed schema, as the schema read reports it. */
|
|
103
97
|
export const schemaModelResponseSchema = z.object({
|
|
104
|
-
/** The key local code addresses (`ablo.
|
|
98
|
+
/** The key local code addresses (`ablo.records`). */
|
|
105
99
|
key: z.string(),
|
|
106
100
|
/** The wire typename the engine routes and gates on. */
|
|
107
101
|
typename: z.string(),
|
|
@@ -122,7 +116,7 @@ export const schemaModelResponseSchema = z.object({
|
|
|
122
116
|
*
|
|
123
117
|
* The schema artifact has always carried these and this response dropped
|
|
124
118
|
* them, so a caller with no local schema declaration — which is every caller
|
|
125
|
-
* that is not TypeScript — had no way to learn that `
|
|
119
|
+
* that is not TypeScript — had no way to learn that `item.title` is a
|
|
126
120
|
* required string. It found out from a 400 at the end of a round trip.
|
|
127
121
|
*
|
|
128
122
|
* For an agent that is not merely slow, it is a reasoning detour: a typo
|
package/src/wire/claims.ts
CHANGED
|
@@ -121,7 +121,13 @@ export const listQuerySchema = z.object({
|
|
|
121
121
|
limit: z.string().optional(),
|
|
122
122
|
order_by: z.string().optional(),
|
|
123
123
|
order: z.enum(['asc', 'desc']).optional(),
|
|
124
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* Keyset cursor: the opaque `next_cursor` the previous page returned. It
|
|
126
|
+
* encodes the sort position it was issued for, so it is not a row id and is
|
|
127
|
+
* refused against a different `order_by`/`order`.
|
|
128
|
+
*/
|
|
129
|
+
cursor: z.string().optional(),
|
|
130
|
+
/** @deprecated The pre-0.53.0 spelling of `cursor`. Send `cursor`. */
|
|
125
131
|
starting_after: z.string().optional(),
|
|
126
132
|
});
|
|
127
133
|
export type ListQuery = z.infer<typeof listQuerySchema>;
|
package/src/wire/commit.ts
CHANGED
|
@@ -102,6 +102,31 @@ export type CommitWait = z.infer<typeof commitWaitSchema>;
|
|
|
102
102
|
const missingIdsSchema = z.array(z.string().min(1));
|
|
103
103
|
const notificationsSchema = z.array(staleNotificationSchema);
|
|
104
104
|
|
|
105
|
+
export const commitOperationOutcomeSchema = z.enum([
|
|
106
|
+
'created',
|
|
107
|
+
'updated',
|
|
108
|
+
'deleted',
|
|
109
|
+
'archived',
|
|
110
|
+
'unarchived',
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
export const commitOperationResultSchema = z.strictObject({
|
|
114
|
+
transactionId: z.string().min(1),
|
|
115
|
+
outcome: commitOperationOutcomeSchema,
|
|
116
|
+
row: z.record(z.string(), z.unknown()),
|
|
117
|
+
});
|
|
118
|
+
export type CommitOperationResult<
|
|
119
|
+
Row extends Record<string, unknown> = Record<string, unknown>,
|
|
120
|
+
> = Omit<z.infer<typeof commitOperationResultSchema>, 'row'> & { readonly row: Row };
|
|
121
|
+
|
|
122
|
+
const operationResultsSchema = z
|
|
123
|
+
.array(commitOperationResultSchema)
|
|
124
|
+
.min(1)
|
|
125
|
+
.refine(
|
|
126
|
+
(results) => new Set(results.map((result) => result.transactionId)).size === results.length,
|
|
127
|
+
'operation result transactionIds must be unique',
|
|
128
|
+
);
|
|
129
|
+
|
|
105
130
|
export const commitActorSchema = z.strictObject({
|
|
106
131
|
kind: participantKindSchema,
|
|
107
132
|
id: z.string().min(1),
|
|
@@ -155,6 +180,8 @@ const successfulReceiptCommonShape = {
|
|
|
155
180
|
authority: effectiveAuthoritySchema,
|
|
156
181
|
notifications: notificationsSchema.optional(),
|
|
157
182
|
missingIds: missingIdsSchema.optional(),
|
|
183
|
+
/** Exact rows returned by the writing transaction; absent on durable replay. */
|
|
184
|
+
operationResults: operationResultsSchema.optional(),
|
|
158
185
|
} as const;
|
|
159
186
|
|
|
160
187
|
const queuedCommitReceiptSchema = queuedCommitStatusSchema.safeExtend(
|
|
@@ -316,6 +343,7 @@ export type CommitExecutionResult = z.infer<typeof commitExecutionResultSchema>;
|
|
|
316
343
|
const ackCommonShape = {
|
|
317
344
|
notifications: notificationsSchema.optional(),
|
|
318
345
|
missingIds: missingIdsSchema.optional(),
|
|
346
|
+
operationResults: operationResultsSchema.optional(),
|
|
319
347
|
} as const;
|
|
320
348
|
|
|
321
349
|
/** Normalized acknowledgement handed from a mutation transport to the queue. */
|
|
@@ -350,6 +378,7 @@ export const clientCommitReceiptSchema = z.strictObject({
|
|
|
350
378
|
lastSyncId: readSetWatermarkSchema.optional(),
|
|
351
379
|
notifications: notificationsSchema.optional(),
|
|
352
380
|
missingIds: missingIdsSchema.optional(),
|
|
381
|
+
operationResults: operationResultsSchema.optional(),
|
|
353
382
|
});
|
|
354
383
|
export type ClientCommitReceipt = z.infer<typeof clientCommitReceiptSchema>;
|
|
355
384
|
|
|
@@ -382,13 +411,14 @@ export const commitOperationBodySchema = z.object({
|
|
|
382
411
|
action: z.string(),
|
|
383
412
|
model: z.string(),
|
|
384
413
|
data: z.record(z.string(), z.unknown()).nullish(),
|
|
414
|
+
where: z.record(z.string().min(1), z.unknown()).nullish(),
|
|
385
415
|
});
|
|
386
416
|
export type CommitOperationBody = z.infer<typeof commitOperationBodySchema>;
|
|
387
417
|
|
|
388
418
|
/** Commit records retain intent metadata but never copy customer mutation data. */
|
|
389
419
|
export const COMMIT_OPERATION_DATA_RETENTION = 'redacted' as const;
|
|
390
420
|
export const commitRecordOperationSchema = commitOperationBodySchema
|
|
391
|
-
.omit({ data: true })
|
|
421
|
+
.omit({ data: true, where: true })
|
|
392
422
|
.safeExtend({ data: z.strictObject({ retention: z.literal(COMMIT_OPERATION_DATA_RETENTION) }) });
|
|
393
423
|
export type CommitRecordOperation = z.infer<typeof commitRecordOperationSchema>;
|
|
394
424
|
|
package/src/wire/index.ts
CHANGED
|
@@ -22,7 +22,13 @@ export {
|
|
|
22
22
|
INTERNAL_ERROR_PUBLIC_MESSAGE,
|
|
23
23
|
} from './errorEnvelope.js';
|
|
24
24
|
export type { ErrorEnvelope } from './errorEnvelope.js';
|
|
25
|
-
export {
|
|
25
|
+
export {
|
|
26
|
+
listEnvelopeSchema,
|
|
27
|
+
listEnvelope,
|
|
28
|
+
CURSOR_PARAM,
|
|
29
|
+
CURSOR_PARAM_ALIAS,
|
|
30
|
+
CURSOR_PARAM_NAMES,
|
|
31
|
+
} from './listEnvelope.js';
|
|
26
32
|
export type { ListEnvelope } from './listEnvelope.js';
|
|
27
33
|
|
|
28
34
|
// The `GET /v1/logs` feed — the two arms, their envelope, and the cursor that
|
|
@@ -99,6 +105,8 @@ export {
|
|
|
99
105
|
commitStatusSchema,
|
|
100
106
|
commitWaitSchema,
|
|
101
107
|
commitReceiptSchema,
|
|
108
|
+
commitOperationOutcomeSchema,
|
|
109
|
+
commitOperationResultSchema,
|
|
102
110
|
rejectedCommitReceiptSchema,
|
|
103
111
|
mutationResultPayloadSchema,
|
|
104
112
|
mutationResultMessageSchema,
|
|
@@ -121,6 +129,7 @@ export {
|
|
|
121
129
|
} from './commit.js';
|
|
122
130
|
export type {
|
|
123
131
|
CommitOperationBody,
|
|
132
|
+
CommitOperationResult,
|
|
124
133
|
CommitActor,
|
|
125
134
|
CommitAttempt,
|
|
126
135
|
CommitClaimReference,
|
package/src/wire/listEnvelope.ts
CHANGED
|
@@ -10,6 +10,29 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* The query parameter a caller resumes a collection with, and the single alias
|
|
15
|
+
* retained for it.
|
|
16
|
+
*
|
|
17
|
+
* Declared beside the envelope that issues `next_cursor`, because the parameter
|
|
18
|
+
* and the field it consumes are one contract and both planes read them: the
|
|
19
|
+
* server to know which names are taken, the spec generator to document them,
|
|
20
|
+
* the client to send one. When the name lived in each of those separately, this
|
|
21
|
+
* spec described `starting_after` for a model list and `cursor` for a commit
|
|
22
|
+
* record list — the same concept under two names, in one document.
|
|
23
|
+
*
|
|
24
|
+
* `starting_after` is the spelling used through 0.52.0. It borrowed a name whose
|
|
25
|
+
* established meaning elsewhere is a row id, while this value has always been an
|
|
26
|
+
* opaque token bound to the sort it was issued for.
|
|
27
|
+
*/
|
|
28
|
+
export const CURSOR_PARAM = 'cursor';
|
|
29
|
+
|
|
30
|
+
/** @deprecated The pre-0.53.0 spelling of {@link CURSOR_PARAM}. */
|
|
31
|
+
export const CURSOR_PARAM_ALIAS = 'starting_after';
|
|
32
|
+
|
|
33
|
+
/** Both names a cursor may arrive under, for reserving them in a query string. */
|
|
34
|
+
export const CURSOR_PARAM_NAMES: readonly string[] = [CURSOR_PARAM, CURSOR_PARAM_ALIAS];
|
|
35
|
+
|
|
13
36
|
/**
|
|
14
37
|
* Builds the authoritative list-envelope schema for a row schema. Keeping the
|
|
15
38
|
* item validator generic lets every endpoint share the same envelope contract
|
package/src/wire/protocol.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* The lease is three ping intervals long and is renewed on every ping, so a
|
|
17
17
|
* live holder always has at least two intervals of runway and a silent one
|
|
18
18
|
* lapses about two missed pings after it stops renewing. The window measures
|
|
19
|
-
* liveness, not how long a
|
|
19
|
+
* liveness, not how long a item may run: widening the lease without also
|
|
20
20
|
* widening the ping makes holders flap, and neither value should be redefined
|
|
21
21
|
* anywhere else.
|
|
22
22
|
*/
|