@docx-editor.dev/pro 2.11.0 → 2.12.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 (47) hide show
  1. package/dist/chunk-C4RVARMI.cjs +3 -0
  2. package/dist/chunk-DHIPX767.js +3 -0
  3. package/dist/chunk-KOGVHJ7U.js +3 -0
  4. package/dist/chunk-QA3F5EUJ.cjs +3 -0
  5. package/dist/collaboration/hocuspocus.cjs +1 -1
  6. package/dist/collaboration/hocuspocus.d.cts +1 -1
  7. package/dist/collaboration/hocuspocus.d.ts +1 -1
  8. package/dist/collaboration/hocuspocus.js +1 -1
  9. package/dist/collaboration/index.cjs +2 -2
  10. package/dist/collaboration/index.d.cts +35 -3
  11. package/dist/collaboration/index.d.ts +35 -3
  12. package/dist/collaboration/index.js +2 -2
  13. package/dist/collaboration/webrtc.cjs +1 -1
  14. package/dist/collaboration/webrtc.d.cts +1 -1
  15. package/dist/collaboration/webrtc.d.ts +1 -1
  16. package/dist/collaboration/webrtc.js +1 -1
  17. package/dist/{document-session-DiBuzWwA.d.ts → document-session-1VSzWYaC.d.ts} +57 -28
  18. package/dist/document-session-I77CU7RQ.cjs +1 -0
  19. package/dist/{document-session-DVa53DAw.d.cts → document-session-KYavjw8A.d.cts} +57 -28
  20. package/dist/document-session-MTK2LEYT.cjs +1 -0
  21. package/dist/document-session-NFUE7UBO.js +1 -0
  22. package/dist/document-session-WEZH77T3.js +1 -0
  23. package/dist/{hocuspocus-YIKH6ENE.cjs → hocuspocus-3FLNEX7M.cjs} +1 -1
  24. package/dist/{hocuspocus-EUC4BGDD.js → hocuspocus-FC5NXRLW.js} +1 -1
  25. package/dist/react/index.cjs +1 -1
  26. package/dist/react/index.d.cts +1 -1
  27. package/dist/react/index.d.ts +1 -1
  28. package/dist/react/index.js +1 -1
  29. package/dist/vue/hocuspocus.cjs +1 -1
  30. package/dist/vue/hocuspocus.js +1 -1
  31. package/dist/vue/index.cjs +1 -1
  32. package/dist/vue/index.d.cts +2 -2
  33. package/dist/vue/index.d.ts +2 -2
  34. package/dist/vue/index.js +1 -1
  35. package/dist/vue/webrtc.cjs +1 -1
  36. package/dist/vue/webrtc.js +1 -1
  37. package/dist/{webrtc-CDIFHCQY.cjs → webrtc-UAS5I63G.cjs} +1 -1
  38. package/dist/{webrtc-36GPPCW4.js → webrtc-V2JQ2NO7.js} +1 -1
  39. package/package.json +4 -4
  40. package/dist/chunk-32RB7HPL.js +0 -3
  41. package/dist/chunk-4HGT2OVX.cjs +0 -3
  42. package/dist/chunk-7QSJBMZV.js +0 -3
  43. package/dist/chunk-YJM6R76M.cjs +0 -3
  44. package/dist/document-session-2B3QFWBQ.cjs +0 -1
  45. package/dist/document-session-6UET6BWT.js +0 -1
  46. package/dist/document-session-RGNZHMWF.js +0 -1
  47. package/dist/document-session-TU7WVBRB.cjs +0 -1
@@ -1,11 +1,43 @@
1
1
  export { C as CollaborationModuleOptions, c as collaborationModule } from '../collaboration-module-BgRxhW5b.cjs';
2
2
  export { a as CollaborationBootstrap, c as CollaborationHandle, b as CollaborationIdentityUpdate, C as CollaborationSession, d as CreateTextCollaborationOptions, T as TextCollaborationHandle, e as TextCollaborationSession, f as createTextCollaboration } from '../session-BH7Qgyp6.cjs';
3
- export { C as CreateDocumentCollaborationOptions, D as DocumentCollaborationHandle, a as DocumentCollaborationSession, c as createDocumentCollaboration, r as readCollaborationDocument } from '../document-session-DVa53DAw.cjs';
3
+ export { a as CollaborationResourceUsage, C as CreateDocumentCollaborationOptions, D as DocumentCollaborationHandle, b as DocumentCollaborationSession, c as createDocumentCollaboration, r as readCollaborationResourceUsage } from '../document-session-KYavjw8A.cjs';
4
4
  import { CollaborationFailureCode } from '@docx-editor.dev/core/collaboration';
5
+ import * as Y from 'yjs';
5
6
  import '@docx-editor.dev/core/editor';
6
- import 'yjs';
7
7
  import 'y-protocols/awareness';
8
8
 
9
+ /**
10
+ * Server-side read of one collaboration room: shared state to `.docx` bytes, joining nothing.
11
+ */
12
+
13
+ /**
14
+ * Read the document a synchronized `Y.Doc` holds, as `.docx` bytes.
15
+ *
16
+ * This is the server side of a room: export, autosave to your own storage, search indexing, a
17
+ * nightly PDF, a webhook. It JOINS NOTHING. There is no identity, no `Awareness` and no
18
+ * session, so the job that calls it never appears in anyone's avatar stack, and it creates no
19
+ * editing gate, so it cannot write back.
20
+ *
21
+ * `ydoc` must already hold the room's state: connect your provider and wait for its initial
22
+ * sync first, exactly as a `{ kind: \'join\' }` bootstrap does. A document that was never
23
+ * seeded refuses with `not-initialized` rather than returning a truncated file.
24
+ *
25
+ * ```ts
26
+ * // Hocuspocus hands `onStoreDocument` the synced Y.Doc already:
27
+ * async onStoreDocument({ documentName, document }) {
28
+ * await writeFile(`${documentName}.docx`, readCollaborationDocument(document));
29
+ * }
30
+ * ```
31
+ *
32
+ * Synchronous, and it materializes the whole package per call — this is a job, not a render.
33
+ *
34
+ * @throws CollaborationSchemaError — `not-initialized`, `concurrent-seed`,
35
+ * `blob-digest-mismatch`, or a limit code: the same refusals a joining replica makes, for the
36
+ * same reasons.
37
+ * @public
38
+ */
39
+ declare function readCollaborationDocument(ydoc: Y.Doc): Uint8Array;
40
+
9
41
  /** Wire protocol version a replica writes into shared metadata and refuses to mismatch. @public */
10
42
  declare const PROTOCOL_VERSION = 1;
11
43
  /** Shared Yjs schema version a replica writes into shared metadata and refuses to mismatch. @public */
@@ -19,4 +51,4 @@ declare class CollaborationSchemaError extends Error {
19
51
  constructor(code: CollaborationFailureCode, detail?: string | undefined);
20
52
  }
21
53
 
22
- export { CollaborationSchemaError, MAX_BASELINE_BYTES, PROTOCOL_VERSION, SCHEMA_VERSION };
54
+ export { CollaborationSchemaError, MAX_BASELINE_BYTES, PROTOCOL_VERSION, SCHEMA_VERSION, readCollaborationDocument };
@@ -1,11 +1,43 @@
1
1
  export { C as CollaborationModuleOptions, c as collaborationModule } from '../collaboration-module-BgRxhW5b.js';
2
2
  export { a as CollaborationBootstrap, c as CollaborationHandle, b as CollaborationIdentityUpdate, C as CollaborationSession, d as CreateTextCollaborationOptions, T as TextCollaborationHandle, e as TextCollaborationSession, f as createTextCollaboration } from '../session-BH7Qgyp6.js';
3
- export { C as CreateDocumentCollaborationOptions, D as DocumentCollaborationHandle, a as DocumentCollaborationSession, c as createDocumentCollaboration, r as readCollaborationDocument } from '../document-session-DiBuzWwA.js';
3
+ export { a as CollaborationResourceUsage, C as CreateDocumentCollaborationOptions, D as DocumentCollaborationHandle, b as DocumentCollaborationSession, c as createDocumentCollaboration, r as readCollaborationResourceUsage } from '../document-session-1VSzWYaC.js';
4
4
  import { CollaborationFailureCode } from '@docx-editor.dev/core/collaboration';
5
+ import * as Y from 'yjs';
5
6
  import '@docx-editor.dev/core/editor';
6
- import 'yjs';
7
7
  import 'y-protocols/awareness';
8
8
 
9
+ /**
10
+ * Server-side read of one collaboration room: shared state to `.docx` bytes, joining nothing.
11
+ */
12
+
13
+ /**
14
+ * Read the document a synchronized `Y.Doc` holds, as `.docx` bytes.
15
+ *
16
+ * This is the server side of a room: export, autosave to your own storage, search indexing, a
17
+ * nightly PDF, a webhook. It JOINS NOTHING. There is no identity, no `Awareness` and no
18
+ * session, so the job that calls it never appears in anyone's avatar stack, and it creates no
19
+ * editing gate, so it cannot write back.
20
+ *
21
+ * `ydoc` must already hold the room's state: connect your provider and wait for its initial
22
+ * sync first, exactly as a `{ kind: \'join\' }` bootstrap does. A document that was never
23
+ * seeded refuses with `not-initialized` rather than returning a truncated file.
24
+ *
25
+ * ```ts
26
+ * // Hocuspocus hands `onStoreDocument` the synced Y.Doc already:
27
+ * async onStoreDocument({ documentName, document }) {
28
+ * await writeFile(`${documentName}.docx`, readCollaborationDocument(document));
29
+ * }
30
+ * ```
31
+ *
32
+ * Synchronous, and it materializes the whole package per call — this is a job, not a render.
33
+ *
34
+ * @throws CollaborationSchemaError — `not-initialized`, `concurrent-seed`,
35
+ * `blob-digest-mismatch`, or a limit code: the same refusals a joining replica makes, for the
36
+ * same reasons.
37
+ * @public
38
+ */
39
+ declare function readCollaborationDocument(ydoc: Y.Doc): Uint8Array;
40
+
9
41
  /** Wire protocol version a replica writes into shared metadata and refuses to mismatch. @public */
10
42
  declare const PROTOCOL_VERSION = 1;
11
43
  /** Shared Yjs schema version a replica writes into shared metadata and refuses to mismatch. @public */
@@ -19,4 +51,4 @@ declare class CollaborationSchemaError extends Error {
19
51
  constructor(code: CollaborationFailureCode, detail?: string | undefined);
20
52
  }
21
53
 
