@thi.ng/block-fs 0.3.0 → 0.4.1
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/CHANGELOG.md +22 -1
- package/README.md +88 -10
- package/cli.d.ts +2 -0
- package/cli.js +33 -18
- package/entry.d.ts +4 -4
- package/entry.js +18 -18
- package/fs.d.ts +4 -0
- package/fs.js +8 -1
- package/package.json +19 -16
- package/storage/memory.d.ts +1 -1
- package/storage/memory.js +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2025-04-
|
|
3
|
+
- **Last updated**: 2025-04-16T11:11:14Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -11,6 +11,27 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
11
11
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
12
12
|
and/or version bumps of transitive dependencies.
|
|
13
13
|
|
|
14
|
+
### [0.4.1](https://github.com/thi-ng/umbrella/tree/@thi.ng/block-fs@0.4.1) (2025-04-16)
|
|
15
|
+
|
|
16
|
+
#### ♻️ Refactoring
|
|
17
|
+
|
|
18
|
+
- update Entry memory layout ([b5416bd](https://github.com/thi-ng/umbrella/commit/b5416bd))
|
|
19
|
+
- move block start & end ID locations
|
|
20
|
+
|
|
21
|
+
## [0.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/block-fs@0.4.0) (2025-04-06)
|
|
22
|
+
|
|
23
|
+
#### 🚀 Features
|
|
24
|
+
|
|
25
|
+
- add support for wrapping `ArrayBuffer` ([e23f008](https://github.com/thi-ng/umbrella/commit/e23f008))
|
|
26
|
+
- update `MemoryBlockStorageOpts.buffer` to allow array buffers
|
|
27
|
+
- update `MemoryBlockStorage` ctor
|
|
28
|
+
- auto-infer MIME type in `.readAsObjectURL()` ([8fbcebd](https://github.com/thi-ng/umbrella/commit/8fbcebd))
|
|
29
|
+
- use `preferredTypeForPath()` as MIME type fallback
|
|
30
|
+
- update deps
|
|
31
|
+
- update CLI, add include/exclude regexp, logging ([ef04e09](https://github.com/thi-ng/umbrella/commit/ef04e09))
|
|
32
|
+
- add support for multiple include/exclude regexps in `convert` command
|
|
33
|
+
- add `--quiet` flag to disable logging
|
|
34
|
+
|
|
14
35
|
## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/block-fs@0.3.0) (2025-04-02)
|
|
15
36
|
|
|
16
37
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
- [Installation](#installation)
|
|
29
29
|
- [Dependencies](#dependencies)
|
|
30
30
|
- [API](#api)
|
|
31
|
+
- [Basic usage](#basic-usage)
|
|
32
|
+
- [Working with a converted file system blob](#working-with-a-converted-file-system-blob)
|
|
31
33
|
- [Authors](#authors)
|
|
32
34
|
- [License](#license)
|
|
33
35
|
|
|
@@ -94,16 +96,33 @@ entries/sizes. The default [`Entry`
|
|
|
94
96
|
implementation](https://docs.thi.ng/umbrella/block-fs/classes/Entry.html)
|
|
95
97
|
requires 64 bytes.
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+

|
|
98
100
|
|
|
99
101
|
#### File blocks
|
|
100
102
|
|
|
101
103
|
Files are stored as linked lists of blocks, with the first few bytes of each
|
|
102
|
-
block reserved for linkage and number of data bytes in the block.
|
|
103
|
-
bytes effectively available for data depends on the configured block size and
|
|
104
|
-
the max. number of blocks in the storage backend.
|
|
104
|
+
block reserved for linkage and number of data bytes in the block.
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+

|
|
107
|
+
|
|
108
|
+
The number of bytes effectively available for data depends on the configured
|
|
109
|
+
block size and the max. number of blocks in the storage backend. For example, a
|
|
110
|
+
max. block count of 65536 and a block size of 256 bytes only requires a two
|
|
111
|
+
bytes for linkage and a third byte for storing the number of data bytes used in
|
|
112
|
+
the block. Hence, in this configuration 253 bytes per block are available for
|
|
113
|
+
data.
|
|
114
|
+
|
|
115
|
+
The following diagram shows a block which links to block ID 0x1234 and uses the
|
|
116
|
+
full 253 (0xfd in hex) bytes of data available:
|
|
117
|
+
|
|
118
|
+

|
|
119
|
+
|
|
120
|
+
The last block of a file uses a special sentinel marker to indicate that no
|
|
121
|
+
other blocks follow. This sentinel value again depends on the configured max.
|
|
122
|
+
block count, and in this example is 0xffff. This example block only stores 64
|
|
123
|
+
(0x40 in hex) bytes of data, with the remainder zeroed out.
|
|
124
|
+
|
|
125
|
+

|
|
107
126
|
|
|
108
127
|
### Command line app
|
|
109
128
|
|
|
@@ -119,7 +138,8 @@ Once bundled, the binary blob can then be used together with
|
|
|
119
138
|
[`MemoryBlockStorage`](https://docs.thi.ng/umbrella/block-fs/classes/MemoryBlockStorage.html)
|
|
120
139
|
and [`BlockFS`](https://docs.thi.ng/umbrella/block-fs/classes/BlockFS.html) for
|
|
121
140
|
other purposes (e.g. distributed with your web app to provide a virtual
|
|
122
|
-
filesystem).
|
|
141
|
+
filesystem). Also see [API example further
|
|
142
|
+
below](#working-with-a-converted-file-system-blob).
|
|
123
143
|
|
|
124
144
|
Example usage to bundle the source directory of this package:
|
|
125
145
|
|
|
@@ -138,15 +158,31 @@ General usage:
|
|
|
138
158
|
```text
|
|
139
159
|
npx @thi.ng/block-fs convert --help
|
|
140
160
|
|
|
141
|
-
|
|
161
|
+
█ █ █ │
|
|
162
|
+
██ █ │
|
|
163
|
+
█ █ █ █ █ █ █ █ │ @thi.ng/block-fs 0.4.0
|
|
164
|
+
█ █ █ █ █ █ █ █ █ │ Block-based storage & file system layer
|
|
165
|
+
█ │
|
|
166
|
+
█ █ │
|
|
167
|
+
|
|
168
|
+
Usage: blockfs <cmd> [opts] input [...]
|
|
169
|
+
blockfs <cmd> --help
|
|
170
|
+
|
|
171
|
+
Available commands:
|
|
172
|
+
|
|
173
|
+
convert : Convert file tree into single BlockFS blob
|
|
174
|
+
list : List file tree of a BlockFS blob
|
|
142
175
|
|
|
143
176
|
Flags:
|
|
144
177
|
|
|
145
|
-
-
|
|
178
|
+
-q, --quiet Disable logging
|
|
179
|
+
-v, --verbose Display extra logging information
|
|
146
180
|
|
|
147
181
|
Main:
|
|
148
182
|
|
|
149
183
|
-bs BYTES, --block-size BYTES Block size (default: 1024)
|
|
184
|
+
-i EXT, --exclude EXT [multiple] File exclusion regexp
|
|
185
|
+
-i EXT, --include EXT [multiple] File inclusion regexp
|
|
150
186
|
-n INT, --num-blocks INT Number of blocks (multiple of 8)
|
|
151
187
|
-o STR, --out STR [required] Output file path
|
|
152
188
|
```
|
|
@@ -252,7 +288,7 @@ For Node.js REPL:
|
|
|
252
288
|
const bf = await import("@thi.ng/block-fs");
|
|
253
289
|
```
|
|
254
290
|
|
|
255
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 4.
|
|
291
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 4.50 KB
|
|
256
292
|
|
|
257
293
|
## Dependencies
|
|
258
294
|
|
|
@@ -264,6 +300,7 @@ Package sizes (brotli'd, pre-treeshake): ESM: 4.43 KB
|
|
|
264
300
|
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors)
|
|
265
301
|
- [@thi.ng/file-io](https://github.com/thi-ng/umbrella/tree/develop/packages/file-io)
|
|
266
302
|
- [@thi.ng/logger](https://github.com/thi-ng/umbrella/tree/develop/packages/logger)
|
|
303
|
+
- [@thi.ng/mime](https://github.com/thi-ng/umbrella/tree/develop/packages/mime)
|
|
267
304
|
- [@thi.ng/random](https://github.com/thi-ng/umbrella/tree/develop/packages/random)
|
|
268
305
|
- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/develop/packages/strings)
|
|
269
306
|
|
|
@@ -273,7 +310,9 @@ Note: @thi.ng/api is in _most_ cases a type-only import (not used at runtime)
|
|
|
273
310
|
|
|
274
311
|
[Generated API docs](https://docs.thi.ng/umbrella/block-fs/)
|
|
275
312
|
|
|
276
|
-
|
|
313
|
+
### Basic usage
|
|
314
|
+
|
|
315
|
+
```ts tangle:export/readme-1.ts
|
|
277
316
|
import { BlockFS, MemoryBlockStorage } from "@thi.ng/block-fs";
|
|
278
317
|
|
|
279
318
|
// create in-memory storage (64KB)
|
|
@@ -335,6 +374,45 @@ for await (let entry of fs.root.tree()) {
|
|
|
335
374
|
// /deeply/nested/paths/are-ok 4n 2025-04-01T20:18:55.919Z
|
|
336
375
|
```
|
|
337
376
|
|
|
377
|
+
### Working with a converted file system blob
|
|
378
|
+
|
|
379
|
+
This example shows how to use a binary blob created via the [CLI `blockfs
|
|
380
|
+
convert` command](#convert-file-tree-into-single-blockfs-blob) as a virtual file
|
|
381
|
+
system...
|
|
382
|
+
|
|
383
|
+
```ts tangle:export/readme-2.ts
|
|
384
|
+
import { BlockFS, MemoryBlockStorage } from "@thi.ng/block-fs";
|
|
385
|
+
|
|
386
|
+
// load binary blob
|
|
387
|
+
const response = await fetch("./blocks.dat");
|
|
388
|
+
const buffer = await response.arrayBuffer();
|
|
389
|
+
|
|
390
|
+
// wrap as block storage
|
|
391
|
+
const storage = new MemoryBlockStorage({
|
|
392
|
+
buffer,
|
|
393
|
+
blockSize: 1024,
|
|
394
|
+
numBlocks: buffer.byteLength / 1024
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// wrap as file system
|
|
398
|
+
const fs = new BlockFS(storage);
|
|
399
|
+
|
|
400
|
+
// list all entries (recursive)
|
|
401
|
+
for await(let f of fs.root.tree()) {
|
|
402
|
+
console.log(f.path);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// list all entries in a directory
|
|
406
|
+
const dir = (await fs.entryForPath("/path/to/dir")).directory;
|
|
407
|
+
for await (let f of dir) {
|
|
408
|
+
console.log(f.path);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// load an image as blob URL (MIME type is inferred automatically)
|
|
412
|
+
const img = new Image();
|
|
413
|
+
img.src = await fs.readAsObjectURL("/assets/test.jpg");
|
|
414
|
+
```
|
|
415
|
+
|
|
338
416
|
## Authors
|
|
339
417
|
|
|
340
418
|
- [Karsten Schmidt](https://thi.ng)
|
package/cli.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type Command, type CommandCtx } from "@thi.ng/args";
|
|
2
2
|
interface CLIOpts {
|
|
3
3
|
verbose: boolean;
|
|
4
|
+
quiet: boolean;
|
|
4
5
|
}
|
|
5
6
|
interface ConvertOpts extends CLIOpts {
|
|
6
7
|
numBlocks?: number;
|
|
7
8
|
blockSize: number;
|
|
9
|
+
exclude?: string[];
|
|
8
10
|
include?: string[];
|
|
9
11
|
out: string;
|
|
10
12
|
}
|
package/cli.js
CHANGED
|
@@ -28,25 +28,30 @@ const ARG_BLOCKSIZE = {
|
|
|
28
28
|
}
|
|
29
29
|
})
|
|
30
30
|
};
|
|
31
|
-
const collectFiles = (
|
|
32
|
-
|
|
31
|
+
const collectFiles = ({
|
|
32
|
+
opts: { include, exclude },
|
|
33
|
+
inputs
|
|
34
|
+
}) => {
|
|
35
|
+
const root = resolve(inputs[0]);
|
|
33
36
|
const filtered = [];
|
|
34
37
|
const dirs = /* @__PURE__ */ new Set();
|
|
38
|
+
const $include = include?.map((x) => new RegExp(x));
|
|
39
|
+
const $exclude = exclude?.map((x) => new RegExp(x));
|
|
35
40
|
let total = 0;
|
|
36
41
|
for (let f of files(root)) {
|
|
37
42
|
const stats = statSync(f);
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
if ($exclude && $exclude.some((x) => x.test(f))) continue;
|
|
44
|
+
if ($include && !$include.some((x) => x.test(f))) continue;
|
|
45
|
+
const dest = relative(root, f);
|
|
46
|
+
filtered.push({
|
|
47
|
+
src: f,
|
|
48
|
+
dest,
|
|
49
|
+
size: stats.size,
|
|
50
|
+
ctime: stats.ctimeMs,
|
|
51
|
+
mtime: stats.mtimeMs
|
|
52
|
+
});
|
|
53
|
+
dirs.add(dirname(dest));
|
|
54
|
+
total += stats.size;
|
|
50
55
|
}
|
|
51
56
|
return { files: filtered, dirs: [...dirs], size: total };
|
|
52
57
|
};
|
|
@@ -77,9 +82,14 @@ const CONVERT = {
|
|
|
77
82
|
desc: "Output file path",
|
|
78
83
|
optional: false
|
|
79
84
|
}),
|
|
85
|
+
exclude: strings({
|
|
86
|
+
alias: "e",
|
|
87
|
+
desc: "File exclusion regexp",
|
|
88
|
+
hint: "EXT"
|
|
89
|
+
}),
|
|
80
90
|
include: strings({
|
|
81
91
|
alias: "i",
|
|
82
|
-
desc: "
|
|
92
|
+
desc: "File inclusion regexp",
|
|
83
93
|
hint: "EXT"
|
|
84
94
|
})
|
|
85
95
|
},
|
|
@@ -102,7 +112,7 @@ const CONVERT = {
|
|
|
102
112
|
const bfs = new BlockFS(storage, { logger: ctx.logger });
|
|
103
113
|
await bfs.init();
|
|
104
114
|
for (let f of collected.files) {
|
|
105
|
-
ctx.logger.
|
|
115
|
+
ctx.logger.info("writing file:", f.dest);
|
|
106
116
|
await bfs.writeFile(f.dest, readBinary(f.src));
|
|
107
117
|
const entry = await bfs.entryForPath(f.dest);
|
|
108
118
|
entry.ctime = f.ctime;
|
|
@@ -179,7 +189,11 @@ cliApp({
|
|
|
179
189
|
opts: {
|
|
180
190
|
verbose: flag({
|
|
181
191
|
alias: "v",
|
|
182
|
-
desc: "Display extra
|
|
192
|
+
desc: "Display extra logging information"
|
|
193
|
+
}),
|
|
194
|
+
quiet: flag({
|
|
195
|
+
alias: "q",
|
|
196
|
+
desc: "Disable logging"
|
|
183
197
|
})
|
|
184
198
|
},
|
|
185
199
|
commands: {
|
|
@@ -188,7 +202,8 @@ cliApp({
|
|
|
188
202
|
},
|
|
189
203
|
name: "blockfs",
|
|
190
204
|
ctx: async (ctx) => {
|
|
191
|
-
if (ctx.opts.
|
|
205
|
+
if (ctx.opts.quiet) ctx.logger.level = LogLevel.NONE;
|
|
206
|
+
else if (ctx.opts.verbose) ctx.logger.level = LogLevel.DEBUG;
|
|
192
207
|
return ctx;
|
|
193
208
|
},
|
|
194
209
|
start: 3,
|
package/entry.d.ts
CHANGED
|
@@ -20,16 +20,16 @@ export declare class Entry implements IEntry {
|
|
|
20
20
|
set owner(owner: number);
|
|
21
21
|
get name(): string;
|
|
22
22
|
set name(name: string);
|
|
23
|
+
get start(): number;
|
|
24
|
+
set start(block: number);
|
|
25
|
+
get end(): number;
|
|
26
|
+
set end(block: number);
|
|
23
27
|
get size(): bigint;
|
|
24
28
|
set size(size: bigint);
|
|
25
29
|
get ctime(): number;
|
|
26
30
|
set ctime(epoch: number);
|
|
27
31
|
get mtime(): number;
|
|
28
32
|
set mtime(epoch: number);
|
|
29
|
-
get start(): number;
|
|
30
|
-
set start(block: number);
|
|
31
|
-
get end(): number;
|
|
32
|
-
set end(block: number);
|
|
33
33
|
set(spec: EntrySpec): void;
|
|
34
34
|
release(): void;
|
|
35
35
|
save(): Promise<void>;
|
package/entry.js
CHANGED
|
@@ -66,35 +66,35 @@ class Entry {
|
|
|
66
66
|
this.data.subarray(offset, offset + Entry.NAME_MAX_LENGTH)
|
|
67
67
|
);
|
|
68
68
|
}
|
|
69
|
+
get start() {
|
|
70
|
+
return this.view.getUint32(32, true);
|
|
71
|
+
}
|
|
72
|
+
set start(block) {
|
|
73
|
+
this.view.setUint32(32, block, true);
|
|
74
|
+
}
|
|
75
|
+
get end() {
|
|
76
|
+
return this.view.getUint32(36, true);
|
|
77
|
+
}
|
|
78
|
+
set end(block) {
|
|
79
|
+
this.view.setUint32(36, block, true);
|
|
80
|
+
}
|
|
69
81
|
get size() {
|
|
70
|
-
return this.view.getBigUint64(
|
|
82
|
+
return this.view.getBigUint64(40, true);
|
|
71
83
|
}
|
|
72
84
|
set size(size) {
|
|
73
|
-
this.view.setBigUint64(
|
|
85
|
+
this.view.setBigUint64(40, size, true);
|
|
74
86
|
}
|
|
75
87
|
get ctime() {
|
|
76
|
-
return Number(this.view.getBigUint64(
|
|
88
|
+
return Number(this.view.getBigUint64(48, true));
|
|
77
89
|
}
|
|
78
90
|
set ctime(epoch) {
|
|
79
|
-
this.view.setBigUint64(
|
|
91
|
+
this.view.setBigUint64(48, BigInt(epoch), true);
|
|
80
92
|
}
|
|
81
93
|
get mtime() {
|
|
82
|
-
return Number(this.view.getBigUint64(
|
|
94
|
+
return Number(this.view.getBigUint64(56, true));
|
|
83
95
|
}
|
|
84
96
|
set mtime(epoch) {
|
|
85
|
-
this.view.setBigUint64(
|
|
86
|
-
}
|
|
87
|
-
get start() {
|
|
88
|
-
return this.view.getUint32(56, true);
|
|
89
|
-
}
|
|
90
|
-
set start(block) {
|
|
91
|
-
this.view.setUint32(56, block, true);
|
|
92
|
-
}
|
|
93
|
-
get end() {
|
|
94
|
-
return this.view.getUint32(60, true);
|
|
95
|
-
}
|
|
96
|
-
set end(block) {
|
|
97
|
-
this.view.setUint32(60, block, true);
|
|
97
|
+
this.view.setBigUint64(56, BigInt(epoch), true);
|
|
98
98
|
}
|
|
99
99
|
set(spec) {
|
|
100
100
|
this.type = spec.type;
|
package/fs.d.ts
CHANGED
|
@@ -160,6 +160,10 @@ export declare class BlockFS {
|
|
|
160
160
|
* object URL, optionally typed with given MIME type.
|
|
161
161
|
*
|
|
162
162
|
* @remarks
|
|
163
|
+
* If `type` is omitted, it will be attempted to be inferred automatically
|
|
164
|
+
* via [thi.ng/mime](https://thi.ng/mime).
|
|
165
|
+
*
|
|
166
|
+
* @remarks
|
|
163
167
|
* Reference:
|
|
164
168
|
*
|
|
165
169
|
* - https://developer.mozilla.org/en-US/docs/Web/API/Blob#creating_a_url_representing_the_contents_of_a_typed_array
|
package/fs.js
CHANGED
|
@@ -5,6 +5,7 @@ import { assert } from "@thi.ng/errors/assert";
|
|
|
5
5
|
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
6
6
|
import { illegalState } from "@thi.ng/errors/illegal-state";
|
|
7
7
|
import { NULL_LOGGER } from "@thi.ng/logger/null";
|
|
8
|
+
import { preferredTypeForPath } from "@thi.ng/mime";
|
|
8
9
|
import {
|
|
9
10
|
EntryType
|
|
10
11
|
} from "./api.js";
|
|
@@ -289,6 +290,10 @@ class BlockFS {
|
|
|
289
290
|
* object URL, optionally typed with given MIME type.
|
|
290
291
|
*
|
|
291
292
|
* @remarks
|
|
293
|
+
* If `type` is omitted, it will be attempted to be inferred automatically
|
|
294
|
+
* via [thi.ng/mime](https://thi.ng/mime).
|
|
295
|
+
*
|
|
296
|
+
* @remarks
|
|
292
297
|
* Reference:
|
|
293
298
|
*
|
|
294
299
|
* - https://developer.mozilla.org/en-US/docs/Web/API/Blob#creating_a_url_representing_the_contents_of_a_typed_array
|
|
@@ -298,7 +303,9 @@ class BlockFS {
|
|
|
298
303
|
*/
|
|
299
304
|
async readAsObjectURL(path, type) {
|
|
300
305
|
return URL.createObjectURL(
|
|
301
|
-
new Blob([await this.readFile(path)], {
|
|
306
|
+
new Blob([await this.readFile(path)], {
|
|
307
|
+
type: type ?? (isString(path) ? preferredTypeForPath(path) : void 0)
|
|
308
|
+
})
|
|
302
309
|
);
|
|
303
310
|
}
|
|
304
311
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/block-fs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Customizable block-based storage, adapters & file system layer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -42,32 +42,35 @@
|
|
|
42
42
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@thi.ng/api": "^8.11.
|
|
46
|
-
"@thi.ng/args": "^2.3.
|
|
47
|
-
"@thi.ng/binary": "^3.4.
|
|
48
|
-
"@thi.ng/bitfield": "^2.4.
|
|
49
|
-
"@thi.ng/checks": "^3.7.
|
|
50
|
-
"@thi.ng/errors": "^2.5.
|
|
51
|
-
"@thi.ng/file-io": "^2.1.
|
|
52
|
-
"@thi.ng/logger": "^3.1.
|
|
53
|
-
"@thi.ng/
|
|
54
|
-
"@thi.ng/
|
|
45
|
+
"@thi.ng/api": "^8.11.26",
|
|
46
|
+
"@thi.ng/args": "^2.3.67",
|
|
47
|
+
"@thi.ng/binary": "^3.4.49",
|
|
48
|
+
"@thi.ng/bitfield": "^2.4.1",
|
|
49
|
+
"@thi.ng/checks": "^3.7.6",
|
|
50
|
+
"@thi.ng/errors": "^2.5.32",
|
|
51
|
+
"@thi.ng/file-io": "^2.1.35",
|
|
52
|
+
"@thi.ng/logger": "^3.1.7",
|
|
53
|
+
"@thi.ng/mime": "^2.7.8",
|
|
54
|
+
"@thi.ng/random": "^4.1.17",
|
|
55
|
+
"@thi.ng/strings": "^3.9.11"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
57
|
-
"@types/node": "^22.
|
|
58
|
+
"@types/node": "^22.14.1",
|
|
58
59
|
"esbuild": "^0.25.2",
|
|
59
|
-
"typedoc": "^0.28.
|
|
60
|
-
"typescript": "^5.8.
|
|
60
|
+
"typedoc": "^0.28.2",
|
|
61
|
+
"typescript": "^5.8.3"
|
|
61
62
|
},
|
|
62
63
|
"keywords": [
|
|
64
|
+
"async",
|
|
63
65
|
"binary",
|
|
64
66
|
"block",
|
|
65
67
|
"cli",
|
|
66
68
|
"conversion",
|
|
67
69
|
"file",
|
|
68
|
-
"
|
|
70
|
+
"filesystem",
|
|
69
71
|
"memory",
|
|
70
72
|
"memory-mapped",
|
|
73
|
+
"mime",
|
|
71
74
|
"nodejs",
|
|
72
75
|
"path",
|
|
73
76
|
"storage",
|
|
@@ -129,5 +132,5 @@
|
|
|
129
132
|
"status": "alpha",
|
|
130
133
|
"year": 2024
|
|
131
134
|
},
|
|
132
|
-
"gitHead": "
|
|
135
|
+
"gitHead": "c464b6948f92cba90c2ea75b59203dad894fb450\n"
|
|
133
136
|
}
|
package/storage/memory.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface MemoryBlockStorageOpts extends BlockStorageOpts {
|
|
|
16
16
|
* Optional, pre-defined/loaded byte buffer. Must have at least `numBlocks *
|
|
17
17
|
* blockSize` capacity.
|
|
18
18
|
*/
|
|
19
|
-
buffer?: Uint8Array;
|
|
19
|
+
buffer?: Uint8Array | ArrayBufferLike;
|
|
20
20
|
}
|
|
21
21
|
export declare class MemoryBlockStorage extends ABlockStorage<MemoryBlock> {
|
|
22
22
|
buffer: Uint8Array;
|
package/storage/memory.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isArrayBufferLike } from "@thi.ng/checks/is-arraybufferlike";
|
|
1
2
|
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
2
3
|
import { ABlockStorage } from "./astorage.js";
|
|
3
4
|
class MemoryBlock {
|
|
@@ -27,12 +28,13 @@ class MemoryBlockStorage extends ABlockStorage {
|
|
|
27
28
|
constructor(opts) {
|
|
28
29
|
super(opts);
|
|
29
30
|
const size = this.numBlocks * this.blockSize;
|
|
30
|
-
|
|
31
|
+
const buffer = opts.buffer ? isArrayBufferLike(opts.buffer) ? new Uint8Array(opts.buffer) : opts.buffer : void 0;
|
|
32
|
+
if (buffer && buffer.length < size) {
|
|
31
33
|
illegalArgs(
|
|
32
34
|
`given buffer is too small, expected at least ${size} bytes`
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
|
-
this.buffer =
|
|
37
|
+
this.buffer = buffer ?? new Uint8Array(size);
|
|
36
38
|
}
|
|
37
39
|
async hasBlock(id) {
|
|
38
40
|
this.ensureValidID(id);
|