@brass-build/client 0.1.0 → 0.3.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.
Files changed (213) hide show
  1. package/AGENTS.md +72 -63
  2. package/CHANGELOG.md +97 -0
  3. package/README.md +325 -235
  4. package/dist/auth-flow.d.ts +10 -1
  5. package/dist/auth-flow.d.ts.map +1 -1
  6. package/dist/auth-flow.js +64 -20
  7. package/dist/auth-flow.js.map +1 -1
  8. package/dist/client.d.ts +4 -0
  9. package/dist/client.d.ts.map +1 -1
  10. package/dist/client.js +245 -76
  11. package/dist/client.js.map +1 -1
  12. package/dist/document-checkpoints.d.ts +1 -0
  13. package/dist/document-checkpoints.d.ts.map +1 -1
  14. package/dist/document-checkpoints.js +27 -0
  15. package/dist/document-checkpoints.js.map +1 -1
  16. package/dist/document-engine.d.ts +4 -0
  17. package/dist/document-engine.d.ts.map +1 -0
  18. package/dist/document-engine.js +9 -0
  19. package/dist/document-engine.js.map +1 -0
  20. package/dist/document-signals.d.ts +31 -1
  21. package/dist/document-signals.d.ts.map +1 -1
  22. package/dist/document-signals.js +59 -0
  23. package/dist/document-signals.js.map +1 -1
  24. package/dist/document-streams.d.ts +8 -1
  25. package/dist/document-streams.d.ts.map +1 -1
  26. package/dist/document-streams.js +79 -8
  27. package/dist/document-streams.js.map +1 -1
  28. package/dist/document-thumbnail-capture.d.ts +20 -0
  29. package/dist/document-thumbnail-capture.d.ts.map +1 -1
  30. package/dist/document-thumbnail-capture.js +247 -9
  31. package/dist/document-thumbnail-capture.js.map +1 -1
  32. package/dist/documents-namespace.d.ts.map +1 -1
  33. package/dist/documents-namespace.js +22 -3
  34. package/dist/documents-namespace.js.map +1 -1
  35. package/dist/documents.d.ts +49 -16
  36. package/dist/documents.d.ts.map +1 -1
  37. package/dist/documents.js +981 -237
  38. package/dist/documents.js.map +1 -1
  39. package/dist/embed-protocol.d.ts +3 -0
  40. package/dist/embed-protocol.d.ts.map +1 -0
  41. package/dist/embed-protocol.js +26 -0
  42. package/dist/embed-protocol.js.map +1 -0
  43. package/dist/emitter.d.ts.map +1 -1
  44. package/dist/emitter.js +8 -1
  45. package/dist/emitter.js.map +1 -1
  46. package/dist/export-guest.d.ts.map +1 -1
  47. package/dist/export-guest.js +14 -6
  48. package/dist/export-guest.js.map +1 -1
  49. package/dist/fetch-deadline.d.ts +22 -0
  50. package/dist/fetch-deadline.d.ts.map +1 -0
  51. package/dist/fetch-deadline.js +96 -0
  52. package/dist/fetch-deadline.js.map +1 -0
  53. package/dist/fetch-retry.d.ts +1 -0
  54. package/dist/fetch-retry.d.ts.map +1 -1
  55. package/dist/fetch-retry.js +12 -5
  56. package/dist/fetch-retry.js.map +1 -1
  57. package/dist/handle-types.d.ts +150 -0
  58. package/dist/handle-types.d.ts.map +1 -0
  59. package/dist/handle-types.js +8 -0
  60. package/dist/handle-types.js.map +1 -0
  61. package/dist/handles.d.ts +48 -48
  62. package/dist/handles.d.ts.map +1 -1
  63. package/dist/handles.js +3122 -501
  64. package/dist/handles.js.map +1 -1
  65. package/dist/hosted-runtime.d.ts.map +1 -1
  66. package/dist/hosted-runtime.js +8 -12
  67. package/dist/hosted-runtime.js.map +1 -1
  68. package/dist/hosted-ui.d.ts +0 -1
  69. package/dist/hosted-ui.d.ts.map +1 -1
  70. package/dist/hosted-ui.js +29 -24
  71. package/dist/hosted-ui.js.map +1 -1
  72. package/dist/importer.d.ts.map +1 -1
  73. package/dist/importer.js +204 -8
  74. package/dist/importer.js.map +1 -1
  75. package/dist/index.d.ts +10 -10
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +11 -2
  78. package/dist/index.js.map +1 -1
  79. package/dist/internal.d.ts +2 -1
  80. package/dist/internal.d.ts.map +1 -1
  81. package/dist/internal.js +1 -0
  82. package/dist/internal.js.map +1 -1
  83. package/dist/join-coverage.d.ts +12 -0
  84. package/dist/join-coverage.d.ts.map +1 -0
  85. package/dist/join-coverage.js +37 -0
  86. package/dist/join-coverage.js.map +1 -0
  87. package/dist/jwt.d.ts.map +1 -1
  88. package/dist/jwt.js +5 -1
  89. package/dist/jwt.js.map +1 -1
  90. package/dist/launch-context.js +2 -2
  91. package/dist/launch-context.js.map +1 -1
  92. package/dist/mutate-batching.d.ts +25 -2
  93. package/dist/mutate-batching.d.ts.map +1 -1
  94. package/dist/mutate-batching.js +57 -10
  95. package/dist/mutate-batching.js.map +1 -1
  96. package/dist/open-document.d.ts +30 -1
  97. package/dist/open-document.d.ts.map +1 -1
  98. package/dist/open-document.js +1905 -322
  99. package/dist/open-document.js.map +1 -1
  100. package/dist/presence.d.ts +28 -0
  101. package/dist/presence.d.ts.map +1 -1
  102. package/dist/presence.js +149 -7
  103. package/dist/presence.js.map +1 -1
  104. package/dist/record-paging.d.ts +335 -71
  105. package/dist/record-paging.d.ts.map +1 -1
  106. package/dist/record-paging.js +590 -127
  107. package/dist/record-paging.js.map +1 -1
  108. package/dist/selection-persistence.d.ts.map +1 -1
  109. package/dist/selection-persistence.js +11 -1
  110. package/dist/selection-persistence.js.map +1 -1
  111. package/dist/serializer.d.ts +30 -1
  112. package/dist/serializer.d.ts.map +1 -1
  113. package/dist/session-persistence.d.ts.map +1 -1
  114. package/dist/session-persistence.js +9 -8
  115. package/dist/session-persistence.js.map +1 -1
  116. package/dist/session-toolbar.d.ts +0 -1
  117. package/dist/session-toolbar.d.ts.map +1 -1
  118. package/dist/session-toolbar.js +356 -83
  119. package/dist/session-toolbar.js.map +1 -1
  120. package/dist/session.d.ts.map +1 -1
  121. package/dist/session.js +87 -18
  122. package/dist/session.js.map +1 -1
  123. package/dist/tail-ops.d.ts +14 -4
  124. package/dist/tail-ops.d.ts.map +1 -1
  125. package/dist/tail-ops.js +75 -15
  126. package/dist/tail-ops.js.map +1 -1
  127. package/dist/topic-lifecycle.d.ts +4 -0
  128. package/dist/topic-lifecycle.d.ts.map +1 -1
  129. package/dist/topic-lifecycle.js +25 -1
  130. package/dist/topic-lifecycle.js.map +1 -1
  131. package/dist/types.d.ts +47 -1
  132. package/dist/types.d.ts.map +1 -1
  133. package/dist/undo.d.ts +2 -3
  134. package/dist/undo.d.ts.map +1 -1
  135. package/dist/undo.js +11 -0
  136. package/dist/undo.js.map +1 -1
  137. package/dist/unload-guard.d.ts +5 -0
  138. package/dist/unload-guard.d.ts.map +1 -0
  139. package/dist/unload-guard.js +88 -0
  140. package/dist/unload-guard.js.map +1 -0
  141. package/dist/version-bar.d.ts +4 -3
  142. package/dist/version-bar.d.ts.map +1 -1
  143. package/dist/version-bar.js +162 -20
  144. package/dist/version-bar.js.map +1 -1
  145. package/dist/version.d.ts +2 -2
  146. package/dist/version.js +1 -1
  147. package/dist/vite.d.ts +18 -2
  148. package/dist/vite.d.ts.map +1 -1
  149. package/dist/vite.js +133 -8
  150. package/dist/vite.js.map +1 -1
  151. package/dist/when-saved.d.ts +2 -0
  152. package/dist/when-saved.d.ts.map +1 -0
  153. package/dist/when-saved.js +70 -0
  154. package/dist/when-saved.js.map +1 -0
  155. package/dist/ws-client.d.ts +27 -3
  156. package/dist/ws-client.d.ts.map +1 -1
  157. package/dist/ws-client.js +408 -89
  158. package/dist/ws-client.js.map +1 -1
  159. package/dist/ws-frame-limit.d.ts.map +1 -1
  160. package/dist/ws-frame-limit.js +23 -17
  161. package/dist/ws-frame-limit.js.map +1 -1
  162. package/docs/app-manifest.md +7 -8
  163. package/docs/custom-chrome.md +21 -22
  164. package/docs/hosted-ui-advanced.md +14 -17
  165. package/docs/imported-documents.md +53 -197
  166. package/docs/presence.md +45 -21
  167. package/docs/schemas.md +12 -17
  168. package/docs/streams.md +55 -57
  169. package/package.json +4 -3
  170. package/src/auth-flow.ts +90 -23
  171. package/src/client.ts +262 -80
  172. package/src/document-checkpoints.ts +30 -0
  173. package/src/document-engine.ts +15 -0
  174. package/src/document-signals.ts +120 -8
  175. package/src/document-streams.ts +95 -9
  176. package/src/document-thumbnail-capture.ts +253 -9
  177. package/src/documents-namespace.ts +38 -13
  178. package/src/documents.ts +1103 -290
  179. package/src/embed-protocol.ts +25 -0
  180. package/src/emitter.ts +8 -1
  181. package/src/export-guest.ts +15 -9
  182. package/src/fetch-deadline.ts +119 -0
  183. package/src/fetch-retry.ts +14 -5
  184. package/src/handle-types.ts +303 -0
  185. package/src/handles.ts +3407 -683
  186. package/src/hosted-runtime.ts +8 -12
  187. package/src/hosted-ui.ts +28 -32
  188. package/src/importer.ts +216 -8
  189. package/src/index.ts +29 -18
  190. package/src/internal.ts +7 -0
  191. package/src/join-coverage.ts +42 -0
  192. package/src/jwt.ts +8 -1
  193. package/src/launch-context.ts +2 -2
  194. package/src/mutate-batching.ts +60 -11
  195. package/src/open-document.ts +2441 -502
  196. package/src/presence.ts +210 -11
  197. package/src/record-paging.ts +686 -137
  198. package/src/selection-persistence.ts +10 -1
  199. package/src/serializer.ts +33 -1
  200. package/src/session-persistence.ts +9 -8
  201. package/src/session-toolbar.ts +387 -89
  202. package/src/session.ts +91 -17
  203. package/src/tail-ops.ts +76 -10
  204. package/src/topic-lifecycle.ts +31 -1
  205. package/src/types.ts +56 -4
  206. package/src/undo.ts +13 -5
  207. package/src/unload-guard.ts +91 -0
  208. package/src/version-bar.ts +183 -26
  209. package/src/version.ts +1 -1
  210. package/src/vite.ts +175 -10
  211. package/src/when-saved.ts +66 -0
  212. package/src/ws-client.ts +461 -92
  213. package/src/ws-frame-limit.ts +23 -17
