edfcore 0.6.117 → 0.6.118

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.
@@ -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.117";
112
+ export declare const VERSION = "0.6.118";
113
113
  //# sourceMappingURL=constants.d.ts.map
package/dist/constants.js CHANGED
@@ -79,5 +79,5 @@ export const SIGNAL_FIELD_BLOCK_OFFSETS = {
79
79
  reserved: 224,
80
80
  };
81
81
  /** Published package version. Kept in sync with package.json by a test. */
82
- export const VERSION = '0.6.117';
82
+ export const VERSION = '0.6.118';
83
83
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAe,eAAe,EAAE,MAAM,YAAY,CAAC;AAKpG;;;;;;;GAOG;AACH,wBAAuB,aAAa,CAClC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,WAAW,GACpB,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAuF3C"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAe,eAAe,EAAE,MAAM,YAAY,CAAC;AAKpG;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,WAAW,GACpB,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CA+C3C"}
package/dist/stream.js CHANGED
@@ -26,7 +26,22 @@ const DEFAULT_STREAM_RECORDS = 256;
26
26
  * because the record is the only unit every signal in an EDF file shares — signals may sample at
27
27
  * different rates, so "a second of data" is a different number of samples per channel.
28
28
  */
29
- export async function* streamRecords(recording, selection, options) {
29
+ export function streamRecords(recording, selection, options) {
30
+ /*
31
+ * A plain function that validates and RETURNS a generator, rather than a generator function.
32
+ *
33
+ * The body of an `async function*` does not run until the first `next()`, so every check below
34
+ * was deferred to the first `for await` — and `streamRecords(recording)` with no selection at all
35
+ * returned an object, successfully. The comment further down makes this exact argument about
36
+ * `resolveSignals`: "Every other selection error in the package surfaces on the spot; this one
37
+ * waited for data." It waited for iteration too, which is worse, because a caller who builds the
38
+ * stream in one place and consumes it in another gets the refusal in the second.
39
+ *
40
+ * Everything answerable from the arguments now is: the recording, the selection, the chunk size,
41
+ * the signal indices, and the window itself — `resolveTimeWindow` is pure over the timeline and
42
+ * the index, and its refusal for a probed index over a discontinuous file is about the call, not
43
+ * about any byte (fixed in 0.6.118).
44
+ */
30
45
  assertRecording(recording, 'streamRecords');
31
46
  assertSelection(selection, 'streamRecords', '{ signalIndices, startSeconds, durationSeconds } and optionally chunkRecords');
32
47
  const chunkRecords = selection.chunkRecords ?? DEFAULT_STREAM_RECORDS;
@@ -43,6 +58,10 @@ export async function* streamRecords(recording, selection, options) {
43
58
  // Every other selection error in the package surfaces on the spot; this one waited for data.
44
59
  resolveSignals(recording.header, selection.signalIndices);
45
60
  const ranges = resolveTimeWindow(recording.timeline, recording.index, selection.startSeconds, selection.durationSeconds);
61
+ return streamRanges(recording, selection, ranges, chunkRecords, options);
62
+ }
63
+ /** The iteration itself, reached only once every argument above has been accepted. */
64
+ async function* streamRanges(recording, selection, ranges, chunkRecords, options) {
46
65
  const recordDurationTicks = recording.header.recordDurationTicks;
47
66
  for (const run of ranges) {
48
67
  let scanned = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,uEAAuE;AACvE,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,aAAa,CAClC,SAAuB,EACvB,SAA0B,EAC1B,OAAqB;IAErB,eAAe,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAC5C,eAAe,CACb,SAAS,EACT,eAAe,EACf,8EAA8E,CAC/E,CAAC;IACF,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,sBAAsB,CAAC;IACtE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,UAAU,CAClB,0EAA0E;YACxE,GAAG,aAAa,CAAC,YAAY,CAAC,IAAI;YAClC,mFAAmF,CACtF,CAAC;IACJ,CAAC;IAED,+FAA+F;IAC/F,+FAA+F;IAC/F,2FAA2F;IAC3F,sFAAsF;IACtF,6FAA6F;IAC7F,6FAA6F;IAC7F,cAAc,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,iBAAiB,CAC9B,SAAS,CAAC,QAAQ,EAClB,SAAS,CAAC,KAAK,EACf,SAAS,CAAC,YAAY,EACtB,SAAS,CAAC,eAAe,CAC1B,CAAC;IAEF,MAAM,mBAAmB,GAAG,SAAS,CAAC,MAAM,CAAC,mBAAmB,CAAC;IAEjE,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,8FAA8F;QAC9F,6FAA6F;QAC7F,IAAI,cAAuE,CAAC;QAE5E,OAAO,OAAO,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAgB;gBAC3B,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,OAAO;gBAC1B,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC;aACnD,CAAC;YACF,0FAA0F;YAC1F,4FAA4F;YAC5F,MAAM,KAAK,GAAG,MAAM,WAAW,CAC7B,SAAS,EACT,EAAE,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,OAAO,EAAE,EACnD,OAAO,CACR,CAAC;YAEF;;;;;;;;;;;;;;;;;;;eAmBG;YACH,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACjC,qBAAqB,CAAC,cAAc,EAAE;oBACpC,WAAW,EAAE,OAAO,CAAC,KAAK;oBAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;iBAC7B,CAAC,CAAC;YACL,CAAC;YACD,cAAc,GAAG;gBACf,WAAW,EAAE,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,GAAG,CAAC;gBAC9C,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,GAAG,mBAAmB;aACzE,CAAC;YAEF,MAAM,KAAK,CAAC;YACZ,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"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"}
package/docs/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ 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.118
10
+
11
+ - **Fixed** `streamRecords` deferring every argument check to the first `for await`.
12
+ - The body of an `async function*` does not run until the first `next()`, so `streamRecords(recording)`
13
+ with no selection at all returned a generator, successfully. The function's own comment makes this
14
+ argument one level down, about `resolveSignals`: "Every other selection error in the package
15
+ surfaces on the spot; this one waited for data."
16
+ - Waiting for iteration is worse than waiting for data, because the two happen in different places. A
17
+ pipeline that builds the stream in one function and consumes it in another got the refusal in the
18
+ second, with the arguments it names nowhere in sight; a stream that was built and then dropped
19
+ never reported the mistake at all.
20
+ - It is a plain function that validates and returns a generator now. Everything answerable from the
21
+ arguments is answered at the call: the recording, the selection, `chunkRecords`, the signal
22
+ indices, and the window — `resolveTimeWindow` is pure over the timeline and the index, and its
23
+ refusal for a probed index over a discontinuous file is about the call rather than about any byte.
24
+
9
25
  ## 0.6.117
10
26
 
11
27
  - **Fixed** the two per-signal arguments the envelope module did not check, one in each direction.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edfcore",
3
- "version": "0.6.117",
3
+ "version": "0.6.118",
4
4
  "description": "Modern, typed, zero-dependency reader for EDF, EDF+, BDF and BDF+ biosignal files. Works in browsers and Node with true random access.",
5
5
  "keywords": [
6
6
  "edf",
package/src/constants.ts CHANGED
@@ -93,4 +93,4 @@ export const SIGNAL_FIELD_BLOCK_OFFSETS = {
93
93
  } as const;
94
94
 
95
95
  /** Published package version. Kept in sync with package.json by a test. */
96
- export const VERSION = '0.6.117';
96
+ export const VERSION = '0.6.118';
package/src/stream.ts CHANGED
@@ -30,11 +30,26 @@ const DEFAULT_STREAM_RECORDS = 256;
30
30
  * because the record is the only unit every signal in an EDF file shares — signals may sample at
31
31
  * different rates, so "a second of data" is a different number of samples per channel.
32
32
  */
33
- export async function* streamRecords(
33
+ export function streamRecords(
34
34
  recording: EdfRecording,
35
35
  selection: StreamSelection,
36
36
  options?: ReadOptions,
37
37
  ): AsyncGenerator<EdfChunk, void, undefined> {
38
+ /*
39
+ * A plain function that validates and RETURNS a generator, rather than a generator function.
40
+ *
41
+ * The body of an `async function*` does not run until the first `next()`, so every check below
42
+ * was deferred to the first `for await` — and `streamRecords(recording)` with no selection at all
43
+ * returned an object, successfully. The comment further down makes this exact argument about
44
+ * `resolveSignals`: "Every other selection error in the package surfaces on the spot; this one
45
+ * waited for data." It waited for iteration too, which is worse, because a caller who builds the
46
+ * stream in one place and consumes it in another gets the refusal in the second.
47
+ *
48
+ * Everything answerable from the arguments now is: the recording, the selection, the chunk size,
49
+ * the signal indices, and the window itself — `resolveTimeWindow` is pure over the timeline and
50
+ * the index, and its refusal for a probed index over a discontinuous file is about the call, not
51
+ * about any byte (fixed in 0.6.118).
52
+ */
38
53
  assertRecording(recording, 'streamRecords');
39
54
  assertSelection(
40
55
  selection,
@@ -65,6 +80,17 @@ export async function* streamRecords(
65
80
  selection.durationSeconds,
66
81
  );
67
82
 
83
+ return streamRanges(recording, selection, ranges, chunkRecords, options);
84
+ }
85
+
86
+ /** The iteration itself, reached only once every argument above has been accepted. */
87
+ async function* streamRanges(
88
+ recording: EdfRecording,
89
+ selection: StreamSelection,
90
+ ranges: readonly RecordRange[],
91
+ chunkRecords: number,
92
+ options: ReadOptions | undefined,
93
+ ): AsyncGenerator<EdfChunk, void, undefined> {
68
94
  const recordDurationTicks = recording.header.recordDurationTicks;
69
95
 
70
96
  for (const run of ranges) {