wp-studio 1.7.7-alpha1

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.
Files changed (48) hide show
  1. package/LICENSE.md +257 -0
  2. package/README.md +87 -0
  3. package/dist/cli/_events-BeOo0LuG.js +116 -0
  4. package/dist/cli/appdata-07CF2rhg.js +21090 -0
  5. package/dist/cli/archive-xDmkN4wb.js +15942 -0
  6. package/dist/cli/browser-CgWK-yoe.js +44 -0
  7. package/dist/cli/certificate-manager-DdBumKZp.js +250 -0
  8. package/dist/cli/create-BHVhkvTx.js +80 -0
  9. package/dist/cli/create-ZS29BDDi.js +40999 -0
  10. package/dist/cli/delete-BgQn-elT.js +56 -0
  11. package/dist/cli/delete-g8pgaLna.js +132 -0
  12. package/dist/cli/get-wordpress-version-BwSCJujO.js +18 -0
  13. package/dist/cli/index-7pbG_s_U.js +434 -0
  14. package/dist/cli/index-BXRYeCYG.js +1393 -0
  15. package/dist/cli/index-T3F1GwxX.js +2668 -0
  16. package/dist/cli/is-errno-exception-t38xF2pB.js +6 -0
  17. package/dist/cli/list-BE_UBjL5.js +105 -0
  18. package/dist/cli/list-DKz0XxM7.js +1032 -0
  19. package/dist/cli/logger-actions-OaIvl-ai.js +45 -0
  20. package/dist/cli/login-B4PkfKOu.js +82 -0
  21. package/dist/cli/logout-BC9gKlTj.js +48 -0
  22. package/dist/cli/main.js +5 -0
  23. package/dist/cli/mu-plugins-GEfKsl5U.js +530 -0
  24. package/dist/cli/passwords-DyzWd9Xi.js +80 -0
  25. package/dist/cli/process-manager-daemon.js +327 -0
  26. package/dist/cli/process-manager-ipc-AUZeYYDT.js +454 -0
  27. package/dist/cli/proxy-daemon.js +197 -0
  28. package/dist/cli/run-wp-cli-command-BctnMDWG.js +88 -0
  29. package/dist/cli/sequential-BQFuixXz.js +46 -0
  30. package/dist/cli/server-files-C_oy-mnI.js +26 -0
  31. package/dist/cli/set-DknhAZpw.js +327 -0
  32. package/dist/cli/site-utils-CfsabjUn.js +243 -0
  33. package/dist/cli/snapshots-6XE53y_F.js +874 -0
  34. package/dist/cli/sqlite-integration-H4OwSlwR.js +83 -0
  35. package/dist/cli/start-CRJqm09_.js +90 -0
  36. package/dist/cli/status-CWNHIOaY.js +44 -0
  37. package/dist/cli/status-CWWx9jYF.js +110 -0
  38. package/dist/cli/stop-CQosmjqA.js +117 -0
  39. package/dist/cli/update-BgL2HKHW.js +101 -0
  40. package/dist/cli/validation-error-DqLxqQuA.js +40 -0
  41. package/dist/cli/wordpress-server-child.js +514 -0
  42. package/dist/cli/wordpress-server-ipc-Dwsg9jSb.js +140 -0
  43. package/dist/cli/wordpress-server-manager-CtiuJqEb.js +566 -0
  44. package/dist/cli/wordpress-version-utils-B6UVeTh_.js +51 -0
  45. package/dist/cli/wp-UGSnlkN0.js +103 -0
  46. package/package.json +73 -0
  47. package/patches/@wp-playground+wordpress+3.1.12.patch +28 -0
  48. package/scripts/postinstall-npm.mjs +38 -0
