@atomicsmash/cli 11.0.0 → 12.0.0-beta.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/commands/pull-database.d.ts.map +1 -1
- package/dist/commands/pull-database.js +94 -118
- package/dist/commands/pull-media.d.ts.map +1 -1
- package/dist/commands/pull-media.js +45 -73
- package/dist/commands/setup-database.d.ts +1 -0
- package/dist/commands/setup-database.d.ts.map +1 -1
- package/dist/commands/setup-database.js +61 -65
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +145 -150
- package/dist/commands/toggle-media-proxy.d.ts +4 -0
- package/dist/commands/toggle-media-proxy.d.ts.map +1 -0
- package/dist/commands/toggle-media-proxy.js +91 -0
- package/package.json +4 -14
- package/dist/commands/svg.d.ts +0 -21
- package/dist/commands/svg.d.ts.map +0 -1
- package/dist/commands/svg.js +0 -86
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull-database.d.ts","sourceRoot":"","sources":["../../src/commands/pull-database.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO,kBAAkB,CAAC;AACvC,eAAO,MAAM,QAAQ,oEAC6C,CAAC;
|
|
1
|
+
{"version":3,"file":"pull-database.d.ts","sourceRoot":"","sources":["../../src/commands/pull-database.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO,kBAAkB,CAAC;AACvC,eAAO,MAAM,QAAQ,oEAC6C,CAAC;AAEnE,wBAAsB,OAAO,kBA4I5B"}
|
|
@@ -8,128 +8,104 @@ export const command = "pull-database";
|
|
|
8
8
|
export const describe = "Pull the database down from staging and replace local database.";
|
|
9
9
|
export async function handler() {
|
|
10
10
|
const execute = promisify(exec);
|
|
11
|
-
const smashConfig = await getSmashConfig();
|
|
12
|
-
const stagingSSHUsername =
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"wfstatus",
|
|
66
|
-
"wftrafficrates",
|
|
67
|
-
"wfwaffailures",
|
|
68
|
-
// WP All Import/Export
|
|
69
|
-
"pmxi_files",
|
|
70
|
-
"pmxi_geocoding",
|
|
71
|
-
"pmxi_hash",
|
|
72
|
-
"pmxi_history",
|
|
73
|
-
"pmxi_images",
|
|
74
|
-
"pmxi_imports",
|
|
75
|
-
"pmxi_posts",
|
|
76
|
-
"pmxi_templates",
|
|
77
|
-
].map((tableName) => stagingDBPrefix + tableName);
|
|
78
|
-
await execute(`ssh -o "StrictHostKeyChecking no" ${stagingSSHUsername}@${stagingSSHHost} -p ${stagingSSHPort} "${stagingWebRoot !== "" ? `cd ${stagingWebRoot} && ` : ""}wp db export - --add-drop-table --exclude_tables=${tablesToExclude.join(",")}" > ${tmpFile}`)
|
|
79
|
-
.then(async () => {
|
|
80
|
-
await stopRunningMessage();
|
|
81
|
-
console.log("Database downloaded.");
|
|
82
|
-
await execute(`wp db check`).catch(async () => {
|
|
83
|
-
await execute(`wp db create`);
|
|
84
|
-
console.log("Local database created.");
|
|
85
|
-
});
|
|
86
|
-
const stopRunningMessage2 = startRunningMessage("Importing database");
|
|
87
|
-
await execute(`wp db query < ${tmpFile}`)
|
|
88
|
-
.then(async () => {
|
|
89
|
-
await stopRunningMessage2();
|
|
90
|
-
console.log("Database imported.");
|
|
91
|
-
})
|
|
92
|
-
.catch(async (error) => {
|
|
93
|
-
await stopRunningMessage2();
|
|
94
|
-
throw error;
|
|
95
|
-
});
|
|
96
|
-
})
|
|
11
|
+
const smashConfig = await getSmashConfig(2);
|
|
12
|
+
const { projectName, staging: { url: stagingURL, dbPrefix: stagingDBPrefix, webRoot: stagingWebRoot, ssh: { username: stagingSSHUsername, host: stagingSSHHost, port: stagingSSHPort, }, }, } = smashConfig;
|
|
13
|
+
const stopRunningMessage = startRunningMessage("Pulling database from staging");
|
|
14
|
+
performance.mark("Start");
|
|
15
|
+
await (async () => {
|
|
16
|
+
const tmpFile = "/tmp/staging-database.sql";
|
|
17
|
+
const dbPrefixFile = "/tmp/db-prefix.txt";
|
|
18
|
+
const tablesToExclude = [
|
|
19
|
+
// WordFence
|
|
20
|
+
"wfauditevents",
|
|
21
|
+
"wfblockediplog",
|
|
22
|
+
"wfblocks7",
|
|
23
|
+
"wfconfig",
|
|
24
|
+
"wfcrawlers",
|
|
25
|
+
"wffilemods",
|
|
26
|
+
"wfhits",
|
|
27
|
+
"wfhoover",
|
|
28
|
+
"wfissues",
|
|
29
|
+
"wfknownfilelist",
|
|
30
|
+
"wflivetraffichuman",
|
|
31
|
+
"wflocs",
|
|
32
|
+
"wflogins",
|
|
33
|
+
"wfls_2fa_secrets",
|
|
34
|
+
"wfls_role_counts",
|
|
35
|
+
"wfls_settings",
|
|
36
|
+
"wfnotifications",
|
|
37
|
+
"wfpendingissues",
|
|
38
|
+
"wfreversecache",
|
|
39
|
+
"wfsecurityevents",
|
|
40
|
+
"wfsnipcache",
|
|
41
|
+
"wfstatus",
|
|
42
|
+
"wftrafficrates",
|
|
43
|
+
"wfwaffailures",
|
|
44
|
+
// WP All Import/Export
|
|
45
|
+
"pmxi_files",
|
|
46
|
+
"pmxi_geocoding",
|
|
47
|
+
"pmxi_hash",
|
|
48
|
+
"pmxi_history",
|
|
49
|
+
"pmxi_images",
|
|
50
|
+
"pmxi_imports",
|
|
51
|
+
"pmxi_posts",
|
|
52
|
+
"pmxi_templates",
|
|
53
|
+
].map((tableName) => stagingDBPrefix + tableName);
|
|
54
|
+
const port = stagingSSHPort ? `-p ${stagingSSHPort.toString()}` : ``;
|
|
55
|
+
await execute(`ssh -o "StrictHostKeyChecking no" ${stagingSSHUsername}@${stagingSSHHost} ${port} "${stagingWebRoot !== "" ? `cd ${stagingWebRoot} && ` : ""} wp db export - --add-drop-table --exclude_tables=${tablesToExclude.join(",")}" > ${tmpFile}`)
|
|
56
|
+
.then(async () => {
|
|
57
|
+
await stopRunningMessage();
|
|
58
|
+
console.log("Database downloaded.");
|
|
59
|
+
await execute(`wp db check`).catch(async () => {
|
|
60
|
+
await execute(`wp db create`);
|
|
61
|
+
console.log("Local database created.");
|
|
62
|
+
});
|
|
63
|
+
const stopRunningMessage2 = startRunningMessage("Importing database");
|
|
64
|
+
await execute(`wp db query < ${tmpFile}`)
|
|
97
65
|
.then(async () => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.then(async () => {
|
|
101
|
-
await stopRunningMessage3();
|
|
102
|
-
console.log("Search and replace completed.");
|
|
103
|
-
})
|
|
104
|
-
.catch(async (error) => {
|
|
105
|
-
await stopRunningMessage3();
|
|
106
|
-
throw error;
|
|
107
|
-
});
|
|
66
|
+
await stopRunningMessage2();
|
|
67
|
+
console.log("Database imported.");
|
|
108
68
|
})
|
|
69
|
+
.catch(async (error) => {
|
|
70
|
+
await stopRunningMessage2();
|
|
71
|
+
throw error;
|
|
72
|
+
});
|
|
73
|
+
})
|
|
74
|
+
.then(async () => {
|
|
75
|
+
const stopRunningMessage3 = startRunningMessage("Running search and replace");
|
|
76
|
+
await execute(`wp search-replace --url=${projectName}.test //${stagingURL} '//${projectName}.test'`)
|
|
109
77
|
.then(async () => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
deleteFile(tmpFile),
|
|
113
|
-
deleteFile(dbPrefixFile),
|
|
114
|
-
]).then(async () => {
|
|
115
|
-
await stopRunningMessage4();
|
|
116
|
-
});
|
|
117
|
-
console.log(`Database import complete! ${convertMeasureToPrettyString(performance.measure("everything", "Start"))}`);
|
|
118
|
-
console.log("If you want to download recent media you can use `npm run pull:media`, you can also change the number of months to download in your `.env` file.");
|
|
78
|
+
await stopRunningMessage3();
|
|
79
|
+
console.log("Search and replace completed.");
|
|
119
80
|
})
|
|
120
81
|
.catch(async (error) => {
|
|
121
|
-
await
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
82
|
+
await stopRunningMessage3();
|
|
83
|
+
throw error;
|
|
84
|
+
});
|
|
85
|
+
})
|
|
86
|
+
.then(async () => {
|
|
87
|
+
const stopRunningMessage4 = startRunningMessage("Cleaning up");
|
|
88
|
+
await Promise.allSettled([
|
|
89
|
+
deleteFile(tmpFile),
|
|
90
|
+
deleteFile(dbPrefixFile),
|
|
91
|
+
]).then(async () => {
|
|
92
|
+
await stopRunningMessage4();
|
|
132
93
|
});
|
|
133
|
-
|
|
134
|
-
|
|
94
|
+
console.log(`Database import complete! ${convertMeasureToPrettyString(performance.measure("everything", "Start"))}`);
|
|
95
|
+
console.log("If you want to download recent media you can use `npm run pull:media`, you can also change the number of months to download in your `.env` file.");
|
|
96
|
+
})
|
|
97
|
+
.catch(async (error) => {
|
|
98
|
+
await stopRunningMessage();
|
|
99
|
+
console.error("Error during database pull:", error);
|
|
100
|
+
const cleanupResults = await Promise.allSettled([
|
|
101
|
+
deleteFile(tmpFile),
|
|
102
|
+
deleteFile(dbPrefixFile),
|
|
103
|
+
]);
|
|
104
|
+
const failedCleanups = cleanupResults.filter((result) => result.status === "rejected");
|
|
105
|
+
if (failedCleanups.length > 0) {
|
|
106
|
+
console.warn(`Warning: Failed to delete ${failedCleanups.length.toString()} temporary file(s). You may need to clean them up manually.`);
|
|
107
|
+
}
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
});
|
|
110
|
+
})();
|
|
135
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull-media.d.ts","sourceRoot":"","sources":["../../src/commands/pull-media.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pull-media.d.ts","sourceRoot":"","sources":["../../src/commands/pull-media.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,OAAO,eAAe,CAAC;AACpC,eAAO,MAAM,QAAQ,gDAAgD,CAAC;AACtE,wBAAsB,OAAO,kBAgE5B"}
|
|
@@ -4,13 +4,15 @@ import { resolve } from "node:path";
|
|
|
4
4
|
import { performance } from "node:perf_hooks";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
6
|
import { startRunningMessage } from "../utils.js";
|
|
7
|
+
import { getSmashConfig } from "@atomicsmash/smash-config";
|
|
7
8
|
const execute = promisify(exec);
|
|
8
9
|
async function downloadFiles(remotePath, localPath, ssh) {
|
|
10
|
+
const port = ssh.port ? `-P ${ssh.port.toString()}` : ``;
|
|
9
11
|
try {
|
|
10
12
|
// Create local directory if it doesn't exist
|
|
11
13
|
await mkdir(localPath, { recursive: true });
|
|
12
14
|
// Download files using scp
|
|
13
|
-
await execute(`scp -r -p -O -o "StrictHostKeyChecking no"
|
|
15
|
+
await execute(`scp -r -p -O -o "StrictHostKeyChecking no" ${port} "${ssh.username}@${ssh.host}:${remotePath}" "${localPath}"`);
|
|
14
16
|
}
|
|
15
17
|
catch (error) {
|
|
16
18
|
console.log(`Failed to download ${remotePath}`);
|
|
@@ -23,78 +25,48 @@ async function downloadFiles(remotePath, localPath, ssh) {
|
|
|
23
25
|
export const command = "pull-media";
|
|
24
26
|
export const describe = "Pull the media items from the staging site.";
|
|
25
27
|
export async function handler() {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
host: stagingSSHHost,
|
|
57
|
-
username: stagingSSHUsername,
|
|
58
|
-
};
|
|
59
|
-
const stopRunningMessage = startRunningMessage("Pulling media from staging");
|
|
60
|
-
performance.mark("Start");
|
|
61
|
-
await (async () => {
|
|
62
|
-
if (mediaMonths === -1) {
|
|
63
|
-
console.log("Downloading entire uploads directory...");
|
|
64
|
-
const localPath = resolve(mediaLocalPath, "..");
|
|
65
|
-
console.log(`Downloading entire uploads directory: ${mediaPath} -> ${localPath}`);
|
|
66
|
-
await downloadFiles(mediaPath, localPath, ssh);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
console.log(`Downloading media for the last ${mediaMonths.toString()} months...`);
|
|
70
|
-
// Download media for each month
|
|
71
|
-
for (let i = 0; i < mediaMonths; i++) {
|
|
72
|
-
const date = new Date();
|
|
73
|
-
date.setMonth(date.getMonth() - i);
|
|
74
|
-
const year = date.getFullYear();
|
|
75
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
76
|
-
const remotePath = `${mediaPath}/${year.toString()}/${month}`;
|
|
77
|
-
const localPath = `${mediaLocalPath}/${year.toString()}`;
|
|
78
|
-
console.log(`Attempting to download: ${remotePath} -> ${localPath}`);
|
|
79
|
-
try {
|
|
80
|
-
await downloadFiles(remotePath, localPath, ssh);
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
console.log(`Skipping uploads/${year.toString()}/${month} - directory does not exist on remote server`);
|
|
84
|
-
return; // Skip to next iteration
|
|
85
|
-
}
|
|
28
|
+
const { uploadsPath: uploadsPath, staging: { uploadsPath: stagingUploadsPath, webRoot: stagingWebRoot, ssh: stagingSSHDetails, }, cli: { pullMedia: { monthsToPull }, }, } = await getSmashConfig(2);
|
|
29
|
+
const mediaMonths = monthsToPull;
|
|
30
|
+
const mediaServerPath = `${stagingWebRoot}/${stagingUploadsPath}`;
|
|
31
|
+
const mediaLocalPath = uploadsPath;
|
|
32
|
+
const stopRunningMessage = startRunningMessage("Pulling media from staging");
|
|
33
|
+
performance.mark("Start");
|
|
34
|
+
await (async () => {
|
|
35
|
+
if (mediaMonths === -1) {
|
|
36
|
+
console.log("Downloading entire uploads directory...");
|
|
37
|
+
const localPath = resolve(mediaLocalPath, "..");
|
|
38
|
+
console.log(`Downloading entire uploads directory: ${mediaServerPath} -> ${localPath}`);
|
|
39
|
+
await downloadFiles(mediaServerPath, localPath, stagingSSHDetails);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(`Downloading media for the last ${mediaMonths.toString()} months...`);
|
|
43
|
+
// Download media for each month
|
|
44
|
+
for (let i = 0; i < mediaMonths; i++) {
|
|
45
|
+
const date = new Date();
|
|
46
|
+
date.setMonth(date.getMonth() - i);
|
|
47
|
+
const year = date.getFullYear();
|
|
48
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
49
|
+
const remotePath = `${mediaServerPath}/${year.toString()}/${month}`;
|
|
50
|
+
const localPath = `${mediaLocalPath}/${year.toString()}`;
|
|
51
|
+
console.log(`Attempting to download: ${remotePath} -> ${localPath}`);
|
|
52
|
+
try {
|
|
53
|
+
await downloadFiles(remotePath, localPath, stagingSSHDetails);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
console.log(`Skipping uploads/${year.toString()}/${month} - directory does not exist on remote server`);
|
|
57
|
+
return; // Skip to next iteration
|
|
86
58
|
}
|
|
87
|
-
console.log("Finished attempting to download all requested months");
|
|
88
59
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
60
|
+
console.log("Finished attempting to download all requested months");
|
|
61
|
+
}
|
|
62
|
+
})()
|
|
63
|
+
.then(async () => {
|
|
64
|
+
await stopRunningMessage();
|
|
65
|
+
console.log("Media download complete!");
|
|
66
|
+
})
|
|
67
|
+
.catch(async () => {
|
|
68
|
+
await stopRunningMessage();
|
|
69
|
+
console.log("There was an error downloading the media, see the message above.");
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
});
|
|
100
72
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "dotenv/config";
|
|
2
2
|
export declare const command = "setup-database";
|
|
3
3
|
export declare const describe = "Create a new database and initialise the site with no content.";
|
|
4
|
+
export declare const deprecated = "You probably no longer need this with changes to the pull database script. If you do, migrate a copy of these commands into a local project script.";
|
|
4
5
|
export declare function handler(): Promise<void>;
|
|
5
6
|
//# sourceMappingURL=setup-database.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-database.d.ts","sourceRoot":"","sources":["../../src/commands/setup-database.ts"],"names":[],"mappings":"AAKA,OAAO,eAAe,CAAC;AA+EvB,eAAO,MAAM,OAAO,mBAAmB,CAAC;AACxC,eAAO,MAAM,QAAQ,mEAC4C,CAAC;AAClE,wBAAsB,OAAO,
|
|
1
|
+
{"version":3,"file":"setup-database.d.ts","sourceRoot":"","sources":["../../src/commands/setup-database.ts"],"names":[],"mappings":"AAKA,OAAO,eAAe,CAAC;AA+EvB,eAAO,MAAM,OAAO,mBAAmB,CAAC;AACxC,eAAO,MAAM,QAAQ,mEAC4C,CAAC;AAClE,eAAO,MAAM,UAAU,wJAC+H,CAAC;AACvJ,wBAAsB,OAAO,kBAuH5B"}
|
|
@@ -61,6 +61,7 @@ async function activatePluginsWithRetry(execute, pluginsToActivate, excludedPlug
|
|
|
61
61
|
}
|
|
62
62
|
export const command = "setup-database";
|
|
63
63
|
export const describe = "Create a new database and initialise the site with no content.";
|
|
64
|
+
export const deprecated = "You probably no longer need this with changes to the pull database script. If you do, migrate a copy of these commands into a local project script.";
|
|
64
65
|
export async function handler() {
|
|
65
66
|
const execute = promisify(exec);
|
|
66
67
|
const smashConfig = await getSmashConfig();
|
|
@@ -74,69 +75,64 @@ export async function handler() {
|
|
|
74
75
|
password: process.env.WORDPRESS_PASSWORD,
|
|
75
76
|
}
|
|
76
77
|
: null;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
console.error(error);
|
|
138
|
-
process.exitCode = 1;
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}
|
|
78
|
+
const { projectName, themeFolderName } = smashConfig;
|
|
79
|
+
const stopRunningMessage = startRunningMessage("Initialising database");
|
|
80
|
+
performance.mark("Start");
|
|
81
|
+
await execute("wp db create")
|
|
82
|
+
.then(() => {
|
|
83
|
+
return execute(`wp core install --url=http://${process.env.CI ? "127.0.0.1" : `${projectName}.test`}/ --title=Temp --admin_user=Bot --admin_email=fake@fake.com --admin_password=password`);
|
|
84
|
+
})
|
|
85
|
+
.then(() => {
|
|
86
|
+
performance.mark("wordpress-tables");
|
|
87
|
+
console.log(`Wordpress database tables installed. (${convertMeasureToPrettyString(performance.measure("wordpress-tables", "Start"))})`);
|
|
88
|
+
if (newUserToAdd) {
|
|
89
|
+
return execute(`wp user create ${newUserToAdd.user} ${newUserToAdd.email} --user_pass=${newUserToAdd.password} --role=administrator`);
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
.then(async () => {
|
|
93
|
+
if (newUserToAdd) {
|
|
94
|
+
performance.mark("add-custom-user");
|
|
95
|
+
console.log(`Custom user ${newUserToAdd.user} added. (${convertMeasureToPrettyString(performance.measure("add-custom-user", "wordpress-tables"))})`);
|
|
96
|
+
}
|
|
97
|
+
const excludedPlugins = [
|
|
98
|
+
"stream",
|
|
99
|
+
"shortpixel-image-optimiser",
|
|
100
|
+
"wordfence",
|
|
101
|
+
"wp-mail-smtp",
|
|
102
|
+
"modular-connector",
|
|
103
|
+
];
|
|
104
|
+
const { stdout: pluginList } = await execute("wp plugin list --format=json");
|
|
105
|
+
const allPlugins = JSON.parse(pluginList);
|
|
106
|
+
// Filter out excluded plugins and already active plugins
|
|
107
|
+
const pluginsToActivate = allPlugins
|
|
108
|
+
.filter((plugin) => !excludedPlugins.includes(plugin.name) &&
|
|
109
|
+
plugin.status !== "active")
|
|
110
|
+
.map((plugin) => plugin.name);
|
|
111
|
+
await activatePluginsWithRetry(execute, pluginsToActivate, excludedPlugins);
|
|
112
|
+
})
|
|
113
|
+
.then(() => {
|
|
114
|
+
performance.mark("plugins");
|
|
115
|
+
console.log(`Plugins activated. (${convertMeasureToPrettyString(performance.measure("plugins", newUserToAdd ? "add-custom-user" : "wordpress-tables"))})`);
|
|
116
|
+
return execute(`wp theme activate ${themeFolderName}`);
|
|
117
|
+
})
|
|
118
|
+
.then(async () => {
|
|
119
|
+
performance.mark("theme");
|
|
120
|
+
console.log(`Theme activated. (${convertMeasureToPrettyString(performance.measure("theme", "plugins"))})`);
|
|
121
|
+
await stopRunningMessage();
|
|
122
|
+
console.log(`Database set up${newUserToAdd ? ` and ${newUserToAdd.user} user added` : !process.env.CI ? ". To set up a user, run the `wp user create` command." : ""}. (${convertMeasureToPrettyString(performance.measure("everything", "Start"))})`);
|
|
123
|
+
})
|
|
124
|
+
.catch(async (error) => {
|
|
125
|
+
await stopRunningMessage();
|
|
126
|
+
if (typeof error === "object" &&
|
|
127
|
+
error &&
|
|
128
|
+
"stderr" in error &&
|
|
129
|
+
typeof error.stderr === "string" &&
|
|
130
|
+
error.stderr.startsWith("ERROR 1007")) {
|
|
131
|
+
console.error("Database already exists with the name in the wp-config. Please delete that database first with `wp db drop --yes`");
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.error(error);
|
|
135
|
+
process.exitCode = 1;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
142
138
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,QAAQ,kDAAkD,CAAC;AACxE,wBAAsB,OAAO,
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,QAAQ,kDAAkD,CAAC;AACxE,wBAAsB,OAAO,kBA+P5B"}
|
package/dist/commands/setup.js
CHANGED
|
@@ -20,167 +20,162 @@ export async function handler() {
|
|
|
20
20
|
});
|
|
21
21
|
const isCI = process.env.CI ?? false;
|
|
22
22
|
const smashConfig = await getSmashConfig();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
else {
|
|
40
|
-
console.log("Moving .env.example to .config/environments/.env.dev");
|
|
41
|
-
if (!existsSync(".config/environments")) {
|
|
42
|
-
await mkdir(".config/environments", { recursive: true });
|
|
43
|
-
}
|
|
44
|
-
await copyFile(".env.example", ".config/environments/.env.dev", constants.COPYFILE_EXCL);
|
|
45
|
-
await deleteFile(".env.example");
|
|
23
|
+
const { projectName, composerInstallPaths, npmInstallPaths } = smashConfig;
|
|
24
|
+
const stopRunningMessage = startRunningMessage("Running setup");
|
|
25
|
+
performance.mark("Start");
|
|
26
|
+
await Promise.allSettled([
|
|
27
|
+
...(isCI || shouldInstallAndBuildOnly
|
|
28
|
+
? []
|
|
29
|
+
: [
|
|
30
|
+
(async () => {
|
|
31
|
+
if (existsSync(".env.example")) {
|
|
32
|
+
if (existsSync(".config/environments/.env.dev")) {
|
|
33
|
+
throw new Error("Both .env.example and .config/environments/.env.dev files found. Please copy values from the .env.example to the .config/environments/.env.dev file and then delete the .env.example file.");
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log("Moving .env.example to .config/environments/.env.dev");
|
|
37
|
+
if (!existsSync(".config/environments")) {
|
|
38
|
+
await mkdir(".config/environments", { recursive: true });
|
|
46
39
|
}
|
|
40
|
+
await copyFile(".env.example", ".config/environments/.env.dev", constants.COPYFILE_EXCL);
|
|
41
|
+
await deleteFile(".env.example");
|
|
47
42
|
}
|
|
48
|
-
|
|
43
|
+
}
|
|
44
|
+
await copyFile(".config/environments/.env.dev", ".env", constants.COPYFILE_EXCL)
|
|
45
|
+
.then(() => {
|
|
46
|
+
console.log(`.config/environments/.env.dev file copied to .env. (${convertMeasureToPrettyString(performance.measure("Copy env file", "Start"))})`);
|
|
47
|
+
})
|
|
48
|
+
.catch((error) => {
|
|
49
|
+
if (error instanceof Error &&
|
|
50
|
+
"code" in error &&
|
|
51
|
+
error.code === "EEXIST") {
|
|
52
|
+
console.log(`Didn't copy .env file because one already exists. (${convertMeasureToPrettyString(performance.measure("Copy env file", "Start"))})`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.error(error);
|
|
56
|
+
throw new Error("Failed to copy .env file.");
|
|
57
|
+
});
|
|
58
|
+
})(),
|
|
59
|
+
(async () => {
|
|
60
|
+
const ONE_MINUTE_IN_MS = 60000;
|
|
61
|
+
const timeout = setTimeout(() => {
|
|
62
|
+
throw new Error("Herd/Valet commands timed out. Please try again.");
|
|
63
|
+
}, ONE_MINUTE_IN_MS * 1.5);
|
|
64
|
+
if (await execute(`herd --version`)
|
|
65
|
+
.then(() => true)
|
|
66
|
+
.catch(() => false)) {
|
|
67
|
+
if (!existsSync(resolve(process.cwd(), "herd.yaml")) &&
|
|
68
|
+
!existsSync(resolve(process.cwd(), "herd.yml"))) {
|
|
69
|
+
throw new Error("Herd is present on your machine, but the project is missing a herd.yaml file. Please do the initial setup by running herd init.");
|
|
70
|
+
}
|
|
71
|
+
await execute(`herd link ${projectName} --secure`)
|
|
49
72
|
.then(() => {
|
|
50
|
-
|
|
73
|
+
performance.mark("herd link done");
|
|
74
|
+
console.log(`Herd is linked and secured. (${convertMeasureToPrettyString(performance.measure("herd link", "Start"))})`);
|
|
51
75
|
})
|
|
52
76
|
.catch((error) => {
|
|
53
|
-
if (error instanceof Error &&
|
|
54
|
-
"code" in error &&
|
|
55
|
-
error.code === "EEXIST") {
|
|
56
|
-
console.log(`Didn't copy .env file because one already exists. (${convertMeasureToPrettyString(performance.measure("Copy env file", "Start"))})`);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
77
|
console.error(error);
|
|
60
|
-
throw new Error("Failed to
|
|
78
|
+
throw new Error("Failed to link the site using Herd.");
|
|
61
79
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
console.log(`Valet is linked, secured and isolated. (${convertMeasureToPrettyString(performance.measure("herd-or-valet", "Start"))})`);
|
|
101
|
-
})
|
|
102
|
-
.catch((error) => {
|
|
103
|
-
console.error(error);
|
|
104
|
-
throw new Error("Failed to link the site using valet.");
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
throw new Error(`Neither Herd nor Valet is present on your machine, check everything is installed correctly.`);
|
|
109
|
-
}
|
|
110
|
-
})(),
|
|
111
|
-
]),
|
|
112
|
-
execute(`composer install${isCI ? " --prefer-dist" : ""}`)
|
|
80
|
+
await execute(`herd isolate --site=${projectName}`)
|
|
81
|
+
.then(() => {
|
|
82
|
+
console.log(`Herd is isolated. (${convertMeasureToPrettyString(performance.measure("herd isolate", "herd link done"))})`);
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
})
|
|
85
|
+
.catch((error) => {
|
|
86
|
+
console.error(error);
|
|
87
|
+
throw new Error("Failed to isolate the site using Herd.");
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else if (await execute(`valet --version`)
|
|
91
|
+
.then(() => true)
|
|
92
|
+
.catch(() => false)) {
|
|
93
|
+
await execute(`valet link ${projectName} --secure --isolate`)
|
|
94
|
+
.then(() => {
|
|
95
|
+
clearTimeout(timeout);
|
|
96
|
+
console.log(`Valet is linked, secured and isolated. (${convertMeasureToPrettyString(performance.measure("herd-or-valet", "Start"))})`);
|
|
97
|
+
})
|
|
98
|
+
.catch((error) => {
|
|
99
|
+
console.error(error);
|
|
100
|
+
throw new Error("Failed to link the site using valet.");
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
throw new Error(`Neither Herd nor Valet is present on your machine, check everything is installed correctly.`);
|
|
105
|
+
}
|
|
106
|
+
})(),
|
|
107
|
+
]),
|
|
108
|
+
execute(`composer install${isCI ? " --prefer-dist" : ""}`)
|
|
109
|
+
.then(() => {
|
|
110
|
+
console.log(`Root composer install done. (${convertMeasureToPrettyString(performance.measure("root composer install", "Start"))})`);
|
|
111
|
+
})
|
|
112
|
+
.catch((error) => {
|
|
113
|
+
console.error(error);
|
|
114
|
+
throw new Error("Failed to run composer install in the root directory.");
|
|
115
|
+
}),
|
|
116
|
+
...composerInstallPaths.map((path, index) => {
|
|
117
|
+
return execute(`cd "${resolve(process.cwd(), path)}"; composer install${isCI ? " --no-dev --classmap-authoritative" : ""}`)
|
|
113
118
|
.then(() => {
|
|
114
|
-
console.log(`
|
|
119
|
+
console.log(`Additional composer install ${(index + 1).toString()} done. (${convertMeasureToPrettyString(performance.measure(`additional composer install ${(index + 1).toString()}`, "Start"))})`);
|
|
115
120
|
})
|
|
116
121
|
.catch((error) => {
|
|
117
122
|
console.error(error);
|
|
118
|
-
throw new Error(
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
console.log(`Initial build done. (${convertMeasureToPrettyString(performance.measure("build", "root npm install done"))})`);
|
|
143
|
-
})
|
|
144
|
-
.catch((error) => {
|
|
145
|
-
console.error(error);
|
|
146
|
-
throw new Error("Failed to run a build after installing.");
|
|
147
|
-
});
|
|
148
|
-
})().catch((reason) => {
|
|
149
|
-
if (typeof reason === "string") {
|
|
150
|
-
throw new Error(reason);
|
|
151
|
-
}
|
|
152
|
-
throw reason;
|
|
153
|
-
}),
|
|
154
|
-
...npmInstallPaths.map((path, index) => {
|
|
155
|
-
return execute(`cd "${resolve(process.cwd(), path)}"; npm ${isCI ? "ci --omit=dev" : "install"}`)
|
|
156
|
-
.then(() => {
|
|
157
|
-
console.log(`Additional npm install ${(index + 1).toString()} done. (${convertMeasureToPrettyString(performance.measure(`additional npm install ${(index + 1).toString()}`, "Start"))})`);
|
|
158
|
-
})
|
|
159
|
-
.catch((error) => {
|
|
160
|
-
console.error(error);
|
|
161
|
-
throw new Error(`Failed to run additional npm install ${(index + 1).toString()}.`);
|
|
162
|
-
});
|
|
163
|
-
}),
|
|
164
|
-
])
|
|
165
|
-
.then(async (results) => {
|
|
166
|
-
await stopRunningMessage();
|
|
167
|
-
if (results.some((result) => result.status === "rejected")) {
|
|
168
|
-
process.exitCode = 1;
|
|
169
|
-
console.error("Setup failed with the following errors:\n");
|
|
170
|
-
console.error(results
|
|
171
|
-
.filter((result) => result.status === "rejected")
|
|
172
|
-
.map((result) => {
|
|
173
|
-
return `- ${typeof result.reason === "string" ? result.reason : "Unknown reason."}`;
|
|
174
|
-
})
|
|
175
|
-
.join(`\n`));
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
console.log(`Setup is complete. ${convertMeasureToPrettyString(performance.measure("everything", "Start"))}`);
|
|
123
|
+
throw new Error(`Failed to run additional composer install ${(index + 1).toString()}.`);
|
|
124
|
+
});
|
|
125
|
+
}),
|
|
126
|
+
(async () => {
|
|
127
|
+
await execute(`npm ${isCI ? "ci" : "install"}`)
|
|
128
|
+
.then(() => {
|
|
129
|
+
performance.mark("root npm install done");
|
|
130
|
+
console.log(`Root npm install done. (${convertMeasureToPrettyString(performance.measure("root npm install", "Start"))})`);
|
|
131
|
+
})
|
|
132
|
+
.catch((error) => {
|
|
133
|
+
console.error(error);
|
|
134
|
+
throw new Error("Failed to run npm install in the root directory.");
|
|
135
|
+
});
|
|
136
|
+
await execute("npm run build")
|
|
137
|
+
.then(() => {
|
|
138
|
+
console.log(`Initial build done. (${convertMeasureToPrettyString(performance.measure("build", "root npm install done"))})`);
|
|
139
|
+
})
|
|
140
|
+
.catch((error) => {
|
|
141
|
+
console.error(error);
|
|
142
|
+
throw new Error("Failed to run a build after installing.");
|
|
143
|
+
});
|
|
144
|
+
})().catch((reason) => {
|
|
145
|
+
if (typeof reason === "string") {
|
|
146
|
+
throw new Error(reason);
|
|
179
147
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
148
|
+
throw reason;
|
|
149
|
+
}),
|
|
150
|
+
...npmInstallPaths.map((path, index) => {
|
|
151
|
+
return execute(`cd "${resolve(process.cwd(), path)}"; npm ${isCI ? "ci --omit=dev" : "install"}`)
|
|
152
|
+
.then(() => {
|
|
153
|
+
console.log(`Additional npm install ${(index + 1).toString()} done. (${convertMeasureToPrettyString(performance.measure(`additional npm install ${(index + 1).toString()}`, "Start"))})`);
|
|
154
|
+
})
|
|
155
|
+
.catch((error) => {
|
|
156
|
+
console.error(error);
|
|
157
|
+
throw new Error(`Failed to run additional npm install ${(index + 1).toString()}.`);
|
|
158
|
+
});
|
|
159
|
+
}),
|
|
160
|
+
])
|
|
161
|
+
.then(async (results) => {
|
|
162
|
+
await stopRunningMessage();
|
|
163
|
+
if (results.some((result) => result.status === "rejected")) {
|
|
183
164
|
process.exitCode = 1;
|
|
184
|
-
|
|
185
|
-
|
|
165
|
+
console.error("Setup failed with the following errors:\n");
|
|
166
|
+
console.error(results
|
|
167
|
+
.filter((result) => result.status === "rejected")
|
|
168
|
+
.map((result) => {
|
|
169
|
+
return `- ${typeof result.reason === "string" ? result.reason : "Unknown reason."}`;
|
|
170
|
+
})
|
|
171
|
+
.join(`\n`));
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.log(`Setup is complete. ${convertMeasureToPrettyString(performance.measure("everything", "Start"))}`);
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
.catch((error) => {
|
|
178
|
+
console.error(error);
|
|
179
|
+
process.exitCode = 1;
|
|
180
|
+
});
|
|
186
181
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toggle-media-proxy.d.ts","sourceRoot":"","sources":["../../src/commands/toggle-media-proxy.ts"],"names":[],"mappings":"AAuEA,eAAO,MAAM,OAAO,uBAAuB,CAAC;AAC5C,eAAO,MAAM,QAAQ,kEAC2C,CAAC;AAEjE,wBAAsB,OAAO,kBA2D5B"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir, type } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { getSmashConfig } from "@atomicsmash/smash-config";
|
|
7
|
+
const PROXY_MARKER = "location @uploadsproxy";
|
|
8
|
+
const execute = promisify(exec);
|
|
9
|
+
function buildProxyBlock(stagingURL, httpAuth) {
|
|
10
|
+
const authHeader = httpAuth
|
|
11
|
+
? `\n proxy_set_header Authorization "Basic ${httpAuth}";`
|
|
12
|
+
: "";
|
|
13
|
+
return `
|
|
14
|
+
location ^~ /wp-content/uploads/ {
|
|
15
|
+
try_files $uri @uploadsproxy;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
location @uploadsproxy {
|
|
19
|
+
resolver 8.8.8.8 ipv6=off;
|
|
20
|
+
resolver_timeout 10s;
|
|
21
|
+
proxy_http_version 1.1;
|
|
22
|
+
proxy_ssl_server_name on;
|
|
23
|
+
proxy_pass https://${stagingURL}$uri$is_args$args;
|
|
24
|
+
proxy_ssl_verify off;
|
|
25
|
+
proxy_set_header Referer "";
|
|
26
|
+
proxy_set_header User-Agent "Mozilla/5.0";${authHeader}
|
|
27
|
+
}`;
|
|
28
|
+
}
|
|
29
|
+
function addProxyBlock(config, stagingURL, httpAuth) {
|
|
30
|
+
const listenDirective = "listen 127.0.0.1:443 ssl;";
|
|
31
|
+
const listenIndex = config.indexOf(listenDirective);
|
|
32
|
+
if (listenIndex === -1) {
|
|
33
|
+
throw new Error("Could not locate the SSL server block (listen 127.0.0.1:443 ssl;) in the NGINX config.");
|
|
34
|
+
}
|
|
35
|
+
const nextServerBlockIndex = config.indexOf("\nserver", listenIndex);
|
|
36
|
+
const searchUpTo = nextServerBlockIndex !== -1 ? nextServerBlockIndex : config.length;
|
|
37
|
+
const serverBlockEnd = config.lastIndexOf("}", searchUpTo);
|
|
38
|
+
if (serverBlockEnd === -1 || serverBlockEnd < listenIndex) {
|
|
39
|
+
throw new Error("Could not locate the closing brace of the SSL server block.");
|
|
40
|
+
}
|
|
41
|
+
return (config.slice(0, serverBlockEnd) +
|
|
42
|
+
buildProxyBlock(stagingURL, httpAuth) +
|
|
43
|
+
"\n" +
|
|
44
|
+
config.slice(serverBlockEnd));
|
|
45
|
+
}
|
|
46
|
+
function removeProxyBlock(config) {
|
|
47
|
+
return config.replace(/\n\s*location \^~ \/wp-content\/uploads\/\s*\{[\s\S]*?location @uploadsproxy\s*\{[\s\S]*?\}/, "");
|
|
48
|
+
}
|
|
49
|
+
export const command = "toggle-media-proxy";
|
|
50
|
+
export const describe = "Toggle the media proxy in the local NGINX config within Herd.";
|
|
51
|
+
export async function handler() {
|
|
52
|
+
const smashConfig = await getSmashConfig(2);
|
|
53
|
+
const { projectName, staging: { url: stagingURL, httpAuth: stagingHttpAuth }, } = smashConfig;
|
|
54
|
+
const isMacOS = type() === "Darwin";
|
|
55
|
+
const nginxConfigPath = join(homedir(), isMacOS
|
|
56
|
+
? "Library/Application Support/Herd/config/valet/Nginx"
|
|
57
|
+
: ".config\\herd\\config\\nginx", `${projectName}.test`);
|
|
58
|
+
let config;
|
|
59
|
+
try {
|
|
60
|
+
config = await readFile(nginxConfigPath, "utf-8");
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
throw new Error(`Could not read NGINX config at: ${nginxConfigPath}\nMake sure the site exists in Herd.`);
|
|
64
|
+
}
|
|
65
|
+
const httpAuth = stagingHttpAuth
|
|
66
|
+
? Buffer.from(`${stagingHttpAuth.username}:${stagingHttpAuth.password}`).toString("base64")
|
|
67
|
+
: undefined;
|
|
68
|
+
let updatedConfig;
|
|
69
|
+
if (config.includes(PROXY_MARKER)) {
|
|
70
|
+
updatedConfig = removeProxyBlock(config);
|
|
71
|
+
console.log("Media proxy removed from NGINX config.");
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
updatedConfig = addProxyBlock(config, stagingURL, httpAuth);
|
|
75
|
+
if (httpAuth) {
|
|
76
|
+
console.log("Media proxy added to NGINX config (with HTTP auth).");
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.log("Media proxy added to NGINX config (no HTTP auth — STAGING_HTTP_AUTH_USERNAME and STAGING_HTTP_AUTH_PASSWORD not set).");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
await writeFile(nginxConfigPath, updatedConfig, "utf-8");
|
|
83
|
+
console.log("Restarting Herd...");
|
|
84
|
+
await execute("herd restart")
|
|
85
|
+
.then(() => {
|
|
86
|
+
console.log("Herd restarted successfully.");
|
|
87
|
+
})
|
|
88
|
+
.catch(() => {
|
|
89
|
+
console.log("Failed to restart Herd automatically.");
|
|
90
|
+
});
|
|
91
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomicsmash/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0-beta.1",
|
|
4
4
|
"description": "A collection of CLI tools by Atomic Smash.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://www.atomicsmash.co.uk/",
|
|
@@ -40,21 +40,11 @@
|
|
|
40
40
|
"lint:types": "tsc -b"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@atomicsmash/
|
|
44
|
-
"
|
|
45
|
-
"@types/vinyl": "^2.0.12",
|
|
46
|
-
"glob-promise": "^6.0.7",
|
|
47
|
-
"svg-sprite": "^2.0.4",
|
|
48
|
-
"vinyl": "^3.0.1",
|
|
43
|
+
"@atomicsmash/smash-config": "^2.0.0-beta.1",
|
|
44
|
+
"dotenv": "^17.4.2",
|
|
49
45
|
"yargs": "^18.0.0"
|
|
50
46
|
},
|
|
51
47
|
"devDependencies": {
|
|
52
|
-
"
|
|
53
|
-
"@types/svg-sprite": "^0.0.39",
|
|
54
|
-
"type-fest": "^5.6.0"
|
|
55
|
-
},
|
|
56
|
-
"peerDependencies": {
|
|
57
|
-
"dotenv": "^17.3.1",
|
|
58
|
-
"typescript": "~5.9.3"
|
|
48
|
+
"type-fest": "^5.7.0"
|
|
59
49
|
}
|
|
60
50
|
}
|
package/dist/commands/svg.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { YargsInstance } from "../cli.js";
|
|
2
|
-
import type { ArgumentsCamelCase } from "yargs";
|
|
3
|
-
export declare const command = "svg";
|
|
4
|
-
export declare const describe = "Generate an SVG sprite from a group of SVGs.";
|
|
5
|
-
export declare const deprecated = "Migrate to using @atomicsmash/compiler, which supports an icons folder in the src folder.";
|
|
6
|
-
export declare const builder: (yargs: YargsInstance) => import("yargs").Argv<import("yargs").Omit<{}, "in" | "out"> & import("yargs").InferredOptionTypes<{
|
|
7
|
-
in: {
|
|
8
|
-
demandOption: true;
|
|
9
|
-
string: true;
|
|
10
|
-
normalize: true;
|
|
11
|
-
description: string;
|
|
12
|
-
};
|
|
13
|
-
out: {
|
|
14
|
-
demandOption: true;
|
|
15
|
-
string: true;
|
|
16
|
-
normalize: true;
|
|
17
|
-
description: string;
|
|
18
|
-
};
|
|
19
|
-
}>>;
|
|
20
|
-
export declare function handler(args: ArgumentsCamelCase<Awaited<ReturnType<typeof builder>["argv"]>>): void;
|
|
21
|
-
//# sourceMappingURL=svg.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../src/commands/svg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAOhD,eAAO,MAAM,OAAO,QAAQ,CAAC;AAC7B,eAAO,MAAM,QAAQ,iDAAiD,CAAC;AACvE,eAAO,MAAM,UAAU,8FACqE,CAAC;AAC7F,eAAO,MAAM,OAAO,GAAa,OAAO,aAAa;;;;;;;;;;;;;GAiBpD,CAAC;AAEF,wBAAgB,OAAO,CACtB,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAmErE"}
|
package/dist/commands/svg.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { readFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { resolve as resolvePath, join as joinPath, dirname } from "path";
|
|
3
|
-
import glob from "glob-promise";
|
|
4
|
-
import SVGSpriter from "svg-sprite";
|
|
5
|
-
import File from "vinyl";
|
|
6
|
-
export const command = "svg";
|
|
7
|
-
export const describe = "Generate an SVG sprite from a group of SVGs.";
|
|
8
|
-
export const deprecated = "Migrate to using @atomicsmash/compiler, which supports an icons folder in the src folder.";
|
|
9
|
-
export const builder = function (yargs) {
|
|
10
|
-
return yargs
|
|
11
|
-
.options({
|
|
12
|
-
in: {
|
|
13
|
-
demandOption: true,
|
|
14
|
-
string: true,
|
|
15
|
-
normalize: true,
|
|
16
|
-
description: "The directory where the SVGs can be found.",
|
|
17
|
-
},
|
|
18
|
-
out: {
|
|
19
|
-
demandOption: true,
|
|
20
|
-
string: true,
|
|
21
|
-
normalize: true,
|
|
22
|
-
description: "The directory where the SVG sprite will be output.",
|
|
23
|
-
},
|
|
24
|
-
})
|
|
25
|
-
.example("$0 svg --in icons --out public/assets", "");
|
|
26
|
-
};
|
|
27
|
-
export function handler(args) {
|
|
28
|
-
const config = {
|
|
29
|
-
dest: args.out,
|
|
30
|
-
shape: {
|
|
31
|
-
dimension: {
|
|
32
|
-
attributes: false,
|
|
33
|
-
},
|
|
34
|
-
transform: [
|
|
35
|
-
{
|
|
36
|
-
svgo: {},
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
mode: {
|
|
41
|
-
symbol: {
|
|
42
|
-
dest: "",
|
|
43
|
-
sprite: "sprite.svg",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
const spriter = new SVGSpriter(config);
|
|
48
|
-
const cwd = resolvePath(args.in);
|
|
49
|
-
// Find SVG files recursively via `glob`
|
|
50
|
-
glob("**/*.svg", { cwd })
|
|
51
|
-
.then(async (files) => {
|
|
52
|
-
await new Promise((resolve) => {
|
|
53
|
-
files.forEach((file) => {
|
|
54
|
-
// Create and add a vinyl file instance for each SVG
|
|
55
|
-
spriter.add(new File({
|
|
56
|
-
path: joinPath(cwd, file), // Absolute path to the SVG file
|
|
57
|
-
base: cwd, // Base path (see `name` argument)
|
|
58
|
-
contents: readFileSync(joinPath(cwd, file)), // SVG file contents
|
|
59
|
-
}));
|
|
60
|
-
});
|
|
61
|
-
resolve();
|
|
62
|
-
})
|
|
63
|
-
.then(async () => {
|
|
64
|
-
await spriter
|
|
65
|
-
.compileAsync()
|
|
66
|
-
.then((compiledResponse) => {
|
|
67
|
-
const { result } = compiledResponse;
|
|
68
|
-
for (const type of Object.values(result.symbol)) {
|
|
69
|
-
if (type.contents) {
|
|
70
|
-
mkdirSync(dirname(type.path), { recursive: true });
|
|
71
|
-
// TODO: find out how to remove this error.
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- This works despite this error.
|
|
73
|
-
writeFileSync(type.path, type.contents.toString());
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
})
|
|
78
|
-
.then(() => {
|
|
79
|
-
console.log(`SVG sprite was successfully generated in ${args.out}.`);
|
|
80
|
-
});
|
|
81
|
-
})
|
|
82
|
-
.catch((error) => {
|
|
83
|
-
console.error({ error });
|
|
84
|
-
throw error;
|
|
85
|
-
});
|
|
86
|
-
}
|