@brass-build/client 0.1.0 → 0.2.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/AGENTS.md +72 -63
- package/CHANGELOG.md +86 -0
- package/README.md +317 -231
- package/dist/auth-flow.d.ts +10 -1
- package/dist/auth-flow.d.ts.map +1 -1
- package/dist/auth-flow.js +64 -20
- package/dist/auth-flow.js.map +1 -1
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +217 -75
- package/dist/client.js.map +1 -1
- package/dist/document-engine.d.ts +4 -0
- package/dist/document-engine.d.ts.map +1 -0
- package/dist/document-engine.js +9 -0
- package/dist/document-engine.js.map +1 -0
- package/dist/document-streams.d.ts +8 -1
- package/dist/document-streams.d.ts.map +1 -1
- package/dist/document-streams.js +79 -8
- package/dist/document-streams.js.map +1 -1
- package/dist/documents-namespace.d.ts.map +1 -1
- package/dist/documents-namespace.js +19 -3
- package/dist/documents-namespace.js.map +1 -1
- package/dist/documents.d.ts +43 -14
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js +871 -223
- package/dist/documents.js.map +1 -1
- package/dist/embed-protocol.d.ts +3 -0
- package/dist/embed-protocol.d.ts.map +1 -0
- package/dist/embed-protocol.js +26 -0
- package/dist/embed-protocol.js.map +1 -0
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +8 -1
- package/dist/emitter.js.map +1 -1
- package/dist/export-guest.d.ts.map +1 -1
- package/dist/export-guest.js +14 -6
- package/dist/export-guest.js.map +1 -1
- package/dist/fetch-deadline.d.ts +22 -0
- package/dist/fetch-deadline.d.ts.map +1 -0
- package/dist/fetch-deadline.js +96 -0
- package/dist/fetch-deadline.js.map +1 -0
- package/dist/fetch-retry.d.ts +1 -0
- package/dist/fetch-retry.d.ts.map +1 -1
- package/dist/fetch-retry.js +12 -5
- package/dist/fetch-retry.js.map +1 -1
- package/dist/handle-types.d.ts +150 -0
- package/dist/handle-types.d.ts.map +1 -0
- package/dist/handle-types.js +8 -0
- package/dist/handle-types.js.map +1 -0
- package/dist/handles.d.ts +48 -48
- package/dist/handles.d.ts.map +1 -1
- package/dist/handles.js +3122 -501
- package/dist/handles.js.map +1 -1
- package/dist/hosted-runtime.d.ts.map +1 -1
- package/dist/hosted-runtime.js +8 -12
- package/dist/hosted-runtime.js.map +1 -1
- package/dist/hosted-ui.d.ts +0 -1
- package/dist/hosted-ui.d.ts.map +1 -1
- package/dist/hosted-ui.js +29 -24
- package/dist/hosted-ui.js.map +1 -1
- package/dist/importer.d.ts.map +1 -1
- package/dist/importer.js +253 -8
- package/dist/importer.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/join-coverage.d.ts +12 -0
- package/dist/join-coverage.d.ts.map +1 -0
- package/dist/join-coverage.js +37 -0
- package/dist/join-coverage.js.map +1 -0
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js +5 -1
- package/dist/jwt.js.map +1 -1
- package/dist/launch-context.js +2 -2
- package/dist/launch-context.js.map +1 -1
- package/dist/mutate-batching.d.ts +25 -2
- package/dist/mutate-batching.d.ts.map +1 -1
- package/dist/mutate-batching.js +57 -10
- package/dist/mutate-batching.js.map +1 -1
- package/dist/open-document.d.ts +15 -1
- package/dist/open-document.d.ts.map +1 -1
- package/dist/open-document.js +1851 -321
- package/dist/open-document.js.map +1 -1
- package/dist/presence.d.ts +28 -0
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +149 -7
- package/dist/presence.js.map +1 -1
- package/dist/record-paging.d.ts +336 -71
- package/dist/record-paging.d.ts.map +1 -1
- package/dist/record-paging.js +591 -127
- package/dist/record-paging.js.map +1 -1
- package/dist/selection-persistence.d.ts.map +1 -1
- package/dist/selection-persistence.js +11 -1
- package/dist/selection-persistence.js.map +1 -1
- package/dist/serializer.d.ts +30 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/session-persistence.d.ts.map +1 -1
- package/dist/session-persistence.js +9 -8
- package/dist/session-persistence.js.map +1 -1
- package/dist/session-toolbar.d.ts +0 -1
- package/dist/session-toolbar.d.ts.map +1 -1
- package/dist/session-toolbar.js +226 -75
- package/dist/session-toolbar.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +87 -18
- package/dist/session.js.map +1 -1
- package/dist/tail-ops.d.ts +14 -4
- package/dist/tail-ops.d.ts.map +1 -1
- package/dist/tail-ops.js +75 -15
- package/dist/tail-ops.js.map +1 -1
- package/dist/topic-lifecycle.d.ts +4 -0
- package/dist/topic-lifecycle.d.ts.map +1 -1
- package/dist/topic-lifecycle.js +25 -1
- package/dist/topic-lifecycle.js.map +1 -1
- package/dist/types.d.ts +47 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/undo.d.ts +2 -3
- package/dist/undo.d.ts.map +1 -1
- package/dist/undo.js +11 -0
- package/dist/undo.js.map +1 -1
- package/dist/unload-guard.d.ts +5 -0
- package/dist/unload-guard.d.ts.map +1 -0
- package/dist/unload-guard.js +88 -0
- package/dist/unload-guard.js.map +1 -0
- package/dist/version-bar.d.ts +4 -3
- package/dist/version-bar.d.ts.map +1 -1
- package/dist/version-bar.js +140 -19
- package/dist/version-bar.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/dist/vite.d.ts +18 -2
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +133 -8
- package/dist/vite.js.map +1 -1
- package/dist/ws-client.d.ts +23 -3
- package/dist/ws-client.d.ts.map +1 -1
- package/dist/ws-client.js +339 -89
- package/dist/ws-client.js.map +1 -1
- package/dist/ws-frame-limit.d.ts.map +1 -1
- package/dist/ws-frame-limit.js +19 -12
- package/dist/ws-frame-limit.js.map +1 -1
- package/docs/app-manifest.md +7 -8
- package/docs/custom-chrome.md +17 -20
- package/docs/hosted-ui-advanced.md +14 -17
- package/docs/imported-documents.md +53 -197
- package/docs/presence.md +45 -21
- package/docs/schemas.md +12 -17
- package/docs/streams.md +55 -57
- package/package.json +4 -3
- package/src/auth-flow.ts +90 -23
- package/src/client.ts +225 -78
- package/src/document-engine.ts +15 -0
- package/src/document-signals.ts +7 -7
- package/src/document-streams.ts +95 -9
- package/src/documents-namespace.ts +18 -3
- package/src/documents.ts +983 -277
- package/src/embed-protocol.ts +25 -0
- package/src/emitter.ts +8 -1
- package/src/export-guest.ts +15 -9
- package/src/fetch-deadline.ts +119 -0
- package/src/fetch-retry.ts +14 -5
- package/src/handle-types.ts +303 -0
- package/src/handles.ts +3406 -683
- package/src/hosted-runtime.ts +8 -12
- package/src/hosted-ui.ts +28 -32
- package/src/importer.ts +261 -8
- package/src/index.ts +29 -18
- package/src/internal.ts +1 -0
- package/src/join-coverage.ts +42 -0
- package/src/jwt.ts +8 -1
- package/src/launch-context.ts +2 -2
- package/src/mutate-batching.ts +60 -11
- package/src/open-document.ts +2355 -515
- package/src/presence.ts +210 -11
- package/src/record-paging.ts +687 -137
- package/src/selection-persistence.ts +10 -1
- package/src/serializer.ts +33 -1
- package/src/session-persistence.ts +9 -8
- package/src/session-toolbar.ts +249 -80
- package/src/session.ts +91 -17
- package/src/tail-ops.ts +76 -10
- package/src/topic-lifecycle.ts +31 -1
- package/src/types.ts +56 -4
- package/src/undo.ts +13 -5
- package/src/unload-guard.ts +91 -0
- package/src/version-bar.ts +163 -25
- package/src/version.ts +1 -1
- package/src/vite.ts +175 -10
- package/src/ws-client.ts +392 -92
- package/src/ws-frame-limit.ts +19 -12
package/AGENTS.md
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
# Instructions for AI coding agents
|
|
2
2
|
|
|
3
3
|
You are likely an AI coding agent building an app on
|
|
4
|
-
`@brass-build/client`. The [README](./README.md) teaches the API
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
generated app is expected to meet. Apply both.
|
|
4
|
+
`@brass-build/client`. The [README](./README.md) teaches the API. This
|
|
5
|
+
page covers how to verify your work and the UX baseline a generated app
|
|
6
|
+
should meet. Apply both.
|
|
8
7
|
|
|
9
8
|
## Find out where the app's data comes from
|
|
10
9
|
|
|
11
10
|
**The request names a format, a corpus, or an export.** Our IFC models,
|
|
12
11
|
the GPX tracks off my watch, the change orders our subs email us. Ask
|
|
13
12
|
for one real example as your first action, before you design anything.
|
|
14
|
-
|
|
13
|
+
You take your record shape from that file, and an app built ahead of it
|
|
15
14
|
guesses at a shape the real files contradict.
|
|
16
15
|
|
|
17
16
|
**The work has a customary shape in the user's trade.** A punch list, a
|
|
18
17
|
timesheet, an RFI, a site diary: people in that line of work pass these
|
|
19
18
|
around as documents whose fields they all expect, so a shape for it
|
|
20
19
|
exists and the user probably holds a copy. Ask for theirs before you
|
|
21
|
-
design a schema.
|
|
22
|
-
forks
|
|
23
|
-
so each app's documents stop opening in the other, and the split
|
|
24
|
-
stands. Ask the user rather than
|
|
25
|
-
|
|
20
|
+
design a schema. Inventing a schema for a shape that already exists
|
|
21
|
+
forks that shape: the picker routes documents to apps by their declared
|
|
22
|
+
schema, so each app's documents stop opening in the other, and the split
|
|
23
|
+
stands. Ask the user rather than searching for the shape yourself: it
|
|
24
|
+
reaches you as a document they already hold.
|
|
26
25
|
|
|
27
26
|
Ask as well whenever the user brings up another application. What that
|
|
28
27
|
product can hand over decides whether you adopt a shape or integrate,
|
|
29
28
|
and only the user knows.
|
|
30
29
|
|
|
31
|
-
A product you assumed rather than one
|
|
32
|
-
round. Data a product holds reaches you through its API rather than
|
|
33
|
-
a document, so a sprint board, a sales pipeline, or a ticket queue
|
|
34
|
-
guess lives in some tool leaves you no shape to adopt. Build it as
|
|
30
|
+
A product you assumed, rather than one the user named, works the other
|
|
31
|
+
way round. Data a product holds reaches you through its API rather than
|
|
32
|
+
as a document, so a sprint board, a sales pipeline, or a ticket queue
|
|
33
|
+
you guess lives in some tool leaves you no shape to adopt. Build it as
|
|
35
34
|
below until the user names the tool.
|
|
36
35
|
|
|
37
36
|
**The data starts in your app.** A canvas, a poll, a garden planner, a
|
|
@@ -42,10 +41,9 @@ Design the records from the request, declare their schema in
|
|
|
42
41
|
has none behind it, and it reads to the user as though their request
|
|
43
42
|
was incomplete.
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
answer
|
|
47
|
-
|
|
48
|
-
answers.
|
|
44
|
+
Ask either question and keep working on what does not depend on the
|
|
45
|
+
answer: drive the sign-in, fetch the organization's instructions (next
|
|
46
|
+
section), and scaffold the app shell while the user answers.
|
|
49
47
|
|
|
50
48
|
With an example in hand: the user adds it at their Brass dashboard
|
|
51
49
|
(`https://app.brass.build`) and sends you back the document's link,
|
|
@@ -79,18 +77,17 @@ npx @brass-build/cli agents pull --stdout
|
|
|
79
77
|
|
|
80
78
|
It prints the organization's own conventions for apps built on Brass
|
|
81
79
|
(its `AGENTS.md` / `CLAUDE.md`) to stdout. Read them inline and treat
|
|
82
|
-
them as an instruction file for this task
|
|
83
|
-
the generic defaults here. Run
|
|
84
|
-
the org has any:
|
|
85
|
-
proceed with the defaults below
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
`@brass-build/cli` package's `AGENTS.md`.
|
|
80
|
+
them as an instruction file for this task. They take precedence over
|
|
81
|
+
the generic defaults here. Run the command rather than deciding up
|
|
82
|
+
front whether the org has any: an org that set none prints nothing, and
|
|
83
|
+
you proceed with the defaults below.
|
|
84
|
+
|
|
85
|
+
The pull needs a signed-in session, so when `brass agents pull` reports
|
|
86
|
+
no credential, run the sign-in yourself first (`brass login --start`,
|
|
87
|
+
relay the printed URL and code to the human, then `brass login --check`
|
|
88
|
+
until it reports approved). That is the same credential you will use to
|
|
89
|
+
publish (see "Ship the app"), so drive the sign-in now. `brass agents
|
|
90
|
+
pull` is detailed in the `@brass-build/cli` package's `AGENTS.md`.
|
|
94
91
|
|
|
95
92
|
## Have a second agent review your work
|
|
96
93
|
|
|
@@ -98,33 +95,35 @@ Brass documents are persistent and shared: a write that compiles and
|
|
|
98
95
|
looks right on screen can still be subtly wrong in the stored
|
|
99
96
|
document, and once saved it syncs to every collaborator and reopens
|
|
100
97
|
later. You share the blind spot that produced any such bug, so
|
|
101
|
-
reviewing your own work
|
|
102
|
-
loop instead of treating one as optional polish.
|
|
98
|
+
reviewing your own work reconfirms it. Build with a review loop.
|
|
103
99
|
|
|
104
100
|
Once the integration builds, have a **separate** agent (not you)
|
|
105
101
|
adversarially review it and drive it in a real browser against the
|
|
106
102
|
live backend. Hold that reviewer to implementation-independent checks:
|
|
107
103
|
|
|
108
|
-
- It should
|
|
109
|
-
(`doc.map(...).
|
|
110
|
-
|
|
111
|
-
own helpers.
|
|
104
|
+
- It should take the document's own records from a subscriber of its
|
|
105
|
+
own (`doc.map(...).subscribe(...)` / `doc.list(...).subscribe(...)`)
|
|
106
|
+
and validate them against the data spec itself, rather than trusting
|
|
107
|
+
the app's own helpers.
|
|
112
108
|
- It should push the negative, zero, and boundary inputs of every
|
|
113
109
|
operation.
|
|
114
110
|
- It should confirm each edit round-trips and leaves the document
|
|
115
111
|
consistent.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
112
|
+
- It should open the same document as **two** signed-in readers and put
|
|
113
|
+
them in the same field at once: with one reader's caret sitting in a
|
|
114
|
+
field, the other edits it. The first reader's screen has to show that
|
|
115
|
+
value once their caret leaves, and a reader whose own edit goes over a
|
|
116
|
+
peer's has to be told so. Both halves fail silently, and a single
|
|
117
|
+
session never reaches either.
|
|
118
|
+
|
|
119
|
+
Have the reviewer drive any gesture on a touch device as well as a
|
|
120
|
+
desktop mouse. Drags, multi-point taps, and anything else
|
|
121
|
+
pointer-driven commonly work under a mouse and break under touch, and a
|
|
122
|
+
layout that looks right at a narrow width says nothing about whether
|
|
123
|
+
the gesture still works there.
|
|
124
|
+
|
|
125
|
+
Fix what the reviewer finds and iterate until the reviewer's own checks
|
|
126
|
+
pass, before you call the integration done.
|
|
128
127
|
|
|
129
128
|
## Apply these UX defaults
|
|
130
129
|
|
|
@@ -154,11 +153,24 @@ the baseline for when there is no design.
|
|
|
154
153
|
where it bites.
|
|
155
154
|
- **Make touch targets at least 40px**: `padding: 12px 16px` on
|
|
156
155
|
tappable controls.
|
|
156
|
+
- **Draw the `<select>` arrow yourself.** A native `<select>` puts the
|
|
157
|
+
browser's own arrow tight against the control's right edge, at a gap
|
|
158
|
+
that differs per browser, so a select carrying your border and radius
|
|
159
|
+
still reads as a stock control beside your other inputs. Set
|
|
160
|
+
`appearance: none`, draw the chevron as a `background-image` at
|
|
161
|
+
`background-position: right 0.75rem center`, and reserve
|
|
162
|
+
`padding-right: 2.25rem` so a long option cannot run under it.
|
|
157
163
|
- **Disable, don't hide, on read-only documents.** When
|
|
158
|
-
`doc.readOnly` is true
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
164
|
+
`doc.readOnly` is true, render the editor and share controls disabled
|
|
165
|
+
with a `title` explaining why, rather than removing them. It covers
|
|
166
|
+
every reason this reader cannot write: a view-only grant, a view-only
|
|
167
|
+
share link, a historical-version preview, and a document still
|
|
168
|
+
loading. Re-read it in your `doc.subscribe` handler rather than
|
|
169
|
+
reading it once at bind: it also flips when someone withdraws the
|
|
170
|
+
reader's access while the document is open, which is what closes the
|
|
171
|
+
editor at the moment writing stops working. Pair it with
|
|
172
|
+
`Brass.onError`, where the sentence explaining a refused write
|
|
173
|
+
arrives.
|
|
162
174
|
- **Name the next action in empty states.** "No document open. Use
|
|
163
175
|
Open to pick or create one."
|
|
164
176
|
- **Gate edit affordances on an open document.** When
|
|
@@ -168,9 +180,10 @@ the baseline for when there is no design.
|
|
|
168
180
|
user produce work that silently cannot be persisted and is discarded
|
|
169
181
|
when the first document opens.
|
|
170
182
|
- **Render the `error` status.** When `session.status` is `error` (a
|
|
171
|
-
document the user opened could not be opened: deleted,
|
|
172
|
-
|
|
173
|
-
open being deleted out from
|
|
183
|
+
document the user opened could not be opened: deleted, an access the
|
|
184
|
+
platform collapses to a non-disclosing 404, or a file the platform
|
|
185
|
+
could not prepare; or a document that was open being deleted out from
|
|
186
|
+
under the user), render
|
|
174
187
|
`session.error.message` verbatim, surrounded by your own New / Open
|
|
175
188
|
actions, not the plain empty state. Falling through to "No document
|
|
176
189
|
open" reads as if the user asked for nothing and hides the failure.
|
|
@@ -210,13 +223,10 @@ npx @brass-build/cli status
|
|
|
210
223
|
|
|
211
224
|
It inspects the credential and app state for this environment and ends
|
|
212
225
|
in a `Next:` line naming the one command to run. Follow that line, then
|
|
213
|
-
run `brass status` again
|
|
214
|
-
section: rather than reasoning about publishing from prose, you run it
|
|
215
|
-
and do what it says.
|
|
226
|
+
run `brass status` again, for the rest of this section.
|
|
216
227
|
|
|
217
228
|
Two steps need the human's Brass account, and you cannot stand in for
|
|
218
|
-
it.
|
|
219
|
-
stop at:
|
|
229
|
+
it. Drive both to completion rather than noting them and stopping:
|
|
220
230
|
|
|
221
231
|
- **Getting an app id.** `Brass.init` needs the `app_id` of a
|
|
222
232
|
registered app. Run the first `brass publish` (below): it creates the
|
|
@@ -227,11 +237,10 @@ stop at:
|
|
|
227
237
|
on the dashboard and gives you the id.)
|
|
228
238
|
- **A publish credential.** When `brass status` reports no credential,
|
|
229
239
|
drive the sign-in: run `brass login`. In a local session it opens the
|
|
230
|
-
human's browser to approve and completes on approval
|
|
240
|
+
human's browser to approve and completes on approval. On a headless
|
|
231
241
|
box it prints a URL and short code the human approves from any device.
|
|
232
242
|
Running it and getting the human through approval is your step. For CI
|
|
233
|
-
the human supplies `BRASS_SERVICE_TOKEN` instead.
|
|
234
|
-
either, but neither is a wall you stop at.
|
|
243
|
+
the human supplies `BRASS_SERVICE_TOKEN` instead.
|
|
235
244
|
|
|
236
245
|
Once `brass status` reports a credential, publish:
|
|
237
246
|
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,92 @@ and the package follows [semantic versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
6
6
|
While the version is below `1.0.0`, minor releases may introduce
|
|
7
7
|
breaking changes.
|
|
8
8
|
|
|
9
|
+
## 0.2.0
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Large collections page themselves. A map an app fills past 5,000 records
|
|
14
|
+
stores them in compressed pages instead of one container per record, which
|
|
15
|
+
keeps a bulk write and a reload viable at hundreds of thousands of records.
|
|
16
|
+
`get()`, `has()` and `mutate()` read and edit a paged map exactly as they do
|
|
17
|
+
a small one.
|
|
18
|
+
- A map keeps its own bookkeeping beside your records, under keys beginning
|
|
19
|
+
with `brass:`, so a write under one of those keys is refused. Any other key
|
|
20
|
+
is yours.
|
|
21
|
+
- `doc.atCapacity` (and `stream.atCapacity`) reports that the platform has
|
|
22
|
+
refused a write because the document reached its ceiling. A document gets
|
|
23
|
+
there through a band where ordinary editing still lands and a bulk write is
|
|
24
|
+
refused, so this is the signal to stop offering the bulk work (an import, a
|
|
25
|
+
generate pass) while leaving the rest of the app alone. Edits keep applying
|
|
26
|
+
to the local copy while it reads `true`, so an app can show the reader what
|
|
27
|
+
they did alongside the fact that it is not saved. `doc.subscribe` fires when
|
|
28
|
+
it flips, once rather than once per refused change.
|
|
29
|
+
- `onSettled(cb)` on the map, list and ordered-map handles fires when a
|
|
30
|
+
delivery of the whole collection finishes, so the work that follows on the
|
|
31
|
+
collection (framing the camera on what arrived, a first pass over it) has
|
|
32
|
+
somewhere to live other than a single change.
|
|
33
|
+
- `orderedMap.insert(key, value, at)` and `orderedMap.move(key, to)` place and
|
|
34
|
+
reposition an entry against a neighbour, through the new `OrderedMapPosition`
|
|
35
|
+
type.
|
|
36
|
+
- A list draft carries `move(from, to)`. Two people repositioning the same
|
|
37
|
+
entry with it converge on one entry, where a removal paired with an
|
|
38
|
+
insertion keeps both insertions and leaves the entry in the list twice.
|
|
39
|
+
- Presence layers carry a 2,048-byte cap (`PRESENCE_LAYER_MAX_BYTES`). Watch
|
|
40
|
+
`presence.onStatus` to know when Brass is withholding a layer that is over
|
|
41
|
+
it; a `selection` crosses the cap at roughly 130 to 140 typical entity ids,
|
|
42
|
+
so publish a bounded summary when a selection can get large.
|
|
43
|
+
- The browser's own "leave site?" prompt appears while a document holds edits
|
|
44
|
+
the server has not acknowledged, so a reload cannot silently drop them.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- `session.status` reaches `error` for a file Brass could not prepare, on top
|
|
49
|
+
of a deleted or inaccessible document. One error screen still covers them
|
|
50
|
+
all.
|
|
51
|
+
- `doc.readOnly` now also reads `true` for a document that could not be
|
|
52
|
+
loaded, so edit affordances gated on it stay disabled there as well as
|
|
53
|
+
during loading.
|
|
54
|
+
- A store pages at 5,000 records rather than 50,000, where paging starts
|
|
55
|
+
paying for itself: it writes about 3x faster, opens about 5x faster and
|
|
56
|
+
stores about 1.7x smaller. What it costs is merge granularity. Below the
|
|
57
|
+
threshold two people editing different fields of one record both keep their
|
|
58
|
+
edit; above it the record is the merge unit, so one of the two wins.
|
|
59
|
+
- Two tabs of one app are two claimants for an import, so only one of them
|
|
60
|
+
parses the file.
|
|
61
|
+
- A list subscriber receives the splices its change made, applied in the order
|
|
62
|
+
they arrive, so a render costs what the change carried rather than what the
|
|
63
|
+
list holds.
|
|
64
|
+
- `SyntheticSubscribeEvent` names a move through version history `history`
|
|
65
|
+
rather than `checkout`. `ChangeSource` no longer lists it: a version move
|
|
66
|
+
swaps the whole container instead of writing into it, so it reaches a handle
|
|
67
|
+
subscriber as a whole-container fire with no origin, and `doc.subscribe` is
|
|
68
|
+
where that move is reported.
|
|
69
|
+
- A `Document` is reached through `Brass.session`, `Brass.openDocumentById`, or
|
|
70
|
+
`Brass.createDocument`. The class no longer constructs.
|
|
71
|
+
- The capability manifest names the files an app imports under `imports`,
|
|
72
|
+
which is the word the platform and the dashboard use for them.
|
|
73
|
+
|
|
74
|
+
### Removed
|
|
75
|
+
|
|
76
|
+
- `read()` on the map, list and ordered-map handles. A handle feeds an app
|
|
77
|
+
through `subscribe`, which costs what a change carried rather than what the
|
|
78
|
+
document holds, so a collection large enough to page never pays an
|
|
79
|
+
O(document) walk to render. A registered serializer runs detached with no
|
|
80
|
+
subscription behind it, and is handed a `StoredMap` / `StoredList` that
|
|
81
|
+
keeps `read()`.
|
|
82
|
+
- The barrel no longer exports plumbing types that no `Brass`, `Document`, or
|
|
83
|
+
`DocumentSession` member names: `AcquireOrganizationResult`,
|
|
84
|
+
`HostedUiLauncher`, `HostedUiLauncherOptions`, `DocumentSessionDeps`,
|
|
85
|
+
`StreamRuntime`, `CreateDocumentFn`, `DocumentFactory`,
|
|
86
|
+
`DocumentAtVersionResponse`, `DocumentSnapshotResponse`,
|
|
87
|
+
`DocumentDriveSummaryWire`, `OpenDocumentFactoryOptions`,
|
|
88
|
+
`OpenDocumentByIdFn`, and `OpenDocumentWsClient`. What autocomplete offers
|
|
89
|
+
is now what an app can call.
|
|
90
|
+
- `doc.pushToDrive` and `doc.resolveDrive` are internal. Publishing a document
|
|
91
|
+
back to its drive source, and resolving a diverged one, are the hosted
|
|
92
|
+
toolbar's controls. `doc.driveStatus` still reports the sync state, so an
|
|
93
|
+
app can tell the reader they have unpublished edits.
|
|
94
|
+
|
|
9
95
|
## 0.1.0
|
|
10
96
|
|
|
11
97
|
Initial public release. The SDK turns a document into a live,
|