@milaboratories/pl-model-common 1.25.1 → 1.25.3

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 (288) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  2. package/dist/author_marker.d.ts +9 -6
  3. package/dist/base32_encode.cjs +40 -46
  4. package/dist/base32_encode.cjs.map +1 -1
  5. package/dist/base32_encode.js +40 -45
  6. package/dist/base32_encode.js.map +1 -1
  7. package/dist/base64.cjs +5 -4
  8. package/dist/base64.cjs.map +1 -1
  9. package/dist/base64.d.ts +10 -6
  10. package/dist/base64.js +5 -3
  11. package/dist/base64.js.map +1 -1
  12. package/dist/block_state.d.ts +21 -23
  13. package/dist/bmodel/block_config.cjs +9 -10
  14. package/dist/bmodel/block_config.cjs.map +1 -1
  15. package/dist/bmodel/block_config.d.ts +53 -72
  16. package/dist/bmodel/block_config.js +9 -9
  17. package/dist/bmodel/block_config.js.map +1 -1
  18. package/dist/bmodel/code.cjs +7 -6
  19. package/dist/bmodel/code.cjs.map +1 -1
  20. package/dist/bmodel/code.d.ts +17 -13
  21. package/dist/bmodel/code.js +6 -4
  22. package/dist/bmodel/code.js.map +1 -1
  23. package/dist/bmodel/container.d.ts +46 -44
  24. package/dist/bmodel/index.cjs +3 -0
  25. package/dist/bmodel/index.d.ts +5 -6
  26. package/dist/bmodel/index.js +3 -0
  27. package/dist/bmodel/normalization.cjs +90 -106
  28. package/dist/bmodel/normalization.cjs.map +1 -1
  29. package/dist/bmodel/normalization.d.ts +7 -3
  30. package/dist/bmodel/normalization.js +90 -105
  31. package/dist/bmodel/normalization.js.map +1 -1
  32. package/dist/bmodel/types.d.ts +4 -1
  33. package/dist/branding.d.ts +5 -5
  34. package/dist/common_types.d.ts +19 -15
  35. package/dist/driver_kit.d.ts +25 -17
  36. package/dist/drivers/ChunkedStreamReader.cjs +168 -203
  37. package/dist/drivers/ChunkedStreamReader.cjs.map +1 -1
  38. package/dist/drivers/ChunkedStreamReader.d.ts +104 -100
  39. package/dist/drivers/ChunkedStreamReader.js +168 -202
  40. package/dist/drivers/ChunkedStreamReader.js.map +1 -1
  41. package/dist/drivers/blob.cjs +15 -17
  42. package/dist/drivers/blob.cjs.map +1 -1
  43. package/dist/drivers/blob.d.ts +35 -35
  44. package/dist/drivers/blob.js +14 -15
  45. package/dist/drivers/blob.js.map +1 -1
  46. package/dist/drivers/index.cjs +18 -0
  47. package/dist/drivers/index.d.ts +29 -9
  48. package/dist/drivers/index.js +18 -0
  49. package/dist/drivers/interfaces.d.ts +17 -14
  50. package/dist/drivers/log.cjs +4 -3
  51. package/dist/drivers/log.cjs.map +1 -1
  52. package/dist/drivers/log.d.ts +52 -49
  53. package/dist/drivers/log.js +4 -2
  54. package/dist/drivers/log.js.map +1 -1
  55. package/dist/drivers/ls.cjs +16 -19
  56. package/dist/drivers/ls.cjs.map +1 -1
  57. package/dist/drivers/ls.d.ts +73 -76
  58. package/dist/drivers/ls.js +16 -17
  59. package/dist/drivers/ls.js.map +1 -1
  60. package/dist/drivers/pframe/column_filter.d.ts +19 -15
  61. package/dist/drivers/pframe/data_info.cjs +201 -252
  62. package/dist/drivers/pframe/data_info.cjs.map +1 -1
  63. package/dist/drivers/pframe/data_info.d.ts +84 -109
  64. package/dist/drivers/pframe/data_info.js +201 -250
  65. package/dist/drivers/pframe/data_info.js.map +1 -1
  66. package/dist/drivers/pframe/data_types.cjs +38 -63
  67. package/dist/drivers/pframe/data_types.cjs.map +1 -1
  68. package/dist/drivers/pframe/data_types.d.ts +91 -93
  69. package/dist/drivers/pframe/data_types.js +38 -61
  70. package/dist/drivers/pframe/data_types.js.map +1 -1
  71. package/dist/drivers/pframe/driver.cjs +7 -0
  72. package/dist/drivers/pframe/driver.cjs.map +1 -0
  73. package/dist/drivers/pframe/driver.d.ts +50 -45
  74. package/dist/drivers/pframe/driver.js +6 -0
  75. package/dist/drivers/pframe/driver.js.map +1 -0
  76. package/dist/drivers/pframe/filter_spec.d.ts +127 -123
  77. package/dist/drivers/pframe/find_columns.d.ts +21 -17
  78. package/dist/drivers/pframe/index.cjs +15 -0
  79. package/dist/drivers/pframe/index.d.ts +23 -16
  80. package/dist/drivers/pframe/index.js +15 -0
  81. package/dist/drivers/pframe/linker_columns.cjs +184 -238
  82. package/dist/drivers/pframe/linker_columns.cjs.map +1 -1
  83. package/dist/drivers/pframe/linker_columns.d.ts +45 -38
  84. package/dist/drivers/pframe/linker_columns.js +184 -236
  85. package/dist/drivers/pframe/linker_columns.js.map +1 -1
  86. package/dist/drivers/pframe/pframe.d.ts +26 -21
  87. package/dist/drivers/pframe/query/index.cjs +1 -0
  88. package/dist/drivers/pframe/query/index.d.ts +3 -4
  89. package/dist/drivers/pframe/query/index.js +1 -0
  90. package/dist/drivers/pframe/query/query_common.d.ts +205 -247
  91. package/dist/drivers/pframe/query/query_data.d.ts +25 -23
  92. package/dist/drivers/pframe/query/query_spec.d.ts +30 -29
  93. package/dist/drivers/pframe/query/utils.cjs +164 -183
  94. package/dist/drivers/pframe/query/utils.cjs.map +1 -1
  95. package/dist/drivers/pframe/query/utils.d.ts +13 -12
  96. package/dist/drivers/pframe/query/utils.js +164 -181
  97. package/dist/drivers/pframe/query/utils.js.map +1 -1
  98. package/dist/drivers/pframe/spec/anchored.cjs +178 -216
  99. package/dist/drivers/pframe/spec/anchored.cjs.map +1 -1
  100. package/dist/drivers/pframe/spec/anchored.d.ts +53 -49
  101. package/dist/drivers/pframe/spec/anchored.js +176 -214
  102. package/dist/drivers/pframe/spec/anchored.js.map +1 -1
  103. package/dist/drivers/pframe/spec/filtered_column.cjs +8 -7
  104. package/dist/drivers/pframe/spec/filtered_column.cjs.map +1 -1
  105. package/dist/drivers/pframe/spec/filtered_column.d.ts +20 -17
  106. package/dist/drivers/pframe/spec/filtered_column.js +8 -6
  107. package/dist/drivers/pframe/spec/filtered_column.js.map +1 -1
  108. package/dist/drivers/pframe/spec/ids.cjs +16 -14
  109. package/dist/drivers/pframe/spec/ids.cjs.map +1 -1
  110. package/dist/drivers/pframe/spec/ids.d.ts +13 -8
  111. package/dist/drivers/pframe/spec/ids.js +14 -12
  112. package/dist/drivers/pframe/spec/ids.js.map +1 -1
  113. package/dist/drivers/pframe/spec/index.cjs +6 -0
  114. package/dist/drivers/pframe/spec/index.d.ts +6 -7
  115. package/dist/drivers/pframe/spec/index.js +6 -0
  116. package/dist/drivers/pframe/spec/native_id.cjs +16 -16
  117. package/dist/drivers/pframe/spec/native_id.cjs.map +1 -1
  118. package/dist/drivers/pframe/spec/native_id.d.ts +9 -4
  119. package/dist/drivers/pframe/spec/native_id.js +13 -13
  120. package/dist/drivers/pframe/spec/native_id.js.map +1 -1
  121. package/dist/drivers/pframe/spec/selectors.cjs +72 -112
  122. package/dist/drivers/pframe/spec/selectors.cjs.map +1 -1
  123. package/dist/drivers/pframe/spec/selectors.d.ts +99 -94
  124. package/dist/drivers/pframe/spec/selectors.js +72 -110
  125. package/dist/drivers/pframe/spec/selectors.js.map +1 -1
  126. package/dist/drivers/pframe/spec/spec.cjs +282 -324
  127. package/dist/drivers/pframe/spec/spec.cjs.map +1 -1
  128. package/dist/drivers/pframe/spec/spec.d.ts +263 -272
  129. package/dist/drivers/pframe/spec/spec.js +281 -322
  130. package/dist/drivers/pframe/spec/spec.js.map +1 -1
  131. package/dist/drivers/pframe/table.d.ts +28 -24
  132. package/dist/drivers/pframe/table_calculate.cjs +117 -147
  133. package/dist/drivers/pframe/table_calculate.cjs.map +1 -1
  134. package/dist/drivers/pframe/table_calculate.d.ts +219 -220
  135. package/dist/drivers/pframe/table_calculate.js +117 -145
  136. package/dist/drivers/pframe/table_calculate.js.map +1 -1
  137. package/dist/drivers/pframe/table_common.cjs +13 -14
  138. package/dist/drivers/pframe/table_common.cjs.map +1 -1
  139. package/dist/drivers/pframe/table_common.d.ts +24 -19
  140. package/dist/drivers/pframe/table_common.js +13 -13
  141. package/dist/drivers/pframe/table_common.js.map +1 -1
  142. package/dist/drivers/pframe/unique_values.d.ts +23 -18
  143. package/dist/drivers/upload.d.ts +21 -18
  144. package/dist/drivers/urls.cjs +5 -6
  145. package/dist/drivers/urls.cjs.map +1 -1
  146. package/dist/drivers/urls.d.ts +12 -9
  147. package/dist/drivers/urls.js +5 -5
  148. package/dist/drivers/urls.js.map +1 -1
  149. package/dist/errors.cjs +65 -86
  150. package/dist/errors.cjs.map +1 -1
  151. package/dist/errors.d.ts +36 -33
  152. package/dist/errors.js +65 -85
  153. package/dist/errors.js.map +1 -1
  154. package/dist/flags/block_flags.cjs +7 -6
  155. package/dist/flags/block_flags.cjs.map +1 -1
  156. package/dist/flags/block_flags.d.ts +12 -8
  157. package/dist/flags/block_flags.js +7 -5
  158. package/dist/flags/block_flags.js.map +1 -1
  159. package/dist/flags/flag_utils.cjs +69 -108
  160. package/dist/flags/flag_utils.cjs.map +1 -1
  161. package/dist/flags/flag_utils.d.ts +40 -42
  162. package/dist/flags/flag_utils.js +70 -107
  163. package/dist/flags/flag_utils.js.map +1 -1
  164. package/dist/flags/type_utils.d.ts +12 -11
  165. package/dist/httpAuth.cjs +16 -20
  166. package/dist/httpAuth.cjs.map +1 -1
  167. package/dist/httpAuth.d.ts +10 -7
  168. package/dist/httpAuth.js +16 -19
  169. package/dist/httpAuth.js.map +1 -1
  170. package/dist/index.cjs +176 -179
  171. package/dist/index.d.ts +58 -20
  172. package/dist/index.js +37 -34
  173. package/dist/json.cjs +10 -8
  174. package/dist/json.cjs.map +1 -1
  175. package/dist/json.d.ts +18 -18
  176. package/dist/json.js +8 -6
  177. package/dist/json.js.map +1 -1
  178. package/dist/navigation.cjs +3 -2
  179. package/dist/navigation.cjs.map +1 -1
  180. package/dist/navigation.d.ts +18 -21
  181. package/dist/navigation.js +3 -1
  182. package/dist/navigation.js.map +1 -1
  183. package/dist/plid.cjs +16 -20
  184. package/dist/plid.cjs.map +1 -1
  185. package/dist/plid.d.ts +11 -7
  186. package/dist/plid.js +15 -18
  187. package/dist/plid.js.map +1 -1
  188. package/dist/pool/entry.d.ts +11 -11
  189. package/dist/pool/index.d.ts +3 -4
  190. package/dist/pool/query.cjs +21 -43
  191. package/dist/pool/query.cjs.map +1 -1
  192. package/dist/pool/query.d.ts +25 -20
  193. package/dist/pool/query.js +20 -40
  194. package/dist/pool/query.js.map +1 -1
  195. package/dist/pool/spec.cjs +40 -47
  196. package/dist/pool/spec.cjs.map +1 -1
  197. package/dist/pool/spec.d.ts +33 -31
  198. package/dist/pool/spec.js +40 -45
  199. package/dist/pool/spec.js.map +1 -1
  200. package/dist/ref.cjs +51 -71
  201. package/dist/ref.cjs.map +1 -1
  202. package/dist/ref.d.ts +36 -33
  203. package/dist/ref.js +50 -69
  204. package/dist/ref.js.map +1 -1
  205. package/dist/utag.d.ts +18 -14
  206. package/dist/util.cjs +8 -7
  207. package/dist/util.cjs.map +1 -1
  208. package/dist/util.d.ts +5 -2
  209. package/dist/util.js +8 -6
  210. package/dist/util.js.map +1 -1
  211. package/dist/value_or_error.cjs +7 -3
  212. package/dist/value_or_error.cjs.map +1 -1
  213. package/dist/value_or_error.d.ts +9 -6
  214. package/dist/value_or_error.js +7 -2
  215. package/dist/value_or_error.js.map +1 -1
  216. package/package.json +6 -6
  217. package/src/flags/block_flags.ts +2 -1
  218. package/src/flags/flag_utils.ts +0 -22
  219. package/dist/author_marker.d.ts.map +0 -1
  220. package/dist/base32_encode.d.ts +0 -8
  221. package/dist/base32_encode.d.ts.map +0 -1
  222. package/dist/base64.d.ts.map +0 -1
  223. package/dist/block_state.d.ts.map +0 -1
  224. package/dist/bmodel/block_config.d.ts.map +0 -1
  225. package/dist/bmodel/code.d.ts.map +0 -1
  226. package/dist/bmodel/container.d.ts.map +0 -1
  227. package/dist/bmodel/index.d.ts.map +0 -1
  228. package/dist/bmodel/normalization.d.ts.map +0 -1
  229. package/dist/bmodel/types.d.ts.map +0 -1
  230. package/dist/branding.d.ts.map +0 -1
  231. package/dist/common_types.d.ts.map +0 -1
  232. package/dist/driver_kit.d.ts.map +0 -1
  233. package/dist/drivers/ChunkedStreamReader.d.ts.map +0 -1
  234. package/dist/drivers/blob.d.ts.map +0 -1
  235. package/dist/drivers/index.d.ts.map +0 -1
  236. package/dist/drivers/interfaces.d.ts.map +0 -1
  237. package/dist/drivers/log.d.ts.map +0 -1
  238. package/dist/drivers/ls.d.ts.map +0 -1
  239. package/dist/drivers/pframe/column_filter.d.ts.map +0 -1
  240. package/dist/drivers/pframe/data_info.d.ts.map +0 -1
  241. package/dist/drivers/pframe/data_types.d.ts.map +0 -1
  242. package/dist/drivers/pframe/driver.d.ts.map +0 -1
  243. package/dist/drivers/pframe/filter_spec.d.ts.map +0 -1
  244. package/dist/drivers/pframe/find_columns.d.ts.map +0 -1
  245. package/dist/drivers/pframe/index.d.ts.map +0 -1
  246. package/dist/drivers/pframe/linker_columns.d.ts.map +0 -1
  247. package/dist/drivers/pframe/pframe.d.ts.map +0 -1
  248. package/dist/drivers/pframe/query/index.d.ts.map +0 -1
  249. package/dist/drivers/pframe/query/query_common.d.ts.map +0 -1
  250. package/dist/drivers/pframe/query/query_data.d.ts.map +0 -1
  251. package/dist/drivers/pframe/query/query_spec.d.ts.map +0 -1
  252. package/dist/drivers/pframe/query/utils.d.ts.map +0 -1
  253. package/dist/drivers/pframe/spec/anchored.d.ts.map +0 -1
  254. package/dist/drivers/pframe/spec/filtered_column.d.ts.map +0 -1
  255. package/dist/drivers/pframe/spec/ids.d.ts.map +0 -1
  256. package/dist/drivers/pframe/spec/index.d.ts.map +0 -1
  257. package/dist/drivers/pframe/spec/native_id.d.ts.map +0 -1
  258. package/dist/drivers/pframe/spec/selectors.d.ts.map +0 -1
  259. package/dist/drivers/pframe/spec/spec.d.ts.map +0 -1
  260. package/dist/drivers/pframe/table.d.ts.map +0 -1
  261. package/dist/drivers/pframe/table_calculate.d.ts.map +0 -1
  262. package/dist/drivers/pframe/table_common.d.ts.map +0 -1
  263. package/dist/drivers/pframe/type_util.d.ts +0 -5
  264. package/dist/drivers/pframe/type_util.d.ts.map +0 -1
  265. package/dist/drivers/pframe/unique_values.d.ts.map +0 -1
  266. package/dist/drivers/upload.d.ts.map +0 -1
  267. package/dist/drivers/urls.d.ts.map +0 -1
  268. package/dist/errors.d.ts.map +0 -1
  269. package/dist/flags/block_flags.d.ts.map +0 -1
  270. package/dist/flags/flag_utils.d.ts.map +0 -1
  271. package/dist/flags/index.d.ts +0 -4
  272. package/dist/flags/index.d.ts.map +0 -1
  273. package/dist/flags/type_utils.d.ts.map +0 -1
  274. package/dist/httpAuth.d.ts.map +0 -1
  275. package/dist/index.cjs.map +0 -1
  276. package/dist/index.d.ts.map +0 -1
  277. package/dist/index.js.map +0 -1
  278. package/dist/json.d.ts.map +0 -1
  279. package/dist/navigation.d.ts.map +0 -1
  280. package/dist/plid.d.ts.map +0 -1
  281. package/dist/pool/entry.d.ts.map +0 -1
  282. package/dist/pool/index.d.ts.map +0 -1
  283. package/dist/pool/query.d.ts.map +0 -1
  284. package/dist/pool/spec.d.ts.map +0 -1
  285. package/dist/ref.d.ts.map +0 -1
  286. package/dist/utag.d.ts.map +0 -1
  287. package/dist/util.d.ts.map +0 -1
  288. package/dist/value_or_error.d.ts.map +0 -1
