DEV Community

thinkThroo
thinkThroo

Posted on

How CodeMirror v6 dev setup retrieves packages without a monorepo

In the OSS community, it is quite common to come across monorepo projects where the workspaces and packages are all in a single repository. CodeMirror has a different style to the way packages are managed, each package that is used is a repository on its own. In this article, we analyse what these packages are that CodeMirror uses and how they are installed when you want to setup CodeMirror v6 locally to contribute.

bin/packages.js

Before we analyse the install function, let’s first understand the variours packages that make up the CodeMirror. You

will find these packages listed in bin/packages.js file

Image description

These below are the core packages:

exports.core = [
 "state",
 "view",
 "language",
 "commands",
 "search",
 "autocomplete",
 "lint",
 "collab",
 "language-data",
 "codemirror",
]
Enter fullscreen mode Exit fullscreen mode

These below are the non-core packages.

exports.nonCore = [
 "lang-javascript",
 "lang-java",
 "lang-json",
 "lang-cpp",
 "lang-php",
 "lang-python",
 "lang-go",
 "lang-css",
 "lang-sass",
 "lang-html",
 "lang-sql",
 "lang-rust",
 "lang-xml",
 "lang-markdown",
 "lang-lezer",
 "lang-wast",
 "lang-angular",
 "lang-vue",
 "lang-liquid",
 "lang-less",
 "lang-yaml",
 "legacy-modes",
 "theme-one-dark",
 "merge"
]
Enter fullscreen mode Exit fullscreen mode

You will find repositories in the CodeMirror organisation for all these packages shown above. There is no single repository containing all these packages like in a monorepo, instead you have all these repositories that make up the CodeMirror.

exports.core and exports.nonCore

You will find that these packages are accessed via a function named loadPackages.

Image description

You might be wondering what exports.all here is in the above image, at line 42. It is interesting how the concat is made on exports.core and exports.nonCore and this you have all these packages merged into one array and assigned to exports.all.

exports.loadPackages

let packages = exports.all.map(n => new Pkg(n))
Enter fullscreen mode Exit fullscreen mode

Using map on exports.all, new Pkg class is instantiated using the Pkg class that’s shown below:

class Pkg {
 constructor(name) {
 this.name = name
 this.dir = join(__dirname, "..", name)
 this.main = null
 if (name != "legacy-modes" && fs.existsSync(this.dir)) {
 let files = fs.readdirSync(join(this.dir, "src")).filter(f => /^[^.]+\.ts$/.test(f))
 let main = files.length == 1 ? files[0] : files.includes("index.ts") ? "index.ts"
 : files.includes(name.replace(/^(theme-|lang-)/, "") + ".ts") ? name.replace(/^(theme-|lang-)/, "") + ".ts" : null
 if (!main) throw new Error("Couldn't find a main script for " + name)
 this.main = join(this.dir, "src", main)
 }
 }
}
Enter fullscreen mode Exit fullscreen mode

It technically sets name, dir and main.

let packageNames = Object.create(null)
for (let p of packages) packageNames[p.name] = p
Enter fullscreen mode Exit fullscreen mode

Image description

Object.create(null) creates an empty object, that’s fancy way of creating a obj that would otherwise be just obj = {} and finally below is the return statement.

return {
  packages, 
  packageNames, 
  buildPackages: packages.filter(p => p.main)
}
Enter fullscreen mode Exit fullscreen mode

About us:

At Thinkthroo, we study large open source projects and provide architectural guides. We have developed reusable Components, built with tailwind, that you can use in your project. We offer Next.js, React and Node development services.

Book a meeting with us to discuss your project.

Image description

References

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

  2. https://github.com/codemirror/dev/blob/main/bin/packages.js

  3. https://github.com/orgs/codemirror/repositories

Top comments (0)