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.
- package/LICENSE +21 -0
- package/README.md +128 -28
- package/dist/_bytes-builder.d.ts +34 -0
- package/dist/_bytes-builder.d.ts.map +1 -0
- package/dist/_bytes-builder.js +48 -0
- package/dist/cache-storage.d.ts +74 -0
- package/dist/cache-storage.d.ts.map +1 -0
- package/dist/cache-storage.js +1 -0
- package/dist/dl-once.d.ts +242 -0
- package/dist/dl-once.d.ts.map +1 -0
- package/dist/dl-once.js +245 -0
- package/dist/hash-verification-hook.d.ts +46 -0
- package/dist/hash-verification-hook.d.ts.map +1 -0
- package/dist/hash-verification-hook.js +97 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/indexeddb-cache-storage.d.ts +51 -0
- package/dist/indexeddb-cache-storage.d.ts.map +1 -0
- package/dist/indexeddb-cache-storage.js +573 -0
- package/dist/md5-verification-hook.d.ts +15 -0
- package/dist/md5-verification-hook.d.ts.map +1 -0
- package/dist/md5-verification-hook.js +17 -0
- package/dist/memory-cache-storage.d.ts +41 -0
- package/dist/memory-cache-storage.d.ts.map +1 -0
- package/dist/memory-cache-storage.js +290 -0
- package/dist/node-fs-cache-storage.d.ts +63 -0
- package/dist/node-fs-cache-storage.d.ts.map +1 -0
- package/dist/node-fs-cache-storage.js +565 -0
- package/dist/sha256-verification-hook.d.ts +15 -0
- package/dist/sha256-verification-hook.d.ts.map +1 -0
- package/dist/sha256-verification-hook.js +17 -0
- package/package.json +46 -7
- package/src/_bytes-builder.ts +66 -0
- package/src/cache-storage.ts +86 -0
- package/src/dl-once.ts +554 -0
- package/src/hash-verification-hook.ts +98 -0
- package/src/index.ts +28 -0
- package/src/indexeddb-cache-storage.ts +535 -0
- package/src/md5-verification-hook.ts +18 -0
- package/src/memory-cache-storage.ts +361 -0
- package/src/node-fs-cache-storage.ts +511 -0
- package/src/sha256-verification-hook.ts +18 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { tryCaptureStackTrace } from "try-capture-stack-trace";
|
|
2
|
+
import type { ClearOptions, CloseOptions, ICacheStorage, OpenOptions } from "./cache-storage.js";
|
|
3
|
+
import type { GetReaderArgs, GetWriterArgs, ICacheHandle, IWriter } from "./dl-once.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 中断理由が設定されていないことを示すための初期値シンボルです。
|
|
7
|
+
*/
|
|
8
|
+
const NONE = Symbol();
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* メモリーキャッシュへの書き込みを担当するクラスです。
|
|
12
|
+
*
|
|
13
|
+
* データのチャンクを一時的に蓄積し、完了時にストレージへ保存します。
|
|
14
|
+
*/
|
|
15
|
+
class MemoryCacheWriter implements IWriter {
|
|
16
|
+
/**
|
|
17
|
+
* 参照先のメモリーキャッシュストレージです。
|
|
18
|
+
*/
|
|
19
|
+
readonly #storage: MemoryCacheStorage;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 書き込み完了時に実行されるコールバック関数です。
|
|
23
|
+
*/
|
|
24
|
+
#onComplete: (data: Uint8Array<ArrayBuffer>[]) => void;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 書き込まれたバイナリーデータのチャンクを保持する配列です。
|
|
28
|
+
*/
|
|
29
|
+
#buffer: Uint8Array<ArrayBuffer>[];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 書き込みが中断(abort)された際の理由を保持します。
|
|
33
|
+
*/
|
|
34
|
+
#reason: unknown;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ライターが閉じられたかどうかを管理するフラグです。
|
|
38
|
+
*/
|
|
39
|
+
#isClosed: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* MemoryCacheWriter の新しいインスタンスを生成します。
|
|
43
|
+
*
|
|
44
|
+
* @param storage 関連付けられたメモリーキャッシュストレージです。
|
|
45
|
+
* @param onComplete 書き込み成功時にチャンク配列を受け取るコールバックです。
|
|
46
|
+
*/
|
|
47
|
+
constructor(
|
|
48
|
+
storage: MemoryCacheStorage,
|
|
49
|
+
onComplete: (buffer: Uint8Array<ArrayBuffer>[]) => void,
|
|
50
|
+
) {
|
|
51
|
+
this.#storage = storage;
|
|
52
|
+
this.#onComplete = onComplete;
|
|
53
|
+
this.#buffer = [];
|
|
54
|
+
this.#reason = NONE;
|
|
55
|
+
this.#isClosed = false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* このインスタンスが利用可能かどうかを確認します。
|
|
60
|
+
*/
|
|
61
|
+
#assertOk(): void {
|
|
62
|
+
// ストレージ本体が有効であることを確認します。
|
|
63
|
+
if (!this.#storage.isOpen) {
|
|
64
|
+
const error = new Error("MemoryCacheStorage is closed");
|
|
65
|
+
tryCaptureStackTrace(error, this.#assertOk);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ライターがクローズまたはアボート済みでないか確認します。
|
|
70
|
+
if (this.#isClosed) {
|
|
71
|
+
// 異常終了(abort)している場合はその理由を、正常終了している場合は標準エラーを投げます。
|
|
72
|
+
if (this.#reason === NONE) {
|
|
73
|
+
const error = new Error("MemoryCacheWriter is closed");
|
|
74
|
+
tryCaptureStackTrace(error, this.#assertOk);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
throw this.#reason;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* データのチャンクを内部バッファーに書き込みます。
|
|
84
|
+
*
|
|
85
|
+
* @param chunkData 書き込むバイナリーデータです。
|
|
86
|
+
*/
|
|
87
|
+
public write(chunkData: Uint8Array<ArrayBuffer>): void {
|
|
88
|
+
this.#assertOk();
|
|
89
|
+
|
|
90
|
+
// メモリー上の配列にチャンクを追加します。
|
|
91
|
+
this.#buffer.push(chunkData);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 書き込みを正常に終了し、蓄積されたデータを確定させます。
|
|
96
|
+
*/
|
|
97
|
+
public close(): void {
|
|
98
|
+
this.#assertOk();
|
|
99
|
+
|
|
100
|
+
// 蓄積した全チャンクをコールバックに渡し、キャッシュとして確定させます。
|
|
101
|
+
this.#onComplete(this.#buffer);
|
|
102
|
+
|
|
103
|
+
this.#onComplete = () => {};
|
|
104
|
+
this.#buffer = [];
|
|
105
|
+
this.#isClosed = true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 書き込みを中断し、蓄積されたデータを破棄します。
|
|
110
|
+
*
|
|
111
|
+
* @param reason 中断した理由(エラーオブジェクトなど)です。
|
|
112
|
+
*/
|
|
113
|
+
public abort(reason: unknown): void {
|
|
114
|
+
this.#assertOk();
|
|
115
|
+
|
|
116
|
+
// 蓄積していたバッファーを直ちに解放します。
|
|
117
|
+
this.#buffer = [];
|
|
118
|
+
this.#reason = reason;
|
|
119
|
+
this.#isClosed = true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 特定のキーに対応するキャッシュデータを操作するためのハンドルです。
|
|
125
|
+
*/
|
|
126
|
+
class MemoryCacheHandle implements ICacheHandle {
|
|
127
|
+
/**
|
|
128
|
+
* 親となるストレージインスタンスです。
|
|
129
|
+
*/
|
|
130
|
+
readonly #storage: MemoryCacheStorage;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* キャッシュされたバイナリーデータのリストです。まだデータがない場合は null です。
|
|
134
|
+
*/
|
|
135
|
+
#buffer: Uint8Array<ArrayBuffer>[] | null;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* MemoryCacheHandle の新しいインスタンスを生成します。
|
|
139
|
+
*
|
|
140
|
+
* @param storage 関連付けられたメモリーキャッシュストレージです。
|
|
141
|
+
*/
|
|
142
|
+
public constructor(storage: MemoryCacheStorage) {
|
|
143
|
+
this.#storage = storage;
|
|
144
|
+
this.#buffer = null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* このインスタンスが利用可能かどうかを確認します。
|
|
149
|
+
*/
|
|
150
|
+
#assertOk(): void {
|
|
151
|
+
// ストレージ本体が有効であることを確認します。
|
|
152
|
+
if (!this.#storage.isOpen) {
|
|
153
|
+
const error = new Error("MemoryCacheStorage is closed");
|
|
154
|
+
tryCaptureStackTrace(error, this.#assertOk);
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* キャッシュされたデータをクリアします。
|
|
161
|
+
*/
|
|
162
|
+
public clear(): void {
|
|
163
|
+
this.#assertOk();
|
|
164
|
+
|
|
165
|
+
this.#buffer = null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* キャッシュされたデータを読み取るためのイテレーターを取得します。
|
|
170
|
+
*
|
|
171
|
+
* @returns データのチャンクを順次返すイテレーターを返します。キャッシュがない場合は null を返します。
|
|
172
|
+
*/
|
|
173
|
+
public getReader(args: GetReaderArgs): Generator<Uint8Array<ArrayBuffer>, void, unknown> | null {
|
|
174
|
+
const { signal } = args;
|
|
175
|
+
|
|
176
|
+
signal?.throwIfAborted();
|
|
177
|
+
|
|
178
|
+
this.#assertOk();
|
|
179
|
+
|
|
180
|
+
// まだ書き込みが完了していない(キャッシュデータがない)場合は null を返して終了します。
|
|
181
|
+
if (!this.#buffer) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const buffer = this.#buffer;
|
|
186
|
+
const storage = this.#storage;
|
|
187
|
+
|
|
188
|
+
function* createReader() {
|
|
189
|
+
// 保存されているチャンクを順番に yield します。
|
|
190
|
+
for (const chunk of buffer) {
|
|
191
|
+
// 読み取り中にストレージが破棄されていないか確認します。
|
|
192
|
+
if (!storage.isOpen) {
|
|
193
|
+
throw new Error("MemoryCacheStorage is closed");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
yield chunk;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return createReader();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* キャッシュにデータを書き込むためのライターを生成します。
|
|
205
|
+
*
|
|
206
|
+
* @returns IWriter インターフェースを実装したライターオブジェクトを返します。
|
|
207
|
+
*/
|
|
208
|
+
public getWriter(args: GetWriterArgs): MemoryCacheWriter {
|
|
209
|
+
const { signal } = args;
|
|
210
|
+
|
|
211
|
+
signal?.throwIfAborted();
|
|
212
|
+
|
|
213
|
+
this.#assertOk();
|
|
214
|
+
|
|
215
|
+
// ライターが close されたときに、このハンドル内の #buffer にデータがセットされるようにします。
|
|
216
|
+
return new MemoryCacheWriter(this.#storage, buffer => {
|
|
217
|
+
this.#buffer = buffer;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* メモリー上でのデータキャッシュを管理するストレージクラスです。
|
|
224
|
+
*
|
|
225
|
+
* Map を使用してキーごとにキャッシュハンドルを保持します。
|
|
226
|
+
*/
|
|
227
|
+
export default class MemoryCacheStorage implements ICacheStorage, Disposable {
|
|
228
|
+
/**
|
|
229
|
+
* キャッシュキーとハンドルの対応を保持する内部マップです。
|
|
230
|
+
*
|
|
231
|
+
* ストレージが閉じているときは null になります。
|
|
232
|
+
*/
|
|
233
|
+
#store: Map<string, MemoryCacheHandle> | null = null;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* このインスタンスが利用可能かどうかを確認します。
|
|
237
|
+
*/
|
|
238
|
+
#assertOk(): void {
|
|
239
|
+
// ストレージ本体が有効であることを確認します。
|
|
240
|
+
if (!this.isOpen) {
|
|
241
|
+
const error = new Error("MemoryCacheStorage is closed");
|
|
242
|
+
tryCaptureStackTrace(error, this.#assertOk);
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* ストレージが現在開いているかどうかを返します。
|
|
249
|
+
*/
|
|
250
|
+
public get isOpen(): boolean {
|
|
251
|
+
return !!this.#store;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* ストレージを開き、利用可能な状態にします。
|
|
256
|
+
*/
|
|
257
|
+
public open(options: OpenOptions | undefined = {}): void {
|
|
258
|
+
const { signal } = options;
|
|
259
|
+
|
|
260
|
+
signal?.throwIfAborted();
|
|
261
|
+
|
|
262
|
+
if (this.#store) {
|
|
263
|
+
throw new Error("Storage is already open");
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.#store = new Map();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* ストレージを閉じ、すべてのキャッシュデータを破棄します。
|
|
271
|
+
*/
|
|
272
|
+
public close(options: CloseOptions | undefined = {}): void {
|
|
273
|
+
const { signal } = options;
|
|
274
|
+
|
|
275
|
+
signal?.throwIfAborted();
|
|
276
|
+
|
|
277
|
+
this.#assertOk();
|
|
278
|
+
|
|
279
|
+
// メモリ解放のためマップをクリアし、null を代入します。
|
|
280
|
+
this.#store!.clear();
|
|
281
|
+
this.#store = null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Explicit Resource Management (Using 構文) をサポートするための破棄メソッドです。
|
|
286
|
+
*/
|
|
287
|
+
public [Symbol.dispose](): void {
|
|
288
|
+
// 既に閉じられている可能性を考慮し、オプショナルチェイニングを使用してクリアします。
|
|
289
|
+
this.#store?.clear();
|
|
290
|
+
this.#store = null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* キャッシュをクリアします。引数が指定された場合はそのキーのみ、指定されない場合は全てのキャッシュを削除します。
|
|
295
|
+
*
|
|
296
|
+
* @param cacheKey キャッシュを一意に識別する文字列です。
|
|
297
|
+
*/
|
|
298
|
+
public clear(
|
|
299
|
+
cacheKey?: string | undefined,
|
|
300
|
+
options?: Omit<ClearOptions, "cacheKey"> | undefined,
|
|
301
|
+
): void;
|
|
302
|
+
|
|
303
|
+
public clear(options?: ClearOptions | undefined): void;
|
|
304
|
+
|
|
305
|
+
public clear(
|
|
306
|
+
cacheKeyOrOptions?: string | ClearOptions | undefined,
|
|
307
|
+
options: Omit<ClearOptions, "cacheKey"> | undefined = {},
|
|
308
|
+
): void {
|
|
309
|
+
// 引数の型に応じてオプションを正規化します。
|
|
310
|
+
const {
|
|
311
|
+
signal,
|
|
312
|
+
cacheKey,
|
|
313
|
+
} = typeof cacheKeyOrOptions === "object"
|
|
314
|
+
? cacheKeyOrOptions
|
|
315
|
+
: {
|
|
316
|
+
...options,
|
|
317
|
+
cacheKey: cacheKeyOrOptions,
|
|
318
|
+
};
|
|
319
|
+
signal?.throwIfAborted();
|
|
320
|
+
|
|
321
|
+
this.#assertOk();
|
|
322
|
+
|
|
323
|
+
const store = this.#store!;
|
|
324
|
+
|
|
325
|
+
if (cacheKey !== undefined) {
|
|
326
|
+
const handle = store.get(cacheKey);
|
|
327
|
+
if (handle) {
|
|
328
|
+
handle.clear();
|
|
329
|
+
store.delete(cacheKey);
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
// 全てのハンドルのデータをクリアしてから Map を空にする
|
|
333
|
+
for (const handle of store.values()) {
|
|
334
|
+
handle.clear();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
store.clear();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* 指定したキーに対応するキャッシュハンドルを取得、または新規作成します。
|
|
343
|
+
*
|
|
344
|
+
* @param key キャッシュを一意に識別する文字列です。
|
|
345
|
+
* @returns ICacheHandle を実装したオブジェクトを返します。
|
|
346
|
+
*/
|
|
347
|
+
public createCacheHandle(key: string): ICacheHandle {
|
|
348
|
+
this.#assertOk();
|
|
349
|
+
|
|
350
|
+
const store = this.#store!;
|
|
351
|
+
|
|
352
|
+
// 既にハンドルが存在すればそれを返し、なければ新規作成してストアに登録します。
|
|
353
|
+
let handle = store.get(key);
|
|
354
|
+
if (!handle) {
|
|
355
|
+
handle = new MemoryCacheHandle(this);
|
|
356
|
+
store.set(key, handle);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return handle;
|
|
360
|
+
}
|
|
361
|
+
}
|