edfcore 0.6.115 → 0.6.116
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/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +30 -0
- package/dist/node.js.map +1 -1
- package/dist/text/describe.d.ts.map +1 -1
- package/dist/text/describe.js +10 -0
- package/dist/text/describe.js.map +1 -1
- package/docs/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/node.ts +36 -0
- package/src/text/describe.ts +10 -0
package/dist/constants.d.ts
CHANGED
|
@@ -109,5 +109,5 @@ export declare const SIGNAL_FIELD_BLOCK_OFFSETS: {
|
|
|
109
109
|
readonly reserved: 224;
|
|
110
110
|
};
|
|
111
111
|
/** Published package version. Kept in sync with package.json by a test. */
|
|
112
|
-
export declare const VERSION = "0.6.
|
|
112
|
+
export declare const VERSION = "0.6.116";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
package/dist/node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAQH,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,YAAY,CAAC;AAElE;;;;;;GAMG;AACH,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CACF,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAYD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,kBAAkB,CA0F/F;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyD1E"}
|
package/dist/node.js
CHANGED
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
import * as nodeFsPromises from 'node:fs/promises';
|
|
45
45
|
import { EdfSourceError } from './errors.js';
|
|
46
46
|
import { assertExactRead, assertReadRange, throwIfAborted } from './io/source.js';
|
|
47
|
+
import { describeValue } from './text/describe.js';
|
|
47
48
|
const fs = nodeFsPromises;
|
|
48
49
|
/**
|
|
49
50
|
* A `ByteSource` over an open file handle.
|
|
@@ -69,6 +70,20 @@ export function fileHandleSource(handle, byteLength) {
|
|
|
69
70
|
* `parseHeader` — which does guard it — blaming a caller who passed it the right arguments
|
|
70
71
|
* (fixed in 0.6.85).
|
|
71
72
|
*/
|
|
73
|
+
/*
|
|
74
|
+
* And the handle, which 0.6.85 did not check. `fileHandleSource(path, size)` — the two arguments
|
|
75
|
+
* in the order `fileSource(path)` teaches, with the size this function is named for — was
|
|
76
|
+
* accepted, returned a source advertising the right `byteLength`, and failed later on
|
|
77
|
+
* `handle.read is not a function` or `handle.close is not a function`. `byteSource` states the
|
|
78
|
+
* rule this breaks: refuse at CONSTRUCTION, because a source built over something that cannot
|
|
79
|
+
* serve bytes surfaces later as a complaint about the file (fixed in 0.6.116).
|
|
80
|
+
*/
|
|
81
|
+
const given = handle;
|
|
82
|
+
if (typeof given?.read !== 'function' || typeof given.close !== 'function') {
|
|
83
|
+
throw new EdfSourceError(`fileHandleSource() needs an open file handle — an object with a read() and a close() — and ` +
|
|
84
|
+
`received ${describeValue(handle)}. Next: pass what fs.open(path, 'r') from ` +
|
|
85
|
+
'"node:fs/promises" resolved to, or use fileSource(path), which opens one for you.', { offset: 0, requestedLength: 0 });
|
|
86
|
+
}
|
|
72
87
|
if (!Number.isSafeInteger(byteLength) || byteLength < 0) {
|
|
73
88
|
throw new EdfSourceError(`fileHandleSource() was given a byteLength of ${String(byteLength)}, which is not a byte ` +
|
|
74
89
|
'count edfcore can address. Next: pass the size of the file or of the range you mean to ' +
|
|
@@ -137,6 +152,21 @@ export function fileHandleSource(handle, byteLength) {
|
|
|
137
152
|
* caller's job through `source.close()`.
|
|
138
153
|
*/
|
|
139
154
|
export async function fileSource(path) {
|
|
155
|
+
/*
|
|
156
|
+
* The path, before Node is asked to open it.
|
|
157
|
+
*
|
|
158
|
+
* `fs.open` accepts a `Uint8Array` as a path — the BYTES OF a filename — so `fileSource(bytes)`,
|
|
159
|
+
* which is the mistake a caller with a file already in memory makes, reached the syscall and came
|
|
160
|
+
* back as `ENOENT: no such file or directory, open '0 X X X X '`: the EDF
|
|
161
|
+
* header's own bytes rendered as a filename, in an error that also names `Uint8Array` as an
|
|
162
|
+
* accepted type. `assertByteSource` recognises a path string and names `fileSource`; this is that
|
|
163
|
+
* courtesy in the other direction (fixed in 0.6.116).
|
|
164
|
+
*/
|
|
165
|
+
if (typeof path !== 'string' && Object.prototype.toString.call(path) !== '[object URL]') {
|
|
166
|
+
throw new EdfSourceError(`fileSource() needs a path, and received ${describeValue(path)}. Next: pass the path as a ` +
|
|
167
|
+
'string, or byteSource(bytes) for a file you have already read into memory — a Uint8Array ' +
|
|
168
|
+
'here would be opened as the bytes of a filename.', { offset: 0, requestedLength: 0 });
|
|
169
|
+
}
|
|
140
170
|
const handle = await fs.open(path, 'r');
|
|
141
171
|
try {
|
|
142
172
|
const stats = await handle.stat();
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,4FAA4F;AAC5F,2FAA2F;AAC3F,OAAO,KAAK,cAAc,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/text/describe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/text/describe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAmBpD"}
|
package/dist/text/describe.js
CHANGED
|
@@ -28,6 +28,16 @@ export function describeValue(value) {
|
|
|
28
28
|
return 'null';
|
|
29
29
|
if (value === undefined)
|
|
30
30
|
return 'undefined';
|
|
31
|
+
/*
|
|
32
|
+
* A binary value is named by its built-in tag — `Uint8Array`, `ArrayBuffer`, `DataView` — because
|
|
33
|
+
* that IS the mistake wherever one turns up: `fileSource(bytes)` is a file already in memory and
|
|
34
|
+
* `decodeHeaderLatin1(buffer)` is a fetch result, and "an object" says nothing a reader can act
|
|
35
|
+
* on. The tag, not `instanceof`: it is the same across realms, which is why `io/bytes.ts` uses it
|
|
36
|
+
* too. Never the contents (0.6.116).
|
|
37
|
+
*/
|
|
38
|
+
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
39
|
+
return Object.prototype.toString.call(value).slice(8, -1);
|
|
40
|
+
}
|
|
31
41
|
// `an object` covers an array too: a reader who passed one knows which they passed, and printing
|
|
32
42
|
// its contents is how a 512-signal selection ends up on one line behind `edfcore: `.
|
|
33
43
|
return typeof value === 'object' ? 'an object' : `a ${typeof value}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/text/describe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,cAAc,KAAK,GAAG,CAAC;IAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5E,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C,iGAAiG;IACjG,qFAAqF;IACrF,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC;AACvE,CAAC"}
|
|
1
|
+
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/text/describe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,cAAc,KAAK,GAAG,CAAC;IAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5E,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C;;;;;;OAMG;IACH,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QAC9D,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,iGAAiG;IACjG,qFAAqF;IACrF,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC;AACvE,CAAC"}
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,21 @@ alone does not tell you whether you were affected.
|
|
|
6
6
|
edfcore is pre-1.0. Patch releases have carried behaviour changes where the old behaviour was a
|
|
7
7
|
defect; those are called out below.
|
|
8
8
|
|
|
9
|
+
## 0.6.116
|
|
10
|
+
|
|
11
|
+
- **Fixed** `fileSource(bytes)` opening the file's own bytes as a filename. `fs.open` accepts a
|
|
12
|
+
`Uint8Array` as a path — the bytes OF a filename — so the mistake a caller with a file already in
|
|
13
|
+
memory makes came back as `ENOENT: no such file or directory, open '0 X X X X '`:
|
|
14
|
+
the EDF header rendered as a path, in an error that also lists `Uint8Array` as an accepted type.
|
|
15
|
+
It now names `byteSource(bytes)`, which is `assertByteSource`'s courtesy in the other direction.
|
|
16
|
+
- **Fixed** `fileHandleSource` accepting something that is not a handle. 0.6.85 checked the size and
|
|
17
|
+
not the handle, so `fileHandleSource(path, size)` — the two arguments in the order
|
|
18
|
+
`fileSource(path)` teaches, with the size this function is named for — returned a source
|
|
19
|
+
advertising the right `byteLength` and failed later on `handle.read is not a function`.
|
|
20
|
+
- A binary value is now named by its built-in tag wherever edfcore describes a rejected argument —
|
|
21
|
+
`Uint8Array`, `ArrayBuffer`, `DataView` — because that is the mistake wherever one turns up.
|
|
22
|
+
Never its contents.
|
|
23
|
+
|
|
9
24
|
## 0.6.115
|
|
10
25
|
|
|
11
26
|
- **Behaviour change:** `maxItems` no longer accepts a value that is not a number.
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
package/src/node.ts
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
import * as nodeFsPromises from 'node:fs/promises';
|
|
46
46
|
import { EdfSourceError } from './errors.js';
|
|
47
47
|
import { assertExactRead, assertReadRange, throwIfAborted } from './io/source.js';
|
|
48
|
+
import { describeValue } from './text/describe.js';
|
|
48
49
|
import type { ClosableByteSource, ReadOptions } from './types.js';
|
|
49
50
|
|
|
50
51
|
/**
|
|
@@ -106,6 +107,23 @@ export function fileHandleSource(handle: FileHandleLike, byteLength: number): Cl
|
|
|
106
107
|
* `parseHeader` — which does guard it — blaming a caller who passed it the right arguments
|
|
107
108
|
* (fixed in 0.6.85).
|
|
108
109
|
*/
|
|
110
|
+
/*
|
|
111
|
+
* And the handle, which 0.6.85 did not check. `fileHandleSource(path, size)` — the two arguments
|
|
112
|
+
* in the order `fileSource(path)` teaches, with the size this function is named for — was
|
|
113
|
+
* accepted, returned a source advertising the right `byteLength`, and failed later on
|
|
114
|
+
* `handle.read is not a function` or `handle.close is not a function`. `byteSource` states the
|
|
115
|
+
* rule this breaks: refuse at CONSTRUCTION, because a source built over something that cannot
|
|
116
|
+
* serve bytes surfaces later as a complaint about the file (fixed in 0.6.116).
|
|
117
|
+
*/
|
|
118
|
+
const given = handle as { read?: unknown; close?: unknown } | null | undefined;
|
|
119
|
+
if (typeof given?.read !== 'function' || typeof given.close !== 'function') {
|
|
120
|
+
throw new EdfSourceError(
|
|
121
|
+
`fileHandleSource() needs an open file handle — an object with a read() and a close() — and ` +
|
|
122
|
+
`received ${describeValue(handle)}. Next: pass what fs.open(path, 'r') from ` +
|
|
123
|
+
'"node:fs/promises" resolved to, or use fileSource(path), which opens one for you.',
|
|
124
|
+
{ offset: 0, requestedLength: 0 },
|
|
125
|
+
);
|
|
126
|
+
}
|
|
109
127
|
if (!Number.isSafeInteger(byteLength) || byteLength < 0) {
|
|
110
128
|
throw new EdfSourceError(
|
|
111
129
|
`fileHandleSource() was given a byteLength of ${String(byteLength)}, which is not a byte ` +
|
|
@@ -180,6 +198,24 @@ export function fileHandleSource(handle: FileHandleLike, byteLength: number): Cl
|
|
|
180
198
|
* caller's job through `source.close()`.
|
|
181
199
|
*/
|
|
182
200
|
export async function fileSource(path: string): Promise<ClosableByteSource> {
|
|
201
|
+
/*
|
|
202
|
+
* The path, before Node is asked to open it.
|
|
203
|
+
*
|
|
204
|
+
* `fs.open` accepts a `Uint8Array` as a path — the BYTES OF a filename — so `fileSource(bytes)`,
|
|
205
|
+
* which is the mistake a caller with a file already in memory makes, reached the syscall and came
|
|
206
|
+
* back as `ENOENT: no such file or directory, open '0 X X X X '`: the EDF
|
|
207
|
+
* header's own bytes rendered as a filename, in an error that also names `Uint8Array` as an
|
|
208
|
+
* accepted type. `assertByteSource` recognises a path string and names `fileSource`; this is that
|
|
209
|
+
* courtesy in the other direction (fixed in 0.6.116).
|
|
210
|
+
*/
|
|
211
|
+
if (typeof path !== 'string' && Object.prototype.toString.call(path) !== '[object URL]') {
|
|
212
|
+
throw new EdfSourceError(
|
|
213
|
+
`fileSource() needs a path, and received ${describeValue(path)}. Next: pass the path as a ` +
|
|
214
|
+
'string, or byteSource(bytes) for a file you have already read into memory — a Uint8Array ' +
|
|
215
|
+
'here would be opened as the bytes of a filename.',
|
|
216
|
+
{ offset: 0, requestedLength: 0 },
|
|
217
|
+
);
|
|
218
|
+
}
|
|
183
219
|
const handle = await fs.open(path, 'r');
|
|
184
220
|
try {
|
|
185
221
|
const stats = await handle.stat();
|
package/src/text/describe.ts
CHANGED
|
@@ -24,6 +24,16 @@ export function describeValue(value: unknown): string {
|
|
|
24
24
|
if (typeof value === 'string') return `the string ${JSON.stringify(value)}`;
|
|
25
25
|
if (value === null) return 'null';
|
|
26
26
|
if (value === undefined) return 'undefined';
|
|
27
|
+
/*
|
|
28
|
+
* A binary value is named by its built-in tag — `Uint8Array`, `ArrayBuffer`, `DataView` — because
|
|
29
|
+
* that IS the mistake wherever one turns up: `fileSource(bytes)` is a file already in memory and
|
|
30
|
+
* `decodeHeaderLatin1(buffer)` is a fetch result, and "an object" says nothing a reader can act
|
|
31
|
+
* on. The tag, not `instanceof`: it is the same across realms, which is why `io/bytes.ts` uses it
|
|
32
|
+
* too. Never the contents (0.6.116).
|
|
33
|
+
*/
|
|
34
|
+
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
35
|
+
return Object.prototype.toString.call(value).slice(8, -1);
|
|
36
|
+
}
|
|
27
37
|
// `an object` covers an array too: a reader who passed one knows which they passed, and printing
|
|
28
38
|
// its contents is how a 512-signal selection ends up on one line behind `edfcore: `.
|
|
29
39
|
return typeof value === 'object' ? 'an object' : `a ${typeof value}`;
|