@tenphi/akno-core 0.2.0 → 0.4.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/README.md +4 -2
- package/config/default.jsonc +38 -15
- package/dist/config/load.d.ts +5 -2
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +43 -12
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +27 -3
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +39 -4
- package/dist/config/schema.js.map +1 -1
- package/dist/config/write-setup.d.ts +2 -0
- package/dist/config/write-setup.d.ts.map +1 -1
- package/dist/config/write-setup.js +7 -3
- package/dist/config/write-setup.js.map +1 -1
- package/dist/doctor.d.ts +15 -5
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +18 -0
- package/dist/doctor.js.map +1 -1
- package/dist/index/indexer.d.ts +12 -6
- package/dist/index/indexer.d.ts.map +1 -1
- package/dist/index/indexer.js +41 -24
- package/dist/index/indexer.js.map +1 -1
- package/dist/ingest/extract.d.ts +14 -4
- package/dist/ingest/extract.d.ts.map +1 -1
- package/dist/ingest/extract.js +142 -26
- package/dist/ingest/extract.js.map +1 -1
- package/dist/ingest/extractor-contract.d.ts +63 -0
- package/dist/ingest/extractor-contract.d.ts.map +1 -0
- package/dist/ingest/extractor-contract.js +26 -0
- package/dist/ingest/extractor-contract.js.map +1 -0
- package/dist/ingest/fetch.d.ts +16 -13
- package/dist/ingest/fetch.d.ts.map +1 -1
- package/dist/ingest/fetch.js +176 -52
- package/dist/ingest/fetch.js.map +1 -1
- package/dist/ingest/linux-extractor.d.ts +32 -0
- package/dist/ingest/linux-extractor.d.ts.map +1 -0
- package/dist/ingest/linux-extractor.js +344 -0
- package/dist/ingest/linux-extractor.js.map +1 -0
- package/dist/kb/frontmatter.d.ts +15 -0
- package/dist/kb/frontmatter.d.ts.map +1 -1
- package/dist/kb/frontmatter.js +105 -9
- package/dist/kb/frontmatter.js.map +1 -1
- package/dist/maintenance/adopt.d.ts.map +1 -1
- package/dist/maintenance/adopt.js +2 -1
- package/dist/maintenance/adopt.js.map +1 -1
- package/dist/maintenance/curate.js +3 -3
- package/dist/maintenance/curate.js.map +1 -1
- package/dist/maintenance/dream.d.ts.map +1 -1
- package/dist/maintenance/dream.js +27 -17
- package/dist/maintenance/dream.js.map +1 -1
- package/dist/open.d.ts +1 -1
- package/dist/open.d.ts.map +1 -1
- package/dist/ops/ingest.d.ts.map +1 -1
- package/dist/ops/ingest.js +11 -5
- package/dist/ops/ingest.js.map +1 -1
- package/dist/ops/remember.d.ts.map +1 -1
- package/dist/ops/remember.js +2 -1
- package/dist/ops/remember.js.map +1 -1
- package/dist/ops/retain.js +2 -2
- package/dist/ops/retain.js.map +1 -1
- package/dist/ops/undo.d.ts +1 -1
- package/dist/ops/undo.js +1 -1
- package/dist/ops/write.d.ts.map +1 -1
- package/dist/ops/write.js +11 -7
- package/dist/ops/write.js.map +1 -1
- package/dist/store/db.d.ts.map +1 -1
- package/dist/store/db.js +4 -1
- package/dist/store/db.js.map +1 -1
- package/dist/store/migrations.d.ts +7 -6
- package/dist/store/migrations.d.ts.map +1 -1
- package/dist/store/migrations.js +16 -8
- package/dist/store/migrations.js.map +1 -1
- package/dist/watch/watcher.d.ts +3 -3
- package/dist/watch/watcher.js +5 -5
- package/dist/watch/watcher.js.map +1 -1
- package/dist/write/journal.d.ts +4 -8
- package/dist/write/journal.d.ts.map +1 -1
- package/dist/write/journal.js +215 -55
- package/dist/write/journal.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function selectDocumentExtractorBackend(platform, backends) {
|
|
2
|
+
if (platform === 'darwin')
|
|
3
|
+
return backends.macos;
|
|
4
|
+
if (platform === 'linux')
|
|
5
|
+
return backends.linux;
|
|
6
|
+
return unsupportedBackend(platform);
|
|
7
|
+
}
|
|
8
|
+
function unsupportedBackend(platform) {
|
|
9
|
+
return {
|
|
10
|
+
name: 'unsupported',
|
|
11
|
+
extract: async () => ({
|
|
12
|
+
text: '',
|
|
13
|
+
pages: null,
|
|
14
|
+
ocr: false,
|
|
15
|
+
confidence: null,
|
|
16
|
+
provenance: { backend: 'unsupported', tool: null },
|
|
17
|
+
text_from: 'none',
|
|
18
|
+
degradation: {
|
|
19
|
+
kind: 'unsupported-platform',
|
|
20
|
+
message: `document extraction is not supported on ${platform}`,
|
|
21
|
+
platform,
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=extractor-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor-contract.js","sourceRoot":"","sources":["../../src/ingest/extractor-contract.ts"],"names":[],"mappings":"AAyFA,MAAM,UAAU,8BAA8B,CAC5C,QAAgB,EAChB,QAA2B;IAE3B,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC;IACjD,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC;IAChD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACpB,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,KAAK;YACV,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE;YAClD,SAAS,EAAE,MAAM;YACjB,WAAW,EAAE;gBACX,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,2CAA2C,QAAQ,EAAE;gBAC9D,QAAQ;aACT;SACF,CAAC;KACH,CAAC;AACJ,CAAC"}
|
package/dist/ingest/fetch.d.ts
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `ingest` pulls documents from a file, a folder, or a URL. This is the URL.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* path on the machine through an interface that looks like it fetches the web, and
|
|
9
|
-
* `data:` would smuggle bytes past the size cap.
|
|
10
|
-
* - **Redirects are followed** by `fetch`, which caps the chain itself; a redirect is
|
|
11
|
-
* normal and an infinite one is already handled below us.
|
|
12
|
-
* - **The size cap applies to what arrives, not to what the server claims.** A
|
|
13
|
-
* `Content-Length` is a promise, and the stream is what actually lands on disk.
|
|
14
|
-
* - **The filename comes from the response, then the URL, then the content type.** A
|
|
15
|
-
* URL path is often `/download` or `/`, which says nothing — and a name adding nothing is
|
|
16
|
-
* exactly what naming-from-content replaces.
|
|
4
|
+
* A URL is an instruction to make a network connection, so validation is performed on
|
|
5
|
+
* resolved destinations rather than on spelling alone. Every DNS answer must be public,
|
|
6
|
+
* the request is pinned to one of those validated answers, and every redirect starts the
|
|
7
|
+
* same process again. That closes both redirect-to-private and DNS-rebinding paths.
|
|
17
8
|
*/
|
|
18
9
|
export interface Fetched {
|
|
19
10
|
/** A temp file. The caller ingests it and is responsible for cleaning up. */
|
|
@@ -24,12 +15,24 @@ export interface Fetched {
|
|
|
24
15
|
bytes: number;
|
|
25
16
|
finalUrl: string;
|
|
26
17
|
}
|
|
18
|
+
interface ResolvedAddress {
|
|
19
|
+
address: string;
|
|
20
|
+
family: 4 | 6;
|
|
21
|
+
}
|
|
27
22
|
export interface FetchOptions {
|
|
28
23
|
url: string;
|
|
29
24
|
maxBytes: number;
|
|
30
25
|
timeoutMs?: number;
|
|
26
|
+
/** Exact origins explicitly trusted to reach non-public destinations. */
|
|
27
|
+
trustedOrigins?: string[];
|
|
28
|
+
/** Test seam; production uses the operating system resolver. */
|
|
29
|
+
resolve?: (hostname: string) => Promise<ResolvedAddress[]>;
|
|
30
|
+
maxRedirects?: number;
|
|
31
31
|
}
|
|
32
32
|
export declare function fetchDocument(options: FetchOptions): Promise<Fetched>;
|
|
33
33
|
/** The temp directory a fetch created. Removed once the bytes have been stored. */
|
|
34
34
|
export declare function cleanupFetch(fetched: Fetched): Promise<void>;
|
|
35
|
+
/** Exposed for deterministic policy tests without making a network request. */
|
|
36
|
+
export declare function assertSafeUrlDestination(raw: string, options?: Pick<FetchOptions, 'trustedOrigins' | 'resolve'>): Promise<void>;
|
|
37
|
+
export {};
|
|
35
38
|
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/ingest/fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/ingest/fetch.ts"],"names":[],"mappings":"AASA;;;;;;;GAOG;AAEH,MAAM,WAAW,OAAO;IACtB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAKD,wBAAsB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAkE3E;AAED,mFAAmF;AACnF,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAElE;AAED,+EAA+E;AAC/E,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,SAAS,CAAM,GAC7D,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
package/dist/ingest/fetch.js
CHANGED
|
@@ -1,88 +1,222 @@
|
|
|
1
|
+
import dns from 'node:dns/promises';
|
|
2
|
+
import http, {} from 'node:http';
|
|
3
|
+
import https from 'node:https';
|
|
4
|
+
import { BlockList, isIP } from 'node:net';
|
|
1
5
|
import fsp from 'node:fs/promises';
|
|
2
6
|
import os from 'node:os';
|
|
3
7
|
import path from 'node:path';
|
|
4
8
|
import { AknoError } from '@tenphi/akno-protocol';
|
|
9
|
+
const DENIED_DESTINATIONS = deniedDestinations();
|
|
10
|
+
const REDIRECTS = new Set([301, 302, 303, 307, 308]);
|
|
5
11
|
export async function fetchDocument(options) {
|
|
6
|
-
const
|
|
12
|
+
const timeoutMs = options.timeoutMs ?? 60_000;
|
|
13
|
+
const trusted = new Set((options.trustedOrigins ?? []).map(normalizeTrustedOrigin));
|
|
14
|
+
const resolve = options.resolve ?? resolveHost;
|
|
15
|
+
let url = parseUrl(options.url);
|
|
16
|
+
let redirects = 0;
|
|
7
17
|
let response;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
throw new AknoError('unavailable', `${url.href} returned ${response.status} ${response.statusText}`);
|
|
18
|
+
while (true) {
|
|
19
|
+
const addresses = await permittedAddresses(url, trusted, resolve);
|
|
20
|
+
response = await request(url, addresses, timeoutMs);
|
|
21
|
+
const status = response.statusCode ?? 0;
|
|
22
|
+
if (!REDIRECTS.has(status))
|
|
23
|
+
break;
|
|
24
|
+
const location = header(response.headers, 'location');
|
|
25
|
+
response.resume();
|
|
26
|
+
if (!location)
|
|
27
|
+
throw new AknoError('unavailable', 'URL redirect returned no location');
|
|
28
|
+
if (redirects++ >= (options.maxRedirects ?? 5)) {
|
|
29
|
+
throw new AknoError('unavailable', 'URL redirect limit exceeded');
|
|
30
|
+
}
|
|
31
|
+
url = parseUrl(new URL(location, url).href);
|
|
23
32
|
}
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
const status = response.statusCode ?? 0;
|
|
34
|
+
if (status < 200 || status >= 300) {
|
|
35
|
+
response.resume();
|
|
36
|
+
throw new AknoError('unavailable', `URL returned ${status}${response.statusMessage ? ` ${response.statusMessage}` : ''}`);
|
|
26
37
|
}
|
|
27
|
-
const contentType = (response.headers
|
|
28
|
-
const originalName = filenameFor(response, url, contentType);
|
|
38
|
+
const contentType = (header(response.headers, 'content-type') ?? '').split(';')[0].trim() || null;
|
|
39
|
+
const originalName = filenameFor(response.headers, url, contentType);
|
|
29
40
|
const directory = await fsp.mkdtemp(path.join(os.tmpdir(), 'akno-fetch-'));
|
|
30
41
|
const target = path.join(directory, originalName);
|
|
31
|
-
const handle = await fsp.open(target, 'w');
|
|
32
42
|
let written = 0;
|
|
43
|
+
let handle = null;
|
|
33
44
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
handle = await fsp.open(target, 'w');
|
|
46
|
+
for await (const chunk of response) {
|
|
47
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
48
|
+
written += bytes.byteLength;
|
|
49
|
+
// Enforced against the bytes that actually arrive: Content-Length is only a claim.
|
|
38
50
|
if (written > options.maxBytes) {
|
|
39
|
-
|
|
40
|
-
await fsp.rm(directory, { recursive: true, force: true });
|
|
41
|
-
throw new AknoError('invalid', `${url.href} is larger than the configured limit of ${Math.round(options.maxBytes / 1_048_576)} MB`);
|
|
51
|
+
throw new AknoError('invalid', `download is larger than the configured limit of ${Math.round(options.maxBytes / 1_048_576)} MB`);
|
|
42
52
|
}
|
|
43
|
-
await handle.write(
|
|
53
|
+
await handle.write(bytes);
|
|
44
54
|
}
|
|
45
55
|
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
await fsp.rm(directory, { recursive: true, force: true });
|
|
58
|
+
throw networkFailure(error);
|
|
59
|
+
}
|
|
46
60
|
finally {
|
|
47
|
-
|
|
61
|
+
if (handle)
|
|
62
|
+
await handle.close().catch(() => { });
|
|
48
63
|
}
|
|
49
64
|
if (written === 0) {
|
|
50
65
|
await fsp.rm(directory, { recursive: true, force: true });
|
|
51
|
-
throw new AknoError('unavailable',
|
|
66
|
+
throw new AknoError('unavailable', 'URL returned an empty body');
|
|
52
67
|
}
|
|
53
|
-
return { path: target, originalName, contentType, bytes: written, finalUrl:
|
|
68
|
+
return { path: target, originalName, contentType, bytes: written, finalUrl: url.href };
|
|
54
69
|
}
|
|
55
70
|
/** The temp directory a fetch created. Removed once the bytes have been stored. */
|
|
56
71
|
export async function cleanupFetch(fetched) {
|
|
57
72
|
await fsp.rm(path.dirname(fetched.path), { recursive: true, force: true });
|
|
58
73
|
}
|
|
74
|
+
/** Exposed for deterministic policy tests without making a network request. */
|
|
75
|
+
export async function assertSafeUrlDestination(raw, options = {}) {
|
|
76
|
+
const url = parseUrl(raw);
|
|
77
|
+
const trusted = new Set((options.trustedOrigins ?? []).map(normalizeTrustedOrigin));
|
|
78
|
+
await permittedAddresses(url, trusted, options.resolve ?? resolveHost);
|
|
79
|
+
}
|
|
80
|
+
async function permittedAddresses(url, trusted, resolve) {
|
|
81
|
+
const hostname = normalizeHost(url.hostname);
|
|
82
|
+
let addresses;
|
|
83
|
+
try {
|
|
84
|
+
addresses = isIP(hostname)
|
|
85
|
+
? [{ address: hostname, family: isIP(hostname) }]
|
|
86
|
+
: await resolve(hostname);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
throw new AknoError('unavailable', 'could not resolve URL host');
|
|
90
|
+
}
|
|
91
|
+
if (addresses.length === 0)
|
|
92
|
+
throw new AknoError('unavailable', 'URL host resolved to no addresses');
|
|
93
|
+
if (!trusted.has(url.origin) && addresses.some((entry) => !isPublicAddress(entry))) {
|
|
94
|
+
throw new AknoError('forbidden', 'URL destination is not allowed by network policy', {
|
|
95
|
+
reason: 'network_destination_denied',
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return addresses;
|
|
99
|
+
}
|
|
100
|
+
async function resolveHost(hostname) {
|
|
101
|
+
const answers = await dns.lookup(hostname, { all: true, verbatim: true });
|
|
102
|
+
return answers.map((answer) => ({ address: answer.address, family: answer.family }));
|
|
103
|
+
}
|
|
104
|
+
function isPublicAddress(entry) {
|
|
105
|
+
return !DENIED_DESTINATIONS.check(entry.address, entry.family === 4 ? 'ipv4' : 'ipv6');
|
|
106
|
+
}
|
|
107
|
+
function deniedDestinations() {
|
|
108
|
+
const list = new BlockList();
|
|
109
|
+
for (const [network, prefix] of [
|
|
110
|
+
['0.0.0.0', 8],
|
|
111
|
+
['10.0.0.0', 8],
|
|
112
|
+
['100.64.0.0', 10],
|
|
113
|
+
['127.0.0.0', 8],
|
|
114
|
+
['169.254.0.0', 16],
|
|
115
|
+
['172.16.0.0', 12],
|
|
116
|
+
['192.0.0.0', 24],
|
|
117
|
+
['192.0.2.0', 24],
|
|
118
|
+
['192.168.0.0', 16],
|
|
119
|
+
['192.88.99.0', 24],
|
|
120
|
+
['198.18.0.0', 15],
|
|
121
|
+
['198.51.100.0', 24],
|
|
122
|
+
['203.0.113.0', 24],
|
|
123
|
+
['224.0.0.0', 4],
|
|
124
|
+
['240.0.0.0', 4],
|
|
125
|
+
]) {
|
|
126
|
+
list.addSubnet(network, prefix, 'ipv4');
|
|
127
|
+
}
|
|
128
|
+
for (const [network, prefix] of [
|
|
129
|
+
['::', 128],
|
|
130
|
+
['::1', 128],
|
|
131
|
+
['::', 96],
|
|
132
|
+
['::ffff:0:0', 96],
|
|
133
|
+
['::ffff:0:0:0', 96],
|
|
134
|
+
['64:ff9b::', 96],
|
|
135
|
+
['64:ff9b:1::', 48],
|
|
136
|
+
['100::', 64],
|
|
137
|
+
['100:0:0:1::', 64],
|
|
138
|
+
['fc00::', 7],
|
|
139
|
+
['fe80::', 10],
|
|
140
|
+
['fec0::', 10],
|
|
141
|
+
['ff00::', 8],
|
|
142
|
+
['2001::', 23],
|
|
143
|
+
['2001:db8::', 32],
|
|
144
|
+
['2002::', 16],
|
|
145
|
+
['3fff::', 20],
|
|
146
|
+
['5f00::', 16],
|
|
147
|
+
]) {
|
|
148
|
+
list.addSubnet(network, prefix, 'ipv6');
|
|
149
|
+
}
|
|
150
|
+
return list;
|
|
151
|
+
}
|
|
152
|
+
function request(url, addresses, timeoutMs) {
|
|
153
|
+
const transport = url.protocol === 'https:' ? https : http;
|
|
154
|
+
const lookup = (_hostname, lookupOptions, callback) => {
|
|
155
|
+
if (lookupOptions.all) {
|
|
156
|
+
callback(null, addresses);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const selected = addresses[0];
|
|
160
|
+
callback(null, selected.address, selected.family);
|
|
161
|
+
};
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
const req = transport.get(url, {
|
|
164
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
165
|
+
headers: { accept: '*/*' },
|
|
166
|
+
lookup,
|
|
167
|
+
}, resolve);
|
|
168
|
+
req.on('error', (error) => reject(networkFailure(error)));
|
|
169
|
+
});
|
|
170
|
+
}
|
|
59
171
|
function parseUrl(raw) {
|
|
60
172
|
let url;
|
|
61
173
|
try {
|
|
62
174
|
url = new URL(raw);
|
|
63
175
|
}
|
|
64
176
|
catch {
|
|
65
|
-
throw new AknoError('invalid',
|
|
177
|
+
throw new AknoError('invalid', 'not a usable URL');
|
|
66
178
|
}
|
|
67
179
|
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
68
180
|
throw new AknoError('invalid', `only http and https URLs are fetched, not ${url.protocol} — pass a local path instead`);
|
|
69
181
|
}
|
|
182
|
+
if (url.username || url.password) {
|
|
183
|
+
throw new AknoError('invalid', 'credentials are not allowed in an ingest URL');
|
|
184
|
+
}
|
|
70
185
|
return url;
|
|
71
186
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
187
|
+
function normalizeHost(value) {
|
|
188
|
+
return value
|
|
189
|
+
.replace(/^\[|\]$/g, '')
|
|
190
|
+
.replace(/\.$/, '')
|
|
191
|
+
.toLowerCase();
|
|
192
|
+
}
|
|
193
|
+
function normalizeTrustedOrigin(value) {
|
|
194
|
+
const url = parseUrl(value);
|
|
195
|
+
if (url.pathname !== '/' || url.search || url.hash) {
|
|
196
|
+
throw new AknoError('invalid', 'a trusted URL origin may contain only scheme, host, and port');
|
|
197
|
+
}
|
|
198
|
+
return url.origin;
|
|
199
|
+
}
|
|
200
|
+
function networkFailure(error) {
|
|
201
|
+
if (error instanceof AknoError)
|
|
202
|
+
return error;
|
|
203
|
+
const name = error instanceof Error ? error.name : '';
|
|
204
|
+
return new AknoError('unavailable', name === 'AbortError' || name === 'TimeoutError' ? 'fetching URL timed out' : 'could not fetch URL');
|
|
205
|
+
}
|
|
206
|
+
function header(headers, name) {
|
|
207
|
+
const value = headers[name];
|
|
208
|
+
if (Array.isArray(value))
|
|
209
|
+
return value[0] ?? null;
|
|
210
|
+
return value ?? null;
|
|
211
|
+
}
|
|
212
|
+
/** Content-Disposition, then URL path, then an extension guessed from content type. */
|
|
213
|
+
function filenameFor(headers, url, contentType) {
|
|
214
|
+
const disposition = header(headers, 'content-disposition');
|
|
79
215
|
const candidates = [];
|
|
80
216
|
if (disposition) {
|
|
81
217
|
const star = /filename\*=(?:UTF-8'')?([^;]+)/i.exec(disposition);
|
|
82
218
|
const plain = /filename="?([^";]+)"?/i.exec(disposition);
|
|
83
219
|
const raw = star?.[1] ?? plain?.[1];
|
|
84
|
-
// `path.basename` is what stops `../../../etc/passwd` being a path: a server chooses
|
|
85
|
-
// this header, so it is untrusted input that becomes a filename.
|
|
86
220
|
if (raw)
|
|
87
221
|
candidates.push(sanitize(path.basename(safeDecode(raw.trim()))));
|
|
88
222
|
}
|
|
@@ -91,18 +225,10 @@ function filenameFor(response, url, contentType) {
|
|
|
91
225
|
for (const candidate of candidates) {
|
|
92
226
|
if (candidate.length === 0 || candidate === '.' || candidate === '..')
|
|
93
227
|
continue;
|
|
94
|
-
// The extractor dispatches on the extension, so a name without one is unusable even
|
|
95
|
-
// though it reads fine. Servers send `filename="report"` often enough that guessing
|
|
96
|
-
// from the content type is the difference between working and skipping.
|
|
97
228
|
return path.extname(candidate) ? candidate : `${candidate}${extension}`;
|
|
98
229
|
}
|
|
99
230
|
return `download${extension}`;
|
|
100
231
|
}
|
|
101
|
-
/**
|
|
102
|
-
* A server chooses these bytes, so they are untrusted input on their way to becoming a
|
|
103
|
-
* filename: separators and control characters are dropped. Spaces survive, because a
|
|
104
|
-
* filename with spaces is ordinary and the rename handles presentation anyway.
|
|
105
|
-
*/
|
|
106
232
|
function sanitize(name) {
|
|
107
233
|
return [...name]
|
|
108
234
|
.filter((char) => char !== '/' && char !== '\\' && char.codePointAt(0) >= 0x20)
|
|
@@ -135,8 +261,6 @@ function extensionFor(contentType) {
|
|
|
135
261
|
'application/msword': '.doc',
|
|
136
262
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
|
|
137
263
|
};
|
|
138
|
-
// No extension at all is honest: the extractor dispatches on it and will say it has
|
|
139
|
-
// none, which is better than claiming `.bin` and looking like a decision.
|
|
140
264
|
return contentType ? (table[contentType] ?? '') : '';
|
|
141
265
|
}
|
|
142
266
|
//# sourceMappingURL=fetch.js.map
|
package/dist/ingest/fetch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/ingest/fetch.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/ingest/fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DocumentExtractorBackend } from './extractor-contract.ts';
|
|
2
|
+
type LinuxExecuteFile = (command: string, args: string[], options: {
|
|
3
|
+
maxBuffer: number;
|
|
4
|
+
timeout: number;
|
|
5
|
+
killSignal: NodeJS.Signals;
|
|
6
|
+
}) => Promise<{
|
|
7
|
+
stdout: string;
|
|
8
|
+
stderr: string;
|
|
9
|
+
}>;
|
|
10
|
+
export interface LinuxCommandRunner {
|
|
11
|
+
available(command: string): Promise<boolean>;
|
|
12
|
+
makeTempDir(): Promise<string>;
|
|
13
|
+
readText(file: string): Promise<string>;
|
|
14
|
+
removeTempDir(directory: string): Promise<void>;
|
|
15
|
+
run(command: string, args: string[]): Promise<{
|
|
16
|
+
stdout: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createNodeLinuxCommandRunner(execute?: LinuxExecuteFile): LinuxCommandRunner;
|
|
20
|
+
export interface LinuxExtractionCapabilities {
|
|
21
|
+
backend: 'linux-native';
|
|
22
|
+
libreoffice: boolean;
|
|
23
|
+
pdfinfo: boolean;
|
|
24
|
+
pdftotext: boolean;
|
|
25
|
+
pdftoppm: boolean;
|
|
26
|
+
tesseract: boolean;
|
|
27
|
+
note: string | null;
|
|
28
|
+
}
|
|
29
|
+
export declare function linuxExtractionCapabilities(commands: LinuxCommandRunner): Promise<LinuxExtractionCapabilities>;
|
|
30
|
+
export declare function createLinuxDocumentExtractor(commands: LinuxCommandRunner): DocumentExtractorBackend;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=linux-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linux-extractor.d.ts","sourceRoot":"","sources":["../../src/ingest/linux-extractor.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAOjC,KAAK,gBAAgB,GAAG,CACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAA;CAAE,KACxE,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAOjD,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAED,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,gBAA8B,GAAG,kBAAkB,CAexG;AAkBD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,2BAA2B,CAAC,CAgBtC;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,kBAAkB,GAAG,wBAAwB,CAcnG"}
|