22
- export { CollaborationSchemaError, MAX_BASELINE_BYTES, PROTOCOL_VERSION, SCHEMA_VERSION };
54
+ export { CollaborationSchemaError, MAX_BASELINE_BYTES, PROTOCOL_VERSION, SCHEMA_VERSION, readCollaborationDocument };
@@ -1,2 +1,2 @@
1
- export{b as collaborationModule}from'../chunk-Q2VBO66F.js';import {d,f,g,h as h$1,i,e,a,b}from'../chunk-32RB7HPL.js';export{d as CollaborationSchemaError,c as MAX_BASELINE_BYTES,a as PROTOCOL_VERSION,b as SCHEMA_VERSION,l as createDocumentCollaboration,k as readCollaborationDocument}from'../chunk-32RB7HPL.js';import*as l from'yjs';import {ORIGIN_IDS}from'@docx-editor.dev/core/store';import {createCollaborationStatusTracker,isCollaborationFailureCode}from'@docx-editor.dev/core/collaboration';var C="docxEditor",h=256,O=256,I=1e6,D=3e4;function U(a){let t=a.actorId.trim(),n=a.name.trim();if(t.length===0||t.length>h||n.length===0||n.length>h)throw new d("invalid-identity");if(a.color!==void 0&&a.color.length>64)throw new d("invalid-identity-color");return Object.freeze({actorId:t,name:n,...a.color?{color:a.color}:{},role:a.role??"human"})}function B(a){let t=a.trim();if(t.length===0||t.length>h)throw new d("invalid-document-id");return t}function F(a){let t=a?.trim()||globalThis.crypto.randomUUID();if(t.length===0||t.length>h)throw new d("invalid-session-id");return t}function N(a,t){let n=a.toString();if(n===t)return;let o=0;for(;o<n.length&&o<t.length&&n.charCodeAt(o)===t.charCodeAt(o);)o+=1;let e=0;for(;e<n.length-o&&e<t.length-o&&n.charCodeAt(n.length-e-1)===t.charCodeAt(t.length-e-1);)e+=1;let r=n.length-o-e;r>0&&a.delete(o,r);let i=t.slice(o,t.length-e);i.length>0&&a.insert(o,i);}function L(a){if(typeof a!="object"||a===null||Array.isArray(a))return null;let t=a;return typeof t.paragraphId!="string"||t.paragraphId.length!==8||typeof t.position!="string"||t.position.length===0||t.position.length>2048||!/^[A-Za-z0-9_-]+$/.test(t.position)?null:{paragraphId:t.paragraphId,position:t.position}}function H(a){if(a===void 0||typeof a!="object"||a===null||Array.isArray(a))return;let t=a,n=L(t.anchor),o=L(t.head);if(n&&o)return {anchor:n,head:o};if(typeof t.paragraphId=="string"&&t.paragraphId.length===8&&typeof t.anchor=="string"&&typeof t.head=="string"&&t.anchor.length>0&&t.head.length>0&&t.anchor.length<=2048&&t.head.length<=2048&&/^[A-Za-z0-9_-]+$/.test(t.anchor)&&/^[A-Za-z0-9_-]+$/.test(t.head))return {anchor:{paragraphId:t.paragraphId,position:t.anchor},head:{paragraphId:t.paragraphId,position:t.head}}}function R(a){if(typeof a!="object"||a===null||Array.isArray(a))return null;let t=a;if(typeof t.actorId!="string"||t.actorId.length===0||t.actorId.length>h||typeof t.name!="string"||t.name.length===0||t.name.length>h)return null;let n=typeof t.color=="string"&&t.color.length<=64?t.color:void 0,o=t.role==="agent"?"agent":"human",e=H(t.selection);return {actorId:t.actorId,name:t.name,...n?{color:n}:{},role:o,...e?{selection:e}:{}}}function V(a){let t="";for(let n of a)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function X(a){let t=a.replace(/-/g,"+").replace(/_/g,"/"),n=atob(t+"=".repeat((4-t.length%4)%4));return Uint8Array.from(n,o=>o.charCodeAt(0))}var w=class{constructor(t,n,o,e$1,r,i){this.ydoc=t;this.awareness=n;this.baseline=i;this.documentId=o,this.sessionId=e$1,this.identity=r;let{root:d,paragraphs:p}=e(t);this.baselineSha256=String(d.get("baselineSha256")),this.initializedBy=String(d.get("initializedBy")),this.undoManager=new l.UndoManager([...p.values()],{trackedOrigins:new Set([this.localOrigin]),captureTimeout:0}),t.on("afterTransaction",this.onYjsTransaction),n.on("change",this.onAwarenessChange),this.publishAwareness(),this.setStatus("ready");}ydoc;awareness;baseline;documentId;sessionId;identity;statusState=createCollaborationStatusTracker();statusListeners=new Set;selectionListeners=new Set;participantListeners=new Set;localOrigin=Object.freeze({kind:"docx-collaboration-local"});undoManager;baselineSha256;initializedBy;port=null;detachPort=null;applyingSharedState=false;remoteCounter=0;destroyed=false;status(){return this.statusState.status()}statusSnapshot(){return this.statusState.snapshot()}subscribeStatus(t){return this.statusListeners.add(t),()=>this.statusListeners.delete(t)}setTransportStatus(t,n,o){if(!this.destroyed&&!(this.statusState.status()==="error"&&t!=="error")){if(n!==void 0){this.setStatus(t,n,o);return}this.setStatus(t);}}get attached(){return this.port!==null}attach(t){if(this.destroyed)return ()=>{};if(this.port)return ()=>{};if(t.documentId!==this.documentId)return this.setStatus("error","document-id-mismatch"),()=>{};this.validateParagraphSet(t),this.port=t,this.reconcilePortFromYjs();let n=t.subscribe(o=>{if(!(this.destroyed||this.applyingSharedState)&&!(o.origin===ORIGIN_IDS.mutationRemote||o.origin===ORIGIN_IDS.projection||o.origin===ORIGIN_IDS.awareness))try{this.reconcileYjsFromPort();}catch(e){this.setStatus("error",e instanceof d?e.code:"local-mirror-failed",e instanceof d?e.detail:void 0);}});return this.detachPort=()=>{this.flushPendingJournals(),n(),this.port===t&&(this.port=null),this.detachPort=null;},()=>this.detachPort?.()}gateOperations(t,n){if(this.destroyed)return "collaboration-session-destroyed";if(this.statusState.status()!=="ready")return "collaboration-session-not-ready";if(!this.port)return "collaboration-session-not-attached";if(n.kind!=="body")return "experimental-collaboration-body-text-only";let o=new Map(this.port.paragraphs().map(e=>[e.nodeId,e.text.length]));for(let e of t){if(e.op!=="insertText"&&e.op!=="deleteText")return "experimental-collaboration-text-only";if("revision"in e&&e.revision!==void 0)return "experimental-collaboration-untracked-text-only";if(!this.port.paragraphByNodeId(e.paragraphId))return "experimental-collaboration-existing-paragraphs-only";let r=o.get(e.paragraphId);if(r===void 0)return "experimental-collaboration-existing-paragraphs-only";let i=e.op==="insertText"?r+e.text.length:r-Math.max(0,e.end-e.start);if(i>I)return "collaboration-text-limit";o.set(e.paragraphId,Math.max(0,i));}return null}canUndo(){return !this.destroyed&&this.undoManager.undoStack.length>0}canRedo(){return !this.destroyed&&this.undoManager.redoStack.length>0}undo(){return this.canUndo()?(this.undoManager.undo(),true):false}redo(){return this.canRedo()?(this.undoManager.redo(),true):false}setLocalSelection(t){if(this.destroyed)return;let{paragraphs:n}=e(this.ydoc),o=(r,i)=>{let d=n.get(r.toUpperCase());if(d)return {paragraphId:r.toUpperCase(),position:V(l.encodeRelativePosition(l.createRelativePositionFromTypeIndex(d,Math.max(0,Math.min(i,d.length)))))}},e$1;if(t){let r=o(t.anchor.paragraphId,t.anchor.offset),i=o(t.head.paragraphId,t.head.offset);r&&i&&(e$1={anchor:r,head:i});}this.publishAwareness(e$1);}participants(){let t=[],n=[...this.awareness.getStates().entries()].slice(0,O);for(let[o,e]of n){let r=R(e[C]);r&&t.push({actorId:r.actorId,name:r.name,...r.color?{color:r.color}:{},role:r.role??"human",isLocal:o===this.awareness.clientID});}return Object.freeze(t)}subscribeParticipants(t){return this.participantListeners.add(t),()=>this.participantListeners.delete(t)}remoteSelections(){if(!this.port)return [];let t=[...this.awareness.getStates().entries()].slice(0,O),{paragraphs:n}=e(this.ydoc),o=[];for(let[e,r]of t){if(e===this.awareness.clientID)continue;let i=R(r[C]);if(!i?.selection)continue;let d=y=>{let x=n.get(y.paragraphId);if(!x)return null;let u;try{u=l.createAbsolutePositionFromRelativePosition(l.decodeRelativePosition(X(y.position)),this.ydoc);}catch{return null}if(!u||u.type!==x)return null;let f=this.port?.paragraphs().find(M=>M.paragraphId===y.paragraphId);return f?{paragraphId:f.paragraphId,nodeId:f.nodeId,offset:u.index}:null},p=d(i.selection.anchor),v=d(i.selection.head);!p||!v||o.push(Object.freeze({actorId:i.actorId,name:i.name,...i.color?{color:i.color}:{},anchor:Object.freeze(p),head:Object.freeze(v)}));}return Object.freeze(o)}subscribeRemoteSelections(t){return this.selectionListeners.add(t),()=>this.selectionListeners.delete(t)}destroy(){this.destroyed||(this.flushPendingJournals(),this.detachPort?.(),this.destroyed=true,this.ydoc.off("afterTransaction",this.onYjsTransaction),this.awareness.off("change",this.onAwarenessChange),this.awareness.setLocalState(null),this.undoManager.destroy(),this.setStatus("destroyed"),this.statusListeners.clear(),this.selectionListeners.clear(),this.participantListeners.clear());}flushPendingJournals(){this.port?.flushPendingJournals();}onYjsTransaction=t=>{if(!this.destroyed&&t.origin!==this.localOrigin){try{this.validateImmutableSchema();}catch(n){this.setStatus("error",n instanceof d?n.code:"shared-schema-invalid",n instanceof d?n.detail:void 0);return}this.port&&this.reconcilePortFromYjs();}};onAwarenessChange=()=>{if(this.destroyed)return;let t=this.remoteSelections();for(let o of [...this.selectionListeners])o(t);let n=this.participants();for(let o of [...this.participantListeners])o(n);};publishAwareness(t){let n={actorId:this.identity.actorId,name:this.identity.name,...this.identity.color?{color:this.identity.color}:{},role:this.identity.role??"human",...t?{selection:t}:{}};this.awareness.setLocalStateField(C,n);}validateParagraphSet(t){let{paragraphs:n}=e(this.ydoc),o=t.paragraphs();if(o.length!==n.size||o.some(e=>!n.has(e.paragraphId)||!(n.get(e.paragraphId)instanceof l.Text)||n.get(e.paragraphId).length>I))throw new d("paragraph-set-mismatch")}validateImmutableSchema(){let{root:t,paragraphs:n}=e(this.ydoc),o=new Set(["protocolVersion","schemaVersion","documentId","baselineSha256","baselineByteLength","initializedBy","baseline","initialized"]);if([...t.keys()].some(r=>!o.has(r)))throw new d("unsupported-root-key");if(t.get("protocolVersion")!==a||t.get("schemaVersion")!==b||t.get("documentId")!==this.documentId||t.get("baselineSha256")!==this.baselineSha256||t.get("baselineByteLength")!==this.baseline.bytes.byteLength||t.get("initializedBy")!==this.initializedBy||t.get("initialized")!==true)throw new d("immutable-metadata-changed");let e$1=t.get("baseline");if(!(e$1 instanceof Uint8Array)||e$1.byteLength!==this.baseline.bytes.byteLength||e$1.some((r,i)=>r!==this.baseline.bytes[i]))throw new d("immutable-baseline-changed");for(let[r,i]of n)if(!this.baseline.paragraphs.some(d=>d.paragraphId===r)||!(i instanceof l.Text)||i.length>I)throw new d("paragraph-set-mismatch")}reconcileYjsFromPort(){let t=this.port;if(!t)return;let{paragraphs:n}=e(this.ydoc);this.ydoc.transact(()=>{for(let o of t.paragraphs()){let e=n.get(o.paragraphId);if(!e)throw new d("paragraph-set-mismatch");N(e,o.text);}},this.localOrigin),this.undoManager.stopCapturing();}reconcilePortFromYjs(){let t=this.port;if(!t||this.applyingSharedState)return;let{paragraphs:n}=e(this.ydoc);this.applyingSharedState=true;try{this.validateParagraphSet(t);let o=[];for(let e of t.paragraphs()){let r=n.get(e.paragraphId);if(!r)throw new d("paragraph-set-mismatch");let i=r.toString();i!==e.text&&o.push({paragraphId:e.paragraphId,text:i});}if(o.length>0){this.remoteCounter+=1;let e=t.applyParagraphTexts(o,{origin:ORIGIN_IDS.mutationRemote,actorId:"remote",operationId:`remote:${this.remoteCounter}`});if(!e.ok)throw new d(isCollaborationFailureCode(e.reason)?e.reason:"remote-apply-failed",isCollaborationFailureCode(e.reason)?void 0:e.reason)}}catch(o){this.setStatus("error",o instanceof d?o.code:"remote-apply-failed",o instanceof d?o.detail:void 0);}finally{this.applyingSharedState=false;}}setStatus(t,n,o){if(!this.statusState.set(t,n,o))return;let e=this.statusState.snapshot();for(let r of [...this.statusListeners])r(e.status,e.reason?.code,e.reason?.detail);}};async function $(a,t,n){if(a.bootstrap.kind==="create-or-join")throw new TypeError("createTextCollaboration does not support bootstrap kind 'create-or-join'. Use createDocumentCollaboration.");if(a.bootstrap.kind==="create"){let o=f(a.bootstrap.document,t);return await g(a.ydoc,t,n.actorId,o),h$1(a.ydoc,t)}return await i(a.ydoc,a.bootstrap.timeoutMs??D,a.bootstrap.signal),h$1(a.ydoc,t)}async function J(a){let t=B(a.documentId),n=F(a.sessionId),o=U(a.identity),e=await $(a,t,o),r=new w(a.ydoc,a.awareness,t,n,o,e);return Object.freeze({document:new Uint8Array(e.bytes),session:r,destroy:()=>r.destroy()})}
2
- export{J as createTextCollaboration};
1
+ export{b as collaborationModule}from'../chunk-Q2VBO66F.js';import {d,f,g,h as h$1,i,e,a,b}from'../chunk-KOGVHJ7U.js';export{d as CollaborationSchemaError,c as MAX_BASELINE_BYTES,a as PROTOCOL_VERSION,b as SCHEMA_VERSION,m as createDocumentCollaboration,k as readCollaborationDocument,j as readCollaborationResourceUsage}from'../chunk-KOGVHJ7U.js';import*as l from'yjs';import {ORIGIN_IDS}from'@docx-editor.dev/core/store';import {createCollaborationStatusTracker,isCollaborationFailureCode}from'@docx-editor.dev/core/collaboration';var C="docxEditor",h=256,O=256,I=1e6,D=3e4;function B(a){let t=a.actorId.trim(),n=a.name.trim();if(t.length===0||t.length>h||n.length===0||n.length>h)throw new d("invalid-identity");if(a.color!==void 0&&a.color.length>64)throw new d("invalid-identity-color");return Object.freeze({actorId:t,name:n,...a.color?{color:a.color}:{},role:a.role??"human"})}function F(a){let t=a.trim();if(t.length===0||t.length>h)throw new d("invalid-document-id");return t}function N(a){let t=a?.trim()||globalThis.crypto.randomUUID();if(t.length===0||t.length>h)throw new d("invalid-session-id");return t}function H(a,t){let n=a.toString();if(n===t)return;let o=0;for(;o<n.length&&o<t.length&&n.charCodeAt(o)===t.charCodeAt(o);)o+=1;let e=0;for(;e<n.length-o&&e<t.length-o&&n.charCodeAt(n.length-e-1)===t.charCodeAt(t.length-e-1);)e+=1;let r=n.length-o-e;r>0&&a.delete(o,r);let i=t.slice(o,t.length-e);i.length>0&&a.insert(o,i);}function R(a){if(typeof a!="object"||a===null||Array.isArray(a))return null;let t=a;return typeof t.paragraphId!="string"||t.paragraphId.length!==8||typeof t.position!="string"||t.position.length===0||t.position.length>2048||!/^[A-Za-z0-9_-]+$/.test(t.position)?null:{paragraphId:t.paragraphId,position:t.position}}function V(a){if(a===void 0||typeof a!="object"||a===null||Array.isArray(a))return;let t=a,n=R(t.anchor),o=R(t.head);if(n&&o)return {anchor:n,head:o};if(typeof t.paragraphId=="string"&&t.paragraphId.length===8&&typeof t.anchor=="string"&&typeof t.head=="string"&&t.anchor.length>0&&t.head.length>0&&t.anchor.length<=2048&&t.head.length<=2048&&/^[A-Za-z0-9_-]+$/.test(t.anchor)&&/^[A-Za-z0-9_-]+$/.test(t.head))return {anchor:{paragraphId:t.paragraphId,position:t.anchor},head:{paragraphId:t.paragraphId,position:t.head}}}function L(a){if(typeof a!="object"||a===null||Array.isArray(a))return null;let t=a;if(typeof t.actorId!="string"||t.actorId.length===0||t.actorId.length>h||typeof t.name!="string"||t.name.length===0||t.name.length>h)return null;let n=typeof t.color=="string"&&t.color.length<=64?t.color:void 0,o=t.role==="agent"?"agent":"human",e=V(t.selection);return {actorId:t.actorId,name:t.name,...n?{color:n}:{},role:o,...e?{selection:e}:{}}}function X(a){let t="";for(let n of a)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function $(a){let t=a.replace(/-/g,"+").replace(/_/g,"/"),n=atob(t+"=".repeat((4-t.length%4)%4));return Uint8Array.from(n,o=>o.charCodeAt(0))}var w=class{constructor(t,n,o,e$1,r,i){this.ydoc=t;this.awareness=n;this.baseline=i;this.documentId=o,this.sessionId=e$1,this.identity=r;let{root:d,paragraphs:p}=e(t);this.baselineSha256=String(d.get("baselineSha256")),this.initializedBy=String(d.get("initializedBy")),this.undoManager=new l.UndoManager([...p.values()],{trackedOrigins:new Set([this.localOrigin]),captureTimeout:0}),t.on("afterTransaction",this.onYjsTransaction),n.on("change",this.onAwarenessChange),this.publishAwareness(),this.setStatus("ready");}ydoc;awareness;baseline;documentId;sessionId;identity;statusState=createCollaborationStatusTracker();statusListeners=new Set;selectionListeners=new Set;participantListeners=new Set;localOrigin=Object.freeze({kind:"docx-collaboration-local"});undoManager;baselineSha256;initializedBy;port=null;detachPort=null;applyingSharedState=false;remoteCounter=0;destroyed=false;status(){return this.statusState.status()}statusSnapshot(){return this.statusState.snapshot()}subscribeStatus(t){return this.statusListeners.add(t),()=>this.statusListeners.delete(t)}setTransportStatus(t,n,o){if(!this.destroyed&&!(this.statusState.status()==="error"&&t!=="error")){if(n!==void 0){this.setStatus(t,n,o);return}this.setStatus(t);}}get attached(){return this.port!==null}attach(t){if(this.destroyed)return ()=>{};if(this.port)return ()=>{};if(t.documentId!==this.documentId)return this.setStatus("error","document-id-mismatch"),()=>{};this.validateParagraphSet(t),this.port=t,this.reconcilePortFromYjs();let n=t.subscribe(o=>{if(!(this.destroyed||this.applyingSharedState)&&!(o.origin===ORIGIN_IDS.mutationRemote||o.origin===ORIGIN_IDS.projection||o.origin===ORIGIN_IDS.awareness))try{this.reconcileYjsFromPort();}catch(e){this.setStatus("error",e instanceof d?e.code:"local-mirror-failed",e instanceof d?e.detail:void 0);}});return this.detachPort=()=>{this.flushPendingJournals(),n(),this.port===t&&(this.port=null),this.detachPort=null;},()=>this.detachPort?.()}gateOperations(t,n){if(this.destroyed)return "collaboration-session-destroyed";if(this.statusState.status()!=="ready")return "collaboration-session-not-ready";if(!this.port)return "collaboration-session-not-attached";if(n.kind!=="body")return "experimental-collaboration-body-text-only";let o=new Map(this.port.paragraphs().map(e=>[e.nodeId,e.text.length]));for(let e of t){if(e.op!=="insertText"&&e.op!=="deleteText")return "experimental-collaboration-text-only";if("revision"in e&&e.revision!==void 0)return "experimental-collaboration-untracked-text-only";if(!this.port.paragraphByNodeId(e.paragraphId))return "experimental-collaboration-existing-paragraphs-only";let r=o.get(e.paragraphId);if(r===void 0)return "experimental-collaboration-existing-paragraphs-only";let i=e.op==="insertText"?r+e.text.length:r-Math.max(0,e.end-e.start);if(i>I)return "collaboration-text-limit";o.set(e.paragraphId,Math.max(0,i));}return null}canUndo(){return !this.destroyed&&this.statusState.status()==="ready"&&this.undoManager.undoStack.length>0}canRedo(){return !this.destroyed&&this.statusState.status()==="ready"&&this.undoManager.redoStack.length>0}undo(){return this.canUndo()?(this.undoManager.undo(),true):false}redo(){return this.canRedo()?(this.undoManager.redo(),true):false}setLocalSelection(t){if(this.destroyed)return;let{paragraphs:n}=e(this.ydoc),o=(r,i)=>{let d=n.get(r.toUpperCase());if(d)return {paragraphId:r.toUpperCase(),position:X(l.encodeRelativePosition(l.createRelativePositionFromTypeIndex(d,Math.max(0,Math.min(i,d.length)))))}},e$1;if(t){let r=o(t.anchor.paragraphId,t.anchor.offset),i=o(t.head.paragraphId,t.head.offset);r&&i&&(e$1={anchor:r,head:i});}this.publishAwareness(e$1);}participants(){let t=[],n=[...this.awareness.getStates().entries()].slice(0,O);for(let[o,e]of n){let r=L(e[C]);r&&t.push({actorId:r.actorId,name:r.name,...r.color?{color:r.color}:{},role:r.role??"human",isLocal:o===this.awareness.clientID});}return Object.freeze(t)}subscribeParticipants(t){return this.participantListeners.add(t),()=>this.participantListeners.delete(t)}remoteSelections(){if(!this.port)return [];let t=[...this.awareness.getStates().entries()].slice(0,O),{paragraphs:n}=e(this.ydoc),o=[];for(let[e,r]of t){if(e===this.awareness.clientID)continue;let i=L(r[C]);if(!i?.selection)continue;let d=y=>{let x=n.get(y.paragraphId);if(!x)return null;let u;try{u=l.createAbsolutePositionFromRelativePosition(l.decodeRelativePosition($(y.position)),this.ydoc);}catch{return null}if(!u||u.type!==x)return null;let f=this.port?.paragraphs().find(M=>M.paragraphId===y.paragraphId);return f?{paragraphId:f.paragraphId,nodeId:f.nodeId,offset:u.index}:null},p=d(i.selection.anchor),v=d(i.selection.head);!p||!v||o.push(Object.freeze({actorId:i.actorId,name:i.name,...i.color?{color:i.color}:{},anchor:Object.freeze(p),head:Object.freeze(v)}));}return Object.freeze(o)}subscribeRemoteSelections(t){return this.selectionListeners.add(t),()=>this.selectionListeners.delete(t)}destroy(){this.destroyed||(this.flushPendingJournals(),this.detachPort?.(),this.destroyed=true,this.ydoc.off("afterTransaction",this.onYjsTransaction),this.awareness.off("change",this.onAwarenessChange),this.awareness.setLocalState(null),this.undoManager.destroy(),this.setStatus("destroyed"),this.statusListeners.clear(),this.selectionListeners.clear(),this.participantListeners.clear());}flushPendingJournals(){this.port?.flushPendingJournals();}onYjsTransaction=t=>{if(!this.destroyed&&t.origin!==this.localOrigin){try{this.validateImmutableSchema();}catch(n){this.setStatus("error",n instanceof d?n.code:"shared-schema-invalid",n instanceof d?n.detail:void 0);return}this.port&&this.reconcilePortFromYjs();}};onAwarenessChange=()=>{if(this.destroyed)return;let t=this.remoteSelections();for(let o of [...this.selectionListeners])o(t);let n=this.participants();for(let o of [...this.participantListeners])o(n);};publishAwareness(t){let n={actorId:this.identity.actorId,name:this.identity.name,...this.identity.color?{color:this.identity.color}:{},role:this.identity.role??"human",...t?{selection:t}:{}};this.awareness.setLocalStateField(C,n);}validateParagraphSet(t){let{paragraphs:n}=e(this.ydoc),o=t.paragraphs();if(o.length!==n.size||o.some(e=>!n.has(e.paragraphId)||!(n.get(e.paragraphId)instanceof l.Text)||n.get(e.paragraphId).length>I))throw new d("paragraph-set-mismatch")}validateImmutableSchema(){let{root:t,paragraphs:n}=e(this.ydoc),o=new Set(["protocolVersion","schemaVersion","documentId","baselineSha256","baselineByteLength","initializedBy","baseline","initialized"]);if([...t.keys()].some(r=>!o.has(r)))throw new d("unsupported-root-key");if(t.get("protocolVersion")!==a||t.get("schemaVersion")!==b||t.get("documentId")!==this.documentId||t.get("baselineSha256")!==this.baselineSha256||t.get("baselineByteLength")!==this.baseline.bytes.byteLength||t.get("initializedBy")!==this.initializedBy||t.get("initialized")!==true)throw new d("immutable-metadata-changed");let e$1=t.get("baseline");if(!(e$1 instanceof Uint8Array)||e$1.byteLength!==this.baseline.bytes.byteLength||e$1.some((r,i)=>r!==this.baseline.bytes[i]))throw new d("immutable-baseline-changed");for(let[r,i]of n)if(!this.baseline.paragraphs.some(d=>d.paragraphId===r)||!(i instanceof l.Text)||i.length>I)throw new d("paragraph-set-mismatch")}reconcileYjsFromPort(){let t=this.port;if(!t)return;let{paragraphs:n}=e(this.ydoc);this.ydoc.transact(()=>{for(let o of t.paragraphs()){let e=n.get(o.paragraphId);if(!e)throw new d("paragraph-set-mismatch");H(e,o.text);}},this.localOrigin),this.undoManager.stopCapturing();}reconcilePortFromYjs(){let t=this.port;if(!t||this.applyingSharedState)return;let{paragraphs:n}=e(this.ydoc);this.applyingSharedState=true;try{this.validateParagraphSet(t);let o=[];for(let e of t.paragraphs()){let r=n.get(e.paragraphId);if(!r)throw new d("paragraph-set-mismatch");let i=r.toString();i!==e.text&&o.push({paragraphId:e.paragraphId,text:i});}if(o.length>0){this.remoteCounter+=1;let e=t.applyParagraphTexts(o,{origin:ORIGIN_IDS.mutationRemote,actorId:"remote",operationId:`remote:${this.remoteCounter}`});if(!e.ok)throw new d(isCollaborationFailureCode(e.reason)?e.reason:"remote-apply-failed",isCollaborationFailureCode(e.reason)?void 0:e.reason)}}catch(o){this.setStatus("error",o instanceof d?o.code:"remote-apply-failed",o instanceof d?o.detail:void 0);}finally{this.applyingSharedState=false;}}setStatus(t,n,o){if(!this.statusState.set(t,n,o))return;let e=this.statusState.snapshot();for(let r of [...this.statusListeners])r(e.status,e.reason?.code,e.reason?.detail);}};async function J(a,t,n){if(a.bootstrap.kind==="create-or-join")throw new TypeError("createTextCollaboration does not support bootstrap kind 'create-or-join'. Use createDocumentCollaboration.");if(a.bootstrap.kind==="create"){let o=f(a.bootstrap.document,t);return await g(a.ydoc,t,n.actorId,o),h$1(a.ydoc,t)}return await i(a.ydoc,a.bootstrap.timeoutMs??D,a.bootstrap.signal),h$1(a.ydoc,t)}async function Z(a){let t=F(a.documentId),n=N(a.sessionId),o=B(a.identity),e=await J(a,t,o),r=new w(a.ydoc,a.awareness,t,n,o,e);return Object.freeze({document:new Uint8Array(e.bytes),session:r,destroy:()=>r.destroy()})}
2
+ export{Z as createTextCollaboration};
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkLUUFBXJ5_cjs=require('../chunk-LUUFBXJ5.cjs'),chunk4HGT2OVX_cjs=require('../chunk-4HGT2OVX.cjs'),F=require('yjs'),awareness=require('y-protocols/awareness'),yWebrtc=require('y-webrtc');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var F__namespace=/*#__PURE__*/_interopNamespace(F);var D=new WeakSet,T=(e,n)=>(e[n]<<24|e[n+1]<<16|e[n+2]<<8|e[n+3])>>>0,w=(e,n,i)=>{e[n]=i>>>24&255,e[n+1]=i>>>16&255,e[n+2]=i>>>8&255,e[n+3]=i&255;},B=e=>e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):null,Y=e=>new Promise(n=>{setTimeout(n,e);});function L(e,n){if(D.has(e))return;D.add(e);let i=e.send.bind(e),o=e._onChannelMessage.bind(e),d=n?.partialTimeoutMs,c=typeof d=="number"&&Number.isFinite(d)&&d>0?d:3e4,l=n?.onAbandonedMessage,f=[],s=new Map,b=false,E=1,h=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),s.delete(t),e.destroyed!==true&&l?.());},S=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),r.timer=setTimeout(()=>{h(t);},c));},u=()=>e._channel?.bufferedAmount??0,p=async()=>{let t=0;for(;u()>1048576;){if(e.destroyed===true||t>=3e4)return false;await Y(20),t+=20;}return e.destroyed!==true},I=async t=>{let r=Math.ceil(t.byteLength/16371);if(r>8192)throw new Error(`collaboration message needs ${r} chunks, above the 8192 limit`);let g=E;E=E+1>>>0||1;for(let A=0;A<r;A+=1){if(!await p())return;let y=A*16371,a=t.subarray(y,Math.min(y+16371,t.byteLength)),m=new Uint8Array(13+a.byteLength);m[0]=251,w(m,1,g),w(m,5,A),w(m,9,r),m.set(a,13),i(m);}},k=async()=>{if(!b){b=true;try{for(;f.length>0;){let t=f.shift();if(t){if(e.destroyed===!0)return;await I(t);}}}finally{b=false;}}};e.send=t=>{if(typeof t=="string"||t.byteLength<=16371){i(t);return}f.push(t),k();},e._onChannelMessage=t=>{let r=B(t.data);if(!r||r.byteLength<13||r[0]!==251){o(t);return}let g=T(r,1),A=T(r,5),y=T(r,9);if(y===0||y>8192||A>=y)return;let a=s.get(g);if(!a){if(s.size>=4){let _=s.keys().next();_.done||h(_.value);}a={chunks:new Array(y),count:y,received:0,bytes:0,timer:void 0},s.set(g,a);}if(a.count!==y||a.chunks[A])return;let m=r.subarray(13);if(a.chunks[A]=m,a.received+=1,a.bytes+=m.byteLength,a.received!==a.count){S(g);return}a.timer!==void 0&&clearTimeout(a.timer),s.delete(g);let v=new Uint8Array(a.bytes),P=0;for(let _ of a.chunks){if(!_)return;v.set(_,P),P+=_.byteLength;}e.destroyed!==true&&e.push(v);};}var W=Object.freeze(["wss://turn.0docker.com/ws"]),R=false;function H(e){e===void 0&&(R||(R=true,console.warn("[docx-editor] createWebrtcCollaboration was called without `signaling`, so it uses the public demo endpoints. They are shared, unauthenticated, and can go away. Pass your own `signaling` URLs (and TURN `iceServers`) in production, or pass `signaling: DEMO_SIGNALING_ENDPOINTS` explicitly to accept the demo endpoints.")));}function V(){R=false;}var G=/^[A-Za-z0-9_-]{24,256}$/,U="#collab=";function X(e){let n=e.password?.trim()??"";return n.length>0?n:K(e.href)}var K=e=>{let n=e??(typeof globalThis.location=="object"&&globalThis.location!==null?String(globalThis.location.href??""):"");if(n.length===0)return;let i;try{i=new URL(n).hash;}catch{return}if(!i.startsWith(U))return;let o;try{o=decodeURIComponent(i.slice(U.length));}catch{return}if(G.test(o))return o},z=(e,n)=>{Promise.resolve(e.key).then(()=>{let i=e.room;if(!i)return;let o=i.webrtcConns,d=l=>{L(l.peer,{onAbandonedMessage:n});};for(let l of o.values())d(l);let c=o.set.bind(o);o.set=(l,f)=>(d(f),c(l,f));});};async function ee(e){let n=chunkLUUFBXJ5_cjs.b(e.roomId);H(e.signaling);let i=X({password:e.password}),o=new F__namespace.Doc,d=new awareness.Awareness(o),c=null,l=()=>{},f=()=>{let u=new yWebrtc.WebrtcProvider(n,o,{awareness:d,signaling:[...e.signaling??W],...i!==void 0?{password:i}:{},...e.iceServers?{peerOpts:{config:{iceServers:e.iceServers.map(p=>({...p}))}}}:{}});return z(u,()=>l()),u},s;try{e.bootstrap.kind!=="create"&&(c=f()),s=await chunk4HGT2OVX_cjs.l({ydoc:o,awareness:d,documentId:n,identity:e.identity,bootstrap:e.bootstrap,offlineEditing:e.offlineEditing}),c||(c=f());}catch(u){throw c?.destroy(),d.destroy(),o.destroy(),u}if(!c)throw s.destroy(),d.destroy(),o.destroy(),new Error("WebRTC provider did not initialize");let b=c,E=s.session;l=()=>{E.setTransportStatus("error","transport","incomplete chunk");};let h=u=>{E.setTransportStatus(u.connected?"ready":"disconnected",u.connected?void 0:"transport-disconnected",u.connected?void 0:"webrtc disconnected");};b.on("status",h);let S=false;return Object.freeze({document:s.document,session:E,ydoc:o,provider:b,destroy(){S||(S=true,b.off("status",h),s.destroy(),b.destroy(),d.destroy(),o.destroy());}})}
1
+ 'use strict';var chunkLUUFBXJ5_cjs=require('../chunk-LUUFBXJ5.cjs'),chunkC4RVARMI_cjs=require('../chunk-C4RVARMI.cjs'),F=require('yjs'),awareness=require('y-protocols/awareness'),yWebrtc=require('y-webrtc');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var F__namespace=/*#__PURE__*/_interopNamespace(F);var D=new WeakSet,T=(e,n)=>(e[n]<<24|e[n+1]<<16|e[n+2]<<8|e[n+3])>>>0,w=(e,n,i)=>{e[n]=i>>>24&255,e[n+1]=i>>>16&255,e[n+2]=i>>>8&255,e[n+3]=i&255;},B=e=>e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):null,Y=e=>new Promise(n=>{setTimeout(n,e);});function L(e,n){if(D.has(e))return;D.add(e);let i=e.send.bind(e),o=e._onChannelMessage.bind(e),d=n?.partialTimeoutMs,c=typeof d=="number"&&Number.isFinite(d)&&d>0?d:3e4,l=n?.onAbandonedMessage,f=[],s=new Map,b=false,E=1,h=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),s.delete(t),e.destroyed!==true&&l?.());},S=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),r.timer=setTimeout(()=>{h(t);},c));},u=()=>e._channel?.bufferedAmount??0,p=async()=>{let t=0;for(;u()>1048576;){if(e.destroyed===true||t>=3e4)return false;await Y(20),t+=20;}return e.destroyed!==true},I=async t=>{let r=Math.ceil(t.byteLength/16371);if(r>8192)throw new Error(`collaboration message needs ${r} chunks, above the 8192 limit`);let g=E;E=E+1>>>0||1;for(let A=0;A<r;A+=1){if(!await p())return;let y=A*16371,a=t.subarray(y,Math.min(y+16371,t.byteLength)),m=new Uint8Array(13+a.byteLength);m[0]=251,w(m,1,g),w(m,5,A),w(m,9,r),m.set(a,13),i(m);}},k=async()=>{if(!b){b=true;try{for(;f.length>0;){let t=f.shift();if(t){if(e.destroyed===!0)return;await I(t);}}}finally{b=false;}}};e.send=t=>{if(typeof t=="string"||t.byteLength<=16371){i(t);return}f.push(t),k();},e._onChannelMessage=t=>{let r=B(t.data);if(!r||r.byteLength<13||r[0]!==251){o(t);return}let g=T(r,1),A=T(r,5),y=T(r,9);if(y===0||y>8192||A>=y)return;let a=s.get(g);if(!a){if(s.size>=4){let _=s.keys().next();_.done||h(_.value);}a={chunks:new Array(y),count:y,received:0,bytes:0,timer:void 0},s.set(g,a);}if(a.count!==y||a.chunks[A])return;let m=r.subarray(13);if(a.chunks[A]=m,a.received+=1,a.bytes+=m.byteLength,a.received!==a.count){S(g);return}a.timer!==void 0&&clearTimeout(a.timer),s.delete(g);let v=new Uint8Array(a.bytes),P=0;for(let _ of a.chunks){if(!_)return;v.set(_,P),P+=_.byteLength;}e.destroyed!==true&&e.push(v);};}var W=Object.freeze(["wss://turn.0docker.com/ws"]),R=false;function H(e){e===void 0&&(R||(R=true,console.warn("[docx-editor] createWebrtcCollaboration was called without `signaling`, so it uses the public demo endpoints. They are shared, unauthenticated, and can go away. Pass your own `signaling` URLs (and TURN `iceServers`) in production, or pass `signaling: DEMO_SIGNALING_ENDPOINTS` explicitly to accept the demo endpoints.")));}function V(){R=false;}var G=/^[A-Za-z0-9_-]{24,256}$/,U="#collab=";function X(e){let n=e.password?.trim()??"";return n.length>0?n:K(e.href)}var K=e=>{let n=e??(typeof globalThis.location=="object"&&globalThis.location!==null?String(globalThis.location.href??""):"");if(n.length===0)return;let i;try{i=new URL(n).hash;}catch{return}if(!i.startsWith(U))return;let o;try{o=decodeURIComponent(i.slice(U.length));}catch{return}if(G.test(o))return o},z=(e,n)=>{Promise.resolve(e.key).then(()=>{let i=e.room;if(!i)return;let o=i.webrtcConns,d=l=>{L(l.peer,{onAbandonedMessage:n});};for(let l of o.values())d(l);let c=o.set.bind(o);o.set=(l,f)=>(d(f),c(l,f));});};async function ee(e){let n=chunkLUUFBXJ5_cjs.b(e.roomId);H(e.signaling);let i=X({password:e.password}),o=new F__namespace.Doc,d=new awareness.Awareness(o),c=null,l=()=>{},f=()=>{let u=new yWebrtc.WebrtcProvider(n,o,{awareness:d,signaling:[...e.signaling??W],...i!==void 0?{password:i}:{},...e.iceServers?{peerOpts:{config:{iceServers:e.iceServers.map(p=>({...p}))}}}:{}});return z(u,()=>l()),u},s;try{e.bootstrap.kind!=="create"&&(c=f()),s=await chunkC4RVARMI_cjs.m({ydoc:o,awareness:d,documentId:n,identity:e.identity,bootstrap:e.bootstrap,offlineEditing:e.offlineEditing}),c||(c=f());}catch(u){throw c?.destroy(),d.destroy(),o.destroy(),u}if(!c)throw s.destroy(),d.destroy(),o.destroy(),new Error("WebRTC provider did not initialize");let b=c,E=s.session;l=()=>{E.setTransportStatus("error","transport","incomplete chunk");};let h=u=>{E.setTransportStatus(u.connected?"ready":"disconnected",u.connected?void 0:"transport-disconnected",u.connected?void 0:"webrtc disconnected");};b.on("status",h);let S=false;return Object.freeze({document:s.document,session:E,ydoc:o,provider:b,destroy(){S||(S=true,b.off("status",h),s.destroy(),b.destroy(),d.destroy(),o.destroy());}})}
2
2
  Object.defineProperty(exports,"createCollaborationRoomId",{enumerable:true,get:function(){return chunkLUUFBXJ5_cjs.a}});Object.defineProperty(exports,"validateRoomId",{enumerable:true,get:function(){return chunkLUUFBXJ5_cjs.b}});exports.DEMO_SIGNALING_ENDPOINTS=W;exports.createWebrtcCollaboration=ee;exports.resetDemoSignalingWarningForTests=V;exports.resolveWebrtcRoomPassword=X;exports.warnOnDemoSignalingFallback=H;
