Tiny build helper for monorepo packages
makage is a tiny, cross-platform build helper that replaces common build tools like cpy and rimraf with zero dependencies. It provides essential commands for managing package builds in monorepos.
makage =
make+package. A delightful portmanteau, like brunch for build tools—except makage actually gets things done.
- One-command builds -
makage buildruns clean, TypeScript compilation, and asset copying - Development mode - Add
--devfor source maps and faster iteration - Glob pattern support - Copy files using patterns like
src/**/*.sql(replacement forcopyfiles) - Cross-platform copy - Copy files with
--flatand--footeroptions (replacement forcpy) - Cross-platform clean - Recursively remove directories (replacement for
rimraf) - README + Footer concatenation - Combine README with footer content before publishing
- Assets helper - One-command copying of LICENSE, README, and package.json
- Build TypeScript helper - Run both CJS and ESM TypeScript builds
- Update workspace dependencies - Automatically convert internal package references to
workspace:* - Zero dependencies - Uses only Node.js built-in modules
npm install makageReplace your existing build scripts with makage:
{
"scripts": {
"build": "makage build",
"build:dev": "makage build --dev",
"prepublishOnly": "npm run build"
}
}See how makage simplifies your build scripts:
Before:
"build:dev": "npm run clean; tsc -p tsconfig.json --declarationMap; tsc -p tsconfig.esm.json --declarationMap; npm run copy"After:
"build:dev": "makage build --dev"Or if you need more control:
"build:dev": "makage clean && makage build-ts --dev && makage copy"Before:
"copy": "copyfiles -f ../../LICENSE README.md package.json dist"After:
"copy": "makage copy ../../LICENSE README.md package.json dist --flat"Bonus: Add --footer to automatically concatenate your README with a footer:
"copy": "makage copy ../../LICENSE README.md package.json dist --flat --footer"Before:
"copy:sql": "copyfiles -f src/migrate/sql/* dist/migrate/sql && copyfiles -f src/migrate/sql/* dist/esm/migrate/sql"After:
"copy:sql": "makage copy src/migrate/sql/* dist/migrate/sql --flat && makage copy src/migrate/sql/* dist/esm/migrate/sql --flat"Or with recursive patterns:
"copy:all-sql": "makage copy src/**/*.sql dist/sql --flat"Note: For convenience,
makage assetscombines copy + footer functionality and is kept for backwards compatibility.
# Full build (clean + build-ts + assets)
makage build
# Full build with development mode (adds --declarationMap)
makage build --dev
# Clean build directories (defaults to "dist")
makage clean
makage clean dist build temp # or specify multiple directories
# Build TypeScript (both CJS and ESM)
makage build-ts
# Build TypeScript with source maps for development
makage build-ts --dev
# Copy files to destination
makage copy ../../LICENSE README.md package.json dist --flat
# Copy files with glob patterns
makage copy src/migrate/sql/* dist/migrate/sql --flat
makage copy src/**/*.sql dist/sql --flat
# Copy with automatic README + footer concatenation
makage copy ../../LICENSE README.md package.json dist --flat --footer
# Copy standard assets (LICENSE, package.json, README+FOOTER)
makage assets
# Concatenate README with footer (lower-level command)
makage readme-footer --source README.md --footer FOOTER.md --dest dist/README.md
# Update workspace dependencies
makage update-workspace
# Update outdated cross-repo dependencies (structured JSON output)
makage update-deps --from ./constructive --in .
# Detect only, without writing any files
makage update-deps --from ./constructive --in . --dry-runThe update-deps command enables deterministic, version-aware dependency synchronization across repositories. It detects outdated packages and updates the target repo's package.json files in place (use --dry-run for detection only).
- Discovers all packages in a source pnpm workspace (by reading
pnpm-workspace.yaml) - Scans the target repo's
package.jsonfiles (supports both monorepo and non-workspace layouts) - Cross-references dependencies to find packages that exist in both source and target
- Compares versions using semver to identify outdated packages
- Rewrites outdated version specs in the target
package.jsonfiles, preserving^/~prefixes and skippingworkspace:deps (unless--dry-run) - Outputs structured JSON to stdout for CI consumption (logs go to stderr)
makage update-deps --from <source-workspace> --in <target-repo> [--dry-run]| Flag | Description |
|---|---|
--from |
Path to the source pnpm workspace (contains pnpm-workspace.yaml) |
--in |
Path to the target repo to scan for outdated deps |
--dry-run |
Detect only — report outdated deps without writing any files (alias: --check) |
{
"sourcePackages": [{ "name": "@constructive/foo", "version": "1.2.3", "path": "packages/foo" }],
"matchedPackages": [{ "name": "@constructive/foo", "currentVersion": "^1.1.0", "availableVersion": "1.2.3", "depType": "dependencies", "consumer": "@myapp/bar", "outdated": true }],
"outdatedPackages": [/* subset of matchedPackages where outdated=true */],
"updatedFiles": ["application/bar/package.json"],
"dry_run": false,
"has_dep_changes": true
}The update-deps command is used in GitHub Actions to automatically update downstream repos when the source workspace publishes new versions. The typical CI flow:
- Check out the target repo + source workspace side by side
- Run
makage update-deps --from ./constructive --in .— this updates the target'spackage.jsonfiles and emits structured JSON - Run
pnpm install --no-frozen-lockfile(workspace repos) or per-directorypnpm installto sync lockfiles - Create a PR with the results
The workflow currently updates:
constructive-db(default, also triggers schema propagation)dashboardpgpm-modulesdev-utilssandbox-templatespgpm-boilerplates
For detailed usage and API documentation, see packages/makage/README.md.
- Clone the repository:
git clone https://github.com/constructive-io/makage.git- Install dependencies:
cd makage
pnpm install
pnpm build- Test the package:
cd packages/makage
pnpm test:watchBuilt for developers, with developers.
👉 https://constructive.io
AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.
No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.