@youcan/cli-kit 2.8.0 → 2.8.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/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/common/string.js +16 -12
- package/dist/index.js +20 -37
- package/dist/internal/node/constants.js +9 -11
- package/dist/internal/node/ui.js +57 -46
- package/dist/node/callback.js +61 -56
- package/dist/node/cli.js +70 -94
- package/dist/node/config.js +25 -23
- package/dist/node/context/helpers.js +12 -5
- package/dist/node/context/local.js +5 -5
- package/dist/node/crypto.js +23 -12
- package/dist/node/env.js +28 -33
- package/dist/node/filesystem.js +111 -105
- package/dist/node/form.js +23 -38
- package/dist/node/git.js +39 -43
- package/dist/node/github.js +12 -9
- package/dist/node/http.js +41 -47
- package/dist/node/path.js +18 -10
- package/dist/node/session.js +80 -99
- package/dist/node/system.js +87 -103
- package/dist/node/tasks.js +30 -35
- package/dist/node/worker.js +37 -53
- package/dist/services/cloudflared.js +159 -200
- package/dist/services/cloudflared.test.js +92 -110
- package/dist/services/index.js +6 -1
- package/dist/ui/components/DevOutput.js +52 -56
- package/dist/ui/components/Error.js +14 -15
- package/dist/ui/components/HotKeys.js +14 -20
- package/dist/ui/components/utils/symbols.js +6 -6
- package/dist/ui/index.js +12 -3
- package/package.json +5 -5
package/dist/node/worker.js
CHANGED
|
@@ -1,53 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
renderDevOutput.outputSubject.emit({
|
|
39
|
-
timestamp: time,
|
|
40
|
-
color: this.color,
|
|
41
|
-
label: this.type,
|
|
42
|
-
buffer: line,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
class Abstract {
|
|
49
|
-
async cleanup() {
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export { Abstract, Logger };
|
|
1
|
+
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { renderDevOutput } from "../ui/components/DevOutput.js";
|
|
3
|
+
import "../index.js";
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
import { Writable } from "node:stream";
|
|
6
|
+
import dayjs from "dayjs";
|
|
7
|
+
//#region lib/node/worker.ts
|
|
8
|
+
var worker_exports = /* @__PURE__ */ __exportAll({
|
|
9
|
+
Abstract: () => Abstract,
|
|
10
|
+
Logger: () => Logger
|
|
11
|
+
});
|
|
12
|
+
var Logger = class extends Writable {
|
|
13
|
+
type;
|
|
14
|
+
color;
|
|
15
|
+
constructor(type, color) {
|
|
16
|
+
super();
|
|
17
|
+
this.type = type;
|
|
18
|
+
this.color = color;
|
|
19
|
+
}
|
|
20
|
+
write(chunk) {
|
|
21
|
+
if (!(chunk instanceof Buffer) && typeof chunk !== "string") return false;
|
|
22
|
+
const time = dayjs().format("HH:mm:ss:SSS");
|
|
23
|
+
const lines = chunk.toString().split("\n").map((s) => s.trim()).filter((s) => s !== "");
|
|
24
|
+
for (const line of lines) renderDevOutput.outputSubject.emit({
|
|
25
|
+
timestamp: time,
|
|
26
|
+
color: this.color,
|
|
27
|
+
label: this.type,
|
|
28
|
+
buffer: line
|
|
29
|
+
});
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var Abstract = class {
|
|
34
|
+
async cleanup() {}
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { Abstract, Logger, worker_exports };
|
|
@@ -1,221 +1,180 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
import 'formdata-node';
|
|
13
|
-
import 'formdata-node/file-from-path';
|
|
14
|
-
import 'simple-git';
|
|
15
|
-
import { exec } from '../node/system.js';
|
|
16
|
-
import 'node-fetch';
|
|
17
|
-
import 'ramda';
|
|
18
|
-
import { join, dirname, basename, resolve } from '../node/path.js';
|
|
19
|
-
import 'kleur';
|
|
20
|
-
import 'dayjs';
|
|
21
|
-
import '../ui/components/DevOutput.js';
|
|
22
|
-
import 'react';
|
|
23
|
-
import 'ink';
|
|
24
|
-
|
|
25
|
-
const LINUX_TARGET_NAMES = {
|
|
26
|
-
arm64: 'cloudflared-linux-arm64',
|
|
27
|
-
arm: 'cloudflared-linux-arm',
|
|
28
|
-
x64: 'cloudflared-linux-amd64',
|
|
29
|
-
ia32: 'cloudflared-linux-386',
|
|
30
|
-
};
|
|
31
|
-
const MACOS_TARGET_NAMES = {
|
|
32
|
-
arm64: 'cloudflared-darwin-arm64.tgz',
|
|
33
|
-
x64: 'cloudflared-darwin-amd64.tgz',
|
|
34
|
-
};
|
|
35
|
-
const WINDOWS_TARGET_NAMES = {
|
|
36
|
-
x64: 'cloudflared-windows-amd64.exe',
|
|
37
|
-
ia32: 'cloudflared-windows-386.exe',
|
|
38
|
-
arm64: 'cloudflared-windows-amd64.exe',
|
|
39
|
-
};
|
|
1
|
+
import { chmod, decompressGzip, extractTar, isExecutable, mkdir, move, tapIntoTmp } from "../node/filesystem.js";
|
|
2
|
+
import { exec } from "../node/system.js";
|
|
3
|
+
import { basename, dirname, join, resolve } from "../node/path.js";
|
|
4
|
+
import "../index.js";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { createWriteStream } from "node:fs";
|
|
7
|
+
import { pipeline } from "node:stream/promises";
|
|
8
|
+
import { Buffer } from "node:buffer";
|
|
9
|
+
import { Readable, Writable } from "node:stream";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
//#region lib/services/cloudflared.ts
|
|
40
12
|
const TARGET_NAMES = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
13
|
+
linux: {
|
|
14
|
+
arm64: "cloudflared-linux-arm64",
|
|
15
|
+
arm: "cloudflared-linux-arm",
|
|
16
|
+
x64: "cloudflared-linux-amd64",
|
|
17
|
+
ia32: "cloudflared-linux-386"
|
|
18
|
+
},
|
|
19
|
+
darwin: {
|
|
20
|
+
arm64: "cloudflared-darwin-arm64.tgz",
|
|
21
|
+
x64: "cloudflared-darwin-amd64.tgz"
|
|
22
|
+
},
|
|
23
|
+
win32: {
|
|
24
|
+
x64: "cloudflared-windows-amd64.exe",
|
|
25
|
+
ia32: "cloudflared-windows-386.exe",
|
|
26
|
+
arm64: "cloudflared-windows-amd64.exe"
|
|
27
|
+
}
|
|
44
28
|
};
|
|
45
29
|
function composeDownloadUrl(platform, arch) {
|
|
46
|
-
|
|
47
|
-
const supportedVersion = '2024.11.1';
|
|
48
|
-
const filename = TARGET_NAMES[platform][arch];
|
|
49
|
-
return `${releaseDownloadUrl}/${supportedVersion}/${filename}`;
|
|
30
|
+
return `https://github.com/cloudflare/cloudflared/releases/download/2024.11.1/${TARGET_NAMES[platform][arch]}`;
|
|
50
31
|
}
|
|
51
32
|
function resolveBinaryPath(platform) {
|
|
52
|
-
|
|
53
|
-
return join(rootDir, 'bin', platform === 'win32' ? 'cloudflared.exe' : 'cloudflared');
|
|
33
|
+
return join(fileURLToPath(new URL("../".repeat(2), import.meta.url)), "bin", platform === "win32" ? "cloudflared.exe" : "cloudflared");
|
|
54
34
|
}
|
|
55
35
|
function isPlatformSupported(platform) {
|
|
56
|
-
|
|
36
|
+
return platform in TARGET_NAMES;
|
|
57
37
|
}
|
|
58
38
|
function isArchSupported(arch, platform) {
|
|
59
|
-
|
|
39
|
+
return arch in TARGET_NAMES[platform];
|
|
60
40
|
}
|
|
61
41
|
async function downloadFromRelease(url, downloadPath) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const fileWriteStream = createWriteStream(downloadPath, { mode: 0o664 });
|
|
68
|
-
await pipeline(Readable.fromWeb(body), fileWriteStream);
|
|
42
|
+
const response = await fetch(url, { redirect: "follow" });
|
|
43
|
+
if (!response.ok) throw new Error(`failed to download cloudflared: ${response.statusText}`);
|
|
44
|
+
const { body } = response;
|
|
45
|
+
const fileWriteStream = createWriteStream(downloadPath, { mode: 436 });
|
|
46
|
+
await pipeline(Readable.fromWeb(body), fileWriteStream);
|
|
69
47
|
}
|
|
70
48
|
async function installForMacOs(url, destination) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
49
|
+
await tapIntoTmp(async (tmpDir) => {
|
|
50
|
+
const parentDir = dirname(destination);
|
|
51
|
+
const binaryName = basename(destination);
|
|
52
|
+
const downloadedFile = resolve(tmpDir, `${binaryName}.tgz`);
|
|
53
|
+
const decompressedFile = resolve(tmpDir, `${binaryName}.gz`);
|
|
54
|
+
await mkdir(parentDir);
|
|
55
|
+
await mkdir(tmpDir);
|
|
56
|
+
await downloadFromRelease(url, downloadedFile);
|
|
57
|
+
await decompressGzip(downloadedFile, decompressedFile);
|
|
58
|
+
await extractTar(decompressedFile, tmpDir, 493);
|
|
59
|
+
await move(resolve(tmpDir, binaryName), destination, { overwrite: true });
|
|
60
|
+
});
|
|
83
61
|
}
|
|
84
62
|
async function installForLinux(url, destination) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await chmod(destination, 0o755);
|
|
63
|
+
await mkdir(dirname(destination));
|
|
64
|
+
await downloadFromRelease(url, destination);
|
|
65
|
+
await chmod(destination, 493);
|
|
89
66
|
}
|
|
90
67
|
async function installForWindows(url, destination) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
await downloadFromRelease(url, destination);
|
|
68
|
+
mkdir(dirname(destination));
|
|
69
|
+
await downloadFromRelease(url, destination);
|
|
94
70
|
}
|
|
95
71
|
async function install(platform, downloadUrl, destinationPath) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
class OutputStream extends Writable {
|
|
109
|
-
tunnelUrl = null;
|
|
110
|
-
tunnelError = null;
|
|
111
|
-
buffer = '';
|
|
112
|
-
static ErrorsRegex = [
|
|
113
|
-
/failed to build quick tunnel request/,
|
|
114
|
-
/failed to request quick Tunnel/,
|
|
115
|
-
/failed to read quick-tunnel response/,
|
|
116
|
-
/failed to parse quick Tunnel ID/,
|
|
117
|
-
/Couldn't start tunnel/,
|
|
118
|
-
];
|
|
119
|
-
write(chunk, encoding, callback) {
|
|
120
|
-
if (!(chunk instanceof Buffer) && typeof chunk !== 'string') {
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
this.buffer += chunk.toString();
|
|
124
|
-
if (this.tunnelUrl === null) {
|
|
125
|
-
this.tunnelUrl = this.extractTunnelUrl();
|
|
126
|
-
}
|
|
127
|
-
if (callback && typeof callback === 'function') {
|
|
128
|
-
callback();
|
|
129
|
-
}
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
extractTunnelUrl() {
|
|
133
|
-
const regex = /https:\/\/(?!api\.trycloudflare\.com)\S+\.trycloudflare\.com/;
|
|
134
|
-
return this.buffer.match(regex)?.[0] || null;
|
|
135
|
-
}
|
|
136
|
-
extractError() {
|
|
137
|
-
for (const errorRegex of OutputStream.ErrorsRegex) {
|
|
138
|
-
if (errorRegex.test(this.buffer)) {
|
|
139
|
-
return errorRegex.source;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
getTunnelUrl() {
|
|
145
|
-
return this.tunnelUrl;
|
|
146
|
-
}
|
|
147
|
-
clearBuffer() {
|
|
148
|
-
this.buffer = '';
|
|
149
|
-
}
|
|
150
|
-
getBuffer() {
|
|
151
|
-
return this.buffer;
|
|
152
|
-
}
|
|
72
|
+
switch (platform) {
|
|
73
|
+
case "darwin":
|
|
74
|
+
await installForMacOs(downloadUrl, destinationPath);
|
|
75
|
+
break;
|
|
76
|
+
case "linux":
|
|
77
|
+
await installForLinux(downloadUrl, destinationPath);
|
|
78
|
+
break;
|
|
79
|
+
case "win32":
|
|
80
|
+
await installForWindows(downloadUrl, destinationPath);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
153
83
|
}
|
|
154
|
-
class
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
84
|
+
var OutputStream = class OutputStream extends Writable {
|
|
85
|
+
tunnelUrl = null;
|
|
86
|
+
tunnelError = null;
|
|
87
|
+
buffer = "";
|
|
88
|
+
static ErrorsRegex = [
|
|
89
|
+
/failed to build quick tunnel request/,
|
|
90
|
+
/failed to request quick Tunnel/,
|
|
91
|
+
/failed to read quick-tunnel response/,
|
|
92
|
+
/failed to parse quick Tunnel ID/,
|
|
93
|
+
/Couldn't start tunnel/
|
|
94
|
+
];
|
|
95
|
+
write(chunk, encoding, callback) {
|
|
96
|
+
if (!(chunk instanceof Buffer) && typeof chunk !== "string") return false;
|
|
97
|
+
this.buffer += chunk.toString();
|
|
98
|
+
if (this.tunnelUrl === null) this.tunnelUrl = this.extractTunnelUrl();
|
|
99
|
+
if (callback && typeof callback === "function") callback();
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
extractTunnelUrl() {
|
|
103
|
+
return this.buffer.match(/https:\/\/(?!api\.trycloudflare\.com)\S+\.trycloudflare\.com/)?.[0] || null;
|
|
104
|
+
}
|
|
105
|
+
extractError() {
|
|
106
|
+
for (const errorRegex of OutputStream.ErrorsRegex) if (errorRegex.test(this.buffer)) return errorRegex.source;
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
getTunnelUrl() {
|
|
110
|
+
return this.tunnelUrl;
|
|
111
|
+
}
|
|
112
|
+
clearBuffer() {
|
|
113
|
+
this.buffer = "";
|
|
114
|
+
}
|
|
115
|
+
getBuffer() {
|
|
116
|
+
return this.buffer;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var Cloudflared = class {
|
|
120
|
+
bin;
|
|
121
|
+
system;
|
|
122
|
+
output = new OutputStream();
|
|
123
|
+
constructor() {
|
|
124
|
+
const platform = process.platform;
|
|
125
|
+
const arch = process.arch;
|
|
126
|
+
if (!isPlatformSupported(platform)) throw new Error(`unsupported platform: ${platform}`);
|
|
127
|
+
if (!isArchSupported(arch, platform)) throw new Error(`unsupported architecture: ${arch}`);
|
|
128
|
+
this.bin = resolveBinaryPath(platform);
|
|
129
|
+
this.system = {
|
|
130
|
+
platform,
|
|
131
|
+
arch
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
async tunnel(port, host = "localhost", signal) {
|
|
135
|
+
await this.install();
|
|
136
|
+
const { bin, args } = this.composeTunnelingCommand(port, host);
|
|
137
|
+
this.exec(bin, args, 3, signal);
|
|
138
|
+
}
|
|
139
|
+
async install() {
|
|
140
|
+
if (await isExecutable(this.bin)) return;
|
|
141
|
+
const downloadUrl = composeDownloadUrl(this.system.platform, this.system.arch);
|
|
142
|
+
await install(this.system.platform, downloadUrl, this.bin);
|
|
143
|
+
if (!await isExecutable(this.bin)) throw new Error(`Failed to install executable cloudflared binary at ${this.bin}. Check file permissions and platform compatibility.`);
|
|
144
|
+
}
|
|
145
|
+
composeTunnelingCommand(port, host = "localhost") {
|
|
146
|
+
return {
|
|
147
|
+
bin: this.bin,
|
|
148
|
+
args: [
|
|
149
|
+
"tunnel",
|
|
150
|
+
`--url=${host}:${port}`,
|
|
151
|
+
"--no-autoupdate"
|
|
152
|
+
]
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async exec(bin, args, maxRetries = 3, signal) {
|
|
156
|
+
if (this.getUrl()) return;
|
|
157
|
+
if (maxRetries === 0) {
|
|
158
|
+
const extractedError = this.output.extractError();
|
|
159
|
+
const errorMessage = extractedError ? `cloudflared failed: ${extractedError}` : `cloudflared failed for unknown reason. Binary: ${bin}, Args: ${args.join(" ")}, Buffer: ${this.output.getBuffer()}`;
|
|
160
|
+
throw new Error(errorMessage);
|
|
161
|
+
}
|
|
162
|
+
this.output.clearBuffer();
|
|
163
|
+
await exec(bin, args, {
|
|
164
|
+
stderr: this.output,
|
|
165
|
+
signal,
|
|
166
|
+
errorHandler: async (error) => {
|
|
167
|
+
console.error(`cloudflared execution error (retries left: ${maxRetries - 1}):`, error);
|
|
168
|
+
await this.exec(bin, args, maxRetries - 1, signal);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
getUrl() {
|
|
173
|
+
return this.output.getTunnelUrl();
|
|
174
|
+
}
|
|
175
|
+
getError() {
|
|
176
|
+
return this.output.extractError();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
//#endregion
|
|
221
180
|
export { Cloudflared };
|