@nitpicker/crawler 0.6.3 → 0.7.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.
- package/lib/crawler/fetch-destination.js +11 -5
- package/package.json +2 -2
- package/lib/archive/common-queries.d.ts +0 -14
- package/lib/archive/common-queries.js +0 -40
- package/lib/archive/filesystem/index.d.ts +0 -17
- package/lib/archive/filesystem/index.js +0 -17
- package/lib/archive/filesystem/utils.d.ts +0 -109
- package/lib/archive/filesystem/utils.js +0 -185
- package/lib/archive/filesystem/zip.d.ts +0 -29
- package/lib/archive/filesystem/zip.js +0 -53
- package/lib/archive/index.d.ts +0 -6
- package/lib/archive/index.js +0 -11
- package/lib/crawler/index.d.ts +0 -2
- package/lib/crawler/index.js +0 -2
- package/lib/crawler/network.d.ts +0 -30
- package/lib/crawler/network.js +0 -226
- package/lib/crawler/result-handler.d.ts +0 -118
- package/lib/crawler/result-handler.js +0 -153
- package/lib/crawler/speculative-pagination.d.ts +0 -52
- package/lib/crawler/speculative-pagination.js +0 -215
- package/lib/crawler/url-filter.d.ts +0 -56
- package/lib/crawler/url-filter.js +0 -110
- package/lib/index.d.ts +0 -16
- package/lib/index.js +0 -18
- package/lib/qzilla.d.ts +0 -136
- package/lib/qzilla.js +0 -292
- package/lib/utils/array/index.d.ts +0 -1
- package/lib/utils/array/index.js +0 -1
- package/lib/utils/async/index.d.ts +0 -1
- package/lib/utils/async/index.js +0 -1
- package/lib/utils/error/index.d.ts +0 -3
- package/lib/utils/error/index.js +0 -2
- package/lib/utils/event-emitter/index.d.ts +0 -6
- package/lib/utils/event-emitter/index.js +0 -6
- package/lib/utils/index.d.ts +0 -5
- package/lib/utils/index.js +0 -5
- package/lib/utils/network/index.d.ts +0 -1
- package/lib/utils/network/index.js +0 -1
- package/lib/utils/object/index.d.ts +0 -1
- package/lib/utils/object/index.js +0 -1
- package/lib/utils/path/index.d.ts +0 -1
- package/lib/utils/path/index.js +0 -1
- package/lib/utils/path/safe-filepath.d.ts +0 -7
- package/lib/utils/path/safe-filepath.js +0 -12
- package/lib/utils/regexp/index.d.ts +0 -1
- package/lib/utils/regexp/index.js +0 -1
- package/lib/utils/retryable/index.d.ts +0 -2
- package/lib/utils/retryable/index.js +0 -1
- package/lib/utils/sort/index.d.ts +0 -14
- package/lib/utils/sort/index.js +0 -61
- package/lib/utils/sort/remove-matches.d.ts +0 -9
- package/lib/utils/sort/remove-matches.js +0 -23
- package/lib/utils/types/index.d.ts +0 -1
- package/lib/utils/types/index.js +0 -1
- package/lib/utils/url/index.d.ts +0 -5
- package/lib/utils/url/index.js +0 -5
- package/lib/utils/url/is-lower-layer.d.ts +0 -15
- package/lib/utils/url/is-lower-layer.js +0 -55
- package/lib/utils/url/parse-url.d.ts +0 -11
- package/lib/utils/url/parse-url.js +0 -20
- package/lib/utils/url/path-match.d.ts +0 -11
- package/lib/utils/url/path-match.js +0 -18
- package/lib/utils/url/sort-url.d.ts +0 -10
- package/lib/utils/url/sort-url.js +0 -24
- package/lib/utils/url/url-partial-match.d.ts +0 -11
- package/lib/utils/url/url-partial-match.js +0 -32
|
@@ -28,13 +28,19 @@ export async function fetchDestination(params) {
|
|
|
28
28
|
return cache;
|
|
29
29
|
}
|
|
30
30
|
const effectiveMethod = titleBytesLimit == null ? method : 'GET';
|
|
31
|
+
// Race the fetch against a 10-second timeout. The losing timer is cleared
|
|
32
|
+
// explicitly so it never keeps the event loop alive after the race settles
|
|
33
|
+
// (a plain `delay()` in `Promise.race` would leak the timer until it fires).
|
|
34
|
+
let timeoutHandle;
|
|
31
35
|
const result = await Promise.race([
|
|
32
36
|
_fetchHead(url, isExternal, effectiveMethod, titleBytesLimit, userAgent).catch((error) => (error instanceof Error ? error : new Error(String(error)))),
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
new Promise((resolve) => {
|
|
38
|
+
timeoutHandle = setTimeout(() => resolve(new NetTimeoutError(url.href)), 10 * 1000);
|
|
39
|
+
}),
|
|
40
|
+
]).finally(() => {
|
|
41
|
+
if (timeoutHandle)
|
|
42
|
+
clearTimeout(timeoutHandle);
|
|
43
|
+
});
|
|
38
44
|
destinationCache.set(cacheKey, result);
|
|
39
45
|
if (result instanceof Error) {
|
|
40
46
|
throw result;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitpicker/crawler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Web crawler engine with headless browser rendering and archive storage",
|
|
5
5
|
"author": "D-ZERO",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"@types/tar": "7.0.87",
|
|
49
49
|
"@types/unzipper": "0.10.11"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "3b4c33adf8af69a46a85faf8c04eddb5ab563972"
|
|
52
52
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Knex } from 'knex';
|
|
2
|
-
/**
|
|
3
|
-
* Returns a Knex subquery builder that selects page IDs with pagination,
|
|
4
|
-
* ordered by the `order` column (nulls last), excluding redirected pages.
|
|
5
|
-
* @param limit - The maximum number of page IDs to return.
|
|
6
|
-
* @param offset - The number of page IDs to skip before returning results.
|
|
7
|
-
*/
|
|
8
|
-
export declare function limitedPageIds(limit: number, offset: number): (qb: Knex.QueryBuilder<Record<string, unknown>, unknown>) => Promise<void>;
|
|
9
|
-
/**
|
|
10
|
-
* Returns a Knex subquery builder that joins pages with their redirect destinations.
|
|
11
|
-
* When `includeNull` is true, also includes pages without redirects (self-referencing).
|
|
12
|
-
* @param includeNull - Whether to include non-redirected pages in the result. Defaults to `true`.
|
|
13
|
-
*/
|
|
14
|
-
export declare function redirectTable(includeNull?: boolean): (qb: Knex.QueryBuilder<Record<string, unknown>, unknown>) => Promise<void>;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns a Knex subquery builder that selects page IDs with pagination,
|
|
3
|
-
* ordered by the `order` column (nulls last), excluding redirected pages.
|
|
4
|
-
* @param limit - The maximum number of page IDs to return.
|
|
5
|
-
* @param offset - The number of page IDs to skip before returning results.
|
|
6
|
-
*/
|
|
7
|
-
export function limitedPageIds(limit, offset) {
|
|
8
|
-
return async (qb) => {
|
|
9
|
-
await qb
|
|
10
|
-
.select('id')
|
|
11
|
-
.from('pages')
|
|
12
|
-
.orderByRaw('`order` ASC NULLS LAST')
|
|
13
|
-
.whereNull('redirectDestId')
|
|
14
|
-
.limit(limit)
|
|
15
|
-
.offset(offset);
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Returns a Knex subquery builder that joins pages with their redirect destinations.
|
|
20
|
-
* When `includeNull` is true, also includes pages without redirects (self-referencing).
|
|
21
|
-
* @param includeNull - Whether to include non-redirected pages in the result. Defaults to `true`.
|
|
22
|
-
*/
|
|
23
|
-
export function redirectTable(includeNull = true) {
|
|
24
|
-
return async (qb) => {
|
|
25
|
-
const list = qb
|
|
26
|
-
.select('A.id as fromId', 'A.url as from', 'B.url as to', 'B.id as toId')
|
|
27
|
-
.from('pages as A')
|
|
28
|
-
.join('pages as B', (j) => {
|
|
29
|
-
j.on('A.redirectDestId', '=', 'B.id').andOnNotNull('A.redirectDestId');
|
|
30
|
-
});
|
|
31
|
-
if (includeNull) {
|
|
32
|
-
await list.union(async (qb) => {
|
|
33
|
-
await qb
|
|
34
|
-
.select('A.id as fromId', 'A.url as from', 'A.url as to', 'A.id as toId')
|
|
35
|
-
.from('pages as A')
|
|
36
|
-
.whereNull('A.redirectDestId');
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export { outputJSON } from './output-json.js';
|
|
2
|
-
export { readJSON } from './read-json.js';
|
|
3
|
-
export { outputText } from './output-text.js';
|
|
4
|
-
export { appendText } from './append-text.js';
|
|
5
|
-
export { readText } from './read-text.js';
|
|
6
|
-
export { copyDir } from './copy-dir.js';
|
|
7
|
-
export { copyDirSync } from './copy-dir-sync.js';
|
|
8
|
-
export { isDir } from './is-dir.js';
|
|
9
|
-
export { remove } from './remove.js';
|
|
10
|
-
export { rename } from './rename.js';
|
|
11
|
-
export { getFileList } from './get-file-list.js';
|
|
12
|
-
export { readline } from './readline.js';
|
|
13
|
-
export { mkdir } from './mkdir.js';
|
|
14
|
-
export { exists } from './exists.js';
|
|
15
|
-
export { tar } from './tar.js';
|
|
16
|
-
export { untar } from './untar.js';
|
|
17
|
-
export { zip, unzip, extractZip } from '@d-zero/fs/zip';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export { outputJSON } from './output-json.js';
|
|
2
|
-
export { readJSON } from './read-json.js';
|
|
3
|
-
export { outputText } from './output-text.js';
|
|
4
|
-
export { appendText } from './append-text.js';
|
|
5
|
-
export { readText } from './read-text.js';
|
|
6
|
-
export { copyDir } from './copy-dir.js';
|
|
7
|
-
export { copyDirSync } from './copy-dir-sync.js';
|
|
8
|
-
export { isDir } from './is-dir.js';
|
|
9
|
-
export { remove } from './remove.js';
|
|
10
|
-
export { rename } from './rename.js';
|
|
11
|
-
export { getFileList } from './get-file-list.js';
|
|
12
|
-
export { readline } from './readline.js';
|
|
13
|
-
export { mkdir } from './mkdir.js';
|
|
14
|
-
export { exists } from './exists.js';
|
|
15
|
-
export { tar } from './tar.js';
|
|
16
|
-
export { untar } from './untar.js';
|
|
17
|
-
export { zip, unzip, extractZip } from '@d-zero/fs/zip';
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Writes data to a JSON file at the specified path.
|
|
3
|
-
*
|
|
4
|
-
* Creates parent directories if they do not exist.
|
|
5
|
-
* The output is formatted with 2-space indentation.
|
|
6
|
-
* @param filePath - The absolute or relative path to the JSON file to write.
|
|
7
|
-
* @param data - The data to serialize as JSON and write to the file.
|
|
8
|
-
*/
|
|
9
|
-
export declare function outputJSON(filePath: string, data: unknown): Promise<void>;
|
|
10
|
-
/**
|
|
11
|
-
* Reads and parses a JSON file from the specified path.
|
|
12
|
-
* @template T - The expected type of the parsed JSON content. Defaults to `unknown`.
|
|
13
|
-
* @param filePath - The absolute or relative path to the JSON file to read.
|
|
14
|
-
* @returns The parsed JSON content, cast to the specified generic type.
|
|
15
|
-
*/
|
|
16
|
-
export declare function readJSON<T = unknown>(filePath: string): Promise<T>;
|
|
17
|
-
/**
|
|
18
|
-
* Writes text data to a file at the specified path.
|
|
19
|
-
*
|
|
20
|
-
* Creates parent directories if they do not exist.
|
|
21
|
-
* If the file path exceeds the OS limit (ENAMETOOLONG), the file is saved
|
|
22
|
-
* with an auto-generated short name and an accompanying `.meta.txt` file
|
|
23
|
-
* that records the original file path.
|
|
24
|
-
* @param filePath - The absolute or relative path to the text file to write.
|
|
25
|
-
* @param data - The text content to write to the file.
|
|
26
|
-
*/
|
|
27
|
-
export declare function outputText(filePath: string, data: string): Promise<void>;
|
|
28
|
-
/**
|
|
29
|
-
* Appends text data to a file at the specified path.
|
|
30
|
-
*
|
|
31
|
-
* Creates parent directories if they do not exist.
|
|
32
|
-
* A newline character is prepended to the data before appending.
|
|
33
|
-
* @param filePath - The absolute or relative path to the file to append to.
|
|
34
|
-
* @param data - The text content to append to the file.
|
|
35
|
-
*/
|
|
36
|
-
export declare function appendText(filePath: string, data: string): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* Reads the entire contents of a text file as a UTF-8 string.
|
|
39
|
-
* @param filePath - The absolute or relative path to the text file to read.
|
|
40
|
-
* @returns The text content of the file.
|
|
41
|
-
*/
|
|
42
|
-
export declare function readText(filePath: string): Promise<string>;
|
|
43
|
-
/**
|
|
44
|
-
* Recursively copies a directory and its contents from one location to another.
|
|
45
|
-
* @param from - The source directory path to copy from.
|
|
46
|
-
* @param to - The destination directory path to copy to.
|
|
47
|
-
* @returns `true` if the copy succeeded, `false` if an error occurred.
|
|
48
|
-
*/
|
|
49
|
-
export declare function copyDir(from: string, to: string): Promise<boolean>;
|
|
50
|
-
/**
|
|
51
|
-
* Synchronously copies a directory and its contents from one location to another.
|
|
52
|
-
* @param from - The source directory path to copy from.
|
|
53
|
-
* @param to - The destination directory path to copy to.
|
|
54
|
-
*/
|
|
55
|
-
export declare function copyDirSync(from: string, to: string): void;
|
|
56
|
-
/**
|
|
57
|
-
* Checks whether the given path points to a directory.
|
|
58
|
-
* @param dirPath - The path to check.
|
|
59
|
-
* @returns `true` if the path is a directory, `false` otherwise.
|
|
60
|
-
*/
|
|
61
|
-
export declare function isDir(dirPath: string): Promise<boolean>;
|
|
62
|
-
/**
|
|
63
|
-
* Recursively removes a file or directory at the specified path.
|
|
64
|
-
* @param dirPath - The path of the file or directory to remove.
|
|
65
|
-
*/
|
|
66
|
-
export declare function remove(dirPath: string): Promise<void>;
|
|
67
|
-
/**
|
|
68
|
-
* Renames (moves) a file or directory from one path to another.
|
|
69
|
-
*
|
|
70
|
-
* If `override` is `true` and the destination already exists,
|
|
71
|
-
* the destination is removed before renaming.
|
|
72
|
-
* @param oldPath - The current path of the file or directory.
|
|
73
|
-
* @param newPath - The new path for the file or directory.
|
|
74
|
-
* @param override - Whether to overwrite the destination if it already exists. Defaults to `false`.
|
|
75
|
-
*/
|
|
76
|
-
export declare function rename(oldPath: string, newPath: string, override?: boolean): Promise<void>;
|
|
77
|
-
/**
|
|
78
|
-
* Lists the file names in a directory, optionally filtered by a pattern.
|
|
79
|
-
* @param dirPath - The directory path to list files from.
|
|
80
|
-
* @param filter - An optional RegExp or string pattern to filter file names.
|
|
81
|
-
* Only file names matching this pattern are included in the result.
|
|
82
|
-
* @returns An array of file names in the directory that match the filter (or all if no filter is provided).
|
|
83
|
-
*/
|
|
84
|
-
export declare function getFileList(dirPath: string, filter?: RegExp | string): Promise<string[]>;
|
|
85
|
-
/**
|
|
86
|
-
* Reads a file line by line and invokes the callback for each line.
|
|
87
|
-
*
|
|
88
|
-
* The callback may return a Promise for asynchronous processing.
|
|
89
|
-
* All callback results are collected and awaited via `Promise.all` before returning.
|
|
90
|
-
* @param filePath - The path to the file to read line by line.
|
|
91
|
-
* @param callback - A function invoked for each line of the file.
|
|
92
|
-
* May return a Promise for asynchronous operations.
|
|
93
|
-
* @returns A promise that resolves when all line callbacks have completed.
|
|
94
|
-
*/
|
|
95
|
-
export declare function readline(filePath: string, callback: (line: string) => Promise<void> | void): Promise<void[]>;
|
|
96
|
-
/**
|
|
97
|
-
* Ensures the parent directory of the given file path exists.
|
|
98
|
-
*
|
|
99
|
-
* If the parent directory does not exist, it is created recursively
|
|
100
|
-
* with permissions `0o755`.
|
|
101
|
-
* @param filePath - The file path whose parent directory should be created.
|
|
102
|
-
*/
|
|
103
|
-
export declare function mkdir(filePath: string): void;
|
|
104
|
-
/**
|
|
105
|
-
* Checks whether a file or directory exists at the given path.
|
|
106
|
-
* @param filePath - The path to check for existence.
|
|
107
|
-
* @returns `true` if the path exists, `false` otherwise.
|
|
108
|
-
*/
|
|
109
|
-
export declare function exists(filePath: string): boolean;
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { createReadStream, existsSync, promises as fs, mkdirSync } from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import Readline from 'node:readline';
|
|
4
|
-
import fsx from 'fs-extra';
|
|
5
|
-
/**
|
|
6
|
-
* Writes data to a JSON file at the specified path.
|
|
7
|
-
*
|
|
8
|
-
* Creates parent directories if they do not exist.
|
|
9
|
-
* The output is formatted with 2-space indentation.
|
|
10
|
-
* @param filePath - The absolute or relative path to the JSON file to write.
|
|
11
|
-
* @param data - The data to serialize as JSON and write to the file.
|
|
12
|
-
*/
|
|
13
|
-
export async function outputJSON(filePath, data) {
|
|
14
|
-
mkdir(filePath);
|
|
15
|
-
await fs.writeFile(filePath, JSON.stringify(data, null, 2), { encoding: 'utf8' });
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Reads and parses a JSON file from the specified path.
|
|
19
|
-
* @template T - The expected type of the parsed JSON content. Defaults to `unknown`.
|
|
20
|
-
* @param filePath - The absolute or relative path to the JSON file to read.
|
|
21
|
-
* @returns The parsed JSON content, cast to the specified generic type.
|
|
22
|
-
*/
|
|
23
|
-
export async function readJSON(filePath) {
|
|
24
|
-
const data = await fs.readFile(filePath, { encoding: 'utf8' });
|
|
25
|
-
return JSON.parse(data);
|
|
26
|
-
}
|
|
27
|
-
let filePathTooLongCount = 0;
|
|
28
|
-
/**
|
|
29
|
-
* Writes text data to a file at the specified path.
|
|
30
|
-
*
|
|
31
|
-
* Creates parent directories if they do not exist.
|
|
32
|
-
* If the file path exceeds the OS limit (ENAMETOOLONG), the file is saved
|
|
33
|
-
* with an auto-generated short name and an accompanying `.meta.txt` file
|
|
34
|
-
* that records the original file path.
|
|
35
|
-
* @param filePath - The absolute or relative path to the text file to write.
|
|
36
|
-
* @param data - The text content to write to the file.
|
|
37
|
-
*/
|
|
38
|
-
export async function outputText(filePath, data) {
|
|
39
|
-
mkdir(filePath);
|
|
40
|
-
await fs.writeFile(filePath, data, { encoding: 'utf8' }).catch(async (error) => {
|
|
41
|
-
if (error instanceof Error && 'code' in error && error.code === 'ENAMETOOLONG') {
|
|
42
|
-
// eslint-disable-next-line no-console
|
|
43
|
-
console.error(`File path too long: ${filePath}`);
|
|
44
|
-
const dir = path.dirname(filePath);
|
|
45
|
-
const altFileName = `__file_path_too_long_${(filePathTooLongCount++).toString().padStart(4, '0')}`;
|
|
46
|
-
const ext = path.extname(filePath);
|
|
47
|
-
const altFilePath = path.resolve(dir, `${altFileName}${ext}`);
|
|
48
|
-
// eslint-disable-next-line no-console
|
|
49
|
-
console.error(`Try to save to: ${altFilePath}`);
|
|
50
|
-
const altMetaFilePath = path.resolve(dir, `${altFileName}.meta.txt`);
|
|
51
|
-
await outputText(altFilePath, data);
|
|
52
|
-
await outputText(altMetaFilePath, `Original file path: ${filePath}`);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Appends text data to a file at the specified path.
|
|
58
|
-
*
|
|
59
|
-
* Creates parent directories if they do not exist.
|
|
60
|
-
* A newline character is prepended to the data before appending.
|
|
61
|
-
* @param filePath - The absolute or relative path to the file to append to.
|
|
62
|
-
* @param data - The text content to append to the file.
|
|
63
|
-
*/
|
|
64
|
-
export async function appendText(filePath, data) {
|
|
65
|
-
mkdir(filePath);
|
|
66
|
-
await fs.appendFile(filePath, `\n${data}`, { encoding: 'utf8' });
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Reads the entire contents of a text file as a UTF-8 string.
|
|
70
|
-
* @param filePath - The absolute or relative path to the text file to read.
|
|
71
|
-
* @returns The text content of the file.
|
|
72
|
-
*/
|
|
73
|
-
export async function readText(filePath) {
|
|
74
|
-
const data = await fs.readFile(filePath, { encoding: 'utf8' });
|
|
75
|
-
return data;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Recursively copies a directory and its contents from one location to another.
|
|
79
|
-
* @param from - The source directory path to copy from.
|
|
80
|
-
* @param to - The destination directory path to copy to.
|
|
81
|
-
* @returns `true` if the copy succeeded, `false` if an error occurred.
|
|
82
|
-
*/
|
|
83
|
-
export async function copyDir(from, to) {
|
|
84
|
-
return fsx
|
|
85
|
-
.copy(from, to)
|
|
86
|
-
.then(() => true)
|
|
87
|
-
.catch(() => false);
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Synchronously copies a directory and its contents from one location to another.
|
|
91
|
-
* @param from - The source directory path to copy from.
|
|
92
|
-
* @param to - The destination directory path to copy to.
|
|
93
|
-
*/
|
|
94
|
-
export function copyDirSync(from, to) {
|
|
95
|
-
fsx.copySync(from, to);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Checks whether the given path points to a directory.
|
|
99
|
-
* @param dirPath - The path to check.
|
|
100
|
-
* @returns `true` if the path is a directory, `false` otherwise.
|
|
101
|
-
*/
|
|
102
|
-
export async function isDir(dirPath) {
|
|
103
|
-
const stat = await fsx.stat(dirPath);
|
|
104
|
-
return stat.isDirectory();
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Recursively removes a file or directory at the specified path.
|
|
108
|
-
* @param dirPath - The path of the file or directory to remove.
|
|
109
|
-
*/
|
|
110
|
-
export async function remove(dirPath) {
|
|
111
|
-
await fs.rm(dirPath, {
|
|
112
|
-
recursive: true,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Renames (moves) a file or directory from one path to another.
|
|
117
|
-
*
|
|
118
|
-
* If `override` is `true` and the destination already exists,
|
|
119
|
-
* the destination is removed before renaming.
|
|
120
|
-
* @param oldPath - The current path of the file or directory.
|
|
121
|
-
* @param newPath - The new path for the file or directory.
|
|
122
|
-
* @param override - Whether to overwrite the destination if it already exists. Defaults to `false`.
|
|
123
|
-
*/
|
|
124
|
-
export async function rename(oldPath, newPath, override = false) {
|
|
125
|
-
if (override && exists(newPath)) {
|
|
126
|
-
await remove(newPath);
|
|
127
|
-
}
|
|
128
|
-
await fs.rename(oldPath, newPath);
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Lists the file names in a directory, optionally filtered by a pattern.
|
|
132
|
-
* @param dirPath - The directory path to list files from.
|
|
133
|
-
* @param filter - An optional RegExp or string pattern to filter file names.
|
|
134
|
-
* Only file names matching this pattern are included in the result.
|
|
135
|
-
* @returns An array of file names in the directory that match the filter (or all if no filter is provided).
|
|
136
|
-
*/
|
|
137
|
-
export async function getFileList(dirPath, filter) {
|
|
138
|
-
const list = await fsx.readdir(dirPath);
|
|
139
|
-
return filter ? list.filter((fileName) => fileName.match(filter)) : list;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Reads a file line by line and invokes the callback for each line.
|
|
143
|
-
*
|
|
144
|
-
* The callback may return a Promise for asynchronous processing.
|
|
145
|
-
* All callback results are collected and awaited via `Promise.all` before returning.
|
|
146
|
-
* @param filePath - The path to the file to read line by line.
|
|
147
|
-
* @param callback - A function invoked for each line of the file.
|
|
148
|
-
* May return a Promise for asynchronous operations.
|
|
149
|
-
* @returns A promise that resolves when all line callbacks have completed.
|
|
150
|
-
*/
|
|
151
|
-
export async function readline(filePath, callback) {
|
|
152
|
-
const stream = createReadStream(filePath);
|
|
153
|
-
const rLine = Readline.createInterface(stream);
|
|
154
|
-
const promiseBuffer = [];
|
|
155
|
-
await new Promise((resolve) => {
|
|
156
|
-
rLine.on('line', (line) => {
|
|
157
|
-
promiseBuffer.push(callback(line));
|
|
158
|
-
});
|
|
159
|
-
rLine.on('close', () => {
|
|
160
|
-
resolve();
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
return Promise.all(promiseBuffer);
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Ensures the parent directory of the given file path exists.
|
|
167
|
-
*
|
|
168
|
-
* If the parent directory does not exist, it is created recursively
|
|
169
|
-
* with permissions `0o755`.
|
|
170
|
-
* @param filePath - The file path whose parent directory should be created.
|
|
171
|
-
*/
|
|
172
|
-
export function mkdir(filePath) {
|
|
173
|
-
const { dir } = path.parse(filePath);
|
|
174
|
-
if (!existsSync(dir)) {
|
|
175
|
-
mkdirSync(path.resolve(dir), { recursive: true, mode: 0o755 });
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Checks whether a file or directory exists at the given path.
|
|
180
|
-
* @param filePath - The path to check for existence.
|
|
181
|
-
* @returns `true` if the path exists, `false` otherwise.
|
|
182
|
-
*/
|
|
183
|
-
export function exists(filePath) {
|
|
184
|
-
return existsSync(filePath);
|
|
185
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a ZIP archive from a directory and writes it to a file.
|
|
3
|
-
*
|
|
4
|
-
* All files and subdirectories within `targetDir` are added to the archive
|
|
5
|
-
* at the root level (no wrapping directory).
|
|
6
|
-
* @param outputfilePath - The file path where the ZIP archive will be written.
|
|
7
|
-
* @param targetDir - The directory whose contents will be compressed into the ZIP archive.
|
|
8
|
-
* @returns A promise that resolves when the ZIP file has been fully written,
|
|
9
|
-
* or rejects if the write stream encounters an error.
|
|
10
|
-
*/
|
|
11
|
-
export declare function zip(outputfilePath: string, targetDir: string): Promise<void>;
|
|
12
|
-
/**
|
|
13
|
-
* Extracts a ZIP archive to a target directory.
|
|
14
|
-
* @param zipFilePath - The path to the ZIP file to extract.
|
|
15
|
-
* @param targetDir - The directory where the ZIP contents will be extracted to.
|
|
16
|
-
* @returns A promise that resolves when extraction is complete,
|
|
17
|
-
* or rejects if an error occurs during extraction.
|
|
18
|
-
*/
|
|
19
|
-
export declare function unzip(zipFilePath: string, targetDir: string): Promise<void>;
|
|
20
|
-
/**
|
|
21
|
-
* Opens a ZIP file and returns its directory listing without extracting.
|
|
22
|
-
*
|
|
23
|
-
* This is useful for inspecting the contents of a ZIP archive
|
|
24
|
-
* before performing a full extraction.
|
|
25
|
-
* @param zipFilePath - The path to the ZIP file to open and inspect.
|
|
26
|
-
* @returns A directory object representing the ZIP archive contents,
|
|
27
|
-
* which can be used to list or selectively extract entries.
|
|
28
|
-
*/
|
|
29
|
-
export declare function extractZip(zipFilePath: string): Promise<any>;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import archiver from 'archiver';
|
|
3
|
-
import unzipper from 'unzipper';
|
|
4
|
-
/**
|
|
5
|
-
* Creates a ZIP archive from a directory and writes it to a file.
|
|
6
|
-
*
|
|
7
|
-
* All files and subdirectories within `targetDir` are added to the archive
|
|
8
|
-
* at the root level (no wrapping directory).
|
|
9
|
-
* @param outputfilePath - The file path where the ZIP archive will be written.
|
|
10
|
-
* @param targetDir - The directory whose contents will be compressed into the ZIP archive.
|
|
11
|
-
* @returns A promise that resolves when the ZIP file has been fully written,
|
|
12
|
-
* or rejects if the write stream encounters an error.
|
|
13
|
-
*/
|
|
14
|
-
export async function zip(outputfilePath, targetDir) {
|
|
15
|
-
const output = fs.createWriteStream(outputfilePath);
|
|
16
|
-
const archive = archiver('zip');
|
|
17
|
-
archive.pipe(output);
|
|
18
|
-
archive.directory(targetDir, false);
|
|
19
|
-
await archive.finalize();
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
output.on('finish', () => resolve());
|
|
22
|
-
output.on('error', () => reject(`Failed to save file "${outputfilePath}" from "${targetDir}"`));
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Extracts a ZIP archive to a target directory.
|
|
27
|
-
* @param zipFilePath - The path to the ZIP file to extract.
|
|
28
|
-
* @param targetDir - The directory where the ZIP contents will be extracted to.
|
|
29
|
-
* @returns A promise that resolves when extraction is complete,
|
|
30
|
-
* or rejects if an error occurs during extraction.
|
|
31
|
-
*/
|
|
32
|
-
export async function unzip(zipFilePath, targetDir) {
|
|
33
|
-
const extract = fs.createReadStream(zipFilePath).pipe(unzipper.Extract({
|
|
34
|
-
path: targetDir,
|
|
35
|
-
}));
|
|
36
|
-
return new Promise((resolve, reject) => {
|
|
37
|
-
extract.on('finish', () => resolve());
|
|
38
|
-
extract.on('error', (err) => reject(err));
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Opens a ZIP file and returns its directory listing without extracting.
|
|
43
|
-
*
|
|
44
|
-
* This is useful for inspecting the contents of a ZIP archive
|
|
45
|
-
* before performing a full extraction.
|
|
46
|
-
* @param zipFilePath - The path to the ZIP file to open and inspect.
|
|
47
|
-
* @returns A directory object representing the ZIP archive contents,
|
|
48
|
-
* which can be used to list or selectively extract entries.
|
|
49
|
-
*/
|
|
50
|
-
export async function extractZip(zipFilePath) {
|
|
51
|
-
const directory = await unzipper.Open.file(zipFilePath);
|
|
52
|
-
return directory;
|
|
53
|
-
}
|
package/lib/archive/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export * from './archive-accessor.js';
|
|
2
|
-
export type { Redirect, Referrer, Anchor, StaticPageData } from './page.js';
|
|
3
|
-
export { default as Page } from './page.js';
|
|
4
|
-
export { default as Resource } from './resource.js';
|
|
5
|
-
export * from './types.js';
|
|
6
|
-
export { default } from './archive.js';
|
package/lib/archive/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Archive storage and retrieval layer for Nitpicker crawl data.
|
|
2
|
-
//
|
|
3
|
-
// This package provides the `Archive` class for creating, reading, and writing
|
|
4
|
-
// `.nitpicker` archive files that store crawl results in a SQLite database along with
|
|
5
|
-
// optional HTML snapshots. It also exports the `ArchiveAccessor` for read-only
|
|
6
|
-
// access, `Page` and `Resource` model classes, and all related types.
|
|
7
|
-
export * from './archive-accessor.js';
|
|
8
|
-
export { default as Page } from './page.js';
|
|
9
|
-
export { default as Resource } from './resource.js';
|
|
10
|
-
export * from './types.js';
|
|
11
|
-
export { default } from './archive.js';
|
package/lib/crawler/index.d.ts
DELETED
package/lib/crawler/index.js
DELETED
package/lib/crawler/network.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { ExURL } from '@d-zero/shared/parse-url';
|
|
2
|
-
import type { PageData } from '@nitpicker/beholder';
|
|
3
|
-
/**
|
|
4
|
-
* Clears the in-memory cache of HTTP request results.
|
|
5
|
-
* Should be called between crawl sessions to prevent memory leaks.
|
|
6
|
-
*/
|
|
7
|
-
export declare function clearDestinationCache(): void;
|
|
8
|
-
/**
|
|
9
|
-
* Fetches the destination metadata for a URL using an HTTP HEAD request (or GET as fallback).
|
|
10
|
-
*
|
|
11
|
-
* Results are cached in memory so that repeated calls for the same URL
|
|
12
|
-
* (without hash) return immediately. The request races against a 10-second
|
|
13
|
-
* timeout; if the server does not respond in time, a {@link NetTimeoutError} is thrown.
|
|
14
|
-
*
|
|
15
|
-
* If the server returns 405 (Method Not Allowed), 501 (Not Implemented), or 503
|
|
16
|
-
* (Service Unavailable) for a HEAD request, the function automatically retries with GET.
|
|
17
|
-
* @param url - The extended URL to fetch.
|
|
18
|
-
* @param isExternal - Whether the URL is external to the crawl scope.
|
|
19
|
-
* @param method - The HTTP method to use. Defaults to `"HEAD"`.
|
|
20
|
-
* @param options - Additional options.
|
|
21
|
-
* @param options.titleBytesLimit - When set, forces a GET request and reads up to this many
|
|
22
|
-
* bytes from the response body to extract an HTML `<title>` tag. The connection is
|
|
23
|
-
* destroyed as soon as the limit is reached or a title is found.
|
|
24
|
-
* @returns The page metadata obtained from the HTTP response.
|
|
25
|
-
* @throws {NetTimeoutError} If the request exceeds the 10-second timeout.
|
|
26
|
-
* @throws {Error} If the HTTP request fails for any other reason.
|
|
27
|
-
*/
|
|
28
|
-
export declare function fetchDestination(url: ExURL, isExternal: boolean, method?: string, options?: {
|
|
29
|
-
titleBytesLimit?: number;
|
|
30
|
-
}): Promise<PageData>;
|