dl-once 0.0.1 → 0.0.2

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -28
  3. package/dist/_bytes-builder.d.ts +34 -0
  4. package/dist/_bytes-builder.d.ts.map +1 -0
  5. package/dist/_bytes-builder.js +48 -0
  6. package/dist/cache-storage.d.ts +74 -0
  7. package/dist/cache-storage.d.ts.map +1 -0
  8. package/dist/cache-storage.js +1 -0
  9. package/dist/dl-once.d.ts +242 -0
  10. package/dist/dl-once.d.ts.map +1 -0
  11. package/dist/dl-once.js +245 -0
  12. package/dist/hash-verification-hook.d.ts +46 -0
  13. package/dist/hash-verification-hook.d.ts.map +1 -0
  14. package/dist/hash-verification-hook.js +97 -0
  15. package/dist/index.d.ts +16 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +8 -0
  18. package/dist/indexeddb-cache-storage.d.ts +51 -0
  19. package/dist/indexeddb-cache-storage.d.ts.map +1 -0
  20. package/dist/indexeddb-cache-storage.js +573 -0
  21. package/dist/md5-verification-hook.d.ts +15 -0
  22. package/dist/md5-verification-hook.d.ts.map +1 -0
  23. package/dist/md5-verification-hook.js +17 -0
  24. package/dist/memory-cache-storage.d.ts +41 -0
  25. package/dist/memory-cache-storage.d.ts.map +1 -0
  26. package/dist/memory-cache-storage.js +290 -0
  27. package/dist/node-fs-cache-storage.d.ts +63 -0
  28. package/dist/node-fs-cache-storage.d.ts.map +1 -0
  29. package/dist/node-fs-cache-storage.js +565 -0
  30. package/dist/sha256-verification-hook.d.ts +15 -0
  31. package/dist/sha256-verification-hook.d.ts.map +1 -0
  32. package/dist/sha256-verification-hook.js +17 -0
  33. package/package.json +46 -7
  34. package/src/_bytes-builder.ts +66 -0
  35. package/src/cache-storage.ts +86 -0
  36. package/src/dl-once.ts +554 -0
  37. package/src/hash-verification-hook.ts +98 -0
  38. package/src/index.ts +28 -0
  39. package/src/indexeddb-cache-storage.ts +535 -0
  40. package/src/md5-verification-hook.ts +18 -0
  41. package/src/memory-cache-storage.ts +361 -0
  42. package/src/node-fs-cache-storage.ts +511 -0
  43. package/src/sha256-verification-hook.ts +18 -0
