@cocreate/cli 1.49.0 → 1.51.0
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/CHANGELOG.md +29 -0
- package/CoCreate.config.js +498 -413
- package/docs/index.html +250 -250
- package/package.json +5 -5
- package/prettier.config.js +2 -0
- package/src/addMeta.js +74 -67
- package/src/coc.js +166 -114
- package/src/commands/acme.js +19 -22
- package/src/commands/bump.js +149 -87
- package/src/commands/clone.js +26 -22
- package/src/commands/fs/automated.js +1 -1
- package/src/commands/fs/config.js +1 -1
- package/src/commands/fs/gitignore.js +13 -22
- package/src/commands/fs/manual.js +17 -27
- package/src/commands/fs/prettier.config.js +1 -1
- package/src/commands/fs/remove.js +7 -12
- package/src/commands/fs/replace.js +23 -31
- package/src/commands/fs/webpack.js +143 -149
- package/src/commands/install.js +18 -22
- package/src/commands/link.js +73 -60
- package/src/commands/nginx.js +19 -22
- package/src/commands/symlink.js +132 -115
- package/src/execute.js +63 -50
- package/src/index.js +3 -0
- package/src/spinner.js +85 -0
package/src/commands/symlink.js
CHANGED
|
@@ -1,136 +1,153 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require("path")
|
|
3
|
-
const spawn = require(
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const spawn = require("../spawn");
|
|
4
4
|
|
|
5
5
|
const cwdPath = path.resolve(process.cwd());
|
|
6
|
-
let cwdNodeModulesPath = path.resolve(cwdPath,
|
|
6
|
+
let cwdNodeModulesPath = path.resolve(cwdPath, "node_modules");
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
let reposLength,
|
|
9
|
+
failed = [];
|
|
10
10
|
|
|
11
11
|
module.exports = async function (repos, args) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
12
|
+
reposLength = repos.length;
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < repos.length; i++) {
|
|
15
|
+
if (
|
|
16
|
+
cwdPath === repos[i].absolutePath &&
|
|
17
|
+
!fs.existsSync(cwdNodeModulesPath)
|
|
18
|
+
) {
|
|
19
|
+
await install(repos[i], repos);
|
|
20
|
+
reposLength -= 1;
|
|
21
|
+
} else if (repos[i].install == true) {
|
|
22
|
+
reposLength -= 1;
|
|
23
|
+
await install(repos[i], repos);
|
|
24
|
+
} else if (cwdPath !== repos[i].absolutePath) {
|
|
25
|
+
await createSymlink(repos[i]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log("symlink complete");
|
|
30
|
+
return failed;
|
|
31
|
+
};
|
|
33
32
|
|
|
34
33
|
async function createSymlink(repo) {
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
34
|
+
let dpath = path.resolve(repo.absolutePath);
|
|
35
|
+
if (!fs.existsSync(dpath)) {
|
|
36
|
+
failed.push({
|
|
37
|
+
name: "createSymlink",
|
|
38
|
+
error: "path doesn't exist:" + dpath
|
|
39
|
+
});
|
|
40
|
+
return console.error(dpath, "not exist");
|
|
41
|
+
}
|
|
42
|
+
let response = "";
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
let dest = path.resolve(dpath, "node_modules");
|
|
46
|
+
if (dest) {
|
|
47
|
+
if (fs.existsSync(dest)) {
|
|
48
|
+
if (!cwdNodeModulesPath.includes("/CoCreateJS")) {
|
|
49
|
+
let isSymlink = await isSymlinkDirectory(dest);
|
|
50
|
+
if (isSymlink) {
|
|
51
|
+
const targetPath = await getSymlinkTargetPath(dest);
|
|
52
|
+
if (targetPath.includes("/CoCreateJS")) {
|
|
53
|
+
console.warn(
|
|
54
|
+
"symlink already exists with CoCreateJS"
|
|
55
|
+
);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
await symlink(repo.name, dest);
|
|
63
|
+
}
|
|
64
|
+
} catch (err) {
|
|
65
|
+
failed.push({
|
|
66
|
+
name: "symlink",
|
|
67
|
+
error: "with response:" + response + err
|
|
68
|
+
});
|
|
69
|
+
console.error(
|
|
70
|
+
repo.name,
|
|
71
|
+
"failed to aquire symlink",
|
|
72
|
+
"with response:",
|
|
73
|
+
response,
|
|
74
|
+
err
|
|
75
|
+
);
|
|
76
|
+
}
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
async function symlink(name, dest) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
try {
|
|
81
|
+
if (fs.existsSync(dest))
|
|
82
|
+
await fs.promises.rm(dest, { recursive: true, force: true });
|
|
83
|
+
|
|
84
|
+
await fs.promises.symlink(cwdNodeModulesPath, dest, "dir");
|
|
85
|
+
console.log(name, "node_modules symlink added");
|
|
86
|
+
} catch (err) {
|
|
87
|
+
failed.push({
|
|
88
|
+
name: "symlink",
|
|
89
|
+
error: "with response: " + response,
|
|
90
|
+
err
|
|
91
|
+
});
|
|
92
|
+
console.error(
|
|
93
|
+
repo.name,
|
|
94
|
+
"failed to acquire symlink",
|
|
95
|
+
"with response:",
|
|
96
|
+
response,
|
|
97
|
+
err
|
|
98
|
+
);
|
|
99
|
+
}
|
|
82
100
|
}
|
|
83
101
|
|
|
84
|
-
|
|
85
102
|
async function install(repo, repos) {
|
|
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
|
-
|
|
103
|
+
let dpath = repo.absolutePath;
|
|
104
|
+
if (!fs.existsSync(dpath)) {
|
|
105
|
+
failed.push({ name: "install", error: "path doesn't exist:" + dpath });
|
|
106
|
+
return console.error(dpath, "not exist");
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
console.log("installing", repo.name);
|
|
110
|
+
let exitCode = await spawn(repo.packageManager, ["install"], {
|
|
111
|
+
cwd: repo.absolutePath,
|
|
112
|
+
shell: true,
|
|
113
|
+
stdio: "inherit"
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (exitCode !== 0) {
|
|
117
|
+
failed.push({
|
|
118
|
+
name: repo.name,
|
|
119
|
+
error: `${repo.packageManager} install failed`
|
|
120
|
+
});
|
|
121
|
+
console.error(
|
|
122
|
+
`${repo.name}: ${repo.packageManager} install failed`.red
|
|
123
|
+
);
|
|
124
|
+
} else {
|
|
125
|
+
console.log(
|
|
126
|
+
`${repo.name}: ${repo.packageManager} install succesful`.green
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.error(repo.name, "did not install", err);
|
|
131
|
+
}
|
|
115
132
|
}
|
|
116
133
|
|
|
117
134
|
async function isSymlinkDirectory(path) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
try {
|
|
136
|
+
const stats = await fs.promises.lstat(path);
|
|
137
|
+
return stats.isSymbolicLink();
|
|
138
|
+
} catch (err) {
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
async function getSymlinkTargetPath(symlinkPath) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
144
|
+
try {
|
|
145
|
+
const target = await fs.promises.readlink(symlinkPath);
|
|
146
|
+
const targetPath = fs.realpathSync(target);
|
|
147
|
+
return targetPath;
|
|
148
|
+
} catch (err) {
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
134
151
|
}
|
|
135
152
|
|
|
136
|
-
// module.exports = { symlink }
|
|
153
|
+
// module.exports = { symlink }
|
package/src/execute.js
CHANGED
|
@@ -1,65 +1,78 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
2
|
const fs = require("fs");
|
|
3
|
-
const spawn = require(
|
|
4
|
-
const util = require(
|
|
5
|
-
const exec = util.promisify(require(
|
|
6
|
-
const { color } = require(
|
|
3
|
+
const spawn = require("./spawn");
|
|
4
|
+
const util = require("node:util");
|
|
5
|
+
const exec = util.promisify(require("node:child_process").exec);
|
|
6
|
+
const { color } = require("./fonts");
|
|
7
7
|
|
|
8
8
|
module.exports = async function execute(command, repos = [], config) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
let type = args[0]
|
|
12
|
-
args.shift()
|
|
9
|
+
let failed = [];
|
|
10
|
+
let [filename, ...args] = command.replaceAll("'", '"').trim().split(" ");
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
let type;
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (filename.endsWith(".js")) {
|
|
15
|
+
type = filename.slice(0, -3);
|
|
16
|
+
} else {
|
|
17
|
+
type = filename;
|
|
18
|
+
filename += ".js";
|
|
19
|
+
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.log(color.blue + 'running on all repos' + color.reset)
|
|
21
|
+
let predefined = path.resolve(__dirname, "commands", filename);
|
|
22
|
+
let isPredefined = fs.existsSync(predefined);
|
|
23
|
+
let repositories = [];
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
for (let repo of repos) {
|
|
26
|
+
try {
|
|
27
|
+
if (
|
|
28
|
+
repo.exclude &&
|
|
29
|
+
(repo.exclude.includes(type) || repo.exclude.includes(filename))
|
|
30
|
+
) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
const packageJsonPath = path.resolve(repo.path, "package.json");
|
|
35
|
+
const packageObj = require(packageJsonPath);
|
|
36
|
+
repo.entry = packageObj.main;
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
console.log(color.green + `${repo.name}: ` + color.reset, command)
|
|
33
|
-
let exitCode;
|
|
34
|
-
if (config.hideMessage) {
|
|
35
|
-
const { error } = await exec(command, {
|
|
36
|
-
cwd: repo.absolutePath,
|
|
37
|
-
});
|
|
38
|
+
if (isPredefined) {
|
|
39
|
+
repositories.push(repo);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
stdio: 'inherit'
|
|
46
|
-
})
|
|
47
|
-
}
|
|
43
|
+
console.log(color.green + `${repo.name}: ` + color.reset, command);
|
|
44
|
+
let exitCode;
|
|
45
|
+
if (config.hideMessage) {
|
|
46
|
+
const { error } = await exec(command, {
|
|
47
|
+
cwd: repo.absolutePath
|
|
48
|
+
});
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if (error) exitCode = 1;
|
|
51
|
+
} else {
|
|
52
|
+
exitCode = await spawn(type, args, {
|
|
53
|
+
cwd: repo.absolutePath,
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: "inherit"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
54
58
|
|
|
59
|
+
if (exitCode !== 0) {
|
|
60
|
+
repo.error = "command failed: " + command;
|
|
61
|
+
failed.push(repo);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error(
|
|
65
|
+
color.red +
|
|
66
|
+
`an error occured executing command in ${repo.name} repository` +
|
|
67
|
+
color.reset,
|
|
68
|
+
err.message
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
55
72
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
73
|
+
if (isPredefined) {
|
|
74
|
+
failed = require(predefined)(repositories, args);
|
|
75
|
+
}
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
77
|
+
return failed;
|
|
78
|
+
};
|
package/src/index.js
ADDED
package/src/spinner.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Define an object holding various spinner patterns, each pattern is an array of strings representing different frames
|
|
2
|
+
const spinnerPatterns = {
|
|
3
|
+
// Dots pattern: sequential increase in dots
|
|
4
|
+
dots: [". ", ".. ", "..."],
|
|
5
|
+
|
|
6
|
+
// Bar filling up incrementally
|
|
7
|
+
bar: ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"],
|
|
8
|
+
|
|
9
|
+
// A bouncing ball effect using Braille characters
|
|
10
|
+
bouncingBall: ["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"],
|
|
11
|
+
|
|
12
|
+
// Wave pattern: characters form a wave-like effect
|
|
13
|
+
wave: ["⎺", "⎻", "⎼", "⎽", "⎼", "⎻"],
|
|
14
|
+
|
|
15
|
+
// Rotating arrows pattern for direction indication
|
|
16
|
+
arrows: ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"],
|
|
17
|
+
|
|
18
|
+
// Rotating dots pattern with increasing and decreasing length
|
|
19
|
+
rotatingDots: [
|
|
20
|
+
". ",
|
|
21
|
+
".. ",
|
|
22
|
+
"... ",
|
|
23
|
+
".... ",
|
|
24
|
+
".....",
|
|
25
|
+
" ....",
|
|
26
|
+
" ...",
|
|
27
|
+
" ..",
|
|
28
|
+
" ."
|
|
29
|
+
],
|
|
30
|
+
|
|
31
|
+
// Horizontal bounce pattern to simulate a bouncing ball effect
|
|
32
|
+
horizontalBounce: [
|
|
33
|
+
"[ ]",
|
|
34
|
+
"[= ]",
|
|
35
|
+
"[== ]",
|
|
36
|
+
"[=== ]",
|
|
37
|
+
"[ ===]",
|
|
38
|
+
"[ ==]",
|
|
39
|
+
"[ =]"
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// spinner.js
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a spinner with the specified configuration
|
|
47
|
+
* @param {Object} options - Configuration options for the spinner
|
|
48
|
+
* @param {string} options.type - The type of spinner pattern
|
|
49
|
+
* @param {number} options.milliseconds - Interval in milliseconds for frame change
|
|
50
|
+
* @param {string} options.prefix - String to prefix before the spinner frame
|
|
51
|
+
* @param {string} options.suffix - String to suffix after the spinner frame
|
|
52
|
+
* @param {Function} options.onComplete - Callback function to execute when the spinner ends
|
|
53
|
+
* @returns {Object} - An object with an `end` method to stop the spinner
|
|
54
|
+
*/
|
|
55
|
+
function createSpinner({
|
|
56
|
+
type = "dots", // Default type is 'dots'
|
|
57
|
+
milliseconds = 200, // Default interval time is 200 ms
|
|
58
|
+
prefix = "", // Default prefix is an empty string
|
|
59
|
+
suffix = "", // Default suffix is an empty string
|
|
60
|
+
onComplete = () => process.stdout.write("\r") // Default onComplete action is to clear the line
|
|
61
|
+
}) {
|
|
62
|
+
// Get the frames for the specified spinner type, fall back to 'dots' pattern if type not found
|
|
63
|
+
const frames = spinnerPatterns[type] || spinnerPatterns.dots;
|
|
64
|
+
let spinnerIndex = 0; // Track current frame index
|
|
65
|
+
|
|
66
|
+
// Set an interval to update the spinner frame
|
|
67
|
+
const interval = setInterval(() => {
|
|
68
|
+
// Write spinner frame to the process standard output along with prefix and suffix
|
|
69
|
+
process.stdout.write(`\r${prefix}${frames[spinnerIndex]}${suffix}`);
|
|
70
|
+
// Update frame index, reset to 0 if it exceeds available frames
|
|
71
|
+
spinnerIndex = (spinnerIndex + 1) % frames.length;
|
|
72
|
+
}, milliseconds);
|
|
73
|
+
|
|
74
|
+
// Return an interface to interact with spinner
|
|
75
|
+
return {
|
|
76
|
+
// Method to stop the spinner and execute the onComplete callback
|
|
77
|
+
end: () => {
|
|
78
|
+
clearInterval(interval); // Clear the frame update interval
|
|
79
|
+
onComplete(); // Execute onComplete callback (default clears the current line)
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Export createSpinner function as a module
|
|
85
|
+
module.exports = createSpinner;
|