@@ -1,207 +1,172 @@
1
- 'use strict';
2
1
 
2
+ //#region src/drivers/ChunkedStreamReader.ts
3
3
  /**
4
- * ChunkedStreamReader creates a ReadableStream that reads data from a blob driver
5
- * in fixed-size chunks. This is useful for streaming large files without loading
6
- * them entirely into memory.
7
- */
8
- class ChunkedStreamReader {
9
- currentPosition = 0;
10
- _read = true;
11
- _canceled = false;
12
- _errored = false;
13
- abortController = null;
14
- options;
15
- /**
16
- * Creates a new ChunkedStreamReader instance.
17
- * Use the static `create` method instead.
18
- */
19
- constructor(options) {
20
- // Normalize options with defaults
21
- this.options = {
22
- ...options,
23
- chunkSize: options.chunkSize ?? 16 * 1024 * 1024,
24
- onError: options.onError ??
25
- (async () => {
26
- // Default behavior: error (will automatically call controller.error)
27
- return "error";
28
- }),
29
- };
30
- if (this.totalSize < 0) {
31
- throw new Error("Total size must be non-negative");
32
- }
33
- if (this.chunkSize <= 0) {
34
- throw new Error("Chunk size must be positive");
35
- }
36
- }
37
- /**
38
- * Gets the fetchChunk function from options
39
- */
40
- get fetchChunk() {
41
- return this.options.fetchChunk;
42
- }
43
- /**
44
- * Gets the total size from options
45
- */
46
- get totalSize() {
47
- return this.options.totalSize;
48
- }
49
- /**
50
- * Gets the chunk size from options
51
- */
52
- get chunkSize() {
53
- return this.options.chunkSize;
54
- }
55
- /**
56
- * Gets the onError callback from options
57
- */
58
- get onError() {
59
- return this.options.onError;
60
- }
61
- /**
62
- * Creates and returns a ReadableStream that reads data in chunks.
63
- *
64
- * @param options - Configuration options for the chunked stream reader
65
- * @returns ReadableStream that can be consumed by zip.add or other stream consumers
66
- *
67
- * @example
68
- * ```typescript
69
- * const stream = ChunkedStreamReader.create({
70
- * fetchChunk: async (range, signal) => {
71
- * const response = await fetch(`/api/data?from=${range.from}&to=${range.to}`, { signal });
72
- * return new Uint8Array(await response.arrayBuffer());
73
- * },
74
- * totalSize: 1024 * 1024, // 1MB
75
- * chunkSize: 64 * 1024, // 64KB chunks
76
- * });
77
- * ```
78
- */
79
- static create(options) {
80
- const reader = new ChunkedStreamReader(options);
81
- return reader.createStream();
82
- }
83
- readStart() {
84
- this._read = true;
85
- }
86
- readStop() {
87
- this._read = false;
88
- }
89
- async tryRead(controller) {
90
- if (this._canceled) {
91
- return true;
92
- }
93
- // Check if we've read all data
94
- if (this.isComplete()) {
95
- controller.close();
96
- return true;
97
- }
98
- try {
99
- // Calculate the end position for this chunk
100
- // Ensure we don't read beyond the total size
101
- const endPosition = Math.min(this.currentPosition + this.chunkSize, this.totalSize);
102
- // Fetch the chunk from the blob driver, passing the abort signal if available
103
- const data = await this.fetchChunk({ from: this.currentPosition, to: endPosition }, this.abortController?.signal);
104
- // Check if stream was cancelled during the fetch
105
- if (this._canceled) {
106
- return true;
107
- }
108
- // Enqueue the data into the stream
109
- controller.enqueue(data);
110
- // Update the current position for the next chunk
111
- this.currentPosition = endPosition;
112
- if (!controller.desiredSize || controller.desiredSize <= 0) {
113
- // The internal queue is full, so propagate
114
- // the backpressure signal to the underlying source.
115
- this.readStop();
116
- }
117
- }
118
- catch (error) {
119
- // If any error occurs during chunk reading, call the error handler
120
- const status = await this.onError(error);
121
- if (status === "error") {
122
- this._errored = true;
123
- // Error the stream and abort any ongoing fetch operations
124
- controller.error(error);
125
- this.abortController?.abort("Stream errored");
126
- return true; // Stop reading
127
- }
128
- if (status === "cancel") {
129
- this._canceled = true;
130
- // Close the stream gracefully and abort any ongoing fetch operations
131
- controller.close();
132
- this.abortController?.abort("Stream cancelled");
133
- console.debug("ChunkedStreamReader cancelled due to error");
134
- return true; // Stop reading
135
- }
136
- }
137
- return false;
138
- }
139
- /**
140
- * Creates and returns a ReadableStream that reads data in chunks.
141
- * The stream will automatically close when all data has been read.
142
- *
143
- * @private - Use the static `create` method instead
144
- * @returns ReadableStream that can be consumed by zip.add or other stream consumers
145
- */
146
- createStream() {
147
- // Create an AbortController for this stream
148
- this.abortController = new AbortController();
149
- return new ReadableStream({
150
- start: async (controller) => {
151
- while (true) {
152
- if (this._canceled || this._errored) {
153
- return;
154
- }
155
- if (!this._read) {
156
- await new Promise((r) => setTimeout(r, 0));
157
- if (controller.desiredSize) {
158
- this.readStart();
159
- }
160
- }
161
- else {
162
- const isDone = await this.tryRead(controller);
163
- if (isDone) {
164
- return;
165
- }
166
- }
167
- }
168
- },
169
- pull: () => {
170
- this.readStart();
171
- },
172
- cancel: (reason) => {
173
- this._canceled = true;
174
- // Abort any ongoing fetch operations
175
- this.abortController?.abort(reason);
176
- console.debug("ChunkedStreamReader cancelled:", reason);
177
- },
178
- });
179
- }
180
- /**
181
- * Gets the current reading position in bytes.
182
- *
183
- * @returns Current position as number of bytes read
184
- */
185
- getCurrentPosition() {
186
- return this.currentPosition;
187
- }
188
- /**
189
- * Gets the remaining bytes to be read.
190
- *
191
- * @returns Number of bytes remaining
192
- */
193
- getRemainingBytes() {
194
- return Math.max(0, this.totalSize - this.currentPosition);
195
- }
196
- /**
197
- * Checks if the entire blob has been read.
198
- *
199
- * @returns True if all data has been read
200
- */
201
- isComplete() {
202
- return this.currentPosition >= this.totalSize;
203
- }
204
- }
4
+ * ChunkedStreamReader creates a ReadableStream that reads data from a blob driver
5
+ * in fixed-size chunks. This is useful for streaming large files without loading
6
+ * them entirely into memory.
7
+ */
8
+ var ChunkedStreamReader = class ChunkedStreamReader {
9
+ currentPosition = 0;
10
+ _read = true;
11
+ _canceled = false;
12
+ _errored = false;
13
+ abortController = null;
14
+ options;
15
+ /**
16
+ * Creates a new ChunkedStreamReader instance.
17
+ * Use the static `create` method instead.
18
+ */
19
+ constructor(options) {
20
+ this.options = {
21
+ ...options,
22
+ chunkSize: options.chunkSize ?? 16 * 1024 * 1024,
23
+ onError: options.onError ?? (async () => {
24
+ return "error";
25
+ })
26
+ };
27
+ if (this.totalSize < 0) throw new Error("Total size must be non-negative");
28
+ if (this.chunkSize <= 0) throw new Error("Chunk size must be positive");
29
+ }
30
+ /**
31
+ * Gets the fetchChunk function from options
32
+ */
33
+ get fetchChunk() {
34
+ return this.options.fetchChunk;
35
+ }
36
+ /**
37
+ * Gets the total size from options
38
+ */
39
+ get totalSize() {
40
+ return this.options.totalSize;
41
+ }
42
+ /**
43
+ * Gets the chunk size from options
44
+ */
45
+ get chunkSize() {
46
+ return this.options.chunkSize;
47
+ }
48
+ /**
49
+ * Gets the onError callback from options
50
+ */
51
+ get onError() {
52
+ return this.options.onError;
53
+ }
54
+ /**
55
+ * Creates and returns a ReadableStream that reads data in chunks.
56
+ *
57
+ * @param options - Configuration options for the chunked stream reader
58
+ * @returns ReadableStream that can be consumed by zip.add or other stream consumers
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const stream = ChunkedStreamReader.create({
63
+ * fetchChunk: async (range, signal) => {
64
+ * const response = await fetch(`/api/data?from=${range.from}&to=${range.to}`, { signal });
65
+ * return new Uint8Array(await response.arrayBuffer());
66
+ * },
67
+ * totalSize: 1024 * 1024, // 1MB
68
+ * chunkSize: 64 * 1024, // 64KB chunks
69
+ * });
70
+ * ```
71
+ */
72
+ static create(options) {
73
+ return new ChunkedStreamReader(options).createStream();
74
+ }
75
+ readStart() {
76
+ this._read = true;
77
+ }
78
+ readStop() {
79
+ this._read = false;
80
+ }
81
+ async tryRead(controller) {
82
+ if (this._canceled) return true;
83
+ if (this.isComplete()) {
84
+ controller.close();
85
+ return true;
86
+ }
87
+ try {
88
+ const endPosition = Math.min(this.currentPosition + this.chunkSize, this.totalSize);
89
+ const data = await this.fetchChunk({
90
+ from: this.currentPosition,
91
+ to: endPosition
92
+ }, this.abortController?.signal);
93
+ if (this._canceled) return true;
94
+ controller.enqueue(data);
95
+ this.currentPosition = endPosition;
96
+ if (!controller.desiredSize || controller.desiredSize <= 0) this.readStop();
97
+ } catch (error) {
98
+ const status = await this.onError(error);
99
+ if (status === "error") {
100
+ this._errored = true;
101
+ controller.error(error);
102
+ this.abortController?.abort("Stream errored");
103
+ return true;
104
+ }
105
+ if (status === "cancel") {
106
+ this._canceled = true;
107
+ controller.close();
108
+ this.abortController?.abort("Stream cancelled");
109
+ console.debug("ChunkedStreamReader cancelled due to error");
110
+ return true;
111
+ }
112
+ }
113
+ return false;
114
+ }
115
+ /**
116
+ * Creates and returns a ReadableStream that reads data in chunks.
117
+ * The stream will automatically close when all data has been read.
118
+ *
119
+ * @private - Use the static `create` method instead
120
+ * @returns ReadableStream that can be consumed by zip.add or other stream consumers
121
+ */
122
+ createStream() {
123
+ this.abortController = new AbortController();
124
+ return new ReadableStream({
125
+ start: async (controller) => {
126
+ while (true) {
127
+ if (this._canceled || this._errored) return;
128
+ if (!this._read) {
129
+ await new Promise((r) => setTimeout(r, 0));
130
+ if (controller.desiredSize) this.readStart();
131
+ } else if (await this.tryRead(controller)) return;
132
+ }
133
+ },
134
+ pull: () => {
135
+ this.readStart();
136
+ },
137
+ cancel: (reason) => {
138
+ this._canceled = true;
139
+ this.abortController?.abort(reason);
140
+ console.debug("ChunkedStreamReader cancelled:", reason);
141
+ }
142
+ });
143
+ }
144
+ /**
145
+ * Gets the current reading position in bytes.
146
+ *
147
+ * @returns Current position as number of bytes read
148
+ */
149
+ getCurrentPosition() {
150
+ return this.currentPosition;
151
+ }
152
+ /**
153
+ * Gets the remaining bytes to be read.
154
+ *
155
+ * @returns Number of bytes remaining
156
+ */
157
+ getRemainingBytes() {
158
+ return Math.max(0, this.totalSize - this.currentPosition);
159
+ }
160
+ /**
161
+ * Checks if the entire blob has been read.
162
+ *
163
+ * @returns True if all data has been read
164
+ */
165
+ isComplete() {
166
+ return this.currentPosition >= this.totalSize;
167
+ }
168
+ };
205
169
 