@@ -1,7 +1,7 @@
1
1
  import * as Y from 'yjs';
2
2
  import { WebrtcProvider } from 'y-webrtc';
3
3
  import { CollaborationIdentity } from '@docx-editor.dev/core/collaboration';
4
- import { D as DocumentCollaborationHandle } from '../document-session-DVa53DAw.cjs';
4
+ import { D as DocumentCollaborationHandle } from '../document-session-KYavjw8A.cjs';
5
5
  import { a as CollaborationBootstrap } from '../session-BH7Qgyp6.cjs';
6
6
  export { c as createCollaborationRoomId, v as validateRoomId } from '../room-id-BfudXOZz.cjs';
7
7
  import 'y-protocols/awareness';
@@ -1,7 +1,7 @@
1
1
  import * as Y from 'yjs';
2
2
  import { WebrtcProvider } from 'y-webrtc';
3
3
  import { CollaborationIdentity } from '@docx-editor.dev/core/collaboration';
4
- import { D as DocumentCollaborationHandle } from '../document-session-DiBuzWwA.js';
4
+ import { D as DocumentCollaborationHandle } from '../document-session-1VSzWYaC.js';
5
5
  import { a as CollaborationBootstrap } from '../session-BH7Qgyp6.js';
6
6
  export { c as createCollaborationRoomId, v as validateRoomId } from '../room-id-BfudXOZz.js';
