edfcore 0.1.0

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 (188) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +319 -0
  3. package/dist/bytes/latin1.d.ts +43 -0
  4. package/dist/bytes/latin1.d.ts.map +1 -0
  5. package/dist/bytes/latin1.js +84 -0
  6. package/dist/bytes/latin1.js.map +1 -0
  7. package/dist/bytes/numbers.d.ts +45 -0
  8. package/dist/bytes/numbers.d.ts.map +1 -0
  9. package/dist/bytes/numbers.js +87 -0
  10. package/dist/bytes/numbers.js.map +1 -0
  11. package/dist/bytes/view.d.ts +27 -0
  12. package/dist/bytes/view.d.ts.map +1 -0
  13. package/dist/bytes/view.js +53 -0
  14. package/dist/bytes/view.js.map +1 -0
  15. package/dist/constants.d.ts +113 -0
  16. package/dist/constants.d.ts.map +1 -0
  17. package/dist/constants.js +83 -0
  18. package/dist/constants.js.map +1 -0
  19. package/dist/decode/digital.d.ts +49 -0
  20. package/dist/decode/digital.d.ts.map +1 -0
  21. package/dist/decode/digital.js +180 -0
  22. package/dist/decode/digital.js.map +1 -0
  23. package/dist/decode/physical.d.ts +37 -0
  24. package/dist/decode/physical.d.ts.map +1 -0
  25. package/dist/decode/physical.js +178 -0
  26. package/dist/decode/physical.js.map +1 -0
  27. package/dist/diagnostics/codes.d.ts +38 -0
  28. package/dist/diagnostics/codes.d.ts.map +1 -0
  29. package/dist/diagnostics/codes.js +134 -0
  30. package/dist/diagnostics/codes.js.map +1 -0
  31. package/dist/diagnostics/collector.d.ts +76 -0
  32. package/dist/diagnostics/collector.d.ts.map +1 -0
  33. package/dist/diagnostics/collector.js +95 -0
  34. package/dist/diagnostics/collector.js.map +1 -0
  35. package/dist/diagnostics/format.d.ts +21 -0
  36. package/dist/diagnostics/format.d.ts.map +1 -0
  37. package/dist/diagnostics/format.js +125 -0
  38. package/dist/diagnostics/format.js.map +1 -0
  39. package/dist/errors.d.ts +143 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/errors.js +135 -0
  42. package/dist/errors.js.map +1 -0
  43. package/dist/header/dates.d.ts +101 -0
  44. package/dist/header/dates.d.ts.map +1 -0
  45. package/dist/header/dates.js +378 -0
  46. package/dist/header/dates.js.map +1 -0
  47. package/dist/header/fields.d.ts +105 -0
  48. package/dist/header/fields.d.ts.map +1 -0
  49. package/dist/header/fields.js +363 -0
  50. package/dist/header/fields.js.map +1 -0
  51. package/dist/header/identification.d.ts +47 -0
  52. package/dist/header/identification.d.ts.map +1 -0
  53. package/dist/header/identification.js +156 -0
  54. package/dist/header/identification.js.map +1 -0
  55. package/dist/header/lookup.d.ts +33 -0
  56. package/dist/header/lookup.d.ts.map +1 -0
  57. package/dist/header/lookup.js +67 -0
  58. package/dist/header/lookup.js.map +1 -0
  59. package/dist/header/parse.d.ts +32 -0
  60. package/dist/header/parse.d.ts.map +1 -0
  61. package/dist/header/parse.js +319 -0
  62. package/dist/header/parse.js.map +1 -0
  63. package/dist/header/scale.d.ts +68 -0
  64. package/dist/header/scale.d.ts.map +1 -0
  65. package/dist/header/scale.js +154 -0
  66. package/dist/header/scale.js.map +1 -0
  67. package/dist/header/signals.d.ts +64 -0
  68. package/dist/header/signals.d.ts.map +1 -0
  69. package/dist/header/signals.js +374 -0
  70. package/dist/header/signals.js.map +1 -0
  71. package/dist/header/variant.d.ts +67 -0
  72. package/dist/header/variant.d.ts.map +1 -0
  73. package/dist/header/variant.js +180 -0
  74. package/dist/header/variant.js.map +1 -0
  75. package/dist/index.d.ts +46 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +59 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/inspect.d.ts +31 -0
  80. package/dist/inspect.d.ts.map +1 -0
  81. package/dist/inspect.js +165 -0
  82. package/dist/inspect.js.map +1 -0
  83. package/dist/io/blob.d.ts +14 -0
  84. package/dist/io/blob.d.ts.map +1 -0
  85. package/dist/io/blob.js +29 -0
  86. package/dist/io/blob.js.map +1 -0
  87. package/dist/io/bytes.d.ts +11 -0
  88. package/dist/io/bytes.d.ts.map +1 -0
  89. package/dist/io/bytes.js +26 -0
  90. package/dist/io/bytes.js.map +1 -0
  91. package/dist/io/cached.d.ts +19 -0
  92. package/dist/io/cached.d.ts.map +1 -0
  93. package/dist/io/cached.js +129 -0
  94. package/dist/io/cached.js.map +1 -0
  95. package/dist/io/http.d.ts +20 -0
  96. package/dist/io/http.d.ts.map +1 -0
  97. package/dist/io/http.js +225 -0
  98. package/dist/io/http.js.map +1 -0
  99. package/dist/io/read.d.ts +42 -0
  100. package/dist/io/read.d.ts.map +1 -0
  101. package/dist/io/read.js +119 -0
  102. package/dist/io/read.js.map +1 -0
  103. package/dist/io/source.d.ts +33 -0
  104. package/dist/io/source.d.ts.map +1 -0
  105. package/dist/io/source.js +72 -0
  106. package/dist/io/source.js.map +1 -0
  107. package/dist/node.d.ts +70 -0
  108. package/dist/node.d.ts.map +1 -0
  109. package/dist/node.js +109 -0
  110. package/dist/node.js.map +1 -0
  111. package/dist/record-index.d.ts +58 -0
  112. package/dist/record-index.d.ts.map +1 -0
  113. package/dist/record-index.js +290 -0
  114. package/dist/record-index.js.map +1 -0
  115. package/dist/recording.d.ts +57 -0
  116. package/dist/recording.d.ts.map +1 -0
  117. package/dist/recording.js +178 -0
  118. package/dist/recording.js.map +1 -0
  119. package/dist/tal/annotations.d.ts +36 -0
  120. package/dist/tal/annotations.d.ts.map +1 -0
  121. package/dist/tal/annotations.js +437 -0
  122. package/dist/tal/annotations.js.map +1 -0
  123. package/dist/tal/grammar.d.ts +111 -0
  124. package/dist/tal/grammar.d.ts.map +1 -0
  125. package/dist/tal/grammar.js +324 -0
  126. package/dist/tal/grammar.js.map +1 -0
  127. package/dist/tal/ticks.d.ts +69 -0
  128. package/dist/tal/ticks.d.ts.map +1 -0
  129. package/dist/tal/ticks.js +137 -0
  130. package/dist/tal/ticks.js.map +1 -0
  131. package/dist/time/segments.d.ts +33 -0
  132. package/dist/time/segments.d.ts.map +1 -0
  133. package/dist/time/segments.js +87 -0
  134. package/dist/time/segments.js.map +1 -0
  135. package/dist/time/timeline.d.ts +62 -0
  136. package/dist/time/timeline.d.ts.map +1 -0
  137. package/dist/time/timeline.js +227 -0
  138. package/dist/time/timeline.js.map +1 -0
  139. package/dist/time/window.d.ts +54 -0
  140. package/dist/time/window.d.ts.map +1 -0
  141. package/dist/time/window.js +232 -0
  142. package/dist/time/window.js.map +1 -0
  143. package/dist/types.d.ts +409 -0
  144. package/dist/types.d.ts.map +1 -0
  145. package/dist/types.js +16 -0
  146. package/dist/types.js.map +1 -0
  147. package/dist/validate.d.ts +53 -0
  148. package/dist/validate.d.ts.map +1 -0
  149. package/dist/validate.js +483 -0
  150. package/dist/validate.js.map +1 -0
  151. package/package.json +77 -0
  152. package/src/bytes/latin1.ts +87 -0
  153. package/src/bytes/numbers.ts +115 -0
  154. package/src/bytes/view.ts +59 -0
  155. package/src/constants.ts +96 -0
  156. package/src/decode/digital.ts +258 -0
  157. package/src/decode/physical.ts +235 -0
  158. package/src/diagnostics/codes.ts +209 -0
  159. package/src/diagnostics/collector.ts +129 -0
  160. package/src/diagnostics/format.ts +143 -0
  161. package/src/errors.ts +208 -0
  162. package/src/header/dates.ts +453 -0
  163. package/src/header/fields.ts +455 -0
  164. package/src/header/identification.ts +196 -0
  165. package/src/header/lookup.ts +81 -0
  166. package/src/header/parse.ts +398 -0
  167. package/src/header/scale.ts +268 -0
  168. package/src/header/signals.ts +550 -0
  169. package/src/header/variant.ts +239 -0
  170. package/src/index.ts +151 -0
  171. package/src/inspect.ts +181 -0
  172. package/src/io/blob.ts +31 -0
  173. package/src/io/bytes.ts +29 -0
  174. package/src/io/cached.ts +136 -0
  175. package/src/io/http.ts +299 -0
  176. package/src/io/read.ts +152 -0
  177. package/src/io/source.ts +87 -0
  178. package/src/node.ts +138 -0
  179. package/src/record-index.ts +389 -0
  180. package/src/recording.ts +234 -0
  181. package/src/tal/annotations.ts +574 -0
  182. package/src/tal/grammar.ts +540 -0
  183. package/src/tal/ticks.ts +172 -0
  184. package/src/time/segments.ts +109 -0
  185. package/src/time/timeline.ts +290 -0
  186. package/src/time/window.ts +304 -0
  187. package/src/types.ts +490 -0
  188. package/src/validate.ts +610 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/io/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The `ByteSource` contract guard.
