@nebutra/collab 0.2.2 → 0.2.4

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/CHANGELOG.md +8 -0
  2. package/README.md +0 -0
  3. package/dist/{chunk-S2HTNEZN.js → chunk-PMIKORQM.js} +1 -1
  4. package/dist/chunk-PMIKORQM.js.map +1 -0
  5. package/dist/index.d.ts +0 -0
  6. package/dist/index.js +3 -3
  7. package/dist/index.js.map +1 -1
  8. package/dist/transport/loopback.d.ts +0 -0
  9. package/dist/transport/loopback.js +1 -1
  10. package/package.json +18 -8
  11. package/.turbo/turbo-build.log +0 -28
  12. package/.turbo/turbo-test.log +0 -14
  13. package/.turbo/turbo-typecheck.log +0 -4
  14. package/coverage/base.css +0 -224
  15. package/coverage/block-navigation.js +0 -87
  16. package/coverage/clover.xml +0 -156
  17. package/coverage/coverage-final.json +0 -7
  18. package/coverage/favicon.png +0 -0
  19. package/coverage/index.html +0 -146
  20. package/coverage/prettify.css +0 -1
  21. package/coverage/prettify.js +0 -2
  22. package/coverage/sort-arrow-sprite.png +0 -0
  23. package/coverage/sorter.js +0 -210
  24. package/coverage/src/errors.ts.html +0 -211
  25. package/coverage/src/hub.ts.html +0 -619
  26. package/coverage/src/index.html +0 -161
  27. package/coverage/src/index.ts.html +0 -211
  28. package/coverage/src/room.ts.html +0 -529
  29. package/coverage/src/store/index.html +0 -116
  30. package/coverage/src/store/memory.ts.html +0 -235
  31. package/coverage/src/transport/index.html +0 -116
  32. package/coverage/src/transport/loopback.ts.html +0 -0
  33. package/dist/chunk-S2HTNEZN.js.map +0 -1
  34. package/examples/snapshot-restore.ts +0 -39
  35. package/examples/tenant-isolation.ts +0 -42
  36. package/examples/zero-config-convergence.ts +0 -43
  37. package/src/__tests__/collab.test.ts +0 -240
  38. package/src/cli.ts +0 -27
  39. package/src/errors.ts +0 -42
  40. package/src/hub.ts +0 -0
  41. package/src/index.ts +0 -42
  42. package/src/room.ts +0 -130
  43. package/src/store/memory.ts +0 -43
  44. package/src/transport/loopback.ts +0 -0
  45. package/src/types.ts +0 -64
  46. package/tsconfig.json +0 -12
  47. package/tsup.config.ts +0 -11