7
7
  import 'y-protocols/awareness';
@@ -1,2 +1,2 @@
1
- import {b}from'../chunk-6DEUT2RQ.js';export{a as createCollaborationRoomId,b as validateRoomId}from'../chunk-6DEUT2RQ.js';import {l}from'../chunk-32RB7HPL.js';import*as F from'yjs';import {Awareness}from'y-protocols/awareness';import {WebrtcProvider}from'y-webrtc';var D=new WeakSet,T=(e,n)=>(e[n]<<24|e[n+1]<<16|e[n+2]<<8|e[n+3])>>>0,w=(e,n,i)=>{e[n]=i>>>24&255,e[n+1]=i>>>16&255,e[n+2]=i>>>8&255,e[n+3]=i&255;},B=e=>e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):null,Y=e=>new Promise(n=>{setTimeout(n,e);});function L(e,n){if(D.has(e))return;D.add(e);let i=e.send.bind(e),o=e._onChannelMessage.bind(e),d=n?.partialTimeoutMs,c=typeof d=="number"&&Number.isFinite(d)&&d>0?d:3e4,l=n?.onAbandonedMessage,f=[],s=new Map,b=false,E=1,h=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),s.delete(t),e.destroyed!==true&&l?.());},S=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),r.timer=setTimeout(()=>{h(t);},c));},u=()=>e._channel?.bufferedAmount??0,p=async()=>{let t=0;for(;u()>1048576;){if(e.destroyed===true||t>=3e4)return false;await Y(20),t+=20;}return e.destroyed!==true},I=async t=>{let r=Math.ceil(t.byteLength/16371);if(r>8192)throw new Error(`collaboration message needs ${r} chunks, above the 8192 limit`);let g=E;E=E+1>>>0||1;for(let A=0;A<r;A+=1){if(!await p())return;let y=A*16371,a=t.subarray(y,Math.min(y+16371,t.byteLength)),m=new Uint8Array(13+a.byteLength);m[0]=251,w(m,1,g),w(m,5,A),w(m,9,r),m.set(a,13),i(m);}},k=async()=>{if(!b){b=true;try{for(;f.length>0;){let t=f.shift();if(t){if(e.destroyed===!0)return;await I(t);}}}finally{b=false;}}};e.send=t=>{if(typeof t=="string"||t.byteLength<=16371){i(t);return}f.push(t),k();},e._onChannelMessage=t=>{let r=B(t.data);if(!r||r.byteLength<13||r[0]!==251){o(t);return}let g=T(r,1),A=T(r,5),y=T(r,9);if(y===0||y>8192||A>=y)return;let a=s.get(g);if(!a){if(s.size>=4){let _=s.keys().next();_.done||h(_.value);}a={chunks:new Array(y),count:y,received:0,bytes:0,timer:void 0},s.set(g,a);}if(a.count!==y||a.chunks[A])return;let m=r.subarray(13);if(a.chunks[A]=m,a.received+=1,a.bytes+=m.byteLength,a.received!==a.count){S(g);return}a.timer!==void 0&&clearTimeout(a.timer),s.delete(g);let v=new Uint8Array(a.bytes),P=0;for(let _ of a.chunks){if(!_)return;v.set(_,P),P+=_.byteLength;}e.destroyed!==true&&e.push(v);};}var W=Object.freeze(["wss://turn.0docker.com/ws"]),R=false;function H(e){e===void 0&&(R||(R=true,console.warn("[docx-editor] createWebrtcCollaboration was called without `signaling`, so it uses the public demo endpoints. They are shared, unauthenticated, and can go away. Pass your own `signaling` URLs (and TURN `iceServers`) in production, or pass `signaling: DEMO_SIGNALING_ENDPOINTS` explicitly to accept the demo endpoints.")));}function V(){R=false;}var G=/^[A-Za-z0-9_-]{24,256}$/,U="#collab=";function X(e){let n=e.password?.trim()??"";return n.length>0?n:K(e.href)}var K=e=>{let n=e??(typeof globalThis.location=="object"&&globalThis.location!==null?String(globalThis.location.href??""):"");if(n.length===0)return;let i;try{i=new URL(n).hash;}catch{return}if(!i.startsWith(U))return;let o;try{o=decodeURIComponent(i.slice(U.length));}catch{return}if(G.test(o))return o},z=(e,n)=>{Promise.resolve(e.key).then(()=>{let i=e.room;if(!i)return;let o=i.webrtcConns,d=l=>{L(l.peer,{onAbandonedMessage:n});};for(let l of o.values())d(l);let c=o.set.bind(o);o.set=(l,f)=>(d(f),c(l,f));});};async function ee(e){let n=b(e.roomId);H(e.signaling);let i=X({password:e.password}),o=new F.Doc,d=new Awareness(o),c=null,l$1=()=>{},f=()=>{let u=new WebrtcProvider(n,o,{awareness:d,signaling:[...e.signaling??W],...i!==void 0?{password:i}:{},...e.iceServers?{peerOpts:{config:{iceServers:e.iceServers.map(p=>({...p}))}}}:{}});return z(u,()=>l$1()),u},s;try{e.bootstrap.kind!=="create"&&(c=f()),s=await l({ydoc:o,awareness:d,documentId:n,identity:e.identity,bootstrap:e.bootstrap,offlineEditing:e.offlineEditing}),c||(c=f());}catch(u){throw c?.destroy(),d.destroy(),o.destroy(),u}if(!c)throw s.destroy(),d.destroy(),o.destroy(),new Error("WebRTC provider did not initialize");let b$1=c,E=s.session;l$1=()=>{E.setTransportStatus("error","transport","incomplete chunk");};let h=u=>{E.setTransportStatus(u.connected?"ready":"disconnected",u.connected?void 0:"transport-disconnected",u.connected?void 0:"webrtc disconnected");};b$1.on("status",h);let S=false;return Object.freeze({document:s.document,session:E,ydoc:o,provider:b$1,destroy(){S||(S=true,b$1.off("status",h),s.destroy(),b$1.destroy(),d.destroy(),o.destroy());}})}
1
+ import {b}from'../chunk-6DEUT2RQ.js';export{a as createCollaborationRoomId,b as validateRoomId}from'../chunk-6DEUT2RQ.js';import {m}from'../chunk-KOGVHJ7U.js';import*as F from'yjs';import {Awareness}from'y-protocols/awareness';import {WebrtcProvider}from'y-webrtc';var D=new WeakSet,T=(e,n)=>(e[n]<<24|e[n+1]<<16|e[n+2]<<8|e[n+3])>>>0,w=(e,n,i)=>{e[n]=i>>>24&255,e[n+1]=i>>>16&255,e[n+2]=i>>>8&255,e[n+3]=i&255;},B=e=>e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):null,Y=e=>new Promise(n=>{setTimeout(n,e);});function L(e,n){if(D.has(e))return;D.add(e);let i=e.send.bind(e),o=e._onChannelMessage.bind(e),d=n?.partialTimeoutMs,c=typeof d=="number"&&Number.isFinite(d)&&d>0?d:3e4,l=n?.onAbandonedMessage,f=[],s=new Map,b=false,E=1,h=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),s.delete(t),e.destroyed!==true&&l?.());},S=t=>{let r=s.get(t);r&&(r.timer!==void 0&&clearTimeout(r.timer),r.timer=setTimeout(()=>{h(t);},c));},u=()=>e._channel?.bufferedAmount??0,p=async()=>{let t=0;for(;u()>1048576;){if(e.destroyed===true||t>=3e4)return false;await Y(20),t+=20;}return e.destroyed!==true},I=async t=>{let r=Math.ceil(t.byteLength/16371);if(r>8192)throw new Error(`collaboration message needs ${r} chunks, above the 8192 limit`);let g=E;E=E+1>>>0||1;for(let A=0;A<r;A+=1){if(!await p())return;let y=A*16371,a=t.subarray(y,Math.min(y+16371,t.byteLength)),m=new Uint8Array(13+a.byteLength);m[0]=251,w(m,1,g),w(m,5,A),w(m,9,r),m.set(a,13),i(m);}},k=async()=>{if(!b){b=true;try{for(;f.length>0;){let t=f.shift();if(t){if(e.destroyed===!0)return;await I(t);}}}finally{b=false;}}};e.send=t=>{if(typeof t=="string"||t.byteLength<=16371){i(t);return}f.push(t),k();},e._onChannelMessage=t=>{let r=B(t.data);if(!r||r.byteLength<13||r[0]!==251){o(t);return}let g=T(r,1),A=T(r,5),y=T(r,9);if(y===0||y>8192||A>=y)return;let a=s.get(g);if(!a){if(s.size>=4){let _=s.keys().next();_.done||h(_.value);}a={chunks:new Array(y),count:y,received:0,bytes:0,timer:void 0},s.set(g,a);}if(a.count!==y||a.chunks[A])return;let m=r.subarray(13);if(a.chunks[A]=m,a.received+=1,a.bytes+=m.byteLength,a.received!==a.count){S(g);return}a.timer!==void 0&&clearTimeout(a.timer),s.delete(g);let v=new Uint8Array(a.bytes),P=0;for(let _ of a.chunks){if(!_)return;v.set(_,P),P+=_.byteLength;}e.destroyed!==true&&e.push(v);};}var W=Object.freeze(["wss://turn.0docker.com/ws"]),R=false;function H(e){e===void 0&&(R||(R=true,console.warn("[docx-editor] createWebrtcCollaboration was called without `signaling`, so it uses the public demo endpoints. They are shared, unauthenticated, and can go away. Pass your own `signaling` URLs (and TURN `iceServers`) in production, or pass `signaling: DEMO_SIGNALING_ENDPOINTS` explicitly to accept the demo endpoints.")));}function V(){R=false;}var G=/^[A-Za-z0-9_-]{24,256}$/,U="#collab=";function X(e){let n=e.password?.trim()??"";return n.length>0?n:K(e.href)}var K=e=>{let n=e??(typeof globalThis.location=="object"&&globalThis.location!==null?String(globalThis.location.href??""):"");if(n.length===0)return;let i;try{i=new URL(n).hash;}catch{return}if(!i.startsWith(U))return;let o;try{o=decodeURIComponent(i.slice(U.length));}catch{return}if(G.test(o))return o},z=(e,n)=>{Promise.resolve(e.key).then(()=>{let i=e.room;if(!i)return;let o=i.webrtcConns,d=l=>{L(l.peer,{onAbandonedMessage:n});};for(let l of o.values())d(l);let c=o.set.bind(o);o.set=(l,f)=>(d(f),c(l,f));});};async function ee(e){let n=b(e.roomId);H(e.signaling);let i=X({password:e.password}),o=new F.Doc,d=new Awareness(o),c=null,l=()=>{},f=()=>{let u=new WebrtcProvider(n,o,{awareness:d,signaling:[...e.signaling??W],...i!==void 0?{password:i}:{},...e.iceServers?{peerOpts:{config:{iceServers:e.iceServers.map(p=>({...p}))}}}:{}});return z(u,()=>l()),u},s;try{e.bootstrap.kind!=="create"&&(c=f()),s=await m({ydoc:o,awareness:d,documentId:n,identity:e.identity,bootstrap:e.bootstrap,offlineEditing:e.offlineEditing}),c||(c=f());}catch(u){throw c?.destroy(),d.destroy(),o.destroy(),u}if(!c)throw s.destroy(),d.destroy(),o.destroy(),new Error("WebRTC provider did not initialize");let b$1=c,E=s.session;l=()=>{E.setTransportStatus("error","transport","incomplete chunk");};let h=u=>{E.setTransportStatus(u.connected?"ready":"disconnected",u.connected?void 0:"transport-disconnected",u.connected?void 0:"webrtc disconnected");};b$1.on("status",h);let S=false;return Object.freeze({document:s.document,session:E,ydoc:o,provider:b$1,destroy(){S||(S=true,b$1.off("status",h),s.destroy(),b$1.destroy(),d.destroy(),o.destroy());}})}
2
2
  export{W as DEMO_SIGNALING_ENDPOINTS,ee as createWebrtcCollaboration,V as resetDemoSignalingWarningForTests,X as resolveWebrtcRoomPassword,H as warnOnDemoSignalingFallback};
