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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@smartcompanion/engraft

v0.2.2

Published

Apply customizations to any project without templating placeholders

Readme

engraft

Apply customizations to any project without templating placeholders.

The Problem

Customizing a project (e.g., white-label products) forces a choice between bad options:

  • Templating tools (Cookiecutter, Copier, Yeoman) require {{ placeholders }} in source code — the repo is no longer a working app
  • Forking leads to diverging codebases that are painful to sync with upstream
  • Manual editing is error-prone, undocumented, and impossible to reproduce

engraft solves this by keeping the source repo clean and runnable while providing a declarative, reproducible customization layer on top.

How It Works

engraft uses a two-file model:

  • Template file — defines what can be customized and how (maintained by the repo author)
  • Values file — contains the consumer's customization values

The original project stays untouched. Run engraft apply and the customizations are applied in place.

Installation

Requires Node.js 20 or newer.

npm install -g @smartcompanion/engraft

Quick Start

Given a project with a config.json:

{
  "name": "DefaultApp",
  "version": "1.0.0"
}

Create a template file engraft.template.yml:

variables:
  app_name:
    description: Application name
    default: DefaultApp

customizations:
  - action: json_replace
    file: config.json
    replace:
      - selector: $.name
        variable: app_name

Create a values file engraft.values.yml:

app_name: MyApp

Apply:

engraft apply --template engraft.template.yml --values engraft.values.yml

Result — config.json now contains:

{
  "name": "MyApp",
  "version": "1.0.0"
}

Action Reference

json_replace

Replace values in JSON files using JSONPath-like selectors.

- action: json_replace
  file: app.json
  replace:
    - selector: $.expo.name
      variable: app_name
    - selector: $.expo.extra.items[0].label
      variable: item_label

Selectors use dot notation with optional array indices: $.path.to.key or $.array[0].field.

html_replace

Replace values in HTML files using XPath selectors. Supports both element text and attribute values.

- action: html_replace
  file: index.html
  replace:
    - selector: //title
      variable: page_title
    - selector: //meta[@name='description']/@content
      variable: page_description

The selector must match exactly one element or attribute. Matching zero or more than one is an error.

regex_replace

Replace values in any text file using regex with a named capture group.

- action: regex_replace
  file: src/theme.ts
  replace:
    - selector: '(PRIMARY_COLOR\s*=\s*)"(?<value>[^"]*)"'
      variable: primary_color

The selector must contain a named capture group called value. Both syntaxes are accepted:

  • ECMAScript/JavaScript style: (?<value>...)
  • Python style: (?P<value>...)

Using either form keeps templates portable between the Python and TypeScript implementations. Only the captured group is replaced; the surrounding match is preserved.

file_replace

Replace an entire file with a source file referenced by a variable.

- action: file_replace
  file: assets/logo.png
  variable: logo

The variable value is a path relative to the values file directory. Useful for binary files like images.

Values file notes

Values are parsed as YAML 1.2 (js-yaml's default). The bare words yes, no, on, off parse as strings. Non-string scalars (numbers, booleans) are coerced to strings. A key whose value is null is treated as "not provided".

Development

cd typescript/

# Install dependencies
npm install

# Build the CLI bundle (outputs dist/cli.js)
npm run build

# Run tests
npm test

# Type-check only
npm run lint

The repo also has an end-to-end pytest harness under e2e/ (run from the repo root) that runs the same fixture scenarios against both the Python and TypeScript CLIs and asserts identical output.