@@ -1,7 +1,7 @@
1
1
  // SDK surface: `Brass.documents.*`. The metadata surface: get /
2
- // thumbnails / branches. The editable surface (snapshot + ops +
3
- // mutate) is the `Document` runtime class via `Brass.openDocumentById`
4
- // / `Brass.createDocument`. Access-granting is hosted-only (the share
2
+ // thumbnails. The editable surface (snapshot + ops + mutate) is the
3
+ // `Document` runtime class via `Brass.openDocumentById` /
4
+ // `Brass.createDocument`. Access-granting is hosted-only (the share
5
5
  // dialog), not a programmatic method here.
6
6
 
7
7
  import type { Document } from './documents.js';
@@ -94,10 +94,9 @@ export interface DocumentRecord extends DocumentSummary {
94
94
  // `organization_id`, so the hierarchy above the document can evolve
95
95
  // (folders / teams) without a client change.
96
96
  location_label: string | null;
97
- // Whether someone can produce a file from this document: a platform
98
- // codec, an opaque blob's stored bytes, or an app installed on the
99
- // document's organization that declares an output for it. The server
100
- // resolves it, so a newly exportable format needs no client change.
97
+ // Whether anything can produce a file from this document. The server
98
+ // resolves who would write it, so a newly exportable format needs no
99
+ // client change.
101
100
  downloadable: boolean;
102
101
  }
