Skip to content

fs-Packages — The Armory

Shared frontend service packages monorepo under the @script-development npm scope. Published to the public npm registry via OIDC Trusted Publishing.

Tech Stack

  • Language: TypeScript 5.9+ (strict mode, verbatimModuleSyntax)
  • Build: tsdown (Rolldown/oxc) — dual ESM + CJS output with type declarations
  • Test: vitest 4 (100% coverage) + Stryker (90% mutation threshold)
  • Lint / Format: oxlint + oxfmt
  • Package lint: publint + attw
  • Publish: OIDC Trusted Publishing (no stored tokens)
  • CI: 8-gate pipeline — audit → format → lint → build → typecheck → pkg-lint → coverage → mutation

Architecture Overview

The Armory forges standardized service packages consumed across the Kendo, Brick Inventory, Entreezuil, UBLGenie, and The Laboratory territories. Each package follows a strict set of conventions:

  • Factory pattern. Every package exports a createXxxService() factory returning a plain service object. No classes, no singletons.
  • Single entry point. Each package has src/index.ts as the sole barrel export. Named exports only; no defaults.
  • Peer dependencies. Vue-dependent packages declare vue as a peer. Inter-package dependencies are peers too — consumers resolve the graph.
  • Loose coupling via structural typing. fs-theme's ThemeStorageContract is the exemplar — it duck-types its storage dependency rather than importing fs-storage.
  • Identical build config. All packages share the same tsdown.config.ts structure. Drift is an architectural regression.

Packages

PackageVuePurpose
fs-httpNoHTTP service factory with middleware architecture
fs-storageNolocalStorage service factory with prefix namespacing
fs-helpersNoTree-shakeable utilities (deep copy, type guards, case conversion)
fs-themeYesReactive dark/light mode with storage persistence
fs-loadingYesLoading state service with HTTP middleware
fs-adapter-storeYesReactive adapter-store pattern with CRUD resource adapters
fs-toastYesComponent-agnostic toast queue (FIFO)
fs-dialogYesComponent-agnostic dialog stack (LIFO) with error middleware
fs-translationYesType-safe reactive i18n with dot-notation keys
fs-routerYesType-safe router service factory with CRUD navigation and middleware pipeline

Key Decisions

Most War Room ADRs target Laravel backends and do not apply to a library territory. The ones that do:

DecisionStatusImpact
Adapter-Store PatternAcceptedPublished here as fs-adapter-store; fs-packages is the canonical home
ADR GovernanceAcceptedGovernance applies; projections live in this territory's CLAUDE.md
Page Integration TestsAcceptedKendo, BIO, Entreezuil mock only @script-development/fs-http — fs-packages is the mock target

Publishing

  • Public npm registry under @script-development/*.
  • Trusted Publishing via GitHub OIDC — no stored npm tokens.
  • Versioning: manual package.json bumps (not changesets).
  • Branch protection on main: required PR + 1 approval, dismiss stale reviews, enforce on admins.
  • Publish workflow separates build (contents: read) from publish (id-token: write).

Documentation

Ally-facing docs at packages.script.nl (VitePress + Cloudflare Pages). Every package has substantive coverage (What It Does, Basic Usage, API Reference). Progressive disclosure: Getting Started (quickstart) → Architecture (philosophy) → Package refs (API).

Architecture documentation for contributors and collaborators.