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/README.md +12 -21
- package/dist/main.cjs +199 -196
- package/dist/main.d.cts +2 -2
- package/dist/main.d.mts +2 -2
- package/dist/main.mjs +199 -196
- package/dist/native-DGzYrMHK.d.mts +46 -0
- package/dist/native-_NmVYcF6.d.cts +46 -0
- package/dist/native.cjs +15 -12
- package/dist/native.d.cts +1 -1
- package/dist/native.d.mts +1 -1
- package/dist/native.mjs +15 -12
- package/dist/worker.cjs +40 -28
- package/dist/worker.mjs +40 -28
- package/package.json +9 -9
- package/dist/native-BNwCco1j.d.cts +0 -27
- package/dist/native-BWytCdQz.d.mts +0 -27
package/dist/native.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createNativePager } from "./native-
|
|
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,
|
|
32
|
-
const
|
|
33
|
-
|
|
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
|
|
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 =
|
|
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 (
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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:
|
|
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.
|
|
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/
|
|
13
|
-
"benchmark:deno": "deno --allow-write --allow-read --allow-env test/
|
|
14
|
-
"benchmark:bun": "bun 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"
|
|
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.
|
|
23
|
+
"tsdown": "~0.21.6",
|
|
24
24
|
"typescript": "~6.0.2"
|
|
25
25
|
},
|
|
26
26
|
"optionalDependencies": {
|
|
27
|
-
"@devmor-j/readline-pager-linux-arm64": "0.
|
|
28
|
-
"@devmor-j/readline-pager-linux-musl-arm64": "0.
|
|
29
|
-
"@devmor-j/readline-pager-linux-musl-x64": "0.
|
|
30
|
-
"@devmor-j/readline-pager-linux-x64": "0.
|
|
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 };
|