Sharing NPM Scripts Via a Package to be Utilized by Project upon Installation

I have streamlined my linting setup by consolidating all configuration and related packages/plugins/presets (for prettier, stylelint, eslint, commitlint) into an npm package. This allows me to utilize the same setup across multiple projects, simply extending or merging the config into local files for consistency without the hassle of managing dependencies separately.

In addition to the configuration, I have implemented a set of handy npm scripts that run linters and various development tasks. For instance:

"lint:prettier": "prettier 'src/**/*.{js,json}' --write",
"lint:eslint": "eslint 'src/**/*.js'",
"lint:compatibilityCheck": "eslint --print-config .eslintrc.js | eslint-config-prettier-check",
"lint": "npm run lint:compatibilityCheck && npm run lint:prettier && npm run lint:eslint"

Currently, these scripts are duplicated in each project. However, I aim to distribute them alongside my shared package so they can be centrally defined. What would be the best approach for achieving this?

Answer №1

According to a post on the npm blog, there are no straightforward methods to expose dev scripts in an npm package. The recommendation is to create JavaScript files that can run your desired scripts by utilizing the shelljs module.

For instance: Suppose you want to expose the script

lint:prettier": "prettier 'src/**/*.{js,json}' --write"

You can wrap the call inside a file named bin/lintprettier.js:

#! /usr/bin/env node
var shell = require("shelljs");
const path = require("path")

process.env.PATH += (path.delimiter + path.join(process.cwd(), 'node_modules', '.bin'));
shell.exec("prettier 'src/**/*.{js,json}' --write");

Next, add this script to the exported console scripts in your package.json:

...
"bin": {
   "lint-prettier": "bin/lintprettier.js"
}
...

Lastly, you can now reuse your script within your project:

"scripts": {
   "build": "...",
   "lint:prettier": "lint-prettier"
 }

Answer №2

Using Builder is one way to achieve this.

With Builder, you can package npm scripts and use them in any project where the package containing the scripts is installed.

In my experience, I consolidate all my build/test/lint scripts into an NPM package which I then install across multiple projects. This allows me to execute the same commands consistently in each project.

Despite being less actively maintained recently, Builder remains stable and reliable. I have personally had great success using it. The detailed README provides comprehensive guidance on how to get started.

Alternatively, following Cristiano's suggestion may provide more control over the implementation of the solution compared to utilizing Builder, which introduces another project with its unique set of challenges.

Answer №3

Trying to let a dependency change the dependent configuration might not be the best approach, even if there was an easy way to do it.

Instead of starting from the bottom and going up, consider going in the opposite direction. I highly recommend using lerna.

Lerna is an excellent tool for managing packages in a monorepo. It allows you to hoist shared dependencies across your packages. Additionally, you can define all your packages under one main package.json, where you can set your npm scripts just once and run them for all packages (or only a few using the scope feature) with a single command.

Answer №4

Introducing a helpful tool I developed to tackle these types of issues: Dictator Builder. This tool is designed to generate dictators that are standalone NPM packages.

With Dictator Builder, you can specify the rules for what scripts should be included in the package.json file, as well as provide additional configurations:

