Skip to content

Commit 53649f6

Browse files
committed
fix(cli): improve error handling and adjust child process spawning logic
1 parent 866c76a commit 53649f6

5 files changed

Lines changed: 54 additions & 31 deletions

File tree

packages/cli-core/src/CliCore.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ export class CliCore {
109109
const cliService = inject(CliService);
110110
constant("plugins") && (await loadPlugins());
111111

112-
await $asyncEmit("$beforeInit");
113112
await injector().load();
114113
await $asyncEmit("$afterInit");
115114

packages/cli-core/src/services/CliHttpClient.spec.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ describe("CliHttpClient", () => {
99
beforeEach(() => DITest.create());
1010
afterEach(() => DITest.reset());
1111

12-
describe("$afterInit()", () => {
13-
it("should call $afterInit method", async () => {
12+
describe("proxy settings", () => {
13+
it("should resolve proxy settings once for non-local HTTP endpoints", async () => {
1414
const cliProxyAgent = {
15-
resolveProxySettings: vi.fn()
15+
resolveProxySettings: vi.fn().mockResolvedValue(undefined),
16+
hasProxy: vi.fn().mockReturnValue(false),
17+
get: vi.fn().mockReturnValue(null)
1618
};
1719
const client = await DITest.invoke<CliHttpClient>(CliHttpClient, [
1820
{
@@ -21,9 +23,15 @@ describe("CliHttpClient", () => {
2123
}
2224
]);
2325

24-
await client.$afterInit();
26+
(axios as any).mockResolvedValue({
27+
headers: {},
28+
data: {}
29+
});
30+
31+
await client.get("https://api.tsed.dev/test");
32+
await client.get("https://api.tsed.dev/test");
2533

26-
expect(cliProxyAgent.resolveProxySettings).toHaveBeenCalled();
34+
expect(cliProxyAgent.resolveProxySettings).toHaveBeenCalledTimes(1);
2735
});
2836
});
2937
describe("head()", () => {

packages/cli-core/src/services/CliHttpClient.ts

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,56 +15,55 @@ export interface CliHttpClientOptions extends AxiosRequestConfig, Record<string,
1515

1616
export class CliHttpClient extends CliHttpLogClient {
1717
protected cliProxyAgent = inject(CliProxyAgent);
18-
1918
protected host: string;
19+
private proxySettingsInitialized = false;
20+
private proxySettingsPromise?: Promise<void>;
2021

2122
static getParamsSerializer(params: any) {
2223
return stringify(cleanObject(params));
2324
}
2425

25-
async $afterInit() {
26-
await this.cliProxyAgent.resolveProxySettings();
27-
}
28-
2926
async head<T = Record<string, any>>(endpoint: string, options: CliHttpClientOptions = {}): Promise<T> {
30-
const {headers} = await axios(this.getRequestParameters("HEAD", endpoint, options));
27+
const {headers} = await axios(await this.getRequestParameters("HEAD", endpoint, options));
3128

3229
return headers as any;
3330
}
3431

3532
async get<T = unknown>(endpoint: string, options: CliHttpClientOptions = {}): Promise<T> {
36-
const result = await this.send(this.getRequestParameters("GET", endpoint, options));
33+
const result = await this.send(await this.getRequestParameters("GET", endpoint, options));
3734

3835
return this.mapResponse(result, options);
3936
}
4037

4138
async post<T = unknown>(endpoint: string, options: CliHttpClientOptions = {}): Promise<T> {
42-
const result = await this.send(this.getRequestParameters("POST", endpoint, options));
39+
const result = await this.send(await this.getRequestParameters("POST", endpoint, options));
4340

4441
return this.mapResponse(result, options);
4542
}
4643

4744
async put<T = any>(endpoint: string, options: CliHttpClientOptions = {}): Promise<T> {
48-
const result = await this.send(this.getRequestParameters("PUT", endpoint, options));
45+
const result = await this.send(await this.getRequestParameters("PUT", endpoint, options));
4946

5047
return this.mapResponse(result, options);
5148
}
5249

5350
async patch<T = any>(endpoint: string, options: CliHttpClientOptions = {}): Promise<T> {
54-
const result = await this.send(this.getRequestParameters("PATCH", endpoint, options));
51+
const result = await this.send(await this.getRequestParameters("PATCH", endpoint, options));
5552

5653
return this.mapResponse(result, options);
5754
}
5855

5956
async delete<T = any>(endpoint: string, options: CliHttpClientOptions = {}): Promise<T> {
60-
const result = await this.send(this.getRequestParameters("DELETE", endpoint, options));
57+
const result = await this.send(await this.getRequestParameters("DELETE", endpoint, options));
6158

6259
return this.mapResponse(result, options);
6360
}
6461

65-
protected getRequestParameters(method: Method, endpoint: string, options: CliHttpClientOptions) {
62+
protected async getRequestParameters(method: Method, endpoint: string, options: CliHttpClientOptions) {
6663
const url = (this.host || "") + endpoint.replace(this.host || "", "");
6764

65+
await this.resolveProxySettingsOnce();
66+
6867
options = {
6968
method,
7069
...options,
@@ -78,23 +77,42 @@ export class CliHttpClient extends CliHttpLogClient {
7877
}
7978
};
8079

81-
this.configureProxy(url, options);
80+
await this.configureProxy(url, options);
8281

8382
return options;
8483
}
8584

86-
protected configureProxy(endpoint: string, options: CliHttpClientOptions) {
85+
private async resolveProxySettingsOnce() {
86+
if (this.proxySettingsInitialized) {
87+
return;
88+
}
89+
90+
if (!this.proxySettingsPromise) {
91+
this.proxySettingsPromise = this.cliProxyAgent
92+
.resolveProxySettings()
93+
.catch(() => {
94+
return;
95+
})
96+
.finally(() => {
97+
this.proxySettingsInitialized = true;
98+
});
99+
}
100+
101+
await this.proxySettingsPromise;
102+
}
103+
104+
protected async configureProxy(endpoint: string, options: CliHttpClientOptions) {
87105
const url = new URL(endpoint);
88106

89107
if (this.cliProxyAgent.hasProxy()) {
90108
const protocol = url.protocol.replace(":", "");
91109
switch (protocol) {
92110
case "https":
93-
options.httpsAgent = this.cliProxyAgent.get(protocol);
111+
options.httpsAgent = await this.cliProxyAgent.get(protocol);
94112
options.proxy = false;
95113
break;
96114
case "http":
97-
options.httpAgent = this.cliProxyAgent.get(protocol);
115+
options.httpAgent = await this.cliProxyAgent.get(protocol);
98116
options.proxy = false;
99117
break;
100118
default:

packages/cli-core/src/services/CliProxyAgent.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,14 @@ export class CliProxyAgent {
1616
readonly proxySettings = refValue<CliProxySettings>("proxy", {} as never);
1717
protected projectPackageJson = inject(ProjectPackageJson);
1818
protected cliExeca = inject(CliExeca);
19-
protected tunnel: typeof import("tunnel");
20-
21-
async $onInit() {
22-
this.tunnel = await import("tunnel");
23-
}
2419

2520
hasProxy() {
2621
return !!this.proxySettings.value.url;
2722
}
2823

29-
get(type: "http" | "https") {
24+
async get(type: "http" | "https") {
3025
if (this.hasProxy()) {
26+
const tunnel = await import("tunnel");
3127
const {strictSsl = true} = this.proxySettings.value;
3228
const url = new URL(this.proxySettings.value.url);
3329
const protocol = url.protocol.replace(":", "");
@@ -43,8 +39,8 @@ export class CliProxyAgent {
4339

4440
const method = camelCase([type, "over", protocol].join(" "));
4541

46-
if ((this.tunnel as any)[method]) {
47-
return (this.tunnel as any)[method](options);
42+
if ((tunnel as any)[method]) {
43+
return (tunnel as any)[method](options);
4844
}
4945
}
5046

packages/cli/src/bin/tsed-dev.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ async function runViteController(rawArgs: string[]) {
8888
let queued = false;
8989

9090
const startChild = () => {
91-
childProcess = spawn(process.execPath, [runnerFile, ...rawArgs], {
91+
const cliEntry = process.argv[1];
92+
93+
childProcess = spawn(process.execPath, cliEntry ? [cliEntry, "dev", ...rawArgs] : [runnerFile, ...rawArgs], {
9294
env: {
9395
...process.env,
9496
[RUN_MODE]: "app"

0 commit comments

Comments
 (0)