@@ -0,0 +1,454 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ import { EventEmitter } from "events";
4
+ import fs from "fs";
5
+ import net from "net";
6
+ import { i as isErrnoException } from "./is-errno-exception-t38xF2pB.js";
7
+ import { z } from "zod";
8
+ import { c as childMessageFromProcessManagerSchema, m as managerMessageSchema } from "./wordpress-server-ipc-Dwsg9jSb.js";
9
+ const PROCESS_MANAGER_HOME = process.env.STUDIO_PROCESS_MANAGER_HOME ?? path.join(os.homedir(), ".studio", "pm2");
10
+ const PROCESS_MANAGER_LOGS_DIR = path.join(PROCESS_MANAGER_HOME, "logs");
11
+ const PROCESS_MANAGER_CONTROL_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\studio-daemon.sock" : path.join(PROCESS_MANAGER_HOME, "daemon.sock");
12
+ const PROCESS_MANAGER_EVENTS_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\studio-daemon-events.sock" : path.join(PROCESS_MANAGER_HOME, "daemon-events.sock");
13
+ const DEFAULT_CONNECT_TIMEOUT_MS = 500;
14
+ const DEFAULT_RECONNECT_DELAY_MS = 500;
15
+ function isWindowsNamedPipe(endpoint) {
16
+ return endpoint.startsWith("\\\\.\\pipe\\");
17
+ }
18
+ function isUnixSocketPath(endpoint) {
19
+ return !isWindowsNamedPipe(endpoint);
20
+ }
21
+ function encodeSocketMessage(message) {
22
+ const json = JSON.stringify(message);
23
+ const body = Buffer.from(json, "utf8");
24
+ const header = Buffer.allocUnsafe(4);
25
+ header.writeUInt32BE(body.length, 0);
26
+ return Buffer.concat([header, body]);
27
+ }
28
+ class SocketMessageDecoder {
29
+ constructor() {
30
+ this.buffer = Buffer.alloc(0);
31
+ }
32
+ write(chunk) {
33
+ this.buffer = Buffer.concat([this.buffer, chunk]);
34
+ const messages = [];
35
+ while (this.buffer.length >= 4) {
36
+ const length = this.buffer.readUInt32BE(0);
37
+ if (this.buffer.length < 4 + length) {
38
+ break;
39
+ }
40
+ const payload = this.buffer.subarray(4, 4 + length);
41
+ this.buffer = this.buffer.subarray(4 + length);
42
+ messages.push(JSON.parse(payload.toString("utf8")));
43
+ }
44
+ return messages;
45
+ }
46
+ }
47
+ async function connectToEndpoint(peer, connectTimeoutMs) {
48
+ let timeoutId;
49
+ const socket = net.createConnection(peer);
50
+ return new Promise((resolve, reject) => {
51
+ timeoutId = setTimeout(() => {
52
+ socket.destroy();
53
+ reject(new Error(`Socket connect timeout: ${peer}`));
54
+ }, connectTimeoutMs);
55
+ socket.once("connect", () => {
56
+ resolve(socket);
57
+ });
58
+ socket.once("error", (error) => {
59
+ reject(error);
60
+ });
61
+ }).finally(() => {
62
+ clearTimeout(timeoutId);
63
+ socket.removeAllListeners();
64
+ });
65
+ }
66
+ class SocketClientEventEmitter extends EventEmitter {
67
+ on(event, listener) {
68
+ return super.on(event, listener);
69
+ }
70
+ emit(event, payload) {
71
+ return super.emit(event, payload);
72
+ }
73
+ }
74
+ class SocketStreamClient extends SocketClientEventEmitter {
75
+ constructor(endpoint, connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MS) {
76
+ super();
77
+ this.socket = null;
78
+ this.connectPromise = null;
79
+ this.reconnectTimer = null;
80
+ this.closedByClient = false;
81
+ this.endpoint = endpoint;
82
+ this.connectTimeoutMs = connectTimeoutMs;
83
+ this.reconnectDelayMs = DEFAULT_RECONNECT_DELAY_MS;
84
+ }
85
+ async connect() {
86
+ this.closedByClient = false;
87
+ if (this.isConnected()) {
88
+ return this.socket;
89
+ }
90
+ if (this.connectPromise) {
91
+ return this.connectPromise;
92
+ }
93
+ this.connectPromise = connectToEndpoint(this.endpoint, this.connectTimeoutMs).then((socket) => {
94
+ this.attachPersistentSocketListeners(socket);
95
+ this.emit("connect", { socket });
96
+ return socket;
97
+ }).finally(() => {
98
+ this.connectPromise = null;
99
+ });
100
+ return this.connectPromise;
101
+ }
102
+ isConnected() {
103
+ return this.socket !== null && !this.socket.destroyed;
104
+ }
105
+ async close() {
106
+ this.closedByClient = true;
107
+ if (this.reconnectTimer) {
108
+ clearTimeout(this.reconnectTimer);
109
+ this.reconnectTimer = null;
110
+ }
111
+ const socket = this.socket;
112
+ this.socket = null;
113
+ if (socket && !socket.destroyed) {
114
+ await new Promise((resolve) => {
115
+ socket.once("close", () => resolve());
116
+ socket.end();
117
+ });
118
+ }
119
+ }
120
+ scheduleReconnect() {
121
+ if (this.closedByClient || this.reconnectTimer) {
122
+ return;
123
+ }
124
+ this.emit("reconnecting", { delayMs: this.reconnectDelayMs });
125
+ this.reconnectTimer = setTimeout(() => {
126
+ this.reconnectTimer = null;
127
+ void this.connect().catch(() => {
128
+ this.scheduleReconnect();
129
+ });
130
+ }, this.reconnectDelayMs);
131
+ }
132
+ attachPersistentSocketListeners(socket) {
133
+ this.socket = socket;
134
+ socket.on("data", (chunk) => {
135
+ this.emit("data", { chunk, socket });
136
+ });
137
+ socket.on("error", (error) => {
138
+ this.emit("error", { error });
139
+ });
140
+ socket.on("close", (hadError) => {
141
+ if (this.socket === socket) {
142
+ this.socket = null;
143
+ }
144
+ this.emit("close", { hadError });
145
+ this.scheduleReconnect();
146
+ });
147
+ }
148
+ }
149
+ class SocketRequestClient {
150
+ constructor(endpoint, connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MS) {
151
+ this.queue = Promise.resolve();
152
+ this.endpoint = endpoint;
153
+ this.connectTimeoutMs = connectTimeoutMs;
154
+ }
155
+ send(message) {
156
+ const payload = encodeSocketMessage(message);
157
+ const sendPromise = this.queue.then(async () => {
158
+ const socket = await connectToEndpoint(this.endpoint, this.connectTimeoutMs);
159
+ await this.sendToSocket(socket, payload);
160
+ });
161
+ this.queue = sendPromise.catch(() => void 0);
162
+ return sendPromise;
163
+ }
164
+ async sendToSocket(socket, payload) {
165
+ return new Promise((resolve, reject) => {
166
+ socket.once("error", (error) => {
167
+ reject(error);
168
+ });
169
+ socket.once("close", () => {
170
+ resolve();
171
+ });
172
+ if (socket.destroyed) {
173
+ reject(new Error(`Socket closed before send: ${this.endpoint}`));
174
+ return;
175
+ }
176
+ socket.end(payload);
177
+ }).finally(() => {
178
+ socket.removeAllListeners();
179
+ });
180
+ }
181
+ sendAndWaitForResponse(message) {
182
+ const payload = encodeSocketMessage(message);
183
+ const responsePromise = this.queue.then(async () => {
184
+ const socket = await connectToEndpoint(this.endpoint, this.connectTimeoutMs);
185
+ return this.sendAndReadFromSocket(socket, payload);
186
+ });
187
+ this.queue = responsePromise.then(
188
+ () => void 0,
189
+ () => void 0
190
+ );
191
+ return responsePromise;
192
+ }
193
+ async sendAndReadFromSocket(socket, payload) {
194
+ const decoder = new SocketMessageDecoder();
195
+ return new Promise((resolve, reject) => {
196
+ socket.once("error", (error) => {
197
+ reject(error);
198
+ });
199
+ socket.on("data", (chunk) => {
200
+ try {
201
+ for (const message of decoder.write(chunk)) {
202
+ resolve(message);
203
+ return;
204
+ }
205
+ } catch (error) {
206
+ reject(error);
207
+ }
208
+ });
209
+ socket.once("close", () => {
210
+ reject(new Error(`Socket closed before response: ${this.endpoint}`));
211
+ });
212
+ if (socket.destroyed) {
213
+ reject(new Error(`Socket closed before send: ${this.endpoint}`));
214
+ return;
215
+ }
216
+ socket.write(payload);
217
+ }).finally(() => {
218
+ socket.removeAllListeners();
219
+ socket.end();
220
+ });
221
+ }
222
+ }
223
+ class SocketServerEventEmitter extends EventEmitter {
224
+ on(event, listener) {
225
+ return super.on(event, listener);
226
+ }
227
+ emit(event, payload) {
228
+ return super.emit(event, payload);
229
+ }
230
+ }
231
+ class SocketServer extends SocketServerEventEmitter {
232
+ constructor(endpoint, connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MS) {
233
+ super();
234
+ this.sockets = /* @__PURE__ */ new Set();
235
+ this.endpoint = endpoint;
236
+ this.connectTimeoutMs = connectTimeoutMs;
237
+ this.server = net.createServer((socket) => {
238
+ this.sockets.add(socket);
239
+ const decoder = new SocketMessageDecoder();
240
+ socket.on("data", (chunk) => {
241
+ try {
242
+ for (const message of decoder.write(chunk)) {
243
+ this.emit("message", { message, socket });
244
+ }
245
+ } catch (error) {
246
+ this.emit("message-error", { error });
247
+ }
248
+ });
249
+ socket.on("close", () => {
250
+ this.sockets.delete(socket);
251
+ });
252
+ socket.on("error", () => {
253
+ this.sockets.delete(socket);
254
+ });
255
+ });
256
+ }
257
+ async listen() {
258
+ try {
259
+ await this.attemptServerListen();
260
+ } catch (bindError) {
261
+ const isRecoverableInUse = isErrnoException(bindError) && bindError.code === "EADDRINUSE" && isUnixSocketPath(this.endpoint);
262
+ if (!isRecoverableInUse) {
263
+ throw bindError;
264
+ }
265
+ const activeServerExists = await this.canConnectUsingClient();
266
+ if (activeServerExists) {
267
+ throw bindError;
268
+ }
269
+ try {
270
+ fs.unlinkSync(this.endpoint);
271
+ } catch (unlinkError) {
272
+ if (isErrnoException(unlinkError) && unlinkError.code !== "ENOENT") {
273
+ throw unlinkError;
274
+ }
275
+ }
276
+ await this.attemptServerListen();
277
+ }
278
+ }
279
+ sendAndClose(socket, message) {
280
+ socket.end(encodeSocketMessage(message));
281
+ }
282
+ send(socket, message) {
283
+ socket.write(encodeSocketMessage(message));
284
+ }
285
+ broadcast(message) {
286
+ const payload = encodeSocketMessage(message);
287
+ for (const socket of this.sockets) {
288
+ if (!socket.destroyed) {
289
+ socket.write(payload);
290
+ }
291
+ }
292
+ }
293
+ async attemptServerListen() {
294
+ let timeoutId;
295
+ return new Promise((resolve, reject) => {
296
+ timeoutId = setTimeout(() => {
297
+ reject(new Error("Socket bind timeout"));
298
+ }, this.connectTimeoutMs);
299
+ this.server.once("error", (error) => {
300
+ reject(error);
301
+ });
302
+ this.server.once("listening", () => {
303
+ resolve();
304
+ });
305
+ this.server.listen(this.endpoint);
306
+ }).finally(() => {
307
+ this.server.removeAllListeners("error");
308
+ this.server.removeAllListeners("listening");
309
+ clearTimeout(timeoutId);
310
+ });
311
+ }
312
+ async canConnectUsingClient(timeoutMs = DEFAULT_CONNECT_TIMEOUT_MS) {
313
+ let timeoutId;
314
+ const socket = net.createConnection(this.endpoint);
315
+ return new Promise((resolve) => {
316
+ timeoutId = setTimeout(() => {
317
+ socket.destroy();
318
+ resolve(false);
319
+ }, timeoutMs);
320
+ socket.once("connect", () => {
321
+ socket.destroy();
322
+ resolve(true);
323
+ });
324
+ socket.once("error", () => {
325
+ resolve(false);
326
+ });
327
+ }).finally(() => {
328
+ clearTimeout(timeoutId);
329
+ });
330
+ }
331
+ close() {
332
+ return new Promise((resolve) => {
333
+ for (const socket of this.sockets) {
334
+ socket.destroy();
335
+ }
336
+ if (!this.server.listening) {
337
+ resolve();
338
+ return;
339
+ }
340
+ this.server.close(() => {
341
+ resolve();
342
+ });
343
+ });
344
+ }
345
+ }
346
+ const processDescriptionSchemaBase = z.object({
347
+ name: z.string(),
348
+ pmId: z.number()
349
+ });
350
+ const processDescriptionSchemaRunning = processDescriptionSchemaBase.extend({
351
+ status: z.literal("online"),
352
+ pid: z.number()
353
+ });
354
+ const processDescriptionSchemaStopped = processDescriptionSchemaBase.extend({
355
+ status: z.literal("stopped")
356
+ });
357
+ const processDescriptionSchema = z.discriminatedUnion("status", [
358
+ processDescriptionSchemaRunning,
359
+ processDescriptionSchemaStopped
360
+ ]);
361
+ const daemonRequestPingSchema = z.object({
362
+ type: z.literal("ping")
363
+ });
364
+ const daemonRequestStartProcessSchema = z.object({
365
+ type: z.literal("start-process"),
366
+ processName: z.string(),
367
+ scriptPath: z.string(),
368
+ env: z.record(z.string(), z.string()).optional(),
369
+ args: z.array(z.string()).optional()
370
+ });
371
+ const daemonRequestStopProcessSchema = z.object({
372
+ type: z.literal("stop-process"),
373
+ processName: z.string()
374
+ });
375
+ const daemonRequestListProcessesSchema = z.object({
376
+ type: z.literal("list-processes")
377
+ });
378
+ const daemonRequestSendMessageToProcessSchema = z.object({
379
+ type: z.literal("send-message-to-process"),
380
+ processId: z.number(),
381
+ message: managerMessageSchema
382
+ });
383
+ const daemonRequestKillSchema = z.object({
384
+ type: z.literal("kill-daemon")
385
+ });
386
+ const daemonRequestSchema = z.discriminatedUnion("type", [
387
+ daemonRequestPingSchema,
388
+ daemonRequestStartProcessSchema,
389
+ daemonRequestStopProcessSchema,
390
+ daemonRequestListProcessesSchema,
391
+ daemonRequestSendMessageToProcessSchema,
392
+ daemonRequestKillSchema
393
+ ]);
394
+ const daemonResponseResultSchema = z.object({
395
+ type: z.literal("result"),
396
+ payload: z.unknown()
397
+ });
398
+ const daemonResponseErrorSchema = z.object({
399
+ type: z.literal("error"),
400
+ error: z.object({
401
+ message: z.string(),
402
+ stack: z.string().optional()
403
+ })
404
+ });
405
+ const daemonResponseSchema = z.discriminatedUnion("type", [
406
+ daemonResponseResultSchema,
407
+ daemonResponseErrorSchema
408
+ ]);
409
+ const processEventSchema = z.object({
410
+ process: z.object({
411
+ name: z.string(),
412
+ pm_id: z.number()
413
+ }),
414
+ event: z.union([
415
+ z.literal("delete"),
416
+ z.literal("exit"),
417
+ z.literal("online"),
418
+ z.literal("restart"),
419
+ z.literal("stop")
420
+ ])
421
+ });
422
+ const daemonProcessEventSchema = z.object({
423
+ type: z.literal("process-event"),
424
+ payload: processEventSchema
425
+ });
426
+ const daemonProcessMessageSchema = z.object({
427
+ type: z.literal("process-message"),
428
+ payload: childMessageFromProcessManagerSchema
429
+ });
430
+ const daemonKillEventSchema = z.object({
431
+ type: z.literal("daemon-kill"),
432
+ payload: z.object({
433
+ reason: z.string().optional()
434
+ })
435
+ });
436
+ const daemonEventSchema = z.discriminatedUnion("type", [
437
+ daemonProcessEventSchema,
438
+ daemonProcessMessageSchema,
439
+ daemonKillEventSchema
440
+ ]);
441
+ export {
442
+ PROCESS_MANAGER_CONTROL_SOCKET_PATH as P,
443
+ SocketServer as S,
444
+ PROCESS_MANAGER_EVENTS_SOCKET_PATH as a,
445
+ PROCESS_MANAGER_LOGS_DIR as b,
446
+ daemonEventSchema as c,
447
+ daemonRequestSchema as d,
448
+ SocketRequestClient as e,
449
+ daemonResponseSchema as f,
450
+ PROCESS_MANAGER_HOME as g,
451
+ SocketMessageDecoder as h,
452
+ SocketStreamClient as i,
453
+ processDescriptionSchema as p
454
+ };
@@ -0,0 +1,197 @@
1
+ import require$$0 from "http";
2
+ import require$$1 from "https";
3
+ import { createSecureContext } from "node:tls";
4
+ import { domainToASCII } from "node:url";
5
+ import httpProxy from "http-proxy";
6
+ import { r as readAppdata } from "./appdata-07CF2rhg.js";
7
+ import { g as generateSiteCertificate } from "./certificate-manager-DdBumKZp.js";
8
+ let httpProxyServer = null;
9
+ let httpsProxyServer = null;
10
+ let isHttpProxyRunning = false;
11
+ let isHttpsProxyRunning = false;
12
+ const proxy = httpProxy.createProxyServer();
13
+ proxy.on("error", (err, req, res) => {
14
+ console.error("[Proxy Error]", err.message);
15
+ if (res && res instanceof require$$0.ServerResponse) {
16
+ res.writeHead(500, { "Content-Type": "text/plain" });
17
+ res.end("Proxy error: " + err.message);
18
+ }
19
+ });
20
+ async function getSiteByHost(domain) {
21
+ try {
22
+ const appdata = await readAppdata();
23
+ const site = appdata.sites.find(
24
+ (site2) => domainToASCII(site2.customDomain ?? "") === domainToASCII(domain)
25
+ );
26
+ return site ?? null;
27
+ } catch (error) {
28
+ console.error("[Proxy] Error looking up domain:", error);
29
+ return null;
30
+ }
31
+ }
32
+ function handleHealthCheck(res) {
33
+ res.writeHead(200, { "Content-Type": "application/json" });
34
+ res.end(
35
+ JSON.stringify({
36
+ status: "ok",
37
+ http: isHttpProxyRunning,
38
+ https: isHttpsProxyRunning,
39
+ timestamp: Date.now()
40
+ })
41
+ );
42
+ }
43
+ async function handleProxyRequest(req, res, isHttps) {
44
+ if (req.url === "/__studio_health") {
45
+ return handleHealthCheck(res);
46
+ }
47
+ const host = req.headers.host?.split(":")[0];
48
+ if (!host) {
49
+ console.log("[Proxy] No host header found");
50
+ res.writeHead(404, { "Content-Type": "text/plain" });
51
+ res.end("No host header found");
52
+ return;
53
+ }
54
+ const site = await getSiteByHost(host);
55
+ if (!site) {
56
+ console.log(`[Proxy] Domain not found: ${host}`);
57
+ res.writeHead(404, { "Content-Type": "text/plain" });
58
+ res.end(`Domain not found: ${host}`);
59
+ return;
60
+ }
61
+ if (!isHttps && site.enableHttps) {
62
+ res.writeHead(301, {
63
+ Location: `https://${host}${req.url}`
64
+ });
65
+ res.end();
66
+ return;
67
+ }
68
+ const headers = {};
69
+ if (isHttps) {
70
+ headers["X-Forwarded-Proto"] = "https";
71
+ }
72
+ proxy.web(req, res, {
73
+ target: `http://localhost:${site.port}`,
74
+ xfwd: true,
75
+ // Pass along x-forwarded headers
76
+ headers
77
+ });
78
+ }
79
+ async function startHttpProxy() {
80
+ if (isHttpProxyRunning) {
81
+ console.log("[Proxy] HTTP proxy already running");
82
+ return;
83
+ }
84
+ return new Promise((resolve, reject) => {
85
+ httpProxyServer = require$$0.createServer((req, res) => handleProxyRequest(req, res, false));
86
+ httpProxyServer.listen(80, () => {
87
+ console.log("[Proxy] HTTP server started on port 80");
88
+ isHttpProxyRunning = true;
89
+ resolve();
90
+ }).on("error", (err) => {
91
+ console.error("[Proxy] Error starting HTTP server:", err);
92
+ reject(err);
93
+ });
94
+ });
95
+ }
96
+ async function startHttpsProxy() {
97
+ if (isHttpsProxyRunning) {
98
+ console.log("[Proxy] HTTPS proxy already running");
99
+ return;
100
+ }
101
+ return new Promise((resolve, reject) => {
102
+ const defaultOptions = {
103
+ SNICallback: async (servername, cb) => {
104
+ try {
105
+ const site = await getSiteByHost(servername);
106
+ if (!site || !site.customDomain || !site.enableHttps) {
107
+ console.error(`[Proxy] SNI: Invalid hostname: ${servername}`);
108
+ cb(new Error(`Invalid hostname: ${servername}`));
109
+ return;
110
+ }
111
+ const { cert, key } = await generateSiteCertificate(site.customDomain);
112
+ const ctx = createSecureContext({
113
+ key,
114
+ cert,
115
+ minVersion: "TLSv1.2"
116
+ });
117
+ cb(null, ctx);
118
+ } catch (error) {
119
+ console.error(`[Proxy] SNI callback error for ${servername}:`, error);
120
+ cb(error);
121
+ }
122
+ }
123
+ };
124
+ httpsProxyServer = require$$1.createServer(
125
+ defaultOptions,
126
+ (req, res) => handleProxyRequest(req, res, true)
127
+ );
128
+ httpsProxyServer.listen(443, () => {
129
+ console.log("[Proxy] HTTPS server started on port 443");
130
+ isHttpsProxyRunning = true;
131
+ resolve();
132
+ }).on("error", (err) => {
133
+ console.error("[Proxy] Error starting HTTPS server:", err);
134
+ reject(err);
135
+ });
136
+ });
137
+ }
138
+ async function stopProxyServers() {
139
+ console.log("[Proxy] Stopping proxy servers…");
140
+ const promises = [];
141
+ if (httpProxyServer) {
142
+ promises.push(
143
+ new Promise((resolve) => {
144
+ httpProxyServer.close(() => {
145
+ httpProxyServer = null;
146
+ isHttpProxyRunning = false;
147
+ console.log("[Proxy] HTTP server stopped");
148
+ resolve();
149
+ });
150
+ })
151
+ );
152
+ }
153
+ if (httpsProxyServer) {
154
+ promises.push(
155
+ new Promise((resolve) => {
156
+ httpsProxyServer.close(() => {
157
+ httpsProxyServer = null;
158
+ isHttpsProxyRunning = false;
159
+ console.log("[Proxy] HTTPS server stopped");
160
+ resolve();
161
+ });
162
+ })
163
+ );
164
+ }
165
+ await Promise.all(promises);
166
+ console.log("[Proxy] All servers stopped");
167
+ }
168
+ async function startProxyServers() {
169
+ console.log("[Proxy] Starting WordPress Studio Proxy Server…");
170
+ const shutdown = async (signal) => {
171
+ console.log(`[Proxy] Received ${signal}, shutting down gracefully...`);
172
+ await stopProxyServers();
173
+ process.exit(0);
174
+ };
175
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
176
+ process.on("SIGINT", () => shutdown("SIGINT"));
177
+ try {
178
+ await startHttpProxy();
179
+ await startHttpsProxy();
180
+ console.log("[Proxy] Proxy servers started successfully");
181
+ console.log("[Proxy] Ready to handle custom domain requests");
182
+ process.stdin.resume();
183
+ } catch (error) {
184
+ console.error("[Proxy] Failed to start proxy servers:", error);
185
+ throw error;
186
+ }
187
+ }
188
+ async function main() {
189
+ try {
190
+ console.log("[Proxy Daemon] Starting WordPress Studio Proxy Daemon…");
191
+ await startProxyServers();
192
+ } catch (error) {
193
+ console.error("[Proxy Daemon] Failed to start:", error);
194
+ process.exit(1);
195
+ }
196
+ }
197
+ void main();