@cocreate/cli 1.51.2 → 1.52.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/package.json CHANGED
@@ -1,18 +1,10 @@
1
1
  {
2
2
  "name": "@cocreate/cli",
3
- "version": "1.51.2",
3
+ "version": "1.52.0",
4
4
  "description": "Polyrepo management bash CLI tool. Run all git commands and yarn commands on multiple repositories. Also includes a few custom macros for cloning, installing, etc.",
5
5
  "keywords": [
6
6
  "cli",
7
- "cocreate",
8
- "low-code-framework",
9
- "no-code-framework",
10
- "cocreatejs",
11
- "cocreatejs-component",
12
- "cocreate-framework",
13
- "no-code",
14
7
  "low-code",
15
- "collaborative-framework",
16
8
  "realtime",
17
9
  "realtime-framework",
18
10
  "collaboration",
package/src/coc.js CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  // Import necessary modules for path operations, file system operations, and more
4
4
  const path = require("path");
5
- const fs = require("fs");
6
5
  const readline = require("readline");
7
6
  const execute = require("./execute");
8
7
  const addMeta = require("./addMeta");
9
8
  const { color } = require("./fonts");
9
+ const { getConfig } = require("./getConfig");
10
10
 
11
11
  // Configuration object for storing options
12
12
  let config = {};
@@ -15,41 +15,36 @@ let config = {};
15
15
  const argv = process.argv.slice(2);
16
16
 
17
17
  // Define available command-line options
18
- const options = ["-self"];
19
-
20
- // Iterate over available options and set configurations if specified in argv
21
- for (let option of options) {
22
- if (argv.includes(option)) {
23
- config[option.replace(/^--/, "")] = true;
24
- const index = argv.indexOf(option);
25
- delete argv[index];
18
+ const availableOptions = {
19
+ "--self": { key: "self", type: "boolean" },
20
+ "-s": { key: "self", type: "boolean" },
21
+ "--directory": { key: "directory", type: "string" },
22
+ "-d": { key: "directory", type: "string" },
23
+ "--config": { key: "config", type: "string" },
24
+ "-c": { key: "config", type: "string" }
25
+ };
26
+
27
+ const options = {};
28
+ const commandParts = [];
29
+ for (let i = 0; i < argv.length; i++) {
30
+ let option = availableOptions[argv[i]];
31
+ if (option) {
32
+ if (option.type === "boolean") {
33
+ options[option.key] = true;
34
+ } else if (option.type === "string") {
35
+ options[option.key] = argv[i + 1];
36
+ argv.splice(i + 1, 1);
37
+ }
38
+ } else {
39
+ if (argv[i].match(/[\s'"]/)) {
40
+ commandParts.push(`'${argv[i].replace(/'/g, "\\'")}'`);
41
+ } else {
42
+ commandParts.push(argv[i]);
43
+ }
26
44
  }
27
45
  }
28
46
 
29
- // Format command from argv, handling spaces and quotes
30
- command = argv
31
- .map((part) => (part.match(/ |'|"/) ? `'${part.replace(/'/, "'")}'` : part))
32
- .join(" ");
33
-
34
- /**
35
- * Load repository configuration from the given path.
36
- * @param {string} path - The file path to load repository config from.
37
- * @returns {Array} - List of repositories.
38
- */
39
- function getRepositories(path) {
40
- try {
41
- const config = require(path);
42
- return config.repositories;
43
- } catch (err) {
44
- console.error(
45
- color.red + "cannot read repository file in" + color.reset,
46
- path,
47
- color.red + "error:" + color.reset,
48
- err.message
49
- );
50
- process.exit(1);
51
- }
52
- }
47
+ command = commandParts.join(" ");
53
48
 
54
49
  /**
55
50
  * Main function to execute commands across repositories.
@@ -57,68 +52,60 @@ function getRepositories(path) {
57
52
  * @param {Array} [repos=null] - List of repositories to process.
58
53
  * @param {string} [directory=null] - The directory path of the configuration.
59
54
  */
60
- async function main(config = {}, repos = null, directory = null) {
61
- if (!repos) {
62
- // Determine repositories and configuration file paths
63
- const currentRepoPath = path.resolve(
64
- process.cwd(),
65
- "CoCreate.config.js"
66
- );
67
- const packageJsonPath = path.resolve(process.cwd(), "package.json");
68
-
69
- // Load repositories from specified config file
70
- if (config["c"] && fs.existsSync(config["c"])) {
71
- repos = getRepositories(config["c"]);
72
- directory = path.dirname(config["c"]);
73
- console.warn(
74
- `${color.yellow}using ${config["c"]} configuration${color.reset}`
75
- );
76
- }
77
- // Load repositories from default CoCreate.config.js if exists
78
- else if (!config["self"] && fs.existsSync(currentRepoPath)) {
79
- repos = getRepositories(currentRepoPath);
80
- directory = path.dirname(currentRepoPath);
81
- console.warn(
82
- `${color.yellow}using ${currentRepoPath} configuration${color.reset}`
83
- );
84
- }
85
- // If package.json exists, load repository details from it
86
- else if (fs.existsSync(packageJsonPath)) {
87
- const repoPath = path.resolve(process.cwd());
88
- const packageObj = require(packageJsonPath);
89
- const repoUrl =
90
- packageObj.repository &&
91
- packageObj.repository.url.substring(12);
92
- const repoEntry = packageObj.main;
93
- repos = [
94
- {
95
- path: repoPath,
96
- repo: repoUrl,
97
- entry: repoEntry
98
- }
99
- ];
100
- directory = path.dirname(packageJsonPath);
101
- console.warn(
102
- `${color.yellow}using ${packageJsonPath} configuration${color.reset}`
103
- );
55
+ async function main(config = {}, options) {
56
+ let directory = options["directory"] || process.cwd();
57
+ if (!config.repositories) {
58
+ let configString = options["config"];
59
+ if (configString) {
60
+ try {
61
+ config = JSON.parse(configString);
62
+ console.warn(
63
+ `${color.yellow}using supplied JSON configuration${color.reset}`
64
+ );
65
+ } catch (error) {
66
+ directory = configString;
67
+ config = await getConfig(directory);
68
+ }
69
+ } else {
70
+ config = await getConfig(directory);
104
71
  }
105
- // Error if no configuration can be found
106
- else {
107
- console.error(
108
- `${color.red}a configuration file cannot be found${color.reset}`
109
- );
110
- process.exit(1);
72
+
73
+ if (!config.configPath) {
74
+ const package = await getConfig(directory, "package.json");
75
+ if (package.configPath) {
76
+ config.configPath = package.configPath;
77
+ const repoUrl =
78
+ package.repository && package.repository.url.substring(12);
79
+ config.repositories = [
80
+ {
81
+ path: package.configPath,
82
+ repo: repoUrl,
83
+ entry: package.main
84
+ }
85
+ ];
86
+ } else {
87
+ console.error(
88
+ `${color.red}config file cannot be found${color.reset}`
89
+ );
90
+ process.exit(1);
91
+ }
111
92
  }
93
+
94
+ directory = path.dirname(config.configPath);
95
+ console.warn(
96
+ `${color.yellow}using config ${config.configPath} ${color.reset}`
97
+ );
112
98
  }
113
99
 
114
- // Set default config values
115
- config = { hideMessage: false, ...config };
100
+ config.hideMessage = false;
116
101
 
117
- // Add metadata to repos if any are present
118
- if (repos && repos.length) repos = await addMeta(repos, [], directory);
102
+ // Add metadata to repositories if any are present
103
+ if (config.repositories && config.repositories.length) {
104
+ config.repositories = await addMeta(config.repositories, [], directory);
105
+ }
119
106
 
120
107
  // Execute the command across repositories
121
- const failed = await execute(command, repos, config);
108
+ const failed = await execute(command, config);
122
109
 
123
110
  // Handle any failed command executions
124
111
  if (failed && failed.length > 0) {
@@ -134,7 +121,7 @@ async function main(config = {}, repos = null, directory = null) {
134
121
  }
135
122
 
136
123
  // Prompt user to retry failed commands
137
- await promptRetry(failed, config, directory);
124
+ await promptRetry(failed, config, options);
138
125
  }
139
126
  }
140
127
 
@@ -144,7 +131,7 @@ async function main(config = {}, repos = null, directory = null) {
144
131
  * @param {Object} config - Configuration object.
145
132
  * @param {string} directory - Path of the configuration directory.
146
133
  */
147
- async function promptRetry(failed, config, directory) {
134
+ async function promptRetry(failed, config, options) {
148
135
  const rl = readline.createInterface({
149
136
  input: process.stdin,
150
137
  output: process.stdout
@@ -155,7 +142,8 @@ async function promptRetry(failed, config, directory) {
155
142
  async (answer) => {
156
143
  rl.close();
157
144
  if (answer.toLowerCase() === "yes") {
158
- await main(config, failed, directory);
145
+ config.repositories = failed;
146
+ await main(config, options);
159
147
  } else {
160
148
  process.exit(0);
161
149
  }
@@ -164,4 +152,4 @@ async function promptRetry(failed, config, directory) {
164
152
  }
165
153
 
166
154
  // Call the main function with initial configuration
167
- main(config);
155
+ main(config, options);
@@ -1,102 +1,78 @@
1
- const file = require('@cocreate/file')
2
- const path = require('path');
3
- const fs = require('fs');
1
+ const file = require("@cocreate/file");
2
+ const path = require("path");
3
+ const fs = require("fs");
4
+ const { getConfig } = require("../getConfig");
4
5
 
5
6
  module.exports = async function upload(directory, args) {
6
- if (args && !Array.isArray(args))
7
- args = [args]
8
-
9
- let isWatch = false
10
- if (directory && typeof directory === 'string') {
11
- if (['-w', '--watch'].includes(directory)) {
12
- isWatch = true
13
- directory = process.cwd()
14
- }
15
- } else
16
- directory = process.cwd()
17
-
18
- if (isWatch || args.includes('-w') || args.includes('--watch')) {
19
- for (let i = 0; i < args.length; i++) {
20
- if (args[i].startsWith('-'))
21
- continue
22
- else if (path.isAbsolute(args[i]))
23
- directory = args[i]
24
- else
25
- directory = path.resolve(directory, args[i]);
26
- }
27
-
28
- console.log('Watching: ', directory)
29
- fs.watch(directory, { recursive: true }, async (eventType, filename) => {
30
- if (!filename.includes('CoCreate.config.js')) {
31
- const { config, configPath, filePath } = await getConfig(directory, filename);
32
- if (config) {
33
- await file(config, configPath, filePath)
34
- } else {
35
- console.log(`Failed to read or parse CoCreate.config.js for file: ${filename}`);
36
- }
37
- }
38
- });
39
-
40
- } else {
41
- if (!args.length) {
42
- directory = process.cwd()
43
- const { config, configPath, filePath } = await getConfig(directory);
44
- if (config) {
45
- await file(config, configPath, filePath)
46
- } else {
47
- console.log('Failed to read or parse CoCreate.config.js.');
48
- }
49
-
50
- } else {
51
- for (let arg of args) {
52
- let CoCreateConfig
53
-
54
- try {
55
- CoCreateConfig = JSON.parse(arg)
56
- } catch (error) { }
57
-
58
-
59
- if (!CoCreateConfig) {
60
- const { config, configPath, filePath } = await getConfig(arg);
61
- if (config) {
62
- await file(config, configPath, filePath)
63
- } else {
64
- console.log('Failed to read or parse CoCreate.config.js.');
65
- }
66
- }
67
- }
68
- }
69
- }
70
-
71
- async function getConfig(directory, filename = '') {
72
- let config, configPath
73
- const filePath = path.resolve(directory, filename);
74
- if (!filePath.includes('node_modules/')) {
75
- configPath = findClosestConfig(filePath)
76
- if (configPath) {
77
- config = require(configPath)
78
- } else {
79
- console.log('No CoCreate.config file found in parent directories.');
80
- }
81
- }
82
-
83
- return { config, configPath, filePath };
84
- }
85
-
86
- function findClosestConfig(filePath) {
87
- let currentDir = filePath;
88
-
89
- while (currentDir !== '/' && currentDir !== '.') {
90
- let configFile = path.join(currentDir, 'CoCreate.config.js');
91
-
92
- if (fs.existsSync(configFile)) {
93
- return configFile;
94
- }
95
-
96
- currentDir = path.dirname(currentDir);
97
- }
98
-
99
- return null;
100
- }
101
-
102
- }
7
+ if (args && !Array.isArray(args)) args = [args];
8
+
9
+ let isWatch = false;
10
+ if (directory && typeof directory === "string") {
11
+ if (["-w", "--watch"].includes(directory)) {
12
+ isWatch = true;
13
+ directory = process.cwd();
14
+ }
15
+ } else directory = process.cwd();
16
+
17
+ if (isWatch || args.includes("-w") || args.includes("--watch")) {
18
+ for (let i = 0; i < args.length; i++) {
19
+ if (args[i].startsWith("-")) continue;
20
+ else if (path.isAbsolute(args[i])) directory = args[i];
21
+ else directory = path.resolve(directory, args[i]);
22
+ }
23
+
24
+ console.log("Watching: ", directory);
25
+ fs.watch(
26
+ directory,
27
+ { recursive: true },
28
+ async (eventType, filename) => {
29
+ if (!filename.includes("CoCreate.config.js")) {
30
+ const config = await getConfig(directory, filename);
31
+ if (config.configPath) {
32
+ await file(config, config.configPath, config.filePath);
33
+ } else {
34
+ console.log(
35
+ "Failed to read or parse CoCreate.config.js."
36
+ );
37
+ }
38
+ }
39
+ }
40
+ );
41
+ } else {
42
+ if (!args.length) {
43
+ const CoCreateConfig = await getConfig(directory);
44
+ if (CoCreateConfig.configPath) {
45
+ await file(
46
+ CoCreateConfig,
47
+ CoCreateConfig.configPath,
48
+ CoCreateConfig.filePath
49
+ );
50
+ } else {
51
+ console.log("Failed to read or parse CoCreate.config.js.");
52
+ }
53
+ } else {
54
+ for (let arg of args) {
55
+ let CoCreateConfig;
56
+
57
+ try {
58
+ CoCreateConfig = JSON.parse(arg);
59
+ } catch (error) {}
60
+
61
+ if (!CoCreateConfig) {
62
+ CoCreateConfig = await getConfig(arg);
63
+ if (CoCreateConfig.configPath) {
64
+ await file(
65
+ CoCreateConfig,
66
+ CoCreateConfig.configPath,
67
+ CoCreateConfig.filePath
68
+ );
69
+ } else {
70
+ console.log(
71
+ "Failed to read or parse CoCreate.config.js."
72
+ );
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ };
package/src/execute.js CHANGED
@@ -3,9 +3,11 @@ const fs = require("fs");
3
3
  const spawn = require("./spawn");
4
4
  const util = require("node:util");
5
5
  const exec = util.promisify(require("node:child_process").exec);
6
+ const { getConfig } = require("./getConfig");
7
+
6
8
  const { color } = require("./fonts");
7
9
 
8
- module.exports = async function execute(command, repos = [], config) {
10
+ module.exports = async function execute(command, config) {
9
11
  let failed = [];
10
12
  let [filename, ...args] = command.replaceAll("'", '"').trim().split(" ");
11
13
 
@@ -22,7 +24,7 @@ module.exports = async function execute(command, repos = [], config) {
22
24
  let isPredefined = fs.existsSync(predefined);
23
25
  let repositories = [];
24
26
 
25
- for (let repo of repos) {
27
+ for (let repo of config.repositories || []) {
26
28
  try {
27
29
  if (
28
30
  repo.exclude &&
@@ -71,7 +73,7 @@ module.exports = async function execute(command, repos = [], config) {
71
73
  }
72
74
 
73
75
  if (isPredefined) {
74
- failed = require(predefined)(repositories, args);
76
+ failed = await require(predefined)(repositories, args);
75
77
  }
76
78
 
77
79
  return failed;
@@ -0,0 +1,37 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ async function getConfig(directory, filename = "CoCreate.config.js") {
5
+ let config;
6
+ const filePath = path.resolve(directory, filename);
7
+ if (!filePath.includes("node_modules/")) {
8
+ const configPath = findClosestConfig(filePath, "CoCreate.config.js");
9
+ if (configPath) {
10
+ config = require(configPath);
11
+ config.configPath = configPath;
12
+ config.filePath = filePath;
13
+ } else {
14
+ console.log("No CoCreate.config file found in parent directories.");
15
+ }
16
+ }
17
+
18
+ return config;
19
+ }
20
+
21
+ function findClosestConfig(filePath, filename) {
22
+ let currentDir = filePath;
23
+
24
+ while (currentDir !== "/" && currentDir !== ".") {
25
+ let configFile = path.join(currentDir, filename);
26
+
27
+ if (fs.existsSync(configFile)) {
28
+ return configFile;
29
+ }
30
+
31
+ currentDir = path.dirname(currentDir);
32
+ }
33
+
34
+ return null;
35
+ }
36
+
37
+ module.exports = { getConfig, findClosestConfig };