{
  "message": "Configure package.json and implement linting",
  "actions": [
    {
      "message": "Ensure lint script is present in package.json",
      "haveJsonPathValues": [
        {
          "expression": "$.scripts.lint",
          "value": "npm run eslint"
        }
      ],
      "target": "package.json"
    },
    {
      "copyFrom": "static-files",
      "target": "."
    }
  ]
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I interact with a v-dialog component within a child component in Vue.js using Vuetify?

Exploring Vue.js for the first time and hoping to display a login dialog upon button click. To maintain cleanliness in my code, I shifted the dialog to a child component within a parent component with nested LoginDialog. Below are snippets of the parent co ...

Ways to insert text into an SVG file

I am currently using vue-svg-map with a USA map. I am trying to display the state code (path.id) on my svg map. Can anyone provide guidance on how to achieve this? <radio-svg-map v-model="selectedLocation" :map="usa" :location-class="getLocation ...

Is it better to store CSS and JavaScript in separate files or within the main HTML document

While the best practice is to place JavaScript and CSS code in separate files (such as .js and .css), many popular websites like Amazon, Facebook, etc. often include a large portion of their JavaScript and CSS code directly within the main HTML page. Whic ...

Locating the exact position of a DOM node within the source document

Purpose In the process of creating a series of 'extractor' functions to identify components on a page using jsdom and nodejs, I aim to organize these identified 'component' objects based on their original placement within the page. Ch ...

Error: Update required to lodash version 3.0.0 to proceed with the build process

Help needed! My build server on Visual Studio Team Services (also known as VSO) is encountering an error message. Any suggestions on how to resolve this issue? npm WARNING deprecated [email protected]: lodash@<3.0.0 is no longer being supported. ...

The system cannot locate the "default" task. Please consider using the --force option to proceed. The process has been halted due to warnings

Below is the content of my gruntfile.js file var fs = require("fs"), browserify = require("browserify"), pkg = require("./package.json"); module.exports = function(grunt) { grunt.initConfig({ mochaTest: { test: { options: { ...

Having Trouble with Typescript Modules? Module Not Found Error Arising Due to Source Location Mismatch?

I have recently developed and released a Typescript package, serving as an SDK for my API. This was a new endeavor for me, and I heavily relied on third-party tools to assist in this process. However, upon installation from NPM, the package does not functi ...

Let's explore further - delving into JSON & array manipulation using the foreach loop in Pure JavaScript

Although I have some experience with Java Script, I still consider myself a beginner in certain areas, particularly when it comes to accessing JSON objects and arrays. I've tried various syntax and options for accessing arrays using [], but so far, I ...

What is the mechanism behind declaring a function using square brackets in Node.js/Javascript?

Encountering something new while working with Node.js - a unique way of declaring functions. You can find an example at this link. 'use strict'; const Actions = { ONE: 'one', TWO: 'two', THREE: 'three' }; clas ...

What causes isomorphic-style-loader to generate a TypeError: Cannot read property 'apply' of undefined when utilized alongside CSS-Modules?

Currently, I am working on server-side rendering the application, and while the HTML and JS are loading fine, I have encountered an issue with my styles (.less | .scss) not being loaded. After some research, I believe that the problem lies in missing the i ...

Encountering issues with reading undefined properties while working with react-chartjs-2 and chart js

Having trouble with react chartjs errors? Visit the link for more details https://i.stack.imgur.com/lI2EP.png The versions I'm using are ^3.5.0 for chart.js and ^4.0.1 for react-chartjs-2 Tried downgrading to version 2 but it didn't solve the ...

Is there a way to deactivate the click function in ngx-quill editor for angular when it is empty?

In the following ngx-quill editor, users can input text that will be displayed when a click button is pressed. However, there is an issue I am currently facing: I am able to click the button even if no text has been entered, and this behavior continues li ...

Infinite scroll layout meets Semantic UI visibility for a dynamic user experience

I am attempting to implement an infinite scrolling Masonry layout within the Semantic UI framework, utilizing the pre-existing visibility function. While everything appears to be functioning correctly, I am encountering difficulties with getting Masonry t ...

Is it possible to update table cell content depending on selected option?

Displayed here is the select block: <form> <select id="select"> <option disabled selected value="choose"> CHOOSE </option> <option value="i2g" id="i ...

Not triggering onDragStart in Material UI Autocomplete component in React

I'm facing an issue with an onDragStart handler in a React Autocomplete component. Despite adding the handler, it fails to trigger when dragging using the mouse. You can explore a live demo of this problem here: https://codesandbox.io/s/material-demo- ...

Unraveling the Enigma of Event Handlers: Mastering the Organization of a Sprawling jQuery File within an AJAX

I've created a web application that heavily relies on AJAX and jQuery for DOM manipulation and making AJAX requests. However, I'm facing a problem with my JavaScript file: The issue is that my JavaScript file consists of a huge collection of eve ...

In Visual Studio, the .js.map files and .js files seem to be mysteriously hidden, leaving only the TypeScript .ts files visible

In the past, I utilized Visual Studio Code for Angular 2 development and had the ability to hide .js and .js.map files from the IDE. Now, I am working on a project using VS 2017 Professional with Typescript, Jasmine, Karma, and Angular 4. Task Runner, etc. ...

Sending a JWT token to a middleware with a GET request in Express Node.js - the proper way

Struggling with Js and web development, I've scoured the web for a solution to no avail... After completing a project for a small lab, my current challenge is creating a login page and generating a web token using JWT... I successfully created a use ...

Refresh the webpage source code for an AJAX request

When using AJAX calls on a page, I have noticed that the page source remains unchanged. This can be problematic if a user performs forward/backward operations in their browser, as the browser will display the original HTML code instead of the updated conte ...

Communication between child and parent components in Vue.js is an essential feature

Attempting to invoke functions from my component to Vue for the login process. This is the code snippet of my component : Vue.component('auths', { data: function() { return { ip: '', sessiontoken: '' } ...