@@ -3,6 +3,52 @@ import { Awareness } from 'y-protocols/awareness';
3
3
  import { CollaborationIdentity } from '@docx-editor.dev/core/collaboration';
4
4
  import { a as CollaborationBootstrap, c as CollaborationHandle, e as TextCollaborationSession, b as CollaborationIdentityUpdate } from './session-BH7Qgyp6.js';
5
5
 
6
+ /**
7
+ * Room-size observability.
8
+ *
9
+ * A room only grows: deletion is a tombstone, and deleted blob bytes stay in the shared blob
10
+ * map. The resource caps that bound hostile amplification run on every received edit and
11
+ * count that growth, so a long-lived room walks toward a terminal `too-many-nodes` or
12
+ * `blob-store-full` failure. Until compaction exists (the generation reset of issue #554),
13
+ * the honest interim is visibility: a host that can SEE the walk can archive and re-room
14
+ * before the caps end the session for it.
15
+ */
16
+
17
+ /**
18
+ * One reading of a room's replicated size against this replica's hard limits.
19
+ *
20
+ * Every `max*` value is the cap whose crossing turns the session status terminal.
21
+ * `tombstonedNodes` is included in `nodes`: a tombstone is never map-deleted, so it keeps
22
+ * counting against `maxNodes` for the life of the room. A reading is a snapshot — take a new
23
+ * one to observe growth.
24
+ *
25
+ * @public
26
+ */
27
+ interface CollaborationResourceUsage {
28
+ /** Replicated node records, tombstones included. */
29
+ readonly nodes: number;
30
+ /** The subset of `nodes` that is tombstoned: permanent, and only compaction reclaims it. */
31
+ readonly tombstonedNodes: number;
32
+ readonly maxNodes: number;
33
+ readonly relationships: number;
34
+ readonly maxRelationships: number;
35
+ readonly parts: number;
36
+ readonly maxParts: number;
37
+ /** Bytes in the shared blob map, unreferenced bytes included. */
38
+ readonly blobBytes: number;
39
+ readonly maxBlobBytes: number;
40
+ }
41
+ /**
42
+ * Read a room's resource usage from a synchronized `Y.Doc`, joining nothing.
43
+ *
44
+ * The server-side sibling of `readCollaborationDocument`: call it from the same jobs — an
45
+ * autosave hook, a metrics scraper — to watch a room's growth against the caps that would
46
+ * end it. It creates no session and writes nothing, and it walks the node map once per call.
47
+ *
48
+ * @public
49
+ */
50
+ declare function readCollaborationResourceUsage(ydoc: Y.Doc): CollaborationResourceUsage;
51
+
6
52
  /**
7
53
  * Full-document collaboration over the canonical primitive journal.
8
54
  *
@@ -29,6 +75,15 @@ interface DocumentCollaborationSession extends TextCollaborationSession {
29
75
  * runtime property is ignored.
30
76
  */
