@scrapeatlas/cli 0.4.0 → 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/catalog.json +41424 -11498
- package/package.json +1 -1
- package/src/http.mjs +4 -2
- package/src/route-path.d.mts +5 -0
- package/src/route-path.mjs +42 -0
package/package.json
CHANGED
package/src/http.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { routeInput } from './route-path.mjs';
|
|
2
3
|
|
|
3
4
|
const { version } = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
4
5
|
|
|
@@ -37,9 +38,10 @@ export function origin(value) {
|
|
|
37
38
|
return url.origin;
|
|
38
39
|
}
|
|
39
40
|
export async function request(base, key, operation, input, timeout) {
|
|
40
|
-
const
|
|
41
|
+
const route = routeInput(operation.path, input);
|
|
42
|
+
const url = new URL(route.path, base);
|
|
41
43
|
if (operation.method === 'GET')
|
|
42
|
-
for (const [name, value] of Object.entries(
|
|
44
|
+
for (const [name, value] of Object.entries(route.query)) {
|
|
43
45
|
url.searchParams.set(name, typeof value === 'object' ? JSON.stringify(value) : String(value));
|
|
44
46
|
}
|
|
45
47
|
const controller = new AbortController();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Pure route-template handling shared by CLI, MCP, gateway and request examples.
|
|
2
|
+
export function routeInput(template, input = {}) {
|
|
3
|
+
const query = { ...input };
|
|
4
|
+
const path = template.replace(/\{([a-z][a-zA-Z0-9]*)\}/g, (_, name) => {
|
|
5
|
+
const value = input[name];
|
|
6
|
+
if (
|
|
7
|
+
typeof value !== 'string' ||
|
|
8
|
+
!value ||
|
|
9
|
+
/[\/\\\u0000-\u001f\u007f]/.test(value) ||
|
|
10
|
+
value === '.' ||
|
|
11
|
+
value === '..'
|
|
12
|
+
)
|
|
13
|
+
throw new Error('Invalid route parameter');
|
|
14
|
+
delete query[name];
|
|
15
|
+
return encodeURIComponent(value);
|
|
16
|
+
});
|
|
17
|
+
return { path, query };
|
|
18
|
+
}
|
|
19
|
+
export function matchRoutePath(template, path) {
|
|
20
|
+
const expected = template.split('/'),
|
|
21
|
+
actual = path.split('/');
|
|
22
|
+
if (actual.length !== expected.length) return null;
|
|
23
|
+
const values = {};
|
|
24
|
+
for (let i = 0; i < expected.length; i++) {
|
|
25
|
+
const match = /^\{([a-z][a-zA-Z0-9]*)\}$/.exec(expected[i]);
|
|
26
|
+
if (!match) {
|
|
27
|
+
if (expected[i] !== actual[i]) return null;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
values[match[1]] = decodeURIComponent(actual[i]);
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
routeInput(template, values);
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return values;
|
|
42
|
+
}
|