@@ -1,619 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for src/hub.ts</title>
7
- <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../prettify.css" />
9
- <link rel="stylesheet" href="../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
- <meta name="viewport" content="width=device-width, initial-scale=1" />
12
- <style type='text/css'>
13
- .coverage-summary .sorter {
14
- background-image: url(../sort-arrow-sprite.png);
15
- }
16
- </style>
17
- </head>
18
-
19
- <body>
20
- <div class='wrapper'>
21
- <div class='pad1'>
22
- <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> hub.ts</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">92.98% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>53/57</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">79.31% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>23/29</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">90% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>9/10</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">92.72% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>51/55</span>
50
- </div>
51
-
52
-
53
- </div>
54
- <p class="quiet">
55
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
- </p>
57
- <template id="filterTemplate">
58
- <div class="quiet">
59
- Filter:
60
- <input type="search" id="fileSearch">
61
- </div>
62
- </template>
63
- </div>
64
- <div class='status-line high'></div>
65
- <pre><table class="coverage">
66
- <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
- <a name='L2'></a><a href='#L2'>2</a>
68
- <a name='L3'></a><a href='#L3'>3</a>
69
- <a name='L4'></a><a href='#L4'>4</a>
70
- <a name='L5'></a><a href='#L5'>5</a>
71
- <a name='L6'></a><a href='#L6'>6</a>
72
- <a name='L7'></a><a href='#L7'>7</a>
73
- <a name='L8'></a><a href='#L8'>8</a>
74
- <a name='L9'></a><a href='#L9'>9</a>
75
- <a name='L10'></a><a href='#L10'>10</a>
76
- <a name='L11'></a><a href='#L11'>11</a>
77
- <a name='L12'></a><a href='#L12'>12</a>
78
- <a name='L13'></a><a href='#L13'>13</a>
79
- <a name='L14'></a><a href='#L14'>14</a>
80
- <a name='L15'></a><a href='#L15'>15</a>
81
- <a name='L16'></a><a href='#L16'>16</a>
82
- <a name='L17'></a><a href='#L17'>17</a>
83
- <a name='L18'></a><a href='#L18'>18</a>
84
- <a name='L19'></a><a href='#L19'>19</a>
85
- <a name='L20'></a><a href='#L20'>20</a>
86
- <a name='L21'></a><a href='#L21'>21</a>
87
- <a name='L22'></a><a href='#L22'>22</a>
88
- <a name='L23'></a><a href='#L23'>23</a>
89
- <a name='L24'></a><a href='#L24'>24</a>
90
- <a name='L25'></a><a href='#L25'>25</a>
91
- <a name='L26'></a><a href='#L26'>26</a>
92
- <a name='L27'></a><a href='#L27'>27</a>
93
- <a name='L28'></a><a href='#L28'>28</a>
94
- <a name='L29'></a><a href='#L29'>29</a>
95
- <a name='L30'></a><a href='#L30'>30</a>
96
- <a name='L31'></a><a href='#L31'>31</a>
97
- <a name='L32'></a><a href='#L32'>32</a>
98
- <a name='L33'></a><a href='#L33'>33</a>
99
- <a name='L34'></a><a href='#L34'>34</a>
100
- <a name='L35'></a><a href='#L35'>35</a>
101
- <a name='L36'></a><a href='#L36'>36</a>
102
- <a name='L37'></a><a href='#L37'>37</a>
103
- <a name='L38'></a><a href='#L38'>38</a>
104
- <a name='L39'></a><a href='#L39'>39</a>
105
- <a name='L40'></a><a href='#L40'>40</a>
106
- <a name='L41'></a><a href='#L41'>41</a>
107
- <a name='L42'></a><a href='#L42'>42</a>
108
- <a name='L43'></a><a href='#L43'>43</a>
109
- <a name='L44'></a><a href='#L44'>44</a>
110
- <a name='L45'></a><a href='#L45'>45</a>
111
- <a name='L46'></a><a href='#L46'>46</a>
112
- <a name='L47'></a><a href='#L47'>47</a>
113
- <a name='L48'></a><a href='#L48'>48</a>
114
- <a name='L49'></a><a href='#L49'>49</a>
115
- <a name='L50'></a><a href='#L50'>50</a>
116
- <a name='L51'></a><a href='#L51'>51</a>
117
- <a name='L52'></a><a href='#L52'>52</a>
118
- <a name='L53'></a><a href='#L53'>53</a>
119
- <a name='L54'></a><a href='#L54'>54</a>
120
- <a name='L55'></a><a href='#L55'>55</a>
121
- <a name='L56'></a><a href='#L56'>56</a>
122
- <a name='L57'></a><a href='#L57'>57</a>
123
- <a name='L58'></a><a href='#L58'>58</a>
124
- <a name='L59'></a><a href='#L59'>59</a>
125
- <a name='L60'></a><a href='#L60'>60</a>
126
- <a name='L61'></a><a href='#L61'>61</a>
127
- <a name='L62'></a><a href='#L62'>62</a>
128
- <a name='L63'></a><a href='#L63'>63</a>
129
- <a name='L64'></a><a href='#L64'>64</a>
130
- <a name='L65'></a><a href='#L65'>65</a>
131
- <a name='L66'></a><a href='#L66'>66</a>
132
- <a name='L67'></a><a href='#L67'>67</a>
133
- <a name='L68'></a><a href='#L68'>68</a>
134
- <a name='L69'></a><a href='#L69'>69</a>
135
- <a name='L70'></a><a href='#L70'>70</a>
136
- <a name='L71'></a><a href='#L71'>71</a>
137
- <a name='L72'></a><a href='#L72'>72</a>
138
- <a name='L73'></a><a href='#L73'>73</a>
139
- <a name='L74'></a><a href='#L74'>74</a>
140
- <a name='L75'></a><a href='#L75'>75</a>
141
- <a name='L76'></a><a href='#L76'>76</a>
142
- <a name='L77'></a><a href='#L77'>77</a>
143
- <a name='L78'></a><a href='#L78'>78</a>
144
- <a name='L79'></a><a href='#L79'>79</a>
145
- <a name='L80'></a><a href='#L80'>80</a>
146
- <a name='L81'></a><a href='#L81'>81</a>
147
- <a name='L82'></a><a href='#L82'>82</a>
148
- <a name='L83'></a><a href='#L83'>83</a>
149
- <a name='L84'></a><a href='#L84'>84</a>
150
- <a name='L85'></a><a href='#L85'>85</a>
151
- <a name='L86'></a><a href='#L86'>86</a>
152
- <a name='L87'></a><a href='#L87'>87</a>
153
- <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a>
173
- <a name='L108'></a><a href='#L108'>108</a>
174
- <a name='L109'></a><a href='#L109'>109</a>
175
- <a name='L110'></a><a href='#L110'>110</a>
176
- <a name='L111'></a><a href='#L111'>111</a>
177
- <a name='L112'></a><a href='#L112'>112</a>
178
- <a name='L113'></a><a href='#L113'>113</a>
179
- <a name='L114'></a><a href='#L114'>114</a>
180
- <a name='L115'></a><a href='#L115'>115</a>
181
- <a name='L116'></a><a href='#L116'>116</a>
182
- <a name='L117'></a><a href='#L117'>117</a>
183
- <a name='L118'></a><a href='#L118'>118</a>
184
- <a name='L119'></a><a href='#L119'>119</a>
185
- <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a>
187
- <a name='L122'></a><a href='#L122'>122</a>
188
- <a name='L123'></a><a href='#L123'>123</a>
189
- <a name='L124'></a><a href='#L124'>124</a>
190
- <a name='L125'></a><a href='#L125'>125</a>
191
- <a name='L126'></a><a href='#L126'>126</a>
192
- <a name='L127'></a><a href='#L127'>127</a>
193
- <a name='L128'></a><a href='#L128'>128</a>
194
- <a name='L129'></a><a href='#L129'>129</a>
195
- <a name='L130'></a><a href='#L130'>130</a>
196
- <a name='L131'></a><a href='#L131'>131</a>
197
- <a name='L132'></a><a href='#L132'>132</a>
198
- <a name='L133'></a><a href='#L133'>133</a>
199
- <a name='L134'></a><a href='#L134'>134</a>
200
- <a name='L135'></a><a href='#L135'>135</a>
201
- <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a>
217
- <a name='L152'></a><a href='#L152'>152</a>
218
- <a name='L153'></a><a href='#L153'>153</a>
219
- <a name='L154'></a><a href='#L154'>154</a>
220
- <a name='L155'></a><a href='#L155'>155</a>
221
- <a name='L156'></a><a href='#L156'>156</a>
222
- <a name='L157'></a><a href='#L157'>157</a>
223
- <a name='L158'></a><a href='#L158'>158</a>
224
- <a name='L159'></a><a href='#L159'>159</a>
225
- <a name='L160'></a><a href='#L160'>160</a>
226
- <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a>
228
- <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a>
230
- <a name='L165'></a><a href='#L165'>165</a>
231
- <a name='L166'></a><a href='#L166'>166</a>
232
- <a name='L167'></a><a href='#L167'>167</a>
233
- <a name='L168'></a><a href='#L168'>168</a>
234
- <a name='L169'></a><a href='#L169'>169</a>
235
- <a name='L170'></a><a href='#L170'>170</a>
236
- <a name='L171'></a><a href='#L171'>171</a>
237
- <a name='L172'></a><a href='#L172'>172</a>
238
- <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a>
240
- <a name='L175'></a><a href='#L175'>175</a>
241
- <a name='L176'></a><a href='#L176'>176</a>
242
- <a name='L177'></a><a href='#L177'>177</a>
243
- <a name='L178'></a><a href='#L178'>178</a>
244
- <a name='L179'></a><a href='#L179'>179</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
245
- <span class="cline-any cline-neutral">&nbsp;</span>
246
- <span class="cline-any cline-neutral">&nbsp;</span>
247
- <span class="cline-any cline-neutral">&nbsp;</span>
248
- <span class="cline-any cline-neutral">&nbsp;</span>
249
- <span class="cline-any cline-neutral">&nbsp;</span>
250
- <span class="cline-any cline-neutral">&nbsp;</span>
251
- <span class="cline-any cline-neutral">&nbsp;</span>
252
- <span class="cline-any cline-neutral">&nbsp;</span>
253
- <span class="cline-any cline-neutral">&nbsp;</span>
254
- <span class="cline-any cline-neutral">&nbsp;</span>
255
- <span class="cline-any cline-neutral">&nbsp;</span>
256
- <span class="cline-any cline-neutral">&nbsp;</span>
257
- <span class="cline-any cline-neutral">&nbsp;</span>
258
- <span class="cline-any cline-neutral">&nbsp;</span>
259
- <span class="cline-any cline-neutral">&nbsp;</span>
260
- <span class="cline-any cline-neutral">&nbsp;</span>
261
- <span class="cline-any cline-neutral">&nbsp;</span>
262
- <span class="cline-any cline-neutral">&nbsp;</span>
263
- <span class="cline-any cline-neutral">&nbsp;</span>
264
- <span class="cline-any cline-neutral">&nbsp;</span>
265
- <span class="cline-any cline-neutral">&nbsp;</span>
266
- <span class="cline-any cline-neutral">&nbsp;</span>
267
- <span class="cline-any cline-neutral">&nbsp;</span>
268
- <span class="cline-any cline-neutral">&nbsp;</span>
269
- <span class="cline-any cline-neutral">&nbsp;</span>
270
- <span class="cline-any cline-neutral">&nbsp;</span>
271
- <span class="cline-any cline-neutral">&nbsp;</span>
272
- <span class="cline-any cline-neutral">&nbsp;</span>
273
- <span class="cline-any cline-yes">1x</span>
274
- <span class="cline-any cline-neutral">&nbsp;</span>
275
- <span class="cline-any cline-neutral">&nbsp;</span>
276
- <span class="cline-any cline-yes">20x</span>
277
- <span class="cline-any cline-neutral">&nbsp;</span>
278
- <span class="cline-any cline-neutral">&nbsp;</span>
279
- <span class="cline-any cline-neutral">&nbsp;</span>
280
- <span class="cline-any cline-yes">37x</span>
281
- <span class="cline-any cline-yes">1x</span>
282
- <span class="cline-any cline-neutral">&nbsp;</span>
283
- <span class="cline-any cline-neutral">&nbsp;</span>
284
- <span class="cline-any cline-neutral">&nbsp;</span>
285
- <span class="cline-any cline-neutral">&nbsp;</span>
286
- <span class="cline-any cline-neutral">&nbsp;</span>
287
- <span class="cline-any cline-neutral">&nbsp;</span>
288
- <span class="cline-any cline-neutral">&nbsp;</span>
289
- <span class="cline-any cline-neutral">&nbsp;</span>
290
- <span class="cline-any cline-neutral">&nbsp;</span>
291
- <span class="cline-any cline-neutral">&nbsp;</span>
292
- <span class="cline-any cline-neutral">&nbsp;</span>
293
- <span class="cline-any cline-yes">15x</span>
294
- <span class="cline-any cline-neutral">&nbsp;</span>
295
- <span class="cline-any cline-neutral">&nbsp;</span>
296
- <span class="cline-any cline-neutral">&nbsp;</span>
297
- <span class="cline-any cline-neutral">&nbsp;</span>
298
- <span class="cline-any cline-yes">15x</span>
299
- <span class="cline-any cline-yes">15x</span>
300
- <span class="cline-any cline-neutral">&nbsp;</span>
301
- <span class="cline-any cline-neutral">&nbsp;</span>
302
- <span class="cline-any cline-neutral">&nbsp;</span>
303
- <span class="cline-any cline-yes">19x</span>
304
- <span class="cline-any cline-yes">19x</span>
305
- <span class="cline-any cline-yes">19x</span>
306
- <span class="cline-any cline-yes">19x</span>
307
- <span class="cline-any cline-yes">19x</span>
308
- <span class="cline-any cline-yes">16x</span>
309
- <span class="cline-any cline-yes">16x</span>
310
- <span class="cline-any cline-neutral">&nbsp;</span>
311
- <span class="cline-any cline-yes">18x</span>
312
- <span class="cline-any cline-neutral">&nbsp;</span>
313
- <span class="cline-any cline-neutral">&nbsp;</span>
314
- <span class="cline-any cline-neutral">&nbsp;</span>
315
- <span class="cline-any cline-neutral">&nbsp;</span>
316
- <span class="cline-any cline-neutral">&nbsp;</span>
317
- <span class="cline-any cline-neutral">&nbsp;</span>
318
- <span class="cline-any cline-yes">2x</span>
319
- <span class="cline-any cline-yes">2x</span>
320
- <span class="cline-any cline-yes">2x</span>
321
- <span class="cline-any cline-neutral">&nbsp;</span>
322
- <span class="cline-any cline-neutral">&nbsp;</span>
323
- <span class="cline-any cline-yes">2x</span>
324
- <span class="cline-any cline-yes">1x</span>
325
- <span class="cline-any cline-neutral">&nbsp;</span>
326
- <span class="cline-any cline-neutral">&nbsp;</span>
327
- <span class="cline-any cline-neutral">&nbsp;</span>
328
- <span class="cline-any cline-yes">1x</span>
329
- <span class="cline-any cline-neutral">&nbsp;</span>
330
- <span class="cline-any cline-neutral">&nbsp;</span>
331
- <span class="cline-any cline-yes">1x</span>
332
- <span class="cline-any cline-yes">1x</span>
333
- <span class="cline-any cline-yes">1x</span>
334
- <span class="cline-any cline-yes">1x</span>
335
- <span class="cline-any cline-yes">1x</span>
336
- <span class="cline-any cline-yes">1x</span>
337
- <span class="cline-any cline-yes">1x</span>
338
- <span class="cline-any cline-yes">1x</span>
339
- <span class="cline-any cline-yes">1x</span>
340
- <span class="cline-any cline-yes">1x</span>
341
- <span class="cline-any cline-yes">1x</span>
342
- <span class="cline-any cline-neutral">&nbsp;</span>
343
- <span class="cline-any cline-neutral">&nbsp;</span>
344
- <span class="cline-any cline-neutral">&nbsp;</span>
345
- <span class="cline-any cline-neutral">&nbsp;</span>
346
- <span class="cline-any cline-neutral">&nbsp;</span>
347
- <span class="cline-any cline-neutral">&nbsp;</span>
348
- <span class="cline-any cline-no">&nbsp;</span>
349
- <span class="cline-any cline-neutral">&nbsp;</span>
350
- <span class="cline-any cline-neutral">&nbsp;</span>
351
- <span class="cline-any cline-neutral">&nbsp;</span>
352
- <span class="cline-any cline-yes">1x</span>
353
- <span class="cline-any cline-yes">1x</span>
354
- <span class="cline-any cline-yes">1x</span>
355
- <span class="cline-any cline-yes">1x</span>
356
- <span class="cline-any cline-yes">1x</span>
357
- <span class="cline-any cline-yes">1x</span>
358
- <span class="cline-any cline-yes">1x</span>
359
- <span class="cline-any cline-neutral">&nbsp;</span>
360
- <span class="cline-any cline-neutral">&nbsp;</span>
361
- <span class="cline-any cline-neutral">&nbsp;</span>
362
- <span class="cline-any cline-neutral">&nbsp;</span>
363
- <span class="cline-any cline-neutral">&nbsp;</span>
364
- <span class="cline-any cline-neutral">&nbsp;</span>
365
- <span class="cline-any cline-no">&nbsp;</span>
366
- <span class="cline-any cline-neutral">&nbsp;</span>
367
- <span class="cline-any cline-neutral">&nbsp;</span>
368
- <span class="cline-any cline-neutral">&nbsp;</span>
369
- <span class="cline-any cline-yes">1x</span>
370
- <span class="cline-any cline-yes">1x</span>
371
- <span class="cline-any cline-yes">1x</span>
372
- <span class="cline-any cline-yes">1x</span>
373
- <span class="cline-any cline-neutral">&nbsp;</span>
374
- <span class="cline-any cline-neutral">&nbsp;</span>
375
- <span class="cline-any cline-neutral">&nbsp;</span>
376
- <span class="cline-any cline-yes">1x</span>
377
- <span class="cline-any cline-neutral">&nbsp;</span>
378
- <span class="cline-any cline-neutral">&nbsp;</span>
379
- <span class="cline-any cline-yes">1x</span>
380
- <span class="cline-any cline-neutral">&nbsp;</span>
381
- <span class="cline-any cline-neutral">&nbsp;</span>
382
- <span class="cline-any cline-neutral">&nbsp;</span>
383
- <span class="cline-any cline-neutral">&nbsp;</span>
384
- <span class="cline-any cline-yes">1x</span>
385
- <span class="cline-any cline-yes">1x</span>
386
- <span class="cline-any cline-neutral">&nbsp;</span>
387
- <span class="cline-any cline-neutral">&nbsp;</span>
388
- <span class="cline-any cline-neutral">&nbsp;</span>
389
- <span class="cline-any cline-neutral">&nbsp;</span>
390
- <span class="cline-any cline-neutral">&nbsp;</span>
391
- <span class="cline-any cline-neutral">&nbsp;</span>
392
- <span class="cline-any cline-no">&nbsp;</span>
393
- <span class="cline-any cline-neutral">&nbsp;</span>
394
- <span class="cline-any cline-neutral">&nbsp;</span>
395
- <span class="cline-any cline-yes">1x</span>
396
- <span class="cline-any cline-neutral">&nbsp;</span>
397
- <span class="cline-any cline-neutral">&nbsp;</span>
398
- <span class="cline-any cline-neutral">&nbsp;</span>
399
- <span class="cline-any cline-neutral">&nbsp;</span>
400
- <span class="cline-any cline-neutral">&nbsp;</span>
401
- <span class="cline-any cline-neutral">&nbsp;</span>
402
- <span class="cline-any cline-neutral">&nbsp;</span>
403
- <span class="cline-any cline-yes">2x</span>
404
- <span class="cline-any cline-yes">2x</span>
405
- <span class="cline-any cline-neutral">&nbsp;</span>
406
- <span class="cline-any cline-neutral">&nbsp;</span>
407
- <span class="cline-any cline-neutral">&nbsp;</span>
408
- <span class="cline-any cline-neutral">&nbsp;</span>
409
- <span class="cline-any cline-neutral">&nbsp;</span>
410
- <span class="cline-any cline-yes">15x</span>
411
- <span class="cline-any cline-neutral">&nbsp;</span>
412
- <span class="cline-any cline-neutral">&nbsp;</span>
413
- <span class="cline-any cline-neutral">&nbsp;</span>
414
- <span class="cline-any cline-neutral">&nbsp;</span>
415
- <span class="cline-any cline-neutral">&nbsp;</span>
416
- <span class="cline-any cline-neutral">&nbsp;</span>
417
- <span class="cline-any cline-neutral">&nbsp;</span>
418
- <span class="cline-any cline-neutral">&nbsp;</span>
419
- <span class="cline-any cline-neutral">&nbsp;</span>
420
- <span class="cline-any cline-no">&nbsp;</span>
421
- <span class="cline-any cline-neutral">&nbsp;</span>
422
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
423
- * `CollabHub` — the tenant-partition boundary.
424
- *
425
- * TENANT ISOLATION IS STRUCTURAL: rooms are stored in a `Map` keyed by a
426
- * composite `tenantIdroomId` string with a NUL separator that cannot
427
- * appear in a normal id. There is no API that takes only a roomId, so a key
428
- * minted for tenant A is unreachable from tenant B — a room handle is only
429
- * ever produced by passing an explicit `tenantId`, and the snapshot store +
430
- * transport are likewise addressed by (tenantId, roomId). The same property
431
- * a Prisma adapter gets from RLS is enforced here by the composite key, with
432
- * no trust placed in caller-supplied payload.
433
- */
434
- &nbsp;
435
- import { CollabError } from "./errors";
436
- import { Room } from "./room";
437
- import { InMemorySnapshotStore } from "./store/memory";
438
- import { LoopbackTransport } from "./transport/loopback";
439
- import type {
440
- CollabConfig,
441
- CollabHub,
442
- CollabRoom,
443
- CollabTransport,
444
- DoctorReport,
445
- SnapshotStore,
446
- } from "./types";
447
- &nbsp;
448
- // NUL separator: it cannot appear in a normal tenant/room id, so the pairs
449
- // ("a","bc") and ("ab","c") can never collide into the same room key — the
450
- // tenant partition is exact, not merely conventional.
451
- const KEY_SEP = "";
452
- &nbsp;
453
- function roomKey(tenantId: string, roomId: string): string {
454
- return `${tenantId}${KEY_SEP}${roomId}`;
455
- }
456
- &nbsp;
457
- function assertId(value: string, kind: "tenant" | "room"): void {
458
- if (typeof value !== "string" || value.trim().length === 0) {
459
- throw new CollabError(`A non-empty ${kind}Id is required.`, {
460
- code: kind === "tenant" ? "COLLAB_INVALID_TENANT" : <span class="branch-1 cbranch-no" title="branch not covered" >"COLLAB_INVALID_ROOM",</span>
461
- suggestion:
462
- kind === "tenant"
463
- ? "Pass the current tenant id, e.g. from getCurrentTenant().tenantId — " +
464
- "never call room() without an explicit tenant."
465
- : <span class="branch-1 cbranch-no" title="branch not covered" >"Pass a stable, non-empty roomId (document/canvas id).",</span>
466
- });
467
- }
468
- }
469
- &nbsp;
470
- class Hub implements CollabHub {
471
- private readonly rooms = new Map&lt;string, Room&gt;();
472
- private readonly store: SnapshotStore;
473
- private readonly transport: CollabTransport;
474
- &nbsp;
475
- constructor(config: CollabConfig = {}) {
476
- this.store = config.store ?? new InMemorySnapshotStore();
477
- this.transport = config.transport ?? new LoopbackTransport();
478
- }
479
- &nbsp;
480
- room(tenantId: string, roomId: string): CollabRoom {
481
- assertId(tenantId, "tenant");
482
- assertId(roomId, "room");
483
- const key = roomKey(tenantId, roomId);
484
- let room = this.rooms.get(key);
485
- if (!room) {
486
- room = new Room(tenantId, roomId, this.store, this.transport);
487
- this.rooms.set(key, room);
488
- }
489
- return room;
490
- }
491
- &nbsp;
492
- async roomRestored(
493
- tenantId: string,
494
- roomId: string,
495
- ): Promise&lt;CollabRoom&gt; {
496
- const key = roomKey(tenantId, roomId);
497
- const existed = this.rooms.has(key);
498
- const room = this.room(tenantId, roomId) as Room;
499
- // Only hydrate a freshly created room; an already-live room is the
500
- // authoritative in-memory state.
501
- <span class="missing-if-branch" title="else path not taken" >E</span>if (!existed) await room._restore();
502
- return room;
503
- }
504
- &nbsp;
505
- async doctor(): Promise&lt;DoctorReport&gt; {
506
- const start = Date.now();
507
- &nbsp;
508
- // 1. Yjs presence + a real round-trip (not just "is it imported").
509
- let yjs = { ok: false, detail: "" };
510
- try {
511
- const Y = await import("yjs");
512
- const probe = new Y.Doc();
513
- probe.getMap("p").set("k", 1);
514
- const restored = new Y.Doc();
515
- Y.applyUpdate(restored, Y.encodeStateAsUpdate(probe));
516
- const ok = restored.getMap("p").get("k") === 1;
517
- probe.destroy();
518
- restored.destroy();
519
- yjs = {
520
- ok,
521
- detail: ok
522
- ? "Yjs encode/apply round-trip succeeded."
523
- : <span class="branch-1 cbranch-no" title="branch not covered" >"Yjs round-trip produced unexpected state.",</span>
524
- };
525
- } catch (e) {
526
- <span class="cstat-no" title="statement not covered" > yjs = { ok: false, detail: `Yjs unavailable: ${String(e)}` };</span>
527
- }
528
- &nbsp;
529
- // 2. Store health — write+read under a reserved diagnostic tenant.
530
- let store = { ok: false, detail: "" };
531
- try {
532
- const probe = new Uint8Array([7, 7, 7]);
533
- await this.store.save("__collab_doctor__", "__probe__", probe);
534
- const back = await this.store.load("__collab_doctor__", "__probe__");
535
- const ok = !!back &amp;&amp; back.length === probe.length &amp;&amp; back[0] === 7;
536
- store = {
537
- ok,
538
- detail: ok
539
- ? "SnapshotStore save/load round-trip succeeded."
540
- : <span class="branch-1 cbranch-no" title="branch not covered" >"SnapshotStore returned unexpected bytes.",</span>
541
- };
542
- } catch (e) {
543
- <span class="cstat-no" title="statement not covered" > store = { ok: false, detail: `SnapshotStore error: ${String(e)}` };</span>
544
- }
545
- &nbsp;
546
- // 3. Transport health — subscribe, broadcast, observe, unsubscribe.
547
- let transport = { ok: false, detail: "" };
548
- try {
549
- let received = false;
550
- const off = this.transport.subscribe(
551
- "__collab_doctor__",
552
- "__probe__",
553
- () =&gt; {
554
- received = true;
555
- },
556
- );
557
- await this.transport.broadcast(
558
- "__collab_doctor__",
559
- "__probe__",
560
- new Uint8Array([1]),
561
- );
562
- off();
563
- transport = {
564
- ok: received,
565
- detail: received
566
- ? "Transport broadcast/subscribe round-trip succeeded."
567
- : <span class="branch-1 cbranch-no" title="branch not covered" >"Transport did not deliver the probe (network adapter may be async).",</span>
568
- };
569
- } catch (e) {
570
- <span class="cstat-no" title="statement not covered" > transport = { ok: false, detail: `Transport error: ${String(e)}` };</span>
571
- }
572
- &nbsp;
573
- return {
574
- ok: yjs.ok &amp;&amp; store.ok &amp;&amp; transport.ok,
575
- durationMs: Date.now() - start,
576
- checks: { yjs, store, transport },
577
- };
578
- }
579
- &nbsp;
580
- destroy(): void {
581
- for (const room of this.rooms.values()) room.destroy();
582
- this.rooms.clear();
583
- }
584
- }
585
- &nbsp;
586
- /** Synchronous factory. */
587
- export function createCollab(config?: CollabConfig): CollabHub {
588
- return new Hub(config);
589
- }
590
- &nbsp;
591
- /**
592
- * Async factory mirroring other Sailor integration packages. There is no
593
- * env/credential negotiation for the zero-config defaults, so this resolves
594
- * immediately — the async shape is reserved for future credentialed
595
- * store/transport providers without a breaking signature change.
596
- */
597
- export async function <span class="fstat-no" title="function not covered" >getCollab(c</span>onfig?: CollabConfig): Promise&lt;CollabHub&gt; {
598
- <span class="cstat-no" title="statement not covered" > return createCollab(config);</span>
599
- }
600
- &nbsp;</pre></td></tr></table></pre>
601
-
602
- <div class='push'></div><!-- for sticky footer -->
603
- </div><!-- /wrapper -->
604
- <div class='footer quiet pad2 space-top1 center small'>
605
- Code coverage generated by
606
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
607
- at 2026-05-17T09:08:52.337Z
608
- </div>
609
- <script src="../prettify.js"></script>
610
- <script>
611
- window.onload = function () {
612
- prettyPrint();
613
- };
614
- </script>
615
- <script src="../sorter.js"></script>
616
- <script src="../block-navigation.js"></script>
617
- </body>
618
- </html>
619
-