31
77
  setIdentity(update: CollaborationIdentityUpdate): void;
78
+ /**
79
+ * One reading of the room's replicated size against this replica's hard limits.
80
+ *
81
+ * A room only grows — deletion is a tombstone — and the limits that bound hostile
82
+ * amplification turn terminal when crossed. Watch this to archive and re-room before that
83
+ * happens. The tombstone count walks the node map once per call, so read it on your own
84
+ * schedule rather than per keystroke.
85
+ */
86
+ resourceUsage(): CollaborationResourceUsage;
32
87
  }
33
88
  /** Owned full-document collaboration replica. @public */
34
89
  type DocumentCollaborationHandle = CollaborationHandle<DocumentCollaborationSession>;
@@ -56,33 +111,7 @@ interface CreateDocumentCollaborationOptions {
56
111
  */
57
112
  readonly offlineEditing?: boolean;
58
113
  }
59
- /**
60
- * Read the document a synchronized `Y.Doc` holds, as `.docx` bytes.
61
- *
62
- * This is the server side of a room: export, autosave to your own storage, search indexing, a
63
- * nightly PDF, a webhook. It JOINS NOTHING. There is no identity, no `Awareness` and no
64
- * session, so the job that calls it never appears in anyone's avatar stack, and it creates no
65
- * editing gate, so it cannot write back.
66
- *
67
- * `ydoc` must already hold the room's state: connect your provider and wait for its initial
68
- * sync first, exactly as a `{ kind: \'join\' }` bootstrap does. A document that was never
69
- * seeded refuses with `not-initialized` rather than returning a truncated file.
70
- *
71
- * ```ts
72
- * // Hocuspocus hands `onStoreDocument` the synced Y.Doc already:
73
- * async onStoreDocument({ documentName, document }) {
74
- * await writeFile(`${documentName}.docx`, readCollaborationDocument(document));
75
- * }
76
- * ```
77
- *
78
- * Synchronous, and it materializes the whole package per call — this is a job, not a render.
79
- *
80
- * @throws CollaborationSchemaError — `not-initialized`, `concurrent-seed`,
81
- * `blob-digest-mismatch`, or a limit code: the same refusals a joining replica makes, for the
82
- * same reasons.
83
- * @public
84
- */
85
- declare function readCollaborationDocument(ydoc: Y.Doc): Uint8Array;
114
+
86
115
  /**
87
116
  * Create or join one full-document collaboration replica.
88
117
  *
@@ -91,4 +120,4 @@ declare function readCollaborationDocument(ydoc: Y.Doc): Uint8Array;
91
120
  */
