@spooky-sync/core 0.0.1-canary.239 → 0.0.1-canary.240

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 (139) hide show
  1. package/coverage/lcov-report/base.css +224 -0
  2. package/coverage/lcov-report/block-navigation.js +87 -0
  3. package/coverage/lcov-report/favicon.png +0 -0
  4. package/coverage/lcov-report/index.html +476 -0
  5. package/coverage/lcov-report/prettify.css +1 -0
  6. package/coverage/lcov-report/prettify.js +2 -0
  7. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  8. package/coverage/lcov-report/sorter.js +210 -0
  9. package/coverage/lcov-report/src/boot/auth-flip.saga.ts.html +271 -0
  10. package/coverage/lcov-report/src/boot/boot.saga.ts.html +469 -0
  11. package/coverage/lcov-report/src/boot/bucket-switch.saga.ts.html +430 -0
  12. package/coverage/lcov-report/src/boot/index.html +161 -0
  13. package/coverage/lcov-report/src/boot/preload.saga.ts.html +178 -0
  14. package/coverage/lcov-report/src/client/bucket-handle.ts.html +766 -0
  15. package/coverage/lcov-report/src/client/index.html +161 -0
  16. package/coverage/lcov-report/src/client/router.ts.html +367 -0
  17. package/coverage/lcov-report/src/client/runtime.ts.html +940 -0
  18. package/coverage/lcov-report/src/client/sp00ky-client.ts.html +1531 -0
  19. package/coverage/lcov-report/src/events/index.html +116 -0
  20. package/coverage/lcov-report/src/events/index.ts.html +877 -0
  21. package/coverage/lcov-report/src/index.html +146 -0
  22. package/coverage/lcov-report/src/index.ts.html +202 -0
  23. package/coverage/lcov-report/src/kernel/constants.ts.html +247 -0
  24. package/coverage/lcov-report/src/kernel/effects.ts.html +562 -0
  25. package/coverage/lcov-report/src/kernel/events.ts.html +250 -0
  26. package/coverage/lcov-report/src/kernel/index.html +176 -0
  27. package/coverage/lcov-report/src/kernel/interpreter.ts.html +514 -0
  28. package/coverage/lcov-report/src/kernel/saga.ts.html +304 -0
  29. package/coverage/lcov-report/src/modules/app-release/index.html +116 -0
  30. package/coverage/lcov-report/src/modules/app-release/index.ts.html +712 -0
  31. package/coverage/lcov-report/src/modules/auth/events/index.html +116 -0
  32. package/coverage/lcov-report/src/modules/auth/events/index.ts.html +142 -0
  33. package/coverage/lcov-report/src/modules/auth/index.html +116 -0
  34. package/coverage/lcov-report/src/modules/auth/index.ts.html +1225 -0
  35. package/coverage/lcov-report/src/modules/crdt/crdt-field.ts.html +967 -0
  36. package/coverage/lcov-report/src/modules/crdt/index.html +146 -0
  37. package/coverage/lcov-report/src/modules/crdt/index.ts.html +1474 -0
  38. package/coverage/lcov-report/src/modules/crdt/loro-loader.ts.html +160 -0
  39. package/coverage/lcov-report/src/modules/devtools/flags.ts.html +1132 -0
  40. package/coverage/lcov-report/src/modules/devtools/index.html +161 -0
  41. package/coverage/lcov-report/src/modules/devtools/index.ts.html +2413 -0
  42. package/coverage/lcov-report/src/modules/devtools/storage-info.ts.html +589 -0
  43. package/coverage/lcov-report/src/modules/devtools/versions.ts.html +415 -0
  44. package/coverage/lcov-report/src/modules/feature-flag/index.html +116 -0
  45. package/coverage/lcov-report/src/modules/feature-flag/index.ts.html +1033 -0
  46. package/coverage/lcov-report/src/modules/index.html +116 -0
  47. package/coverage/lcov-report/src/modules/ref-tables.ts.html +349 -0
  48. package/coverage/lcov-report/src/mutation/index.html +191 -0
  49. package/coverage/lcov-report/src/mutation/jobs.ts.html +208 -0
  50. package/coverage/lcov-report/src/mutation/mutation-id.ts.html +190 -0
  51. package/coverage/lcov-report/src/mutation/push.saga.ts.html +730 -0
  52. package/coverage/lcov-report/src/mutation/rows.ts.html +1216 -0
  53. package/coverage/lcov-report/src/mutation/tray.saga.ts.html +229 -0
  54. package/coverage/lcov-report/src/mutation/write.saga.ts.html +583 -0
  55. package/coverage/lcov-report/src/otel/index.html +116 -0
  56. package/coverage/lcov-report/src/otel/index.ts.html +466 -0
  57. package/coverage/lcov-report/src/query/env.ts.html +253 -0
  58. package/coverage/lcov-report/src/query/fetch.saga.ts.html +412 -0
  59. package/coverage/lcov-report/src/query/hash.ts.html +139 -0
  60. package/coverage/lcov-report/src/query/index.html +281 -0
  61. package/coverage/lcov-report/src/query/lifecycle.saga.ts.html +388 -0
  62. package/coverage/lcov-report/src/query/materialize.saga.ts.html +310 -0
  63. package/coverage/lcov-report/src/query/materialize.ts.html +217 -0
  64. package/coverage/lcov-report/src/query/membership.saga.ts.html +709 -0
  65. package/coverage/lcov-report/src/query/membership.ts.html +559 -0
  66. package/coverage/lcov-report/src/query/register.saga.ts.html +655 -0
  67. package/coverage/lcov-report/src/query/render-set.ts.html +265 -0
  68. package/coverage/lcov-report/src/query/sql.ts.html +322 -0
  69. package/coverage/lcov-report/src/query/window-query.ts.html +670 -0
  70. package/coverage/lcov-report/src/services/blobs/blob-cache.ts.html +1894 -0
  71. package/coverage/lcov-report/src/services/blobs/blob-manifest.ts.html +766 -0
  72. package/coverage/lcov-report/src/services/blobs/blob-store.ts.html +1162 -0
  73. package/coverage/lcov-report/src/services/blobs/index.html +161 -0
  74. package/coverage/lcov-report/src/services/blobs/index.ts.html +295 -0
  75. package/coverage/lcov-report/src/services/database/cache-engine.ts.html +664 -0
  76. package/coverage/lcov-report/src/services/database/connection-supervisor.ts.html +1330 -0
  77. package/coverage/lcov-report/src/services/database/database.ts.html +658 -0
  78. package/coverage/lcov-report/src/services/database/engine-factory.ts.html +184 -0
  79. package/coverage/lcov-report/src/services/database/errors.ts.html +187 -0
  80. package/coverage/lcov-report/src/services/database/events/index.html +116 -0
  81. package/coverage/lcov-report/src/services/database/events/index.ts.html +184 -0
  82. package/coverage/lcov-report/src/services/database/index.html +386 -0
  83. package/coverage/lcov-report/src/services/database/index.ts.html +121 -0
  84. package/coverage/lcov-report/src/services/database/local-migrator.ts.html +703 -0
  85. package/coverage/lcov-report/src/services/database/local.ts.html +1633 -0
  86. package/coverage/lcov-report/src/services/database/plan-render.ts.html +409 -0
  87. package/coverage/lcov-report/src/services/database/relation-resolver.ts.html +682 -0
  88. package/coverage/lcov-report/src/services/database/remote.ts.html +1036 -0
  89. package/coverage/lcov-report/src/services/database/sqlite-cache-engine.ts.html +4132 -0
  90. package/coverage/lcov-report/src/services/database/sqlite-lock-verify.ts.html +220 -0
  91. package/coverage/lcov-report/src/services/database/sqlite-open.ts.html +577 -0
  92. package/coverage/lcov-report/src/services/database/sqlite-plan-sql.ts.html +499 -0
  93. package/coverage/lcov-report/src/services/database/sqlite-select.ts.html +478 -0
  94. package/coverage/lcov-report/src/services/database/sqlite-transport.ts.html +757 -0
  95. package/coverage/lcov-report/src/services/database/surql-translate.ts.html +1333 -0
  96. package/coverage/lcov-report/src/services/database/surreal-cache-engine.ts.html +568 -0
  97. package/coverage/lcov-report/src/services/logger/index.html +116 -0
  98. package/coverage/lcov-report/src/services/logger/index.ts.html +154 -0
  99. package/coverage/lcov-report/src/services/persistence/index.html +146 -0
  100. package/coverage/lcov-report/src/services/persistence/localstorage.ts.html +163 -0
  101. package/coverage/lcov-report/src/services/persistence/resilient.ts.html +208 -0
  102. package/coverage/lcov-report/src/services/persistence/surrealdb.ts.html +271 -0
  103. package/coverage/lcov-report/src/services/stream-processor/index.html +146 -0
  104. package/coverage/lcov-report/src/services/stream-processor/index.ts.html +3313 -0
  105. package/coverage/lcov-report/src/services/stream-processor/permissions.ts.html +244 -0
  106. package/coverage/lcov-report/src/services/stream-processor/wasm-types.ts.html +346 -0
  107. package/coverage/lcov-report/src/services/tabs/broker-client.ts.html +934 -0
  108. package/coverage/lcov-report/src/services/tabs/coordinator.ts.html +1984 -0
  109. package/coverage/lcov-report/src/services/tabs/index.html +191 -0
  110. package/coverage/lcov-report/src/services/tabs/leader-locks.ts.html +310 -0
  111. package/coverage/lcov-report/src/services/tabs/protocol.ts.html +871 -0
  112. package/coverage/lcov-report/src/services/tabs/support.ts.html +193 -0
  113. package/coverage/lcov-report/src/services/tabs/tabs-broker-worker.ts.html +2005 -0
  114. package/coverage/lcov-report/src/sp00ky.ts.html +100 -0
  115. package/coverage/lcov-report/src/state/client-state.ts.html +637 -0
  116. package/coverage/lcov-report/src/state/index.html +161 -0
  117. package/coverage/lcov-report/src/state/lifecycle.ts.html +343 -0
  118. package/coverage/lcov-report/src/state/reducers.ts.html +1471 -0
  119. package/coverage/lcov-report/src/state/selectors.ts.html +637 -0
  120. package/coverage/lcov-report/src/sync/connection.saga.ts.html +343 -0
  121. package/coverage/lcov-report/src/sync/index.html +176 -0
  122. package/coverage/lcov-report/src/sync/live.saga.ts.html +232 -0
  123. package/coverage/lcov-report/src/sync/policy.ts.html +1606 -0
  124. package/coverage/lcov-report/src/sync/poll.saga.ts.html +193 -0
  125. package/coverage/lcov-report/src/sync/tabs.saga.ts.html +361 -0
  126. package/coverage/lcov-report/src/types.ts.html +2419 -0
  127. package/coverage/lcov-report/src/utils/blurhash.ts.html +355 -0
  128. package/coverage/lcov-report/src/utils/error-classification.ts.html +244 -0
  129. package/coverage/lcov-report/src/utils/index.html +191 -0
  130. package/coverage/lcov-report/src/utils/index.ts.html +820 -0
  131. package/coverage/lcov-report/src/utils/parser.ts.html +313 -0
  132. package/coverage/lcov-report/src/utils/semver.ts.html +175 -0
  133. package/coverage/lcov-report/src/utils/surql.ts.html +667 -0
  134. package/coverage/lcov.info +19079 -0
  135. package/dist/index.js +3 -3
  136. package/dist/sqlite-open.js +20 -1
  137. package/package.json +3 -3
  138. package/src/services/database/relation-resolver.test.ts +55 -1
  139. package/src/services/database/relation-resolver.ts +0 -0
