10 Commits
Author SHA1 Message Date
SenrokaiandClaude Opus 5.5 5f2f3f0af1 Renovate : preset commun avalon-vanguard/renovate-config
CI / verify (20.x) (pull_request) Successful in 2m43s
CI / verify (22.x) (pull_request) Successful in 1m25s
CI / verify (24.x) (pull_request) Successful in 1m17s
node / check (pull_request) Successful in 1m17s
Le dépôt étend la base seulement (pas la couche Angular). Renovate tourne
depuis avalon-vanguard/renovate ; aucun workflow renovate à retirer ici.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 17:03:33 +02:00
SenrokaiandClaude Opus 5.5 e4b8c0f6aa CI sur Gitea Actions par le workflow commun avalon-vanguard/ci
.gitea/workflows/ci.yml appelle node.yml@v1 sur la même matrice (Node 20.x,
22.x, 24.x) et les mêmes déclencheurs que .github/workflows/ci.yml. Comme
node.yml ne connaît que lint, typecheck, test, build et check :
- « typecheck » renvoie à « type-check » ;
- « check » enchaîne, dans l'ordre de la CI GitHub, les contrôles
  post-build : points d'entrée publiés, démo, check:types, check:docs,
  check:docs-sync.

Les cinq « node -e » de chargement des points d'entrée passent dans
scripts/check-entry-points.mjs, que la CI GitHub appelle aussi : les deux
CI vérifient la même chose.

node.yml lance « npm test » et non « test:coverage » : vitest.config.ts ne
fixe aucun seuil et rien ne lit le rapport lcov, donc ce sont les mêmes
tests qui décident. La CI GitHub garde test:coverage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 17:03:33 +02:00
SenrokaiandClaude Opus 5.5 68d5d46ec0 Config partagée : ESLint et tsconfig depuis @avalon-vanguard/config
eslint.config.mjs prend @avalon-vanguard/config/eslint, qui contient les deux
mêmes entrées qu'avant (@eslint/js recommended + typescript-eslint recommended) ;
les règles, globals et ignores propres à cereale restent ici. tsconfig.json
étend tsconfig/library.json, qui porte les huit options retirées. « strict »
reste explicite.

Pas de .editorconfig : sans config Prettier dans le dépôt, Prettier le lirait
et changerait le formatage.

.npmrc : le scope @avalon-vanguard se lit sur le registre npm de Gitea, en
lecture anonyme, sans jeton.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 17:03:23 +02:00
Senrokai 5f2e310f61 Merge pull request #16 from avalon-vanguard/develop
🔖 0.4.1 — the published README says the package is not on npm
2026-08-20 18:36:07 +02:00
Claude 057162e45b 🔖 fix: sync package-lock, and stamp the version fallbacks from the build
Junie's review on #16 caught the lock, and it was worse than reported:
package-lock.json said 0.3.0, so it had already missed the 0.4.0 release. It
does not ship (npm excludes it from tarballs, and `files` lists only dist, src,
FRAMEWORKS.md and CHANGELOG.md) and `npm ci` never complained because it only
diffs dependencies, not the project's own version — which is exactly why it
drifted two releases without anyone noticing. Regenerated with
`npm install --package-lock-only`.

The other half was the two version strings in docs/index.html: the brand badge
and the "It is still 0.x" line. Both are no-JavaScript fallbacks — page.js
overwrites them from meta.js — so they are right in a browser and stale in a
text reader or a scraper. Bumping them by hand is what failed on 0.4.0 and
again here, and it is the "release facts hand-bumped beside their generator"
finding from the code review.

So build-docs.mjs now stamps them, next to the meta.js it already writes. The
docs-sync gate turns a forgotten bump into a CI failure instead of a review
comment. Both regexes are asserted: renaming the markup fails the build with
the pattern that stopped matching, rather than silently stamping nothing —
verified by renaming the id and watching it exit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-20 16:34:49 +00:00
Claude 46e30909c7 🔖 fix: regenerate docs/meta.js for 0.4.1
The version bump left meta.js at 0.4.0, so CI's docs-sync gate failed on all
three Node versions — the gate doing exactly its job.

