📦 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:
@@ -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"
|
||||
@@ -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.
|
||||
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
|
||||
|
||||
> The project stays on 0.x while nothing has been published: under semver that signals the
|
||||
|
||||
+11
-4
@@ -23,7 +23,11 @@
|
||||
"./dist/cjs/metadata.js"
|
||||
],
|
||||
"files": [
|
||||
"dist"
|
||||
"dist",
|
||||
"src",
|
||||
"CHANGELOG.md",
|
||||
"!src/**/*.test.ts",
|
||||
"!src/example.ts"
|
||||
],
|
||||
"scripts": {
|
||||
"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": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Avalon-Vanguard/cereale.git"
|
||||
"url": "git+https://github.com/avalon-vanguard/cereale.git"
|
||||
},
|
||||
"keywords": [
|
||||
"json",
|
||||
@@ -62,9 +66,9 @@
|
||||
"author": "Avalon Vanguard",
|
||||
"license": "MIT",
|
||||
"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": {
|
||||
"@babel/standalone": "^8.0.4",
|
||||
"@eslint/js": "^10.0.1",
|
||||
@@ -78,5 +82,8 @@
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "^8.58.2",
|
||||
"vitest": "^4.1.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user