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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@feinarbyte/file-merge

v2.2.0

Published

File fragment merger - merge JSON, YAML, text files and more from templates, fragments, and overrides. Batteries included, dlx-ready.

Readme

@feinarbyte/file-merge

File fragment merger - batteries included, dlx-ready.

Merge files from templates, fragments, and overrides with intelligent strategies for YAML, JSON, GitLab CI, Docker Compose, TypeScript configs, text files, and more.

Installation

# Using pnpm dlx (recommended)
pnpm dlx @feinarbyte/file-merge

# Using npx
npx @feinarbyte/file-merge

# Or install globally
pnpm add -g @feinarbyte/file-merge

Configuration

Create a config file in your project root to customize behavior:

# Create YAML config (recommended)
file-merge init

# Or create JSON config
file-merge init --json

YAML Configuration (Recommended)

# .file-merge.config.yaml
templatesDir: config-templates

# Glob patterns with negation support
fragmentPatterns:
  - "**/*.fragment.*"        # Include all fragment files
  - "!node_modules/**"       # Exclude node_modules
  - "!dist/**"               # Exclude dist
  # Advanced: Exclude folder but include specific patterns
  # - "!folderA/folderB/**"
  # - "folderA/folderB/catalog.*.fragment.*"

ignorePatterns:
  - "**/node_modules/**"
  - "**/dist/**"
  - "**/.git/**"

JSON Configuration

{
  "templatesDir": "config-templates",
  "fragmentPatterns": [
    "**/*.fragment.*",
    "!node_modules/**",
    "!dist/**"
  ],
  "ignorePatterns": [
    "**/node_modules/**",
    "**/dist/**",
    "**/.git/**"
  ]
}

Configuration Options

  • noSymlink - Copy single-source outputs instead of creating symlinks (default: false)
  • copyPatterns - Per-file glob patterns (relative to project root) for targets that should be copied instead of symlinked when they have a single source (default: [])
  • templatesDir - Directory containing template files with __ prefix (default: "atom-framework/config-templates")
  • fragmentPatterns - Glob patterns to discover fragment files. Supports negation with ! prefix
    • Example: ["**/*.fragment.*", "!node_modules/**", "!folderA/**", "folderA/catalog.*.fragment.*"]
  • ignorePatterns - Additional patterns to ignore (applied after fragmentPatterns)
  • modules - Optional module activation filtering (atom-framework specific)
    • activeDir - Directory where active modules are symlinked
    • sourceDir - Directory containing available modules
  • watchPatterns - Patterns to watch in watch mode (optional, auto-derived if not set)

Copy instead of symlink (per file)

By default, targets with a single source (typically a template) are symlinked to keep a single canonical file. If you need a real file (for example .gitignore in some environments), configure per-target copy rules:

# .file-merge.config.yaml
copyPatterns:
  - ".gitignore"

Config File Formats

File-merge automatically detects and loads config files in this order:

  1. .file-merge.config.yaml (recommended)
  2. .file-merge.config.yml
  3. .file-merge.config.json

If no config file exists, file-merge uses default patterns suitable for the atom-framework structure.

Custom Config Location

You can specify a custom config file location:

# Use a different config file
file-merge apply --config configs/prod.config.json

# Use a shared config from parent directory
file-merge apply --config ../shared-config.json

# Watch with custom config
file-merge watch --config my-config.json

Usage

Apply Merging

file-merge apply

Options:

  • --dry-run - Show what would be generated without writing files
  • --verbose - Detailed output
  • --filter <patterns...> - Only process files matching patterns
  • --config <path> - Path to config file (default: auto-detect .yaml, .yml, or .json)

Watch Mode

file-merge watch

Automatically regenerates merged files when source files change.

Options:

  • --verbose - Detailed output
  • --config <path> - Path to config file (default: auto-detect .yaml, .yml, or .json)

Migration

# Analyze existing files
file-merge migrate analyze

# Extract differences into override files
file-merge migrate extract --strategy smart