@@ -0,0 +1,766 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/services/blobs/blob-manifest.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/services/blobs</a> blob-manifest.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">89.47% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>136/152</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">70.58% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>36/51</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'>18/20</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">89.47% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>136/152</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>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</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-neutral">&nbsp;</span>
299
+ <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
304
+ <span class="cline-any cline-neutral">&nbsp;</span>
305
+ <span class="cline-any cline-neutral">&nbsp;</span>
306
+ <span class="cline-any cline-neutral">&nbsp;</span>
307
+ <span class="cline-any cline-neutral">&nbsp;</span>
308
+ <span class="cline-any cline-neutral">&nbsp;</span>
309
+ <span class="cline-any cline-neutral">&nbsp;</span>
310
+ <span class="cline-any cline-neutral">&nbsp;</span>
311
+ <span class="cline-any cline-neutral">&nbsp;</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-yes">1x</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-neutral">&nbsp;</span>
319
+ <span class="cline-any cline-neutral">&nbsp;</span>
320
+ <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
324
+ <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</span>
329
+ <span class="cline-any cline-neutral">&nbsp;</span>
330
+ <span class="cline-any cline-yes">1x</span>
331
+ <span class="cline-any cline-no">&nbsp;</span>
332
+ <span class="cline-any cline-no">&nbsp;</span>
333
+ <span class="cline-any cline-neutral">&nbsp;</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-yes">1x</span>
343
+ <span class="cline-any cline-yes">1x</span>
344
+ <span class="cline-any cline-yes">1x</span>
345
+ <span class="cline-any cline-yes">1x</span>
346
+ <span class="cline-any cline-yes">1x</span>
347
+ <span class="cline-any cline-yes">1x</span>
348
+ <span class="cline-any cline-yes">1x</span>
349
+ <span class="cline-any cline-yes">1x</span>
350
+ <span class="cline-any cline-neutral">&nbsp;</span>
351
+ <span class="cline-any cline-yes">11x</span>
352
+ <span class="cline-any cline-yes">11x</span>
353
+ <span class="cline-any cline-yes">11x</span>
354
+ <span class="cline-any cline-yes">11x</span>
355
+ <span class="cline-any cline-yes">11x</span>
356
+ <span class="cline-any cline-yes">11x</span>
357
+ <span class="cline-any cline-yes">11x</span>
358
+ <span class="cline-any cline-yes">11x</span>
359
+ <span class="cline-any cline-yes">11x</span>
360
+ <span class="cline-any cline-yes">11x</span>
361
+ <span class="cline-any cline-yes">11x</span>
362
+ <span class="cline-any cline-yes">11x</span>
363
+ <span class="cline-any cline-neutral">&nbsp;</span>
364
+ <span class="cline-any cline-yes">1x</span>
365
+ <span class="cline-any cline-yes">24x</span>
366
+ <span class="cline-any cline-neutral">&nbsp;</span>
367
+ <span class="cline-any cline-yes">24x</span>
368
+ <span class="cline-any cline-yes">24x</span>
369
+ <span class="cline-any cline-yes">24x</span>
370
+ <span class="cline-any cline-neutral">&nbsp;</span>
371
+ <span class="cline-any cline-yes">24x</span>
372
+ <span class="cline-any cline-neutral">&nbsp;</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-neutral">&nbsp;</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">24x</span>
380
+ <span class="cline-any cline-yes">6x</span>
381
+ <span class="cline-any cline-yes">6x</span>
382
+ <span class="cline-any cline-yes">6x</span>
383
+ <span class="cline-any cline-yes">6x</span>
384
+ <span class="cline-any cline-yes">5x</span>
385
+ <span class="cline-any cline-yes">5x</span>
386
+ <span class="cline-any cline-yes">5x</span>
387
+ <span class="cline-any cline-yes">5x</span>
388
+ <span class="cline-any cline-yes">5x</span>
389
+ <span class="cline-any cline-yes">5x</span>
390
+ <span class="cline-any cline-yes">6x</span>
391
+ <span class="cline-any cline-yes">1x</span>
392
+ <span class="cline-any cline-yes">1x</span>
393
+ <span class="cline-any cline-yes">6x</span>
394
+ <span class="cline-any cline-yes">1x</span>
395
+ <span class="cline-any cline-yes">1x</span>
396
+ <span class="cline-any cline-yes">1x</span>
397
+ <span class="cline-any cline-yes">1x</span>
398
+ <span class="cline-any cline-yes">1x</span>
399
+ <span class="cline-any cline-yes">6x</span>
400
+ <span class="cline-any cline-neutral">&nbsp;</span>
401
+ <span class="cline-any cline-yes">24x</span>
402
+ <span class="cline-any cline-yes">8x</span>
403
+ <span class="cline-any cline-yes">8x</span>
404
+ <span class="cline-any cline-neutral">&nbsp;</span>
405
+ <span class="cline-any cline-yes">24x</span>
406
+ <span class="cline-any cline-yes">181x</span>
407
+ <span class="cline-any cline-yes">181x</span>
408
+ <span class="cline-any cline-neutral">&nbsp;</span>
409
+ <span class="cline-any cline-yes">24x</span>
410
+ <span class="cline-any cline-yes">15x</span>
411
+ <span class="cline-any cline-yes">15x</span>
412
+ <span class="cline-any cline-neutral">&nbsp;</span>
413
+ <span class="cline-any cline-yes">24x</span>
414
+ <span class="cline-any cline-yes">95x</span>
415
+ <span class="cline-any cline-yes">95x</span>
416
+ <span class="cline-any cline-yes">95x</span>
417
+ <span class="cline-any cline-yes">95x</span>
418
+ <span class="cline-any cline-neutral">&nbsp;</span>
419
+ <span class="cline-any cline-yes">24x</span>
420
+ <span class="cline-any cline-yes">6x</span>
421
+ <span class="cline-any cline-yes">6x</span>
422
+ <span class="cline-any cline-yes">6x</span>
423
+ <span class="cline-any cline-yes">6x</span>
424
+ <span class="cline-any cline-neutral">&nbsp;</span>
425
+ <span class="cline-any cline-yes">24x</span>
426
+ <span class="cline-any cline-yes">84x</span>
427
+ <span class="cline-any cline-yes">84x</span>
428
+ <span class="cline-any cline-yes">84x</span>
429
+ <span class="cline-any cline-yes">84x</span>
430
+ <span class="cline-any cline-neutral">&nbsp;</span>
431
+ <span class="cline-any cline-yes">24x</span>
432
+ <span class="cline-any cline-yes">15x</span>
433
+ <span class="cline-any cline-yes">15x</span>
434
+ <span class="cline-any cline-yes">15x</span>
435
+ <span class="cline-any cline-yes">15x</span>
436
+ <span class="cline-any cline-yes">15x</span>
437
+ <span class="cline-any cline-yes">15x</span>
438
+ <span class="cline-any cline-neutral">&nbsp;</span>
439
+ <span class="cline-any cline-yes">24x</span>
440
+ <span class="cline-any cline-no">&nbsp;</span>
441
+ <span class="cline-any cline-no">&nbsp;</span>
442
+ <span class="cline-any cline-no">&nbsp;</span>
443
+ <span class="cline-any cline-no">&nbsp;</span>
444
+ <span class="cline-any cline-no">&nbsp;</span>
445
+ <span class="cline-any cline-no">&nbsp;</span>
446
+ <span class="cline-any cline-neutral">&nbsp;</span>
447
+ <span class="cline-any cline-yes">24x</span>
448
+ <span class="cline-any cline-yes">12x</span>
449
+ <span class="cline-any cline-yes">11x</span>
450
+ <span class="cline-any cline-yes">11x</span>
451
+ <span class="cline-any cline-yes">12x</span>
452
+ <span class="cline-any cline-neutral">&nbsp;</span>
453
+ <span class="cline-any cline-neutral">&nbsp;</span>
454
+ <span class="cline-any cline-neutral">&nbsp;</span>
455
+ <span class="cline-any cline-yes">24x</span>
456
+ <span class="cline-any cline-yes">6x</span>
457
+ <span class="cline-any cline-yes">6x</span>
458
+ <span class="cline-any cline-yes">6x</span>
459
+ <span class="cline-any cline-yes">6x</span>
460
+ <span class="cline-any cline-neutral">&nbsp;</span>
461
+ <span class="cline-any cline-yes">24x</span>
462
+ <span class="cline-any cline-yes">14x</span>
463
+ <span class="cline-any cline-yes">14x</span>
464
+ <span class="cline-any cline-neutral">&nbsp;</span>
465
+ <span class="cline-any cline-neutral">&nbsp;</span>
466
+ <span class="cline-any cline-neutral">&nbsp;</span>
467
+ <span class="cline-any cline-neutral">&nbsp;</span>
468
+ <span class="cline-any cline-neutral">&nbsp;</span>
469
+ <span class="cline-any cline-neutral">&nbsp;</span>
470
+ <span class="cline-any cline-neutral">&nbsp;</span>
471
+ <span class="cline-any cline-yes">24x</span>
472
+ <span class="cline-any cline-yes">14x</span>
473
+ <span class="cline-any cline-yes">14x</span>
474
+ <span class="cline-any cline-yes">12x</span>
475
+ <span class="cline-any cline-yes">12x</span>
476
+ <span class="cline-any cline-yes">12x</span>
477
+ <span class="cline-any cline-yes">12x</span>
478
+ <span class="cline-any cline-yes">12x</span>
479
+ <span class="cline-any cline-yes">12x</span>
480
+ <span class="cline-any cline-yes">12x</span>
481
+ <span class="cline-any cline-yes">14x</span>
482
+ <span class="cline-any cline-neutral">&nbsp;</span>
483
+ <span class="cline-any cline-yes">24x</span>
484
+ <span class="cline-any cline-yes">12x</span>
485
+ <span class="cline-any cline-yes">12x</span>
486
+ <span class="cline-any cline-yes">12x</span>
487
+ <span class="cline-any cline-yes">12x</span>
488
+ <span class="cline-any cline-yes">12x</span>
489
+ <span class="cline-any cline-yes">11x</span>
490
+ <span class="cline-any cline-yes">11x</span>
491
+ <span class="cline-any cline-yes">11x</span>
492
+ <span class="cline-any cline-neutral">&nbsp;</span>
493
+ <span class="cline-any cline-neutral">&nbsp;</span>
494
+ <span class="cline-any cline-neutral">&nbsp;</span>
495
+ <span class="cline-any cline-yes">11x</span>
496
+ <span class="cline-any cline-yes">11x</span>
497
+ <span class="cline-any cline-neutral">&nbsp;</span>
498
+ <span class="cline-any cline-no">&nbsp;</span>
499
+ <span class="cline-any cline-yes">11x</span>
500
+ <span class="cline-any cline-yes">12x</span>
501
+ <span class="cline-any cline-yes">1x</span>
502
+ <span class="cline-any cline-yes">1x</span>
503
+ <span class="cline-any cline-yes">1x</span>
504
+ <span class="cline-any cline-neutral">&nbsp;</span>
505
+ <span class="cline-any cline-no">&nbsp;</span>
506
+ <span class="cline-any cline-yes">1x</span>
507
+ <span class="cline-any cline-yes">12x</span>
508
+ <span class="cline-any cline-yes">24x</span>
509
+ <span class="cline-any cline-neutral">&nbsp;</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-yes">1x</span>
512
+ <span class="cline-any cline-yes">1x</span>
513
+ <span class="cline-any cline-yes">1x</span>
514
+ <span class="cline-any cline-no">&nbsp;</span>
515
+ <span class="cline-any cline-no">&nbsp;</span>
516
+ <span class="cline-any cline-no">&nbsp;</span>
517
+ <span class="cline-any cline-no">&nbsp;</span>
518
+ <span class="cline-any cline-no">&nbsp;</span>
519
+ <span class="cline-any cline-no">&nbsp;</span>
520
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { RecordId } from 'surrealdb';
521
+ import type { LocalStore, Row } from '../database/cache-engine';
522
+ import type { BlobKey } from './blob-store';
523
+ import { blobKeyId } from './blob-store';
524
+ &nbsp;
525
+ /**
526
+ * Metadata index for the blob cache, persisted in the `_00_blob` table of the
527
+ * local engine.
528
+ *
529
+ * The manifest is deliberately NOT the source of truth for existence — OPFS is.
530
+ * Several existing recovery paths destroy the local store while leaving OPFS
531
+ * intact (the SQLite leader's wipe-on-pool-open, the memory fallback when OPFS
532
+ * refuses to open for SQLite, IndexedDB corruption recovery on the SurrealDB
533
+ * engine). Treating the manifest as an index that `reconcile()` can rebuild
534
+ * from a directory walk means those paths cost metadata, not the offline cache.
535
+ *
536
+ * Runtime reads hit the in-memory map; writes are batched. `lastAccess` changes
537
+ * on every single cache hit, so flushing each one would turn an image render
538
+ * into a local-DB write.
539
+ */
540
+ &nbsp;
541
+ export const BLOB_TABLE = '_00_blob';
542
+ &nbsp;
543
+ export interface BlobEntry {
544
+ /** `${bucket}/${path}` — also the `_00_blob` row id. */
545
+ id: string;
546
+ bucket: string;
547
+ path: string;
548
+ size: number;
549
+ contentType: string;
550
+ createdAt: number;
551
+ lastAccess: number;
552
+ hits: number;
553
+ /** Exempt from pressure eviction. Never expires on its own. */
554
+ pinned: boolean;
555
+ }
556
+ &nbsp;
557
+ export <span class="fstat-no" title="function not covered" >function entryKey(entry: BlobEntry): BlobKey {</span>
558
+ <span class="cstat-no" title="statement not covered" > return { bucket: entry.bucket, path: entry.path };</span>
559
+ <span class="cstat-no" title="statement not covered" >}</span>
560
+ &nbsp;
561
+ function rowToEntry(id: string, row: Row): BlobEntry | null {
562
+ const bucket = typeof row.bucket === 'string' ? row.<span class="branch-0 cbranch-no" title="branch not covered" >bucket : '';</span>
563
+ const path = typeof row.path === 'string' ? row.<span class="branch-0 cbranch-no" title="branch not covered" >path : '';</span>
564
+ if (!bucket || !path) <span class="branch-0 cbranch-no" title="branch not covered" >return null;</span>
565
+ return {
566
+ id,
567
+ bucket,
568
+ path,
569
+ size: Number(row.size<span class="branch-0 cbranch-no" title="branch not covered" >) || 0,</span>
570
+ contentType: typeof row.contentType === 'string' ? row.<span class="branch-0 cbranch-no" title="branch not covered" >contentType : '',</span>
571
+ createdAt: Number(row.createdAt<span class="branch-0 cbranch-no" title="branch not covered" >) || 0,</span>
572
+ lastAccess: Number(row.lastAccess<span class="branch-0 cbranch-no" title="branch not covered" >) || 0,</span>
573
+ hits: Number(row.hits<span class="branch-0 cbranch-no" title="branch not covered" >) || 0,</span>
574
+ pinned: row.pinned === true,
575
+ };
576
+ }
577
+ &nbsp;
578
+ function entryToRow(entry: BlobEntry): Row {
579
+ return {
580
+ bucket: entry.bucket,
581
+ path: entry.path,
582
+ size: entry.size,
583
+ contentType: entry.contentType,
584
+ createdAt: entry.createdAt,
585
+ lastAccess: entry.lastAccess,
586
+ hits: entry.hits,
587
+ pinned: entry.pinned,
588
+ };
589
+ }
590
+ &nbsp;
591
+ export class BlobManifest {
592
+ private entries = new Map&lt;string, BlobEntry&gt;();
593
+ /** Ids whose in-memory state has not been written back yet. */
594
+ private dirty = new Set&lt;string&gt;();
595
+ private removed = new Set&lt;string&gt;();
596
+ private flushing: Promise&lt;void&gt; | null = null;
597
+ &nbsp;
598
+ constructor(private local: LocalStore) {}
599
+ &nbsp;
600
+ /**
601
+ * Hydrate from the rows matching `keys`. Ids come from the OPFS listing, so
602
+ * this never needs a full-table scan (and therefore never needs a QueryPlan).
603
+ * Any read failure yields an empty manifest: reconcile then rebuilds every
604
+ * row from disk, which is exactly the desired degradation.
605
+ */
606
+ async load(ids: string[]): Promise&lt;void&gt; {
607
+ this.entries.clear();
608
+ this.dirty.clear();
609
+ this.removed.clear();
610
+ if (ids.length === 0) return;
611
+ let rows: Row[] = [];
612
+ try {
613
+ rows = await this.local.selectByIds(
614
+ BLOB_TABLE,
615
+ ids.map((id) =&gt; new RecordId(BLOB_TABLE, id))
616
+ );
617
+ } catch {
618
+ return;
619
+ }
620
+ for (const row of rows) {
621
+ const id = readRowId(row);
622
+ if (!id) <span class="branch-0 cbranch-no" title="branch not covered" >continue;</span>
623
+ const entry = rowToEntry(id, row);
624
+ if (entry) this.entries.set(id, entry);
625
+ }
626
+ }
627
+ &nbsp;
628
+ get(key: BlobKey): BlobEntry | undefined {
629
+ return this.entries.get(blobKeyId(key));
630
+ }
631
+ &nbsp;
632
+ getById(id: string): BlobEntry | undefined {
633
+ return this.entries.get(id);
634
+ }
635
+ &nbsp;
636
+ all(): BlobEntry[] {
637
+ return [...this.entries.values()];
638
+ }
639
+ &nbsp;
640
+ totalBytes(): number {
641
+ let total = 0;
642
+ for (const entry of this.entries.values()) total += entry.size;
643
+ return total;
644
+ }
645
+ &nbsp;
646
+ pinnedBytes(): number {
647
+ let total = 0;
648
+ for (const entry of this.entries.values()) if (entry.pinned) total += entry.size;
649
+ return total;
650
+ }
651
+ &nbsp;
652
+ put(entry: BlobEntry): void {
653
+ this.entries.set(entry.id, entry);
654
+ this.removed.delete(entry.id);
655
+ this.dirty.add(entry.id);
656
+ }
657
+ &nbsp;
658
+ touch(id: string, now: number): void {
659
+ const entry = this.entries.get(id);
660
+ if (!entry) <span class="branch-0 cbranch-no" title="branch not covered" >return;</span>
661
+ entry.lastAccess = now;
662
+ entry.hits += 1;
663
+ this.dirty.add(id);
664
+ }
665
+ &nbsp;
666
+ <span class="fstat-no" title="function not covered" > setPinned(id: string, pinned: boolean): boolean {</span>
667
+ <span class="cstat-no" title="statement not covered" > const entry = this.entries.get(id);</span>
668
+ <span class="cstat-no" title="statement not covered" > if (!entry || entry.pinned === pinned) return false;</span>
669
+ <span class="cstat-no" title="statement not covered" > entry.pinned = pinned;</span>
670
+ <span class="cstat-no" title="statement not covered" > this.dirty.add(id);</span>
671
+ <span class="cstat-no" title="statement not covered" > return true;</span>
672
+ <span class="cstat-no" title="statement not covered" > }</span>
673
+ &nbsp;
674
+ remove(id: string): void {
675
+ if (!this.entries.delete(id)) return;
676
+ this.dirty.delete(id);
677
+ this.removed.add(id);
678
+ }
679
+ &nbsp;
680
+ /** Forget everything without scheduling deletes — for a bucket switch, where
681
+ * the rows belong to the store we are leaving and must stay put. */
682
+ reset(): void {
683
+ this.entries.clear();
684
+ this.dirty.clear();
685
+ this.removed.clear();
686
+ }
687
+ &nbsp;
688
+ hasPendingWrites(): boolean {
689
+ return this.dirty.size &gt; 0 || this.removed.size &gt; 0;
690
+ }
691
+ &nbsp;
692
+ /**
693
+ * Write back pending changes. Serialized: a second concurrent flush awaits
694
+ * the first rather than racing it into the same rows. Failures are swallowed
695
+ * on purpose — a lost metadata write costs an LRU timestamp, and the entry is
696
+ * rebuilt from disk on the next reconcile.
697
+ */
698
+ async flush(): Promise&lt;void&gt; {
699
+ if (this.flushing) <span class="branch-0 cbranch-no" title="branch not covered" >return this.flushing;</span>
700
+ if (!this.hasPendingWrites()) return;
701
+ const run = this.doFlush();
702
+ this.flushing = run;
703
+ try {
704
+ await run;
705
+ } finally {
706
+ this.flushing = null;
707
+ }
708
+ }
709
+ &nbsp;
710
+ private async doFlush(): Promise&lt;void&gt; {
711
+ const dirty = [...this.dirty];
712
+ const removed = [...this.removed];
713
+ this.dirty.clear();
714
+ this.removed.clear();
715
+ for (const id of dirty) {
716
+ const entry = this.entries.get(id);
717
+ if (!entry) <span class="branch-0 cbranch-no" title="branch not covered" >continue;</span>
718
+ try {
719
+ // A RecordId, never a bare string: the SurrealDB engine binds the id
720
+ // verbatim and `UPSERT &lt;string&gt;` is an InternalError, so a string id
721
+ // silently never lands (see the same note on `_00_preload`).
722
+ await this.local.upsert(BLOB_TABLE, new RecordId(BLOB_TABLE, id), entryToRow(entry), 'replace');
723
+ <span class="branch-0 cbranch-no" title="branch not covered" > } catch {</span>
724
+ /* metadata only — rebuilt from disk on the next reconcile */
725
+ <span class="cstat-no" title="statement not covered" > }</span>
726
+ }
727
+ for (const id of removed) {
728
+ try {
729
+ await this.local.delete(BLOB_TABLE, new RecordId(BLOB_TABLE, id));
730
+ <span class="branch-0 cbranch-no" title="branch not covered" > } catch {</span>
731
+ /* a surviving row with no file is dropped by the next reconcile */
732
+ <span class="cstat-no" title="statement not covered" > }</span>
733
+ }
734
+ }
735
+ }
736
+ &nbsp;
737
+ /** Row ids come back as a `RecordId` (SurrealDB) or a `table:id` string (SQLite). */
738
+ function readRowId(row: Row): string | null {
739
+ const raw = row.id;
740
+ if (raw instanceof RecordId) return String(raw.id<span class="branch-0 cbranch-no" title="branch not covered" >);</span>
741
+ <span class="cstat-no" title="statement not covered" > if (typeof raw === 'string') {</span>
742
+ <span class="cstat-no" title="statement not covered" > const prefix = `${BLOB_TABLE}:`;</span>
743
+ <span class="cstat-no" title="statement not covered" > return raw.startsWith(prefix) ? raw.slice(prefix.length) : raw;</span>
744
+ <span class="cstat-no" title="statement not covered" > }</span>
745
+ <span class="cstat-no" title="statement not covered" > return null;</span>
746
+ <span class="cstat-no" title="statement not covered" >}</span>
747
+ &nbsp;</pre></td></tr></table></pre>
748
+
749
+ <div class='push'></div><!-- for sticky footer -->
750
+ </div><!-- /wrapper -->
751
+ <div class='footer quiet pad2 space-top1 center small'>
752
+ Code coverage generated by
753
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
754
+ at 2026-09-09T09:49:51.780Z
755
+ </div>
756
+ <script src="../../../prettify.js"></script>
757
+ <script>
758
+ window.onload = function () {
759
+ prettyPrint();
760
+ };
761
+ </script>
762
+ <script src="../../../sorter.js"></script>
763
+ <script src="../../../block-navigation.js"></script>
764
+ </body>
765
+ </html>
766
+