js-bao-wss-client 2.2.0-alpha.13 → 2.2.0-alpha.14
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 +28 -3
- package/dist/JsBaoClient.d.ts +168 -0
- package/dist/JsBaoClient.js +373 -6
- package/dist/api/databaseTypeConfigsApi.d.ts +3 -5
- package/dist/api/databasesApi.d.ts +3 -0
- package/dist/api/documentsApi.d.ts +80 -4
- package/dist/api/documentsApi.js +35 -3
- package/dist/api/geminiApi.d.ts +5 -2
- package/dist/api/geminiApi.js +5 -2
- package/dist/api/invitationsApi.d.ts +7 -4
- package/dist/api/invitationsApi.js +3 -1
- package/dist/browser.umd.js +536 -37
- package/dist/errors.d.ts +1 -1
- package/dist/internal/documentManager.d.ts +58 -0
- package/dist/internal/documentManager.js +98 -27
- package/dist/internal/large-documents/document-format.d.ts +19 -0
- package/dist/internal/large-documents/document-format.js +24 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1280,15 +1280,19 @@ console.log(result.documentId); // The created document ID
|
|
|
1280
1280
|
console.log(result.alias.aliasKey); // "current-draft"
|
|
1281
1281
|
console.log(result.alias.documentId); // Same as documentId
|
|
1282
1282
|
|
|
1283
|
-
// The alias create takes
|
|
1284
|
-
//
|
|
1285
|
-
//
|
|
1283
|
+
// The alias create takes the whole create vocabulary — `tags`, `metadata` and
|
|
1284
|
+
// `documentFormat` — with the same meaning they have on `create()`: applied when
|
|
1285
|
+
// the call creates the document. The response echoes what it applied, and omits
|
|
1286
|
+
// `documentFormat` for an ordinary document.
|
|
1286
1287
|
const ledger = await client.documents.createWithAlias({
|
|
1287
1288
|
title: "Ledger",
|
|
1288
1289
|
alias: { scope: "user", aliasKey: "ledger" },
|
|
1290
|
+
tags: ["ledger", "q3"],
|
|
1291
|
+
metadata: { owner: "finance" },
|
|
1289
1292
|
documentFormat: 2,
|
|
1290
1293
|
});
|
|
1291
1294
|
console.log(ledger.documentFormat); // 2
|
|
1295
|
+
console.log(ledger.tags); // ["ledger", "q3"]
|
|
1292
1296
|
|
|
1293
1297
|
// Attempting to create with an existing alias throws HTTP 409
|
|
1294
1298
|
try {
|
|
@@ -1310,6 +1314,27 @@ try {
|
|
|
1310
1314
|
|
|
1311
1315
|
Use `createWithAlias()` when you need guaranteed uniqueness based on an alias (e.g., "only one home page per app"). Use regular `create()` + `aliases.set()` when offline support is needed or when the document should be created regardless of alias conflicts.
|
|
1312
1316
|
|
|
1317
|
+
#### Get-or-Create with Alias
|
|
1318
|
+
|
|
1319
|
+
When you want the document to exist rather than to be new — "this user's ledger" — `getOrCreateWithAlias()` is the idempotent form: the first call creates it, every later one returns the same document. It takes the same options, applied only when the call creates the document:
|
|
1320
|
+
|
|
1321
|
+
```typescript
|
|
1322
|
+
const ledger = await client.documents.getOrCreateWithAlias({
|
|
1323
|
+
title: "Ledger",
|
|
1324
|
+
alias: { scope: "user", aliasKey: "ledger" },
|
|
1325
|
+
tags: ["ledger"],
|
|
1326
|
+
documentFormat: 2,
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
console.log(ledger.created); // true on the call that made it, false after
|
|
1330
|
+
console.log(ledger.documentFormat); // 2 either way
|
|
1331
|
+
console.log(ledger.tags); // ["ledger"] on the create; absent afterwards
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
A stated `documentFormat` is also a statement about a document the alias already names. If the stored format **differs**, the call is refused with `DOCUMENT_FORMAT_MISMATCH` (409) naming the document and both formats, and nothing is created — being handed an ordinary document when you asked for a large one is the mistake this route exists to prevent. If it agrees, the format is echoed. Omit it and an existing binding is answered exactly as it always was.
|
|
1335
|
+
|
|
1336
|
+
> All three create routes refuse a top-level body key they do not read, with 400 `VALIDATION_FAILED` and a `details` entry naming it. The typed methods above send only keys the routes read; this reaches you only if you build a request body by hand.
|
|
1337
|
+
|
|
1313
1338
|
### Manage Permissions
|
|
1314
1339
|
|
|
1315
1340
|
```typescript
|
package/dist/JsBaoClient.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { type RequestOptions } from "./internal/httpClient";
|
|
|
15
15
|
import { type DocumentPermission as DocumentAccessLevel, type LocalDocumentEntry, type LocalMetadataEntry, type DocumentDebugSnapshot } from "./internal/documentManager";
|
|
16
16
|
import { type OfflineReplayNotice } from "js-bao";
|
|
17
17
|
import type { DocumentOfflineWindowError } from "js-bao";
|
|
18
|
+
import { JsBaoError } from "./errors";
|
|
18
19
|
import { DocumentsAPI, DocumentContext, type DocumentInfo, type ResolveAliasParams, type CreateDocumentOptions } from "./api/documentsApi";
|
|
19
20
|
import { type CacheFacade } from "./api/cacheFacade";
|
|
20
21
|
import { MeAPI } from "./api/meApi";
|
|
@@ -407,6 +408,25 @@ export interface ExecutePromptResult<R = unknown> {
|
|
|
407
408
|
success: boolean;
|
|
408
409
|
output: string;
|
|
409
410
|
error?: string;
|
|
411
|
+
/**
|
|
412
|
+
* The upstream provider's own HTTP status, on a failure where the call
|
|
413
|
+
* reached the provider and it answered. It does not depend on which provider
|
|
414
|
+
* the prompt's configuration names, and it is what a retry decision is made
|
|
415
|
+
* on without parsing `error`: retry on 408, 429, 502, 503 and 504; any other
|
|
416
|
+
* 4xx will fail the same way next time.
|
|
417
|
+
*
|
|
418
|
+
* Absent on success, and absent on a failure where no provider answer was
|
|
419
|
+
* observed — an unset provider key, an oversized payload, a completion that
|
|
420
|
+
* came back empty — so a number here is always the provider's own.
|
|
421
|
+
*/
|
|
422
|
+
upstreamStatus?: number;
|
|
423
|
+
/**
|
|
424
|
+
* `"PROMPT_UPSTREAM_TIMEOUT"` when the provider itself ran out of time,
|
|
425
|
+
* which is the one failure of the model call that carries a code. Absent on
|
|
426
|
+
* success and on every other provider failure, so `error` with no
|
|
427
|
+
* `errorCode` still means "the call failed for some other reason".
|
|
428
|
+
*/
|
|
429
|
+
errorCode?: "PROMPT_UPSTREAM_TIMEOUT";
|
|
410
430
|
metrics: {
|
|
411
431
|
durationMs: number;
|
|
412
432
|
inputTokens?: number;
|
|
@@ -663,6 +683,36 @@ export interface DocumentWriteRefusedEvent {
|
|
|
663
683
|
*/
|
|
664
684
|
error: DocumentOfflineWindowError;
|
|
665
685
|
}
|
|
686
|
+
/**
|
|
687
|
+
* Payload of the `document:format-mismatch` event
|
|
688
|
+
* (`client.on("document:format-mismatch", ...)`).
|
|
689
|
+
*
|
|
690
|
+
* Fired when the platform refuses a document because the format this client
|
|
691
|
+
* believed it had is not the format the platform resolved. The document is
|
|
692
|
+
* CLOSED when this arrives — its local rows and its unacknowledged writes are
|
|
693
|
+
* kept, nothing is evicted — because two of the three open shapes have no
|
|
694
|
+
* waiter to reject: a cached open sends its handshake from a microtask, and an
|
|
695
|
+
* already-open document re-syncs on reconnect. An open that WAS waiting on the
|
|
696
|
+
* network rejects with the same error as well.
|
|
697
|
+
*
|
|
698
|
+
* Diagnose from {@link declared} and {@link actual} before doing anything: the
|
|
699
|
+
* server also logs `Document format disagreement` naming its own pinned format.
|
|
700
|
+
* Evicting the document clears this client's belief, which repairs a stale row
|
|
701
|
+
* and HIDES a mis-pinned document.
|
|
702
|
+
*/
|
|
703
|
+
export interface DocumentFormatMismatchEvent {
|
|
704
|
+
documentId: string;
|
|
705
|
+
/** What this client believed, from its own local metadata row. */
|
|
706
|
+
declared: 1 | 2;
|
|
707
|
+
/** What the platform resolved for the document. */
|
|
708
|
+
actual: 1 | 2;
|
|
709
|
+
/**
|
|
710
|
+
* The very error a waiting `documents.open` rejects with: `code` is
|
|
711
|
+
* `DOCUMENT_FORMAT_MISMATCH` and `details` carries `documentId`, `declared`
|
|
712
|
+
* and `actual`.
|
|
713
|
+
*/
|
|
714
|
+
error: JsBaoError;
|
|
715
|
+
}
|
|
666
716
|
/**
|
|
667
717
|
* Options for `client.syncMetadata()`. Controls whether the sync covers all
|
|
668
718
|
* of the user's document metadata or a single document (`scope` /
|
|
@@ -1794,6 +1844,7 @@ export interface JsBaoEvents {
|
|
|
1794
1844
|
awareness: AwarenessEvent;
|
|
1795
1845
|
"document:snapshot-load": DocumentSnapshotLoadEvent;
|
|
1796
1846
|
"document:write-refused": DocumentWriteRefusedEvent;
|
|
1847
|
+
"document:format-mismatch": DocumentFormatMismatchEvent;
|
|
1797
1848
|
"blobs:upload-progress": BlobUploadProgressEvent;
|
|
1798
1849
|
"blobs:upload-completed": BlobUploadCompletedEvent;
|
|
1799
1850
|
"blobs:upload-failed": BlobUploadFailedEvent;
|
|
@@ -2319,6 +2370,28 @@ export declare class JsBaoClient extends Observable<any> {
|
|
|
2319
2370
|
* and released once the handshake has been answered.
|
|
2320
2371
|
*/
|
|
2321
2372
|
private readonly format2AwaitingHandshake;
|
|
2373
|
+
/**
|
|
2374
|
+
* The format each open attempt in flight pinned — #3764, decision D8.
|
|
2375
|
+
*
|
|
2376
|
+
* One format per open, declared on `syncStep1` and BOUND by the ORM. The
|
|
2377
|
+
* background document read `DocumentManager.openDocument` starts rewrites the
|
|
2378
|
+
* metadata row in between, so reading the row at the bind could bind the
|
|
2379
|
+
* other format after the handshake had agreed on this one — the exact failure
|
|
2380
|
+
* this feature exists to prevent. Cleared when the open settles, after which
|
|
2381
|
+
* the row is the source again.
|
|
2382
|
+
*/
|
|
2383
|
+
private readonly openAttemptFormats;
|
|
2384
|
+
/**
|
|
2385
|
+
* Documents the platform has REFUSED on this connection — #3764.
|
|
2386
|
+
*
|
|
2387
|
+
* A refused document sends no further handshake, is not retried by the sync
|
|
2388
|
+
* watchdog, and does not rebuild the socket on its account; a fresh open of it
|
|
2389
|
+
* is rejected with the refusal rather than waiting out an availability budget
|
|
2390
|
+
* for a handshake this client will not send. The mark is cleared when the
|
|
2391
|
+
* document is closed, evicted, or its metadata row's format changes — after
|
|
2392
|
+
* any of which this client's belief is no longer the one that was refused.
|
|
2393
|
+
*/
|
|
2394
|
+
private readonly format2FormatRefusals;
|
|
2322
2395
|
/** Outbound sequences per large document: queued, sent, acknowledged. */
|
|
2323
2396
|
private readonly format2Ack;
|
|
2324
2397
|
private jsBaoAddDocumentModelMapping;
|
|
@@ -3398,6 +3471,12 @@ export declare class JsBaoClient extends Observable<any> {
|
|
|
3398
3471
|
* the server's mark is contiguous, so nothing above a covered sequence can be
|
|
3399
3472
|
* acknowledged anyway, and claiming it would only invite the prune this
|
|
3400
3473
|
* exists to prevent.
|
|
3474
|
+
*
|
|
3475
|
+
* A `legacy` note (#3760) is the same debt reached a different way — writes
|
|
3476
|
+
* taken over from a pre-amendment pool and kept off the overlay until they
|
|
3477
|
+
* are judged — so it withholds exactly as an ordinary one does (finding
|
|
3478
|
+
* 3760-REVIEW-07). Only the bulk-load kind is left out: `_discontinuities`
|
|
3479
|
+
* owns that debt and its own hold.
|
|
3401
3480
|
*/
|
|
3402
3481
|
private format2ApplyDurableWithhold;
|
|
3403
3482
|
/** The withheld writes have been replayed: their sequences may travel. */
|
|
@@ -3848,6 +3927,95 @@ export declare class JsBaoClient extends Observable<any> {
|
|
|
3848
3927
|
* nothing of its local state may go out (see `format2RequireReload`).
|
|
3849
3928
|
*/
|
|
3850
3929
|
private format2NeedsReload;
|
|
3930
|
+
/**
|
|
3931
|
+
* Pin what this open attempt BELIEVES the document's format is, before any
|
|
3932
|
+
* handshake can leave (#3764, D8).
|
|
3933
|
+
*
|
|
3934
|
+
* Deliberately the local row's own answer rather than `_resolveDocumentFormat`,
|
|
3935
|
+
* and the difference is the whole point twice over:
|
|
3936
|
+
*
|
|
3937
|
+
* - that resolver DEFAULTS. It answers 1 for a document nobody knows about,
|
|
3938
|
+
* which is the right thing to BIND (the compatible layout) and a false
|
|
3939
|
+
* thing to DECLARE — a first open of somebody else's document would claim
|
|
3940
|
+
* format 1 and be refused. Only a row that NAMES a format is a belief, and
|
|
3941
|
+
* `documentFormatOf` answers `null` for anything else (criterion 3).
|
|
3942
|
+
* - it can reach the SERVER, and this runs before the connection is up, so
|
|
3943
|
+
* resolving here would both add a request to the open's critical path and
|
|
3944
|
+
* answer differently depending on how far the connect had got.
|
|
3945
|
+
*
|
|
3946
|
+
* Nothing is pinned when nothing is believed, and the bind then resolves as it
|
|
3947
|
+
* always has. When something IS pinned, the declaration and the bind are that
|
|
3948
|
+
* one value — which is what makes a row rewritten in between unable to move
|
|
3949
|
+
* the bind under a handshake that has already agreed.
|
|
3950
|
+
*/
|
|
3951
|
+
private pinOpenAttemptFormat;
|
|
3952
|
+
/**
|
|
3953
|
+
* The format the ORM binds this document on (#3764, D8).
|
|
3954
|
+
*
|
|
3955
|
+
* The attempt's pinned answer when an open is in flight — never a second
|
|
3956
|
+
* resolution, which is what let a row rewritten mid-open move the bind under a
|
|
3957
|
+
* handshake that had already agreed. With no attempt (a rebind outside an
|
|
3958
|
+
* open) the ordinary resolution stands.
|
|
3959
|
+
*/
|
|
3960
|
+
private boundDocumentFormat;
|
|
3961
|
+
/**
|
|
3962
|
+
* The format this client DECLARES for a document on `syncStep1` (#3764).
|
|
3963
|
+
*
|
|
3964
|
+
* The attempt's pinned answer while an open is in flight, else what the local
|
|
3965
|
+
* metadata row says. `undefined` — a first open of somebody else's document,
|
|
3966
|
+
* or one whose row an eviction removed — declares nothing, and such a client
|
|
3967
|
+
* is served exactly as it was before this field existed (criterion 3).
|
|
3968
|
+
*/
|
|
3969
|
+
private declaredDocumentFormat;
|
|
3970
|
+
/**
|
|
3971
|
+
* Whether the platform has refused this document on this connection (#3764).
|
|
3972
|
+
*
|
|
3973
|
+
* The recorded belief is re-read before the mark is: behavior 17's rule is
|
|
3974
|
+
* that the mark clears when the row's format changes, and a row is written
|
|
3975
|
+
* from more places than the format resolver's own `remember` — a listing
|
|
3976
|
+
* upgrades it, and so does the canonical read an open performs. Asking here
|
|
3977
|
+
* means no write site has to remember, and the answer cannot drift from what
|
|
3978
|
+
* the next handshake would declare.
|
|
3979
|
+
*/
|
|
3980
|
+
private formatRefusalFor;
|
|
3981
|
+
/**
|
|
3982
|
+
* Reject an open whose document the platform refused while it ran (#3764).
|
|
3983
|
+
*
|
|
3984
|
+
* A cached open resolves without a waiter, so a refusal landing while it is
|
|
3985
|
+
* still binding the ORM has nothing to fail. Checked after the bind and
|
|
3986
|
+
* before the handle is returned, the open rejects with the typed error
|
|
3987
|
+
* instead of handing back a document whose sync and persistence the
|
|
3988
|
+
* refusal's teardown has detached. A mark that stood before the open began
|
|
3989
|
+
* never gets here: the open refuses it on entry.
|
|
3990
|
+
*/
|
|
3991
|
+
private rejectIfRefusedDuringOpen;
|
|
3992
|
+
/** Drop a format refusal, naming why it no longer applies (#3764). */
|
|
3993
|
+
private clearFormatRefusal;
|
|
3994
|
+
/**
|
|
3995
|
+
* A document's locally recorded format changed, so the belief that was
|
|
3996
|
+
* refused is no longer the one this client holds (#3764, behavior 17).
|
|
3997
|
+
*
|
|
3998
|
+
* Only a change AWAY from the refused declaration clears the mark: a row that
|
|
3999
|
+
* still says the refused thing would only be refused again.
|
|
4000
|
+
*/
|
|
4001
|
+
private noteDocumentFormatChanged;
|
|
4002
|
+
/**
|
|
4003
|
+
* Refuse ONE document because the platform and this client disagree about its
|
|
4004
|
+
* format — #3764, decision D7.
|
|
4005
|
+
*
|
|
4006
|
+
* A document-scoped teardown rather than a waiter failer, and that is the
|
|
4007
|
+
* whole finding: of the three shapes an open takes, only a network wait has a
|
|
4008
|
+
* waiter. A cached open sends its `syncStep1` from a microtask with nothing
|
|
4009
|
+
* waiting, and an already-open document re-syncs on reconnect — so an
|
|
4010
|
+
* event-only answer would leave both bound and syncing against a document the
|
|
4011
|
+
* platform is refusing to serve them.
|
|
4012
|
+
*
|
|
4013
|
+
* What it does NOT do: close the connection (D1 — one document is refused,
|
|
4014
|
+
* and the socket's other documents are none of its business) and clear any
|
|
4015
|
+
* local data (the rows and `_pending_ops` are kept, so a corrected open
|
|
4016
|
+
* publishes what this client wrote).
|
|
4017
|
+
*/
|
|
4018
|
+
private refuseDocumentFormat;
|
|
3851
4019
|
/**
|
|
3852
4020
|
* Hold every open large document's queued writes until its own handshake on
|
|
3853
4021
|
* this connection has been answered (#3435).
|