readline-pager 0.4.10 → 0.6.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/dist/native.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createNativePager } from "./native-BWytCdQz.mjs";
1
+ import { t as createNativePager } from "./native-DGzYrMHK.mjs";
2
2
  export { createNativePager };
package/dist/native.mjs CHANGED
@@ -28,36 +28,39 @@ function loadNativeAddon() {
28
28
  throw new Error(UNAVAILABLE);
29
29
  }
30
30
  }
31
- function createNativePager(filepath, { pageSize = 1e3, delimiter = "\n" } = {}) {
32
- const pagerNative = loadNativeAddon();
33
- let fd = null;
31
+ function createNativePager(filepath, options) {
32
+ const { pageSize = 1e3, delimiter = "\n", backward = false } = options ?? {};
33
+ if (!filepath) throw new Error("filepath required");
34
+ if (pageSize < 1) throw new RangeError("pageSize must be >= 1");
35
+ if (delimiter.length !== 1) throw new RangeError("native reader only supports single-character delimiters");
36
+ const nativePager = loadNativeAddon();
37
+ let fd = nativePager.open(filepath, pageSize, delimiter, backward);
34
38
  let closed = false;
35
- const init = () => {
36
- fd = pagerNative.open(filepath, pageSize, delimiter);
37
- };
38
39
  const next = async () => {
39
40
  if (closed || !fd) return null;
40
- const data = await pagerNative.next(fd);
41
+ const data = await nativePager.next(fd);
41
42
  if (!data) return null;
42
43
  return data.toString("utf8").split(delimiter);
43
44
  };
44
45
  const nextSync = () => {
45
46
  if (closed || !fd) return null;
46
- const data = pagerNative.nextSync(fd);
47
+ const data = nativePager.nextSync(fd);
47
48
  if (!data) return null;
48
49
  return data.toString("utf8").split(delimiter);
49
50
  };
50
51
  const close = async () => {
51
- if (!closed || fd) {
52
- closed = true;
53
- await pagerNative.close(fd);
52
+ if (closed) return;
53
+ closed = true;
54
+ if (fd) {
55
+ try {
56
+ await nativePager.close(fd);
57
+ } catch {}
54
58
  fd = null;
55
59
  }
56
60
  };
57
61
  function tryClose() {
58
62
  close().catch(() => {});
59
63
  }
60
- init();
61
64
  return {
62
65
  next,
63
66
  nextSync,
package/dist/worker.cjs CHANGED
@@ -3,38 +3,50 @@ let node_worker_threads = require("node:worker_threads");
3
3
  //#region src/worker.ts
4
4
  const { filepath, options } = node_worker_threads.workerData;
5
5
  const { chunkSize, pageSize, delimiter } = options;
6
+ const backpressure = pageSize * 8;
7
+ const post = (msg) => {
8
+ if (!node_worker_threads.parentPort) process.exit(1);
9
+ node_worker_threads.parentPort.postMessage(msg);
10
+ };
6
11
  (async () => {
7
- const fd = await (0, node_fs_promises.open)(filepath, "r");
8
- const { size } = await fd.stat();
9
- let pos = 0;
10
- let buffer = "";
11
- const local = [];
12
- while (pos < size) {
13
- const readSize = Math.min(chunkSize, size - pos);
14
- const buf = Buffer.allocUnsafe(readSize);
15
- const { bytesRead } = await fd.read(buf, 0, readSize, pos);
16
- pos += bytesRead;
17
- buffer += buf.toString("utf8", 0, bytesRead);
18
- let idx;
19
- while ((idx = buffer.indexOf(delimiter)) !== -1) {
20
- const line = buffer.slice(0, idx);
21
- buffer = buffer.slice(idx + delimiter.length);
22
- local.push(line);
23
- while (local.length >= pageSize) node_worker_threads.parentPort?.postMessage({
24
- type: "page",
25
- data: local.splice(0, pageSize)
26
- });
12
+ try {
13
+ const fd = await (0, node_fs_promises.open)(filepath, "r");
14
+ const { size } = await fd.stat();
15
+ let pos = 0;
16
+ let buffer = "";
17
+ const local = [];
18
+ while (pos < size) {
19
+ const readSize = Math.min(chunkSize, size - pos);
20
+ const buf = Buffer.allocUnsafe(readSize);
21
+ const { bytesRead } = await fd.read(buf, 0, readSize, pos);
22
+ pos += bytesRead;
23
+ buffer = buffer + buf.toString("utf8", 0, bytesRead);
24
+ let idx;
25
+ while ((idx = buffer.indexOf(delimiter)) !== -1) {
26
+ const line = buffer.slice(0, idx);
27
+ buffer = buffer.slice(idx + delimiter.length);
28
+ local.push(line);
29
+ if (local.length >= pageSize) {
30
+ post({
31
+ type: "page",
32
+ data: local.splice(0, pageSize)
33
+ });
34
+ if (local.length > backpressure) await new Promise((r) => setImmediate(r));
35
+ }
36
+ }
27
37
  }
28
- }
29
- local.push(buffer);
30
- while (local.length > 0) {
31
- const page = local.splice(0, pageSize);
32
- node_worker_threads.parentPort?.postMessage({
38
+ local.push(buffer);
39
+ while (local.length > 0) post({
33
40
  type: "page",
34
- data: page
41
+ data: local.splice(0, pageSize)
42
+ });
43
+ post({ type: "done" });
44
+ await fd.close();
45
+ } catch (err) {
46
+ post({
47
+ type: "error",
48
+ error: err
35
49
  });
36
50
  }
37
- node_worker_threads.parentPort?.postMessage({ type: "done" });
38
- await fd.close();
39
51
  })();
40
52
  //#endregion
package/dist/worker.mjs CHANGED
@@ -3,39 +3,51 @@ import { parentPort, workerData } from "node:worker_threads";
3
3
  //#region src/worker.ts
4
4
  const { filepath, options } = workerData;
5
5
  const { chunkSize, pageSize, delimiter } = options;
6
+ const backpressure = pageSize * 8;
7
+ const post = (msg) => {
8
+ if (!parentPort) process.exit(1);
9
+ parentPort.postMessage(msg);
10
+ };
6
11
  (async () => {
7
- const fd = await open(filepath, "r");
8
- const { size } = await fd.stat();
9
- let pos = 0;
10
- let buffer = "";
11
- const local = [];
12
- while (pos < size) {
13
- const readSize = Math.min(chunkSize, size - pos);
14
- const buf = Buffer.allocUnsafe(readSize);
15
- const { bytesRead } = await fd.read(buf, 0, readSize, pos);
16
- pos += bytesRead;
17
- buffer += buf.toString("utf8", 0, bytesRead);
18
- let idx;
19
- while ((idx = buffer.indexOf(delimiter)) !== -1) {
20
- const line = buffer.slice(0, idx);
21
- buffer = buffer.slice(idx + delimiter.length);
22
- local.push(line);
23
- while (local.length >= pageSize) parentPort?.postMessage({
24
- type: "page",
25
- data: local.splice(0, pageSize)
26
- });
12
+ try {
13
+ const fd = await open(filepath, "r");
14
+ const { size } = await fd.stat();
15
+ let pos = 0;
16
+ let buffer = "";
17
+ const local = [];
18
+ while (pos < size) {
19
+ const readSize = Math.min(chunkSize, size - pos);
20
+ const buf = Buffer.allocUnsafe(readSize);
21
+ const { bytesRead } = await fd.read(buf, 0, readSize, pos);
22
+ pos += bytesRead;
23
+ buffer = buffer + buf.toString("utf8", 0, bytesRead);
24
+ let idx;
25
+ while ((idx = buffer.indexOf(delimiter)) !== -1) {
26
+ const line = buffer.slice(0, idx);
27
+ buffer = buffer.slice(idx + delimiter.length);
28
+ local.push(line);
29
+ if (local.length >= pageSize) {
30
+ post({
31
+ type: "page",
32
+ data: local.splice(0, pageSize)
33
+ });
34
+ if (local.length > backpressure) await new Promise((r) => setImmediate(r));
35
+ }
36
+ }
27
37
  }
28
- }
29
- local.push(buffer);
30
- while (local.length > 0) {
31
- const page = local.splice(0, pageSize);
32
- parentPort?.postMessage({
38
+ local.push(buffer);
39
+ while (local.length > 0) post({
33
40
  type: "page",
34
- data: page
41
+ data: local.splice(0, pageSize)
42
+ });
43
+ post({ type: "done" });
44
+ await fd.close();
45
+ } catch (err) {
46
+ post({
47
+ type: "error",
48
+ error: err
35
49
  });
36
50
  }
37
- parentPort?.postMessage({ type: "done" });
38
- await fd.close();
39
51
  })();
40
52
  //#endregion
41
53
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "readline-pager",
3
- "version": "0.4.10",
3
+ "version": "0.6.2",
4
4
  "scripts": {
5
5
  "build:js": "tsdown",
6
6
  "build:native": "node-gyp rebuild",
@@ -9,9 +9,9 @@
9
9
  "pretest": "npm run build",
10
10
  "test": "TEST_CLEANUPS=1 node --test --experimental-test-coverage test/**/*.test.ts",
11
11
  "prepublishOnly": "npm run build && npm run test",
12
- "benchmark:node": "node test/_benchmark.ts",
13
- "benchmark:deno": "deno --allow-write --allow-read --allow-env test/_benchmark.ts",
14
- "benchmark:bun": "bun test/_benchmark.ts"
12
+ "benchmark:node": "node test/benchmark.ts",
13
+ "benchmark:deno": "deno --allow-write --allow-read --allow-env test/benchmark.ts",
14
+ "benchmark:bun": "bun test/benchmark.ts"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@types/bun": "~1.3.11",
@@ -20,14 +20,14 @@
20
20
  "node-gyp": "~12.2.0",
21
21
  "prettier": "~3.8.1",
22
22
  "prettier-plugin-organize-imports": "~4.3.0",
23
- "tsdown": "~0.21.5",
23
+ "tsdown": "~0.21.6",
24
24
  "typescript": "~6.0.2"
25
25
  },
26
26
  "optionalDependencies": {
27
- "@devmor-j/readline-pager-linux-arm64": "0.4.10",
28
- "@devmor-j/readline-pager-linux-musl-arm64": "0.4.10",
29
- "@devmor-j/readline-pager-linux-musl-x64": "0.4.10",
30
- "@devmor-j/readline-pager-linux-x64": "0.4.10"
27
+ "@devmor-j/readline-pager-linux-arm64": "0.6.2",
28
+ "@devmor-j/readline-pager-linux-musl-arm64": "0.6.2",
29
+ "@devmor-j/readline-pager-linux-musl-x64": "0.6.2",
30
+ "@devmor-j/readline-pager-linux-x64": "0.6.2"
31
31
  },
32
32
  "gypfile": false,
33
33
  "type": "module",
@@ -1,27 +0,0 @@
1
- //#region src/types.d.ts
2
- interface ReaderOptions {
3
- chunkSize: number;
4
- pageSize: number;
5
- delimiter: string;
6
- prefetch: number;
7
- }
8
- interface PagerOptions extends Partial<ReaderOptions> {
9
- backward?: boolean;
10
- useWorker?: boolean;
11
- }
12
- interface Pager extends AsyncIterable<string[]>, Iterable<string[]> {
13
- next(): Promise<string[] | null>;
14
- nextSync(): string[] | null;
15
- close(): Promise<void>;
16
- }
17
- //#endregion
18
- //#region src/native.d.ts
19
- declare function createNativePager(filepath: string, {
20
- pageSize,
21
- delimiter
22
- }?: {
23
- pageSize?: number | undefined;
24
- delimiter?: string | undefined;
25
- }): Pager;
26
- //#endregion
27
- export { ReaderOptions as i, Pager as n, PagerOptions as r, createNativePager as t };
@@ -1,27 +0,0 @@
1
- //#region src/types.d.ts
2
- interface ReaderOptions {
3
- chunkSize: number;
4
- pageSize: number;
5
- delimiter: string;
6
- prefetch: number;
7
- }
8
- interface PagerOptions extends Partial<ReaderOptions> {
9
- backward?: boolean;
10
- useWorker?: boolean;
11
- }
12
- interface Pager extends AsyncIterable<string[]>, Iterable<string[]> {
13
- next(): Promise<string[] | null>;
14
- nextSync(): string[] | null;
15
- close(): Promise<void>;
16
- }
17
- //#endregion
18
- //#region src/native.d.ts
19
- declare function createNativePager(filepath: string, {
20
- pageSize,
21
- delimiter
22
- }?: {
23
- pageSize?: number | undefined;
24
- delimiter?: string | undefined;
25
- }): Pager;
26
- //#endregion
27
- export { ReaderOptions as i, Pager as n, PagerOptions as r, createNativePager as t };