📦 chore: make the published package actually complete

`files` was ["dist"], but dist carries 256KB of .js.map and .d.ts.map
whose `sources` point at ../../src/*.ts — which was not published. Every
shipped sourcemap resolved to nothing: 44% of the tarball, dead weight.

The source is 116KB and its comments are the most detailed explanation of
why the engine does what it does, so it now ships (tests and the demo
excluded) and the maps resolve. Verified from a real `npm pack` install:
both utils.js.map and utils.d.ts.map now resolve to a file that exists, so
stepping into cereale in a debugger and "go to definition" from a decorator
both land in the real TypeScript.

Also: CHANGELOG.md ships; the repository/homepage/bugs URLs said
Avalon-Vanguard and only worked via GitHub's redirect, now lowercase to
match the org; publishConfig.access is explicit so a later move to a scoped
name cannot quietly attempt a private publish.

Adds a Publish to npm workflow, deliberately manual — pushing a tag does
not publish, because a tag is a decision to cut a release and publishing is
a decision to make it public and immutable. It asserts the tag exists and
points at the commit being published, refuses a version already on the
registry, runs the full verify gate, prints the file list, and defaults to
a dry run.

Checked end to end against the tarball: a strict consumer (no skipLibCheck,
no DOM lib) compiles and runs against both `cereale` and `cereale/vite`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
This commit is contained in:
Claude
2026-08-05 15:03:28 +00:00
parent 7aaef4d388
commit 9796d599dc
3 changed files with 119 additions and 4 deletions
+89
View File
@@ -0,0 +1,89 @@
name: Publish to npm
# Deliberately manual. Pushing a tag does NOT publish — a tag is a decision to cut a release,
# not a decision to make it public and immutable, and npm's 72-hour unpublish window makes the
# second one hard to take back. Run this workflow from the Actions tab when you mean it.
#
# Before the first real run:
# 1. Create an npm automation token and add it as the NPM_TOKEN repository secret.
# 2. Run once with dry_run left as `true` and read the file list it prints.
# 3. Run again with dry_run set to `false`.
on:
workflow_dispatch:
inputs:
dry_run:
description: 'Resolve and pack everything, but do not publish'
type: boolean
default: true
permissions:
contents: read
id-token: write # required for npm provenance
jobs:
publish:
name: ${{ inputs.dry_run && 'Dry run' || 'Publish' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22.x
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
# The tag and the manifest disagreeing is the classic way to publish 0.3.0 as 0.2.0.
- name: Tag and package.json version must agree
run: |
VERSION=$(node -p "require('./package.json').version")
echo "package.json version: $VERSION"
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
echo "tag v$VERSION exists"
else
echo "::error::No tag v$VERSION. Tag the release commit before publishing."
exit 1
fi
if [ "$(git rev-parse HEAD)" != "$(git rev-parse "v$VERSION^{commit}")" ]; then
echo "::error::v$VERSION does not point at the commit being published."
exit 1
fi
- name: Refuse to republish a version already on the registry
run: |
VERSION=$(node -p "require('./package.json').version")
NAME=$(node -p "require('./package.json').name")
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
echo "::error::$NAME@$VERSION is already published. Bump the version."
exit 1
fi
echo "$NAME@$VERSION is not on the registry yet."
# The same gate that guards every push: type-check, lint, 259 tests, build, and the
# checks that the published types stand alone and the landing page has no CDN deps.
- name: Verify
run: npm run verify
- name: Show exactly what would ship
run: npm publish --dry-run
- name: Publish
if: ${{ inputs.dry_run == false }}
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Summary
run: |
VERSION=$(node -p "require('./package.json').version")
{
echo "### cereale@$VERSION"
if [ "${{ inputs.dry_run }}" = "true" ]; then
echo "Dry run — nothing was published."
else
echo "Published to https://www.npmjs.com/package/cereale/v/$VERSION"
fi
} >> "$GITHUB_STEP_SUMMARY"
+19
View File
@@ -166,6 +166,25 @@ Serialization is a few percent slower for the representability check. Primitives
inline, and arrays and dates skip it, so it costs one `Symbol.toStringTag` read per object. inline, and arrays and dates skip it, so it costs one `Symbol.toStringTag` read per object.
Validation is unchanged. Validation is unchanged.
### Packaging
`files` was `["dist"]`, but `dist` carries 256 KB of `.js.map` and `.d.ts.map` files whose
`sources` point at `../../src/*.ts` — which was not published. Every shipped sourcemap
resolved to nothing: 44% of the tarball, dead. The source is only 116 KB and its comments are
the most detailed explanation of why the engine does what it does, so it is now published
(tests and the demo excluded) and the maps resolve. Stepping into cereale in a debugger, and
"go to definition" from a decorator, both land in the real TypeScript.
`CHANGELOG.md` ships too. The `repository`, `homepage` and `bugs` URLs said `Avalon-Vanguard`
and only worked through GitHub's redirect; they now use the org's actual lowercase name.
`publishConfig.access` is set explicitly so a future move to a scoped name cannot quietly
attempt a private publish.
A `Publish to npm` workflow is in place but deliberately manual — pushing a tag does not
publish. It checks that the tag exists and points at the commit being published, refuses a
version already on the registry, runs the full `verify` gate, prints the file list, and
defaults to a dry run. Publishing needs an `NPM_TOKEN` secret and someone choosing to run it.
## [0.2.0] - 2026-08-04 ## [0.2.0] - 2026-08-04
> The project stays on 0.x while nothing has been published: under semver that signals the > The project stays on 0.x while nothing has been published: under semver that signals the
+11 -4
View File
@@ -23,7 +23,11 @@
"./dist/cjs/metadata.js" "./dist/cjs/metadata.js"
], ],
"files": [ "files": [
"dist" "dist",
"src",
"CHANGELOG.md",
"!src/**/*.test.ts",
"!src/example.ts"
], ],
"scripts": { "scripts": {
"build": "rm -rf dist && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json", "build": "rm -rf dist && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json",
@@ -45,7 +49,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/Avalon-Vanguard/cereale.git" "url": "git+https://github.com/avalon-vanguard/cereale.git"
}, },
"keywords": [ "keywords": [
"json", "json",
@@ -62,9 +66,9 @@
"author": "Avalon Vanguard", "author": "Avalon Vanguard",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/Avalon-Vanguard/cereale/issues" "url": "https://github.com/avalon-vanguard/cereale/issues"
}, },
"homepage": "https://github.com/Avalon-Vanguard/cereale#readme", "homepage": "https://github.com/avalon-vanguard/cereale#readme",
"devDependencies": { "devDependencies": {
"@babel/standalone": "^8.0.4", "@babel/standalone": "^8.0.4",
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
@@ -78,5 +82,8 @@
"typescript": "^6.0.2", "typescript": "^6.0.2",
"typescript-eslint": "^8.58.2", "typescript-eslint": "^8.58.2",
"vitest": "^4.1.4" "vitest": "^4.1.4"
},
"publishConfig": {
"access": "public"
} }
} }