@brass-build/client 0.3.0 → 0.4.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/AGENTS.md +50 -7
- package/CHANGELOG.md +63 -2
- package/README.md +233 -77
- package/dist/acting-organization.d.ts +131 -0
- package/dist/acting-organization.d.ts.map +1 -0
- package/dist/acting-organization.js +273 -0
- package/dist/acting-organization.js.map +1 -0
- package/dist/api-headers.js +7 -7
- package/dist/api-headers.js.map +1 -1
- package/dist/call-service.d.ts +74 -0
- package/dist/call-service.d.ts.map +1 -0
- package/dist/call-service.js +253 -0
- package/dist/call-service.js.map +1 -0
- package/dist/client.d.ts +31 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +611 -12
- package/dist/client.js.map +1 -1
- package/dist/document-contents.d.ts +15 -0
- package/dist/document-contents.d.ts.map +1 -0
- package/dist/document-contents.js +88 -0
- package/dist/document-contents.js.map +1 -0
- package/dist/document-streams.d.ts +4 -2
- package/dist/document-streams.d.ts.map +1 -1
- package/dist/document-streams.js +6 -0
- package/dist/document-streams.js.map +1 -1
- package/dist/documents.d.ts +45 -1
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js +305 -22
- package/dist/documents.js.map +1 -1
- package/dist/export-guest.d.ts.map +1 -1
- package/dist/export-guest.js +5 -0
- package/dist/export-guest.js.map +1 -1
- package/dist/handle-types.d.ts +23 -0
- package/dist/handle-types.d.ts.map +1 -1
- package/dist/handles.d.ts +1 -1
- package/dist/handles.d.ts.map +1 -1
- package/dist/handles.js +1 -1
- package/dist/handles.js.map +1 -1
- package/dist/hosted-ui.d.ts +10 -0
- package/dist/hosted-ui.d.ts.map +1 -1
- package/dist/hosted-ui.js +115 -30
- package/dist/hosted-ui.js.map +1 -1
- package/dist/importer.d.ts.map +1 -1
- package/dist/importer.js +17 -6
- package/dist/importer.js.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/mutate-batching.js +2 -2
- package/dist/mutate-batching.js.map +1 -1
- package/dist/open-document.d.ts +1 -1
- package/dist/open-document.d.ts.map +1 -1
- package/dist/open-document.js +69 -34
- package/dist/open-document.js.map +1 -1
- package/dist/presence.d.ts +10 -0
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js.map +1 -1
- package/dist/session-toolbar.d.ts +9 -0
- package/dist/session-toolbar.d.ts.map +1 -1
- package/dist/session-toolbar.js +60 -12
- package/dist/session-toolbar.js.map +1 -1
- package/dist/tail-ops.js +2 -2
- package/dist/tail-ops.js.map +1 -1
- package/dist/types.d.ts +0 -42
- package/dist/types.d.ts.map +1 -1
- package/dist/undo.d.ts +1 -1
- package/dist/undo.d.ts.map +1 -1
- package/dist/undo.js +1 -1
- package/dist/undo.js.map +1 -1
- package/dist/version-bar.d.ts.map +1 -1
- package/dist/version-bar.js +52 -2
- package/dist/version-bar.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/dist/wasm-ready-gate.d.ts +13 -0
- package/dist/wasm-ready-gate.d.ts.map +1 -0
- package/dist/wasm-ready-gate.js +28 -0
- package/dist/wasm-ready-gate.js.map +1 -0
- package/dist/wasm-runtime.browser.d.ts +11 -0
- package/dist/wasm-runtime.browser.d.ts.map +1 -0
- package/dist/wasm-runtime.browser.js +44 -0
- package/dist/wasm-runtime.browser.js.map +1 -0
- package/dist/wasm-runtime.d.ts +6 -0
- package/dist/wasm-runtime.d.ts.map +1 -0
- package/dist/wasm-runtime.js +20 -0
- package/dist/wasm-runtime.js.map +1 -0
- package/docs/app-manifest.md +335 -5
- package/docs/custom-chrome.md +3 -0
- package/docs/presence.md +12 -0
- package/docs/services.md +265 -0
- package/docs/text-fields.md +191 -0
- package/package.json +4 -5
- package/src/acting-organization.ts +390 -0
- package/src/api-headers.ts +7 -7
- package/src/call-service.ts +354 -0
- package/src/client.ts +680 -14
- package/src/document-contents.ts +104 -0
- package/src/document-streams.ts +15 -1
- package/src/documents.ts +340 -20
- package/src/export-guest.ts +5 -0
- package/src/handle-types.ts +35 -0
- package/src/handles.ts +1 -1
- package/src/hosted-ui.ts +155 -29
- package/src/importer.ts +17 -6
- package/src/index.ts +43 -4
- package/src/internal.ts +4 -0
- package/src/mutate-batching.ts +2 -2
- package/src/open-document.ts +79 -38
- package/src/presence.ts +6 -0
- package/src/session-toolbar.ts +80 -12
- package/src/tail-ops.ts +2 -2
- package/src/types.ts +6 -4
- package/src/undo.ts +1 -1
- package/src/version-bar.ts +53 -2
- package/src/version.ts +1 -1
- package/src/wasm-ready-gate.ts +30 -0
- package/src/wasm-runtime.browser.ts +48 -0
- package/src/wasm-runtime.ts +21 -0
- package/dist/vite.d.ts +0 -31
- package/dist/vite.d.ts.map +0 -1
- package/dist/vite.js +0 -161
- package/dist/vite.js.map +0 -1
- package/src/vite.ts +0 -214
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-document.d.ts","sourceRoot":"","sources":["../src/open-document.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,QAAQ,EACR,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EAGvB,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"open-document.d.ts","sourceRoot":"","sources":["../src/open-document.ts"],"names":[],"mappings":"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"}
|
package/dist/open-document.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// raw Loro import at 50k entities, so the materialisation path adds no
|
|
5
5
|
// full-snapshot logging or deep cloning of decoded bytes.
|
|
6
6
|
import { DEFAULT_STREAM_NAME, Document, } from './documents.js';
|
|
7
|
+
import { ensureWasmReady } from './wasm-runtime.js';
|
|
7
8
|
import { createPresenceController } from './presence.js';
|
|
8
9
|
import { applyAppAssertionHeader, applyClientVersionHeader } from './api-headers.js';
|
|
9
10
|
import { brassErrorFromBody } from './api-fetch.js';
|
|
@@ -533,16 +534,16 @@ export function createOpenDocument(opts) {
|
|
|
533
534
|
// open on something that clears on its own.
|
|
534
535
|
//
|
|
535
536
|
// Longer than the default handful of attempts because of what a 503 means
|
|
536
|
-
// on this route: the document is intact and its storage is busy.
|
|
537
|
-
//
|
|
538
|
-
// answer 503 is one that was just written hard, which is exactly the
|
|
537
|
+
// on this route: the document is intact and its storage is busy. A
|
|
538
|
+
// document's own writes contend with each other, so the one most likely
|
|
539
|
+
// to answer 503 is one that was just written hard, which is exactly the
|
|
539
540
|
// moment a person reloads to see their work. That pressure clears over
|
|
540
541
|
// tens of seconds, not the one second the default budget spans, and the
|
|
541
542
|
// cost of giving up early is telling someone their document will not open
|
|
542
543
|
// when waiting would have opened it.
|
|
543
544
|
//
|
|
544
545
|
// A thrown request gets a short budget of its own: it never reached the
|
|
545
|
-
// API, so
|
|
546
|
+
// API, so busy storage is not what is wrong, and a blocked origin
|
|
546
547
|
// or a host that does not resolve answers the seventh attempt as it
|
|
547
548
|
// answered the first, with the reader watching a loading surface
|
|
548
549
|
// throughout.
|
|
@@ -665,7 +666,7 @@ export function createOpenDocument(opts) {
|
|
|
665
666
|
// piped through `open` to materialise the editable Document.
|
|
666
667
|
// What the app hears when an op the socket could not carry also failed
|
|
667
668
|
// over HTTP. The server's message is preferred where it has one, since it
|
|
668
|
-
// names the actual refusal (too large
|
|
669
|
+
// names the actual refusal (too large to store inline, a revoked
|
|
669
670
|
// role); the status-shaped fallbacks cover a response that carries none.
|
|
670
671
|
function opWriteFailureMessage(status, parsed) {
|
|
671
672
|
const serverMessage = parsed?.error;
|
|
@@ -678,12 +679,12 @@ export function createOpenDocument(opts) {
|
|
|
678
679
|
return 'This document is no longer available.';
|
|
679
680
|
return `This change could not be saved (${status}).`;
|
|
680
681
|
}
|
|
681
|
-
// Write one op over HTTP. The socket carries an op only up to
|
|
682
|
-
//
|
|
683
|
-
//
|
|
682
|
+
// Write one op over HTTP. The socket carries an op only up to its own
|
|
683
|
+
// message cap; past it the message is not delivered and the connection is
|
|
684
|
+
// closed, so `wireDocTransport` sends the large ones here.
|
|
684
685
|
// Not retried on a transient failure: the caller holds the op in its
|
|
685
686
|
// outstanding tracker and re-asserts it, and a blind replay would write a
|
|
686
|
-
// second
|
|
687
|
+
// second stored copy of the same edit.
|
|
687
688
|
// Mint a presigned PUT and upload the blob to it, returning the staging
|
|
688
689
|
// key the op write names. The PUT carries no Brass headers: the URL is
|
|
689
690
|
// signed, and an extra header falls outside that signature.
|
|
@@ -735,9 +736,9 @@ export function createOpenDocument(opts) {
|
|
|
735
736
|
};
|
|
736
737
|
applyClientVersionHeader(headers);
|
|
737
738
|
await applyAppAssertionHeader(headers, opts.getAppAssertion);
|
|
738
|
-
// Past
|
|
739
|
-
//
|
|
740
|
-
//
|
|
739
|
+
// Past the size an op can carry inline, the blob is uploaded first and
|
|
740
|
+
// the write names what was staged, so a multi-megabyte op never travels
|
|
741
|
+
// through a request body.
|
|
741
742
|
let stagedKey;
|
|
742
743
|
if (opBlobNeedsStaging(opBlobB64)) {
|
|
743
744
|
stagedKey = await stageOpBlob(docId, opBlobB64, token);
|
|
@@ -821,31 +822,35 @@ export function createOpenDocument(opts) {
|
|
|
821
822
|
// a needed destination / organization before showing a loading state; any
|
|
822
823
|
// other non-2xx throws.
|
|
823
824
|
//
|
|
824
|
-
// A create that names no placement of its own
|
|
825
|
-
//
|
|
826
|
-
//
|
|
827
|
-
//
|
|
828
|
-
//
|
|
825
|
+
// A create that names no placement of its own lands in the organization the
|
|
826
|
+
// app is already acting in: the one a launch named, the one a document the
|
|
827
|
+
// reader just closed lives in, or the one they chose in the account menu's
|
|
828
|
+
// switch. Without it a member of several organizations is asked to name a
|
|
829
|
+
// destination they have already answered, once per create. An explicit
|
|
830
|
+
// `siblingOf` / `destination` outranks it: placing a document beside the
|
|
831
|
+
// open one is the more specific answer.
|
|
829
832
|
const createDocumentId = async (args) => {
|
|
830
|
-
const
|
|
831
|
-
? (opts.
|
|
833
|
+
const preferred = args.siblingOf === undefined && args.destination === undefined
|
|
834
|
+
? (opts.preferredOrganizationId?.() ?? null)
|
|
832
835
|
: null;
|
|
833
|
-
if (
|
|
836
|
+
if (preferred === null)
|
|
834
837
|
return postAndClassify(args);
|
|
835
838
|
try {
|
|
836
839
|
return await postAndClassify({
|
|
837
840
|
...args,
|
|
838
|
-
destination: { organization_id:
|
|
841
|
+
destination: { organization_id: preferred },
|
|
839
842
|
});
|
|
840
843
|
}
|
|
841
844
|
catch (err) {
|
|
842
|
-
//
|
|
843
|
-
//
|
|
844
|
-
//
|
|
845
|
-
//
|
|
846
|
-
//
|
|
847
|
-
//
|
|
848
|
-
//
|
|
845
|
+
// Every source of this value is a preference rather than an answer: a
|
|
846
|
+
// URL parameter, a document open in an organization reached through a
|
|
847
|
+
// shared project, a choice made before the person left. Each can name
|
|
848
|
+
// an organization the caller no longer has, which the server answers
|
|
849
|
+
// with a plain 404. Drop it and let the server resolve the destination
|
|
850
|
+
// on its own, which routes a multi-organization caller to the picker. A
|
|
851
|
+
// coded rejection (`app_not_installed`) belongs to the caller's own
|
|
852
|
+
// consent flow and passes through untouched, as does the 404 for an
|
|
853
|
+
// organization that exists but denies the app.
|
|
849
854
|
if (err instanceof BrassError && err.status === 404 && !err.code) {
|
|
850
855
|
return postAndClassify(args);
|
|
851
856
|
}
|
|
@@ -1052,6 +1057,7 @@ export function createOpenDocument(opts) {
|
|
|
1052
1057
|
resyncFromSnapshot,
|
|
1053
1058
|
skipPresence: true,
|
|
1054
1059
|
parkable: false,
|
|
1060
|
+
capacityReloadsDocument: false,
|
|
1055
1061
|
});
|
|
1056
1062
|
}
|
|
1057
1063
|
return doc;
|
|
@@ -1533,6 +1539,12 @@ export function createOpenDocument(opts) {
|
|
|
1533
1539
|
}
|
|
1534
1540
|
if (opts.reportError)
|
|
1535
1541
|
doc.setErrorReporter(opts.reportError);
|
|
1542
|
+
// No socket on a document the caller can write to: the write path reaches
|
|
1543
|
+
// no server, so the document reports the first attempt rather than
|
|
1544
|
+
// discarding it. Outside tests this is `wsBaseUrl` left unset, which
|
|
1545
|
+
// naming any other base URL does.
|
|
1546
|
+
if (!opts.wsClient && !doc.readOnly)
|
|
1547
|
+
doc.markTransportUnavailable();
|
|
1536
1548
|
return doc;
|
|
1537
1549
|
}
|
|
1538
1550
|
// Open at a historical version: read-only, no transport. The at-version
|
|
@@ -1749,8 +1761,13 @@ export function createOpenDocument(opts) {
|
|
|
1749
1761
|
// guest).
|
|
1750
1762
|
function wireGuestTransport(doc, token, docId, lineId, canEdit) {
|
|
1751
1763
|
const wsClient = opts.wsClient;
|
|
1752
|
-
if (!wsClient)
|
|
1764
|
+
if (!wsClient) {
|
|
1765
|
+
// No socket: a write would change local state and reach no server, so
|
|
1766
|
+
// the document reports the first one instead of discarding it quietly.
|
|
1767
|
+
if (canEdit)
|
|
1768
|
+
doc.markTransportUnavailable();
|
|
1753
1769
|
return;
|
|
1770
|
+
}
|
|
1754
1771
|
const topic = `doc:${docId}:${lineId}`;
|
|
1755
1772
|
// Ops on the socket awaiting an answer, keyed by `client_op_id`. An
|
|
1756
1773
|
// `unavailable` shed names no op, so re-asserting one needs the frames
|
|
@@ -2060,11 +2077,12 @@ export function createOpenDocument(opts) {
|
|
|
2060
2077
|
// create + obtain the doc_id, then `open(docId)`); they aren't fused
|
|
2061
2078
|
// because the create response is metadata-only and the open path already
|
|
2062
2079
|
// handles the empty-snapshot case via `Document.create()`. This is the
|
|
2063
|
-
// low-level path (`Brass.createDocument`): the
|
|
2064
|
-
// the
|
|
2065
|
-
//
|
|
2066
|
-
//
|
|
2067
|
-
//
|
|
2080
|
+
// low-level path (`Brass.createDocument`): the doc lands in the
|
|
2081
|
+
// organization the app is acting in, and otherwise in the caller's single
|
|
2082
|
+
// organization; a caller with none is routed to the hosted
|
|
2083
|
+
// acquire-organization surface and the create retries; a multi-org caller
|
|
2084
|
+
// whose app is acting nowhere rejects with a 409 (no hosted picker here,
|
|
2085
|
+
// that is the session's `create()`).
|
|
2068
2086
|
const create = async (options) => {
|
|
2069
2087
|
const args = { name: options?.name ?? 'Untitled' };
|
|
2070
2088
|
if (options?.app_metadata !== undefined)
|
|
@@ -2757,6 +2775,18 @@ function wireDocTransport(args) {
|
|
|
2757
2775
|
clearTimeout(gapTimer);
|
|
2758
2776
|
gapTimer = null;
|
|
2759
2777
|
}
|
|
2778
|
+
// A stream line reaches this only at capacity, and it has no owner to
|
|
2779
|
+
// reopen it: the session reopens the top-level id, but a stream is one
|
|
2780
|
+
// part of a document nothing reloads on its behalf. So it stops the
|
|
2781
|
+
// divergence (above) and marks itself read-only at capacity, which
|
|
2782
|
+
// `stream.readOnly` / `stream.atCapacity` already surface to the app,
|
|
2783
|
+
// rather than alerting the reader and reloading a document it is part
|
|
2784
|
+
// of. The diverged edit stays visible until the app reopens the stream;
|
|
2785
|
+
// it reached no other reader, so nothing is lost by leaving it.
|
|
2786
|
+
if (args.capacityReloadsDocument === false) {
|
|
2787
|
+
args.doc._markReadOnly('capacity');
|
|
2788
|
+
return;
|
|
2789
|
+
}
|
|
2760
2790
|
args.doc._markReadOnly('unsaved');
|
|
2761
2791
|
// The user is told by the SDK, not by each app, because an app that
|
|
2762
2792
|
// renders nothing is exactly the case this has to cover: a document that
|
|
@@ -3656,6 +3686,11 @@ function snapshotKindTooNewError() {
|
|
|
3656
3686
|
return new BrassError('This document needs a newer version of this app. Update to the latest @brass-build/client to open it.', { status: 426 });
|
|
3657
3687
|
}
|
|
3658
3688
|
async function materialise(body, documentOptions, onSnapshotProgress) {
|
|
3689
|
+
// Constructing the document is the first thing in this package that runs the
|
|
3690
|
+
// WASM, and `Brass.init` only starts the fetch, so this is where it is
|
|
3691
|
+
// waited on. Usually it resolved during the auth round-trip and this costs
|
|
3692
|
+
// nothing.
|
|
3693
|
+
await ensureWasmReady();
|
|
3659
3694
|
// Stamp the server-minted doc_id onto the Document (via DocumentOptions, so
|
|
3660
3695
|
// it threads through the LoroDoc constructor without changing the static
|
|
3661
3696
|
// factory signatures) so callers can read `doc.id` to correlate.
|