Logo

dev-resources.site

for different kinds of informations.

How CodeMirror v6 dev setup installs packages without a monorepo

Published at
11/27/2024
Categories
opensource
node
codemirror
monorepo
Author
ramunarasinga-11
Author
16 person written this
ramunarasinga-11
open
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" ? "[email protected]: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 [email protected]

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

monorepo Article's
30 articles in total
Favicon
Creating a scalable Monorepo for Vue - Workspaces
Favicon
Creating a scalable Monorepo for Vue - Intro
Favicon
Unlocking the Power of Modern Web Architecture: Monorepos, Micro-Frontends, and Vite πŸš€βœ¨
Favicon
Emerging Trends in Git: GitOps, Monorepos, Distributed Repositories, and AI Integration
Favicon
Using Node's built-in test runner with Turborepo
Favicon
Building a Scalable Monorepo with TurboRepo
Favicon
Cookiecutter for fast starting with polylith
Favicon
Monorepo vs Microservices: Finding the Perfect Fit for Your Project
Favicon
Nx + TypeORM + NestJS + Migrations
Favicon
How to Build a Changelog Feature in React for Your App
Favicon
Convert a ReactJS app from Vite to Nx
Favicon
How to deploy Google Cloud Functions with PNPM workspaces
Favicon
How CodeMirror v6 dev setup installs packages without a monorepo
Favicon
How CodeMirror v6 dev setup retrieves packages without a monorepo
Favicon
Nx 20: Exploring the new TS preset and TypeScript project references
Favicon
Simple hello world program using Bazel and Go lang
Favicon
A practical example of shared libraries in a monorepo
Favicon
πŸ—‚οΈ Monorepo vs. Polyrepo: Choosing the Right Strategy for Your Projects πŸš€
Favicon
Turborepo vs Nx: Mana yang Terbaik untuk Monorepo?
Favicon
Turborepo vs Nx: Which Monorepo Tool is Right for You?
Favicon
Optimizing +200 Pipelines of a Monorepo
Favicon
GitHub Actions: run a job only if a package has changed
Favicon
Building a Solid Foundation: Bootstrapping with Turbo Repo
Favicon
Nestjs Workspaces to build Monorepo
Favicon
Installing EmberJS v2 addons from GitHub forks using PNPM
Favicon
Understanding Monorepo
Favicon
Build Containerized MERN App with Lerna Monorepo
Favicon
Advanced monorepo management with Turborepo 2.0
Favicon
Vite config reuse
Favicon
Monorepo VS Polyrepo

Featured ones: