npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@hollowverse/clown

v3.2.0

Published

CLI for scaffolding projects and juggling common configurations

Downloads

18

Readme

@hollowverse/clown Build Status

clown is a CLI that:

  • Helps with scaffolding a project
  • Extending project configurations
  • Sharing configurations between different projects
  • Ensuring that a project configurations are up to date

How does it do that? Mostly by copying files from one folder to another 🤡

...but also by its ability to merge fragments of configuration files together.

How it works

Extending configurations

First, install:

yarn add @hollowverse/clown -D

# npm i @hollowverse/clown --save-dev

Next add it to package.json scripts.

{
  "scripts": {
    "clown": "clown"
  }
}

Now, say the the root of our project, where we just installed clown, looks like this:

|-- src/
|
|-- node_modules/
|   |-- some Node modules...
|
|-- package.json
|-- .gitignore

Now we want to bring ESLint configurations, package.json values, and .gitignore values to our repo. Say the stuff we want to bring is in a folder located at ./node_modules/our-config-module (a module we had previously published to npm, it does not have to be a Node module, it can be any folder on our disk). The content of our-config-module could look like this:

|-- common/
|   |-- LICENSE
|   |-- package.json
|   |-- .gitignore
|
|-- eslint/
|   |-- package.json
|   |-- eslintrc.json
|
|-- README.md
|-- package.json

As we can see above, we have a common folder and an eslint folder. Note that there are 3 package.json files in our-config-module. The only real package.json of these 3 in the eyes of Node and npm is the one at the root. The other two only contain fragments of values. For example, the eslint/package.json file may have nothing more than:

{
  "scripts": {
    "lint": "eslint"
  },
  "devDependencies": {
    "eslint": "^5.0.0"
  }
}

(clown will merge this eslint/package.json fragment with the package.json in the root of our project that we want to extend after we run clown.)

The next step would be to create a clown.json file at the root of our project.

clown.json would look like this:

{
  "extensions": [
    "./node_modules/our-config-module/common",
    "./node_modules/our-config-module/eslint"
  ]
}

Now it's time to run clown. Run:

yarn clown

# npm run clown

What clown will do is look at each of the extensions folders that we have specified, go inside it, and merge or copy its content with the content at the root of our repo.

The end result will be:

|-- src/
|
|-- node_modules/
|   |-- some Node modules...
|
|-- package.json # extended by `eslint/package.json` and `common/package.json`
|-- .gitignore # extended by `common/.gitignore`
|-- LICENSE # copied over from `common/LICENSE`

How clown handles different file types

Non-existing files

If clown encounters a configuration file that doesn't exist in the destination project, it will copy the file over as-is.

Existing files

If clown encounters a configuration file that exists in both the extension folder and the destination project, it will try to merge the content of the extension file with the content of the destination file if it knows how.

JSON files

JSON files will be merged in a manner that we think works better for configuration files than simply using Object.assign or _.merge.

.gitignore, .npmignore, etc

For dot-ignore files, clown will make sure that the lines in the extension file exist in the destination file.

Other file types

Currently, clown only knows how to handle the file types above. For other file types, clown will override the current content with the content from the extension file.

Ensuring up-to-date configurations

We might want to make sure that our project configurations don't diverge from our scaffolded and shared configurations. For this purpose the clown CLI provides

yarn clown check

# npm run clown check

When we run this command, clown will figure out what our configuration files would look like if they were to be extended by clown itself. After it figures this out, it will compare the result with what actually exists. If it sees that the two results are different, it will print an error message telling us which files are different and how they are different.

Overriding configurations

Extension folders that appear later in the extensions array, override the values of previous extension folders.

That means we can override configurations by creating any local folder and specifying it in our clown.json extensions array, like so:

{
  "extensions": [
    "./node_modules/our-config-module/common",
    "./node_modules/our-config-module/eslint",
    "./config-overrides"
  ]
}

We can put in ./config-overrides any files or fragments that we wish to override the previous configurations with.

clownCallback.js

Another way to override content is by using clownCallback.js.

Put clownCallback.js in the extension folder and export a function from it. The exported function will receive an instance of clownFilesystem, which gives access to all the file contents that clown has computed before clown writes those file contents to disk.

Using clownCallback.js you can edit, delete, or add files.

For example, in ./config-overrides/clownCallback.js we can have the following code:

module.exports = clownFilesystem => {
  clownFilesystem.editJson('/package.json', pkgJson => {
    delete pkgJson.foo;

    return pkgJson;
  });

  return clownFilesystem.fileContents;
};

Escaping filenames

Some filenames, such as .eslintrc.json and package.json, have special meaning to tools, so when files with these names exist in our config-overrides folder, they could confuse these tools (see this discussion).

That's why clown makes it possible to "escape" these filenames by appending c__ to the filename.

If our config-overrides contains a file named c__package.json, clown would know that the target destination for this file is package.json and would merge the configurations correctly.

For issues or questions

A lot of the above may very well not make much sense. So feel free to post issues or questions here:

https://github.com/hollowverse/hollowverse/issues