Worth naming why it got through locally: `npm run verify` does not chain
check:docs-sync, so a green verify says nothing about docs/ being current. I
briefly added it, then took it back out. check:docs-sync is built on
`git status`, so inside verify it would fail during any in-progress docs edit,
and docs/ does not ship in the tarball — the package `files` list is dist,
src, FRAMEWORKS.md and CHANGELOG.md. Publishing correctness never depended on
it. CI and the Pages workflow already gate the site, which is the only thing
that stale docs affect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-20 16:31:11 +00:00
Claude b2f2de2bd4 🔖 chore: 0.4.1 — the published README says the package is not on npm
The README inside a tarball is what npmjs.com renders, so the cereale package
page currently tells visitors: "npm install cereale does not resolve to this
library — the name is unclaimed on the registry." True when it was written,
nonsense on the page of the thing it describes.

Nothing could have prevented it. 0.4.0 was the first publish, so the docs could
only be corrected after the registry proved the claim wrong; the fix has to
ride a second version.

No code changes. Every emitted file is byte-identical to 0.4.0 except the
banner line of dist/cereale.min.js, which carries the version string — checked
by unpacking the published 0.4.0 tarball and diffing it against a fresh pack,
which is also why the changelog no longer claims dist/ is untouched. It said
that first, and it was wrong.

Patch rather than minor: no API surface moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-20 16:23:09 +00:00
Senrokai 1b9202edf1 Merge pull request #15 from avalon-vanguard/develop
📦 cereale is on npm — docs, badge, and trusted publishing
2026-08-20 18:18:05 +02:00
Claude 730e5902a5 🔎 ci: make the dry run prove trusted publishing engaged
npm calls oidc() before every dryRun branch in publish.js, so `npm publish
--dry-run` performs the real token exchange and the existing step is already a
trusted-publishing smoke test — it just could not be read.

The exchange is non-throwing by design, so at the default log level a working
OIDC exchange and a silent fallback to NPM_TOKEN look exactly the same. Raising
that one step to verbose surfaces `oidc Successfully retrieved and set token`,
which turns "did trusted publishing actually work?" into something a dry run
answers without publishing anything.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-20 16:16:19 +00:00
Claude f56d2811cb 📦 docs: cereale is on npm, and release.yml moves to trusted publishing
0.4.0 published, so the three places that said it had not stopped being true:
the README install section, the landing page's install panel, and the "what
cereale is not" item. All three now say `npm install cereale`, and the last
becomes a limitation that is actually still true — it is 0.x, where a minor
bump is allowed to break you.

An npm version badge joins the row, tinted the same brand brown as the rest.
It was held back deliberately while the package did not exist, because a
badge that renders "not found" is worse than no badge.

page.js loses the install-shell substitution: it rewrote the tarball filename
in a code block that no longer exists.

--- release.yml: trusted publishing ---

npm exchanges the workflow's short-lived GitHub identity token for a publish
token scoped to this package, so no long-lived npm token has to exist. The
header documents exactly what to enter on npmjs.com, including the two fields
npm checks against the OIDC claims and refuses on mismatch: the workflow
filename must match this file, and Environment must stay blank while the job
declares none.

The find that matters: Node 22 bundles npm 10.x, which has no OIDC code at
all. Verified by unpacking the CLI — lib/utils/oidc.js is absent in 11.4.2 and
present in 11.5.0. Since npm's OIDC step is deliberately non-throwing, an old
CLI would have skipped trusted publishing in silence and fallen back to token
auth while appearing to work. So the workflow raises npm and then asserts the
version, rather than assuming it.

NPM_TOKEN stays as a fallback for the same non-throwing reason: this can land
before the registry side is configured, and nothing breaks. Delete the secret
once a real run shows OIDC working.

--provenance stays explicit. Under OIDC npm enables it itself for a public
repo, but only when the flag is left at its default (config.isDefault check in
oidc.js), so passing it just skips that auto-enable and lands in the same
place — while remaining the only thing that produces an attestation on the
token path.