3
+ *
4
+ * Layer 5, and the only file in `io/` that imports an error class. Nothing here knows anything
5
+ * about EDF.
6
+ *
7
+ * The contract is one sentence — a read resolves with EXACTLY `length` bytes or rejects, it
8
+ * never pads and never truncates — and it is *checked on every call*, including calls into a
9
+ * source the caller wrote. A source that quietly returns a short buffer is indistinguishable
10
+ * from a truncated file, so without this guard the parser would confidently report the wrong
11
+ * cause for the wrong thing.
12
+ */
13
+ import type { ReadOptions } from '../types.js';
14
+ /**
15
+ * Enforces the exact-length contract and returns the value unchanged so it can wrap a read
16
+ * expression directly.
17
+ */
18
+ export declare function assertExactRead(received: Uint8Array, offset: number, length: number): Uint8Array;
19
+ /**
20
+ * Validates a requested range against the source length, with the real numbers in the message.
21
+ *
22
+ * Offsets are plain JS numbers throughout edfcore — exact to 2^53 — so this checks
23
+ * safe-integer-ness rather than truncating with `| 0`, which silently wraps past 2 GiB.
24
+ */
25
+ export declare function assertReadRange(offset: number, length: number, byteLength: number): void;
26
+ /**
27
+ * Aborts a read when the caller's signal is already aborted.
28
+ *
29
+ * `DOMException` cannot be named without the DOM lib, and the thing consumers actually branch
30
+ * on is `error.name === 'AbortError'`, so that is what this produces.
31
+ */
32
+ export declare function throwIfAborted(options?: ReadOptions): void;
33
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/io/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAYhG;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAuBxF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAK1D"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The `ByteSource` contract guard.
3
+ *
4
+ * Layer 5, and the only file in `io/` that imports an error class. Nothing here knows anything
5
+ * about EDF.
6
+ *
7
+ * The contract is one sentence — a read resolves with EXACTLY `length` bytes or rejects, it
8
+ * never pads and never truncates — and it is *checked on every call*, including calls into a
9
+ * source the caller wrote. A source that quietly returns a short buffer is indistinguishable
10
+ * from a truncated file, so without this guard the parser would confidently report the wrong
11
+ * cause for the wrong thing.
12
+ */
13
+ import { EdfSourceError } from '../errors.js';
14
+ /**
15
+ * A misbehaving source may resolve with something that is not a byte array at all, which is
16
+ * why `EdfSourceError.receivedLength` is `number | undefined` rather than `number`.
17
+ */
18
+ function receivedLengthOf(received) {
19
+ if (received === null || received === undefined)
20
+ return undefined;
21
+ const length = received.length;
22
+ return typeof length === 'number' ? length : undefined;
23
+ }
24
+ /**
25
+ * Enforces the exact-length contract and returns the value unchanged so it can wrap a read
26
+ * expression directly.
27
+ */
28
+ export function assertExactRead(received, offset, length) {
29
+ const receivedLength = receivedLengthOf(received);
30
+ if (receivedLength === length)
31
+ return received;
32
+ const got = receivedLength === undefined ? 'a value that is not a byte array' : `${receivedLength} bytes`;
33
+ throw new EdfSourceError(`ByteSource.read(offset ${offset}, length ${length}) resolved with ${got}. A ByteSource ` +
34
+ 'must resolve with exactly the requested number of bytes or reject: padding or ' +
35
+ 'truncating makes a short read indistinguishable from a truncated file. Next: make ' +
36
+ 'read() loop until `length` bytes have arrived, and reject if they never do.', { offset, requestedLength: length, receivedLength });
37
+ }
38
+ /**
39
+ * Validates a requested range against the source length, with the real numbers in the message.
40
+ *
41
+ * Offsets are plain JS numbers throughout edfcore — exact to 2^53 — so this checks
42
+ * safe-integer-ness rather than truncating with `| 0`, which silently wraps past 2 GiB.
43
+ */
44
+ export function assertReadRange(offset, length, byteLength) {
45
+ if (!Number.isSafeInteger(offset) || offset < 0) {
46
+ throw new EdfSourceError(`ByteSource.read was given offset ${offset}, which is not a non-negative safe integer. ` +
47
+ 'Next: pass a plain integer byte offset; edfcore never truncates offsets to 32 bits.', { offset, requestedLength: length });
48
+ }
49
+ if (!Number.isSafeInteger(length) || length < 0) {
50
+ throw new EdfSourceError(`ByteSource.read was given length ${length}, which is not a non-negative safe integer. ` +
51
+ 'Next: pass a plain integer byte count.', { offset, requestedLength: length });
52
+ }
53
+ if (offset + length > byteLength) {
54
+ throw new EdfSourceError(`ByteSource.read(offset ${offset}, length ${length}) ends at byte ${offset + length}, ` +
55
+ `past the end of a ${byteLength}-byte source. Next: clamp the request, or check that ` +
56
+ 'the source was built over the whole file rather than a prefix of it.', { offset, requestedLength: length });
57
+ }
58
+ }
59
+ /**
60
+ * Aborts a read when the caller's signal is already aborted.
61
+ *
62
+ * `DOMException` cannot be named without the DOM lib, and the thing consumers actually branch
63
+ * on is `error.name === 'AbortError'`, so that is what this produces.
64
+ */
65
+ export function throwIfAborted(options) {
66
+ if (options?.signal?.aborted !== true)
67
+ return;
68
+ const error = new Error('The read was aborted through options.signal.');
69
+ error.name = 'AbortError';
70
+ throw error;
71
+ }
72
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/io/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C;;;GAGG;AACH,SAAS,gBAAgB,CAAC,QAAiB;IACzC,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAClE,MAAM,MAAM,GAAI,QAAiC,CAAC,MAAM,CAAC;IACzD,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAoB,EAAE,MAAc,EAAE,MAAc;IAClF,MAAM,cAAc,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClD,IAAI,cAAc,KAAK,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC/C,MAAM,GAAG,GACP,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,GAAG,cAAc,QAAQ,CAAC;IAChG,MAAM,IAAI,cAAc,CACtB,0BAA0B,MAAM,YAAY,MAAM,mBAAmB,GAAG,iBAAiB;QACvF,gFAAgF;QAChF,oFAAoF;QACpF,6EAA6E,EAC/E,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,CACpD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,MAAc,EAAE,UAAkB;IAChF,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,cAAc,CACtB,oCAAoC,MAAM,8CAA8C;YACtF,qFAAqF,EACvF,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,CACpC,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,cAAc,CACtB,oCAAoC,MAAM,8CAA8C;YACtF,wCAAwC,EAC1C,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,CACpC,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,GAAG,MAAM,GAAG,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,cAAc,CACtB,0BAA0B,MAAM,YAAY,MAAM,kBAAkB,MAAM,GAAG,MAAM,IAAI;YACrF,qBAAqB,UAAU,uDAAuD;YACtF,sEAAsE,EACxE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,CACpC,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI;QAAE,OAAO;IAC9C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACxE,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC;IAC1B,MAAM,KAAK,CAAC;AACd,CAAC"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The Node adapters — the ONLY module in edfcore that imports anything from `node:`.
3
+ *
4
+ * Layer 7, published as `edfcore/node`. Keeping the import in exactly one file is what lets the
5
+ * universal entry (`edfcore`) be bundled for a browser without a polyfill and without a
6
+ * resolution alias, and a packaging test greps the built universal bundle for `node:` to prove it.
7
+ *
8
+ * Two decisions are load-bearing.
9
+ *
10
+ * 1. Reads are POSITIONAL and LOOP. `FileHandle.read` is allowed to return fewer bytes than asked
11
+ * — a signal interrupted the syscall, the file lives on a network mount — and a `ByteSource`
12
+ * that passed a short buffer on would be indistinguishable from a truncated file. The loop
13
+ * runs until `length` bytes have arrived; a genuine end of file falls out as an
14
+ * `EdfSourceError` naming both counts.
15
+ * 2. `fs.openAsBlob` is NEVER used, however tempting `blobSource(await openAsBlob(path))` looks.
16
+ * It reports `size` modulo 2**32 and yields zeros above 4 GiB, which turns a 13 GB BDF into a
17
+ * file that reads as silence with no error anywhere.
18
+ *
19
+ * TYPING. `src/` compiles with `types: []`, so `@types/node` is not available and must never be:
20
+ * the published `.d.ts` may not reference it, or every consumer inherits a dependency on it. The
21
+ * import below is therefore UNTYPED, and the minimal structural shape edfcore needs is declared
22
+ * here instead — `FileHandleLike` and `NodeFsPromises`. A standing CI job compiles a consumer
23
+ * against the real `@types/node` and asserts `fs.promises.FileHandle` is still assignable, which
24
+ * is what stops the two drifting.
25
+ *
26
+ * The suppression on the import is the unconditional `ts-ignore` directive rather than
27
+ * `@ts-expect-error`, and that is not laziness. Whether the specifier resolves depends on whether
28
+ * a `@types/node` happens to be reachable at all: `tsconfig.build.json` compiles `src/` alone and
29
+ * it is not, while `tsconfig.json` also pulls in a dev tool carrying a triple-slash reference to
30
+ * it and it may be. `@ts-expect-error` errors for being UNUSED in the second case, so it would
31
+ * break whichever of the two configurations the machine happens to disagree with.
32
+ */
33
+ import type { ByteSource } from './types.js';
34
+ /**
35
+ * A positional reader with a lifetime. A real `fs.promises.FileHandle` satisfies this.
36
+ *
37
+ * Structural on purpose, so `@types/node` never enters the published `.d.ts` and so a test double
38
+ * — or a handle from another runtime with the same API — is usable without a cast.
39
+ */
40
+ export interface FileHandleLike {
41
+ read(buffer: Uint8Array, offset: number, length: number, position: number): Promise<{
42
+ bytesRead: number;
43
+ }>;
44
+ close(): Promise<void>;
45
+ }
46
+ /**
47
+ * A `ByteSource` over an open file handle.
48
+ *
49
+ * `byteLength` is supplied by the caller rather than read from the handle, because the two ways
50
+ * of learning it differ in what they promise: `fileSource` takes it from the handle it just
51
+ * opened, while a caller wrapping a handle it already had may know something better (a range it
52
+ * intends to expose, a size it verified). Neither is guessed here.
53
+ *
54
+ * `close()` closes the handle. edfcore has no other lifetime mechanism in v0.1 —
55
+ * `Symbol.asyncDispose` is not Baseline yet — so a caller that opened a file is the one that
56
+ * closes it.
57
+ */
58
+ export declare function fileHandleSource(handle: FileHandleLike, byteLength: number): ByteSource;
59
+ /**
60
+ * Open a file for reading and expose it as a `ByteSource`.
61
+ *
62
+ * The size comes from the handle rather than from a separate `stat(path)` call, so the size and
63
+ * the bytes describe the same file even if the path is replaced between the two — on a rotating
64
+ * log or a rsync target that is not hypothetical.
65
+ *
66
+ * The handle is closed if anything goes wrong before it has an owner; after that, closing is the
67
+ * caller's job through `source.close()`.
68
+ */
69
+ export declare function fileSource(path: string): Promise<ByteSource>;
70
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,YAAY,CAAC;AAE1D;;;;;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,UAAU,CA0BvF;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBlE"}
package/dist/node.js ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The Node adapters — the ONLY module in edfcore that imports anything from `node:`.
3
+ *
4
+ * Layer 7, published as `edfcore/node`. Keeping the import in exactly one file is what lets the
5
+ * universal entry (`edfcore`) be bundled for a browser without a polyfill and without a
6
+ * resolution alias, and a packaging test greps the built universal bundle for `node:` to prove it.
7
+ *
8
+ * Two decisions are load-bearing.
9
+ *
10
+ * 1. Reads are POSITIONAL and LOOP. `FileHandle.read` is allowed to return fewer bytes than asked
11
+ * — a signal interrupted the syscall, the file lives on a network mount — and a `ByteSource`
12
+ * that passed a short buffer on would be indistinguishable from a truncated file. The loop
13
+ * runs until `length` bytes have arrived; a genuine end of file falls out as an
14
+ * `EdfSourceError` naming both counts.
15
+ * 2. `fs.openAsBlob` is NEVER used, however tempting `blobSource(await openAsBlob(path))` looks.
16
+ * It reports `size` modulo 2**32 and yields zeros above 4 GiB, which turns a 13 GB BDF into a
17
+ * file that reads as silence with no error anywhere.
18
+ *
19
+ * TYPING. `src/` compiles with `types: []`, so `@types/node` is not available and must never be:
20
+ * the published `.d.ts` may not reference it, or every consumer inherits a dependency on it. The
21
+ * import below is therefore UNTYPED, and the minimal structural shape edfcore needs is declared
22
+ * here instead — `FileHandleLike` and `NodeFsPromises`. A standing CI job compiles a consumer
23
+ * against the real `@types/node` and asserts `fs.promises.FileHandle` is still assignable, which
24
+ * is what stops the two drifting.
25
+ *
26
+ * The suppression on the import is the unconditional `ts-ignore` directive rather than
27
+ * `@ts-expect-error`, and that is not laziness. Whether the specifier resolves depends on whether
28
+ * a `@types/node` happens to be reachable at all: `tsconfig.build.json` compiles `src/` alone and
29
+ * it is not, while `tsconfig.json` also pulls in a dev tool carrying a triple-slash reference to
30
+ * it and it may be. `@ts-expect-error` errors for being UNUSED in the second case, so it would
31
+ * break whichever of the two configurations the machine happens to disagree with.
32
+ */
33
+ // biome-ignore lint/suspicious/noTsIgnore: @ts-expect-error errors when unused — see above.
34
+ // @ts-ignore 'node:fs/promises' has no declarations under `types: []`; its shape is below.
35
+ import * as nodeFsPromises from 'node:fs/promises';
36
+ import { EdfSourceError } from './errors.js';
37
+ import { assertExactRead, assertReadRange, throwIfAborted } from './io/source.js';
38
+ const fs = nodeFsPromises;
39
+ /**
40
+ * A `ByteSource` over an open file handle.
41
+ *
42
+ * `byteLength` is supplied by the caller rather than read from the handle, because the two ways
43
+ * of learning it differ in what they promise: `fileSource` takes it from the handle it just
44
+ * opened, while a caller wrapping a handle it already had may know something better (a range it
45
+ * intends to expose, a size it verified). Neither is guessed here.
46
+ *
47
+ * `close()` closes the handle. edfcore has no other lifetime mechanism in v0.1 —
48
+ * `Symbol.asyncDispose` is not Baseline yet — so a caller that opened a file is the one that
49
+ * closes it.
50
+ */
51
+ export function fileHandleSource(handle, byteLength) {
52
+ return {
53
+ byteLength,
54
+ async read(offset, length, options) {
55
+ throwIfAborted(options);
56
+ assertReadRange(offset, length, byteLength);
57
+ if (length === 0)
58
+ return new Uint8Array(0);
59
+ const buffer = new Uint8Array(length);
60
+ let filled = 0;
61
+ while (filled < length) {
62
+ throwIfAborted(options);
63
+ // Positional: the handle's own file position is never used, so concurrent reads through
64
+ // one handle cannot interleave into each other's buffers.
65
+ const { bytesRead } = await handle.read(buffer, filled, length - filled, offset + filled);
66
+ // Zero bytes means end of file. Looping again would spin forever on a file that is
67
+ // shorter than `byteLength` claimed, so the short read is reported instead.
68
+ if (bytesRead <= 0)
69
+ break;
70
+ filled += bytesRead;
71
+ }
72
+ return assertExactRead(buffer.subarray(0, filled), offset, length);
73
+ },
74
+ async close() {
75
+ await handle.close();
76
+ },
77
+ };
78
+ }
79
+ /**
80
+ * Open a file for reading and expose it as a `ByteSource`.
81
+ *
82
+ * The size comes from the handle rather than from a separate `stat(path)` call, so the size and
83
+ * the bytes describe the same file even if the path is replaced between the two — on a rotating
84
+ * log or a rsync target that is not hypothetical.
85
+ *
86
+ * The handle is closed if anything goes wrong before it has an owner; after that, closing is the
87
+ * caller's job through `source.close()`.
88
+ */
89
+ export async function fileSource(path) {
90
+ const handle = await fs.open(path, 'r');
91
+ try {
92
+ const stats = await handle.stat();
93
+ const byteLength = stats.size;
94
+ if (!Number.isSafeInteger(byteLength) || byteLength < 0) {
95
+ throw new EdfSourceError(`fileSource(): the operating system reported a size of ${byteLength} bytes for ` +
96
+ `${JSON.stringify(path)}, which is not a byte count edfcore can address. Next: check ` +
97
+ 'that the path names a regular file rather than a directory, a pipe or a device.', { offset: 0, requestedLength: 0 });
98
+ }
99
+ return fileHandleSource(handle, byteLength);
100
+ }
101
+ catch (error) {
102
+ // A failure to close is not what the caller needs to hear about: the reason the file is
103
+ // unusable is `error`, and letting close() replace it would hide the diagnosis behind the
104
+ // cleanup. The descriptor is leaked in that case, which is the lesser of the two.
105
+ await handle.close().catch(() => undefined);
106
+ throw error;
107
+ }
108
+ }
109
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;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;AA2BlF,MAAM,EAAE,GAAmB,cAA2C,CAAC;AAEvE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAsB,EAAE,UAAkB;IACzE,OAAO;QACL,UAAU;QACV,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc,EAAE,OAAqB;YAC9D,cAAc,CAAC,OAAO,CAAC,CAAC;YACxB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;YAC5C,IAAI,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAE3C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,OAAO,MAAM,GAAG,MAAM,EAAE,CAAC;gBACvB,cAAc,CAAC,OAAO,CAAC,CAAC;gBACxB,wFAAwF;gBACxF,0DAA0D;gBAC1D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;gBAC1F,mFAAmF;gBACnF,4EAA4E;gBAC5E,IAAI,SAAS,IAAI,CAAC;oBAAE,MAAM;gBAC1B,MAAM,IAAI,SAAS,CAAC;YACtB,CAAC;YACD,OAAO,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrE,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,cAAc,CACtB,yDAAyD,UAAU,aAAa;gBAC9E,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,+DAA+D;gBACtF,iFAAiF,EACnF,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAClC,CAAC;QACJ,CAAC;QACD,OAAO,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,wFAAwF;QACxF,0FAA0F;QAC1F,kFAAkF;QAClF,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The record index: two probes at open, one targeted probe on demand, a full scan only if asked.
3
+ *
4
+ * Layer 6. This module owns the I/O STRATEGY for record onsets and nothing else — what a valid
5
+ * timeline is belongs to `time/timeline.ts`, what a timekeeping TAL is belongs to
6
+ * `tal/annotations.ts`, and segmentation belongs to `time/segments.ts`. Every onset that reaches
7
+ * those modules from here came out of `decodeAnnotations`, so the "first TAL of the first
8
+ * annotation signal" rule has exactly one implementation.
9
+ *
10
+ * Cost is the design constraint. Opening a million-record EDF+D over HTTP must not read the file,
11
+ * so:
12
+ *
13
+ * - a file with no annotation signal is probed ZERO times: without a timekeeping TAL there is no
14
+ * per-record onset on disk, and record `r` starts at `r * recordDuration` by definition;
15
+ * - otherwise `buildTimeline` probes exactly two records, the first and the last, which detects
16
+ * any NET drift of the timeline for two reads. It is not a proof of contiguity, and
17
+ * `time/timeline.ts` says so in the diagnostic it emits;
18
+ * - `onsetTicks(r)` reads that ONE record and memoises the answer, so `locate()` costs
19
+ * O(log recordCount) reads and a second `locate()` nearby costs almost none;
20
+ * - `buildRecordIndex()` is the only function here that touches every record, it is chunked so
21
+ * memory stays bounded whatever the file size, and it is never called implicitly.
22
+ *
23
+ * A probe reads a whole data record rather than just the annotation signal's region. That is
24
+ * decision 7 of the design — the unit of I/O is the record range, never the channel range — and
25
+ * it is also what lets `decodeAnnotations` own the timekeeping rule: it requires the record's
26
+ * full bytes, and reading less would mean reimplementing that rule here.
27
+ */
28
+ import type { BuildIndexOptions, ByteSource, EdfHeader, EdfRecordIndex, EdfRecording, EdfTimeline, OpenOptions } from './types.js';
29
+ /** Records per chunk of a full traversal: bounded memory, and never fewer than one record. */
30
+ export declare function scanChunkRecords(header: EdfHeader, maxMaterializeBytes?: number): number;
31
+ /**
32
+ * The timeline and a lazily probing index, for two reads at most.
33
+ *
34
+ * The probes are records 0 and `recordCount - 1` (one probe for a single-record file, none at all
35
+ * when the file has no annotation signal). Both are memoised into the index, so `onsetTicks(0)`
36
+ * and `onsetTicks(recordCount - 1)` are free after `openEdf`.
37
+ *
38
+ * `index.coverage` stays `'probed'` and `index.segments`/`index.gaps` stay `undefined` until
39
+ * `buildRecordIndex()` promotes them. Nothing on the returned object can be mistaken for a
40
+ * verified statement that the recording is continuous.
41
+ */
42
+ export declare function buildTimeline(source: ByteSource, header: EdfHeader, options?: OpenOptions): Promise<{
43
+ timeline: EdfTimeline;
44
+ index: EdfRecordIndex;
45
+ }>;
46
+ /**
47
+ * A `'complete'` index: every onset verified, with the segments and gaps they imply.
48
+ *
49
+ * This is one of only two functions that read the whole file, the other being `validateRecording`, and it is never called
50
+ * implicitly. Its diagnostics are deliberately not returned — an `EdfRecordIndex` is a
51
+ * structural answer, and `validateRecording()` is the call that reports on a traversal — but a
52
+ * non-monotonic timeline still throws, because no index over it would mean anything.
53
+ *
54
+ * `EdfRecording` is a plain struct, so the returned index is used by rebuilding one:
55
+ * `readWindow({ ...recording, index }, selection)`.
56
+ */
57
+ export declare function buildRecordIndex(recording: EdfRecording, options?: BuildIndexOptions): Promise<EdfRecordIndex>;
58
+ //# sourceMappingURL=record-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-index.d.ts","sourceRoot":"","sources":["../src/record-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAcH,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EAIV,SAAS,EAET,cAAc,EACd,YAAY,EAEZ,WAAW,EACX,WAAW,EAGZ,MAAM,YAAY,CAAC;AAWpB,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,CAOxF;AAkKD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,SAAS,EACjB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC,CAsD3D;AA4CD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,YAAY,EACvB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAyBzB"}