DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on • Edited on

How CodeMirror v6 dev setup installs packages without a monorepo

In the article, we looked at:

1. How CodeMirror v6 setup command processes CLI arguments?

2. How CodeMirror v6 dev setup retrieves packages without a monorepo

This leads to the next question how are packages installed as part development environment setup without using a monorepo. install function is called using apply as explained in the previous articles mentioned above.

Image description

let base = arg == " - ssh" ? "git@github.com:codemirror/" : "https://github.com/codemirror/"
if (arg && arg != " - ssh") help(1)
Enter fullscreen mode Exit fullscreen mode

In case you are wondeirng what these 2 lines are for, Github lets you clone a repository via the ssh, hence this scenaria is handled to set the correct base url.

for (let pkg of packages) {
 if (fs.existsSync(pkg.dir)) {
   console.warn(`Skipping cloning of ${pkg.name} (directory exists)`)
 } else {
   let origin = base + (pkg.name == "codemirror" ? "basic-setup" : pkg.name) + ".git"
   run("git", ["clone", origin, pkg.dir])
 }
}
Enter fullscreen mode Exit fullscreen mode

If a package already exists, it is checked via existsSync and console.warn is shown about it being skipped otherwise, origin is assigned a value using base with a .git extension, since this is a URL there is no point in using API such as join as that is applicable to file system and the run function is called.

run function

function run(cmd, args, wd = root, { shell = false } = {}) {
 return child.execFileSync(cmd, args, {shell, cwd: wd, encoding: "utf8", stdio: ["ignore", "pipe", process.stderr]})
}
Enter fullscreen mode Exit fullscreen mode

run functions seems to be using execFileSync API provided by child. child is initialized at the top of the file.

const child = require("child_process")
Enter fullscreen mode Exit fullscreen mode

We need to understand what child_process and execFileSync API are.

child_process

The node:child_process module provides the ability to spawn subprocesses in a manner that is similar, but not identical, to popen. This capability is primarily provided by the child_process.spawn() function:

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
 console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
 console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
 console.log(`child process exited with code ${code}`);
});
Enter fullscreen mode Exit fullscreen mode

This above information is picked from Node.js documentation

execFileSync

The child_process.execFileSync() method is generally identical to child_process.execFile() with theexception that the method will not return until the child process has fully closed. When a timeout has been encountered and killSignal is sent, the method won’t return until the process has completely exited.

If the child process intercepts and handles the SIGTERM signal and does not exit, the parent process will still wait until the child process has exited.

If the process times out or has a non-zero exit code, this method will throw an Error that will include the full result of the underlying child_process.spawnSync().

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

const { execFileSync } = require('node:child_process');
try {
 const stdout = execFileSync('my-script.sh', ['my-arg'], {
 // Capture stdout and stderr from child process. Overrides the
 // default behavior of streaming child stderr to the parent stderr
 stdio: 'pipe',
// Use utf8 encoding for stdio pipes
 encoding: 'utf8',
 });
console.log(stdout);
} catch (err) {
 if (err.code) {
 // Spawning child process failed
 console.error(err.code);
 } else {
 // Child was spawned but exited with non-zero exit code
 // Error contains any stdout and stderr from the child
 const { stdout, stderr } = err;
console.error({ stdout, stderr });
 }
}
Enter fullscreen mode Exit fullscreen mode

This above information is picked from Node.js documentation

Now that we understand what this API is used for, we can now look at the run function from CodeMirror.

function run(cmd, args, wd = root, { shell = false } = {}) {
 return child.execFileSync(cmd, args, {shell, cwd: wd, encoding: "utf8", stdio: ["ignore", "pipe", process.stderr]})
}
Enter fullscreen mode Exit fullscreen mode

execFileSync executes the cmd (command) passed in as the first parameter. Install function calls run using the below variables.

run("git", ["clone", origin, pkg.dir])
Enter fullscreen mode Exit fullscreen mode

Here the command is git and args is an array — [“clone”, origin, pkg.dir]. Install function basically clones the packages that are public repositories in the CodeMirror organization. Executing the commands programattically reminds me of two related concepts:

1. [Execa](https://www.npmjs.com/package/execa)

2. [Degit](https://github.com/Rich-Harris/degit)

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on an interesting project. Send me an email at ramu.narasinga@gmail.com

My Github - https://github.com/ramu-narasinga
My website - https://ramunarasinga.com
My Youtube channel - https://www.youtube.com/@thinkthroo
Learning platform - https://thinkthroo.com
Codebase Architecture - https://app.thinkthroo.com/architecture
Best practices - https://app.thinkthroo.com/best-practices
Production-grade projects - https://app.thinkthroo.com/production-grade-projects

References

  1. https://github.com/codemirror/dev/blob/main/bin/cm.js#L64C1-L66C2

  2. https://github.com/codemirror/dev/blob/main/bin/cm.js#L81

  3. https://nodejs.org/api/child_process.html#child_processexecfilesyncfile-args-options

  4. https://nodejs.org/api/child_process.html#child_processexecfilefile-args-options-callback

Top comments (0)