actionlint clean; the version guard tested against 10.9.7, 11.4.2, 11.5.0 and
12.0.2; the page re-rendered with no errors and no "not on npm" text left.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-20 16:10:42 +00:00
16 changed files with 201 additions and 61 deletions
+25
View File
@@ -0,0 +1,25 @@
# Contrôles de .github/workflows/ci.yml sur Gitea, par le workflow commun avalon-vanguard/ci.
# Ce dossier fait ignorer .github/workflows par Gitea ; GitHub continue d'exécuter les siens
# (CI, Pages, publication npm). Les contrôles post-build (points d'entrée, démo, types publiés,
# page de docs) sont regroupés dans le script « check ».
#
# node.yml lance « npm test », pas « test:coverage » : vitest.config.ts ne fixe aucun seuil de
# couverture et rien ne lit le rapport lcov, donc les mêmes tests décident du résultat.
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
verify:
strategy:
fail-fast: false
matrix:
node: [20.x, 22.x, 24.x]
uses: avalon-vanguard/ci/.gitea/workflows/node.yml@v1
with:
node-version: ${{ matrix.node }}
secrets: inherit
+1 -6
View File
@@ -34,12 +34,7 @@ jobs:
- name: Build
run: npm run build
- name: Verify published entry points load
run: |
node --input-type=module -e "import * as m from './dist/esm/index.js'; if (typeof m.toInstance !== 'function') throw new Error('ESM entry point broken');"
node --input-type=commonjs -e "const m = require('./dist/cjs/index.js'); if (typeof m.toInstance !== 'function') throw new Error('CJS entry point broken');"
node --input-type=module -e "import { standardDecorators } from './dist/esm/vite.js'; if (standardDecorators().enforce !== 'pre') throw new Error('ESM cereale/vite broken');"
node --input-type=commonjs -e "const { standardDecorators } = require('./dist/cjs/vite.js'); if (standardDecorators().enforce !== 'pre') throw new Error('CJS cereale/vite broken');"
node --input-type=module -e "import * as m from './dist/cereale.min.js'; if (typeof m.toInstanceSync !== 'function') throw new Error('flat bundle broken');"
run: node scripts/check-entry-points.mjs
- name: Run Demo
run: npm run demo
- name: Published types stand alone
+54 -5
View File
@@ -4,10 +4,28 @@ name: Publish to npm
# 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`.
# Authentication is by **trusted publishing** (OIDC): npm exchanges the workflow's
# short-lived GitHub identity token for a publish token scoped to this package, so no
# long-lived npm token has to exist. To enable it, on npmjs.com → the cereale package →
# Settings → Trusted publisher → GitHub Actions, set:
#
# Organization or user: avalon-vanguard
# Repository: cereale
# Workflow filename: release.yml
# Environment: (leave blank — this workflow does not use one)
#
# The workflow filename must match this file's name, and the Environment field must be
# blank unless a matching `environment:` is added to the publish job; npm checks both
# against the OIDC claims and refuses the exchange if either disagrees.
#
# NPM_TOKEN is kept as a fallback. npm's OIDC step is deliberately non-throwing — if the
# trusted publisher is not configured, or the CLI is too old, it logs and falls through
# to token auth. That makes the switch safe to land before the registry side is set up.
# Once a real run shows OIDC working, the NPM_TOKEN secret can be deleted.
#
# Before a real run:
# 1. Run once with dry_run left as `true` and read the file list it prints.
# 2. Run again with dry_run set to `false`.
on:
workflow_dispatch:
inputs:
@@ -18,7 +36,7 @@ on:
permissions:
contents: read
id-token: write # required for npm provenance
id-token: write # the OIDC identity npm exchanges, and provenance
jobs:
publish:
@@ -37,6 +55,21 @@ jobs:
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
# Node 22 bundles npm 10.x, which has no OIDC support at all — it would skip
# trusted publishing in silence and fall back to token auth. Trusted publishing
# landed in npm 11.5.0 (lib/utils/oidc.js), so the version is raised and then
# asserted rather than assumed.
- name: Use an npm that can do trusted publishing
run: |
npm install -g npm@latest
V=$(npm --version)
echo "npm $V"
MAJ=${V%%.*}; REST=${V#*.}; MIN=${REST%%.*}
if [ "$MAJ" -lt 11 ] || { [ "$MAJ" -eq 11 ] && [ "$MIN" -lt 5 ]; }; then
echo "::error::npm $V has no OIDC support; trusted publishing needs >= 11.5.0"
exit 1
fi
- name: Install dependencies
run: npm ci
@@ -72,12 +105,28 @@ jobs:
run: npm run verify
- name: Show exactly what would ship
# `npm publish --dry-run` performs the OIDC token exchange before it short-circuits
# (publish.js calls oidc() ahead of every dryRun branch), so this step is also the
# trusted-publishing smoke test — a dry run proves the exchange without publishing.
#
# verbose, because npm's OIDC step is non-throwing: at the default log level a
# successful exchange and a silent fallback to token auth look identical. Success
# prints `oidc Successfully retrieved and set token`; if that line is missing,
# trusted publishing did not engage. (The reasons it skips are logged at silly.)
env:
NPM_CONFIG_LOGLEVEL: verbose
run: npm publish --dry-run
- name: Publish
if: ${{ inputs.dry_run == false }}
# --provenance stays explicit. Under OIDC npm would enable it on its own for a
# public repo, but only when the flag was left at its default; asking for it
# directly just skips that auto-enable and reaches the same place. On the token
# fallback path it is the only thing that produces an attestation at all.
run: npm publish --provenance --access public
env:
# Fallback only. Ignored once the trusted publisher is configured, because npm
# sets its own short-lived token before reading credentials.
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Summary
+1
View File
@@ -0,0 +1 @@
@avalon-vanguard:registry=https://git.avalonvanguard.com/api/packages/avalon-vanguard/npm/
+14
View File
@@ -5,6 +5,20 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.4.1] - 2026-08-20
No code changes. Every emitted file is byte-identical to 0.4.0 except the banner line of
`dist/cereale.min.js`, which carries the version string. This exists because the README
inside the 0.4.0 tarball is the one npmjs.com renders, and it said the package was not on
npm: *"`npm install cereale` does not resolve to this library — the name is unclaimed on
the registry."* True when it was written, nonsense on the package page of the thing it
describes.
0.4.0 was the first publish, so nothing could have carried the corrected text: the docs
could only be fixed after the registry proved the claim wrong. The install instructions,
the landing page panel, and the "what cereale is not" entry now say `npm install cereale`,
and the README carries an npm version badge.
## [0.4.0] - 2026-08-05
### `cereale/min` — one file, no bundler
+5 -11
View File
@@ -1,5 +1,6 @@
# Cereale
[![npm](https://img.shields.io/npm/v/cereale?color=a0784a&label=npm)](https://www.npmjs.com/package/cereale)
[![CI](https://github.com/avalon-vanguard/cereale/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/avalon-vanguard/cereale/actions/workflows/ci.yml)
[![Docs](https://github.com/avalon-vanguard/cereale/actions/workflows/pages.yml/badge.svg)](https://avalon-vanguard.github.io/cereale/)
[![Node ≥20](https://img.shields.io/badge/node-%E2%89%A520-a0784a)](https://github.com/avalon-vanguard/cereale/blob/main/package.json)
@@ -79,20 +80,13 @@ entity, anything with behaviour attached. Reach for Zod when you just want the d
## Installation
Not on npm yet: `npm install cereale` does **not** resolve to this library — the name is
unclaimed on the registry. Installing straight from GitHub will not work either, because the
build output is not committed. Until the first publish, install from a clone:
```bash
git clone https://github.com/avalon-vanguard/cereale
cd cereale
npm install && npm run build
npm pack # → cereale-0.4.0.tgz
# then, from your own project
npm install ../cereale/cereale-0.4.0.tgz
npm install cereale
```
Published with [provenance](https://www.npmjs.com/package/cereale), so the registry carries a
verified attestation linking the tarball to the commit it was built from.
Cereale uses **TC39 standard decorators** (since 0.2.0), so no `experimentalDecorators` flag:
```json
+11 -16
View File
@@ -410,7 +410,7 @@ footer { border-top: 1px solid var(--border); padding-block: 2.5rem; color: var(
<header class="nav">
<div class="wrap nav-inner">
<a class="brand" href="#top"><svg class="mark" width="10" height="18" viewBox="0 0 10 18" aria-hidden="true" focusable="false"><rect x="4" y="0" width="2" height="18" fill="currentColor" opacity=".3"/><rect x="0" y="2" width="10" height="2" fill="currentColor"/><rect x="0" y="6" width="10" height="2" fill="currentColor"/><rect x="0" y="10" width="10" height="2" fill="currentColor"/><rect x="0" y="14" width="10" height="2" fill="currentColor"/></svg>cereale <span class="badge" id="version-badge">v0.4.0</span></a>
<a class="brand" href="#top"><svg class="mark" width="10" height="18" viewBox="0 0 10 18" aria-hidden="true" focusable="false"><rect x="4" y="0" width="2" height="18" fill="currentColor" opacity=".3"/><rect x="0" y="2" width="10" height="2" fill="currentColor"/><rect x="0" y="6" width="10" height="2" fill="currentColor"/><rect x="0" y="10" width="10" height="2" fill="currentColor"/><rect x="0" y="14" width="10" height="2" fill="currentColor"/></svg>cereale <span class="badge" id="version-badge">v0.4.1</span></a>
<nav class="nav-links" aria-label="Primary">
<a class="nav-hide" href="#guarantee">Guarantee</a>
<a class="nav-hide" href="#playground">Playground</a>
@@ -814,22 +814,15 @@ export default defineConfig({
</div>
<div>
<p class="compare-label"><span class="pill pill-bad">not on npm yet</span> installing it today</p>
<p class="compare-label"><span class="pill pill-ok">on npm</span> installing it</p>
<div class="code">
<div class="code-head"><span class="name">shell</span></div>
<pre><code data-lang="text" id="install-shell">git clone https://github.com/avalon-vanguard/cereale
cd cereale
npm install &amp;&amp; npm run build
npm pack # → cereale-0.4.0.tgz
# then, from your own project
npm install ../cereale/cereale-0.4.0.tgz</code></pre>
<pre><code data-lang="text">npm install cereale</code></pre>
</div>
<p class="pg-note">
<code class="inline-code">npm install cereale</code> does <strong>not</strong> resolve to
this library — the name is unclaimed on the registry. Installing straight from GitHub
will not work either: the build output is not committed, so the package would arrive
without its <code class="inline-code">dist/</code>.
Published from CI with <strong>provenance</strong>, so the registry carries a verified
attestation linking the tarball to the commit it was built from — visible on the
<a href="https://www.npmjs.com/package/cereale">package page</a>.
</p>
</div>
</div>
@@ -998,9 +991,11 @@ npm install ../cereale/cereale-0.4.0.tgz</code></pre>
cannot reach. Both are errors rather than silent no-ops.</p>
</div>
<div class="note-item">
<h3>It is not on npm yet</h3>
<p><span class="js-version">0.4.0</span> lives in the repository. <code class="inline-code">npm install cereale</code> does not
resolve to this library — build it from source until it is published.</p>
<h3>It is still 0.x</h3>
<p><span class="js-version">0.4.1</span> is published, and under semver a 0.x minor bump
is allowed to break you. Pin the version until 1.0; the
<a href="https://github.com/avalon-vanguard/cereale/blob/main/CHANGELOG.md">changelog</a>
says what moved and why.</p>
</div>
</div>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
// Generated by scripts/build-docs.mjs — do not edit.
window.CEREALE_META = {
"version": "0.4.0",
"version": "0.4.1",
"node": ">=20.0.0"
};
-6
View File
@@ -43,12 +43,6 @@
Array.prototype.forEach.call(document.querySelectorAll('.js-version'), function (el) {
el.textContent = meta.version;
});
// The install snippet names the tarball npm pack produces; keep it tied to the
// same package.json fact the badge uses instead of hand-bumping it each release.
var shell = document.getElementById('install-shell');
if (shell) {
shell.textContent = shell.textContent.replace(/cereale-[\d.]+\.tgz/g, 'cereale-' + meta.version + '.tgz');
}
}
if (decoratorCount) {
Array.prototype.forEach.call(document.querySelectorAll('.js-dec-count'), function (el) {
+3 -3
View File
@@ -1,4 +1,4 @@
import eslint from '@eslint/js';
import avalonBase from '@avalon-vanguard/config/eslint';
import tseslint from 'typescript-eslint';
import globals from 'globals';
@@ -6,8 +6,8 @@ export default tseslint.config(
{
ignores: ['dist/**', 'node_modules/**', 'coverage/**', 'docs/**'],
},
eslint.configs.recommended,
...tseslint.configs.recommended,
// @eslint/js recommended + typescript-eslint recommended, shared across avalon-vanguard
avalonBase,
{
languageOptions: {
globals: {
+35 -2
View File
@@ -1,14 +1,15 @@
{
"name": "cereale",
"version": "0.3.0",
"version": "0.4.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cereale",
"version": "0.3.0",
"version": "0.4.1",
"license": "MIT",
"devDependencies": {
"@avalon-vanguard/config": "^1.0.0",
"@babel/standalone": "^8.0.4",
"@eslint/js": "^10.0.1",
"@swc/core": "^1.15.47",
@@ -26,6 +27,38 @@
"node": ">=20.0.0"
}
},
"node_modules/@avalon-vanguard/config": {
"version": "1.0.0",
"resolved": "https://git.avalonvanguard.com/api/packages/avalon-vanguard/npm/%40avalon-vanguard%2Fconfig/-/1.0.0/config-1.0.0.tgz",
"integrity": "sha512-ySojd0OONRb9N9KT4CJeyLf5GUrfRP8jxfPTMRv3HUk7gld4VuzZd16lW774SfLkMBMOUYVVf9SKBMO+JATTTA==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"@eslint/js": "^10.0.0",
"angular-eslint": "^22.0.0",
"eslint": "^10.0.0",
"prettier": "^3.0.0",
"typescript": "^6.0.0",
"typescript-eslint": "^8.0.0"
},
"peerDependenciesMeta": {
"@eslint/js": {
"optional": true
},
"angular-eslint": {
"optional": true
},
"eslint": {
"optional": true
},
"prettier": {
"optional": true
},
"typescript-eslint": {
"optional": true
}
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+4 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cereale",
"version": "0.4.0",
"version": "0.4.1",
"description": "Strongly typed JSON mapping and validation for TypeScript classes \u2014 validated domain objects, not validated data. A zero-dependency replacement for class-validator + class-transformer, on TC39 standard decorators.",
"type": "module",
"main": "./dist/cjs/index.js",
@@ -42,6 +42,7 @@
"build:docs": "node scripts/build-docs.mjs",
"demo": "node --no-warnings=ExperimentalWarning --loader ts-node/esm src/example.ts",
"type-check": "tsc --noEmit",
"typecheck": "npm run type-check",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
@@ -49,6 +50,7 @@
"lint:fix": "eslint . --fix",
"verify": "npm run type-check && npm run lint && npm run test && npm run build && npm run check:types && npm run check:docs",
"prepublishOnly": "npm run verify",
"check": "node scripts/check-entry-points.mjs && npm run demo && npm run check:types && npm run check:docs && npm run check:docs-sync",
"check:docs": "node scripts/check-docs.mjs",
"check:types": "node scripts/check-types.mjs",
"check:docs-sync": "npm run build:docs && node scripts/check-docs-sync.mjs"
@@ -79,6 +81,7 @@
},
"homepage": "https://avalon-vanguard.github.io/cereale/",
"devDependencies": {
"@avalon-vanguard/config": "^1.0.0",
"@babel/standalone": "^8.0.4",
"@eslint/js": "^10.0.1",
"@swc/core": "^1.15.47",
+4
View File
@@ -0,0 +1,4 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["local>avalon-vanguard/renovate-config"]
}
+21
View File
@@ -49,6 +49,27 @@ await writeFile(
`window.CEREALE_META = ${JSON.stringify({ version: pkg.version, node: pkg.engines.node }, null, 2)};\n`
);
// 2b. The same version, stamped into the two spots in index.html that page.js later
// overwrites from meta.js. Those are the no-JavaScript fallbacks: correct in a browser,
// stale in a text reader or a scraper, and hand-bumped until now — they went stale on
// 0.4.0 and again on 0.4.1. Stamping them here means the docs-sync gate catches the
// drift instead of a reviewer. The regexes are asserted, so if the markup is renamed
// the build fails loudly rather than silently stamping nothing.
const indexPath = path.join(docs, 'index.html');
let index = await readFile(indexPath, 'utf8');
const stamps = [
[/(<span class="badge" id="version-badge">)v[\d.]+(<\/span>)/, `$1v${pkg.version}$2`],
[/(<span class="js-version">)[\d.]+(<\/span>)/g, `$1${pkg.version}$2`],
];
for (const [re, replacement] of stamps) {
if (!re.test(index)) {
console.error(`build-docs: nothing in docs/index.html matched ${re} — the version fallback markup moved.`);
process.exit(1);
}
index = index.replace(re, replacement);
}
await writeFile(indexPath, index);
// 3. The compiler errors the page quotes, produced by actually running the compiler. If a
// snippet the page calls a compile error ever compiles, this fails the build.
const { byCase, problems } = await collectDiagnostics(root);
+18
View File
@@ -0,0 +1,18 @@
/**
* Fails if a published entry point does not load from dist/: `.` and `./vite`, each as ESM
* and as CommonJS, and the flat `./min` bundle. Run after `npm run build` (first step of
* `npm run check`). Moved here from inline `node -e` lines in .github/workflows/ci.yml so
* that the GitHub and Gitea workflows run the same check.
*/
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const assert = (ok, what) => {
if (!ok) throw new Error(`${what} broken`);
};
assert(typeof (await import('../dist/esm/index.js')).toInstance === 'function', 'ESM entry point');
assert(typeof require('../dist/cjs/index.js').toInstance === 'function', 'CJS entry point');
assert((await import('../dist/esm/vite.js')).standardDecorators().enforce === 'pre', 'ESM cereale/vite');
assert(require('../dist/cjs/vite.js').standardDecorators().enforce === 'pre', 'CJS cereale/vite');
assert(typeof (await import('../dist/cereale.min.js')).toInstanceSync === 'function', 'flat bundle');
+4 -10
View File
@@ -1,5 +1,9 @@
{
// Visit https://aka.ms/tsconfig to read more about this file
// Shared (@avalon-vanguard/config/tsconfig/library.json): sourceMap, declaration,
// declarationMap, noImplicitReturns, noImplicitOverride, noFallthroughCasesInSwitch,
// isolatedModules, skipLibCheck.
"extends": "@avalon-vanguard/config/tsconfig/library.json",
"compilerOptions": {
// File Layout
"rootDir": "src",
@@ -11,27 +15,17 @@
"lib": ["ESNext", "ESNext.Decorators"],
"types": ["node"],
// Other Outputs
"sourceMap": true,
"declaration": true,
"declarationMap": true,
// Stricter Typechecking Options
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
// Style Options
"noImplicitReturns": true,
"noImplicitOverride": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
// Recommended Options
"strict": true,
"strictPropertyInitialization": false,
"isolatedModules": true,
"skipLibCheck": true,
// NOTE: no `experimentalDecorators`. v2 uses TC39 standard decorators, which is what
// gives ClassFieldDecoratorContext<This, Value> and therefore compile-time checking of