92
121
  declare function createDocumentCollaboration(options: CreateDocumentCollaborationOptions): Promise<DocumentCollaborationHandle>;
93
122
 
94
- export { type CreateDocumentCollaborationOptions as C, type DocumentCollaborationHandle as D, type DocumentCollaborationSession as a, createDocumentCollaboration as c, readCollaborationDocument as r };
123
+ export { type CreateDocumentCollaborationOptions as C, type DocumentCollaborationHandle as D, type CollaborationResourceUsage as a, type DocumentCollaborationSession as b, createDocumentCollaboration as c, readCollaborationResourceUsage as r };
@@ -0,0 +1 @@
1
+ 'use strict';var chunkQA3F5EUJ_cjs=require('./chunk-QA3F5EUJ.cjs');Object.defineProperty(exports,"ATTACH_WATCHDOG_MS_FOR_TESTS",{enumerable:true,get:function(){return chunkQA3F5EUJ_cjs.c}});Object.defineProperty(exports,"createDocumentCollaboration",{enumerable:true,get:function(){return chunkQA3F5EUJ_cjs.d}});Object.defineProperty(exports,"readCollaborationDocument",{enumerable:true,get:function(){return chunkQA3F5EUJ_cjs.b}});
@@ -3,6 +3,52 @@ import { Awareness } from 'y-protocols/awareness';
3
3
  import { CollaborationIdentity } from '@docx-editor.dev/core/collaboration';
4
4
  import { a as CollaborationBootstrap, c as CollaborationHandle, e as TextCollaborationSession, b as CollaborationIdentityUpdate } from './session-BH7Qgyp6.cjs';
5
5
 
6
+ /**
7
+ * Room-size observability.
8
+ *
9
+ * A room only grows: deletion is a tombstone, and deleted blob bytes stay in the shared blob
10
+ * map. The resource caps that bound hostile amplification run on every received edit and
11
+ * count that growth, so a long-lived room walks toward a terminal `too-many-nodes` or
12
+ * `blob-store-full` failure. Until compaction exists (the generation reset of issue #554),
13
+ * the honest interim is visibility: a host that can SEE the walk can archive and re-room
14
+ * before the caps end the session for it.
15
+ */
16
+
17
+ /**
18
+ * One reading of a room's replicated size against this replica's hard limits.
19
+ *
20
+ * Every `max*` value is the cap whose crossing turns the session status terminal.
21
+ * `tombstonedNodes` is included in `nodes`: a tombstone is never map-deleted, so it keeps
22
+ * counting against `maxNodes` for the life of the room. A reading is a snapshot — take a new
23
+ * one to observe growth.
24
+ *
25
+ * @public
26
+ */
27
+ interface CollaborationResourceUsage {
28
+ /** Replicated node records, tombstones included. */
29
+ readonly nodes: number;
30
+ /** The subset of `nodes` that is tombstoned: permanent, and only compaction reclaims it. */
31
+ readonly tombstonedNodes: number;
32
+ readonly maxNodes: number;
33
+ readonly relationships: number;
34
+ readonly maxRelationships: number;
35
+ readonly parts: number;
36
+ readonly maxParts: number;
37
+ /** Bytes in the shared blob map, unreferenced bytes included. */
38
+ readonly blobBytes: number;
39
+ readonly maxBlobBytes: number;
40
+ }
41
+ /**
42
+ * Read a room's resource usage from a synchronized `Y.Doc`, joining nothing.
43
+ *
44
+ * The server-side sibling of `readCollaborationDocument`: call it from the same jobs — an
45
+ * autosave hook, a metrics scraper — to watch a room's growth against the caps that would
46
+ * end it. It creates no session and writes nothing, and it walks the node map once per call.
47
+ *
48
+ * @public
49
+ */
50
+ declare function readCollaborationResourceUsage(ydoc: Y.Doc): CollaborationResourceUsage;
51
+
6
52
  /**
7
53
  * Full-document collaboration over the canonical primitive journal.
8
54
  *
@@ -29,6 +75,15 @@ interface DocumentCollaborationSession extends TextCollaborationSession {
29
75
  * runtime property is ignored.
30
76
  */
31
77
  setIdentity(update: CollaborationIdentityUpdate): void;
78
+ /**
79
+ * One reading of the room's replicated size against this replica's hard limits.
80
+ *
81
+ * A room only grows — deletion is a tombstone — and the limits that bound hostile
82
+ * amplification turn terminal when crossed. Watch this to archive and re-room before that
83
+ * happens. The tombstone count walks the node map once per call, so read it on your own
84
+ * schedule rather than per keystroke.
85
+ */
86
+ resourceUsage(): CollaborationResourceUsage;
32
87
  }
33
88
  /** Owned full-document collaboration replica. @public */
34
89
  type DocumentCollaborationHandle = CollaborationHandle<DocumentCollaborationSession>;
@@ -56,33 +111,7 @@ interface CreateDocumentCollaborationOptions {
56
111
  */
57
112
  readonly offlineEditing?: boolean;
58
113
  }
59
- /**
60
- * Read the document a synchronized `Y.Doc` holds, as `.docx` bytes.
61
- *
62
- * This is the server side of a room: export, autosave to your own storage, search indexing, a
63
- * nightly PDF, a webhook. It JOINS NOTHING. There is no identity, no `Awareness` and no
64
- * session, so the job that calls it never appears in anyone's avatar stack, and it creates no
65
- * editing gate, so it cannot write back.
66
- *
67
- * `ydoc` must already hold the room's state: connect your provider and wait for its initial
68
- * sync first, exactly as a `{ kind: \'join\' }` bootstrap does. A document that was never
69
- * seeded refuses with `not-initialized` rather than returning a truncated file.
70
- *
71
- * ```ts
72
- * // Hocuspocus hands `onStoreDocument` the synced Y.Doc already:
73
- * async onStoreDocument({ documentName, document }) {
74
- * await writeFile(`${documentName}.docx`, readCollaborationDocument(document));
75
- * }
76
- * ```
77
- *
78
- * Synchronous, and it materializes the whole package per call — this is a job, not a render.
79
- *
80
- * @throws CollaborationSchemaError — `not-initialized`, `concurrent-seed`,
81
- * `blob-digest-mismatch`, or a limit code: the same refusals a joining replica makes, for the
82
- * same reasons.
83
- * @public
84
- */
85
- declare function readCollaborationDocument(ydoc: Y.Doc): Uint8Array;
114
+
86
115
  /**
87
116
  * Create or join one full-document collaboration replica.
88
117
  *
@@ -91,4 +120,4 @@ declare function readCollaborationDocument(ydoc: Y.Doc): Uint8Array;
91
120
  */
92
121
  declare function createDocumentCollaboration(options: CreateDocumentCollaborationOptions): Promise<DocumentCollaborationHandle>;
93
122
 
