unplugin-cloudflare-tunnel 0.0.0-alpha-1 → 0.0.1
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/api.d.ts +50 -1
- package/dist/api.js +59 -1
- package/dist/esbuild.d.ts +1 -1
- package/dist/esbuild.js +1 -1
- package/dist/farm.d.ts +1 -1
- package/dist/farm.js +1 -1
- package/dist/{index-BjNI6nQt.d.ts → index-BK_mUExr.d.ts} +33 -33
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/rolldown.d.ts +1 -1
- package/dist/rolldown.js +1 -1
- package/dist/rollup.d.ts +1 -1
- package/dist/rollup.js +1 -1
- package/dist/rspack.d.ts +1 -1
- package/dist/rspack.js +1 -1
- package/dist/{src-BC4MyCER.js → src-CVRdCQUT.js} +323 -65
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -1
- package/dist/webpack.d.ts +1 -1
- package/dist/webpack.js +1 -1
- package/package.json +17 -17
package/dist/api.d.ts
CHANGED
|
@@ -1 +1,50 @@
|
|
|
1
|
-
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
|
|
3
|
+
//#region src/api.d.ts
|
|
4
|
+
declare const CloudflareErrorSchema: z.ZodMiniObject<{
|
|
5
|
+
code: z.ZodMiniNumber<number>;
|
|
6
|
+
message: z.ZodMiniString<string>;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
declare const CloudflareApiResponseSchema: z.ZodMiniObject<{
|
|
9
|
+
success: z.ZodMiniBoolean<boolean>;
|
|
10
|
+
errors: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
|
|
11
|
+
code: z.ZodMiniNumber<number>;
|
|
12
|
+
message: z.ZodMiniString<string>;
|
|
13
|
+
}, z.core.$strip>>>;
|
|
14
|
+
messages: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
15
|
+
result: z.ZodMiniUnknown;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
declare const AccountSchema: z.ZodMiniObject<{
|
|
18
|
+
id: z.ZodMiniString<string>;
|
|
19
|
+
name: z.ZodMiniString<string>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
declare const ZoneSchema: z.ZodMiniObject<{
|
|
22
|
+
id: z.ZodMiniString<string>;
|
|
23
|
+
name: z.ZodMiniString<string>;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
declare const TunnelSchema: z.ZodMiniObject<{
|
|
26
|
+
id: z.ZodMiniString<string>;
|
|
27
|
+
name: z.ZodMiniString<string>;
|
|
28
|
+
account_tag: z.ZodMiniString<string>;
|
|
29
|
+
created_at: z.ZodMiniString<string>;
|
|
30
|
+
connections: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniUnknown>>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
declare const DNSRecordSchema: z.ZodMiniObject<{
|
|
33
|
+
id: z.ZodMiniString<string>;
|
|
34
|
+
type: z.ZodMiniString<string>;
|
|
35
|
+
name: z.ZodMiniString<string>;
|
|
36
|
+
content: z.ZodMiniString<string>;
|
|
37
|
+
proxied: z.ZodMiniBoolean<boolean>;
|
|
38
|
+
comment: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
declare function normalizeAddress(address: string | {
|
|
41
|
+
address?: string;
|
|
42
|
+
port?: number;
|
|
43
|
+
} | null | undefined): {
|
|
44
|
+
host: string;
|
|
45
|
+
port?: number;
|
|
46
|
+
};
|
|
47
|
+
declare function ensureCloudflaredBinary(binPath: string): Promise<void>;
|
|
48
|
+
declare function getLocalTarget(host: string, port: number): string;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { AccountSchema, CloudflareApiResponseSchema, CloudflareErrorSchema, DNSRecordSchema, TunnelSchema, ZoneSchema, ensureCloudflaredBinary, getLocalTarget, normalizeAddress };
|
package/dist/api.js
CHANGED
|
@@ -1 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
import NodeFS from "node:fs/promises";
|
|
3
|
+
import { install } from "cloudflared";
|
|
4
|
+
|
|
5
|
+
//#region src/api.ts
|
|
6
|
+
const CloudflareErrorSchema = z.object({
|
|
7
|
+
code: z.number(),
|
|
8
|
+
message: z.string()
|
|
9
|
+
});
|
|
10
|
+
const CloudflareApiResponseSchema = z.object({
|
|
11
|
+
success: z.boolean(),
|
|
12
|
+
errors: z.optional(z.array(CloudflareErrorSchema)),
|
|
13
|
+
messages: z.optional(z.array(z.string())),
|
|
14
|
+
result: z.unknown()
|
|
15
|
+
});
|
|
16
|
+
const AccountSchema = z.object({
|
|
17
|
+
id: z.string(),
|
|
18
|
+
name: z.string()
|
|
19
|
+
});
|
|
20
|
+
const ZoneSchema = z.object({
|
|
21
|
+
id: z.string(),
|
|
22
|
+
name: z.string()
|
|
23
|
+
});
|
|
24
|
+
const TunnelSchema = z.object({
|
|
25
|
+
id: z.string(),
|
|
26
|
+
name: z.string(),
|
|
27
|
+
account_tag: z.string(),
|
|
28
|
+
created_at: z.string(),
|
|
29
|
+
connections: z.optional(z.array(z.unknown()))
|
|
30
|
+
});
|
|
31
|
+
const DNSRecordSchema = z.object({
|
|
32
|
+
id: z.string(),
|
|
33
|
+
type: z.string(),
|
|
34
|
+
name: z.string(),
|
|
35
|
+
content: z.string(),
|
|
36
|
+
proxied: z.boolean(),
|
|
37
|
+
comment: z.nullish(z.string())
|
|
38
|
+
});
|
|
39
|
+
function normalizeAddress(address) {
|
|
40
|
+
if (address && typeof address === "object") return {
|
|
41
|
+
host: "address" in address && address.address ? address.address : "localhost",
|
|
42
|
+
port: "port" in address && typeof address.port === "number" ? address.port : void 0
|
|
43
|
+
};
|
|
44
|
+
return { host: "localhost" };
|
|
45
|
+
}
|
|
46
|
+
async function ensureCloudflaredBinary(binPath) {
|
|
47
|
+
try {
|
|
48
|
+
await NodeFS.access(binPath);
|
|
49
|
+
} catch {
|
|
50
|
+
console.log("[unplugin-cloudflare-tunnel] Installing cloudflared binary...");
|
|
51
|
+
await install(binPath);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function getLocalTarget(host, port) {
|
|
55
|
+
return `http://${host.includes(":") ? `[${host}]` : host}:${port}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { AccountSchema, CloudflareApiResponseSchema, CloudflareErrorSchema, DNSRecordSchema, TunnelSchema, ZoneSchema, ensureCloudflaredBinary, getLocalTarget, normalizeAddress };
|
package/dist/esbuild.d.ts
CHANGED
package/dist/esbuild.js
CHANGED
package/dist/farm.d.ts
CHANGED
package/dist/farm.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
1
|
import { UnpluginInstance } from "unplugin";
|
|
2
|
+
import * as z from "zod/mini";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
5
|
|
|
6
|
-
declare const CloudflareApiResponseSchema: z.
|
|
7
|
-
success: boolean
|
|
8
|
-
errors
|
|
9
|
-
code: number
|
|
10
|
-
message: string
|
|
11
|
-
}
|
|
12
|
-
messages
|
|
13
|
-
result:
|
|
14
|
-
}>;
|
|
15
|
-
declare const AccountSchema: z.
|
|
16
|
-
id: string
|
|
17
|
-
name: string
|
|
18
|
-
}>;
|
|
19
|
-
declare const ZoneSchema: z.
|
|
20
|
-
id: string
|
|
21
|
-
name: string
|
|
22
|
-
}>;
|
|
23
|
-
declare const TunnelSchema: z.
|
|
24
|
-
id: string
|
|
25
|
-
name: string
|
|
26
|
-
account_tag: string
|
|
27
|
-
created_at: string
|
|
28
|
-
connections
|
|
29
|
-
}>;
|
|
30
|
-
declare const DNSRecordSchema: z.
|
|
31
|
-
id: string
|
|
32
|
-
type: string
|
|
33
|
-
name: string
|
|
34
|
-
content: string
|
|
35
|
-
proxied: boolean
|
|
36
|
-
comment
|
|
37
|
-
}>;
|
|
6
|
+
declare const CloudflareApiResponseSchema: z.ZodMiniObject<{
|
|
7
|
+
success: z.ZodMiniBoolean<boolean>;
|
|
8
|
+
errors: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
|
|
9
|
+
code: z.ZodMiniNumber<number>;
|
|
10
|
+
message: z.ZodMiniString<string>;
|
|
11
|
+
}, z.core.$strip>>>;
|
|
12
|
+
messages: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
13
|
+
result: z.ZodMiniUnknown;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
declare const AccountSchema: z.ZodMiniObject<{
|
|
16
|
+
id: z.ZodMiniString<string>;
|
|
17
|
+
name: z.ZodMiniString<string>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
declare const ZoneSchema: z.ZodMiniObject<{
|
|
20
|
+
id: z.ZodMiniString<string>;
|
|
21
|
+
name: z.ZodMiniString<string>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
declare const TunnelSchema: z.ZodMiniObject<{
|
|
24
|
+
id: z.ZodMiniString<string>;
|
|
25
|
+
name: z.ZodMiniString<string>;
|
|
26
|
+
account_tag: z.ZodMiniString<string>;
|
|
27
|
+
created_at: z.ZodMiniString<string>;
|
|
28
|
+
connections: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniUnknown>>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
declare const DNSRecordSchema: z.ZodMiniObject<{
|
|
31
|
+
id: z.ZodMiniString<string>;
|
|
32
|
+
type: z.ZodMiniString<string>;
|
|
33
|
+
name: z.ZodMiniString<string>;
|
|
34
|
+
content: z.ZodMiniString<string>;
|
|
35
|
+
proxied: z.ZodMiniBoolean<boolean>;
|
|
36
|
+
comment: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
38
|
type CloudflareApiResponse<T = unknown> = z.infer<typeof CloudflareApiResponseSchema> & {
|
|
39
39
|
result: T;
|
|
40
40
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as DNSRecord, i as CloudflareTunnelOptions, n as CloudflareApiResponse, o as Tunnel, r as CloudflareTunnel, s as Zone, t as Account } from "./index-
|
|
1
|
+
import { a as DNSRecord, i as CloudflareTunnelOptions, n as CloudflareApiResponse, o as Tunnel, r as CloudflareTunnel, s as Zone, t as Account } from "./index-BK_mUExr.js";
|
|
2
2
|
export { Account, CloudflareApiResponse, CloudflareTunnel, CloudflareTunnel as default, CloudflareTunnelOptions, DNSRecord, Tunnel, Zone };
|
package/dist/index.js
CHANGED
package/dist/rolldown.d.ts
CHANGED
package/dist/rolldown.js
CHANGED
package/dist/rollup.d.ts
CHANGED
package/dist/rollup.js
CHANGED
package/dist/rspack.d.ts
CHANGED
package/dist/rspack.js
CHANGED
|
@@ -1,19 +1,53 @@
|
|
|
1
|
-
import { bin, install } from "cloudflared";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import { exec, spawn } from "node:child_process";
|
|
4
|
-
import { z } from "zod";
|
|
5
1
|
import { createUnplugin } from "unplugin";
|
|
2
|
+
import * as z from "zod/mini";
|
|
3
|
+
import NodeFS from "node:fs/promises";
|
|
4
|
+
import { bin, install } from "cloudflared";
|
|
5
|
+
import * as NodeChildProcess from "node:child_process";
|
|
6
6
|
|
|
7
7
|
//#region src/index.ts
|
|
8
|
+
const PLUGIN_NAME = "unplugin-cloudflare-tunnel";
|
|
8
9
|
const INFO_LOG_REGEX = /^.*Z INF .*/;
|
|
10
|
+
const LOG_LEVEL_RANK = {
|
|
11
|
+
debug: 10,
|
|
12
|
+
info: 20,
|
|
13
|
+
warn: 30,
|
|
14
|
+
error: 40,
|
|
15
|
+
fatal: 50
|
|
16
|
+
};
|
|
17
|
+
function shouldLog(threshold, level) {
|
|
18
|
+
return LOG_LEVEL_RANK[level] >= LOG_LEVEL_RANK[threshold];
|
|
19
|
+
}
|
|
20
|
+
function supportsColor() {
|
|
21
|
+
if (!process.stdout.isTTY) return false;
|
|
22
|
+
if (process.env.NO_COLOR !== void 0) return false;
|
|
23
|
+
if (process.env.TERM === "dumb") return false;
|
|
24
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const ANSI = {
|
|
28
|
+
reset: "\x1B[0m",
|
|
29
|
+
dim: "\x1B[2m",
|
|
30
|
+
bold: "\x1B[1m",
|
|
31
|
+
blue: "\x1B[34m",
|
|
32
|
+
yellow: "\x1B[33m"
|
|
33
|
+
};
|
|
34
|
+
const ANSI_ESCAPE = String.fromCharCode(27);
|
|
35
|
+
const ANSI_STYLE_SEQUENCE_REGEX = new RegExp(`${ANSI_ESCAPE}\\[[0-9;]*m`, "g");
|
|
36
|
+
function stripAnsi(text) {
|
|
37
|
+
return text.replace(ANSI_STYLE_SEQUENCE_REGEX, "");
|
|
38
|
+
}
|
|
39
|
+
function colorize(text, ansi) {
|
|
40
|
+
if (!supportsColor()) return text;
|
|
41
|
+
return `${ansi}${text}${ANSI.reset}`;
|
|
42
|
+
}
|
|
9
43
|
const CloudflareErrorSchema = z.object({
|
|
10
44
|
code: z.number(),
|
|
11
45
|
message: z.string()
|
|
12
46
|
});
|
|
13
47
|
const CloudflareApiResponseSchema = z.object({
|
|
14
48
|
success: z.boolean(),
|
|
15
|
-
errors: z.array(CloudflareErrorSchema)
|
|
16
|
-
messages: z.array(z.string())
|
|
49
|
+
errors: z.optional(z.array(CloudflareErrorSchema)),
|
|
50
|
+
messages: z.optional(z.array(z.string())),
|
|
17
51
|
result: z.unknown()
|
|
18
52
|
});
|
|
19
53
|
const AccountSchema = z.object({
|
|
@@ -29,7 +63,7 @@ const TunnelSchema = z.object({
|
|
|
29
63
|
name: z.string(),
|
|
30
64
|
account_tag: z.string(),
|
|
31
65
|
created_at: z.string(),
|
|
32
|
-
connections: z.array(z.unknown())
|
|
66
|
+
connections: z.optional(z.array(z.unknown()))
|
|
33
67
|
});
|
|
34
68
|
const DNSRecordSchema = z.object({
|
|
35
69
|
id: z.string(),
|
|
@@ -37,14 +71,14 @@ const DNSRecordSchema = z.object({
|
|
|
37
71
|
name: z.string(),
|
|
38
72
|
content: z.string(),
|
|
39
73
|
proxied: z.boolean(),
|
|
40
|
-
comment: z.
|
|
74
|
+
comment: z.nullish(z.string())
|
|
41
75
|
});
|
|
42
76
|
const unpluginFactory = (options = {}) => {
|
|
43
77
|
const { enabled = true } = options;
|
|
44
78
|
if (enabled === false) {
|
|
45
79
|
const VIRTUAL_MODULE_ID_STUB = "virtual:unplugin-cloudflare-tunnel";
|
|
46
80
|
return {
|
|
47
|
-
name:
|
|
81
|
+
name: PLUGIN_NAME,
|
|
48
82
|
enforce: "pre",
|
|
49
83
|
resolveId(id) {
|
|
50
84
|
if (id === VIRTUAL_MODULE_ID_STUB) return "\0" + VIRTUAL_MODULE_ID_STUB;
|
|
@@ -95,8 +129,79 @@ const unpluginFactory = (options = {}) => {
|
|
|
95
129
|
cleanupConfig = namedOptions.cleanup || {};
|
|
96
130
|
}
|
|
97
131
|
const { port: userProvidedPort, logFile, logLevel, debug = false } = options;
|
|
98
|
-
const
|
|
99
|
-
|
|
132
|
+
const effectivePluginLogLevel = logLevel ?? (debug ? "debug" : "info");
|
|
133
|
+
const pluginLog = {
|
|
134
|
+
debug: (...args) => {
|
|
135
|
+
if (debug || effectivePluginLogLevel === "debug") console.log("[cloudflare-tunnel:debug]", ...args);
|
|
136
|
+
},
|
|
137
|
+
info: (message) => {
|
|
138
|
+
if (shouldLog(effectivePluginLogLevel, "info")) console.log(`[unplugin-cloudflare-tunnel] ${message}`);
|
|
139
|
+
},
|
|
140
|
+
warn: (message) => {
|
|
141
|
+
if (shouldLog(effectivePluginLogLevel, "warn")) console.warn(`[unplugin-cloudflare-tunnel] ${message}`);
|
|
142
|
+
},
|
|
143
|
+
error: (message) => {
|
|
144
|
+
if (shouldLog(effectivePluginLogLevel, "error")) console.error(`[unplugin-cloudflare-tunnel] ${message}`);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const debugLog = pluginLog.debug;
|
|
148
|
+
const makeLocalDisplay = (localTarget) => {
|
|
149
|
+
if (!localTarget) return localTarget;
|
|
150
|
+
return localTarget.replace("http://[::1]:", "http://localhost:").replace("http://127.0.0.1:", "http://localhost:");
|
|
151
|
+
};
|
|
152
|
+
const announceConnecting = () => {
|
|
153
|
+
if (globalState.__tunnelConnectingAnnounced) return;
|
|
154
|
+
globalState.__tunnelConnectingAnnounced = true;
|
|
155
|
+
const message = isQuickMode ? "cf tunnel connecting…" : hostname ? `cf tunnel connecting… (${hostname})` : "cf tunnel connecting…";
|
|
156
|
+
console.log("");
|
|
157
|
+
console.log(colorize(message, ANSI.bold));
|
|
158
|
+
};
|
|
159
|
+
const announceTunnel = (params) => {
|
|
160
|
+
if (!params.url) return;
|
|
161
|
+
if (globalState.__lastAnnouncedTunnelKey === params.key) return;
|
|
162
|
+
globalState.__lastAnnouncedTunnelKey = params.key;
|
|
163
|
+
const cols = process.stdout.columns ?? 80;
|
|
164
|
+
const maxWidth = Math.max(10, cols - 2);
|
|
165
|
+
const headerText = "unplugin-cloudflare-tunnel";
|
|
166
|
+
const header = (() => {
|
|
167
|
+
return `${colorize("[", ANSI.yellow)}${headerText}${colorize("]", ANSI.yellow)}`;
|
|
168
|
+
})();
|
|
169
|
+
const urlLine = colorize(params.url, ANSI.blue + ANSI.bold);
|
|
170
|
+
const localLine = params.localTarget ? makeLocalDisplay(params.localTarget) : "";
|
|
171
|
+
const headerPlainLen = stripAnsi(header).length;
|
|
172
|
+
const contentPlainLen = Math.max(stripAnsi(urlLine).length, localLine.length, 10, 5);
|
|
173
|
+
const width = Math.min(90, maxWidth, Math.max(44, headerPlainLen, contentPlainLen + 4));
|
|
174
|
+
const rule = "─".repeat(width);
|
|
175
|
+
const center = (text) => {
|
|
176
|
+
const plainLen = stripAnsi(text).length;
|
|
177
|
+
const pad = Math.max(0, Math.floor((width - plainLen) / 2));
|
|
178
|
+
return `${" ".repeat(pad)}${text}`;
|
|
179
|
+
};
|
|
180
|
+
if (cols < 70) {
|
|
181
|
+
const out$1 = [];
|
|
182
|
+
out$1.push("");
|
|
183
|
+
out$1.push(`${header} ${colorize("Tunnel URL", ANSI.bold)} ${urlLine}`);
|
|
184
|
+
if (localLine) out$1.push(`${header} ${colorize("Local", ANSI.dim + ANSI.bold)} ${localLine}`);
|
|
185
|
+
out$1.push("");
|
|
186
|
+
console.log(out$1.join("\n"));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const out = [];
|
|
190
|
+
out.push("");
|
|
191
|
+
out.push(center(header));
|
|
192
|
+
out.push(rule);
|
|
193
|
+
out.push(center(colorize("Tunnel URL", ANSI.bold)));
|
|
194
|
+
out.push(center(urlLine));
|
|
195
|
+
out.push(center(urlLine));
|
|
196
|
+
out.push(center(urlLine));
|
|
197
|
+
if (localLine) {
|
|
198
|
+
out.push("");
|
|
199
|
+
out.push(center(colorize("Local", ANSI.dim + ANSI.bold)));
|
|
200
|
+
out.push(center(localLine));
|
|
201
|
+
}
|
|
202
|
+
out.push(rule);
|
|
203
|
+
out.push("");
|
|
204
|
+
console.log(out.join("\n"));
|
|
100
205
|
};
|
|
101
206
|
if (!isQuickMode && (!hostname || typeof hostname !== "string")) throw new Error("[unplugin-cloudflare-tunnel] hostname is required and must be a valid string in named tunnel mode");
|
|
102
207
|
let tunnelUrl = hostname ? `https://${hostname}` : "";
|
|
@@ -252,7 +357,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
252
357
|
if (logFile) cloudflaredArgs.push("--logfile", logFile);
|
|
253
358
|
cloudflaredArgs.push("--url", localTarget);
|
|
254
359
|
debugLog("Spawning quick tunnel:", bin, cloudflaredArgs);
|
|
255
|
-
const child$1 = spawn(bin, cloudflaredArgs, {
|
|
360
|
+
const child$1 = NodeChildProcess.spawn(bin, cloudflaredArgs, {
|
|
256
361
|
stdio: [
|
|
257
362
|
"ignore",
|
|
258
363
|
"pipe",
|
|
@@ -262,7 +367,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
262
367
|
windowsHide: true,
|
|
263
368
|
shell: process.platform === "win32"
|
|
264
369
|
});
|
|
265
|
-
|
|
370
|
+
debugLog(`[unplugin-cloudflare-tunnel] Quick tunnel process spawned with PID: ${child$1.pid}`);
|
|
266
371
|
return new Promise((resolve, reject) => {
|
|
267
372
|
let urlFound = false;
|
|
268
373
|
const timeout = setTimeout(() => {
|
|
@@ -310,17 +415,17 @@ const unpluginFactory = (options = {}) => {
|
|
|
310
415
|
globalState.shuttingDown = true;
|
|
311
416
|
globalState.tunnelUrl = void 0;
|
|
312
417
|
try {
|
|
313
|
-
|
|
314
|
-
if (!child.kill(signal) && process.platform === "win32") exec(`taskkill /pid ${child.pid} /T /F`, () => {});
|
|
418
|
+
debugLog(`[unplugin-cloudflare-tunnel] Terminating cloudflared process (PID: ${child.pid}) with ${signal}...`);
|
|
419
|
+
if (!child.kill(signal) && process.platform === "win32") NodeChildProcess.exec(`taskkill /pid ${child.pid} /T /F`, () => {});
|
|
315
420
|
if (signal === "SIGTERM") setTimeout(() => {
|
|
316
421
|
if (child && !child.killed) {
|
|
317
|
-
|
|
318
|
-
if (process.platform === "win32") exec(`taskkill /pid ${child.pid} /T /F`, () => {});
|
|
422
|
+
debugLog("[unplugin-cloudflare-tunnel] Force killing cloudflared process...");
|
|
423
|
+
if (process.platform === "win32") NodeChildProcess.exec(`taskkill /pid ${child.pid} /T /F`, () => {});
|
|
319
424
|
else child.kill("SIGKILL");
|
|
320
425
|
}
|
|
321
426
|
}, 2e3);
|
|
322
427
|
} catch (error) {
|
|
323
|
-
|
|
428
|
+
debugLog(`[unplugin-cloudflare-tunnel] Note: Error killing cloudflared: ${error}`);
|
|
324
429
|
}
|
|
325
430
|
};
|
|
326
431
|
let exitHandlersRegistered = globalState.exitHandlersRegistered ?? false;
|
|
@@ -359,9 +464,27 @@ const unpluginFactory = (options = {}) => {
|
|
|
359
464
|
const generateDnsComment = () => {
|
|
360
465
|
return `unplugin-cloudflare-tunnel:${tunnelName}`;
|
|
361
466
|
};
|
|
467
|
+
const registerListeningHandler = (handler) => {
|
|
468
|
+
const httpServer = server.httpServer;
|
|
469
|
+
if (!httpServer) return;
|
|
470
|
+
const invokeHandler = () => {
|
|
471
|
+
try {
|
|
472
|
+
const maybePromise = handler();
|
|
473
|
+
if (maybePromise && typeof maybePromise.then === "function") maybePromise.catch((error) => {
|
|
474
|
+
console.error(`[unplugin-cloudflare-tunnel] ❌ Dev server listening hook failed: ${error.message}`);
|
|
475
|
+
});
|
|
476
|
+
} catch (error) {
|
|
477
|
+
console.error(`[unplugin-cloudflare-tunnel] ❌ Dev server listening hook failed: ${error.message}`);
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
httpServer.on("listening", invokeHandler);
|
|
481
|
+
if (httpServer.listening) invokeHandler();
|
|
482
|
+
};
|
|
362
483
|
try {
|
|
363
484
|
const { host: serverHost, port: detectedPort } = normalizeAddress(server.httpServer?.address());
|
|
364
|
-
const
|
|
485
|
+
const configPortValue = server.config?.server?.port;
|
|
486
|
+
const resolvedConfigPort = typeof configPortValue === "string" ? Number.parseInt(configPortValue, 10) : configPortValue;
|
|
487
|
+
const port = userProvidedPort || detectedPort || (typeof resolvedConfigPort === "number" && !Number.isNaN(resolvedConfigPort) ? resolvedConfigPort : void 0) || 5173;
|
|
365
488
|
const newConfigHash = JSON.stringify({
|
|
366
489
|
isQuickMode,
|
|
367
490
|
hostname,
|
|
@@ -372,13 +495,13 @@ const unpluginFactory = (options = {}) => {
|
|
|
372
495
|
});
|
|
373
496
|
if (globalState.child && !globalState.child.killed && globalState.configHash === newConfigHash) {
|
|
374
497
|
tunnelUrl = await globalState.tunnelUrl ?? "";
|
|
375
|
-
|
|
498
|
+
debugLog("[unplugin-cloudflare-tunnel] Config unchanged – re-using existing tunnel");
|
|
376
499
|
globalState.shuttingDown = false;
|
|
377
500
|
registerExitHandler();
|
|
378
501
|
return;
|
|
379
502
|
}
|
|
380
503
|
if (globalState.child && !globalState.child.killed) {
|
|
381
|
-
|
|
504
|
+
debugLog("[unplugin-cloudflare-tunnel] Config changed – terminating previous tunnel...");
|
|
382
505
|
try {
|
|
383
506
|
globalState.child.kill("SIGTERM");
|
|
384
507
|
} catch (_) {}
|
|
@@ -387,7 +510,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
387
510
|
delete globalState.configHash;
|
|
388
511
|
globalState.shuttingDown = false;
|
|
389
512
|
if (isQuickMode) {
|
|
390
|
-
|
|
513
|
+
debugLog("[unplugin-cloudflare-tunnel] Starting quick tunnel mode...");
|
|
391
514
|
debugLog("Quick tunnel mode - no API token or hostname required");
|
|
392
515
|
await ensureCloudflaredBinary(bin);
|
|
393
516
|
const localTarget$1 = getLocalTarget(serverHost, port);
|
|
@@ -399,20 +522,33 @@ const unpluginFactory = (options = {}) => {
|
|
|
399
522
|
globalState.child = child;
|
|
400
523
|
globalState.configHash = newConfigHash;
|
|
401
524
|
registerExitHandler();
|
|
402
|
-
|
|
403
|
-
|
|
525
|
+
registerListeningHandler(() => {
|
|
526
|
+
const { host: actualServerHost, port: actualPort } = normalizeAddress(server.httpServer?.address());
|
|
527
|
+
const actualLocalTarget = getLocalTarget(actualServerHost, actualPort ?? port);
|
|
528
|
+
announceTunnel({
|
|
529
|
+
key: `quick:${url}:${actualPort ?? port}`,
|
|
530
|
+
url,
|
|
531
|
+
localTarget: actualLocalTarget
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
registerListeningHandler(async () => {
|
|
404
535
|
try {
|
|
405
536
|
const { host: actualServerHost, port: actualPort } = normalizeAddress(server.httpServer?.address());
|
|
406
537
|
if (actualPort !== port) {
|
|
407
|
-
|
|
408
|
-
|
|
538
|
+
pluginLog.warn(`Port conflict detected - server is using port ${actualPort} instead of ${port}`);
|
|
539
|
+
pluginLog.info("Restarting quick tunnel for the new port...");
|
|
409
540
|
killCloudflared("SIGTERM");
|
|
410
541
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
411
|
-
const
|
|
542
|
+
const newLocalTarget = getLocalTarget(actualServerHost, actualPort ?? port);
|
|
543
|
+
const { child: newChild, url: newUrl } = await spawnQuickTunnel(newLocalTarget);
|
|
412
544
|
tunnelUrl = newUrl;
|
|
413
545
|
child = newChild;
|
|
414
546
|
globalState.child = child;
|
|
415
|
-
|
|
547
|
+
announceTunnel({
|
|
548
|
+
key: `quick:${newUrl}:${actualPort ?? port}`,
|
|
549
|
+
url: newUrl,
|
|
550
|
+
localTarget: newLocalTarget
|
|
551
|
+
});
|
|
416
552
|
globalState.configHash = JSON.stringify({
|
|
417
553
|
isQuickMode,
|
|
418
554
|
hostname,
|
|
@@ -435,10 +571,10 @@ const unpluginFactory = (options = {}) => {
|
|
|
435
571
|
throw error;
|
|
436
572
|
}
|
|
437
573
|
}
|
|
438
|
-
|
|
574
|
+
debugLog("[unplugin-cloudflare-tunnel] Starting named tunnel mode...");
|
|
439
575
|
const apiToken = providedApiToken || process.env.CLOUDFLARE_API_KEY;
|
|
440
576
|
if (!apiToken) throw new Error("[unplugin-cloudflare-tunnel] API token is required. Provide it via 'apiToken' option or set the CLOUDFLARE_API_KEY environment variable. Get your token at: https://dash.cloudflare.com/profile/api-tokens");
|
|
441
|
-
|
|
577
|
+
debugLog(`[unplugin-cloudflare-tunnel] Using port ${port}${userProvidedPort === port ? " (user-provided)" : " (from bundler config)"}`);
|
|
442
578
|
await ensureCloudflaredBinary(bin);
|
|
443
579
|
const accounts = await cf(apiToken, "GET", "/accounts", void 0, z.array(AccountSchema));
|
|
444
580
|
const accountId = forcedAccount || accounts[0]?.id;
|
|
@@ -462,7 +598,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
462
598
|
const { autoCleanup = true } = cleanupConfig;
|
|
463
599
|
let tunnel = (await cf(apiToken, "GET", `/accounts/${accountId}/cfd_tunnel?name=${tunnelName}`, void 0, z.array(TunnelSchema)))[0];
|
|
464
600
|
if (!tunnel) {
|
|
465
|
-
|
|
601
|
+
pluginLog.info(`Creating tunnel '${tunnelName}'...`);
|
|
466
602
|
tunnel = await cf(apiToken, "POST", `/accounts/${accountId}/cfd_tunnel`, {
|
|
467
603
|
name: tunnelName,
|
|
468
604
|
config_src: "cloudflare"
|
|
@@ -470,13 +606,13 @@ const unpluginFactory = (options = {}) => {
|
|
|
470
606
|
}
|
|
471
607
|
const tunnelId = tunnel.id;
|
|
472
608
|
if (autoCleanup) {
|
|
473
|
-
|
|
609
|
+
debugLog(`[unplugin-cloudflare-tunnel] Running resource cleanup for tunnel '${tunnelName}'...`);
|
|
474
610
|
const dnsCleanup = await cleanupMismatchedDnsRecords(apiToken, zoneId, generateDnsComment(), hostname, tunnelId);
|
|
475
|
-
if (dnsCleanup.found.length > 0)
|
|
611
|
+
if (dnsCleanup.found.length > 0) pluginLog.warn(`DNS cleanup: ${dnsCleanup.found.length} mismatched, ${dnsCleanup.deleted.length} deleted`);
|
|
476
612
|
const mismatchedSslCerts = await findMismatchedSslCertificates(apiToken, zoneId, tunnelName, hostname);
|
|
477
613
|
if (mismatchedSslCerts.length > 0) {
|
|
478
614
|
for (const cert of mismatchedSslCerts) await cf(apiToken, "DELETE", `/zones/${zoneId}/ssl/certificate_packs/${cert.id}`);
|
|
479
|
-
|
|
615
|
+
pluginLog.warn(`SSL cleanup: ${mismatchedSslCerts.length} deleted`);
|
|
480
616
|
}
|
|
481
617
|
} else debugLog("← Cleanup skipped", cleanupConfig);
|
|
482
618
|
const localTarget = getLocalTarget(serverHost, port);
|
|
@@ -549,7 +685,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
549
685
|
debugLog("← Total TLS", totalTls);
|
|
550
686
|
const existingHostnameCert = certContainingHost(hostname);
|
|
551
687
|
if (totalTls.status !== "on" && !existingHostnameCert) {
|
|
552
|
-
|
|
688
|
+
pluginLog.info(`Requesting edge certificate for ${hostname}...`);
|
|
553
689
|
const tagHostname = generateSslTagHostname();
|
|
554
690
|
const certificateHosts = [hostname, tagHostname];
|
|
555
691
|
debugLog(`Adding tag hostname to certificate: ${tagHostname}`);
|
|
@@ -574,7 +710,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
574
710
|
if (logFile) cloudflaredArgs.push("--logfile", logFile);
|
|
575
711
|
debugLog("Spawning cloudflared", bin, cloudflaredArgs);
|
|
576
712
|
cloudflaredArgs.push("run", "--token", token);
|
|
577
|
-
child = spawn(bin, cloudflaredArgs, {
|
|
713
|
+
child = NodeChildProcess.spawn(bin, cloudflaredArgs, {
|
|
578
714
|
stdio: [
|
|
579
715
|
"ignore",
|
|
580
716
|
"pipe",
|
|
@@ -584,18 +720,37 @@ const unpluginFactory = (options = {}) => {
|
|
|
584
720
|
windowsHide: true,
|
|
585
721
|
shell: process.platform === "win32"
|
|
586
722
|
});
|
|
587
|
-
|
|
723
|
+
debugLog(`[unplugin-cloudflare-tunnel] Process spawned with PID: ${child.pid}`);
|
|
588
724
|
globalState.child = child;
|
|
589
725
|
globalState.configHash = newConfigHash;
|
|
590
726
|
registerExitHandler();
|
|
591
727
|
let tunnelReady = false;
|
|
728
|
+
const logCloudflaredLines = (kind, text) => {
|
|
729
|
+
if (globalState.shuttingDown && !debug) return;
|
|
730
|
+
const isVerbose = effectiveLogLevel === "debug" || effectiveLogLevel === "info";
|
|
731
|
+
const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
732
|
+
if (isVerbose) {
|
|
733
|
+
for (const line of lines) {
|
|
734
|
+
const prefix = kind === "stdout" ? "[cloudflared stdout]" : "[cloudflared stderr]";
|
|
735
|
+
if (kind === "stdout") console.log(`${prefix} ${line}`);
|
|
736
|
+
else console.error(`${prefix} ${line}`);
|
|
737
|
+
}
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
for (const line of lines) {
|
|
741
|
+
if (INFO_LOG_REGEX.test(line)) continue;
|
|
742
|
+
const prefix = kind === "stdout" ? "[cloudflared stdout]" : "[cloudflared stderr]";
|
|
743
|
+
if (kind === "stdout") console.log(`${prefix} ${line}`);
|
|
744
|
+
else console.error(`${prefix} ${line}`);
|
|
745
|
+
}
|
|
746
|
+
};
|
|
592
747
|
child.stdout?.on("data", (data) => {
|
|
593
748
|
const output = data.toString();
|
|
594
|
-
|
|
749
|
+
logCloudflaredLines("stdout", output);
|
|
595
750
|
if (output.includes("Connection") && output.includes("registered")) {
|
|
596
751
|
if (!tunnelReady) {
|
|
597
752
|
tunnelReady = true;
|
|
598
|
-
|
|
753
|
+
pluginLog.info(`Tunnel connected for https://${hostname}`);
|
|
599
754
|
}
|
|
600
755
|
}
|
|
601
756
|
});
|
|
@@ -605,10 +760,7 @@ const unpluginFactory = (options = {}) => {
|
|
|
605
760
|
if (logLevel === "debug") console.log(`[cloudflared debug] ${error}`);
|
|
606
761
|
return;
|
|
607
762
|
}
|
|
608
|
-
|
|
609
|
-
if (error.toLowerCase().includes("error") || error.toLowerCase().includes("failed") || error.toLowerCase().includes("fatal")) {
|
|
610
|
-
if (!globalState.shuttingDown || debug) console.error(`[unplugin-cloudflare-tunnel] ⚠️ ${error}`);
|
|
611
|
-
}
|
|
763
|
+
logCloudflaredLines("stderr", error);
|
|
612
764
|
});
|
|
613
765
|
child.on("error", (error) => {
|
|
614
766
|
console.error(`[unplugin-cloudflare-tunnel] ❌ Failed to start tunnel process: ${error.message}`);
|
|
@@ -620,25 +772,31 @@ const unpluginFactory = (options = {}) => {
|
|
|
620
772
|
if (signal) console.error(`[unplugin-cloudflare-tunnel] Process terminated by signal: ${signal}`);
|
|
621
773
|
} else if (code === 0) console.log(`[unplugin-cloudflare-tunnel] ✅ Tunnel process exited cleanly`);
|
|
622
774
|
});
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
775
|
+
registerListeningHandler(() => {
|
|
776
|
+
const { host: actualServerHost, port: actualPort } = normalizeAddress(server.httpServer?.address());
|
|
777
|
+
const actualLocalTarget = getLocalTarget(actualServerHost, actualPort ?? port);
|
|
778
|
+
announceTunnel({
|
|
779
|
+
key: `named:${hostname}:${actualPort ?? port}`,
|
|
780
|
+
url: `https://${hostname}`,
|
|
781
|
+
localTarget: actualLocalTarget
|
|
782
|
+
});
|
|
783
|
+
});
|
|
626
784
|
server.httpServer?.once("close", () => {
|
|
627
785
|
killCloudflared("SIGTERM");
|
|
628
786
|
});
|
|
629
|
-
|
|
787
|
+
registerListeningHandler(async () => {
|
|
630
788
|
try {
|
|
631
789
|
const { host: actualServerHost, port: actualPort } = normalizeAddress(server.httpServer?.address());
|
|
632
790
|
if (actualPort !== port) {
|
|
633
|
-
|
|
634
|
-
|
|
791
|
+
pluginLog.warn(`Port conflict detected - server is using port ${actualPort} instead of ${port}`);
|
|
792
|
+
pluginLog.info("Updating tunnel configuration...");
|
|
635
793
|
const newLocalTarget = getLocalTarget(actualServerHost, actualPort ?? port);
|
|
636
794
|
debugLog("← Updating local target to", newLocalTarget);
|
|
637
795
|
await cf(apiToken, "PUT", `/accounts/${accountId}/cfd_tunnel/${tunnelId}/configurations`, { config: { ingress: [{
|
|
638
796
|
hostname,
|
|
639
797
|
service: newLocalTarget
|
|
640
798
|
}, { service: "http_status:404" }] } });
|
|
641
|
-
|
|
799
|
+
pluginLog.info(`Tunnel configuration updated to use port ${actualPort}`);
|
|
642
800
|
globalState.configHash = JSON.stringify({
|
|
643
801
|
hostname,
|
|
644
802
|
port: actualPort,
|
|
@@ -652,27 +810,121 @@ const unpluginFactory = (options = {}) => {
|
|
|
652
810
|
}
|
|
653
811
|
});
|
|
654
812
|
} catch (error) {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
813
|
+
if (error instanceof Error) {
|
|
814
|
+
console.error(`[unplugin-cloudflare-tunnel] ❌ Setup failed: ${error.message}`);
|
|
815
|
+
if (error.message.includes("API token")) {
|
|
816
|
+
console.error(`[unplugin-cloudflare-tunnel] 💡 Check your API token at: https://dash.cloudflare.com/profile/api-tokens`);
|
|
817
|
+
console.error(`[unplugin-cloudflare-tunnel] 💡 Required permissions: Zone:Zone:Read, Zone:DNS:Edit, Account:Cloudflare Tunnel:Edit`);
|
|
818
|
+
} else if (error.message.includes("Zone") && error.message.includes("not found")) console.error(`[unplugin-cloudflare-tunnel] 💡 Make sure '${hostname}' domain is added to your Cloudflare account`);
|
|
819
|
+
else if (error.message.includes("cloudflared")) console.error(`[unplugin-cloudflare-tunnel] 💡 Try deleting node_modules and reinstalling to get a fresh cloudflared binary`);
|
|
820
|
+
}
|
|
661
821
|
throw error;
|
|
662
822
|
}
|
|
663
823
|
};
|
|
824
|
+
const ensureWebpackAllowedHosts = (devServerOptions, bundler) => {
|
|
825
|
+
if (!devServerOptions) return;
|
|
826
|
+
const hostToAllow = isQuickMode ? ".trycloudflare.com" : hostname;
|
|
827
|
+
if (!hostToAllow) return;
|
|
828
|
+
const label = bundler === "webpack" ? "Webpack" : "Rspack";
|
|
829
|
+
const normalizeArray = (values) => {
|
|
830
|
+
const unique = Array.from(new Set(values.filter(Boolean)));
|
|
831
|
+
devServerOptions.allowedHosts = unique;
|
|
832
|
+
return unique;
|
|
833
|
+
};
|
|
834
|
+
let modified = false;
|
|
835
|
+
const current = devServerOptions.allowedHosts;
|
|
836
|
+
if (current === "all") return;
|
|
837
|
+
if (typeof current === "undefined" || current === "auto") {
|
|
838
|
+
normalizeArray(["localhost", hostToAllow]);
|
|
839
|
+
modified = true;
|
|
840
|
+
} else if (typeof current === "string") {
|
|
841
|
+
if (current !== hostToAllow) {
|
|
842
|
+
normalizeArray([current, hostToAllow]);
|
|
843
|
+
modified = true;
|
|
844
|
+
}
|
|
845
|
+
} else if (Array.isArray(current)) {
|
|
846
|
+
if (!current.includes(hostToAllow)) {
|
|
847
|
+
current.push(hostToAllow);
|
|
848
|
+
modified = true;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
if (modified) debugLog(`[unplugin-cloudflare-tunnel] Configured ${label} devServer.allowedHosts to include ${hostToAllow}`);
|
|
852
|
+
};
|
|
853
|
+
const setupWebpackLikeDevServerIntegration = (compiler, bundler) => {
|
|
854
|
+
if ((compiler?.options?.mode ?? process.env.NODE_ENV) === "production") return;
|
|
855
|
+
const optionsContainer = compiler.options;
|
|
856
|
+
if (!optionsContainer.devServer) optionsContainer.devServer = {};
|
|
857
|
+
const devServerOptions = optionsContainer.devServer;
|
|
858
|
+
ensureWebpackAllowedHosts(devServerOptions, bundler);
|
|
859
|
+
let lastHttpServer;
|
|
860
|
+
let missingServerWarned = false;
|
|
861
|
+
const runConfiguration = (devServerInstance) => {
|
|
862
|
+
if (!devServerInstance) {
|
|
863
|
+
if (!missingServerWarned) {
|
|
864
|
+
console.warn(`[unplugin-cloudflare-tunnel] ${bundler} dev server instance unavailable; skipping tunnel setup`);
|
|
865
|
+
missingServerWarned = true;
|
|
866
|
+
}
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
const httpServer = [
|
|
870
|
+
devServerInstance.server,
|
|
871
|
+
devServerInstance.httpServer,
|
|
872
|
+
devServerInstance.listeningApp,
|
|
873
|
+
devServerInstance.server?.server
|
|
874
|
+
].find((candidate) => candidate);
|
|
875
|
+
if (!httpServer) {
|
|
876
|
+
if (!missingServerWarned) {
|
|
877
|
+
console.warn(`[unplugin-cloudflare-tunnel] Unable to locate HTTP server from ${bundler} dev server; tunnel will not start`);
|
|
878
|
+
missingServerWarned = true;
|
|
879
|
+
}
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
if (lastHttpServer === httpServer) return;
|
|
883
|
+
lastHttpServer = httpServer;
|
|
884
|
+
httpServer.once("close", () => {
|
|
885
|
+
if (lastHttpServer === httpServer) lastHttpServer = void 0;
|
|
886
|
+
});
|
|
887
|
+
const configuredPromise = configureServer({
|
|
888
|
+
httpServer,
|
|
889
|
+
config: { server: { port: devServerInstance.options?.port ?? devServerOptions?.port } }
|
|
890
|
+
});
|
|
891
|
+
globalState.tunnelUrl = configuredPromise.then(() => tunnelUrl).catch(() => "");
|
|
892
|
+
configuredPromise.catch(() => {});
|
|
893
|
+
};
|
|
894
|
+
const scheduleConfiguration = (devServerInstance) => {
|
|
895
|
+
const httpServer = devServerInstance?.server || devServerInstance?.httpServer || devServerInstance?.listeningApp;
|
|
896
|
+
if (httpServer && typeof httpServer.once === "function") if (httpServer.listening) runConfiguration(devServerInstance);
|
|
897
|
+
else httpServer.once("listening", () => runConfiguration(devServerInstance));
|
|
898
|
+
else runConfiguration(devServerInstance);
|
|
899
|
+
};
|
|
900
|
+
const originalSetupMiddlewares = devServerOptions.setupMiddlewares;
|
|
901
|
+
devServerOptions.setupMiddlewares = function(middlewares, devServer) {
|
|
902
|
+
scheduleConfiguration(devServer);
|
|
903
|
+
if (typeof originalSetupMiddlewares === "function") return originalSetupMiddlewares.call(this, middlewares, devServer);
|
|
904
|
+
return middlewares;
|
|
905
|
+
};
|
|
906
|
+
const originalOnListening = devServerOptions.onListening;
|
|
907
|
+
devServerOptions.onListening = function(devServer) {
|
|
908
|
+
scheduleConfiguration(devServer);
|
|
909
|
+
if (typeof originalOnListening === "function") return originalOnListening.call(this, devServer);
|
|
910
|
+
};
|
|
911
|
+
};
|
|
664
912
|
return {
|
|
665
|
-
name:
|
|
913
|
+
name: PLUGIN_NAME,
|
|
666
914
|
enforce: "pre",
|
|
667
|
-
resolveId(id) {
|
|
668
|
-
if (id === VIRTUAL_MODULE_ID)
|
|
915
|
+
resolveId: (id) => {
|
|
916
|
+
if (id === VIRTUAL_MODULE_ID) {
|
|
917
|
+
debugLog("resolveId called for", id);
|
|
918
|
+
return "\0" + VIRTUAL_MODULE_ID;
|
|
919
|
+
}
|
|
669
920
|
},
|
|
670
|
-
async
|
|
921
|
+
load: async (id) => {
|
|
671
922
|
const url = await globalState.tunnelUrl;
|
|
672
923
|
if (id === "\0" + VIRTUAL_MODULE_ID) return `export function getTunnelUrl() { return ${JSON.stringify(url || "")}; }`;
|
|
673
924
|
},
|
|
674
925
|
vite: {
|
|
675
|
-
config(config) {
|
|
926
|
+
config: (config) => {
|
|
927
|
+
announceConnecting();
|
|
676
928
|
if (!config.server) config.server = {};
|
|
677
929
|
if (isQuickMode) {
|
|
678
930
|
config.server.allowedHosts = [".trycloudflare.com"];
|
|
@@ -680,15 +932,15 @@ const unpluginFactory = (options = {}) => {
|
|
|
680
932
|
}
|
|
681
933
|
if (!config.server.allowedHosts) {
|
|
682
934
|
config.server.allowedHosts = [hostname];
|
|
683
|
-
|
|
935
|
+
debugLog(`[unplugin-cloudflare-tunnel] Configured Vite to allow requests from ${hostname}`);
|
|
684
936
|
} else if (Array.isArray(config.server.allowedHosts)) {
|
|
685
937
|
if (!config.server.allowedHosts.includes(hostname)) {
|
|
686
938
|
config.server.allowedHosts.push(hostname);
|
|
687
|
-
|
|
939
|
+
debugLog(`[unplugin-cloudflare-tunnel] Added ${hostname} to allowed hosts`);
|
|
688
940
|
}
|
|
689
941
|
}
|
|
690
942
|
},
|
|
691
|
-
configureServer(server) {
|
|
943
|
+
configureServer: (server) => {
|
|
692
944
|
const configuredPromise = configureServer(server);
|
|
693
945
|
globalState.tunnelUrl = configuredPromise.then(() => tunnelUrl).catch(() => "");
|
|
694
946
|
return async () => {
|
|
@@ -696,6 +948,12 @@ const unpluginFactory = (options = {}) => {
|
|
|
696
948
|
};
|
|
697
949
|
}
|
|
698
950
|
},
|
|
951
|
+
rspack: (compiler) => {
|
|
952
|
+
setupWebpackLikeDevServerIntegration(compiler, "rspack");
|
|
953
|
+
},
|
|
954
|
+
webpack: (compiler) => {
|
|
955
|
+
setupWebpackLikeDevServerIntegration(compiler, "webpack");
|
|
956
|
+
},
|
|
699
957
|
closeBundle() {
|
|
700
958
|
killCloudflared("SIGTERM");
|
|
701
959
|
delete globalState.child;
|
|
@@ -713,7 +971,7 @@ function normalizeAddress(address) {
|
|
|
713
971
|
}
|
|
714
972
|
async function ensureCloudflaredBinary(binPath) {
|
|
715
973
|
try {
|
|
716
|
-
await
|
|
974
|
+
await NodeFS.access(binPath);
|
|
717
975
|
} catch {
|
|
718
976
|
console.log("[unplugin-cloudflare-tunnel] Installing cloudflared binary...");
|
|
719
977
|
await install(binPath);
|
package/dist/vite.d.ts
CHANGED
package/dist/vite.js
CHANGED
package/dist/webpack.d.ts
CHANGED
package/dist/webpack.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unplugin-cloudflare-tunnel",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"packageManager": "bun@1.3.
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"packageManager": "bun@1.3.5",
|
|
5
5
|
"description": "A plugin that automatically creates and manages Cloudflare tunnels for local development",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"imports": {
|
|
@@ -51,28 +51,27 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"cloudflared": "^0.7.1",
|
|
53
53
|
"unplugin": "^2.3.10",
|
|
54
|
-
"
|
|
55
|
-
"zod": "^4.1.12"
|
|
54
|
+
"zod": "^4.2.1"
|
|
56
55
|
},
|
|
57
56
|
"devDependencies": {
|
|
58
57
|
"@arethetypeswrong/core": "^0.18.2",
|
|
59
|
-
"@biomejs/biome": "^2.3.
|
|
60
|
-
"@changesets/changelog-github": "^0.5.
|
|
61
|
-
"@changesets/cli": "^2.29.
|
|
58
|
+
"@biomejs/biome": "^2.3.10",
|
|
59
|
+
"@changesets/changelog-github": "^0.5.2",
|
|
60
|
+
"@changesets/cli": "^2.29.8",
|
|
62
61
|
"@rspack/core": "^1.5.7",
|
|
63
|
-
"@sxzz/test-utils": "^0.5.
|
|
62
|
+
"@sxzz/test-utils": "^0.5.15",
|
|
64
63
|
"@total-typescript/ts-reset": "^0.6.1",
|
|
65
|
-
"@types/bun": "^1.3.
|
|
66
|
-
"@types/node": "^
|
|
67
|
-
"execa": "^9.6.
|
|
68
|
-
"publint": "^0.3.
|
|
64
|
+
"@types/bun": "^1.3.5",
|
|
65
|
+
"@types/node": "^25.0.3",
|
|
66
|
+
"execa": "^9.6.1",
|
|
67
|
+
"publint": "^0.3.16",
|
|
69
68
|
"rollup": "^4.52.3",
|
|
70
|
-
"tsdown": "^0.15.
|
|
71
|
-
"tsx": "^4.
|
|
69
|
+
"tsdown": "^0.15.12",
|
|
70
|
+
"tsx": "^4.21.0",
|
|
72
71
|
"typescript": "^5.9.3",
|
|
73
|
-
"unplugin-unused": "^0.5.
|
|
72
|
+
"unplugin-unused": "^0.5.6",
|
|
74
73
|
"vite": "^7.1.12",
|
|
75
|
-
"vitest": "^4.0.
|
|
74
|
+
"vitest": "^4.0.16",
|
|
76
75
|
"webpack-dev-server": "^5.2.2"
|
|
77
76
|
},
|
|
78
77
|
"peerDependencies": {
|
|
@@ -111,7 +110,7 @@
|
|
|
111
110
|
}
|
|
112
111
|
},
|
|
113
112
|
"engines": {
|
|
114
|
-
"node": ">=20.
|
|
113
|
+
"node": ">=20.0"
|
|
115
114
|
},
|
|
116
115
|
"keywords": [
|
|
117
116
|
"unplugin",
|
|
@@ -126,6 +125,7 @@
|
|
|
126
125
|
],
|
|
127
126
|
"license": "MIT",
|
|
128
127
|
"repository": "o-az/unplugin-cloudflare-tunnel",
|
|
128
|
+
"readme": "https://github.com/o-az/unplugin-cloudflare-tunnel/blob/main/.github/README.md",
|
|
129
129
|
"author": "Omar A <gh@omar.mov>",
|
|
130
130
|
"publishConfig": {
|
|
131
131
|
"access": "public"
|