@abloatai/ablo 0.15.0 → 0.15.1
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 +15 -3
- package/dist/client/Ablo.d.ts +7 -0
- package/dist/client/ApiClient.js +3 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.js +21 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interfaces/index.d.ts +5 -0
- package/dist/server/commit.d.ts +9 -0
- package/dist/wire/frames.d.ts +7 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Loud 0-row writes: surface unmatched UPDATE/DELETE ids and add `AbloNotFoundError`
|
|
8
|
+
|
|
9
|
+
A commit now reports the ids of any UPDATE/DELETE that matched zero rows on
|
|
10
|
+
`CommitReceipt.missingIds`, and the new exported `AbloNotFoundError` lets typed
|
|
11
|
+
write wrappers throw instead of silently treating a missed write as success.
|
|
12
|
+
Additive and back-compatible (the field is omitted when nothing missed). This
|
|
13
|
+
unblocks the slides-sdk name-addressing / own-your-id work, which relies on a
|
|
14
|
+
loud failure when a stale id is written.
|
|
15
|
+
|
|
3
16
|
## 0.15.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -11,7 +24,7 @@
|
|
|
11
24
|
**`onStale` redesigned — Stripe-aligned values (BREAKING).**
|
|
12
25
|
|
|
13
26
|
The mode set is now `'reject' | 'overwrite' | 'notify'`. Each value names its outcome:
|
|
14
|
-
- **`notify` (new, non-coercive)** — the conflicting write is **held** (not applied) and the commit returns a `StaleNotification` carrying the conflicting field's
|
|
27
|
+
- **`notify` (new, non-coercive)** — the conflicting write is **held** (not applied) and the commit returns a `StaleNotification` carrying the conflicting field's _current_ value, so the actor reconciles and re-commits rather than losing work. The rest of the batch still commits.
|
|
15
28
|
- **`overwrite`** (was `force`) — blind last-writer-wins, no signal.
|
|
16
29
|
- **`reject`** (default, unchanged) — throws `AbloStaleContextError`.
|
|
17
30
|
|
|
@@ -33,10 +46,9 @@
|
|
|
33
46
|
**Conflict policy.** `ConflictDecision` gains `{ action: 'notify' }`; `defaultPolicy` maps `onStale: 'notify'` → notify-and-hold, everything else → reject. `StaleContextConflict.requestedMode` is added so custom policies can honor the caller's declared intent.
|
|
34
47
|
|
|
35
48
|
- **Data Source reverse-channel connector (new).** A customer Data Source can now **dial out** to the engine over a single outbound WebSocket (`ablo.source.v1` subprotocol) instead of exposing an inbound HTTP endpoint — the deployment shape private/VPC stores need.
|
|
36
|
-
|
|
37
49
|
- **`createSourceConnector({ apiKey, handler, baseURL? })`** (new public API, exported from the root and `/source`) — opens one outbound socket (Node global `WebSocket`, no new dependency), with reconnect/backoff, and serves the customer's existing Data Source `handler`.
|
|
38
50
|
- Server side: a connector registry + `/v1/source/listen` upgrade route bridge requests down / responses up, teed into `SourceClient` through the storage resolver.
|
|
39
|
-
- **Trust model unchanged:** the Standard-Webhooks HMAC is signed
|
|
51
|
+
- **Trust model unchanged:** the Standard-Webhooks HMAC is signed _above_ the transport, so the socket carries the signed envelope byte-for-byte and the customer's `verifyAbloSourceRequest` is untouched. Transport changes, trust model doesn't.
|
|
40
52
|
- Opt-in per source via `reverse_channel_prod` (migration `20260622150000`); gated in `authorizeUpgrade`.
|
|
41
53
|
|
|
42
54
|
## 0.14.0
|
package/dist/client/Ablo.d.ts
CHANGED
|
@@ -469,6 +469,13 @@ export interface CommitReceipt {
|
|
|
469
469
|
* resolve. Also fires on `conflict:notified`.
|
|
470
470
|
*/
|
|
471
471
|
readonly notifications?: readonly StaleNotification[];
|
|
472
|
+
/**
|
|
473
|
+
* Ids of UPDATE/DELETE targets in this commit that matched ZERO rows (the row
|
|
474
|
+
* doesn't exist, or is outside the caller's org). Present (non-empty) only
|
|
475
|
+
* when a write missed. Typed resource wrappers turn this into a loud
|
|
476
|
+
* `AbloNotFoundError`; a raw `commits.create` caller can inspect it directly.
|
|
477
|
+
*/
|
|
478
|
+
readonly missingIds?: readonly string[];
|
|
472
479
|
}
|
|
473
480
|
export interface CommitResource {
|
|
474
481
|
create(options: CommitCreateOptions): Promise<CommitReceipt>;
|
package/dist/client/ApiClient.js
CHANGED
|
@@ -285,6 +285,9 @@ export function createProtocolClient(options) {
|
|
|
285
285
|
id: body.id ?? body.clientTxId ?? clientTxId,
|
|
286
286
|
status,
|
|
287
287
|
lastSyncId: body.lastSyncId,
|
|
288
|
+
...(body.missingIds && body.missingIds.length > 0
|
|
289
|
+
? { missingIds: body.missingIds }
|
|
290
|
+
: {}),
|
|
288
291
|
};
|
|
289
292
|
},
|
|
290
293
|
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -118,6 +118,21 @@ export declare class AbloConnectionError extends AbloError {
|
|
|
118
118
|
export declare class AbloValidationError extends AbloError {
|
|
119
119
|
readonly type: "AbloValidationError";
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* 404 — an UPDATE/DELETE addressed a row that doesn't exist (or is outside the
|
|
123
|
+
* caller's org). The engine reports such targets on `CommitReceipt.missingIds`;
|
|
124
|
+
* the typed resource wrappers raise this instead of returning a success receipt
|
|
125
|
+
* for a write that quietly matched zero rows. Carries the offending ids so a
|
|
126
|
+
* caller can see exactly which targets were absent.
|
|
127
|
+
*/
|
|
128
|
+
export declare class AbloNotFoundError extends AbloError {
|
|
129
|
+
readonly type: "AbloNotFoundError";
|
|
130
|
+
/** The id(s) that matched no row. */
|
|
131
|
+
readonly missingIds: readonly string[];
|
|
132
|
+
constructor(message: string, missingIds: readonly string[], options?: {
|
|
133
|
+
requestId?: string;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
121
136
|
/** 5xx — server-side error. Usually retryable with backoff. */
|
|
122
137
|
export declare class AbloServerError extends AbloError {
|
|
123
138
|
readonly type: "AbloServerError";
|
|
@@ -272,6 +287,10 @@ export interface CommitReceipt {
|
|
|
272
287
|
/** Number of operations metered. Reported on both success and
|
|
273
288
|
* rejection so quota systems see attempted work. */
|
|
274
289
|
readonly ops?: number;
|
|
290
|
+
/** Ids of UPDATE/DELETE targets that matched ZERO rows (loud 0-row writes).
|
|
291
|
+
* Present (non-empty) only when a write missed; typed wrappers raise
|
|
292
|
+
* `AbloNotFoundError` from it. */
|
|
293
|
+
readonly missingIds?: readonly string[];
|
|
275
294
|
/** Populated on rejection. `requiredCapability` (when present)
|
|
276
295
|
* carries the x402-style structured retry hint. */
|
|
277
296
|
readonly error?: {
|
package/dist/errors.js
CHANGED
|
@@ -132,6 +132,27 @@ export class AbloConnectionError extends AbloError {
|
|
|
132
132
|
export class AbloValidationError extends AbloError {
|
|
133
133
|
type = 'AbloValidationError';
|
|
134
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* 404 — an UPDATE/DELETE addressed a row that doesn't exist (or is outside the
|
|
137
|
+
* caller's org). The engine reports such targets on `CommitReceipt.missingIds`;
|
|
138
|
+
* the typed resource wrappers raise this instead of returning a success receipt
|
|
139
|
+
* for a write that quietly matched zero rows. Carries the offending ids so a
|
|
140
|
+
* caller can see exactly which targets were absent.
|
|
141
|
+
*/
|
|
142
|
+
export class AbloNotFoundError extends AbloError {
|
|
143
|
+
type = 'AbloNotFoundError';
|
|
144
|
+
/** The id(s) that matched no row. */
|
|
145
|
+
missingIds;
|
|
146
|
+
constructor(message, missingIds, options) {
|
|
147
|
+
super(message, {
|
|
148
|
+
code: 'mutate_update_entity_not_found',
|
|
149
|
+
httpStatus: 404,
|
|
150
|
+
details: { missingIds },
|
|
151
|
+
...(options?.requestId !== undefined ? { requestId: options.requestId } : {}),
|
|
152
|
+
});
|
|
153
|
+
this.missingIds = missingIds;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
135
156
|
/** 5xx — server-side error. Usually retryable with backoff. */
|
|
136
157
|
export class AbloServerError extends AbloError {
|
|
137
158
|
type = 'AbloServerError';
|
package/dist/index.d.ts
CHANGED
|
@@ -59,7 +59,7 @@ export default Ablo;
|
|
|
59
59
|
export { dataSource, abloSource, sourceEventForOperation, signAbloSourceRequest, verifyAbloSourceRequest, } from './source/index.js';
|
|
60
60
|
export { createSourceConnector, type SourceConnector, type SourceConnectorOptions, type ConnectorStatus, } from './source/connector.js';
|
|
61
61
|
export { defaultPolicy, capabilityPreemptPolicy } from './policy/index.js';
|
|
62
|
-
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloServerError, AbloStaleContextError, AbloClaimedError, CapabilityError, translateHttpError, hasWireCode, errorFromWire, toAbloError, ERROR_CODES, ERROR_CONTRACT_VERSION, errorCodeSpec, isRetryableCode, classifyRecovery, recoveryClassSchema, RECOVERY_CLASSES, } from './errors.js';
|
|
62
|
+
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloNotFoundError, AbloServerError, AbloStaleContextError, AbloClaimedError, CapabilityError, translateHttpError, hasWireCode, errorFromWire, toAbloError, ERROR_CODES, ERROR_CONTRACT_VERSION, errorCodeSpec, isRetryableCode, classifyRecovery, recoveryClassSchema, RECOVERY_CLASSES, } from './errors.js';
|
|
63
63
|
export type { CommitReceipt, RequiredCapability } from './errors.js';
|
|
64
64
|
export type { ErrorCode, WireErrorCode, ErrorCategory, ErrorCodeSpec, RecoveryClass } from './errors.js';
|
|
65
65
|
export { WS_BEARER_SUBPROTOCOL_PREFIX, WS_SYNC_SUBPROTOCOL } from './auth/credentialSource.js';
|
package/dist/index.js
CHANGED
|
@@ -84,7 +84,7 @@ export { defaultPolicy, capabilityPreemptPolicy } from './policy/index.js';
|
|
|
84
84
|
// Typed error hierarchy — Stripe-style. One import gets every class
|
|
85
85
|
// consumers need to discriminate failures (`e instanceof AbloX` or
|
|
86
86
|
// `e.type === 'AbloX'`) plus the HTTP-response translator.
|
|
87
|
-
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloServerError, AbloStaleContextError, AbloClaimedError, CapabilityError, translateHttpError, hasWireCode, errorFromWire, toAbloError, ERROR_CODES, ERROR_CONTRACT_VERSION, errorCodeSpec, isRetryableCode, classifyRecovery, recoveryClassSchema, RECOVERY_CLASSES, } from './errors.js';
|
|
87
|
+
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloNotFoundError, AbloServerError, AbloStaleContextError, AbloClaimedError, CapabilityError, translateHttpError, hasWireCode, errorFromWire, toAbloError, ERROR_CODES, ERROR_CONTRACT_VERSION, errorCodeSpec, isRetryableCode, classifyRecovery, recoveryClassSchema, RECOVERY_CLASSES, } from './errors.js';
|
|
88
88
|
export { WS_BEARER_SUBPROTOCOL_PREFIX, WS_SYNC_SUBPROTOCOL } from './auth/credentialSource.js';
|
|
89
89
|
export { ENVIRONMENTS, environmentSchema, normalizeEnvironment, environmentFromKeyPrefix, environmentToKeyPrefix, isSandboxEnvironment, } from './environment.js';
|
|
90
90
|
// THE write-options contract — the one Zod schema for the option bag every
|
|
@@ -148,6 +148,11 @@ export interface CommitResult {
|
|
|
148
148
|
* receiving an `AbloStaleContextError`. See `StaleNotification`.
|
|
149
149
|
*/
|
|
150
150
|
notifications?: StaleNotification[];
|
|
151
|
+
/**
|
|
152
|
+
* Ids of UPDATE/DELETE targets that matched ZERO rows (loud 0-row writes).
|
|
153
|
+
* Present (non-empty) only when a write missed.
|
|
154
|
+
*/
|
|
155
|
+
missingIds?: string[];
|
|
151
156
|
}
|
|
152
157
|
/**
|
|
153
158
|
* Per-call knobs attached to any mutation. Mirrors Stripe's options
|
package/dist/server/commit.d.ts
CHANGED
|
@@ -114,4 +114,13 @@ export interface CommitResult {
|
|
|
114
114
|
* `StaleNotification` in `coordination/schema.ts`.
|
|
115
115
|
*/
|
|
116
116
|
notifications?: StaleNotification[];
|
|
117
|
+
/**
|
|
118
|
+
* Ids of UPDATE/DELETE targets that matched ZERO rows — the row doesn't
|
|
119
|
+
* exist (or is outside the caller's org). The engine has always detected
|
|
120
|
+
* this (and logged it); surfacing it here lets the client turn a silent
|
|
121
|
+
* no-op into a loud `AbloNotFoundError`. Present (non-empty) only when at
|
|
122
|
+
* least one op missed. Ids are globally-unique uuids, so a caller can match
|
|
123
|
+
* its own target id against this set without ambiguity.
|
|
124
|
+
*/
|
|
125
|
+
missingIds?: string[];
|
|
117
126
|
}
|
package/dist/wire/frames.d.ts
CHANGED
|
@@ -122,6 +122,13 @@ export interface MutationResultMessage {
|
|
|
122
122
|
* `conflict:notified` event and the commit receipt instead of rejecting.
|
|
123
123
|
*/
|
|
124
124
|
notifications?: StaleNotification[];
|
|
125
|
+
/**
|
|
126
|
+
* Ids of UPDATE/DELETE targets that matched ZERO rows (don't exist or are
|
|
127
|
+
* outside the org). Present (non-empty) only when a write missed. The
|
|
128
|
+
* client turns this into a loud `AbloNotFoundError` for the affected
|
|
129
|
+
* caller instead of treating the no-op as success.
|
|
130
|
+
*/
|
|
131
|
+
missingIds?: string[];
|
|
125
132
|
error?: {
|
|
126
133
|
code: ErrorCode;
|
|
127
134
|
message: string;
|