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,83 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { f as fs } from "./index-BXRYeCYG.js";
|
|
3
|
+
import { c as getServerFilesPath } from "./server-files-C_oy-mnI.js";
|
|
4
|
+
class SqliteIntegrationProvider {
|
|
5
|
+
getSqlitePluginSourcePath() {
|
|
6
|
+
return path.join(this.getServerFilesPath(), this.getSqliteDirname());
|
|
7
|
+
}
|
|
8
|
+
async isSqliteIntegrationAvailable() {
|
|
9
|
+
const sqliteSourcePath = this.getSqlitePluginSourcePath();
|
|
10
|
+
const dbCopyPath = path.join(sqliteSourcePath, "db.copy");
|
|
11
|
+
return await fs.pathExists(sqliteSourcePath) && await fs.pathExists(dbCopyPath);
|
|
12
|
+
}
|
|
13
|
+
// Returns true if site has db.php or no wp-config.php
|
|
14
|
+
async needsSqliteSetup(sitePath) {
|
|
15
|
+
const hasDbPhp = await fs.pathExists(path.join(sitePath, "wp-content", "db.php"));
|
|
16
|
+
const hasWpConfig = await fs.pathExists(path.join(sitePath, "wp-config.php"));
|
|
17
|
+
return hasDbPhp || !hasWpConfig;
|
|
18
|
+
}
|
|
19
|
+
async getSqliteVersionFromInstallation(sqliteMuPluginPath) {
|
|
20
|
+
try {
|
|
21
|
+
const versionFileContent = await fs.readFile(
|
|
22
|
+
path.join(sqliteMuPluginPath, "load.php"),
|
|
23
|
+
"utf8"
|
|
24
|
+
);
|
|
25
|
+
const matches = versionFileContent.match(/\s\*\sVersion:\s*([0-9a-zA-Z.-]+)/);
|
|
26
|
+
return matches?.[1] || "";
|
|
27
|
+
} catch (err) {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async installSqliteIntegration(sitePath) {
|
|
32
|
+
if (!await this.isSqliteIntegrationAvailable()) {
|
|
33
|
+
throw new Error("SQLite integration files not found. Please ensure Studio is installed.");
|
|
34
|
+
}
|
|
35
|
+
const wpContentPath = path.join(sitePath, "wp-content");
|
|
36
|
+
const databasePath = path.join(wpContentPath, "database");
|
|
37
|
+
await fs.mkdir(databasePath, { recursive: true });
|
|
38
|
+
const sqliteSourcePath = this.getSqlitePluginSourcePath();
|
|
39
|
+
const dbCopyContent = await fs.readFile(path.join(sqliteSourcePath, "db.copy"), "utf8");
|
|
40
|
+
const sqliteDirname = this.getSqliteDirname();
|
|
41
|
+
const updatedContent = dbCopyContent.replace(
|
|
42
|
+
"'{SQLITE_IMPLEMENTATION_FOLDER_PATH}'",
|
|
43
|
+
`realpath( __DIR__ . '/mu-plugins/${sqliteDirname}' )`
|
|
44
|
+
).replace(
|
|
45
|
+
"define( 'SQLITE_DB_DROPIN_VERSION'",
|
|
46
|
+
`define( 'SQLITE_MAIN_FILE', __FILE__ );
|
|
47
|
+
define( 'SQLITE_DB_DROPIN_VERSION'`
|
|
48
|
+
);
|
|
49
|
+
await fs.writeFile(path.join(wpContentPath, "db.php"), updatedContent);
|
|
50
|
+
const sqliteDestPath = path.join(wpContentPath, "mu-plugins", sqliteDirname);
|
|
51
|
+
await fs.copy(sqliteSourcePath, sqliteDestPath);
|
|
52
|
+
}
|
|
53
|
+
async keepSqliteIntegrationUpdated(sitePath) {
|
|
54
|
+
if (await this.needsSqliteSetup(sitePath)) {
|
|
55
|
+
await this.installSqliteIntegration(sitePath);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
async isSqliteInstalled(sitePath) {
|
|
61
|
+
return fs.existsSync(path.join(sitePath, "wp-content", "mu-plugins", this.getSqliteDirname())) && fs.existsSync(path.join(sitePath, "wp-content", "db.php"));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const SQLITE_FILENAME = "sqlite-database-integration";
|
|
65
|
+
class CliSqliteProvider extends SqliteIntegrationProvider {
|
|
66
|
+
getServerFilesPath() {
|
|
67
|
+
return getServerFilesPath();
|
|
68
|
+
}
|
|
69
|
+
getSqliteDirname() {
|
|
70
|
+
return SQLITE_FILENAME;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const provider = new CliSqliteProvider();
|
|
74
|
+
async function keepSqliteIntegrationUpdated(sitePath) {
|
|
75
|
+
return provider.keepSqliteIntegrationUpdated(sitePath);
|
|
76
|
+
}
|
|
77
|
+
async function isSqliteIntegrationInstalled(sitePath) {
|
|
78
|
+
return provider.isSqliteInstalled(sitePath);
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
isSqliteIntegrationInstalled as i,
|
|
82
|
+
keepSqliteIntegrationUpdated as k
|
|
83
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { S as SiteCommandLoggerAction } from "./logger-actions-OaIvl-ai.js";
|
|
2
|
+
import { __ } from "@wordpress/i18n";
|
|
3
|
+
import { L as LoggerError, a as Logger, k as getSiteByFolder, H as updateSiteLatestCliPid, I as updateSiteAutoStart } from "./appdata-07CF2rhg.js";
|
|
4
|
+
import { c as connectToDaemon, i as isServerRunning, s as startWordPressServer, d as disconnectFromDaemon } from "./wordpress-server-manager-CtiuJqEb.js";
|
|
5
|
+
import { o as openSiteInBrowser, l as logSiteDetails, s as setupCustomDomain } from "./site-utils-CfsabjUn.js";
|
|
6
|
+
import { k as keepSqliteIntegrationUpdated } from "./sqlite-integration-H4OwSlwR.js";
|
|
7
|
+
const logger = new Logger();
|
|
8
|
+
async function runCommand(sitePath, skipBrowser = false, skipLogDetails = false) {
|
|
9
|
+
try {
|
|
10
|
+
logger.reportStart(SiteCommandLoggerAction.START_DAEMON, __("Starting process daemon…"));
|
|
11
|
+
await connectToDaemon();
|
|
12
|
+
logger.reportSuccess(__("Process daemon started"));
|
|
13
|
+
logger.reportStart(SiteCommandLoggerAction.LOAD_SITES, __("Loading site…"));
|
|
14
|
+
const site = await getSiteByFolder(sitePath);
|
|
15
|
+
logger.reportSuccess(__("Site loaded"));
|
|
16
|
+
const runningProcess = await isServerRunning(site.id);
|
|
17
|
+
if (runningProcess) {
|
|
18
|
+
logger.reportSuccess(__("WordPress server is already running"));
|
|
19
|
+
if (runningProcess.status === "online") {
|
|
20
|
+
await updateSiteLatestCliPid(site.id, runningProcess.pid);
|
|
21
|
+
}
|
|
22
|
+
if (!skipBrowser) {
|
|
23
|
+
await openSiteInBrowser(site);
|
|
24
|
+
}
|
|
25
|
+
if (!skipLogDetails) {
|
|
26
|
+
logSiteDetails(site);
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
await setupCustomDomain(site, logger);
|
|
31
|
+
logger.reportStart(
|
|
32
|
+
SiteCommandLoggerAction.INSTALL_SQLITE,
|
|
33
|
+
__("Setting up SQLite integration, if needed…")
|
|
34
|
+
);
|
|
35
|
+
await keepSqliteIntegrationUpdated(sitePath);
|
|
36
|
+
logger.reportSuccess(__("SQLite integration configured as needed"));
|
|
37
|
+
logger.reportStart(SiteCommandLoggerAction.START_SITE, __("Starting WordPress server…"));
|
|
38
|
+
try {
|
|
39
|
+
const processDesc = await startWordPressServer(site, logger);
|
|
40
|
+
logger.reportSuccess(__("WordPress server started"));
|
|
41
|
+
if (processDesc.status === "online") {
|
|
42
|
+
await updateSiteLatestCliPid(site.id, processDesc.pid);
|
|
43
|
+
}
|
|
44
|
+
await updateSiteAutoStart(site.id, true);
|
|
45
|
+
if (!skipLogDetails) {
|
|
46
|
+
logSiteDetails(site);
|
|
47
|
+
}
|
|
48
|
+
if (!skipBrowser) {
|
|
49
|
+
await openSiteInBrowser(site);
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
throw new LoggerError(__("Failed to start WordPress server"), error);
|
|
53
|
+
}
|
|
54
|
+
} finally {
|
|
55
|
+
await disconnectFromDaemon();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const registerCommand = (yargs) => {
|
|
59
|
+
return yargs.command({
|
|
60
|
+
command: "start",
|
|
61
|
+
describe: __("Start site"),
|
|
62
|
+
builder: (yargs2) => {
|
|
63
|
+
return yargs2.option("skip-browser", {
|
|
64
|
+
type: "boolean",
|
|
65
|
+
describe: __("Skip opening the site in browser after starting"),
|
|
66
|
+
default: false
|
|
67
|
+
}).option("skip-log-details", {
|
|
68
|
+
type: "boolean",
|
|
69
|
+
describe: __("Skip printing site URL and admin credentials after starting"),
|
|
70
|
+
default: false
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
handler: async (argv) => {
|
|
74
|
+
try {
|
|
75
|
+
await runCommand(argv.path, argv.skipBrowser, argv.skipLogDetails);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof LoggerError) {
|
|
78
|
+
logger.reportError(error);
|
|
79
|
+
} else {
|
|
80
|
+
const loggerError = new LoggerError(__("Failed to start site"), error);
|
|
81
|
+
logger.reportError(loggerError);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
export {
|
|
88
|
+
registerCommand,
|
|
89
|
+
runCommand
|
|
90
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { A as AuthCommandLoggerAction } from "./logger-actions-OaIvl-ai.js";
|
|
2
|
+
import { __, sprintf } from "@wordpress/i18n";
|
|
3
|
+
import { a as Logger, g as getAuthToken, L as LoggerError, c as getUserInfo } from "./appdata-07CF2rhg.js";
|
|
4
|
+
async function runCommand() {
|
|
5
|
+
const logger = new Logger();
|
|
6
|
+
logger.reportStart(AuthCommandLoggerAction.STATUS_CHECK, __("Checking authentication status…"));
|
|
7
|
+
let token;
|
|
8
|
+
try {
|
|
9
|
+
token = await getAuthToken();
|
|
10
|
+
} catch (error) {
|
|
11
|
+
logger.reportError(new LoggerError(__("Authentication token is invalid or expired")));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const userData = await getUserInfo(token.accessToken);
|
|
16
|
+
logger.reportSuccess(
|
|
17
|
+
sprintf(__("Authenticated with WordPress.com as `%s`"), userData.username)
|
|
18
|
+
);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
if (error instanceof LoggerError) {
|
|
21
|
+
logger.reportError(error);
|
|
22
|
+
} else {
|
|
23
|
+
logger.reportError(new LoggerError(__("Failed to check authentication status"), error));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const registerCommand = (yargs) => {
|
|
28
|
+
return yargs.command({
|
|
29
|
+
command: "status",
|
|
30
|
+
describe: __("Check authentication status"),
|
|
31
|
+
builder: (yargs2) => {
|
|
32
|
+
return yargs2.option("path", {
|
|
33
|
+
hidden: true
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
handler: async () => {
|
|
37
|
+
await runCommand();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
registerCommand,
|
|
43
|
+
runCommand
|
|
44
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { g as getWordPressVersion } from "./get-wordpress-version-BwSCJujO.js";
|
|
2
|
+
import { d as decodePassword } from "./passwords-DyzWd9Xi.js";
|
|
3
|
+
import { S as SiteCommandLoggerAction } from "./logger-actions-OaIvl-ai.js";
|
|
4
|
+
import { __ } from "@wordpress/i18n";
|
|
5
|
+
import CliTable3 from "cli-table3";
|
|
6
|
+
import { L as LoggerError, a as Logger, k as getSiteByFolder, A as getSiteUrl } from "./appdata-07CF2rhg.js";
|
|
7
|
+
import { c as connectToDaemon, i as isServerRunning, d as disconnectFromDaemon } from "./wordpress-server-manager-CtiuJqEb.js";
|
|
8
|
+
import { c as getPrettyPath } from "./index-7pbG_s_U.js";
|
|
9
|
+
const logger = new Logger();
|
|
10
|
+
async function runCommand(siteFolder, format) {
|
|
11
|
+
try {
|
|
12
|
+
logger.reportStart(SiteCommandLoggerAction.START_DAEMON, __("Starting process daemon…"));
|
|
13
|
+
await connectToDaemon();
|
|
14
|
+
logger.reportSuccess(__("Process daemon started"));
|
|
15
|
+
logger.reportStart(SiteCommandLoggerAction.LOAD_SITES, __("Loading site…"));
|
|
16
|
+
const site = await getSiteByFolder(siteFolder);
|
|
17
|
+
logger.reportSuccess(__("Site loaded"));
|
|
18
|
+
const isOnline = Boolean(await isServerRunning(site.id));
|
|
19
|
+
const status = isOnline ? `🟢 ${__("Online")}` : `🔴 ${__("Offline")}`;
|
|
20
|
+
const siteUrl = getSiteUrl(site);
|
|
21
|
+
const sitePath = getPrettyPath(site.path);
|
|
22
|
+
const wpVersion = getWordPressVersion(site.path);
|
|
23
|
+
const autoLoginUrl = new URL(siteUrl);
|
|
24
|
+
autoLoginUrl.pathname = `/studio-auto-login`;
|
|
25
|
+
autoLoginUrl.searchParams.set("redirect_to", `/wp-admin/`);
|
|
26
|
+
const xdebugStatus = site.enableXdebug ? __("Enabled") : __("Disabled");
|
|
27
|
+
const siteData = [
|
|
28
|
+
{
|
|
29
|
+
key: __("Site URL"),
|
|
30
|
+
jsonKey: "siteUrl",
|
|
31
|
+
value: new URL(siteUrl).toString(),
|
|
32
|
+
type: "url"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: __("Auto-login URL"),
|
|
36
|
+
jsonKey: "autoLoginUrl",
|
|
37
|
+
value: autoLoginUrl.toString(),
|
|
38
|
+
type: "url",
|
|
39
|
+
hidden: !isOnline
|
|
40
|
+
},
|
|
41
|
+
{ key: __("Site Path"), jsonKey: "sitePath", value: sitePath },
|
|
42
|
+
{ key: __("Status"), jsonKey: "status", value: status },
|
|
43
|
+
{ key: __("PHP version"), jsonKey: "phpVersion", value: site.phpVersion },
|
|
44
|
+
{ key: __("WP version"), jsonKey: "wpVersion", value: wpVersion },
|
|
45
|
+
{ key: __("Xdebug"), jsonKey: "xdebug", value: xdebugStatus },
|
|
46
|
+
{
|
|
47
|
+
key: __("Admin username"),
|
|
48
|
+
jsonKey: "adminUsername",
|
|
49
|
+
value: site.adminUsername ?? "admin"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
key: __("Admin password"),
|
|
53
|
+
jsonKey: "adminPassword",
|
|
54
|
+
value: site.adminPassword ? decodePassword(site.adminPassword) : void 0
|
|
55
|
+
},
|
|
56
|
+
{ key: __("Admin email"), jsonKey: "adminEmail", value: site.adminEmail }
|
|
57
|
+
].filter(({ value, hidden }) => value && !hidden);
|
|
58
|
+
if (format === "table") {
|
|
59
|
+
const table = new CliTable3({
|
|
60
|
+
wordWrap: true,
|
|
61
|
+
wrapOnWordBoundary: false,
|
|
62
|
+
style: {
|
|
63
|
+
head: [],
|
|
64
|
+
border: []
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
for (const { key, value, type } of siteData) {
|
|
68
|
+
table.push([key, type === "url" ? { href: value, content: value } : value]);
|
|
69
|
+
}
|
|
70
|
+
console.table(table.toString());
|
|
71
|
+
} else {
|
|
72
|
+
const logData = Object.fromEntries(
|
|
73
|
+
siteData.map(({ jsonKey, value }) => [jsonKey, value])
|
|
74
|
+
);
|
|
75
|
+
console.log(JSON.stringify(logData, null, 2));
|
|
76
|
+
}
|
|
77
|
+
} finally {
|
|
78
|
+
await disconnectFromDaemon();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const registerCommand = (yargs) => {
|
|
82
|
+
return yargs.command({
|
|
83
|
+
command: "status",
|
|
84
|
+
describe: __("Get status of site"),
|
|
85
|
+
builder: (yargs2) => {
|
|
86
|
+
return yargs2.option("format", {
|
|
87
|
+
type: "string",
|
|
88
|
+
choices: ["table", "json"],
|
|
89
|
+
default: "table",
|
|
90
|
+
description: __("Output format")
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
handler: async (argv) => {
|
|
94
|
+
try {
|
|
95
|
+
await runCommand(argv.path, argv.format);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (error instanceof LoggerError) {
|
|
98
|
+
logger.reportError(error);
|
|
99
|
+
} else {
|
|
100
|
+
const loggerError = new LoggerError(__("Failed to load site status"), error);
|
|
101
|
+
logger.reportError(loggerError);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
export {
|
|
108
|
+
registerCommand,
|
|
109
|
+
runCommand
|
|
110
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { S as SiteCommandLoggerAction } from "./logger-actions-OaIvl-ai.js";
|
|
2
|
+
import { __, sprintf, _n } from "@wordpress/i18n";
|
|
3
|
+
import { L as LoggerError, a as Logger, k as getSiteByFolder, K as clearSiteLatestCliPid, I as updateSiteAutoStart, r as readAppdata, l as lockAppdata, s as saveAppdata, u as unlockAppdata } from "./appdata-07CF2rhg.js";
|
|
4
|
+
import { c as connectToDaemon, i as isServerRunning, a as stopWordPressServer, k as killDaemonAndChildren, d as disconnectFromDaemon } from "./wordpress-server-manager-CtiuJqEb.js";
|
|
5
|
+
import { a as stopProxyIfNoSitesNeedIt } from "./site-utils-CfsabjUn.js";
|
|
6
|
+
const logger = new Logger();
|
|
7
|
+
var Mode = /* @__PURE__ */ ((Mode2) => {
|
|
8
|
+
Mode2[Mode2["STOP_SINGLE_SITE"] = 0] = "STOP_SINGLE_SITE";
|
|
9
|
+
Mode2[Mode2["STOP_ALL_SITES"] = 1] = "STOP_ALL_SITES";
|
|
10
|
+
return Mode2;
|
|
11
|
+
})(Mode || {});
|
|
12
|
+
async function runCommand(target, siteFolder, autoStart) {
|
|
13
|
+
try {
|
|
14
|
+
await connectToDaemon();
|
|
15
|
+
if (target === 0 && siteFolder) {
|
|
16
|
+
const site = await getSiteByFolder(siteFolder);
|
|
17
|
+
const runningProcess = await isServerRunning(site.id);
|
|
18
|
+
if (!runningProcess) {
|
|
19
|
+
logger.reportSuccess(__("WordPress server is not running"));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
logger.reportStart(SiteCommandLoggerAction.STOP_SITE, __("Stopping WordPress servers…"));
|
|
23
|
+
try {
|
|
24
|
+
await stopWordPressServer(site.id);
|
|
25
|
+
await clearSiteLatestCliPid(site.id);
|
|
26
|
+
await updateSiteAutoStart(site.id, autoStart);
|
|
27
|
+
logger.reportSuccess(__("WordPress server stopped"));
|
|
28
|
+
await stopProxyIfNoSitesNeedIt(site.id, logger);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw new LoggerError(__("Failed to stop WordPress server"), error);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
const appdata = await readAppdata();
|
|
34
|
+
const runningSites = [];
|
|
35
|
+
for (const site of appdata.sites) {
|
|
36
|
+
const runningProcess = await isServerRunning(site.id);
|
|
37
|
+
if (runningProcess) {
|
|
38
|
+
runningSites.push(site);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!runningSites.length) {
|
|
42
|
+
await killDaemonAndChildren();
|
|
43
|
+
logger.reportSuccess(__("No sites are currently running"));
|
|
44
|
+
} else {
|
|
45
|
+
try {
|
|
46
|
+
await lockAppdata();
|
|
47
|
+
const appdata2 = await readAppdata();
|
|
48
|
+
for (const site of appdata2.sites) {
|
|
49
|
+
if (runningSites.find((r) => r.id === site.id)) {
|
|
50
|
+
delete site.latestCliPid;
|
|
51
|
+
site.autoStart = autoStart;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
await saveAppdata(appdata2);
|
|
55
|
+
} finally {
|
|
56
|
+
await unlockAppdata();
|
|
57
|
+
}
|
|
58
|
+
logger.reportStart(SiteCommandLoggerAction.STOP_ALL_SITES, __("Stopping all WordPress servers…"));
|
|
59
|
+
await killDaemonAndChildren();
|
|
60
|
+
logger.reportSuccess(
|
|
61
|
+
sprintf(
|
|
62
|
+
_n(
|
|
63
|
+
"Successfully stopped %d site",
|
|
64
|
+
"Successfully stopped %d sites",
|
|
65
|
+
runningSites.length
|
|
66
|
+
),
|
|
67
|
+
runningSites.length
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
await disconnectFromDaemon();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const registerCommand = (yargs) => {
|
|
77
|
+
return yargs.command({
|
|
78
|
+
command: "stop",
|
|
79
|
+
describe: __("Stop site(s)"),
|
|
80
|
+
builder: (yargs2) => {
|
|
81
|
+
return yargs2.option("all", {
|
|
82
|
+
type: "boolean",
|
|
83
|
+
describe: __("Stop all sites"),
|
|
84
|
+
default: false
|
|
85
|
+
}).option("auto-start", {
|
|
86
|
+
type: "boolean",
|
|
87
|
+
describe: __("Set auto-start flag for the site(s)"),
|
|
88
|
+
default: false,
|
|
89
|
+
hidden: true
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
handler: async (argv) => {
|
|
93
|
+
try {
|
|
94
|
+
if (argv.all) {
|
|
95
|
+
await runCommand(1, void 0, argv.autoStart);
|
|
96
|
+
} else {
|
|
97
|
+
await runCommand(0, argv.path, argv.autoStart);
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (error instanceof LoggerError) {
|
|
101
|
+
logger.reportError(error);
|
|
102
|
+
} else {
|
|
103
|
+
const loggerError = new LoggerError(
|
|
104
|
+
argv.all ? __("Failed to stop sites") : __("Failed to stop site"),
|
|
105
|
+
error
|
|
106
|
+
);
|
|
107
|
+
logger.reportError(loggerError);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
export {
|
|
114
|
+
Mode,
|
|
115
|
+
registerCommand,
|
|
116
|
+
runCommand
|
|
117
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { a as Logger, g as getAuthToken, o as DEMO_SITE_EXPIRATION_DAYS, L as LoggerError, m as uploadArchive, w as waitForSiteReady, k as getSiteByFolder } from "./appdata-07CF2rhg.js";
|
|
4
|
+
import { g as getWordPressVersion } from "./get-wordpress-version-BwSCJujO.js";
|
|
5
|
+
import { P as PreviewCommandLoggerAction } from "./logger-actions-OaIvl-ai.js";
|
|
6
|
+
import { __, sprintf } from "@wordpress/i18n";
|
|
7
|
+
import { a as archiveSiteContent, c as cleanup } from "./archive-xDmkN4wb.js";
|
|
8
|
+
import { g as getSnapshotsFromAppdata, b as addDays, u as updateSnapshotInAppdata } from "./snapshots-6XE53y_F.js";
|
|
9
|
+
import { n as normalizeHostname } from "./index-7pbG_s_U.js";
|
|
10
|
+
async function getSnapshotToUpdate(snapshots, host, siteFolder, overwrite) {
|
|
11
|
+
const site = await getSiteByFolder(siteFolder);
|
|
12
|
+
const currentSiteId = site.id;
|
|
13
|
+
const snapshotToUpdate = snapshots.find((s) => s.url === host);
|
|
14
|
+
if (!snapshotToUpdate) {
|
|
15
|
+
throw new LoggerError("Preview site not found");
|
|
16
|
+
}
|
|
17
|
+
if (snapshotToUpdate.localSiteId !== currentSiteId && !overwrite) {
|
|
18
|
+
throw new LoggerError(
|
|
19
|
+
__(
|
|
20
|
+
"The specified directory does not match the original site for this preview. If you want to overwrite, run the command with --overwrite."
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return snapshotToUpdate;
|
|
25
|
+
}
|
|
26
|
+
async function runCommand(siteFolder, host, overwrite) {
|
|
27
|
+
const archivePath = path.join(
|
|
28
|
+
os.tmpdir(),
|
|
29
|
+
`${path.basename(siteFolder)}-${Date.now()}.zip`
|
|
30
|
+
);
|
|
31
|
+
const logger = new Logger();
|
|
32
|
+
try {
|
|
33
|
+
logger.reportStart(PreviewCommandLoggerAction.VALIDATE, __("Validating…"));
|
|
34
|
+
const token = await getAuthToken();
|
|
35
|
+
const snapshots = await getSnapshotsFromAppdata(token.id);
|
|
36
|
+
const snapshotToUpdate = await getSnapshotToUpdate(snapshots, host, siteFolder, overwrite);
|
|
37
|
+
const now = /* @__PURE__ */ new Date();
|
|
38
|
+
const endDate = addDays(snapshotToUpdate.date, DEMO_SITE_EXPIRATION_DAYS);
|
|
39
|
+
if (endDate < now) {
|
|
40
|
+
throw new LoggerError(__("Cannot update an expired preview site."));
|
|
41
|
+
}
|
|
42
|
+
logger.reportSuccess(__("Validation successful"), true);
|
|
43
|
+
logger.reportStart(PreviewCommandLoggerAction.ARCHIVE, __("Creating archive…"));
|
|
44
|
+
await archiveSiteContent(siteFolder, archivePath);
|
|
45
|
+
logger.reportSuccess(__("Archive created"));
|
|
46
|
+
logger.reportStart(PreviewCommandLoggerAction.UPLOAD, __("Uploading archive…"));
|
|
47
|
+
const wordpressVersion = getWordPressVersion(siteFolder);
|
|
48
|
+
const uploadResponse = await uploadArchive(
|
|
49
|
+
archivePath,
|
|
50
|
+
token.accessToken,
|
|
51
|
+
wordpressVersion,
|
|
52
|
+
snapshotToUpdate.atomicSiteId
|
|
53
|
+
);
|
|
54
|
+
logger.reportSuccess(__("Archive uploaded"));
|
|
55
|
+
logger.reportStart(PreviewCommandLoggerAction.READY, __("Updating preview site…"));
|
|
56
|
+
await waitForSiteReady(uploadResponse.site_id, token.accessToken);
|
|
57
|
+
logger.reportSuccess(
|
|
58
|
+
sprintf(__("Preview site available at: %s"), `https://${uploadResponse.site_url}`)
|
|
59
|
+
);
|
|
60
|
+
logger.reportStart(PreviewCommandLoggerAction.APPDATA, __("Saving preview site to Studio…"));
|
|
61
|
+
const snapshot = await updateSnapshotInAppdata(uploadResponse.site_id, siteFolder);
|
|
62
|
+
logger.reportSuccess(__("Preview site saved to Studio"));
|
|
63
|
+
logger.reportKeyValuePair("name", snapshot.name ?? "");
|
|
64
|
+
logger.reportKeyValuePair("url", snapshot.url);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof LoggerError) {
|
|
67
|
+
logger.reportError(error);
|
|
68
|
+
} else {
|
|
69
|
+
const loggerError = new LoggerError(__("Failed to update preview site"), error);
|
|
70
|
+
logger.reportError(loggerError);
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
void cleanup(archivePath);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const registerCommand = (yargs) => {
|
|
77
|
+
return yargs.command({
|
|
78
|
+
command: "update <host>",
|
|
79
|
+
describe: __("Update preview site"),
|
|
80
|
+
builder: (yargs2) => {
|
|
81
|
+
return yargs2.positional("host", {
|
|
82
|
+
type: "string",
|
|
83
|
+
description: __("Hostname of the preview site to update"),
|
|
84
|
+
demandOption: true
|
|
85
|
+
}).option("overwrite", {
|
|
86
|
+
alias: "o",
|
|
87
|
+
type: "boolean",
|
|
88
|
+
default: false,
|
|
89
|
+
description: __("Allow updating a preview site from a different directory")
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
handler: async (argv) => {
|
|
93
|
+
const normalizedHost = normalizeHostname(argv.host);
|
|
94
|
+
await runCommand(argv.path, normalizedHost, argv.overwrite);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
export {
|
|
99
|
+
registerCommand,
|
|
100
|
+
runCommand
|
|
101
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { __ } from "@wordpress/i18n";
|
|
2
|
+
const DOMAIN_PATTERN = /^(?!-)[\p{L}\p{N}][\p{L}\p{N}-]{0,61}[\p{L}\p{N}](?<!-)(?:\.(?!-)[\p{L}\p{N}-]{1,61}[\p{L}\p{N}](?<!-))+$/u;
|
|
3
|
+
const getDomainNameValidationError = (useCustomDomain, domainName, existingDomainNames) => {
|
|
4
|
+
if (!useCustomDomain) {
|
|
5
|
+
return "";
|
|
6
|
+
}
|
|
7
|
+
if (!domainName) {
|
|
8
|
+
return __("The domain name is required");
|
|
9
|
+
}
|
|
10
|
+
if (existingDomainNames.includes(domainName)) {
|
|
11
|
+
return __("The domain name is already in use");
|
|
12
|
+
}
|
|
13
|
+
if (!DOMAIN_PATTERN.test(domainName)) {
|
|
14
|
+
return __("Please enter a valid domain name");
|
|
15
|
+
}
|
|
16
|
+
if (domainName.length > 253) {
|
|
17
|
+
return __("The domain name is too long");
|
|
18
|
+
}
|
|
19
|
+
if (!domainName.endsWith(".local")) {
|
|
20
|
+
return __("The domain name must end with .local");
|
|
21
|
+
}
|
|
22
|
+
return "";
|
|
23
|
+
};
|
|
24
|
+
class ValidationError extends Error {
|
|
25
|
+
constructor(optionName, givenValue, validationMessage) {
|
|
26
|
+
super();
|
|
27
|
+
this.name = "ValidationError";
|
|
28
|
+
this.optionName = optionName;
|
|
29
|
+
this.givenValue = givenValue;
|
|
30
|
+
this.validationMessage = validationMessage;
|
|
31
|
+
}
|
|
32
|
+
get message() {
|
|
33
|
+
return `Invalid values:
|
|
34
|
+
- Argument: ${this.optionName}, Given: "${this.givenValue}", ${this.validationMessage}.`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
ValidationError as V,
|
|
39
|
+
getDomainNameValidationError as g
|
|
40
|
+
};
|