bauset
Version:
Simple npm Package builder
313 lines (226 loc) • 8.2 kB
Markdown
# bauset
A lightweight npm package builder that keeps your project metadata in one place and produces ready-to-publish `.tgz` archives with a single command.
## Table of contents
- [Why bauset?](#why-bauset)
- [Installation](#installation)
- [Quick start](#quick-start)
- [Project structure](#project-structure)
- [PROJECT.txt reference](#projecttxt-reference)
- [package.json template](#packagejson-template)
- [Command-line usage](#command-line-usage)
- [Library API](#library-api)
- [Build output](#build-output)
- [Publishing to npm](#publishing-to-npm)
- [Building bauset with bauset](#building-bauset-with-bauset)
- [Running tests](#running-tests)
## Why bauset?
npm can build packages on its own, and if that works for you, keep using it directly. bauset is useful when you want to:
- Keep all project metadata (`name`, `version`, `author`, etc.) in a single plain-text file (`PROJECT.txt`) instead of inside `package.json`.
- Generate `package.json` from a template so it is always consistent with your metadata.
- Produce both a versioned archive (`mypackage-1.2.3.tgz`) and a stable `mypackage-latest.tgz` in one step.
- Optionally install and test the built package in the same command.
## Installation
```bash
npm install -g bauset
```
## Quick start
1. **Copy this project** as a starting point, or set up the [expected structure](#project-structure) in your own project.
2. **Edit `PROJECT.txt`** with your project's details (see [PROJECT.txt reference](#projecttxt-reference)).
3. **Run bauset** from your project root:
```bash
# Build only
bauset
# Build and install globally
bauset --install --global
# Short form
bauset -ig
```
The package appears in `./pkg/` when done.
## Project structure
bauset expects the following layout in your source directory:
```
[project root]
│
├── PROJECT.txt ← Project metadata (name, version, author, …)
├── README.md ← Shown as your npm landing page
├── LICENSE ← License text
│
├── var/
│ └── in.package.json ← package.json template with %VARIABLE% placeholders
│
├── bin/ ← Executable scripts
├── lib/ ← Library source files
├── test/
│ └── test.js ← Test entry point (run with --test flag)
└── doc/ ← Documentation files
```
Missing entries are silently skipped — you only need what your project actually has.
## PROJECT.txt reference
`PROJECT.txt` is a simple whitespace-delimited key/value file. Lines starting with `#` are comments.
```
# My project configuration
name mypackage
version 1.0.0
description A short description of my package
company My Company
author Your Name
email you@example.com
url https://github.com/you/mypackage
repo git+ssh://git@github.com/you/mypackage.git
bugs https://github.com/you/mypackage/issues
license MIT
```
| Key | Description |
|---|---|
| `name` | Package name (used in the `.tgz` filename) |
| `version` | Version string, e.g. `1.2.3` |
| `description` | One-line package description |
| `company` | Organisation name |
| `author` | Author name |
| `email` | Contact email |
| `url` | Project homepage URL |
| `repo` | Repository URL |
| `bugs` | Bug-report URL |
| `license` | License identifier, e.g. `MIT` |
Any key you add becomes available as a `%KEY%` placeholder in your `in.package.json` template.
## package.json template
`var/in.package.json` is a standard JSON file where any value can contain `%KEY%` placeholders. bauset replaces them with the matching values from `PROJECT.txt` before writing the final `package.json` into the build.
Lines that start with `//` or `#` are treated as comments and stripped automatically.
**Example `var/in.package.json`:**
```json
{
"name": "%NAME%",
"version": "%VERSION%",
"description": "%DESCRIPTION%",
"main": "lib/index.js",
"scripts": {
"test": "node --test test/test.js"
},
"bin": {
"%NAME%": "bin/%NAME%.js"
},
"repository": {
"type": "git",
"url": "%REPO%"
},
"author": "%AUTHOR%",
"license": "%LICENSE%",
"bugs": {
"url": "%BUGS%"
},
"homepage": "%URL%"
}
```
## Command-line usage
```
bauset [options]
```
| Flag | Long form | Description |
|---|---|---|
| `-i` | `--install` | Install the built package after packaging |
| `-g` | `--global` | Install globally (only effective with `--install`) |
| `-s` | `--source <dir>` | Source directory (defaults to current directory) |
| `-r` | `--recursive` | Copy source directories recursively |
| `-v` | `--version` | Print the bauset version and exit |
| `-V` | `--verbose` | Enable verbose logging |
| `-h` | `--help` | Show help and exit |
**Examples:**
```bash
# Build a package from the current directory
bauset
# Build and install globally
bauset --install --global
# Build from a specific source directory
bauset --source /path/to/my/project
# Verbose output while building
bauset --verbose
# Combined short flags
bauset -igV
```
## Library API
You can use bauset programmatically in your own build scripts.
```javascript
const bauset = require('bauset');
```
### `bauset.createPackage(src, dst, opts)` → `Promise`
Stages and packages an npm module.
```javascript
bauset.createPackage('/path/to/project', '/path/to/staging', {
install: false, // set true to install after packaging
global: false, // set true to install globally (requires install: true)
test: false, // set true to run ./test/test.js after installing
Log: console.log // logging function, or omit to suppress output
})
.then(() => console.log('Done!'))
.catch(err => console.error('Build failed:', err));
```
### `bauset.fileCopy(src, dst, opts)`
Copies a file or directory tree.
```javascript
bauset.fileCopy('/path/to/src', '/path/to/dst', {
overwrite: true, // overwrite existing files (default: true)
recursive: true, // recurse into subdirectories (default: true)
Log: console.log // logging function, or null to suppress
});
```
### `bauset.__config__`
Exposes the internal config utilities:
```javascript
const cfg = bauset.__config__;
// Load a PROJECT.txt file into an object
const meta = cfg.loadConfig('/path/to/PROJECT.txt');
// Process a template file, replacing %VAR% placeholders
cfg.processFile(meta, '/path/to/in.package.json', '/path/to/package.json');
// Parse a Unix-style argument list
const args = cfg.parseParams('myprog [opts]', process.argv, [
['i', 'install', 'Install after build'],
['s', 'source=', 'Source directory'],
]);
```
## Build output
After a successful run, two files appear in `./pkg/`:
```
pkg/
├── mypackage-1.2.3.tgz ← versioned archive
└── mypackage-latest.tgz ← always points to the most recent build
```
A `./dist/` directory is used as a staging area during the build and can be ignored or added to `.gitignore`.
## Publishing to npm
Once you have a package in `./pkg/`, publish it with:
```bash
npm publish ./pkg/mypackage-latest.tgz
```
Or use the versioned archive if you need to publish a specific release:
```bash
npm publish ./pkg/mypackage-1.2.3.tgz
```
See the [npm publish docs](https://docs.npmjs.com/cli/v10/commands/npm-publish) for registry authentication and other options.
## Building bauset with bauset
If you are hacking on bauset itself and it is not yet installed, you can run it in-place using the `__bootstrap__` flag. This tells bauset to load its library from the local source tree instead of the installed package.
```bash
# From the bauset project directory
./bin/bauset.js __bootstrap__ --install --global
```
## Running tests
```bash
node --test test/test.js
```
The test suite uses the built-in [`node:test`](https://nodejs.org/api/test.html) runner (Node.js 18+) and covers `loadConfig`, `processFile`, `parseParams`, `fileCopy`, and `createPackage`.
## References
- [Node.js](https://nodejs.org/)
- [npm](https://www.npmjs.com/)
- [npm publish docs](https://docs.npmjs.com/cli/v10/commands/npm-publish)