@brass-build/client 0.4.0 → 0.5.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 +142 -41
- package/CHANGELOG.md +93 -4
- package/README.md +666 -179
- package/dist/acting-organization.d.ts.map +1 -1
- package/dist/acting-organization.js +6 -11
- package/dist/acting-organization.js.map +1 -1
- package/dist/api-fetch.d.ts +8 -0
- package/dist/api-fetch.d.ts.map +1 -1
- package/dist/api-fetch.js +35 -8
- package/dist/api-fetch.js.map +1 -1
- package/dist/batched-get.d.ts +11 -0
- package/dist/batched-get.d.ts.map +1 -0
- package/dist/batched-get.js +92 -0
- package/dist/batched-get.js.map +1 -0
- package/dist/call-service.d.ts +4 -0
- package/dist/call-service.d.ts.map +1 -1
- package/dist/call-service.js +66 -3
- package/dist/call-service.js.map +1 -1
- package/dist/client.d.ts +51 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +982 -124
- package/dist/client.js.map +1 -1
- package/dist/document-checkpoints.d.ts +25 -2
- package/dist/document-checkpoints.d.ts.map +1 -1
- package/dist/document-checkpoints.js +258 -61
- package/dist/document-checkpoints.js.map +1 -1
- package/dist/document-commands.d.ts.map +1 -1
- package/dist/document-commands.js +5 -3
- package/dist/document-commands.js.map +1 -1
- package/dist/document-contents.d.ts +10 -0
- package/dist/document-contents.d.ts.map +1 -1
- package/dist/document-contents.js +23 -1
- package/dist/document-contents.js.map +1 -1
- package/dist/document-set-subscription.d.ts +56 -0
- package/dist/document-set-subscription.d.ts.map +1 -0
- package/dist/document-set-subscription.js +240 -0
- package/dist/document-set-subscription.js.map +1 -0
- package/dist/document-signals.d.ts +6 -0
- package/dist/document-signals.d.ts.map +1 -1
- package/dist/document-signals.js +31 -1
- package/dist/document-signals.js.map +1 -1
- package/dist/document-streams.d.ts +36 -2
- package/dist/document-streams.d.ts.map +1 -1
- package/dist/document-streams.js +69 -18
- package/dist/document-streams.js.map +1 -1
- package/dist/document-thumbnail-capture.d.ts +12 -2
- package/dist/document-thumbnail-capture.d.ts.map +1 -1
- package/dist/document-thumbnail-capture.js +103 -27
- package/dist/document-thumbnail-capture.js.map +1 -1
- package/dist/documents-namespace.d.ts +92 -10
- package/dist/documents-namespace.d.ts.map +1 -1
- package/dist/documents-namespace.js +285 -39
- package/dist/documents-namespace.js.map +1 -1
- package/dist/documents.d.ts +173 -8
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js +1778 -310
- package/dist/documents.js.map +1 -1
- package/dist/errors.d.ts +3 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/fetch-retry.d.ts +1 -0
- package/dist/fetch-retry.d.ts.map +1 -1
- package/dist/fetch-retry.js +2 -0
- package/dist/fetch-retry.js.map +1 -1
- package/dist/file-choice.d.ts +2 -0
- package/dist/file-choice.d.ts.map +1 -0
- package/dist/file-choice.js +27 -0
- package/dist/file-choice.js.map +1 -0
- package/dist/guest-link.d.ts +18 -1
- package/dist/guest-link.d.ts.map +1 -1
- package/dist/guest-link.js +329 -1
- package/dist/guest-link.js.map +1 -1
- package/dist/handle-types.d.ts +67 -5
- package/dist/handle-types.d.ts.map +1 -1
- package/dist/handles.d.ts +15 -19
- package/dist/handles.d.ts.map +1 -1
- package/dist/handles.js +231 -76
- package/dist/handles.js.map +1 -1
- package/dist/hosted-ui.d.ts +61 -0
- package/dist/hosted-ui.d.ts.map +1 -1
- package/dist/hosted-ui.js +94 -42
- package/dist/hosted-ui.js.map +1 -1
- package/dist/import-contract.d.ts +74 -0
- package/dist/import-contract.d.ts.map +1 -0
- package/dist/import-contract.js +163 -0
- package/dist/import-contract.js.map +1 -0
- package/dist/import-guest.d.ts +9 -0
- package/dist/import-guest.d.ts.map +1 -0
- package/dist/import-guest.js +155 -0
- package/dist/import-guest.js.map +1 -0
- package/dist/import-report.d.ts +17 -0
- package/dist/import-report.d.ts.map +1 -0
- package/dist/import-report.js +7 -0
- package/dist/import-report.js.map +1 -0
- package/dist/importer-wait.d.ts +2 -0
- package/dist/importer-wait.d.ts.map +1 -0
- package/dist/importer-wait.js +5 -0
- package/dist/importer-wait.js.map +1 -0
- package/dist/importer.d.ts +18 -4
- package/dist/importer.d.ts.map +1 -1
- package/dist/importer.js +322 -105
- package/dist/importer.js.map +1 -1
- package/dist/in-development.d.ts +2 -0
- package/dist/in-development.d.ts.map +1 -0
- package/dist/in-development.js +10 -0
- package/dist/in-development.js.map +1 -0
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -8
- package/dist/index.js.map +1 -1
- package/dist/init-keys.d.ts +1 -1
- package/dist/init-keys.d.ts.map +1 -1
- package/dist/init-keys.js +6 -1
- package/dist/init-keys.js.map +1 -1
- package/dist/input-documents.d.ts +67 -0
- package/dist/input-documents.d.ts.map +1 -0
- package/dist/input-documents.js +693 -0
- package/dist/input-documents.js.map +1 -0
- package/dist/inputs-status.d.ts +80 -0
- package/dist/inputs-status.d.ts.map +1 -0
- package/dist/inputs-status.js +460 -0
- package/dist/inputs-status.js.map +1 -0
- package/dist/inputs.d.ts +2 -0
- package/dist/inputs.d.ts.map +1 -0
- package/dist/inputs.js +793 -0
- package/dist/inputs.js.map +1 -0
- package/dist/internal.d.ts +6 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +4 -1
- package/dist/internal.js.map +1 -1
- package/dist/join-content.d.ts +33 -0
- package/dist/join-content.d.ts.map +1 -0
- package/dist/join-content.js +114 -0
- package/dist/join-content.js.map +1 -0
- package/dist/join-stamp.d.ts +3 -0
- package/dist/join-stamp.d.ts.map +1 -0
- package/dist/join-stamp.js +12 -0
- package/dist/join-stamp.js.map +1 -0
- package/dist/manifest-drift.d.ts +9 -0
- package/dist/manifest-drift.d.ts.map +1 -0
- package/dist/manifest-drift.js +46 -0
- package/dist/manifest-drift.js.map +1 -0
- package/dist/open-document.d.ts +109 -2
- package/dist/open-document.d.ts.map +1 -1
- package/dist/open-document.js +1822 -811
- package/dist/open-document.js.map +1 -1
- package/dist/page-restore.d.ts +12 -0
- package/dist/page-restore.d.ts.map +1 -0
- package/dist/page-restore.js +23 -0
- package/dist/page-restore.js.map +1 -0
- package/dist/placement.d.ts +13 -0
- package/dist/placement.d.ts.map +1 -0
- package/dist/placement.js +34 -0
- package/dist/placement.js.map +1 -0
- package/dist/presence.d.ts +1 -0
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +16 -4
- package/dist/presence.js.map +1 -1
- package/dist/read-only-document.d.ts +87 -0
- package/dist/read-only-document.d.ts.map +1 -0
- package/dist/read-only-document.js +4 -0
- package/dist/read-only-document.js.map +1 -0
- package/dist/record-paging.d.ts +63 -6
- package/dist/record-paging.d.ts.map +1 -1
- package/dist/record-paging.js +122 -29
- package/dist/record-paging.js.map +1 -1
- package/dist/references.d.ts +40 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +135 -0
- package/dist/references.js.map +1 -0
- package/dist/request-lane.d.ts +5 -0
- package/dist/request-lane.d.ts.map +1 -0
- package/dist/request-lane.js +48 -0
- package/dist/request-lane.js.map +1 -0
- package/dist/sealed-arrow.d.ts +170 -0
- package/dist/sealed-arrow.d.ts.map +1 -0
- package/dist/sealed-arrow.js +769 -0
- package/dist/sealed-arrow.js.map +1 -0
- package/dist/sealed-cache.d.ts +21 -0
- package/dist/sealed-cache.d.ts.map +1 -0
- package/dist/sealed-cache.js +247 -0
- package/dist/sealed-cache.js.map +1 -0
- package/dist/sealed-encode.d.ts +87 -0
- package/dist/sealed-encode.d.ts.map +1 -0
- package/dist/sealed-encode.js +876 -0
- package/dist/sealed-encode.js.map +1 -0
- package/dist/sealed-handles.d.ts +45 -0
- package/dist/sealed-handles.d.ts.map +1 -0
- package/dist/sealed-handles.js +408 -0
- package/dist/sealed-handles.js.map +1 -0
- package/dist/sealed-store.d.ts +242 -0
- package/dist/sealed-store.d.ts.map +1 -0
- package/dist/sealed-store.js +1155 -0
- package/dist/sealed-store.js.map +1 -0
- package/dist/serializer.d.ts +6 -15
- package/dist/serializer.d.ts.map +1 -1
- package/dist/session-toolbar.d.ts +20 -5
- package/dist/session-toolbar.d.ts.map +1 -1
- package/dist/session-toolbar.js +419 -67
- package/dist/session-toolbar.js.map +1 -1
- package/dist/session.d.ts +38 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +562 -79
- package/dist/session.js.map +1 -1
- package/dist/sha256.d.ts +3 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +74 -0
- package/dist/sha256.js.map +1 -0
- package/dist/stable-handles.d.ts +19 -0
- package/dist/stable-handles.d.ts.map +1 -0
- package/dist/stable-handles.js +193 -0
- package/dist/stable-handles.js.map +1 -0
- package/dist/staged-seal.d.ts +2 -0
- package/dist/staged-seal.d.ts.map +1 -0
- package/dist/staged-seal.js +76 -0
- package/dist/staged-seal.js.map +1 -0
- package/dist/subscriber-delivery.d.ts +8 -0
- package/dist/subscriber-delivery.d.ts.map +1 -0
- package/dist/subscriber-delivery.js +31 -0
- package/dist/subscriber-delivery.js.map +1 -0
- package/dist/tail-op-import.d.ts +10 -0
- package/dist/tail-op-import.d.ts.map +1 -0
- package/dist/tail-op-import.js +33 -0
- package/dist/tail-op-import.js.map +1 -0
- package/dist/topic-lifecycle.d.ts +6 -0
- package/dist/topic-lifecycle.d.ts.map +1 -1
- package/dist/topic-lifecycle.js +32 -2
- package/dist/topic-lifecycle.js.map +1 -1
- package/dist/trial-replace-dialog.d.ts +10 -0
- package/dist/trial-replace-dialog.d.ts.map +1 -0
- package/dist/trial-replace-dialog.js +153 -0
- package/dist/trial-replace-dialog.js.map +1 -0
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/undo.d.ts +60 -5
- package/dist/undo.d.ts.map +1 -1
- package/dist/undo.js +344 -75
- package/dist/undo.js.map +1 -1
- package/dist/version-bar.d.ts +1 -0
- package/dist/version-bar.d.ts.map +1 -1
- package/dist/version-bar.js +2 -1
- package/dist/version-bar.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/dist/ws-client.d.ts +21 -0
- package/dist/ws-client.d.ts.map +1 -1
- package/dist/ws-client.js +192 -8
- package/dist/ws-client.js.map +1 -1
- package/dist/ws-frame-limit.d.ts +1 -0
- package/dist/ws-frame-limit.d.ts.map +1 -1
- package/dist/ws-frame-limit.js.map +1 -1
- package/docs/app-manifest.md +121 -17
- package/docs/custom-chrome.md +24 -16
- package/docs/hosted-ui-advanced.md +38 -6
- package/docs/imported-documents.md +104 -51
- package/docs/presence.md +16 -4
- package/docs/schemas.md +8 -5
- package/docs/services.md +6 -6
- package/docs/streams.md +139 -150
- package/docs/text-fields.md +26 -19
- package/package.json +5 -2
- package/src/acting-organization.ts +6 -12
- package/src/api-fetch.ts +53 -3
- package/src/auth-flow.ts +1 -1
- package/src/batched-get.ts +117 -0
- package/src/call-service.ts +78 -3
- package/src/client.ts +1092 -121
- package/src/document-checkpoints.ts +307 -65
- package/src/document-commands.ts +5 -5
- package/src/document-contents.ts +27 -1
- package/src/document-set-subscription.ts +274 -0
- package/src/document-signals.ts +47 -5
- package/src/document-streams.ts +85 -16
- package/src/document-thumbnail-capture.ts +118 -32
- package/src/documents-namespace.ts +539 -84
- package/src/documents.ts +2017 -348
- package/src/errors.ts +17 -6
- package/src/fetch-retry.ts +5 -0
- package/src/file-choice.ts +26 -0
- package/src/guest-link.ts +362 -1
- package/src/handle-types.ts +73 -47
- package/src/handles.ts +253 -83
- package/src/hosted-ui.ts +211 -50
- package/src/import-contract.ts +227 -0
- package/src/import-guest.ts +193 -0
- package/src/import-report.ts +24 -0
- package/src/importer-wait.ts +4 -0
- package/src/importer.ts +386 -131
- package/src/in-development.ts +10 -0
- package/src/index.ts +76 -16
- package/src/init-keys.ts +6 -1
- package/src/input-documents.ts +819 -0
- package/src/inputs-status.ts +598 -0
- package/src/inputs.ts +1090 -0
- package/src/internal.ts +7 -0
- package/src/join-content.ts +135 -0
- package/src/join-stamp.ts +12 -0
- package/src/manifest-drift.ts +54 -0
- package/src/open-document.ts +2346 -930
- package/src/page-restore.ts +38 -0
- package/src/placement.ts +54 -0
- package/src/presence.ts +21 -5
- package/src/read-only-document.ts +133 -0
- package/src/record-paging.ts +147 -25
- package/src/references.ts +207 -0
- package/src/request-lane.ts +59 -0
- package/src/sealed-arrow.ts +843 -0
- package/src/sealed-cache.ts +267 -0
- package/src/sealed-encode.ts +1015 -0
- package/src/sealed-handles.ts +486 -0
- package/src/sealed-store.ts +1330 -0
- package/src/serializer.ts +8 -20
- package/src/session-toolbar.ts +463 -72
- package/src/session.ts +740 -99
- package/src/sha256.ts +65 -0
- package/src/stable-handles.ts +235 -0
- package/src/staged-seal.ts +90 -0
- package/src/subscriber-delivery.ts +37 -0
- package/src/tail-op-import.ts +30 -0
- package/src/topic-lifecycle.ts +38 -2
- package/src/trial-replace-dialog.ts +163 -0
- package/src/types.ts +6 -6
- package/src/undo.ts +386 -73
- package/src/version-bar.ts +5 -1
- package/src/version.ts +1 -1
- package/src/ws-client.ts +208 -16
- package/src/ws-frame-limit.ts +1 -0
package/AGENTS.md
CHANGED
|
@@ -16,19 +16,19 @@ guesses at a shape the real files contradict.
|
|
|
16
16
|
**The work has a customary shape in the user's trade.** A punch list, a
|
|
17
17
|
timesheet, an RFI, a site diary: people in that line of work pass these
|
|
18
18
|
around as documents whose fields they all expect, so a shape for it
|
|
19
|
-
exists and the user probably
|
|
19
|
+
exists and the user probably has a copy. Ask for theirs before you
|
|
20
20
|
design a schema. Inventing a schema for a shape that already exists
|
|
21
21
|
forks that shape: the picker routes documents to apps by their declared
|
|
22
22
|
schema, so each app's documents stop opening in the other, and the split
|
|
23
23
|
stands. Ask the user rather than searching for the shape yourself: it
|
|
24
|
-
reaches you as a document they already
|
|
24
|
+
reaches you as a document they already have.
|
|
25
25
|
|
|
26
26
|
Ask as well whenever the user brings up another application. What that
|
|
27
27
|
product can hand over decides whether you adopt a shape or integrate,
|
|
28
28
|
and only the user knows.
|
|
29
29
|
|
|
30
30
|
A product you assumed, rather than one the user named, works the other
|
|
31
|
-
way round. Data a product
|
|
31
|
+
way round. Data a product stores reaches you through its API rather than
|
|
32
32
|
as a document, so a sprint board, a sales pipeline, or a ticket queue
|
|
33
33
|
you guess lives in some tool leaves you no shape to adopt. Build it as
|
|
34
34
|
below until the user names the tool.
|
|
@@ -47,18 +47,40 @@ section), and scaffold the app shell while the user answers.
|
|
|
47
47
|
|
|
48
48
|
With an example in hand: the user adds it at their Brass dashboard
|
|
49
49
|
(`https://app.brass.build`) and sends you back the document's link,
|
|
50
|
-
and you read what that document
|
|
50
|
+
and you read what that document contains. A resolved schema is your
|
|
51
51
|
record contract: pull it and adopt it verbatim
|
|
52
52
|
(`npx @brass-build/cli schema pull --doc <docId>`). Read the records too,
|
|
53
53
|
before you write code against them
|
|
54
|
-
(`npx @brass-build/cli contents --doc <docId>` writes the
|
|
55
|
-
|
|
54
|
+
(`npx @brass-build/cli contents --doc <docId>` writes the document's
|
|
55
|
+
`default` stream as JSON, and `--stream <name>` writes another stream): the
|
|
56
|
+
schema names the fields and the data tells you what is in them.
|
|
57
|
+
When your app reads that document through `Brass.chooseInputs` rather than
|
|
58
|
+
opening it, pull with `--out input-schema.json` instead and copy that
|
|
59
|
+
file's `schema` into an `inputs` entry. A plain pull writes over your
|
|
60
|
+
manifest's `schema`, and Brass would then offer your app to open that
|
|
61
|
+
document's family.
|
|
56
62
|
Read all of it rather than the first few records, since a file's records are
|
|
57
|
-
grouped by type and its opening records carry a couple of
|
|
58
|
-
and none of the rest.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
grouped by type and its opening records carry a couple of its types
|
|
64
|
+
and none of the rest.
|
|
65
|
+
When your app reads many documents through `Brass.chooseInputs`, ask the
|
|
66
|
+
user for the project or folder it will read rather than one file, and
|
|
67
|
+
sample that set with `npx @brass-build/cli contents --from project:<projectId>`.
|
|
68
|
+
Run it first with `--max-documents 0`, which lists the set without reading
|
|
69
|
+
it, to see the families the set's files belong to (the `family` on each
|
|
70
|
+
document it lists), then pass `--family` the families your `chooseInputs`
|
|
71
|
+
call names. The command lists the
|
|
72
|
+
documents that call returns, reads several of them whole, and counts every
|
|
73
|
+
record type their streams contain, with a few records of each type drawn from
|
|
74
|
+
different documents. Sample the set because one file shows only the types
|
|
75
|
+
it carries, and other files in the set can carry more. Reading a file
|
|
76
|
+
starts its import, as opening it does, so keep some files of the set out
|
|
77
|
+
of the sample for the first-run check below.
|
|
78
|
+
If a stored file has no schema, your app is its first importer. Register a
|
|
79
|
+
function with `Brass.registerImporter` that takes the file and returns its
|
|
80
|
+
records as JSON, and declare the schema of those records in
|
|
81
|
+
`brass-app.json` so the next app can adopt it. Call `registerImporter` at
|
|
82
|
+
startup, unconditionally, not after sign-in or after a document opens:
|
|
83
|
+
Brass may load your app only to run its importer.
|
|
62
84
|
In your app, the file opens the way every document opens: through the
|
|
63
85
|
session and the hosted picker (the picker also brings a file into
|
|
64
86
|
Brass).
|
|
@@ -89,11 +111,22 @@ front whether the org has any: an org that set none prints nothing, and
|
|
|
89
111
|
you proceed with the defaults below.
|
|
90
112
|
|
|
91
113
|
The pull needs a signed-in session, so when `brass agents pull` reports
|
|
92
|
-
no credential, run the sign-in yourself first
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
114
|
+
no credential, run the sign-in yourself first: run `brass login --start`
|
|
115
|
+
and copy the URL and code it prints into the visible text of your reply.
|
|
116
|
+
Most interfaces collapse command output, so the human never sees a code
|
|
117
|
+
that stays there. Then keep running `brass login --check --wait` in the
|
|
118
|
+
same turn until it reports approved: only a check stores the session,
|
|
119
|
+
and if the human approves while no check is running, the approval waits
|
|
120
|
+
for your next check. If the human sees your reply only when your turn
|
|
121
|
+
ends (you run as a subagent, or in a harness that shows only the final
|
|
122
|
+
message), end the turn with the URL and code instead, and run the check
|
|
123
|
+
as soon as you resume. That is the same credential you will use to
|
|
124
|
+
publish (see "Ship the app").
|
|
125
|
+
|
|
126
|
+
When the pull lists several organizations instead of pulling, ask the
|
|
127
|
+
human which one the app is for, and pass that id as `--org` to the pull
|
|
128
|
+
and to your first `brass publish`. `brass agents pull` is detailed in
|
|
129
|
+
the `@brass-build/cli` package's `AGENTS.md`.
|
|
97
130
|
|
|
98
131
|
## Have a second agent review your work
|
|
99
132
|
|
|
@@ -105,23 +138,62 @@ reviewing your own work reconfirms it. Build with a review loop.
|
|
|
105
138
|
|
|
106
139
|
Once the integration builds, have a **separate** agent (not you)
|
|
107
140
|
adversarially review it and drive it in a real browser against the
|
|
108
|
-
live backend.
|
|
141
|
+
live backend. Give that reviewer implementation-independent checks:
|
|
109
142
|
|
|
110
|
-
- It should
|
|
111
|
-
|
|
112
|
-
and validate them against the data spec
|
|
113
|
-
the app's own helpers.
|
|
143
|
+
- It should read the document's records itself (walk
|
|
144
|
+
`doc.map(...).entries()` / `doc.list(...).values()`, or subscribe to
|
|
145
|
+
follow edits) and validate them against the data spec, rather than
|
|
146
|
+
trusting the app's own helpers.
|
|
114
147
|
- It should push the negative, zero, and boundary inputs of every
|
|
115
148
|
operation.
|
|
116
149
|
- It should confirm each edit round-trips and leaves the document
|
|
117
150
|
consistent.
|
|
118
|
-
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
151
|
+
- If the app reads across many documents, it should run the app over a
|
|
152
|
+
set that includes files nobody has opened yet (the ones you kept out of
|
|
153
|
+
your `contents --from` sample, or files added just before the run),
|
|
154
|
+
because a file's import can still be running when the app opens it. It should confirm the app shows
|
|
155
|
+
a loading state while such an open waits, and renders the records once
|
|
156
|
+
it resolves. It should include a file only another app imports, and
|
|
157
|
+
confirm the app shows that file as not imported yet when its open
|
|
158
|
+
rejects with `not_imported`. Once the other app has imported the file,
|
|
159
|
+
Brass calls the key's handler for it again, and the app should then
|
|
160
|
+
read it.
|
|
161
|
+
- If the app offers use without an account, it should make a document
|
|
162
|
+
signed out, then sign in through the app's own sign-in on that page and
|
|
163
|
+
confirm the document is still there. Signing in any other way, such as
|
|
164
|
+
through `brass browser-session`, leaves the document behind.
|
|
165
|
+
- It should open the same document as **two** signed-in users and put
|
|
166
|
+
them in the same field at once: with one user's caret sitting in a
|
|
167
|
+
field, the other edits it. The first user's screen has to show that
|
|
168
|
+
value once their caret leaves, and a user whose own edit goes over a
|
|
122
169
|
peer's has to be told so. Both halves fail silently, and a single
|
|
123
170
|
session never reaches either.
|
|
124
171
|
|
|
172
|
+
Both you and the reviewer need a signed-in browser.
|
|
173
|
+
`brass browser-session` prints a URL that opens your app already signed
|
|
174
|
+
in as you:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
npx @brass-build/cli browser-session --return-to http://localhost:5173/
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Point `--return-to` at your dev server while you build, and at the
|
|
181
|
+
published URL once you have one. Run the command once per browser
|
|
182
|
+
context, at the moment that context is ready to navigate. Each URL signs
|
|
183
|
+
in one browser once and expires two minutes after it is printed. Give
|
|
184
|
+
each of the two users a URL. Both sign in to the human's account, so ask
|
|
185
|
+
the human for a second account when a check needs two different people.
|
|
186
|
+
|
|
187
|
+
Open the document by its id, through `Brass.openDocumentById` or the
|
|
188
|
+
`?doc=` parameter the session restores on boot. Use a document your app
|
|
189
|
+
created, or one a user previously opened in your app from Brass. Brass refuses
|
|
190
|
+
access to documents the user has not granted to your app, returning a 403 status.
|
|
191
|
+
Brass's own dialogs, such as the picker, open in that browser too once the human
|
|
192
|
+
has signed in to the Brass dashboard before. Otherwise a dialog asks for a
|
|
193
|
+
sign-in that the human has to complete. The `@brass-build/cli` package's
|
|
194
|
+
`AGENTS.md` covers the rest, including how to install and drive a headless
|
|
195
|
+
browser.
|
|
196
|
+
|
|
125
197
|
Have the reviewer drive any gesture on a touch device as well as a
|
|
126
198
|
desktop mouse. Drags, multi-point taps, and anything else
|
|
127
199
|
pointer-driven commonly work under a mouse and break under touch, and a
|
|
@@ -141,13 +213,23 @@ the baseline for when there is no design.
|
|
|
141
213
|
viewport; do not center the app in a `max-width: 720px` column.
|
|
142
214
|
- **Render two distinct shells, signed-out and signed-in.** A
|
|
143
215
|
signed-in shell with disabled buttons next to a sign-in CTA reads as
|
|
144
|
-
broken. Mount the
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
216
|
+
broken. Mount the working shell when `Brass.authStatus` is
|
|
217
|
+
`'signed-in'` or `'guest'` (a visitor working without an account has no
|
|
218
|
+
user), the signed-out shell only on `'signed-out'`, and **neither**
|
|
219
|
+
during the `'unknown'` window before `init` settles (see "Rendering auth
|
|
220
|
+
state" in the README).
|
|
221
|
+
- **Let a visitor try the app without an account.** Give the signed-out
|
|
222
|
+
shell New and Upload buttons beside Sign in, declare
|
|
223
|
+
`"access": { "create": "anyone" }`, and publish with
|
|
224
|
+
`--gate off --visibility public` (see "Try before signing in" in the
|
|
225
|
+
README). Declare `"create": "signed-in"` instead only when the app's
|
|
226
|
+
content comes from files people pick with `Brass.chooseInputs`, or
|
|
227
|
+
when every action calls a service. When one feature calls a service,
|
|
228
|
+
disable that feature for a visitor and offer the rest.
|
|
148
229
|
- **Put auth chrome in the header of the signed-in shell only**: the
|
|
149
|
-
user's email or sub, plus sign out. The sign-in CTA
|
|
150
|
-
|
|
230
|
+
user's email or sub, plus sign out. The sign-in CTA, and any way in
|
|
231
|
+
without an account (see "Try before signing in" in the README), belong
|
|
232
|
+
in the body of the signed-out shell, not in a pre-rendered header.
|
|
151
233
|
- **Include the viewport meta tag**:
|
|
152
234
|
`<meta name="viewport" content="width=device-width, initial-scale=1">`.
|
|
153
235
|
- **If you toggle shells with `el.hidden`, add
|
|
@@ -169,14 +251,23 @@ the baseline for when there is no design.
|
|
|
169
251
|
- **Disable, don't hide, on read-only documents.** When
|
|
170
252
|
`doc.readOnly` is true, render the editor and share controls disabled
|
|
171
253
|
with a `title` explaining why, rather than removing them. It covers
|
|
172
|
-
every reason this
|
|
173
|
-
share link, a historical-version preview,
|
|
174
|
-
|
|
254
|
+
every reason this user cannot write: a view-only grant, a view-only
|
|
255
|
+
share link, a historical-version preview, a document still loading
|
|
256
|
+
or being prepared for editing, a file too large to edit
|
|
257
|
+
(`doc.atCapacity`), and a copy your app opened with `readOnly` or
|
|
258
|
+
`frozen`. Re-read it in your `doc.subscribe` handler rather than
|
|
175
259
|
reading it once at bind: it also flips when someone withdraws the
|
|
176
|
-
|
|
260
|
+
user's access while the document is open, which is what closes the
|
|
177
261
|
editor at the moment writing stops working. Pair it with
|
|
178
262
|
`Brass.onError`, where the sentence explaining a refused write
|
|
179
263
|
arrives.
|
|
264
|
+
- **Make each user action one Undo step.** Call
|
|
265
|
+
`void doc.createCheckpoint()` at the end of every action that edits
|
|
266
|
+
the document: on `pointerup` after a drag, after a command runs, after
|
|
267
|
+
a field commits. In a text editor, call it in `beforeinput`
|
|
268
|
+
whenever the coming edit starts a new step (see "Undo, checkpoints,
|
|
269
|
+
and version history" in the README), and leave the automatic interval
|
|
270
|
+
as it is.
|
|
180
271
|
- **Name the next action in empty states.** "No document open. Use
|
|
181
272
|
Open to pick or create one."
|
|
182
273
|
- **Gate edit affordances on an open document.** When
|
|
@@ -204,7 +295,7 @@ the baseline for when there is no design.
|
|
|
204
295
|
resting button-like affordance so it reads as clickable rather than
|
|
205
296
|
as a heading.
|
|
206
297
|
- **Wire presence by default, and wire both halves.** When
|
|
207
|
-
`doc.presence` is non-null (any open
|
|
298
|
+
`doc.presence` is non-null (any live open), publish your own
|
|
208
299
|
pointer / camera / selection state on every move AND render other
|
|
209
300
|
participants' state in the working surface, not just an initials
|
|
210
301
|
list in the header (the README's "Presence" section explains why
|
|
@@ -248,11 +339,13 @@ them. Drive each to completion rather than noting it and stopping:
|
|
|
248
339
|
drive the sign-in: run `brass login`. In a local session it opens the
|
|
249
340
|
human's browser to approve and completes on approval. On a headless
|
|
250
341
|
box it prints a URL and short code the human approves from any device.
|
|
342
|
+
Copy both into the visible text of your reply, since most interfaces
|
|
343
|
+
collapse command output.
|
|
251
344
|
Running it and getting the human through approval is your step. For CI
|
|
252
345
|
the human supplies `BRASS_SERVICE_TOKEN` instead.
|
|
253
346
|
- **A key for every service you declared.** An app that declares
|
|
254
347
|
`services` in `brass-app.json` calls those hosts through Brass, which
|
|
255
|
-
|
|
348
|
+
stores the credential, and the credential comes from the provider's own
|
|
256
349
|
console. `brass publish` names each host still waiting and the page
|
|
257
350
|
that takes its key, in the log and in `warnings` under `--json`. Give
|
|
258
351
|
the human that line as it stands: it carries the host and a link
|
|
@@ -264,17 +357,25 @@ Once `brass status` reports a credential, publish:
|
|
|
264
357
|
|
|
265
358
|
```sh
|
|
266
359
|
npm run build
|
|
267
|
-
npx @brass-build/cli publish ./dist
|
|
360
|
+
npx @brass-build/cli publish ./dist --name "My app"
|
|
268
361
|
```
|
|
269
362
|
|
|
270
|
-
This deploys to `https://<slug>.onbrass.app`.
|
|
363
|
+
This deploys to `https://<slug>.onbrass.app`. If the app lets a visitor
|
|
364
|
+
work without an account, declare `"access": { "create": "anyone" }` in
|
|
365
|
+
`brass-app.json` and add `--gate off --visibility public`. Without
|
|
366
|
+
`--gate off`, Brass asks every visitor to sign in before the app loads.
|
|
367
|
+
Without `--visibility public`, a visitor with no account cannot create a
|
|
368
|
+
document, and `Brass.session.error` carries the
|
|
369
|
+
reason.
|
|
370
|
+
Report the integration
|
|
271
371
|
against this end state, and close out every item before you call it
|
|
272
372
|
done:
|
|
273
373
|
|
|
274
374
|
- **built**: `npm run build` is clean.
|
|
275
|
-
- **signed in**: `brass status` confirms a credential.
|
|
375
|
+
- **signed in**: `brass status` confirms a publish credential.
|
|
276
376
|
- **published**: `brass publish` reported a URL.
|
|
277
|
-
- **opened**: you loaded that URL
|
|
377
|
+
- **opened**: you loaded that URL in a browser you drive, signed in
|
|
378
|
+
through `brass browser-session`, and used the app there.
|
|
278
379
|
- **keyed**: `brass publish` named no host as still waiting for a key. A
|
|
279
380
|
host it named is an open item like any other, so offer the link and
|
|
280
381
|
wait rather than reporting the integration done around it.
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,95 @@ 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.5.0
|
|
10
|
+
|
|
11
|
+
### Breaking
|
|
12
|
+
|
|
13
|
+
- `registerImporter` takes `(file) => { streams, report? }` in place of
|
|
14
|
+
`(source, doc) => void`. Return your records instead of writing them to a
|
|
15
|
+
document.
|
|
16
|
+
- 0.5.0 removes `DocumentSourceStream` and `DocumentSourceBlob.streams`.
|
|
17
|
+
- `doc.createCheckpoint()` resolves to `void`, and 0.5.0 removes
|
|
18
|
+
`DocumentCheckpoint`. Remove code that reads the result.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Support for dashboards and other derived content
|
|
23
|
+
- `Brass.chooseInputs(families)` asks a user to select files, folders, or
|
|
24
|
+
projects. `Brass.chooseInput(families)` asks the user to pick a single
|
|
25
|
+
file.
|
|
26
|
+
- `doc.dependsOn(key, refs)` saves picked references in your document.
|
|
27
|
+
- `doc.subscribeInputDocuments(key, handlers)` calls your handlers as the
|
|
28
|
+
referenced files load, change or leave. See "Referencing other
|
|
29
|
+
documents" in the README.
|
|
30
|
+
- `Brass.documents.get(id)` returns a document's `family`, and
|
|
31
|
+
`member_of.chain` lists the folders and archives containing it.
|
|
32
|
+
- `inputs` in `brass-app.json` lists the schemas your app reads. The picker
|
|
33
|
+
offers files that match one of them.
|
|
34
|
+
- Faster read-only opening
|
|
35
|
+
- `readOnly: true` on `Brass.openDocumentById` or `session.open` opens a
|
|
36
|
+
`ReadOnlyDocument`, for apps that only display documents. Large documents
|
|
37
|
+
load significantly faster, and unchanged ones reopen without downloading
|
|
38
|
+
again.
|
|
39
|
+
- `Brass.init(appId, { open: { readOnly: true } })` opens every session
|
|
40
|
+
document read-only. Documents the session creates still open editable.
|
|
41
|
+
- `frozen: true` opens a copy that ignores later edits, for reading many
|
|
42
|
+
documents at once. `doc.onChanged(cb)` reports a change, and
|
|
43
|
+
`doc.reload()` updates the same copy to the latest version.
|
|
44
|
+
- `doc.reopen()` switches an open document between editable, `readOnly` and
|
|
45
|
+
`frozen`, so a user can view first and edit later.
|
|
46
|
+
- Optional trial use for signed-out users
|
|
47
|
+
- Signed-out users can create and open temporary documents, to try your app
|
|
48
|
+
before signing up. `doc.expiresAt` gives the expiry. Signing in from that
|
|
49
|
+
page keeps the document. See "Try before signing in" in the README.
|
|
50
|
+
- `access` in `brass-app.json` sets who can use your app. `create`
|
|
51
|
+
(`false`, `"signed-in"` or `"anyone"`) sets who can make new documents
|
|
52
|
+
(`"anyone"` needs a public app). Use `false` for an app that makes no
|
|
53
|
+
documents of its own. `open` (`"signed-in"` or `"anyone"`) sets who can
|
|
54
|
+
open a public link. A public app with its hosted load gate off and no
|
|
55
|
+
`create` lets signed-out users create documents. Set
|
|
56
|
+
`create: "signed-in"` to require a sign-in.
|
|
57
|
+
- `shared_schemas` in `brass-app.json` defines a schema once for other fields
|
|
58
|
+
to refer to.
|
|
59
|
+
- An `imports` entry can set its own `schema`, for imported files that differ
|
|
60
|
+
from your app's documents.
|
|
61
|
+
- List handles have `get(index)`, so you can read one item by its position.
|
|
62
|
+
To walk every entry, map and ordered map handles have `entries()` and list
|
|
63
|
+
handles have `values()`.
|
|
64
|
+
- `mutate(fn, { undoable: false })` keeps changes the user did not make out of
|
|
65
|
+
Undo.
|
|
66
|
+
- `doc.importReport` returns the report your importer produced.
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- `callService` retries brief refusals itself and returns `rate_limited` if
|
|
71
|
+
they continue. Do not add your own immediate retry.
|
|
72
|
+
- Call `registerImporter` at startup, so your importer is ready whenever an
|
|
73
|
+
import starts.
|
|
74
|
+
|
|
75
|
+
### Deprecated
|
|
76
|
+
|
|
77
|
+
- `read()` on `StoredMap` and `StoredList`. Use `keys()`, `entries()` or
|
|
78
|
+
`values()`.
|
|
79
|
+
- `session.pick()` and `Brass.selectDocument()`. Use `session.open()` with no
|
|
80
|
+
id.
|
|
81
|
+
- `documentOptions.readOnly`. Use the top-level `readOnly`, which returns a
|
|
82
|
+
`ReadOnlyDocument`.
|
|
83
|
+
- `ordered()` on ordered map handles. Use `entries()`.
|
|
84
|
+
|
|
85
|
+
## 0.4.1
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- `Brass.user.display_name` and `Brass.user.avatar_url` keep resolving: the
|
|
90
|
+
profile read identifies the calling app the way every other call does.
|
|
91
|
+
Signing in as someone else also clears the previous person's organization
|
|
92
|
+
from the hosted toolbar.
|
|
93
|
+
- `Brass.callService` and `Brass.connectService` work on a document reached
|
|
94
|
+
through a project shared with you directly, which can sit in an organization
|
|
95
|
+
you are not a member of. Several calls needing an organization at once open
|
|
96
|
+
the chooser once between them.
|
|
97
|
+
|
|
9
98
|
## 0.4.0
|
|
10
99
|
|
|
11
100
|
### Added
|
|
@@ -37,10 +126,10 @@ breaking changes.
|
|
|
37
126
|
|
|
38
127
|
### Fixed
|
|
39
128
|
|
|
40
|
-
- A document
|
|
41
|
-
edits it cannot save. The first
|
|
42
|
-
`doc.readOnly`, and a later `mutate`
|
|
43
|
-
`doc.readOnly`.
|
|
129
|
+
- A document opened with no live connection configured to write through
|
|
130
|
+
reports the failure instead of accepting edits it cannot save. The first
|
|
131
|
+
write calls `Brass.onError` and sets `doc.readOnly`, and a later `mutate`
|
|
132
|
+
throws. Disable your editor on `doc.readOnly`.
|
|
44
133
|
- Reopening a document whose import did not finish runs the import again.
|
|
45
134
|
- A `doc.stream(name)` open that fails closes its connection, instead of
|
|
46
135
|
leaving it open for the life of the page.
|