@smart-byte/leani-sdk 0.1.0-rc.1 → 0.1.0-rc.3

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/README.md CHANGED
@@ -29,10 +29,13 @@ const summary = await leani.request<Summary>(
29
29
  );
30
30
  ```
31
31
 
32
- The client rejects absolute and protocol-relative URLs before attaching a
33
- bearer token. Prefer the canonical instance-scoped `basePath` from capability
34
- discovery; short aliases may be absent when several instances share one
35
- extension.
32
+ The client rejects absolute and protocol-relative URLs, path segments that
33
+ decode to `.` or `..`, backslashes, encoded slashes, backslashes, and percent
34
+ signs, and control characters before attaching a bearer token. Every path
35
+ resolves under the base URL's path, one starting with `/` included, and the SDK
36
+ does not follow redirects. Prefer the canonical instance-scoped `basePath` from
37
+ capability discovery; short aliases may be absent when several instances share
38
+ one extension.
36
39
 
37
40
  When an alias is absent, pass the discovered canonical path to the typed
38
41
  helper instead of giving up its response types:
@@ -52,16 +55,21 @@ Historical subscription orchestration and unified live/history iterators are
52
55
  available from `@smart-byte/leani-sdk/backfill`. Required consumers should commit the
53
56
  application transaction before acknowledging the Leani-owned durable cursor.
54
57
  Destination writes must be idempotent because a crash between those steps can
55
- replay a change.
58
+ replay a change. Acknowledge a batch's `ackCursor` (or `acknowledgeableCursor`),
59
+ never a change's own cursor; a backfill session's `deliveryBatches()` yields
60
+ every such boundary with its changes, while `events()` yields changes only.
56
61
 
57
62
  The browser build assumes a same-origin deployment or a reverse proxy that
58
63
  adds the application's CORS policy. Leani does not enable cross-origin access
59
- on its native API by default.
64
+ on its native API by default, and refuses a browser origin that is neither
65
+ loopback nor listed in `api.allowed_origins`. The SDK's mutations without a
66
+ JSON body send `x-leani-request: 1`, which the node requires.
60
67
 
61
68
  Typed subscriptions accept a configured `processor` instance when a kind is
62
69
  ambiguous. `blobs.subscribe()` yields a `{ block, transactions }` payload on
63
70
  apply. Check `operation` before reading processor data: a finalized event has
64
- `{ throughBlock }` instead. Pass an `AbortSignal` to stop an idle stream;
71
+ `{ throughBlock }` instead, or, when `isLiveGapChange()` holds, the
72
+ `{ fromBlock, toBlock }` the live lane skipped. Pass an `AbortSignal` to stop an idle stream;
65
73
  leaving the loop cancels its response body.
66
74
 
67
75
  `queryAndFollow()` returns the first snapshot page and an atomic stream boundary.
@@ -75,9 +83,16 @@ with `boundaryCursor` and `recovery.follow` set to `null`. `queryAndFollow()`
75
83
  requires delivery and otherwise returns HTTP 409 `delivery_disabled`.
76
84
 
77
85
  Both package entry points use `LeaniError` for HTTP failures, including status,
78
- code, retryability, and request ID. ResetRequiredError is a LeaniError with
86
+ code, retryability, and request ID. A failure below HTTP, such as a refused or
87
+ reset connection or a silent stream, is a retryable `TransportError`, a
88
+ `LeaniError` with status 0. ResetRequiredError is a LeaniError with
79
89
  `code: "cursor_expired"`; rebuild application state from a fresh snapshot.
80
90
 
81
91
  ## License
82
92
 
83
93
  [MIT](LICENSE).
94
+
95
+ Development uses the TypeScript 7 native compiler through `@typescript/native`.
96
+ The pinned `typescript` 5.9 package supplies the JavaScript compiler API required
97
+ by `openapi-typescript`; build and typecheck scripts invoke the native compiler
98
+ explicitly so installing both packages cannot change which compiler runs.
@@ -1,5 +1,5 @@
1
- export { LeaniError } from "./errors.ts";
2
- import type { ChangeEnvelope, DurableConsumer, FetchLike, ProcessorSummary } from "./index.ts";
1
+ export { LeaniError, TransportError } from "./errors.ts";
2
+ import type { ChangeEnvelope, DurableConsumer, FetchLike, ProcessorCoverage, ProcessorSummary } from "./index.ts";
3
3
  export type BackfillExecutionMode = "fill_missing" | "recompute";
4
4
  export type BackfillState = "waiting_for_consumer" | "queued" | "running" | "backpressured" | "storage_backpressured" | "draining" | "complete_reclaimable" | "completed" | "failed" | "cancelled";
5
5
  export interface BackfillRange {
@@ -87,6 +87,16 @@ export type CreateBackfillSubscription = CreateBackfillSubscriptionBase & ({
87
87
  fromBlock?: never;
88
88
  toBlock?: never;
89
89
  });
90
+ /**
91
+ * The `fill_missing` subscription for the blocks a live gap notice
92
+ * announces, its `LiveGapChangeData`, or any other range the destination
93
+ * lacks. Its idempotency key derives from the consumer and the range, so
94
+ * creating it again, as after the notice is delivered again, returns the
95
+ * same subscription.
96
+ */
97
+ export declare function liveGapBackfill(range: BackfillRange, request: Omit<CreateBackfillSubscriptionBase, "mode" | "idempotencyKey"> & {
98
+ consumer: NonNullable<CreateBackfillSubscriptionBase["consumer"]>;
99
+ }): CreateBackfillSubscription;
90
100
  export interface BackfillStreamHello {
91
101
  type: "hello";
92
102
  apiVersion: "1";
@@ -172,6 +182,9 @@ export interface LiveStreamHello {
172
182
  heartbeatIntervalMs: string;
173
183
  sessionExpiresAtUnixMs: string;
174
184
  leaseTtlMs: string;
185
+ /** What the processor covers as the session starts: diff it against the
186
+ * destination to find blocks to request as history. */
187
+ coverage: ProcessorCoverage;
175
188
  }
176
189
  export interface LiveStreamBatch<T = unknown> {
177
190
  type: "batch";
@@ -203,6 +216,16 @@ export interface DeliverySession<THello, TRecord> extends AsyncIterable<TRecord>
203
216
  }
204
217
  export interface BackfillDeliverySession<T = unknown> extends DeliverySession<BackfillStreamHello, BackfillStreamRecord<T>> {
205
218
  batches(): AsyncIterable<BackfillStreamBatch<T>>;
219
+ /**
220
+ * Every acknowledgement boundary with the changes it covers: each batch,
221
+ * including one without changes, then the completion. Commit `events`,
222
+ * then acknowledge `ackCursor`.
223
+ */
224
+ deliveryBatches(): AsyncIterable<HistoryDeliveryBatch<T>>;
225
+ /**
226
+ * The batches' changes, flattened. They carry no acknowledgement
227
+ * boundary; acknowledge from `deliveryBatches()` or `batches()`.
228
+ */
206
229
  events(): AsyncIterable<ChangeEnvelope<T>>;
207
230
  }
208
231
  export type LiveDeliverySession<T = unknown> = DeliverySession<LiveStreamHello, LiveStreamRecord<T>>;
@@ -237,6 +260,10 @@ export type UnifiedDeliveryBatch<T = unknown> = {
237
260
  completion?: BackfillStreamCompletion;
238
261
  record: BackfillStreamBatch<T> | BackfillStreamCompletion;
239
262
  };
263
+ /** One history lane's batch, as `BackfillDeliverySession.deliveryBatches()` yields it. */
264
+ export type HistoryDeliveryBatch<T = unknown> = Extract<UnifiedDeliveryBatch<T>, {
265
+ laneKind: "history";
266
+ }>;
240
267
  export interface MultiLaneDelivery<T = unknown> {
241
268
  batches(): AsyncIterable<UnifiedDeliveryBatch<T>>;
242
269
  liveBatches(): AsyncIterable<UnifiedDeliveryBatch<T>>;
@@ -271,8 +298,18 @@ export interface BackfillSubscriptionClient {
271
298
  cancel(subscription: string, options?: {
272
299
  signal?: AbortSignal;
273
300
  }): Promise<BackfillStatus>;
301
+ /** Re-queue a failed subscription to resume from its committed progress. */
302
+ retry(subscription: string, options?: {
303
+ signal?: AbortSignal;
304
+ }): Promise<BackfillStatus>;
305
+ /**
306
+ * Delete a terminal subscription. A failed or cancelled one is refused
307
+ * while its required consumer has unacknowledged records, unless
308
+ * `discardUnacknowledged` is set.
309
+ */
274
310
  delete(subscription: string, options?: {
275
311
  signal?: AbortSignal;
312
+ discardUnacknowledged?: boolean;
276
313
  }): Promise<HistoricalWorkDeletion>;
277
314
  changes<T = unknown>(subscription: string, consumer: string, options?: {
278
315
  credential?: string;
@@ -296,4 +333,3 @@ export interface BackfillSubscriptionClient {
296
333
  }
297
334
  export declare function createBackfillSubscriptionClient(options: BackfillSubscriptionClientOptions): BackfillSubscriptionClient;
298
335
  export declare function parseNdjson(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<unknown>;
299
- //# sourceMappingURL=backfill.d.ts.map