@@ -0,0 +1,573 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
36
+ if (value !== null && value !== void 0) {
37
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
38
+ var dispose, inner;
39
+ if (async) {
40
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
41
+ dispose = value[Symbol.asyncDispose];
42
+ }
43
+ if (dispose === void 0) {
44
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
45
+ dispose = value[Symbol.dispose];
46
+ if (async) inner = dispose;
47
+ }
48
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
49
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
50
+ env.stack.push({ value: value, dispose: dispose, async: async });
51
+ }
52
+ else if (async) {
53
+ env.stack.push({ async: true });
54
+ }
55
+ return value;
56
+ };
57
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
58
+ return function (env) {
59
+ function fail(e) {
60
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
61
+ env.hasError = true;
62
+ }
63
+ var r, s = 0;
64
+ function next() {
65
+ while (r = env.stack.pop()) {
66
+ try {
67
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
68
+ if (r.dispose) {
69
+ var result = r.dispose.call(r.value);
70
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
71
+ }
72
+ else s |= 1;
73
+ }
74
+ catch (e) {
75
+ fail(e);
76
+ }
77
+ }
78
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
79
+ if (env.hasError) throw env.error;
80
+ }
81
+ return next();
82
+ };
83
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
84
+ var e = new Error(message);
85
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
86
+ });
87
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
88
+ if (kind === "m") throw new TypeError("Private method is not writable");
89
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
90
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
91
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
92
+ };
93
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
94
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
95
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
96
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
97
+ };
98
+ var _IndexedDbCacheHandle_instances, _IndexedDbCacheHandle_storage, _IndexedDbCacheHandle_db, _IndexedDbCacheHandle_mux, _IndexedDbCacheHandle_cacheKey, _IndexedDbCacheHandle_assertOk, _IndexedDbCacheStorage_instances, _IndexedDbCacheStorage_db, _IndexedDbCacheStorage_mux, _IndexedDbCacheStorage_dbName, _IndexedDbCacheStorage_assertOk;
99
+ import { Asyncmux, asyncmux } from "asyncmux";
100
+ import { openDB } from "idb";
101
+ import { tryCaptureStackTrace } from "try-capture-stack-trace";
102
+ /**
103
+ * IndexedDB を開くためのユーティリティー関数です。
104
+ */
105
+ const openIdb = (openDB);
106
+ /**
107
+ * 中断理由が設定されていないことを示すための初期値シンボルです。
108
+ */
109
+ const NONE = Symbol();
110
+ /**
111
+ * 指定された非同期破棄処理を実行する AsyncDisposable オブジェクトを作成します。
112
+ *
113
+ * @param onAsyncDispose 破棄時に実行される非同期関数です。
114
+ * @returns 非同期破棄インターフェースを実装したオブジェクトです。
115
+ */
116
+ function defer(onAsyncDispose) {
117
+ return { [Symbol.asyncDispose]: onAsyncDispose };
118
+ }
119
+ /**
120
+ * IndexedDB に対してキャッシュデータの書き込みを行うクラスです。
121
+ */
122
+ let IndexedDbCacheWriter = (() => {
123
+ var _IndexedDbCacheWriter_instances, _a, _IndexedDbCacheWriter_storage, _IndexedDbCacheWriter_db, _IndexedDbCacheWriter_cacheKey, _IndexedDbCacheWriter_reason, _IndexedDbCacheWriter_isClosed, _IndexedDbCacheWriter_chunkCounter, _IndexedDbCacheWriter_assertOk;
124
+ let _instanceExtraInitializers = [];
125
+ let _write_decorators;
126
+ let _close_decorators;
127
+ let _abort_decorators;
128
+ return _a = class IndexedDbCacheWriter {
129
+ /**
130
+ * IndexedDbCacheWriter のインスタンスを初期化します。
131
+ *
132
+ * @param storage 親となるストレージインスタンスです。
133
+ * @param db 操作対象のデータベースです。
134
+ * @param cacheKey キャッシュの識別キーです。
135
+ */
136
+ constructor(storage, db, cacheKey) {
137
+ _IndexedDbCacheWriter_instances.add(this);
138
+ /**
139
+ * ストレージ本体への参照です。
140
+ */
141
+ _IndexedDbCacheWriter_storage.set(this, __runInitializers(this, _instanceExtraInitializers));
142
+ /**
143
+ * 使用する IndexedDB インスタンスです。
144
+ */
145
+ _IndexedDbCacheWriter_db.set(this, void 0);
146
+ /**
147
+ * 対象となるキャッシュキーです。
148
+ */
149
+ _IndexedDbCacheWriter_cacheKey.set(this, void 0);
150
+ /**
151
+ * 中断された際の理由です。
152
+ */
153
+ _IndexedDbCacheWriter_reason.set(this, void 0);
154
+ /**
155
+ * ライターが閉じられているかどうかを示すフラグです。
156
+ */
157
+ _IndexedDbCacheWriter_isClosed.set(this, void 0);
158
+ /**
159
+ * チャンクのカウンターです。
160
+ */
161
+ _IndexedDbCacheWriter_chunkCounter.set(this, void 0);
162
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_storage, storage, "f");
163
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_db, db, "f");
164
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_cacheKey, cacheKey, "f");
165
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_reason, NONE, "f");
166
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_isClosed, false, "f");
167
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_chunkCounter, 0, "f");
168
+ }
169
+ /**
170
+ * チャンクデータを IndexedDB に書き込みます。
171
+ *
172
+ * @param chunkData 書き込むバイナリーデータです。
173
+ */
174
+ async write(chunkData) {
175
+ __classPrivateFieldGet(this, _IndexedDbCacheWriter_instances, "m", _IndexedDbCacheWriter_assertOk).call(this);
176
+ // インデックスをインクリメントしながら、各チャンクを個別のキーで保存します。
177
+ const index = __classPrivateFieldGet(this, _IndexedDbCacheWriter_chunkCounter, "f");
178
+ await __classPrivateFieldGet(this, _IndexedDbCacheWriter_db, "f").put("buff", chunkData, `${__classPrivateFieldGet(this, _IndexedDbCacheWriter_cacheKey, "f")}:${index}`);
179
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_chunkCounter, __classPrivateFieldGet(this, _IndexedDbCacheWriter_chunkCounter, "f") + 1, "f");
180
+ }
181
+ /**
182
+ * 書き込みを完了し、メタデータを保存してライターを閉じます。
183
+ */
184
+ async close() {
185
+ __classPrivateFieldGet(this, _IndexedDbCacheWriter_instances, "m", _IndexedDbCacheWriter_assertOk).call(this);
186
+ // これまでに書き込んだチャンクの総数をメタデータとして保存します。
187
+ const chunkCount = __classPrivateFieldGet(this, _IndexedDbCacheWriter_chunkCounter, "f");
188
+ const meta = {
189
+ chunkCount,
190
+ };
191
+ await __classPrivateFieldGet(this, _IndexedDbCacheWriter_db, "f").put("meta", meta, __classPrivateFieldGet(this, _IndexedDbCacheWriter_cacheKey, "f"));
192
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_isClosed, true, "f");
193
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_chunkCounter, 0, "f");
194
+ }
195
+ /**
196
+ * 書き込みを中断し、これまでに書き込んだ一時的なチャンクデータを削除します。
197
+ *
198
+ * @param reason 中断した理由です。
199
+ */
200
+ async abort(reason) {
201
+ __classPrivateFieldGet(this, _IndexedDbCacheWriter_instances, "m", _IndexedDbCacheWriter_assertOk).call(this);
202
+ const chunkCount = __classPrivateFieldGet(this, _IndexedDbCacheWriter_chunkCounter, "f");
203
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_reason, reason, "f");
204
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_isClosed, true, "f");
205
+ __classPrivateFieldSet(this, _IndexedDbCacheWriter_chunkCounter, 0, "f");
206
+ // 書き込まれたチャンクがない場合は削除処理をスキップします。
207
+ if (chunkCount === 0) {
208
+ return;
209
+ }
210
+ // 0 から chunkCount - 1 までの範囲キーを作成し、一括削除します。
211
+ const range = IDBKeyRange.bound(`${__classPrivateFieldGet(this, _IndexedDbCacheWriter_cacheKey, "f")}:0`, `${__classPrivateFieldGet(this, _IndexedDbCacheWriter_cacheKey, "f")}:${chunkCount - 1}`);
212
+ await __classPrivateFieldGet(this, _IndexedDbCacheWriter_db, "f").delete("buff", range);
213
+ }
214
+ },
215
+ _IndexedDbCacheWriter_storage = new WeakMap(),
216
+ _IndexedDbCacheWriter_db = new WeakMap(),
217
+ _IndexedDbCacheWriter_cacheKey = new WeakMap(),
218
+ _IndexedDbCacheWriter_reason = new WeakMap(),
219
+ _IndexedDbCacheWriter_isClosed = new WeakMap(),
220
+ _IndexedDbCacheWriter_chunkCounter = new WeakMap(),
221
+ _IndexedDbCacheWriter_instances = new WeakSet(),
222
+ _IndexedDbCacheWriter_assertOk = function _IndexedDbCacheWriter_assertOk() {
223
+ // 親ストレージの稼働状態を確認します。
224
+ if (!__classPrivateFieldGet(this, _IndexedDbCacheWriter_storage, "f").isOpen) {
225
+ const error = new Error("IndexedDbCacheStorage is closed");
226
+ tryCaptureStackTrace(error, __classPrivateFieldGet(this, _IndexedDbCacheWriter_instances, "m", _IndexedDbCacheWriter_assertOk));
227
+ throw error;
228
+ }
229
+ // このライター自体の状態を確認します。
230
+ if (__classPrivateFieldGet(this, _IndexedDbCacheWriter_isClosed, "f")) {
231
+ // 正常に閉じられたのか、エラーで中断されたのかを判定します。
232
+ if (__classPrivateFieldGet(this, _IndexedDbCacheWriter_reason, "f") === NONE) {
233
+ const error = new Error("IndexedDbCacheWriter is closed");
234
+ tryCaptureStackTrace(error, __classPrivateFieldGet(this, _IndexedDbCacheWriter_instances, "m", _IndexedDbCacheWriter_assertOk));
235
+ throw error;
236
+ }
237
+ // 中断理由がある場合は、その理由(エラー等)をそのまま投げます。
238
+ throw __classPrivateFieldGet(this, _IndexedDbCacheWriter_reason, "f");
239
+ }
240
+ },
241
+ (() => {
242
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
243
+ _write_decorators = [asyncmux];
244
+ _close_decorators = [asyncmux];
245
+ _abort_decorators = [asyncmux];
246
+ __esDecorate(_a, null, _write_decorators, { kind: "method", name: "write", static: false, private: false, access: { has: obj => "write" in obj, get: obj => obj.write }, metadata: _metadata }, null, _instanceExtraInitializers);
247
+ __esDecorate(_a, null, _close_decorators, { kind: "method", name: "close", static: false, private: false, access: { has: obj => "close" in obj, get: obj => obj.close }, metadata: _metadata }, null, _instanceExtraInitializers);
248
+ __esDecorate(_a, null, _abort_decorators, { kind: "method", name: "abort", static: false, private: false, access: { has: obj => "abort" in obj, get: obj => obj.abort }, metadata: _metadata }, null, _instanceExtraInitializers);
249
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
250
+ })(),
251
+ _a;
252
+ })();
253
+ /**
254
+ * キャッシュされたデータへのアクセス(読み取り・書き込み)を管理するハンドルクラスです。
255
+ */
256
+ class IndexedDbCacheHandle {
257
+ /**
258
+ * IndexedDbCacheHandle のインスタンスを初期化します。
259
+ *
260
+ * @param storage ストレージインスタンスです。
261
+ * @param db データベースです。
262
+ * @param mux 同期用オブジェクトです。
263
+ * @param cacheKey キーです。
264
+ */
265
+ constructor(storage, db, mux, cacheKey) {
266
+ _IndexedDbCacheHandle_instances.add(this);
267
+ /**
268
+ * 親ストレージへの参照です。
269
+ */
270
+ _IndexedDbCacheHandle_storage.set(this, void 0);
271
+ /**
272
+ * データベースインスタンスです。
273
+ */
274
+ _IndexedDbCacheHandle_db.set(this, void 0);
275
+ /**
276
+ * 排他制御用のミューテックスです。
277
+ */
278
+ _IndexedDbCacheHandle_mux.set(this, void 0);
279
+ /**
280
+ * キャッシュキーです。
281
+ */
282
+ _IndexedDbCacheHandle_cacheKey.set(this, void 0);
283
+ __classPrivateFieldSet(this, _IndexedDbCacheHandle_storage, storage, "f");
284
+ __classPrivateFieldSet(this, _IndexedDbCacheHandle_db, db, "f");
285
+ __classPrivateFieldSet(this, _IndexedDbCacheHandle_mux, mux, "f");
286
+ __classPrivateFieldSet(this, _IndexedDbCacheHandle_cacheKey, cacheKey, "f");
287
+ }
288
+ /**
289
+ * キャッシュデータを読み取るためのジェネレーターを取得します。
290
+ *
291
+ * @param args 読み取りオプション(Signal 等)です。
292
+ * @returns キャッシュが存在する場合は AsyncGenerator、存在しない場合は null を返します。
293
+ */
294
+ async getReader(args) {
295
+ const env_1 = { stack: [], error: void 0, hasError: false };
296
+ try {
297
+ const { signal } = args;
298
+ // 読み取りロックを取得します。
299
+ const _1 = __addDisposableResource(env_1, await __classPrivateFieldGet(this, _IndexedDbCacheHandle_mux, "f").rLock({ signal }), false);
300
+ __classPrivateFieldGet(this, _IndexedDbCacheHandle_instances, "m", _IndexedDbCacheHandle_assertOk).call(this);
301
+ // メタデータを取得するために読み取り専用トランザクションを開始します。
302
+ const tx = __classPrivateFieldGet(this, _IndexedDbCacheHandle_db, "f").transaction(["meta"], "readonly");
303
+ // 外部からの中断シグナルをトランザクションの中断に連携させます。
304
+ signal?.addEventListener("abort", tx.abort, { once: true });
305
+ const _2 = __addDisposableResource(env_1, defer(async () => {
306
+ signal?.removeEventListener("abort", tx.abort);
307
+ }), true);
308
+ const metaStore = tx.objectStore("meta");
309
+ const meta = await metaStore.get(__classPrivateFieldGet(this, _IndexedDbCacheHandle_cacheKey, "f"));
310
+ // キャッシュ(メタデータ)が存在しない場合は null を返して終了します。
311
+ if (!meta) {
312
+ return null;
313
+ }
314
+ const db = __classPrivateFieldGet(this, _IndexedDbCacheHandle_db, "f");
315
+ const storage = __classPrivateFieldGet(this, _IndexedDbCacheHandle_storage, "f");
316
+ const cacheKey = __classPrivateFieldGet(this, _IndexedDbCacheHandle_cacheKey, "f");
317
+ const { chunkCount } = meta;
318
+ /**
319
+ * 実際のチャンク読み取りを行う内部非同期ジェネレーターです。
320
+ */
321
+ async function* createReader() {
322
+ // チャンク取得用のトランザクションを開始します。
323
+ const tx = db.transaction(["buff"], "readonly");
324
+ const buffStore = tx.objectStore("buff");
325
+ for (let index = 0; index < chunkCount; index++) {
326
+ // 読み取りの途中でストレージが閉じられていないか毎ステップ確認します。
327
+ if (!storage.isOpen) {
328
+ throw new Error("IndexedDbCacheStorage is closed");
329
+ }
330
+ const chunk = await buffStore.get(`${cacheKey}:${index}`);
331
+ if (!chunk) {
332
+ throw new Error(`Missing chunk at index ${index}`);
333
+ }
334
+ yield chunk;
335
+ }
336
+ }
337
+ return createReader();
338
+ }
339
+ catch (e_1) {
340
+ env_1.error = e_1;
341
+ env_1.hasError = true;
342
+ }
343
+ finally {
344
+ const result_1 = __disposeResources(env_1);
345
+ if (result_1)
346
+ await result_1;
347
+ }
348
+ }
349
+ /**
350
+ * キャッシュにデータを書き込むためのライターを取得します。
351
+ *
352
+ * @param args 書き込みオプションです。
353
+ * @returns IWriter インターフェースを実装したライターインスタンスです。
354
+ */
355
+ async getWriter(args) {
356
+ const env_2 = { stack: [], error: void 0, hasError: false };
357
+ try {
358
+ const { signal } = args;
359
+ // 書き込みの排他制御のためにロックを取得します。
360
+ const _1 = __addDisposableResource(env_2, await __classPrivateFieldGet(this, _IndexedDbCacheHandle_mux, "f").rLock({ signal }), false);
361
+ __classPrivateFieldGet(this, _IndexedDbCacheHandle_instances, "m", _IndexedDbCacheHandle_assertOk).call(this);
362
+ return new IndexedDbCacheWriter(__classPrivateFieldGet(this, _IndexedDbCacheHandle_storage, "f"), __classPrivateFieldGet(this, _IndexedDbCacheHandle_db, "f"), __classPrivateFieldGet(this, _IndexedDbCacheHandle_cacheKey, "f"));
363
+ }
364
+ catch (e_2) {
365
+ env_2.error = e_2;
366
+ env_2.hasError = true;
367
+ }
368
+ finally {
369
+ __disposeResources(env_2);
370
+ }
371
+ }
372
+ }
373
+ _IndexedDbCacheHandle_storage = new WeakMap(), _IndexedDbCacheHandle_db = new WeakMap(), _IndexedDbCacheHandle_mux = new WeakMap(), _IndexedDbCacheHandle_cacheKey = new WeakMap(), _IndexedDbCacheHandle_instances = new WeakSet(), _IndexedDbCacheHandle_assertOk = function _IndexedDbCacheHandle_assertOk() {
374
+ if (!__classPrivateFieldGet(this, _IndexedDbCacheHandle_storage, "f").isOpen) {
375
+ const error = new Error("IndexedDbCacheStorage is closed");
376
+ tryCaptureStackTrace(error, __classPrivateFieldGet(this, _IndexedDbCacheHandle_instances, "m", _IndexedDbCacheHandle_assertOk));
377
+ throw error;
378
+ }
379
+ };
380
+ /**
381
+ * IndexedDB をバックエンドとしたキャッシュストレージの実装クラスです。
382
+ */
383
+ export default class IndexedDbCacheStorage {
384
+ /**
385
+ * IndexedDbCacheStorage のインスタンスを初期化します。
386
+ *
387
+ * @param dbName データベース名です。指定されない場合はデフォルト名が使用されます。
388
+ */
389
+ constructor(dbName) {
390
+ _IndexedDbCacheStorage_instances.add(this);
391
+ /**
392
+ * データベース接続インスタンスです。閉じられているときは null になります。
393
+ */
394
+ _IndexedDbCacheStorage_db.set(this, void 0);
395
+ /**
396
+ * クラス全体での非同期操作の整合性を保つためのミューテックスです。
397
+ */
398
+ _IndexedDbCacheStorage_mux.set(this, void 0);
399
+ /**
400
+ * 使用する IndexedDB のデータベース名です。
401
+ */
402
+ _IndexedDbCacheStorage_dbName.set(this, void 0);
403
+ __classPrivateFieldSet(this, _IndexedDbCacheStorage_db, null, "f");
404
+ __classPrivateFieldSet(this, _IndexedDbCacheStorage_mux, new Asyncmux(), "f");
405
+ __classPrivateFieldSet(this, _IndexedDbCacheStorage_dbName, dbName ?? "dl-once", "f");
406
+ }
407
+ /**
408
+ * ストレージが開いているかどうかを返します。
409
+ */
410
+ get isOpen() {
411
+ return !!__classPrivateFieldGet(this, _IndexedDbCacheStorage_db, "f");
412
+ }
413
+ /**
414
+ * データベースを開き、初期化を行います。
415
+ *
416
+ * @param options オープン時のオプション(Signal 等)です。
417
+ */
418
+ async open(options = {}) {
419
+ const env_3 = { stack: [], error: void 0, hasError: false };
420
+ try {
421
+ const { signal } = options;
422
+ // 二重オープンを防止するためロックを取得します。
423
+ const _ = __addDisposableResource(env_3, await __classPrivateFieldGet(this, _IndexedDbCacheStorage_mux, "f").lock({ signal }), false);
424
+ if (__classPrivateFieldGet(this, _IndexedDbCacheStorage_db, "f")) {
425
+ throw new Error("Storage is already open");
426
+ }
427
+ // データベースを開き、必要に応じてオブジェクトストアを作成します。
428
+ __classPrivateFieldSet(this, _IndexedDbCacheStorage_db, await openIdb(__classPrivateFieldGet(this, _IndexedDbCacheStorage_dbName, "f"), 1, {
429
+ upgrade(db) {
430
+ if (!db.objectStoreNames.contains("meta")) {
431
+ db.createObjectStore("meta");
432
+ }
433
+ if (!db.objectStoreNames.contains("buff")) {
434
+ db.createObjectStore("buff");
435
+ }
436
+ },
437
+ }), "f");
438
+ }
439
+ catch (e_3) {
440
+ env_3.error = e_3;
441
+ env_3.hasError = true;
442
+ }
443
+ finally {
444
+ __disposeResources(env_3);
445
+ }
446
+ }
447
+ /**
448
+ * データベース接続を閉じます。
449
+ *
450
+ * @param options クローズ時のオプションです。
451
+ */
452
+ async close(options = {}) {
453
+ const env_4 = { stack: [], error: void 0, hasError: false };
454
+ try {
455
+ const { signal } = options;
456
+ const _ = __addDisposableResource(env_4, await __classPrivateFieldGet(this, _IndexedDbCacheStorage_mux, "f").lock({ signal }), false);
457
+ __classPrivateFieldGet(this, _IndexedDbCacheStorage_instances, "m", _IndexedDbCacheStorage_assertOk).call(this);
458
+ __classPrivateFieldGet(this, _IndexedDbCacheStorage_db, "f").close();
459
+ __classPrivateFieldSet(this, _IndexedDbCacheStorage_db, null, "f");
460
+ }
461
+ catch (e_4) {
462
+ env_4.error = e_4;
463
+ env_4.hasError = true;
464
+ }
465
+ finally {
466
+ __disposeResources(env_4);
467
+ }
468
+ }
469
+ /**
470
+ * `using` 構文等で利用される非同期破棄メソッドです。
471
+ *
472
+ * 接続が開いている場合は閉じます。
473
+ */
474
+ async [(_IndexedDbCacheStorage_db = new WeakMap(), _IndexedDbCacheStorage_mux = new WeakMap(), _IndexedDbCacheStorage_dbName = new WeakMap(), _IndexedDbCacheStorage_instances = new WeakSet(), _IndexedDbCacheStorage_assertOk = function _IndexedDbCacheStorage_assertOk() {
475
+ if (!this.isOpen) {
476
+ const error = new Error("IndexedDbCacheStorage is closed");
477
+ tryCaptureStackTrace(error, __classPrivateFieldGet(this, _IndexedDbCacheStorage_instances, "m", _IndexedDbCacheStorage_assertOk));
478
+ throw error;
479
+ }
480
+ }, Symbol.asyncDispose)]() {
481
+ const env_5 = { stack: [], error: void 0, hasError: false };
482
+ try {
483
+ const _ = __addDisposableResource(env_5, await __classPrivateFieldGet(this, _IndexedDbCacheStorage_mux, "f").lock(), false);
484
+ __classPrivateFieldGet(this, _IndexedDbCacheStorage_db, "f")?.close();
485
+ __classPrivateFieldSet(this, _IndexedDbCacheStorage_db, null, "f");
486
+ }
487
+ catch (e_5) {
488
+ env_5.error = e_5;
489
+ env_5.hasError = true;
490
+ }
491
+ finally {
492
+ __disposeResources(env_5);
493
+ }
494
+ }
495
+ async clear(cacheKeyOrOptions, options = {}) {
496
+ const env_6 = { stack: [], error: void 0, hasError: false };
497
+ try {
498
+ // 引数の型に応じてオプションを正規化します。
499
+ const { signal, cacheKey, } = typeof cacheKeyOrOptions === "object"
500
+ ? cacheKeyOrOptions
501
+ : {
502
+ ...options,
503
+ cacheKey: cacheKeyOrOptions,
504
+ };
505
+ // 削除操作の整合性を保つためロックを取得します。
506
+ const _1 = __addDisposableResource(env_6, await __classPrivateFieldGet(this, _IndexedDbCacheStorage_mux, "f").lock({ signal }), false);
507
+ __classPrivateFieldGet(this, _IndexedDbCacheStorage_instances, "m", _IndexedDbCacheStorage_assertOk).call(this);
508
+ // 読み書きトランザクションを開始します。
509
+ const tx = __classPrivateFieldGet(this, _IndexedDbCacheStorage_db, "f").transaction(["buff", "meta"], "readwrite");
510
+ signal?.addEventListener("abort", tx.abort, { once: true });
511
+ // トランザクション完了の待機とイベントリスナーの解除を行います。
512
+ const _2 = __addDisposableResource(env_6, defer(async () => {
513
+ try {
514
+ await tx.done;
515
+ }
516
+ finally {
517
+ signal?.removeEventListener("abort", tx.abort);
518
+ }
519
+ }), true);
520
+ if (cacheKey !== undefined) {
521
+ // 特定のキャッシュキーのみを削除する場合のロジックです。
522
+ const metaStore = tx.objectStore("meta");
523
+ const meta = await metaStore.get(cacheKey);
524
+ if (!meta) {
525
+ return;
526
+ }
527
+ // まずメタデータを削除します。
528
+ await metaStore.delete(cacheKey);
529
+ const { chunkCount } = meta;
530
+ const buffStore = tx.objectStore("buff");
531
+ // チャンク数に応じて削除戦略を切り替えます。
532
+ if (chunkCount === 0) {
533
+ // 削除するバッファーはありません。
534
+ }
535
+ else if (chunkCount === 1) {
536
+ // チャンクが 1 つだけなら直接削除します。
537
+ await buffStore.delete(`${cacheKey}:0`);
538
+ }
539
+ else {
540
+ // チャンクが複数あるなら、範囲指定で一括削除します。
541
+ const keyRange = IDBKeyRange.bound(`${cacheKey}:0`, `${cacheKey}:${chunkCount - 1}`);
542
+ await buffStore.delete(keyRange);
543
+ }
544
+ }
545
+ else {
546
+ // キャッシュキーが指定されていない場合は、すべてのストアの内容を消去します。
547
+ const metaStore = tx.objectStore("meta");
548
+ await metaStore.clear();
549
+ const buffStore = tx.objectStore("buff");
550
+ await buffStore.clear();
551
+ }
552
+ }
553
+ catch (e_6) {
554
+ env_6.error = e_6;
555
+ env_6.hasError = true;
556
+ }
557
+ finally {
558
+ const result_2 = __disposeResources(env_6);
559
+ if (result_2)
560
+ await result_2;
561
+ }
562
+ }
563
+ /**
564
+ * 指定したキーに対するキャッシュ操作ハンドルを作成します。
565
+ *
566
+ * @param key キャッシュキーです。
567
+ * @returns キャッシュハンドルインスタンスです。
568
+ */
569
+ createCacheHandle(key) {
570
+ __classPrivateFieldGet(this, _IndexedDbCacheStorage_instances, "m", _IndexedDbCacheStorage_assertOk).call(this);
571
+ return new IndexedDbCacheHandle(this, __classPrivateFieldGet(this, _IndexedDbCacheStorage_db, "f"), __classPrivateFieldGet(this, _IndexedDbCacheStorage_mux, "f"), key);
572
+ }
573
+ }
@@ -0,0 +1,15 @@
1
+ import HashVerificationHook from "./hash-verification-hook.js";
2
+ /**
3
+ * ダウンロードされたデータの MD5 ハッシュ値を検証するためのフッククラスです。
4
+ *
5
+ * `hash-wasm` ライブラリーを使用して、ストリーム読み込みに合わせて逐次的にハッシュ計算を行い、完了時に期待されるハッシュ値と一致するかを判定します。
6
+ */
7
+ export default class Md5VerificationHook extends HashVerificationHook {
8
+ /**
9
+ * Md5VerificationHook の新しいインスタンスを生成します。
10
+ *
11
+ * @param expectedHash 比較対象となる 16 進数形式の期待されるハッシュ値です。
12
+ */
13
+ constructor(expectedHash: string);
14
+ }
15
+ //# sourceMappingURL=md5-verification-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md5-verification-hook.d.ts","sourceRoot":"","sources":["../src/md5-verification-hook.ts"],"names":[],"mappings":"AACA,OAAO,oBAAoB,MAAM,6BAA6B,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,oBAAoB;IACnE;;;;OAIG;gBACgB,YAAY,EAAE,MAAM;CAGxC"}
@@ -0,0 +1,17 @@
1
+ import { createMD5 } from "hash-wasm";
2
+ import HashVerificationHook from "./hash-verification-hook.js";
3
+ /**
4
+ * ダウンロードされたデータの MD5 ハッシュ値を検証するためのフッククラスです。
5
+ *
6
+ * `hash-wasm` ライブラリーを使用して、ストリーム読み込みに合わせて逐次的にハッシュ計算を行い、完了時に期待されるハッシュ値と一致するかを判定します。
7
+ */
8
+ export default class Md5VerificationHook extends HashVerificationHook {
9
+ /**
10
+ * Md5VerificationHook の新しいインスタンスを生成します。
11
+ *
12
+ * @param expectedHash 比較対象となる 16 進数形式の期待されるハッシュ値です。
13
+ */
14
+ constructor(expectedHash) {
15
+ super(createMD5, expectedHash);
16
+ }
17
+ }
@@ -0,0 +1,41 @@
1
+ import type { ClearOptions, CloseOptions, ICacheStorage, OpenOptions } from "./cache-storage.js";
2
+ import type { ICacheHandle } from "./dl-once.js";
3
+ /**
4
+ * メモリー上でのデータキャッシュを管理するストレージクラスです。
5
+ *
6
+ * Map を使用してキーごとにキャッシュハンドルを保持します。
7
+ */
8
+ export default class MemoryCacheStorage implements ICacheStorage, Disposable {
9
+ #private;
10
+ /**
11
+ * ストレージが現在開いているかどうかを返します。
12
+ */
13
+ get isOpen(): boolean;
14
+ /**
15
+ * ストレージを開き、利用可能な状態にします。
16
+ */
17
+ open(options?: OpenOptions | undefined): void;
18
+ /**
19
+ * ストレージを閉じ、すべてのキャッシュデータを破棄します。
20
+ */
21
+ close(options?: CloseOptions | undefined): void;
22
+ /**
23
+ * Explicit Resource Management (Using 構文) をサポートするための破棄メソッドです。
24
+ */
25
+ [Symbol.dispose](): void;
26
+ /**
27
+ * キャッシュをクリアします。引数が指定された場合はそのキーのみ、指定されない場合は全てのキャッシュを削除します。
28
+ *
29
+ * @param cacheKey キャッシュを一意に識別する文字列です。
30
+ */
31
+ clear(cacheKey?: string | undefined, options?: Omit<ClearOptions, "cacheKey"> | undefined): void;
32
+ clear(options?: ClearOptions | undefined): void;
33
+ /**
34
+ * 指定したキーに対応するキャッシュハンドルを取得、または新規作成します。
35
+ *
36
+ * @param key キャッシュを一意に識別する文字列です。
37
+ * @returns ICacheHandle を実装したオブジェクトを返します。
38
+ */
39
+ createCacheHandle(key: string): ICacheHandle;
40
+ }
41
+ //# sourceMappingURL=memory-cache-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-cache-storage.d.ts","sourceRoot":"","sources":["../src/memory-cache-storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,KAAK,EAAgC,YAAY,EAAW,MAAM,cAAc,CAAC;AA2NxF;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,YAAW,aAAa,EAAE,UAAU;;IAoB1E;;OAEG;IACH,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED;;OAEG;IACI,IAAI,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,IAAI;IAYxD;;OAEG;IACI,KAAK,CAAC,OAAO,GAAE,YAAY,GAAG,SAAc,GAAG,IAAI;IAY1D;;OAEG;IACI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;IAM/B;;;;OAIG;IACI,KAAK,CACV,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,SAAS,GACnD,IAAI;IAEA,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAsCtD;;;;;OAKG;IACI,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY;CAcpD"}