single-file-cli 2.1.0 → 2.1.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/compile.sh +5 -6
- package/deno.json +3 -3
- package/deno.lock +14 -14
- package/lib/browser.js +55 -6
- package/lib/cdp-client-util.js +2 -1
- package/lib/cdp-client.js +53 -12
- package/lib/deno-polyfill.js +19 -2
- package/lib/version.js +1 -1
- package/options.js +192 -94
- package/package.json +5 -5
- package/single-file-cli-api.js +41 -20
- package/single-file-launcher.js +5 -93
- package/test/e2e/crawl.test.js +7 -5
- package/test/e2e/errors-file.test.js +31 -0
- package/test/e2e/frame-gate.test.js +5 -3
- package/test/e2e/output-json.test.js +11 -6
- package/test/e2e/timeouts.test.js +70 -0
- package/test/e2e/urls-file.test.js +37 -0
- package/test/unit/cli-usage.test.js +56 -0
- package/test/unit/options.test.js +136 -0
- package/test/unit/write-file.test.js +37 -0
package/compile.sh
CHANGED
|
@@ -9,15 +9,14 @@ trap 'rm -rf "$stage_dir"' EXIT
|
|
|
9
9
|
cp ./single-file ./single-file-launcher.js ./single-file-cli-api.js ./options.js ./deno.json "$stage_dir"
|
|
10
10
|
cp -R ./lib "$stage_dir/lib"
|
|
11
11
|
cp -R ./resources "$stage_dir/resources"
|
|
12
|
-
jq 'del(.dependencies, .devDependencies)' ./package.json > "$stage_dir/package.json"
|
|
13
12
|
mkdir -p "$dist_dir"
|
|
14
13
|
cd "$stage_dir"
|
|
15
14
|
|
|
16
|
-
deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-aarch64-apple-darwin" --target=aarch64-apple-darwin ./single-file
|
|
17
|
-
deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-x86_64-apple-darwin" --target=x86_64-apple-darwin ./single-file
|
|
18
|
-
deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-x86_64-linux" --target=x86_64-unknown-linux-gnu ./single-file
|
|
19
|
-
deno compile --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-aarch64-linux" --target=aarch64-unknown-linux-gnu ./single-file
|
|
20
|
-
deno compile --allow-all --ext=js --output="$dist_dir/single-file.exe" --target=x86_64-pc-windows-msvc --icon=./resources/single-file.ico ./single-file
|
|
15
|
+
deno compile --minimum-dependency-age=0 --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-aarch64-apple-darwin" --target=aarch64-apple-darwin ./single-file
|
|
16
|
+
deno compile --minimum-dependency-age=0 --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-x86_64-apple-darwin" --target=x86_64-apple-darwin ./single-file
|
|
17
|
+
deno compile --minimum-dependency-age=0 --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-x86_64-linux" --target=x86_64-unknown-linux-gnu ./single-file
|
|
18
|
+
deno compile --minimum-dependency-age=0 --allow-read --allow-write --allow-net --allow-env --allow-run --ext=js --output="$dist_dir/single-file-aarch64-linux" --target=aarch64-unknown-linux-gnu ./single-file
|
|
19
|
+
deno compile --minimum-dependency-age=0 --allow-all --ext=js --output="$dist_dir/single-file.exe" --target=x86_64-pc-windows-msvc --icon=./resources/single-file.ico ./single-file
|
|
21
20
|
|
|
22
21
|
cd - > /dev/null
|
|
23
22
|
|
package/deno.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@single-file/single-file-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "SingleFile CLI",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./single-file-cli-api.js"
|
|
7
7
|
},
|
|
8
8
|
"imports": {
|
|
9
|
-
"simple-cdp": "jsr:@simple-cdp/simple-cdp@^1.10.
|
|
10
|
-
"path": "jsr:@std/path@^1.1.
|
|
9
|
+
"simple-cdp": "jsr:@simple-cdp/simple-cdp@^1.10.1",
|
|
10
|
+
"path": "jsr:@std/path@^1.1.6"
|
|
11
11
|
}
|
|
12
12
|
}
|
package/deno.lock
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "5",
|
|
3
3
|
"specifiers": {
|
|
4
|
-
"jsr:@simple-cdp/simple-cdp@^1.10.
|
|
4
|
+
"jsr:@simple-cdp/simple-cdp@^1.10.1": "1.10.1",
|
|
5
5
|
"jsr:@std/internal@^1.0.14": "1.0.14",
|
|
6
|
-
"jsr:@std/path@^1.1.
|
|
7
|
-
"npm:@eslint/js@^9.39.
|
|
8
|
-
"npm:esbuild@~0.27.
|
|
6
|
+
"jsr:@std/path@^1.1.6": "1.1.6",
|
|
7
|
+
"npm:@eslint/js@^9.39.5": "9.39.5",
|
|
8
|
+
"npm:esbuild@~0.27.7": "0.27.7",
|
|
9
9
|
"npm:eslint@^10.8.1": "10.8.1",
|
|
10
|
-
"npm:simple-cdp@^1.10.
|
|
10
|
+
"npm:simple-cdp@^1.10.1": "1.10.1"
|
|
11
11
|
},
|
|
12
12
|
"jsr": {
|
|
13
|
-
"@simple-cdp/simple-cdp@1.10.
|
|
14
|
-
"integrity": "
|
|
13
|
+
"@simple-cdp/simple-cdp@1.10.1": {
|
|
14
|
+
"integrity": "33c686242e812a53d13ba7fcebd18ed81b4685fb02da37c2ee6ed9a5123f9b8c"
|
|
15
15
|
},
|
|
16
16
|
"@std/internal@1.0.14": {
|
|
17
17
|
"integrity": "291516b3d4c35024d6ffbc0a9df5bf4c64116e05b50012cf846710152d2ffdf7"
|
|
@@ -527,8 +527,8 @@
|
|
|
527
527
|
"shebang-regex@3.0.0": {
|
|
528
528
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
|
529
529
|
},
|
|
530
|
-
"simple-cdp@1.10.
|
|
531
|
-
"integrity": "sha512-
|
|
530
|
+
"simple-cdp@1.10.1": {
|
|
531
|
+
"integrity": "sha512-svGX76zc2MY2ErGAWGb9NWP9aF5XQgDyx00iqAGCgRi1qQd5MQjtBwuC7mcktliFH263gpHdnHicfsB+n7Vnyg=="
|
|
532
532
|
},
|
|
533
533
|
"type-check@0.4.0": {
|
|
534
534
|
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
|
|
@@ -558,15 +558,15 @@
|
|
|
558
558
|
},
|
|
559
559
|
"workspace": {
|
|
560
560
|
"dependencies": [
|
|
561
|
-
"jsr:@simple-cdp/simple-cdp@^1.10.
|
|
562
|
-
"jsr:@std/path@^1.1.
|
|
561
|
+
"jsr:@simple-cdp/simple-cdp@^1.10.1",
|
|
562
|
+
"jsr:@std/path@^1.1.6"
|
|
563
563
|
],
|
|
564
564
|
"packageJson": {
|
|
565
565
|
"dependencies": [
|
|
566
|
-
"npm:@eslint/js@^9.39.
|
|
567
|
-
"npm:esbuild@~0.27.
|
|
566
|
+
"npm:@eslint/js@^9.39.5",
|
|
567
|
+
"npm:esbuild@~0.27.7",
|
|
568
568
|
"npm:eslint@^10.8.1",
|
|
569
|
-
"npm:simple-cdp@^1.10.
|
|
569
|
+
"npm:simple-cdp@^1.10.1"
|
|
570
570
|
]
|
|
571
571
|
}
|
|
572
572
|
}
|
package/lib/browser.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Source.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
/* global fetch */
|
|
24
|
+
/* global fetch, setTimeout */
|
|
25
25
|
|
|
26
26
|
import { BROWSER_PATHS, BROWSER_ARGS } from "./constants.js";
|
|
27
27
|
import { Deno } from "./deno-polyfill.js";
|
|
@@ -29,10 +29,12 @@ import { Deno } from "./deno-polyfill.js";
|
|
|
29
29
|
const NULL_STD_CONFIG = "null";
|
|
30
30
|
const DEBUG_PORT_MIN = 9222;
|
|
31
31
|
const DEBUG_PORT_RANGE = 256;
|
|
32
|
+
const READY_TIMEOUT = 30000;
|
|
33
|
+
const READY_RETRY_DELAY = 250;
|
|
32
34
|
|
|
33
35
|
const { build, makeTempDir, Command, errors, remove } = Deno;
|
|
34
|
-
let child, profilePath;
|
|
35
|
-
export { launchBrowser, closeBrowser };
|
|
36
|
+
let child, profilePath, childExited;
|
|
37
|
+
export { launchBrowser, closeBrowser, browserExited };
|
|
36
38
|
|
|
37
39
|
async function launchBrowser(options = {}, indexPath = 0) {
|
|
38
40
|
const executablePath = options.executablePath || BROWSER_PATHS[build.os][indexPath];
|
|
@@ -78,15 +80,58 @@ async function launchBrowser(options = {}, indexPath = 0) {
|
|
|
78
80
|
} catch (error) {
|
|
79
81
|
await remove(profilePath, { recursive: true }).catch(() => { });
|
|
80
82
|
profilePath = undefined;
|
|
81
|
-
if (error instanceof errors.NotFound
|
|
82
|
-
|
|
83
|
+
if (error instanceof errors.NotFound) {
|
|
84
|
+
if (!options.executablePath && indexPath + 1 < BROWSER_PATHS[build.os].length) {
|
|
85
|
+
return launchBrowser(options, indexPath + 1);
|
|
86
|
+
}
|
|
87
|
+
throw new Error(options.executablePath ?
|
|
88
|
+
`The browser executable was not found at ${JSON.stringify(executablePath)}` :
|
|
89
|
+
"The browser executable was not found, use --browser-executable-path to set its location");
|
|
83
90
|
}
|
|
84
91
|
throw error;
|
|
85
92
|
}
|
|
86
93
|
child.ref();
|
|
94
|
+
childExited = false;
|
|
95
|
+
child.status.then(() => childExited = true);
|
|
96
|
+
try {
|
|
97
|
+
await waitUntilReady(debugPort);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
await closeBrowser();
|
|
100
|
+
if (options.singleProcess) {
|
|
101
|
+
console.warn("Warning: the browser exited when using --browser-single-process, retrying without it"); // eslint-disable-line no-console
|
|
102
|
+
return launchBrowser(Object.assign({}, options, { singleProcess: false }), indexPath);
|
|
103
|
+
}
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
87
106
|
return debugPort;
|
|
88
107
|
}
|
|
89
108
|
|
|
109
|
+
async function waitUntilReady(debugPort) {
|
|
110
|
+
const timeoutTime = Date.now() + READY_TIMEOUT;
|
|
111
|
+
while (!childExited && Date.now() < timeoutTime) {
|
|
112
|
+
try {
|
|
113
|
+
await fetch("http://localhost:" + debugPort + "/json/version");
|
|
114
|
+
return;
|
|
115
|
+
} catch {
|
|
116
|
+
await new Promise(resolve => setTimeout(resolve, READY_RETRY_DELAY));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
throw new Error(childExited ? "The browser exited unexpectedly" : "The browser is not responding");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function browserExited(maxDelay = 0) {
|
|
123
|
+
if (child === undefined) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
if (childExited || !maxDelay) {
|
|
127
|
+
return childExited;
|
|
128
|
+
}
|
|
129
|
+
return Promise.race([
|
|
130
|
+
child.status.then(() => true),
|
|
131
|
+
new Promise(resolve => setTimeout(() => resolve(childExited), maxDelay))
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
|
|
90
135
|
async function getDebugPort(port = getRandomDebugPort(), usedPorts = []) {
|
|
91
136
|
try {
|
|
92
137
|
await fetch("http://localhost:" + port + "/json/version");
|
|
@@ -111,7 +156,11 @@ function getRandomDebugPort() {
|
|
|
111
156
|
|
|
112
157
|
async function closeBrowser() {
|
|
113
158
|
if (child !== undefined) {
|
|
114
|
-
|
|
159
|
+
try {
|
|
160
|
+
child.kill();
|
|
161
|
+
} catch {
|
|
162
|
+
// ignored
|
|
163
|
+
}
|
|
115
164
|
await child.status;
|
|
116
165
|
child = undefined;
|
|
117
166
|
}
|
package/lib/cdp-client-util.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
/* global setTimeout, clearTimeout, fetch, URL, Headers */
|
|
25
25
|
|
|
26
|
+
import { Buffer } from "node:buffer";
|
|
26
27
|
import { Deno, isDeno, path } from "./deno-polyfill.js";
|
|
27
28
|
|
|
28
29
|
const ABORT_EVENT = "abort";
|
|
@@ -82,7 +83,7 @@ function waitForTimeout(abortSignal, maxDelay, errorMessage, errorCode) {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
function arrayBufferToBase64(arrayBuffer) {
|
|
85
|
-
return
|
|
86
|
+
return Buffer.from(arrayBuffer).toString("base64");
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
function getAlternativeUrl(url) {
|
package/lib/cdp-client.js
CHANGED
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
|
|
26
26
|
import {
|
|
27
27
|
launchBrowser,
|
|
28
|
-
closeBrowser
|
|
28
|
+
closeBrowser,
|
|
29
|
+
browserExited
|
|
29
30
|
} from "./browser.js";
|
|
30
31
|
import {
|
|
31
32
|
CDP,
|
|
@@ -57,6 +58,10 @@ const SET_SCREENSHOT_FUNCTION_NAME = "setScreenshot";
|
|
|
57
58
|
const SET_PDF_FUNCTION_NAME = "setPDF";
|
|
58
59
|
const SET_PAGE_DATA_FUNCTION_NAME = "setPageData";
|
|
59
60
|
const BINDING_CALLED_EVENT_TYPE = "bindingCalled";
|
|
61
|
+
const LOCALHOST = "http://localhost:";
|
|
62
|
+
const BROWSER_EXITED_MAX_DELAY = 2000;
|
|
63
|
+
|
|
64
|
+
let browserOptions, relaunchBrowserPromise;
|
|
60
65
|
|
|
61
66
|
export {
|
|
62
67
|
initialize,
|
|
@@ -68,8 +73,7 @@ async function initialize(singleFileOptions) {
|
|
|
68
73
|
if (singleFileOptions.browserServer) {
|
|
69
74
|
options.apiUrl = singleFileOptions.browserServer;
|
|
70
75
|
} else {
|
|
71
|
-
|
|
72
|
-
const browserOptions = {};
|
|
76
|
+
browserOptions = {};
|
|
73
77
|
browserOptions.args = singleFileOptions.browserArgs;
|
|
74
78
|
browserOptions.headless = singleFileOptions.browserHeadless;
|
|
75
79
|
browserOptions.executablePath = singleFileOptions.browserExecutablePath;
|
|
@@ -84,9 +88,21 @@ async function initialize(singleFileOptions) {
|
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
|
|
91
|
+
function relaunchBrowser() {
|
|
92
|
+
if (!relaunchBrowserPromise) {
|
|
93
|
+
console.warn("Warning: the browser exited when using --browser-single-process, retrying without it"); // eslint-disable-line no-console
|
|
94
|
+
relaunchBrowserPromise = (async () => {
|
|
95
|
+
await closeBrowser();
|
|
96
|
+
browserOptions.singleProcess = false;
|
|
97
|
+
options.apiUrl = LOCALHOST + (await launchBrowser(browserOptions));
|
|
98
|
+
})();
|
|
99
|
+
}
|
|
100
|
+
return relaunchBrowserPromise;
|
|
101
|
+
}
|
|
102
|
+
|
|
87
103
|
async function getPageData(options) {
|
|
88
104
|
const EMPTY_PAGE_URL = "about:blank";
|
|
89
|
-
const pageContext = { options, consoleMessages: [], debugMessages: [], httpInfo: {} };
|
|
105
|
+
const pageContext = { options, consoleMessages: [], debugMessages: [], httpInfo: {}, fetchAbortController: new AbortController() };
|
|
90
106
|
let targetInfo, cdp;
|
|
91
107
|
try {
|
|
92
108
|
logData(["Loading page", EMPTY_PAGE_URL], pageContext);
|
|
@@ -108,10 +124,14 @@ async function getPageData(options) {
|
|
|
108
124
|
if (shouldRetryWithFallback(error)) {
|
|
109
125
|
return await retryWithFallback();
|
|
110
126
|
}
|
|
127
|
+
if (await shouldRelaunchBrowser()) {
|
|
128
|
+
return await relaunchBrowserAndRetry();
|
|
129
|
+
}
|
|
111
130
|
attachDebugInfo(error, pageContext);
|
|
112
131
|
throw error;
|
|
113
132
|
} finally {
|
|
114
133
|
logData(["Closing page"], pageContext);
|
|
134
|
+
pageContext.fetchAbortController.abort();
|
|
115
135
|
await closeTarget();
|
|
116
136
|
logData(["Finishing"], pageContext);
|
|
117
137
|
}
|
|
@@ -131,9 +151,28 @@ async function getPageData(options) {
|
|
|
131
151
|
return await getPageData(options);
|
|
132
152
|
}
|
|
133
153
|
|
|
154
|
+
async function shouldRelaunchBrowser() {
|
|
155
|
+
return Boolean(browserOptions && browserOptions.singleProcess) && await browserExited(BROWSER_EXITED_MAX_DELAY);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function relaunchBrowserAndRetry() {
|
|
159
|
+
logData(["Relaunching the browser"], pageContext);
|
|
160
|
+
targetInfo = null;
|
|
161
|
+
if (cdp) {
|
|
162
|
+
cdp.reset();
|
|
163
|
+
cdp = null;
|
|
164
|
+
}
|
|
165
|
+
await relaunchBrowser();
|
|
166
|
+
return await getPageData(options);
|
|
167
|
+
}
|
|
168
|
+
|
|
134
169
|
async function closeTarget() {
|
|
135
170
|
if (targetInfo && !options.browserDebug) {
|
|
136
|
-
|
|
171
|
+
try {
|
|
172
|
+
await CDP.closeTarget(targetInfo.id);
|
|
173
|
+
} catch {
|
|
174
|
+
// ignored
|
|
175
|
+
}
|
|
137
176
|
targetInfo = null;
|
|
138
177
|
}
|
|
139
178
|
// the connection is closed even when the target is left open for
|
|
@@ -416,14 +455,16 @@ async function loadPage({ Page, Runtime }, { options, debugMessages }) {
|
|
|
416
455
|
]),
|
|
417
456
|
waitForTimeout(loadTimeoutAbortSignal, options.browserLoadMaxTime, LOAD_TIMEOUT_ERROR_MESSAGE, LOAD_TIMEOUT_ERROR)
|
|
418
457
|
]);
|
|
458
|
+
// only called when the page loaded, these calls can hang forever on an
|
|
459
|
+
// unresponsive page and would mask the load timeout error
|
|
460
|
+
await Page.setLifecycleEventsEnabled({ enabled: false });
|
|
461
|
+
await Runtime.disable();
|
|
462
|
+
await Page.disable();
|
|
419
463
|
return contextId;
|
|
420
464
|
} finally {
|
|
421
465
|
if (!loadTimeoutAbortSignal.aborted) {
|
|
422
466
|
loadTimeoutAbortController.abort();
|
|
423
467
|
}
|
|
424
|
-
await Page.setLifecycleEventsEnabled({ enabled: false });
|
|
425
|
-
await Runtime.disable();
|
|
426
|
-
await Page.disable();
|
|
427
468
|
}
|
|
428
469
|
}
|
|
429
470
|
|
|
@@ -533,7 +574,7 @@ function setupPageDataCapture({ Runtime }, _contextId, { options, debugMessages
|
|
|
533
574
|
});
|
|
534
575
|
}
|
|
535
576
|
|
|
536
|
-
async function setupBindings({ Page, Runtime }, contextId, { options, debugMessages }) {
|
|
577
|
+
async function setupBindings({ Page, Runtime }, contextId, { options, debugMessages, fetchAbortController }) {
|
|
537
578
|
await Runtime.addBinding({ name: SET_PAGE_DATA_FUNCTION_NAME, executionContextId: contextId });
|
|
538
579
|
if (options.embedScreenshot && options.compressContent) {
|
|
539
580
|
await setupScreenshotCapture({ Page, Runtime }, contextId, { options, debugMessages });
|
|
@@ -544,7 +585,7 @@ async function setupBindings({ Page, Runtime }, contextId, { options, debugMessa
|
|
|
544
585
|
await Runtime.addBinding({ name: FETCH_FUNCTION_NAME, executionContextId: contextId });
|
|
545
586
|
Runtime.addEventListener(BINDING_CALLED_EVENT_TYPE, ignoringErrors(async ({ params }) => {
|
|
546
587
|
if (params.name === FETCH_FUNCTION_NAME) {
|
|
547
|
-
await handleFetchRequest({ Runtime }, params, contextId, { options, debugMessages });
|
|
588
|
+
await handleFetchRequest({ Runtime }, params, contextId, { options, debugMessages, fetchAbortController });
|
|
548
589
|
}
|
|
549
590
|
}, { options, debugMessages }));
|
|
550
591
|
}
|
|
@@ -607,12 +648,12 @@ async function setupPdfCapture({ Page, Runtime }, contextId, { options, debugMes
|
|
|
607
648
|
}
|
|
608
649
|
}
|
|
609
650
|
|
|
610
|
-
async function handleFetchRequest({ Runtime }, params, contextId, { options, debugMessages }) {
|
|
651
|
+
async function handleFetchRequest({ Runtime }, params, contextId, { options, debugMessages, fetchAbortController }) {
|
|
611
652
|
const { payload } = params;
|
|
612
653
|
const { requestId, url, options: fetchOptions } = JSON.parse(payload);
|
|
613
654
|
logData(["Fetching URL", url], { options, debugMessages });
|
|
614
655
|
try {
|
|
615
|
-
const response = await fetch(url, fetchOptions);
|
|
656
|
+
const response = await fetch(url, Object.assign({}, fetchOptions, { signal: fetchAbortController.signal }));
|
|
616
657
|
const arrayBuffer = await response.arrayBuffer();
|
|
617
658
|
const base64Data = arrayBufferToBase64(arrayBuffer);
|
|
618
659
|
const result = {
|
package/lib/deno-polyfill.js
CHANGED
|
@@ -53,6 +53,12 @@ const errors = {
|
|
|
53
53
|
super(message);
|
|
54
54
|
this.name = "NotFound";
|
|
55
55
|
}
|
|
56
|
+
},
|
|
57
|
+
AlreadyExists: DENO_RUNTIME_DETECTED ? Deno.errors.AlreadyExists : class AlreadyExists extends Error {
|
|
58
|
+
constructor(message) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = "AlreadyExists";
|
|
61
|
+
}
|
|
56
62
|
}
|
|
57
63
|
};
|
|
58
64
|
|
|
@@ -157,7 +163,7 @@ async function writeTextFile(path, data, options = {}) {
|
|
|
157
163
|
if (options.append) {
|
|
158
164
|
return fsPromise.appendFile(path, data, options);
|
|
159
165
|
} else {
|
|
160
|
-
return fsPromise
|
|
166
|
+
return nodeWriteFile(fsPromise, path, data, options);
|
|
161
167
|
}
|
|
162
168
|
}
|
|
163
169
|
}
|
|
@@ -167,7 +173,18 @@ async function writeFile(path, data, options = {}) {
|
|
|
167
173
|
return Deno.writeFile(path, data, options);
|
|
168
174
|
} else {
|
|
169
175
|
const fsPromise = await import(NODE_MODULES["fs"]);
|
|
170
|
-
return fsPromise
|
|
176
|
+
return nodeWriteFile(fsPromise, path, data, options);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function nodeWriteFile(fsPromise, path, data, options) {
|
|
181
|
+
if (options.createNew) {
|
|
182
|
+
options.flag = "wx";
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
return await fsPromise.writeFile(path, data, options);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
throw error.code == "EEXIST" ? new errors.AlreadyExists(error.message) : error;
|
|
171
188
|
}
|
|
172
189
|
}
|
|
173
190
|
|
package/lib/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "2.1.
|
|
1
|
+
export const version = "2.1.2";
|