170
+ //#endregion
206
171
  exports.ChunkedStreamReader = ChunkedStreamReader;
207
- //# sourceMappingURL=ChunkedStreamReader.cjs.map
172
+ //# sourceMappingURL=ChunkedStreamReader.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChunkedStreamReader.cjs","sources":["../../src/drivers/ChunkedStreamReader.ts"],"sourcesContent":["import type { RangeBytes } from \"./blob\";\n\n/**\n * Status returned by onError handler to indicate what action to take\n * - 'continue': Retry the failed operation\n * - 'error': Error the stream (calls controller.error, aborts ongoing fetches)\n * - 'cancel': Cancel the stream gracefully (calls controller.close, aborts ongoing fetches)\n */\nexport type ErrorHandlerStatus = \"continue\" | \"error\" | \"cancel\";\n\n/**\n * Options for creating a ChunkedStreamReader\n */\nexport interface ChunkedStreamReaderOptions {\n /**\n * Function to fetch a chunk of data. Optionally accepts an AbortSignal to cancel the fetch.\n */\n fetchChunk: (range: RangeBytes, signal?: AbortSignal) => Promise<Uint8Array>;\n\n /**\n * Total size of the blob in bytes\n */\n totalSize: number;\n\n /**\n * Size of each chunk to read in bytes (default: 16MB)\n */\n chunkSize?: number;\n\n /**\n * Error handler callback. Called when an error occurs during chunk fetching.\n * Should return:\n * - 'continue' to retry the operation\n * - 'error' to error the stream (will call controller.error and abort ongoing fetches)\n * - 'cancel' to cancel gracefully (will call controller.close and abort ongoing fetches)\n * Default behavior: returns 'error'.\n */\n onError?: (error: unknown) => Promise<ErrorHandlerStatus>;\n}\n\n/**\n * ChunkedStreamReader creates a ReadableStream that reads data from a blob driver\n * in fixed-size chunks. This is useful for streaming large files without loading\n * them entirely into memory.\n */\nexport class ChunkedStreamReader {\n private currentPosition: number = 0;\n private _read = true;\n private _canceled = false;\n private _errored = false;\n private abortController: AbortController | null = null;\n private readonly options: Required<ChunkedStreamReaderOptions>;\n\n /**\n * Creates a new ChunkedStreamReader instance.\n * Use the static `create` method instead.\n */\n private constructor(options: ChunkedStreamReaderOptions) {\n // Normalize options with defaults\n this.options = {\n ...options,\n chunkSize: options.chunkSize ?? 16 * 1024 * 1024,\n onError:\n options.onError ??\n (async () => {\n // Default behavior: error (will automatically call controller.error)\n return \"error\";\n }),\n };\n\n if (this.totalSize < 0) {\n throw new Error(\"Total size must be non-negative\");\n }\n if (this.chunkSize <= 0) {\n throw new Error(\"Chunk size must be positive\");\n }\n }\n\n /**\n * Gets the fetchChunk function from options\n */\n private get fetchChunk() {\n return this.options.fetchChunk;\n }\n\n /**\n * Gets the total size from options\n */\n private get totalSize() {\n return this.options.totalSize;\n }\n\n /**\n * Gets the chunk size from options\n */\n private get chunkSize() {\n return this.options.chunkSize;\n }\n\n /**\n * Gets the onError callback from options\n */\n private get onError() {\n return this.options.onError;\n }\n\n /**\n * Creates and returns a ReadableStream that reads data in chunks.\n *\n * @param options - Configuration options for the chunked stream reader\n * @returns ReadableStream that can be consumed by zip.add or other stream consumers\n *\n * @example\n * ```typescript\n * const stream = ChunkedStreamReader.create({\n * fetchChunk: async (range, signal) => {\n * const response = await fetch(`/api/data?from=${range.from}&to=${range.to}`, { signal });\n * return new Uint8Array(await response.arrayBuffer());\n * },\n * totalSize: 1024 * 1024, // 1MB\n * chunkSize: 64 * 1024, // 64KB chunks\n * });\n * ```\n */\n static create(options: ChunkedStreamReaderOptions): ReadableStream<Uint8Array> {\n const reader = new ChunkedStreamReader(options);\n return reader.createStream();\n }\n\n private readStart() {\n this._read = true;\n }\n\n private readStop() {\n this._read = false;\n }\n\n private async tryRead(controller: ReadableStreamDefaultController<Uint8Array>): Promise<boolean> {\n if (this._canceled) {\n return true;\n }\n\n // Check if we've read all data\n if (this.isComplete()) {\n controller.close();\n return true;\n }\n\n try {\n // Calculate the end position for this chunk\n // Ensure we don't read beyond the total size\n const endPosition = Math.min(this.currentPosition + this.chunkSize, this.totalSize);\n\n // Fetch the chunk from the blob driver, passing the abort signal if available\n const data = await this.fetchChunk(\n { from: this.currentPosition, to: endPosition },\n this.abortController?.signal,\n );\n\n // Check if stream was cancelled during the fetch\n if (this._canceled) {\n return true;\n }\n\n // Enqueue the data into the stream\n controller.enqueue(data);\n\n // Update the current position for the next chunk\n this.currentPosition = endPosition;\n\n if (!controller.desiredSize || controller.desiredSize <= 0) {\n // The internal queue is full, so propagate\n // the backpressure signal to the underlying source.\n this.readStop();\n }\n } catch (error) {\n // If any error occurs during chunk reading, call the error handler\n const status = await this.onError(error);\n\n if (status === \"error\") {\n this._errored = true;\n // Error the stream and abort any ongoing fetch operations\n controller.error(error);\n this.abortController?.abort(\"Stream errored\");\n return true; // Stop reading\n }\n\n if (status === \"cancel\") {\n this._canceled = true;\n // Close the stream gracefully and abort any ongoing fetch operations\n controller.close();\n this.abortController?.abort(\"Stream cancelled\");\n console.debug(\"ChunkedStreamReader cancelled due to error\");\n return true; // Stop reading\n }\n }\n\n return false;\n }\n\n /**\n * Creates and returns a ReadableStream that reads data in chunks.\n * The stream will automatically close when all data has been read.\n *\n * @private - Use the static `create` method instead\n * @returns ReadableStream that can be consumed by zip.add or other stream consumers\n */\n private createStream(): ReadableStream<Uint8Array> {\n // Create an AbortController for this stream\n this.abortController = new AbortController();\n\n return new ReadableStream({\n start: async (controller) => {\n while (true) {\n if (this._canceled || this._errored) {\n return;\n }\n\n if (!this._read) {\n await new Promise((r) => setTimeout(r, 0));\n if (controller.desiredSize) {\n this.readStart();\n }\n } else {\n const isDone = await this.tryRead(controller);\n if (isDone) {\n return;\n }\n }\n }\n },\n\n pull: () => {\n this.readStart();\n },\n\n cancel: (reason) => {\n this._canceled = true;\n // Abort any ongoing fetch operations\n this.abortController?.abort(reason);\n console.debug(\"ChunkedStreamReader cancelled:\", reason);\n },\n });\n }\n\n /**\n * Gets the current reading position in bytes.\n *\n * @returns Current position as number of bytes read\n */\n getCurrentPosition(): number {\n return this.currentPosition;\n }\n\n /**\n * Gets the remaining bytes to be read.\n *\n * @returns Number of bytes remaining\n */\n getRemainingBytes(): number {\n return Math.max(0, this.totalSize - this.currentPosition);\n }\n\n /**\n * Checks if the entire blob has been read.\n *\n * @returns True if all data has been read\n */\n isComplete(): boolean {\n return this.currentPosition >= this.totalSize;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChunkedStreamReader.cjs","names":[],"sources":["../../src/drivers/ChunkedStreamReader.ts"],"sourcesContent":["import type { RangeBytes } from \"./blob\";\n\n/**\n * Status returned by onError handler to indicate what action to take\n * - 'continue': Retry the failed operation\n * - 'error': Error the stream (calls controller.error, aborts ongoing fetches)\n * - 'cancel': Cancel the stream gracefully (calls controller.close, aborts ongoing fetches)\n */\nexport type ErrorHandlerStatus = \"continue\" | \"error\" | \"cancel\";\n\n/**\n * Options for creating a ChunkedStreamReader\n */\nexport interface ChunkedStreamReaderOptions {\n /**\n * Function to fetch a chunk of data. Optionally accepts an AbortSignal to cancel the fetch.\n */\n fetchChunk: (range: RangeBytes, signal?: AbortSignal) => Promise<Uint8Array>;\n\n /**\n * Total size of the blob in bytes\n */\n totalSize: number;\n\n /**\n * Size of each chunk to read in bytes (default: 16MB)\n */\n chunkSize?: number;\n\n /**\n * Error handler callback. Called when an error occurs during chunk fetching.\n * Should return:\n * - 'continue' to retry the operation\n * - 'error' to error the stream (will call controller.error and abort ongoing fetches)\n * - 'cancel' to cancel gracefully (will call controller.close and abort ongoing fetches)\n * Default behavior: returns 'error'.\n */\n onError?: (error: unknown) => Promise<ErrorHandlerStatus>;\n}\n\n/**\n * ChunkedStreamReader creates a ReadableStream that reads data from a blob driver\n * in fixed-size chunks. This is useful for streaming large files without loading\n * them entirely into memory.\n */\nexport class ChunkedStreamReader {\n private currentPosition: number = 0;\n private _read = true;\n private _canceled = false;\n private _errored = false;\n private abortController: AbortController | null = null;\n private readonly options: Required<ChunkedStreamReaderOptions>;\n\n /**\n * Creates a new ChunkedStreamReader instance.\n * Use the static `create` method instead.\n */\n private constructor(options: ChunkedStreamReaderOptions) {\n // Normalize options with defaults\n this.options = {\n ...options,\n chunkSize: options.chunkSize ?? 16 * 1024 * 1024,\n onError:\n options.onError ??\n (async () => {\n // Default behavior: error (will automatically call controller.error)\n return \"error\";\n }),\n };\n\n if (this.totalSize < 0) {\n throw new Error(\"Total size must be non-negative\");\n }\n if (this.chunkSize <= 0) {\n throw new Error(\"Chunk size must be positive\");\n }\n }\n\n /**\n * Gets the fetchChunk function from options\n */\n private get fetchChunk() {\n return this.options.fetchChunk;\n }\n\n /**\n * Gets the total size from options\n */\n private get totalSize() {\n return this.options.totalSize;\n }\n\n /**\n * Gets the chunk size from options\n */\n private get chunkSize() {\n return this.options.chunkSize;\n }\n\n /**\n * Gets the onError callback from options\n */\n private get onError() {\n return this.options.onError;\n }\n\n /**\n * Creates and returns a ReadableStream that reads data in chunks.\n *\n * @param options - Configuration options for the chunked stream reader\n * @returns ReadableStream that can be consumed by zip.add or other stream consumers\n *\n * @example\n * ```typescript\n * const stream = ChunkedStreamReader.create({\n * fetchChunk: async (range, signal) => {\n * const response = await fetch(`/api/data?from=${range.from}&to=${range.to}`, { signal });\n * return new Uint8Array(await response.arrayBuffer());\n * },\n * totalSize: 1024 * 1024, // 1MB\n * chunkSize: 64 * 1024, // 64KB chunks\n * });\n * ```\n */\n static create(options: ChunkedStreamReaderOptions): ReadableStream<Uint8Array> {\n const reader = new ChunkedStreamReader(options);\n return reader.createStream();\n }\n\n private readStart() {\n this._read = true;\n }\n\n private readStop() {\n this._read = false;\n }\n\n private async tryRead(controller: ReadableStreamDefaultController<Uint8Array>): Promise<boolean> {\n if (this._canceled) {\n return true;\n }\n\n // Check if we've read all data\n if (this.isComplete()) {\n controller.close();\n return true;\n }\n\n try {\n // Calculate the end position for this chunk\n // Ensure we don't read beyond the total size\n const endPosition = Math.min(this.currentPosition + this.chunkSize, this.totalSize);\n\n // Fetch the chunk from the blob driver, passing the abort signal if available\n const data = await this.fetchChunk(\n { from: this.currentPosition, to: endPosition },\n this.abortController?.signal,\n );\n\n // Check if stream was cancelled during the fetch\n if (this._canceled) {\n return true;\n }\n\n // Enqueue the data into the stream\n controller.enqueue(data);\n\n // Update the current position for the next chunk\n this.currentPosition = endPosition;\n\n if (!controller.desiredSize || controller.desiredSize <= 0) {\n // The internal queue is full, so propagate\n // the backpressure signal to the underlying source.\n this.readStop();\n }\n } catch (error) {\n // If any error occurs during chunk reading, call the error handler\n const status = await this.onError(error);\n\n if (status === \"error\") {\n this._errored = true;\n // Error the stream and abort any ongoing fetch operations\n controller.error(error);\n this.abortController?.abort(\"Stream errored\");\n return true; // Stop reading\n }\n\n if (status === \"cancel\") {\n this._canceled = true;\n // Close the stream gracefully and abort any ongoing fetch operations\n controller.close();\n this.abortController?.abort(\"Stream cancelled\");\n console.debug(\"ChunkedStreamReader cancelled due to error\");\n return true; // Stop reading\n }\n }\n\n return false;\n }\n\n /**\n * Creates and returns a ReadableStream that reads data in chunks.\n * The stream will automatically close when all data has been read.\n *\n * @private - Use the static `create` method instead\n * @returns ReadableStream that can be consumed by zip.add or other stream consumers\n */\n private createStream(): ReadableStream<Uint8Array> {\n // Create an AbortController for this stream\n this.abortController = new AbortController();\n\n return new ReadableStream({\n start: async (controller) => {\n while (true) {\n if (this._canceled || this._errored) {\n return;\n }\n\n if (!this._read) {\n await new Promise((r) => setTimeout(r, 0));\n if (controller.desiredSize) {\n this.readStart();\n }\n } else {\n const isDone = await this.tryRead(controller);\n if (isDone) {\n return;\n }\n }\n }\n },\n\n pull: () => {\n this.readStart();\n },\n\n cancel: (reason) => {\n this._canceled = true;\n // Abort any ongoing fetch operations\n this.abortController?.abort(reason);\n console.debug(\"ChunkedStreamReader cancelled:\", reason);\n },\n });\n }\n\n /**\n * Gets the current reading position in bytes.\n *\n * @returns Current position as number of bytes read\n */\n getCurrentPosition(): number {\n return this.currentPosition;\n }\n\n /**\n * Gets the remaining bytes to be read.\n *\n * @returns Number of bytes remaining\n */\n getRemainingBytes(): number {\n return Math.max(0, this.totalSize - this.currentPosition);\n }\n\n /**\n * Checks if the entire blob has been read.\n *\n * @returns True if all data has been read\n */\n isComplete(): boolean {\n return this.currentPosition >= this.totalSize;\n }\n}\n"],"mappings":";;;;;;;AA6CA,IAAa,sBAAb,MAAa,oBAAoB;CAC/B,AAAQ,kBAA0B;CAClC,AAAQ,QAAQ;CAChB,AAAQ,YAAY;CACpB,AAAQ,WAAW;CACnB,AAAQ,kBAA0C;CAClD,AAAiB;;;;;CAMjB,AAAQ,YAAY,SAAqC;AAEvD,OAAK,UAAU;GACb,GAAG;GACH,WAAW,QAAQ,aAAa,KAAK,OAAO;GAC5C,SACE,QAAQ,YACP,YAAY;AAEX,WAAO;;GAEZ;AAED,MAAI,KAAK,YAAY,EACnB,OAAM,IAAI,MAAM,kCAAkC;AAEpD,MAAI,KAAK,aAAa,EACpB,OAAM,IAAI,MAAM,8BAA8B;;;;;CAOlD,IAAY,aAAa;AACvB,SAAO,KAAK,QAAQ;;;;;CAMtB,IAAY,YAAY;AACtB,SAAO,KAAK,QAAQ;;;;;CAMtB,IAAY,YAAY;AACtB,SAAO,KAAK,QAAQ;;;;;CAMtB,IAAY,UAAU;AACpB,SAAO,KAAK,QAAQ;;;;;;;;;;;;;;;;;;;;CAqBtB,OAAO,OAAO,SAAiE;AAE7E,SADe,IAAI,oBAAoB,QAAQ,CACjC,cAAc;;CAG9B,AAAQ,YAAY;AAClB,OAAK,QAAQ;;CAGf,AAAQ,WAAW;AACjB,OAAK,QAAQ;;CAGf,MAAc,QAAQ,YAA2E;AAC/F,MAAI,KAAK,UACP,QAAO;AAIT,MAAI,KAAK,YAAY,EAAE;AACrB,cAAW,OAAO;AAClB,UAAO;;AAGT,MAAI;GAGF,MAAM,cAAc,KAAK,IAAI,KAAK,kBAAkB,KAAK,WAAW,KAAK,UAAU;GAGnF,MAAM,OAAO,MAAM,KAAK,WACtB;IAAE,MAAM,KAAK;IAAiB,IAAI;IAAa,EAC/C,KAAK,iBAAiB,OACvB;AAGD,OAAI,KAAK,UACP,QAAO;AAIT,cAAW,QAAQ,KAAK;AAGxB,QAAK,kBAAkB;AAEvB,OAAI,CAAC,WAAW,eAAe,WAAW,eAAe,EAGvD,MAAK,UAAU;WAEV,OAAO;GAEd,MAAM,SAAS,MAAM,KAAK,QAAQ,MAAM;AAExC,OAAI,WAAW,SAAS;AACtB,SAAK,WAAW;AAEhB,eAAW,MAAM,MAAM;AACvB,SAAK,iBAAiB,MAAM,iBAAiB;AAC7C,WAAO;;AAGT,OAAI,WAAW,UAAU;AACvB,SAAK,YAAY;AAEjB,eAAW,OAAO;AAClB,SAAK,iBAAiB,MAAM,mBAAmB;AAC/C,YAAQ,MAAM,6CAA6C;AAC3D,WAAO;;;AAIX,SAAO;;;;;;;;;CAUT,AAAQ,eAA2C;AAEjD,OAAK,kBAAkB,IAAI,iBAAiB;AAE5C,SAAO,IAAI,eAAe;GACxB,OAAO,OAAO,eAAe;AAC3B,WAAO,MAAM;AACX,SAAI,KAAK,aAAa,KAAK,SACzB;AAGF,SAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,SAAS,MAAM,WAAW,GAAG,EAAE,CAAC;AAC1C,UAAI,WAAW,YACb,MAAK,WAAW;gBAGH,MAAM,KAAK,QAAQ,WAAW,CAE3C;;;GAMR,YAAY;AACV,SAAK,WAAW;;GAGlB,SAAS,WAAW;AAClB,SAAK,YAAY;AAEjB,SAAK,iBAAiB,MAAM,OAAO;AACnC,YAAQ,MAAM,kCAAkC,OAAO;;GAE1D,CAAC;;;;;;;CAQJ,qBAA6B;AAC3B,SAAO,KAAK;;;;;;;CAQd,oBAA4B;AAC1B,SAAO,KAAK,IAAI,GAAG,KAAK,YAAY,KAAK,gBAAgB;;;;;;;CAQ3D,aAAsB;AACpB,SAAO,KAAK,mBAAmB,KAAK"}