Validation

file-merge validate

Status

file-merge status [file]

Features

  • Configurable - Customize templates directory, fragment patterns, and module locations via .file-merge.config.json
  • Template-based merging - Define templates in configurable templates directory (default: config-templates/)
  • Fragment merging - Merge fragments from packages/modules using configurable patterns
  • Override support - Override templates with project-specific changes
  • Smart merge strategies - Auto-detects merge strategy based on file type
  • Template variables - Use {{VARIABLE}} syntax in filenames and paths (resolved from environment variables)
  • Module filtering - Only include fragments from active modules (configurable)
  • Supported formats: YAML, JSON, TOML, GitLab CI, Docker Compose, TypeScript configs, VS Code tasks, text files (.gitignore, .dockerignore), and more

Template Variables

File-merge supports template variables using {{VARIABLE}} syntax:

  • In template filenames: atom-framework/config-templates/__{{ENV}}.yaml → resolves to {{ENV}}.yaml in project root
  • In fragment _targetPath: _targetPath: "config/{{ENV}}.json" → resolves to the target path

Variables are resolved from environment variables. If a required variable is missing, the tool will fail with a clear error message.

Example:

# Fragment file: packages/my-package/config.fragment.yaml
_targetPath: "config/{{ENV}}/settings.json"
# ... rest of fragment content

If ENV=production, this fragment will target config/production/settings.json.

Merge Strategies

  • deep-merge - Deep merge for JSON objects
  • yaml-merge - Deep merge for YAML files
  • toml-merge - Deep merge for TOML files
  • gitlab-ci - GitLab CI/CD configuration merging
  • docker-compose - Docker Compose file merging
  • tsconfig - TypeScript config merging
  • vscode-tasks - VS Code tasks.json merging
  • append-lines - Line-by-line appending (for .gitignore, etc.)
  • replace - Last source wins

GitLab CI job name prefix override (per fragment)

When merging .gitlab-ci.yml using the gitlab-ci strategy, file-merge normally prefixes jobs based on the fragment file’s folder hierarchy.

You can override this per fragment using __gitlabJobPrefix:

_targetPath: .gitlab-ci.yml
__gitlabJobPrefix: deploy   # "" disables prefixing

build:
  stage: build
  script:
    - echo "hello"

Development

This project uses mise for tool version management.

# Install tools (node, pnpm)
mise install

# Install dependencies
pnpm install

# Build
pnpm run build

# Watch mode
pnpm run dev

Releasing

Releases are automated via GitLab CI. When a version tag is pushed, the pipeline publishes the package to npm.

# Patch release (bug fixes): 2.0.1 → 2.0.2
pnpm run release:patch

# Minor release (new features): 2.0.1 → 2.1.0
pnpm run release:minor

# Major release (breaking changes): 2.0.1 → 3.0.0
pnpm run release:major

Each release command will:

  1. Bump the version in package.json
  2. Create a git commit with message chore(release): vX.Y.Z
  3. Create a git tag vX.Y.Z
  4. Push the commit and tag to origin

The GitLab CI pipeline then automatically publishes to npm.

Manual Publishing

If you need to publish manually:

# Make sure you're logged in to npm with access to @feinarbyte scope
pnpm login

# Publish (will automatically build via prepublishOnly)
pnpm publish --access public

Migration from Hardcoded Paths

If you're using an older version with hardcoded atom-framework/ paths, file-merge will continue to work with the default configuration. To customize for your project:

  1. Run file-merge init to create .file-merge.config.json
  2. Edit the config to match your project structure
  3. Update templatesDir, fragmentPatterns, and modules paths as needed

Example for a different structure:

{
  "templatesDir": "config-templates",
  "fragmentPatterns": [
    "src/**/*.fragment.*",
    "libs/**/*.fragment.*"
  ],
  "modules": {
    "activeDir": "enabled-modules",
    "sourceDir": "src/modules"
  }
}

License

MIT