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.
- package/LICENSE.md +257 -0
- package/README.md +87 -0
- package/dist/cli/_events-BeOo0LuG.js +116 -0
- package/dist/cli/appdata-07CF2rhg.js +21090 -0
- package/dist/cli/archive-xDmkN4wb.js +15942 -0
- package/dist/cli/browser-CgWK-yoe.js +44 -0
- package/dist/cli/certificate-manager-DdBumKZp.js +250 -0
- package/dist/cli/create-BHVhkvTx.js +80 -0
- package/dist/cli/create-ZS29BDDi.js +40999 -0
- package/dist/cli/delete-BgQn-elT.js +56 -0
- package/dist/cli/delete-g8pgaLna.js +132 -0
- package/dist/cli/get-wordpress-version-BwSCJujO.js +18 -0
- package/dist/cli/index-7pbG_s_U.js +434 -0
- package/dist/cli/index-BXRYeCYG.js +1393 -0
- package/dist/cli/index-T3F1GwxX.js +2668 -0
- package/dist/cli/is-errno-exception-t38xF2pB.js +6 -0
- package/dist/cli/list-BE_UBjL5.js +105 -0
- package/dist/cli/list-DKz0XxM7.js +1032 -0
- package/dist/cli/logger-actions-OaIvl-ai.js +45 -0
- package/dist/cli/login-B4PkfKOu.js +82 -0
- package/dist/cli/logout-BC9gKlTj.js +48 -0
- package/dist/cli/main.js +5 -0
- package/dist/cli/mu-plugins-GEfKsl5U.js +530 -0
- package/dist/cli/passwords-DyzWd9Xi.js +80 -0
- package/dist/cli/process-manager-daemon.js +327 -0
- package/dist/cli/process-manager-ipc-AUZeYYDT.js +454 -0
- package/dist/cli/proxy-daemon.js +197 -0
- package/dist/cli/run-wp-cli-command-BctnMDWG.js +88 -0
- package/dist/cli/sequential-BQFuixXz.js +46 -0
- package/dist/cli/server-files-C_oy-mnI.js +26 -0
- package/dist/cli/set-DknhAZpw.js +327 -0
- package/dist/cli/site-utils-CfsabjUn.js +243 -0
- package/dist/cli/snapshots-6XE53y_F.js +874 -0
- package/dist/cli/sqlite-integration-H4OwSlwR.js +83 -0
- package/dist/cli/start-CRJqm09_.js +90 -0
- package/dist/cli/status-CWNHIOaY.js +44 -0
- package/dist/cli/status-CWWx9jYF.js +110 -0
- package/dist/cli/stop-CQosmjqA.js +117 -0
- package/dist/cli/update-BgL2HKHW.js +101 -0
- package/dist/cli/validation-error-DqLxqQuA.js +40 -0
- package/dist/cli/wordpress-server-child.js +514 -0
- package/dist/cli/wordpress-server-ipc-Dwsg9jSb.js +140 -0
- package/dist/cli/wordpress-server-manager-CtiuJqEb.js +566 -0
- package/dist/cli/wordpress-version-utils-B6UVeTh_.js +51 -0
- package/dist/cli/wp-UGSnlkN0.js +103 -0
- package/package.json +73 -0
- package/patches/@wp-playground+wordpress+3.1.12.patch +28 -0
- package/scripts/postinstall-npm.mjs +38 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import fs, { createWriteStream } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import readline from "readline";
|
|
5
|
+
import semver from "semver";
|
|
6
|
+
import { S as SocketServer, P as PROCESS_MANAGER_CONTROL_SOCKET_PATH, a as PROCESS_MANAGER_EVENTS_SOCKET_PATH, b as PROCESS_MANAGER_LOGS_DIR, d as daemonRequestSchema, c as daemonEventSchema } from "./process-manager-ipc-AUZeYYDT.js";
|
|
7
|
+
const SOCKET_TIMEOUT_MS = 2500;
|
|
8
|
+
const STOP_TIMEOUT_MS = 5e3;
|
|
9
|
+
function getProcessLogPaths(processName) {
|
|
10
|
+
return {
|
|
11
|
+
stdoutLogPath: path.join(PROCESS_MANAGER_LOGS_DIR, `${processName}-out.log`),
|
|
12
|
+
stderrLogPath: path.join(PROCESS_MANAGER_LOGS_DIR, `${processName}-error.log`)
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function timestampLogLine(line) {
|
|
16
|
+
return `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
17
|
+
`;
|
|
18
|
+
}
|
|
19
|
+
function writeTimestampedLines(target, content) {
|
|
20
|
+
const normalizedContent = content.split("\r\n").join("\n");
|
|
21
|
+
const lines = normalizedContent.trimEnd().split("\n");
|
|
22
|
+
lines.forEach((line) => {
|
|
23
|
+
target.write(timestampLogLine(line));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
class ProcessManagerDaemon {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.controlServer = new SocketServer(
|
|
29
|
+
PROCESS_MANAGER_CONTROL_SOCKET_PATH,
|
|
30
|
+
SOCKET_TIMEOUT_MS
|
|
31
|
+
);
|
|
32
|
+
this.eventsServer = new SocketServer(
|
|
33
|
+
PROCESS_MANAGER_EVENTS_SOCKET_PATH,
|
|
34
|
+
SOCKET_TIMEOUT_MS
|
|
35
|
+
);
|
|
36
|
+
this.managedProcesses = /* @__PURE__ */ new Map();
|
|
37
|
+
this.nextPmId = 1;
|
|
38
|
+
this.shuttingDown = false;
|
|
39
|
+
}
|
|
40
|
+
async start() {
|
|
41
|
+
fs.mkdirSync(PROCESS_MANAGER_LOGS_DIR, { recursive: true });
|
|
42
|
+
this.controlServer.on("message", ({ message, socket }) => {
|
|
43
|
+
void this.handleDecodedRequest(socket, message);
|
|
44
|
+
});
|
|
45
|
+
await this.eventsServer.listen();
|
|
46
|
+
await this.controlServer.listen();
|
|
47
|
+
process.on("SIGINT", () => void this.shutdown("signal"));
|
|
48
|
+
process.on("SIGTERM", () => void this.shutdown("signal"));
|
|
49
|
+
process.on("exit", () => {
|
|
50
|
+
this.forceCleanupChildren();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async handleDecodedRequest(socket, payload) {
|
|
54
|
+
const parsed = daemonRequestSchema.safeParse(payload);
|
|
55
|
+
if (!parsed.success) {
|
|
56
|
+
this.controlServer.sendAndClose(socket, {
|
|
57
|
+
type: "error",
|
|
58
|
+
error: { message: parsed.error.message }
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const request = parsed.data;
|
|
63
|
+
try {
|
|
64
|
+
const response = await this.handleRequest(request);
|
|
65
|
+
this.controlServer.sendAndClose(socket, response);
|
|
66
|
+
if (request.type === "kill-daemon") {
|
|
67
|
+
setImmediate(() => {
|
|
68
|
+
void this.shutdown("kill-daemon");
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
73
|
+
this.controlServer.sendAndClose(socket, {
|
|
74
|
+
type: "error",
|
|
75
|
+
error: { message: err.message, stack: err.stack }
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async handleRequest(request) {
|
|
80
|
+
switch (request.type) {
|
|
81
|
+
case "ping":
|
|
82
|
+
return {
|
|
83
|
+
type: "result",
|
|
84
|
+
payload: {}
|
|
85
|
+
};
|
|
86
|
+
case "start-process": {
|
|
87
|
+
const processDesc = await this.startProcess(
|
|
88
|
+
request.processName,
|
|
89
|
+
request.scriptPath,
|
|
90
|
+
request.env ?? {},
|
|
91
|
+
request.args ?? []
|
|
92
|
+
);
|
|
93
|
+
return {
|
|
94
|
+
type: "result",
|
|
95
|
+
payload: { process: processDesc }
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
case "stop-process":
|
|
99
|
+
await this.stopProcess(request.processName);
|
|
100
|
+
return {
|
|
101
|
+
type: "result",
|
|
102
|
+
payload: {}
|
|
103
|
+
};
|
|
104
|
+
case "list-processes":
|
|
105
|
+
return {
|
|
106
|
+
type: "result",
|
|
107
|
+
payload: { processes: this.listProcesses() }
|
|
108
|
+
};
|
|
109
|
+
case "send-message-to-process":
|
|
110
|
+
await this.sendMessageToProcess(request.processId, request.message);
|
|
111
|
+
return {
|
|
112
|
+
type: "result",
|
|
113
|
+
payload: {}
|
|
114
|
+
};
|
|
115
|
+
case "kill-daemon":
|
|
116
|
+
return {
|
|
117
|
+
type: "result",
|
|
118
|
+
payload: {}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
listProcesses() {
|
|
123
|
+
return Array.from(this.managedProcesses.values()).map(this.toProcessDescription);
|
|
124
|
+
}
|
|
125
|
+
getManagedProcessByName(processName) {
|
|
126
|
+
for (const managedProcess of this.managedProcesses.values()) {
|
|
127
|
+
if (managedProcess.name === processName) {
|
|
128
|
+
return managedProcess;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return void 0;
|
|
132
|
+
}
|
|
133
|
+
async startProcess(processName, scriptPath, env, args) {
|
|
134
|
+
const existing = this.getManagedProcessByName(processName);
|
|
135
|
+
if (existing && existing.status === "online") {
|
|
136
|
+
return this.toProcessDescription(existing);
|
|
137
|
+
}
|
|
138
|
+
const pmId = this.nextPmId++;
|
|
139
|
+
const { stdoutLogPath, stderrLogPath } = getProcessLogPaths(processName);
|
|
140
|
+
const stdoutStream = createWriteStream(stdoutLogPath, { flags: "a" });
|
|
141
|
+
const stderrStream = createWriteStream(stderrLogPath, { flags: "a" });
|
|
142
|
+
const doesCurrentNodeSupportJspi = semver.gte(process.version, "24.0.0");
|
|
143
|
+
const execArgv = doesCurrentNodeSupportJspi ? ["--experimental-wasm-jspi"] : [];
|
|
144
|
+
const child = spawn(process.execPath, [...execArgv, scriptPath, ...args], {
|
|
145
|
+
env: { ...process.env, ...env },
|
|
146
|
+
stdio: ["ignore", "pipe", "pipe", "ipc"],
|
|
147
|
+
windowsHide: true
|
|
148
|
+
});
|
|
149
|
+
const managedProcess = {
|
|
150
|
+
pmId,
|
|
151
|
+
name: processName,
|
|
152
|
+
scriptPath,
|
|
153
|
+
args,
|
|
154
|
+
env,
|
|
155
|
+
child,
|
|
156
|
+
// `child.pid` is only undefined if there's an error, in which case our error handler
|
|
157
|
+
// immediately changes the status and deletes the process from the map
|
|
158
|
+
pid: child.pid,
|
|
159
|
+
status: "online",
|
|
160
|
+
stdoutLogPath,
|
|
161
|
+
stderrLogPath,
|
|
162
|
+
stdoutStream,
|
|
163
|
+
stderrStream,
|
|
164
|
+
settled: false
|
|
165
|
+
};
|
|
166
|
+
this.managedProcesses.set(pmId, managedProcess);
|
|
167
|
+
this.pipeOutputWithTimestamp(child.stdout, stdoutStream);
|
|
168
|
+
this.pipeOutputWithTimestamp(child.stderr, stderrStream);
|
|
169
|
+
child.on("message", (raw) => {
|
|
170
|
+
const event = daemonEventSchema.safeParse({
|
|
171
|
+
type: "process-message",
|
|
172
|
+
payload: {
|
|
173
|
+
process: { name: processName, pm_id: pmId },
|
|
174
|
+
raw
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
if (event.success) {
|
|
178
|
+
void this.broadcastEvent(event.data);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
child.on("error", (error) => {
|
|
182
|
+
writeTimestampedLines(stderrStream, error.stack ?? error.message);
|
|
183
|
+
void this.handleProcessExit(managedProcess);
|
|
184
|
+
});
|
|
185
|
+
child.on("exit", () => {
|
|
186
|
+
void this.handleProcessExit(managedProcess);
|
|
187
|
+
});
|
|
188
|
+
await this.broadcastEvent({
|
|
189
|
+
type: "process-event",
|
|
190
|
+
payload: {
|
|
191
|
+
process: { name: processName, pm_id: pmId },
|
|
192
|
+
event: "online"
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return this.toProcessDescription(managedProcess);
|
|
196
|
+
}
|
|
197
|
+
async stopProcess(processName) {
|
|
198
|
+
const managedProcess = this.getManagedProcessByName(processName);
|
|
199
|
+
if (!managedProcess || managedProcess.settled) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
await new Promise((resolve) => {
|
|
203
|
+
const timeoutId = setTimeout(() => {
|
|
204
|
+
managedProcess.child.kill("SIGKILL");
|
|
205
|
+
}, STOP_TIMEOUT_MS);
|
|
206
|
+
managedProcess.child.once("exit", () => {
|
|
207
|
+
clearTimeout(timeoutId);
|
|
208
|
+
void this.broadcastEvent({
|
|
209
|
+
type: "process-event",
|
|
210
|
+
payload: {
|
|
211
|
+
process: { name: managedProcess.name, pm_id: managedProcess.pmId },
|
|
212
|
+
event: "delete"
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
resolve();
|
|
216
|
+
});
|
|
217
|
+
managedProcess.child.kill("SIGTERM");
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
async handleProcessExit(managedProcess) {
|
|
221
|
+
if (managedProcess.settled) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
managedProcess.settled = true;
|
|
225
|
+
managedProcess.status = "stopped";
|
|
226
|
+
this.managedProcesses.delete(managedProcess.pmId);
|
|
227
|
+
managedProcess.stdoutStream.end();
|
|
228
|
+
managedProcess.stderrStream.end();
|
|
229
|
+
await this.broadcastEvent({
|
|
230
|
+
type: "process-event",
|
|
231
|
+
payload: {
|
|
232
|
+
process: { name: managedProcess.name, pm_id: managedProcess.pmId },
|
|
233
|
+
event: "exit"
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
async sendMessageToProcess(processId, message) {
|
|
238
|
+
const managedProcess = this.managedProcesses.get(processId);
|
|
239
|
+
if (!managedProcess) {
|
|
240
|
+
throw new Error(`Process with id ${processId} not found`);
|
|
241
|
+
}
|
|
242
|
+
if (!managedProcess.child.connected) {
|
|
243
|
+
throw new Error(`Process with id ${processId} is not connected`);
|
|
244
|
+
}
|
|
245
|
+
await new Promise((resolve, reject) => {
|
|
246
|
+
managedProcess.child.send(message, (error) => {
|
|
247
|
+
if (error) {
|
|
248
|
+
reject(error);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
resolve();
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
async broadcastEvent(event) {
|
|
256
|
+
this.eventsServer.broadcast(event);
|
|
257
|
+
}
|
|
258
|
+
pipeOutputWithTimestamp(input, target) {
|
|
259
|
+
if (!input) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const lineReader = readline.createInterface({
|
|
263
|
+
input,
|
|
264
|
+
crlfDelay: Infinity
|
|
265
|
+
});
|
|
266
|
+
lineReader.on("line", (line) => {
|
|
267
|
+
void target.write(timestampLogLine(line));
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
toProcessDescription(managedProcess) {
|
|
271
|
+
if (managedProcess.status === "stopped") {
|
|
272
|
+
return {
|
|
273
|
+
name: managedProcess.name,
|
|
274
|
+
pmId: managedProcess.pmId,
|
|
275
|
+
status: managedProcess.status
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
name: managedProcess.name,
|
|
280
|
+
pmId: managedProcess.pmId,
|
|
281
|
+
status: managedProcess.status,
|
|
282
|
+
pid: managedProcess.pid
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
forceCleanupChildren() {
|
|
286
|
+
for (const managedProcess of this.managedProcesses.values()) {
|
|
287
|
+
if (managedProcess.settled) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
managedProcess.child.kill("SIGKILL");
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async shutdown(reason) {
|
|
297
|
+
if (this.shuttingDown) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
this.shuttingDown = true;
|
|
301
|
+
await this.broadcastEvent({
|
|
302
|
+
type: "daemon-kill",
|
|
303
|
+
payload: { reason }
|
|
304
|
+
});
|
|
305
|
+
await Promise.allSettled(
|
|
306
|
+
Array.from(this.managedProcesses.values()).map(
|
|
307
|
+
(managedProcess) => this.stopProcess(managedProcess.name)
|
|
308
|
+
)
|
|
309
|
+
);
|
|
310
|
+
await new Promise((resolve) => {
|
|
311
|
+
void this.controlServer.close().then(() => resolve());
|
|
312
|
+
});
|
|
313
|
+
await this.eventsServer.close();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async function main() {
|
|
317
|
+
try {
|
|
318
|
+
const daemon = new ProcessManagerDaemon();
|
|
319
|
+
await daemon.start();
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error(error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
void main();
|
|
325
|
+
export {
|
|
326
|
+
ProcessManagerDaemon
|
|
327
|
+
};
|