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-run
# Update this workspace from sibling repos checked out next to it
makage deps constructive
makage deps constructive pgsql-parser --install
makage deps --all --dry-run
makage deps --listmakage deps is the local, day-to-day front end for update-deps. It assumes all your repos are siblings on disk, so a bare name like constructive resolves to ../constructive relative to the current workspace root — no --from/--in paths to type.
makage deps <sibling-repo...> [--all] [--list] [--dry-run] [--install] [--json] [--in <target>]| Flag | Description |
|---|---|
--all |
Update from every sibling directory that is a pnpm workspace |
--list |
List sibling workspaces and exit |
--dry-run |
Report outdated deps without writing files (alias: --check) |
--install |
Run pnpm install in the target workspace when something changed |
--json |
Emit the structured summary on stdout (logs stay on stderr) |
--in |
Target workspace to update (defaults to the workspace root above cwd) |
Names containing a path separator (or starting with . / /) are treated as paths instead of sibling names, so makage deps ../../other/repo works too.
Wire it up as per-repo scripts:
{
"scripts": {
"deps": "pnpm up -r -i -L",
"deps:constructive": "makage deps constructive",
"deps:pgsql-parser": "makage deps pgsql-parser",
"deps:siblings": "makage deps --all"
}
}Then from constructive-db, pnpm deps:constructive pulls the latest versions published by ../constructive into every package.json in the repo.
The 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.