103
102
 
@@ -177,6 +176,11 @@ export interface DocumentCheckpoint {
177
176
  // changed" can read it). Omitted means no message.
178
177
  export interface PushToDriveInput {
179
178
  message?: string;
179
+ // The file's bytes, for a document the platform has no writer for: its
180
+ // own app serializes it. The SDK supplies these from the registered
181
+ // serializer, so nothing an app calls has to.
182
+ /** @internal */
183
+ bytes?: Uint8Array;
180
184
  }
181
185
 
182
186
  // Outcome of a successful push.
@@ -278,11 +282,11 @@ export interface DocumentsInternalNamespace {
278
282
  doc: Document,
279
283
  input?: PushToDriveInput,
280
284
  ): Promise<PushToDriveResult>;
281
- // Fetch a presigned GET + descriptor for the original file behind an
282
- // opaque-blob document, so an app that knows the format can download
283
- // and parse it in-browser. Rejects with a `BrassError` when the doc is
284
- // not a stored opaque blob or the caller cannot reach it (404). The
285
- // per-doc instance method `doc.sourceBlob()` routes through this.
285
+ // Fetch a presigned GET + descriptor for the file a document was uploaded
286
+ // as, so an app that knows the format can download and parse it
287
+ // in-browser. Rejects with a `BrassError` when the document holds no such
288
+ // file or the caller cannot reach it (404). The per-doc instance method
289
+ // `doc.sourceBlob()` routes through this.
286
290
  sourceBlob(doc: Document): Promise<DocumentSourceBlob>;
287
291
  // The import-claim protocol behind `Brass.registerImporter`. The SDK
288
292
  // (never the app) claims the right to run the import of a stored
@@ -305,6 +309,11 @@ export function createDocumentsNamespace(
305
309
  opts: DocumentsFactoryOptions,
306
310
  ): DocumentsNamespace & DocumentsInternalNamespace {
307
311
  const apiFetch = createApiFetch(opts);
312
+ // Identifies THIS client to the import claim, so two tabs of one app
313
+ // signed in as one user are two claimants and only one of them imports.
314
+ // Minted once per namespace, so re-claiming from this client refreshes
315
+ // its own claim rather than taking a second one.
316
+ const importClientId = randomToken();
308
317
 
309
318
  return {
310
319
  get(docId) {
@@ -427,8 +436,14 @@ export function createDocumentsNamespace(
427
436
  { status: 400 },
428
437
  );
429
438
  }
430
- const body: { message?: string } = {};
439
+ const body: {
440
+ message?: string;
441
+ content_base64?: string;
442
+ } = {};
431
443
  if (input?.message !== undefined) body.message = input.message;
444
+ if (input?.bytes !== undefined) {
445
+ body.content_base64 = bytesToBase64(input.bytes);
446
+ }
432
447
  const res = await apiFetch<PushToDriveResult>({
433
448
  method: 'POST',
434
449
  path: `/documents/${encodeURIComponent(docId)}/drive-sync/push`,
@@ -452,12 +467,14 @@ export function createDocumentsNamespace(
452
467
  return apiFetch<ImportClaimResponse>({
453
468
  method: 'POST',
454
469
  path: `/documents/${encodeURIComponent(docId)}/import-claim`,
470
+ body: { client_id: importClientId },
455
471
  });
456
472
  },
457
473
  completeImport(docId) {
458
474
  return apiFetch<{ schema_ref: { app_id: string; schema_hash: string } }>({
459
475
  method: 'POST',
460
476
  path: `/documents/${encodeURIComponent(docId)}/import-complete`,
477
+ body: { client_id: importClientId },
461
478
  });
462
479
  },
463
480
  async getThumbnail(docId, options) {
@@ -477,6 +494,14 @@ export function createDocumentsNamespace(
477
494
  };
478
495
  }
479
496
 
497
+ function randomToken(): string {
498
+ const g = globalThis as { crypto?: { randomUUID?: () => string } };
499
+ if (g.crypto?.randomUUID) return g.crypto.randomUUID();
500
+ let s = '';
501
+ for (let i = 0; i < 32; i++) s += Math.floor(Math.random() * 16).toString(16);
502
+ return s;
503
+ }
504
+
480
505
  // Reads `SetThumbnailInput.image` into base64 plus a resolved MIME
481
506
  // type. A `Blob` carries its own `type` (canvas `toBlob` sets it);
482
507
  // raw `ArrayBuffer` / `Uint8Array` bytes need an explicit