AbsoluteJS

Changelog

@absolutejs/changelogv0.7.1betaDev Tools

The changelog contract for the AbsoluteJS packages. Changes are written as typed entries the compiler checks, the release gate reconciles them against the package's own published types so a change nobody wrote down cannot ship, and migrations are data rather than prose so an upgrade can be applied instead of read.

#Installation

BASH
bun add @absolutejs/changelog

#Capabilities

Overview

The changelog contract for the AbsoluteJS packages.

A changelog is worth having when it can be trusted and acted on. Prose changelogs manage neither: they rot because writing them is a discipline, and they cannot be acted on because "refactored the server options" is a true sentence that does not say which export moved or what to write instead.

This package makes both possible.

Show 6 more

Entries are typed. A change is written as TypeScript, so the compiler

insists that a breaking change names the exports it breaks and says how to migrate. The entries that cost somebody an afternoon are the ones that cannot be filed empty.

The release gate checks them against the package. Before a release goes

out, the exports that vanished or changed shape are compared with the exports the entries name. Forget an entry and the release stops. Nobody has to remember.

Migrations are data. A rename and a move are the overwhelming majority

of real breaking changes, and both are mechanical. Written as data they can be applied — by a CLI, an editor, or a hosted upgrade button — without running a line of code that came from a registry.

Adopting it

adopt creates changelog/unreleased/, keeps whatever CHANGELOG.md already said as changelog/history.md, adds changelog.json and CHANGELOG.md to the package's files, and makes sure your tsconfig compiles the entries — that last one matters, because an entry nothing compiles is an entry nobody checks.

Then add the gate to the release chain:

Put it after build: the check compares the types you are about to publish against the ones you published last time, and it needs dist to exist.

Writing a change

One file per change, so two branches adding one do not meet over the same line:

Which writes changelog/unreleased/start-is-now-listen.ts:

The import is type-only, so an entry has nothing to resolve at run time and the gate works in a checkout with no dependencies installed.

Show 10 more

Checked where you type it

An entry can be written against the package's own API, and add scaffolds it that way when it finds one:

Suggested rather than required, for two reasons: a removed entry names something that has just stopped existing, and typeof Api cannot see type-only exports at all. The gate is the certain half — it reads the published .d.ts, which carries them.

The kinds

breaking and removed cost a consumer work, and the type refuses them without symbols and a migration. added, changed, deprecated, fixed, security and internal do not.

The migrations

Shape — What it means — Applied

rename: { from, to } — An export kept its meaning and changed its name — yes

moved: { symbol, from, to } — An export moved to another entry point — yes

resubpath: { from, to } — A whole entry point moved — yes

Releasing

Works out the version from the entries — a breaking change moves the minor below 1.0.0 and the major above it, and a version already on a prerelease line moves along that line — then writes changelog.json and CHANGELOG.md, bumps package.json, and deletes the entries it consumed.

--as major|minor|patch|prerelease overrides the inference, --version x.y.z overrides it entirely, and --dry shows the release without writing anything.

The gate

every entry parses, and the disruptive ones carry what they must;

CHANGELOG.md is what the entries say it should be — it is generated, and

editing it is how the two copies drift;

Show 10 more

the version in package.json and the newest release agree;

package.json still ships both documents, and nothing is sitting in the

entry directory that no release will read;

the entries name every export that moved since the newest published

version — not the one in package.json, which between release and publish is a version nobody can fetch;

and every migration describes what actually happened: a rename whose

destination this version does not export, a rename whose source is still exported, a move to an entry point the package does not have, a removal of something still there.

That last one is what makes an applicable migration safe to apply. A migration that reads correctly and rewrites working code into something that does not compile is the whole risk of automating an upgrade, and it fails the release instead.

--offline skips the two that talk to the registry.

adopt also writes prepublishOnly, so the gate runs however a publish was started — a release script, a bare npm publish, a CI job. A rule that can be walked around eventually is.

Reading somebody else's

Anything deciding whether an upgrade is safe reads the published document:

For a package that has not adopted this yet, publishedSurface and diffSurface compare the published types of two versions instead — less than a changelog, and much more than nothing.

Licence

MIT.

Outcomes

What you can build

Overview

The changelog contract for the AbsoluteJS packages.

Adopting it

adopt creates changelog/unreleased/, keeps whatever CHANGELOG.md already said as changelog/history.md, adds changelog.json and CHANGELOG.md to the package's files, and makes sure your tsconfig compiles the entries — that last one matters, because an entry nothing compiles is an entry nobody checks.

Writing a change

One file per change, so two branches adding one do not meet over the same line:

Hardening checklist

Production guidance

Make every external boundary explicitPin the deployed @absolutejs/changelog version, replace example or memory-backed dependencies with durable implementations, bound external calls, protect credentials, and emit enough evidence to retry or recover safely.

Follow in order

Troubleshooting path

1
Trace from the first failed boundary
Reproduce the smallest canonical @absolutejs/changelog example, confirm the supported entry point and version in the API explorer, then inspect the first boundary that did not produce its documented result.

#Adopting it

Partial snippet

Working example for Adopting it.

SH
bun add -d @absolutejs/changelog
bunx absolute-changelog adopt

#Adopting it 2

Partial snippet

adopt creates changelog/unreleased/, keeps whatever CHANGELOG.md already said as changelog/history.md, adds changelog.json and CHANGELOG.md to the package's files, and makes sure your tsconfig compiles the entries — that last one matters, because an entry nothing compiles is an entry nobody checks.

JSON
"check:package": "bun run typecheck && bun run build && bun run test && absolute-changelog check"

#Public entry points

Supported entry points declared by this project’s package manifest. Internal dist paths are not part of the package contract.

@absolutejs/changelogPublic package entry point declared in package.json.

#Package commands

Scripts declared by this project’s package manifest.

bun run buildrm -rf dist && bun build src/index.ts src/cli.ts --outdir dist --root src --sourcemap --target=bun --external typescript && tsc --project tsconfig.build.json
bun run check:packagebun run typecheck && bun run lint && bun run test && bun run build && bun src/cli.ts check
bun run formatprettier --write "./**/*.{ts,json,md}"
bun run linteslint . --max-warnings 0
bun run testbun test tests/
bun run typechecktsc --noEmit

#API reference

Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.

80 symbols
applyMigrationexportPermalink
TS
applyMigration
Exported from @absolutejs/changelog