All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
1.0.0 - 2026-07-27
Initial stable release of @artisanpack-ui/hooks-js. Public API is now stable and follows semantic versioning going forward.
Added
- Documentation surface: full
README.mdwith install, quickstart, API reference, React adapter section, Module Federation section, deprecation section, and examples for both plain JS and React. Hook naming convention documented verbatim from theartisanpack-ui/hooksPHP README. Migration guide from@wordpress/hookscovering namespace removal, priority range, alias handling, React reactivity, and globals. Cross-link section pointing to the PHP twin. - Long-form
/docstree with YAML frontmatter and GitLab-wiki-style cross-links:home.md,getting-started.md,actions.md,filters.md,priorities-and-execution-order.md,hook-naming-and-deprecations.md,react.md(+react/subtree coveringuseFilter,useAction,useHookedChildren,<HookSlot>, and SSR),module-federation.md,devtools-debug.md,migration-from-wordpress-hooks.md,testing.md,faq.md,security.md,contributing.md,changelog.md. CONTRIBUTING.md— dev setup, script matrix, code style, testing conventions, docs conventions, PR conventions, release process.- Automated release workflow (
.github/workflows/release.yml) — triggered onv*.*.*tags, lints/type-checks/tests/builds, verifies that the tag version matchespackage.json, then runsnpm publish --provenance --access publicand creates a GitHub Release whose body is extracted from the matchingCHANGELOG.mdsection. Requires anNPM_TOKENrepo secret with publish rights on the@artisanpack-uiscope; provenance uses OIDC viaid-token: write. - Cross-module state singleton keyed by
Symbol.for('@artisanpack-ui/hooks-js/singleton')onglobalThis. Duplicate copies of the package (Module Federation withoutshared: { singleton: true }) share one registry so callbacks registered under one copy fire when dispatched from another. globalThis.ApHookspublic-API escape hatch installed on first import of the entry module. Plugins loaded outside the bundler graph can callwindow.ApHooks.addAction(...)/.applyFilters(...)without importing the package; calls share state with the imported API.- DevTools debug flag
window.__AP_HOOKS_DEBUG__ = true— logs eachdoAction/applyFiltersdispatch toconsole.debugwith the hook name, a compact argument preview, and the current subscriber count. Read per-dispatch so it can be toggled from DevTools without reloading. - README section documenting
shared: { singleton: true, strictVersion: false }for@originjs/vite-plugin-federation, webpackModuleFederationPlugin, and Rspack, plus a pluginbootModulerecipe for pre-mount hook registration. - Vitest v8 coverage config with per-file thresholds (95%+ core, 90%+ React
adapter) wired into CI via
npm run test:coverage. - Expanded test suite:
removeAll{Actions,Filters}with a specific priority edge cases, add-during-dispatch deferral semantics,applyFiltersreturning seed value when no subscribers, cross-alias dedup for identical bound methods, React adapter sibling-unmount isolation, StrictMode no-double-registration. - Initial repository scaffold: TypeScript, tsup, Vitest (jsdom), ESLint, Prettier,
GitHub Actions CI matrix (Node 20 / 22), and dual entry points (
.+./react). deprecateHook(oldName, newName)with chain collapse, cycle detection, and cross-bucket dedup on dispatch.addAction/addFilteron an alias silently attach to the canonical bucket;doAction/applyFiltersfire callbacks registered under either name exactly once. Deprecation notices log once per alias per session at the level configured viawindow.__AP_HOOKS_DEPRECATION_LEVEL__(off/debug/info/warn/error, defaults toinfo). Helpers:hasAliases(),aliasesFor(canonical),resetDeprecationLogState().- React adapter (
@artisanpack-ui/hooks-js/react):useFilter,useAction,useHookedChildren, and<HookSlot>. Backed byuseSyncExternalStoreon a per-hook version counter that bumps on every registry mutation, including changes on any reverse-alias bucket.useActiondeep-compares args to avoid re-firing on freshly-allocated but semantically-equal tuples. SSR-safe: server render never subscribes, and callbacks registered inuseEffectattach on hydrate.