94
- export { type CreateDocumentCollaborationOptions as C, type DocumentCollaborationHandle as D, type DocumentCollaborationSession as a, createDocumentCollaboration as c, readCollaborationDocument as r };
123
+ export { type CreateDocumentCollaborationOptions as C, type DocumentCollaborationHandle as D, type CollaborationResourceUsage as a, type DocumentCollaborationSession as b, createDocumentCollaboration as c, readCollaborationResourceUsage as r };
@@ -0,0 +1 @@
1
+ 'use strict';var chunkC4RVARMI_cjs=require('./chunk-C4RVARMI.cjs');Object.defineProperty(exports,"ATTACH_WATCHDOG_MS_FOR_TESTS",{enumerable:true,get:function(){return chunkC4RVARMI_cjs.l}});Object.defineProperty(exports,"createDocumentCollaboration",{enumerable:true,get:function(){return chunkC4RVARMI_cjs.m}});Object.defineProperty(exports,"readCollaborationDocument",{enumerable:true,get:function(){return chunkC4RVARMI_cjs.k}});
@@ -0,0 +1 @@
1
+ export{l as ATTACH_WATCHDOG_MS_FOR_TESTS,m as createDocumentCollaboration,k as readCollaborationDocument}from'./chunk-KOGVHJ7U.js';
@@ -0,0 +1 @@
1
+ export{c as ATTACH_WATCHDOG_MS_FOR_TESTS,d as createDocumentCollaboration,b as readCollaborationDocument}from'./chunk-DHIPX767.js';
@@ -1 +1 @@
1
- 'use strict';var chunkLUUFBXJ5_cjs=require('./chunk-LUUFBXJ5.cjs'),chunkYJM6R76M_cjs=require('./chunk-YJM6R76M.cjs'),P=require('yjs'),awareness=require('y-protocols/awareness'),provider=require('@hocuspocus/provider');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var P__namespace=/*#__PURE__*/_interopNamespace(P);var g=3e4,S=Symbol("createHocuspocusCollaboration.provider"),O=o=>new provider.HocuspocusProvider({url:o.url,name:o.name,document:o.document,awareness:o.awareness,...o.token!==void 0?{token:o.token}:{}});function F(o,d){return new Promise((c,e)=>{if(o.isSynced){c();return}let n=()=>{clearTimeout(s),o.off("synced",a),o.off("authenticationFailed",t);},a=()=>{n(),c();},t=r=>{n(),e(new chunkYJM6R76M_cjs.a("initialization-aborted",`authentication failed: ${r.reason}`));},s=setTimeout(()=>{n(),e(new chunkYJM6R76M_cjs.a("initialization-timeout"));},d);o.on("synced",a),o.on("authenticationFailed",t);})}async function E(o){let d=chunkLUUFBXJ5_cjs.b(o.roomId),c=o[S]??O,e=new P__namespace.Doc,n=new awareness.Awareness(e),a=()=>c({url:o.url,name:d,document:e,awareness:n,...o.token!==void 0?{token:o.token}:{}}),t=null,s=null;try{o.bootstrap.kind!=="create"&&(t=a(),await F(t,o.syncedTimeoutMs??g)),s=await chunkYJM6R76M_cjs.d({ydoc:e,awareness:n,documentId:d,identity:o.identity,bootstrap:o.bootstrap,offlineEditing:o.offlineEditing}),t||(t=a());}catch(i){throw s?.destroy(),t?.destroy(),n.destroy(),e.destroy(),i}let r=t,u=s,l=u.session,f=i=>{l.setTransportStatus(i.status==="connected"?"ready":"disconnected",i.status==="connected"?void 0:"transport-disconnected",i.status==="connected"?void 0:"websocket disconnected");};r.on("status",f);let p=()=>{l.setTransportStatus("error","authentication-failed");};r.on("authenticationFailed",p);let b=false;return Object.freeze({document:u.document,session:l,ydoc:e,provider:r,destroy(){b||(b=true,r.off("status",f),r.off("authenticationFailed",p),u.destroy(),r.destroy(),n.destroy(),e.destroy());}})}Object.defineProperty(exports,"createCollaborationRoomId",{enumerable:true,get:function(){return chunkLUUFBXJ5_cjs.a}});Object.defineProperty(exports,"validateRoomId",{enumerable:true,get:function(){return chunkLUUFBXJ5_cjs.b}});exports.HOCUSPOCUS_PROVIDER_FOR_TESTS=S;exports.createHocuspocusCollaboration=E;
1
+ 'use strict';var chunkLUUFBXJ5_cjs=require('./chunk-LUUFBXJ5.cjs'),chunkQA3F5EUJ_cjs=require('./chunk-QA3F5EUJ.cjs'),P=require('yjs'),awareness=require('y-protocols/awareness'),provider=require('@hocuspocus/provider');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var P__namespace=/*#__PURE__*/_interopNamespace(P);var g=3e4,S=Symbol("createHocuspocusCollaboration.provider"),O=o=>new provider.HocuspocusProvider({url:o.url,name:o.name,document:o.document,awareness:o.awareness,...o.token!==void 0?{token:o.token}:{}});function F(o,d){return new Promise((c,e)=>{if(o.isSynced){c();return}let n=()=>{clearTimeout(s),o.off("synced",a),o.off("authenticationFailed",t);},a=()=>{n(),c();},t=r=>{n(),e(new chunkQA3F5EUJ_cjs.a("initialization-aborted",`authentication failed: ${r.reason}`));},s=setTimeout(()=>{n(),e(new chunkQA3F5EUJ_cjs.a("initialization-timeout"));},d);o.on("synced",a),o.on("authenticationFailed",t);})}async function E(o){let d=chunkLUUFBXJ5_cjs.b(o.roomId),c=o[S]??O,e=new P__namespace.Doc,n=new awareness.Awareness(e),a=()=>c({url:o.url,name:d,document:e,awareness:n,...o.token!==void 0?{token:o.token}:{}}),t=null,s=null;try{o.bootstrap.kind!=="create"&&(t=a(),await F(t,o.syncedTimeoutMs??g)),s=await chunkQA3F5EUJ_cjs.d({ydoc:e,awareness:n,documentId:d,identity:o.identity,bootstrap:o.bootstrap,offlineEditing:o.offlineEditing}),t||(t=a());}catch(i){throw s?.destroy(),t?.destroy(),n.destroy(),e.destroy(),i}let r=t,u=s,l=u.session,f=i=>{l.setTransportStatus(i.status==="connected"?"ready":"disconnected",i.status==="connected"?void 0:"transport-disconnected",i.status==="connected"?void 0:"websocket disconnected");};r.on("status",f);let p=()=>{l.setTransportStatus("error","authentication-failed");};r.on("authenticationFailed",p);let b=false;return Object.freeze({document:u.document,session:l,ydoc:e,provider:r,destroy(){b||(b=true,r.off("status",f),r.off("authenticationFailed",p),u.destroy(),r.destroy(),n.destroy(),e.destroy());}})}Object.defineProperty(exports,"createCollaborationRoomId",{enumerable:true,get:function(){return chunkLUUFBXJ5_cjs.a}});Object.defineProperty(exports,"validateRoomId",{enumerable:true,get:function(){return chunkLUUFBXJ5_cjs.b}});exports.HOCUSPOCUS_PROVIDER_FOR_TESTS=S;exports.createHocuspocusCollaboration=E;
@@ -1 +1 @@
1
- import {b}from'./chunk-6DEUT2RQ.js';export{a as createCollaborationRoomId,b as validateRoomId}from'./chunk-6DEUT2RQ.js';import {d,a}from'./chunk-7QSJBMZV.js';import*as P from'yjs';import {Awareness}from'y-protocols/awareness';import {HocuspocusProvider}from'@hocuspocus/provider';var g=3e4,S=Symbol("createHocuspocusCollaboration.provider"),O=o=>new HocuspocusProvider({url:o.url,name:o.name,document:o.document,awareness:o.awareness,...o.token!==void 0?{token:o.token}:{}});function F(o,d){return new Promise((c,e)=>{if(o.isSynced){c();return}let n=()=>{clearTimeout(s),o.off("synced",a$1),o.off("authenticationFailed",t);},a$1=()=>{n(),c();},t=r=>{n(),e(new a("initialization-aborted",`authentication failed: ${r.reason}`));},s=setTimeout(()=>{n(),e(new a("initialization-timeout"));},d);o.on("synced",a$1),o.on("authenticationFailed",t);})}async function E(o){let d$1=b(o.roomId),c=o[S]??O,e=new P.Doc,n=new Awareness(e),a=()=>c({url:o.url,name:d$1,document:e,awareness:n,...o.token!==void 0?{token:o.token}:{}}),t=null,s=null;try{o.bootstrap.kind!=="create"&&(t=a(),await F(t,o.syncedTimeoutMs??g)),s=await d({ydoc:e,awareness:n,documentId:d$1,identity:o.identity,bootstrap:o.bootstrap,offlineEditing:o.offlineEditing}),t||(t=a());}catch(i){throw s?.destroy(),t?.destroy(),n.destroy(),e.destroy(),i}let r=t,u=s,l=u.session,f=i=>{l.setTransportStatus(i.status==="connected"?"ready":"disconnected",i.status==="connected"?void 0:"transport-disconnected",i.status==="connected"?void 0:"websocket disconnected");};r.on("status",f);let p=()=>{l.setTransportStatus("error","authentication-failed");};r.on("authenticationFailed",p);let b$1=false;return Object.freeze({document:u.document,session:l,ydoc:e,provider:r,destroy(){b$1||(b$1=true,r.off("status",f),r.off("authenticationFailed",p),u.destroy(),r.destroy(),n.destroy(),e.destroy());}})}export{S as HOCUSPOCUS_PROVIDER_FOR_TESTS,E as createHocuspocusCollaboration};
1
+ import {b}from'./chunk-6DEUT2RQ.js';export{a as createCollaborationRoomId,b as validateRoomId}from'./chunk-6DEUT2RQ.js';import {d,a}from'./chunk-DHIPX767.js';import*as P from'yjs';import {Awareness}from'y-protocols/awareness';import {HocuspocusProvider}from'@hocuspocus/provider';var g=3e4,S=Symbol("createHocuspocusCollaboration.provider"),O=o=>new HocuspocusProvider({url:o.url,name:o.name,document:o.document,awareness:o.awareness,...o.token!==void 0?{token:o.token}:{}});function F(o,d){return new Promise((c,e)=>{if(o.isSynced){c();return}let n=()=>{clearTimeout(s),o.off("synced",a$1),o.off("authenticationFailed",t);},a$1=()=>{n(),c();},t=r=>{n(),e(new a("initialization-aborted",`authentication failed: ${r.reason}`));},s=setTimeout(()=>{n(),e(new a("initialization-timeout"));},d);o.on("synced",a$1),o.on("authenticationFailed",t);})}async function E(o){let d$1=b(o.roomId),c=o[S]??O,e=new P.Doc,n=new Awareness(e),a=()=>c({url:o.url,name:d$1,document:e,awareness:n,...o.token!==void 0?{token:o.token}:{}}),t=null,s=null;try{o.bootstrap.kind!=="create"&&(t=a(),await F(t,o.syncedTimeoutMs??g)),s=await d({ydoc:e,awareness:n,documentId:d$1,identity:o.identity,bootstrap:o.bootstrap,offlineEditing:o.offlineEditing}),t||(t=a());}catch(i){throw s?.destroy(),t?.destroy(),n.destroy(),e.destroy(),i}let r=t,u=s,l=u.session,f=i=>{l.setTransportStatus(i.status==="connected"?"ready":"disconnected",i.status==="connected"?void 0:"transport-disconnected",i.status==="connected"?void 0:"websocket disconnected");};r.on("status",f);let p=()=>{l.setTransportStatus("error","authentication-failed");};r.on("authenticationFailed",p);let b$1=false;return Object.freeze({document:u.document,session:l,ydoc:e,provider:r,destroy(){b$1||(b$1=true,r.off("status",f),r.off("authenticationFailed",p),u.destroy(),r.destroy(),n.destroy(),e.destroy());}})}export{S as HOCUSPOCUS_PROVIDER_FOR_TESTS,E as createHocuspocusCollaboration};