create-koppajs 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -16,6 +16,42 @@ _No unreleased changes yet._
16
16
 
17
17
  ---
18
18
 
19
+ ## [1.2.2] — Node & Validation Baseline Alignment
20
+
21
+ **2026-03-27**
22
+
23
+ ### Changed
24
+
25
+ - raised the repository and bundled starter minimum Node.js version to `>=22`
26
+ and expanded CI coverage to Node 24
27
+ - aligned CI and release validation around `pnpm validate`, added a packed-CLI
28
+ smoke test, and switched release automation to the maintainer default from
29
+ `.nvmrc`
30
+ - refreshed bundled starter dependencies to the current `@koppajs/koppajs-core`,
31
+ `@koppajs/koppajs-vite-plugin`, and `@koppajs/koppajs-router` baselines
32
+ - removed the obsolete starter-local `.kpa` export wrapper now that the Vite
33
+ plugin emits valid ES modules itself
34
+
35
+ ---
36
+
37
+ ## [1.2.1] — Starter Source Of Truth Cleanup
38
+
39
+ **2026-03-26**
40
+
41
+ Patch release to make the bundled templates the only starter source of truth and
42
+ to refresh the generated starter dependency baseline.
43
+
44
+ ### Changed
45
+
46
+ - documented `template/` and `template-overlays/` as the only maintained source
47
+ of truth for generated starters
48
+ - removed active ecosystem references to the retired `koppajs-example` starter
49
+ repository
50
+ - updated generated starter dependencies to `@koppajs/koppajs-core@^3.0.3` and
51
+ `@koppajs/koppajs-vite-plugin@^1.0.1`
52
+
53
+ ---
54
+
19
55
  ## [1.2.0] — Starter Variants And Router Overlay
20
56
 
21
57
  **2026-03-26**
package/README.md CHANGED
@@ -1,9 +1,63 @@
1
- # create-koppajs
2
-
3
- `create-koppajs` is the official KoppaJS CLI scaffolder. It creates a new
4
- project by copying the versioned base starter in `template/`, optionally
5
- applying a supported starter overlay from `template-overlays/`, and patching a
6
- small, explicit set of identity files.
1
+ <a id="readme-top"></a>
2
+
3
+ <div align="center">
4
+ <img src="https://public-assets-1b57ca06-687a-4142-a525-0635f7649a5c.s3.eu-central-1.amazonaws.com/koppajs/koppajs-logo-text-900x226.png" width="500" alt="KoppaJS Logo">
5
+ </div>
6
+
7
+ <br>
8
+
9
+ <div align="center">
10
+ <a href="https://www.npmjs.com/package/create-koppajs"><img src="https://img.shields.io/npm/v/create-koppajs?style=flat-square" alt="npm version"></a>
11
+ <a href="https://github.com/koppajs/create-koppajs/actions"><img src="https://img.shields.io/github/actions/workflow/status/koppajs/create-koppajs/ci.yml?branch=main&style=flat-square" alt="CI Status"></a>
12
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License"></a>
13
+ </div>
14
+
15
+ <br>
16
+
17
+ <div align="center">
18
+ <h1 align="center">create-koppajs</h1>
19
+ <h3 align="center">Official project scaffolder for KoppaJS</h3>
20
+ <p align="center">
21
+ <i>Generate a ready-to-run KoppaJS starter with the current quality baseline in one command.</i>
22
+ </p>
23
+ </div>
24
+
25
+ <br>
26
+
27
+ <div align="center">
28
+ <p align="center">
29
+ <a href="https://github.com/koppajs/koppajs-documentation">Documentation</a>
30
+ &middot;
31
+ <a href="https://github.com/koppajs/koppajs-core">KoppaJS Core</a>
32
+ &middot;
33
+ <a href="https://github.com/koppajs/koppajs-vite-plugin">Vite Plugin</a>
34
+ &middot;
35
+ <a href="https://github.com/koppajs/koppajs-router">Router</a>
36
+ &middot;
37
+ <a href="https://github.com/koppajs/create-koppajs/issues">Issues</a>
38
+ </p>
39
+ </div>
40
+
41
+ <br>
42
+
43
+ <details>
44
+ <summary>Table of Contents</summary>
45
+ <ol>
46
+ <li><a href="#purpose">Purpose</a></li>
47
+ <li><a href="#repository-classification">Repository Classification</a></li>
48
+ <li><a href="#ownership-boundaries">Ownership Boundaries</a></li>
49
+ <li><a href="#public-contract">Public Contract</a></li>
50
+ <li><a href="#usage">Usage</a></li>
51
+ <li><a href="#requirements">Requirements</a></li>
52
+ <li><a href="#generated-starters">Generated Starters</a></li>
53
+ <li><a href="#ecosystem-fit">Ecosystem Fit</a></li>
54
+ <li><a href="#architecture-governance">Architecture & Governance</a></li>
55
+ <li><a href="#community-contribution">Community & Contribution</a></li>
56
+ <li><a href="#license">License</a></li>
57
+ </ol>
58
+ </details>
59
+
60
+ ---
7
61
 
8
62
  ## Purpose
9
63
 
@@ -17,6 +71,8 @@ This repository exists to do one job well:
17
71
  It is not a runtime package and it does not own application behavior after
18
72
  generation.
19
73
 
74
+ ---
75
+
20
76
  ## Repository Classification
21
77
 
22
78
  - Repo type: CLI scaffolding package with a bundled starter family
@@ -27,12 +83,17 @@ generation.
27
83
  - UI surface: none at the repository root; the generated starter owns the UI
28
84
  - Maturity level: stable, contract-governed, maintenance-first
29
85
 
86
+ ---
87
+
30
88
  ## Ownership Boundaries
31
89
 
32
90
  - `bin/create-koppajs.js` owns argument parsing, prompting, validation, starter
33
91
  selection, template copy, placeholder patching, and next-step output.
34
- - `template/` owns the default `minimal` starter baseline.
92
+ - `template/` owns the default `minimal` starter baseline and is the single
93
+ source of truth for that starter.
35
94
  - `template-overlays/` owns the files that differ for opt-in starter variants.
95
+ Together with `template/`, they define the only source of truth for
96
+ generated starter output.
36
97
  - `scripts/` and `.github/workflows/` own repository-quality and release
37
98
  verification.
38
99
  - Root governance files own the repository doctrine and must stay aligned with
@@ -42,6 +103,8 @@ The root package must not take on runtime concerns that belong in generated
42
103
  applications, and generated applications must not depend on unpublished root
43
104
  files after scaffold completion.
44
105
 
106
+ ---
107
+
45
108
  ## Public Contract
46
109
 
47
110
  The stable public contract of this repository is:
@@ -68,6 +131,8 @@ The governing specs for that contract are:
68
131
  - [docs/specs/cli-scaffolding.md](./docs/specs/cli-scaffolding.md)
69
132
  - [docs/specs/template-starter-contract.md](./docs/specs/template-starter-contract.md)
70
133
 
134
+ ---
135
+
71
136
  ## Usage
72
137
 
73
138
  Default starter:
@@ -104,11 +169,14 @@ pnpm install
104
169
  pnpm dev
105
170
  ```
106
171
 
172
+ ---
173
+
107
174
  ## Requirements
108
175
 
109
- - for `create-koppajs`: Node.js `>=20`
110
- - for generated starter projects: pnpm `>=10` and a starter-supported Node.js
111
- line, currently `20.19+`, `22.13+`, or `24+`
176
+ - for `create-koppajs`: Node.js `>=22`
177
+ - for generated starter projects: Node.js `>=22` and pnpm `>=10`
178
+
179
+ ---
112
180
 
113
181
  ## Generated Starters
114
182
 
@@ -127,7 +195,10 @@ Every starter also includes:
127
195
  - GitHub workflows for CI and tagged releases
128
196
 
129
197
  The root repository treats those starters as versioned product surface, not
130
- test data.
198
+ test data. `template/` plus the supported overlays are the only source of truth
199
+ for starter behavior.
200
+
201
+ ---
131
202
 
132
203
  ## Ecosystem Fit
133
204
 
@@ -143,9 +214,11 @@ application. It complements:
143
214
  The repository stays intentionally narrow so the CLI, starter contract, and
144
215
  governance baseline can evolve together without hidden behavior.
145
216
 
146
- ## Governance
217
+ ---
218
+
219
+ ## Architecture & Governance
147
220
 
148
- The root meta layer defines how this repository changes:
221
+ Project intent, contributor rules, and documentation contracts live in the local repo meta layer:
149
222
 
150
223
  - [AI_CONSTITUTION.md](./AI_CONSTITUTION.md)
151
224
  - [ARCHITECTURE.md](./ARCHITECTURE.md)
@@ -154,12 +227,36 @@ The root meta layer defines how this repository changes:
154
227
  - [TESTING_STRATEGY.md](./TESTING_STRATEGY.md)
155
228
  - [RELEASE.md](./RELEASE.md)
156
229
  - [ROADMAP.md](./ROADMAP.md)
157
- - [docs/meta/README.md](./docs/meta/README.md)
230
+ - [CHANGELOG.md](./CHANGELOG.md)
231
+ - [CONTRIBUTING.md](./CONTRIBUTING.md)
232
+ - [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)
233
+ - [docs/specs/README.md](./docs/specs/README.md)
234
+ - [docs/specs/repository-documentation-contract.md](./docs/specs/repository-documentation-contract.md)
158
235
  - [docs/architecture/README.md](./docs/architecture/README.md)
236
+ - [docs/meta/README.md](./docs/meta/README.md)
159
237
  - [docs/quality/README.md](./docs/quality/README.md)
160
238
 
161
- Tagged releases are documented in [CHANGELOG.md](./CHANGELOG.md). Contributor
162
- workflow rules live in [CONTRIBUTING.md](./CONTRIBUTING.md).
239
+ The file-shape contract for `README.md`, `CHANGELOG.md`, `CODE_OF_CONDUCT.md`, and `CONTRIBUTING.md` is defined in [docs/specs/repository-documentation-contract.md](./docs/specs/repository-documentation-contract.md).
240
+
241
+ Run the local document guard before committing:
242
+
243
+ ```bash
244
+ pnpm run check:docs
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Community & Contribution
250
+
251
+ Issues and pull requests are welcome:
252
+
253
+ https://github.com/koppajs/create-koppajs/issues
254
+
255
+ Contributor workflow details live in [CONTRIBUTING.md](./CONTRIBUTING.md).
256
+
257
+ Community expectations live in [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
258
+
259
+ ---
163
260
 
164
261
  ## License
165
262
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, copyFileSync, statSync } from "node:fs";
3
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, copyFileSync, statSync, realpathSync } from "node:fs";
4
4
  import { basename, join, dirname, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { createInterface } from "node:readline";
@@ -335,7 +335,15 @@ export async function runCli(
335
335
  }
336
336
 
337
337
  function isDirectExecution() {
338
- return Boolean(process.argv[1]) && resolve(process.argv[1]) === __filename;
338
+ if (!process.argv[1]) {
339
+ return false;
340
+ }
341
+
342
+ try {
343
+ return realpathSync(process.argv[1]) === realpathSync(__filename);
344
+ } catch {
345
+ return resolve(process.argv[1]) === __filename;
346
+ }
339
347
  }
340
348
 
341
349
  if (isDirectExecution()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-koppajs",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Scaffold a new KoppaJS project in seconds.",
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "packageManager": "pnpm@10.12.1",
19
19
  "engines": {
20
- "node": ">=20",
20
+ "node": ">=22",
21
21
  "pnpm": ">=10"
22
22
  },
23
23
  "scripts": {
@@ -29,12 +29,15 @@
29
29
  "test:watch": "node scripts/run-unit-tests.mjs --watch",
30
30
  "test:smoke": "node scripts/smoke-test.mjs",
31
31
  "test:template-build": "node scripts/template-build-test.mjs",
32
+ "test:package": "node scripts/test-package-smoke.mjs",
32
33
  "test": "npm run test:unit && npm run test:smoke",
33
34
  "pack:dry-run": "npm pack --dry-run",
34
- "check": "npm run check:meta && npm run lint && npm run format:check && npm run check:cli && npm test && npm run pack:dry-run",
35
- "release:check": "npm run check && npm run test:template-build",
35
+ "check": "pnpm run check:docs && npm run check:meta && npm run lint && npm run format:check && npm run check:cli && npm test && npm run pack:dry-run",
36
+ "validate": "pnpm run check && pnpm run test:template-build && pnpm run test:package",
37
+ "release:check": "pnpm run validate",
36
38
  "prepare": "husky",
37
- "clean": "node scripts/clean.mjs"
39
+ "clean": "node scripts/clean.mjs",
40
+ "check:docs": "node scripts/check-doc-contract.mjs"
38
41
  },
39
42
  "author": "Bastian Bensch",
40
43
  "license": "Apache-2.0",
@@ -10,14 +10,13 @@ This repository is a minimal KoppaJS application starter. It intentionally demon
10
10
  - `src/counter-component.kpa` is the example stateful leaf component. It owns its own `count` state and button event handlers.
11
11
  - `src/style.css` contains the global reset only.
12
12
  - `public/` contains static assets referenced by the HTML shell or components.
13
- - `vite.config.mjs` wires the KoppaJS Vite plugin into the build and applies a small repo-local compatibility transform so `.kpa` files are emitted as valid ES modules.
14
- - `vitest.config.mjs` reuses the Vite config so unit and integration tests exercise the same `.kpa` loading path as the application.
13
+ - `vite.config.mjs` wires the KoppaJS Vite plugin into the build without local compatibility layers.
14
+ - `vitest.config.mjs` reuses the Vite config so integration tests exercise the same `.kpa` loading path as the application.
15
15
  - `playwright.config.ts` runs a Chromium smoke test against `vite preview`, which keeps the minimal UI starter covered by one real browser path.
16
16
  - `CHANGELOG.md` records official tagged milestones for the repository.
17
17
  - `RELEASE.md` documents the maintainer release path across `develop`, `release/*`, and `main`.
18
18
  - `commitlint.config.mjs` defines the repository's commit message convention.
19
19
  - `.github/workflows/release.yml` reruns validation for `vX.Y.Z` tags, checks version alignment, and creates GitHub Releases.
20
- - `tests/unit/` covers isolated logic such as the `.kpa` module export normalization helper.
21
20
  - `tests/integration/` covers application bootstrap wiring without requiring a full browser run.
22
21
  - `tests/e2e/` covers the observable starter flow in a real browser.
23
22
  - `tsconfig.json` enforces strict TypeScript rules for source, tests, and TypeScript config files. `.kpa` compilation is still handled by the KoppaJS Vite plugin.
@@ -46,24 +45,23 @@ More detailed boundaries live in [docs/architecture/module-boundaries.md](./docs
46
45
 
47
46
  ## Module responsibilities
48
47
 
49
- | Module | Responsibility | Must not do |
50
- | ------------------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
51
- | `index.html` | Declare root tag and static assets | Hold business logic or feature wiring |
52
- | `CHANGELOG.md` | Record official tagged release notes | Become a scratchpad for speculative work or duplicate repository docs |
53
- | `RELEASE.md` | Define the maintainer release procedure | Drift away from actual branch, tag, or workflow behavior |
54
- | `commitlint.config.mjs` | Define commit message validation rules | Expand into unrelated repository lint policy |
55
- | `src/main.ts` | Bootstrap and component registration | Accumulate feature logic, state, or DOM manipulation |
56
- | `src/app-view.kpa` | Root layout and composition | Own unrelated business workflows or register components |
57
- | `src/counter-component.kpa` | Local interactive example state | Reach into global DOM or mutate app shell concerns |
58
- | `src/style.css` | Global reset/base rules | Contain feature-specific visuals that belong to components |
59
- | `public/` | Static assets | Store generated build output or source code |
60
- | `tests/unit/` | Isolated tests for helper or tooling logic | Production runtime side effects or browser-only expectations |
61
- | `tests/integration/` | Wiring tests across bootstrap boundaries | Full browser assertions already covered by Playwright |
62
- | `tests/e2e/` | Real browser smoke coverage of the starter UI | Deep implementation-detail assertions or brittle CSS-driven flows |
63
- | `vite.config.mjs` | Build and dev server integration, including the `.kpa` module export compatibility wrapper | Application runtime logic |
64
- | `vitest.config.mjs` | Unit and integration test runner configuration | Runtime feature code |
65
- | `playwright.config.ts` | Browser smoke-test orchestration against preview output | Application runtime logic |
66
- | `.github/workflows/release.yml` | Tagged release validation and GitHub Release creation | Publish to npm while the repository remains private |
48
+ | Module | Responsibility | Must not do |
49
+ | ------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
50
+ | `index.html` | Declare root tag and static assets | Hold business logic or feature wiring |
51
+ | `CHANGELOG.md` | Record official tagged release notes | Become a scratchpad for speculative work or duplicate repository docs |
52
+ | `RELEASE.md` | Define the maintainer release procedure | Drift away from actual branch, tag, or workflow behavior |
53
+ | `commitlint.config.mjs` | Define commit message validation rules | Expand into unrelated repository lint policy |
54
+ | `src/main.ts` | Bootstrap and component registration | Accumulate feature logic, state, or DOM manipulation |
55
+ | `src/app-view.kpa` | Root layout and composition | Own unrelated business workflows or register components |
56
+ | `src/counter-component.kpa` | Local interactive example state | Reach into global DOM or mutate app shell concerns |
57
+ | `src/style.css` | Global reset/base rules | Contain feature-specific visuals that belong to components |
58
+ | `public/` | Static assets | Store generated build output or source code |
59
+ | `tests/integration/` | Wiring tests across bootstrap boundaries | Full browser assertions already covered by Playwright |
60
+ | `tests/e2e/` | Real browser smoke coverage of the starter UI | Deep implementation-detail assertions or brittle CSS-driven flows |
61
+ | `vite.config.mjs` | Build and dev server integration through the upstream KoppaJS Vite plugin | Application runtime logic |
62
+ | `vitest.config.mjs` | Unit and integration test runner configuration | Runtime feature code |
63
+ | `playwright.config.ts` | Browser smoke-test orchestration against preview output | Application runtime logic |
64
+ | `.github/workflows/release.yml` | Tagged release validation and GitHub Release creation | Publish to npm while the repository remains private |
67
65
 
68
66
  ## Invariants
69
67
 
@@ -9,13 +9,14 @@ Only tagged versions represent official releases.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
- This section is intentionally empty.
13
-
14
- Changes will only appear here when they:
15
-
16
- - alter the project's observable behavior,
17
- - change contributor or maintainer workflow,
18
- - or modify documented repository guarantees.
12
+ ### Changed
13
+
14
+ - raised the minimum Node.js version to `>=22` and expanded CI coverage to
15
+ Node 24
16
+ - refreshed the starter dependency baseline to the current `@koppajs/koppajs-core`
17
+ and `@koppajs/koppajs-vite-plugin` releases
18
+ - removed the obsolete local `.kpa` export wrapper because the upstream Vite
19
+ plugin already emits valid ES modules
19
20
 
20
21
  ---
21
22
 
@@ -4,12 +4,9 @@
4
4
 
5
5
  Requirements:
6
6
 
7
- - Node.js 20.19+, 22.13+, or 24+
7
+ - Node.js >= 22
8
8
  - pnpm 10 or newer
9
9
 
10
- Node 23 is intentionally not part of the supported range because the current
11
- upstream frontend tooling excludes it.
12
-
13
10
  Install and run:
14
11
 
15
12
  ```bash
@@ -81,12 +81,9 @@ Use it as a starting point for new KoppaJS projects or as a reference for how co
81
81
 
82
82
  ## Requirements
83
83
 
84
- - Node.js 20.19+, 22.13+, or 24+
84
+ - Node.js >= 22
85
85
  - pnpm >= 10
86
86
 
87
- Node 23 is intentionally not treated as supported here because the current
88
- upstream frontend toolchain excludes it.
89
-
90
87
  ---
91
88
 
92
89
  ## Getting Started
@@ -66,12 +66,9 @@ Before cutting a release, ensure all of the following are true:
66
66
 
67
67
  Tooling expectations for local verification:
68
68
 
69
- - Node.js 20.19+, 22.13+, or 24+
69
+ - Node.js 22 or newer
70
70
  - pnpm 10 or newer
71
71
 
72
- Node 23 is intentionally not treated as supported here because the current
73
- upstream frontend toolchain excludes it.
74
-
75
72
  This repository also enforces `engine-strict=true` in `.npmrc`, so incompatible
76
73
  Node.js or pnpm versions should be treated as a release blocker.
77
74
 
@@ -26,7 +26,10 @@ This repository now has a small automated testing stack aligned with the actual
26
26
 
27
27
  ### Unit tests
28
28
 
29
- Use unit tests for isolated logic that can fail independently of the browser runtime. Today that includes the repo-local `.kpa` export normalization helper in `vite.config.mjs`.
29
+ Use unit tests for isolated logic that can fail independently of the browser runtime.
30
+
31
+ Today the starter does not ship dedicated extracted helper modules, so unit-only
32
+ coverage is optional until new isolated logic actually exists.
30
33
 
31
34
  Typical triggers:
32
35
 
@@ -12,6 +12,9 @@ on:
12
12
  jobs:
13
13
  validate:
14
14
  runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ node: [22, 24]
15
18
 
16
19
  steps:
17
20
  - name: Check out repository
@@ -25,7 +28,7 @@ jobs:
25
28
  - name: Set up Node.js
26
29
  uses: actions/setup-node@v4
27
30
  with:
28
- node-version: 20
31
+ node-version: ${{ matrix.node }}
29
32
  cache: pnpm
30
33
 
31
34
  - name: Install dependencies
@@ -26,7 +26,7 @@ jobs:
26
26
  - name: Set up Node.js
27
27
  uses: actions/setup-node@v4
28
28
  with:
29
- node-version: 20
29
+ node-version: 22
30
30
  cache: pnpm
31
31
 
32
32
  - name: Install dependencies
@@ -0,0 +1,32 @@
1
+ # ADR 0003: Rely on upstream KPA ES module output
2
+
3
+ ## Context
4
+
5
+ The starter depends on `@koppajs/koppajs-vite-plugin` to transform `.kpa`
6
+ files for both development and production builds.
7
+
8
+ Earlier starter revisions carried a repo-local compatibility wrapper in
9
+ `vite.config.mjs` because the plugin emitted raw object literals instead of ES
10
+ modules.
11
+
12
+ The current upstream plugin now emits `export default ...` modules directly, so
13
+ keeping the local wrapper would only duplicate behavior and create drift
14
+ between the starter and the official plugin contract.
15
+
16
+ ## Decision
17
+
18
+ Use the upstream KoppaJS Vite plugin output directly and keep `vite.config.mjs`
19
+ limited to plugin wiring.
20
+
21
+ ## Consequences
22
+
23
+ - The starter stays aligned with the official Vite plugin behavior instead of
24
+ carrying a stale local workaround.
25
+ - Build configuration stays smaller and easier to reason about.
26
+ - Future maintainers must update the starter and the plugin together if the
27
+ `.kpa` module contract changes again.
28
+
29
+ ## Alternatives considered
30
+
31
+ - Keeping a repo-local post-transform in `vite.config.mjs`
32
+ - Forking the plugin behavior inside the starter
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Context
4
4
 
5
- The repository already had a living meta layer and a real interactive UI, but its practical quality gates were still limited to `pnpm typecheck`, `pnpm build`, and manual smoke testing. That left the repo-local `.kpa` build workaround, bootstrap wiring, and browser-visible starter behavior exposed to easy regression.
5
+ The repository already had a living meta layer and a real interactive UI, but its practical quality gates were still limited to `pnpm typecheck`, `pnpm build`, and manual smoke testing. That left bootstrap wiring and browser-visible starter behavior exposed to easy regression.
6
6
 
7
7
  ## Decision
8
8
 
@@ -31,7 +31,7 @@ Use [`TEMPLATE.md`](./TEMPLATE.md). Every ADR must contain:
31
31
 
32
32
  - [`0001-keep-the-starter-minimal.md`](./0001-keep-the-starter-minimal.md)
33
33
  - [`0002-adopt-a-living-meta-layer.md`](./0002-adopt-a-living-meta-layer.md)
34
- - [`0003-normalize-kpa-plugin-output.md`](./0003-normalize-kpa-plugin-output.md)
34
+ - [`0003-rely-on-upstream-kpa-es-module-output.md`](./0003-rely-on-upstream-kpa-es-module-output.md)
35
35
  - [`0004-adopt-an-automated-quality-baseline.md`](./0004-adopt-an-automated-quality-baseline.md)
36
36
  - [`0005-adopt-a-tag-driven-release-baseline.md`](./0005-adopt-a-tag-driven-release-baseline.md)
37
37
  - [`0006-adopt-commit-message-conventions.md`](./0006-adopt-commit-message-conventions.md)
@@ -4,25 +4,24 @@
4
4
 
5
5
  This repository is intentionally shallow. Its boundaries are designed to keep the starter easy to understand.
6
6
 
7
- | Path | Responsibility | Allowed dependencies | Must not depend on |
8
- | ------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------- | ----------------------------------------------------------------- |
9
- | `index.html` | Document shell, root element, asset references | Static assets, `src/main.ts`, `src/style.css` | Feature logic, extra scripts, framework-specific behavior |
10
- | `CHANGELOG.md` | Tagged release history | Release notes, versioned milestones | Unreleased planning notes or unrelated contributor guidance |
11
- | `RELEASE.md` | Maintainer release procedure | `package.json`, `CHANGELOG.md`, GitHub workflows | Runtime code or undocumented branch conventions |
12
- | `commitlint.config.mjs` | Commit message rules | Conventional commit policy | Source-code linting or release branching rules |
13
- | `src/main.ts` | Application bootstrap and component registration | `@koppajs/koppajs-core`, local `.kpa` modules | UI business logic, ad hoc DOM manipulation, network code |
14
- | `src/app-view.kpa` | Root page layout and composition | Local markup, local CSS, child components | Global bootstrap concerns, unrelated feature orchestration |
15
- | `src/counter-component.kpa` | Example local state and interaction | Local markup, local methods, local CSS | Shared infrastructure, global state, direct root DOM coordination |
16
- | `src/style.css` | Global reset and truly global base rules | Standard CSS | Component-specific visual rules |
17
- | `public/` | Static assets served as-is | Static files only | Source code or generated artifacts |
18
- | `tests/unit/` | Isolated tests for helper and tooling logic | Vitest, local modules | Full browser expectations or long integration chains |
19
- | `tests/integration/` | Bootstrap and boundary-level integration tests | Vitest, local modules, selective mocks | Browser-only smoke assertions |
20
- | `tests/e2e/` | Real-browser smoke coverage | Playwright, preview server | Implementation-detail assertions |
21
- | `vite.config.mjs` | Build and dev server integration, including the `.kpa` module export compatibility wrapper | Vite and the KoppaJS Vite plugin | Application runtime logic |
22
- | `vitest.config.mjs` | Vitest orchestration merged with the Vite config | Vitest and Vite config | Application runtime logic |
23
- | `playwright.config.ts` | Playwright orchestration against preview output | Playwright and preview server script | Application runtime logic |
24
- | `.github/workflows/release.yml` | Tag-triggered validation and GitHub Release creation | GitHub Actions, `package.json`, validation scripts | npm publishing while `package.json` is `private` |
25
- | `tsconfig.json` | TypeScript compiler behavior for source, tests, and TS config files | TypeScript compiler options | Application runtime logic |
7
+ | Path | Responsibility | Allowed dependencies | Must not depend on |
8
+ | ------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------- |
9
+ | `index.html` | Document shell, root element, asset references | Static assets, `src/main.ts`, `src/style.css` | Feature logic, extra scripts, framework-specific behavior |
10
+ | `CHANGELOG.md` | Tagged release history | Release notes, versioned milestones | Unreleased planning notes or unrelated contributor guidance |
11
+ | `RELEASE.md` | Maintainer release procedure | `package.json`, `CHANGELOG.md`, GitHub workflows | Runtime code or undocumented branch conventions |
12
+ | `commitlint.config.mjs` | Commit message rules | Conventional commit policy | Source-code linting or release branching rules |
13
+ | `src/main.ts` | Application bootstrap and component registration | `@koppajs/koppajs-core`, local `.kpa` modules | UI business logic, ad hoc DOM manipulation, network code |
14
+ | `src/app-view.kpa` | Root page layout and composition | Local markup, local CSS, child components | Global bootstrap concerns, unrelated feature orchestration |
15
+ | `src/counter-component.kpa` | Example local state and interaction | Local markup, local methods, local CSS | Shared infrastructure, global state, direct root DOM coordination |
16
+ | `src/style.css` | Global reset and truly global base rules | Standard CSS | Component-specific visual rules |
17
+ | `public/` | Static assets served as-is | Static files only | Source code or generated artifacts |
18
+ | `tests/integration/` | Bootstrap and boundary-level integration tests | Vitest, local modules, selective mocks | Browser-only smoke assertions |
19
+ | `tests/e2e/` | Real-browser smoke coverage | Playwright, preview server | Implementation-detail assertions |
20
+ | `vite.config.mjs` | Build and dev server integration through the upstream KoppaJS Vite plugin | Vite and the KoppaJS Vite plugin | Application runtime logic |
21
+ | `vitest.config.mjs` | Vitest orchestration merged with the Vite config | Vitest and Vite config | Application runtime logic |
22
+ | `playwright.config.ts` | Playwright orchestration against preview output | Playwright and preview server script | Application runtime logic |
23
+ | `.github/workflows/release.yml` | Tag-triggered validation and GitHub Release creation | GitHub Actions, `package.json`, validation scripts | npm publishing while `package.json` is `private` |
24
+ | `tsconfig.json` | TypeScript compiler behavior for source, tests, and TS config files | TypeScript compiler options | Application runtime logic |
26
25
 
27
26
  ## Boundary rules
28
27
 
@@ -33,7 +33,7 @@ Keep the starter's tooling, tests, and contributor workflow consistent enough th
33
33
  - Consistent formatting on supported file types
34
34
  - Conventional commit history for maintainable review and release preparation
35
35
  - Type-safe source and TypeScript tooling files
36
- - Automated confidence for the `.kpa` export workaround, bootstrap wiring, and the starter UI smoke path
36
+ - Automated confidence for bootstrap wiring and the starter UI smoke path
37
37
  - A guarded GitHub release path that fails when the pushed tag does not match `package.json`
38
38
  - Fast feedback before commit and in CI
39
39
 
@@ -16,7 +16,7 @@
16
16
  ],
17
17
  "packageManager": "pnpm@10.12.1",
18
18
  "engines": {
19
- "node": "^20.19.0 || ^22.13.0 || >=24.0.0",
19
+ "node": ">=22",
20
20
  "pnpm": ">=10"
21
21
  },
22
22
  "scripts": {
@@ -42,13 +42,13 @@
42
42
  "prepare": "husky"
43
43
  },
44
44
  "dependencies": {
45
- "@koppajs/koppajs-core": "^3.0.2"
45
+ "@koppajs/koppajs-core": "^3.0.7"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@commitlint/cli": "^20.1.0",
49
49
  "@commitlint/config-conventional": "^20.0.0",
50
50
  "@eslint/js": "^10.0.1",
51
- "@koppajs/koppajs-vite-plugin": "^1.0.0",
51
+ "@koppajs/koppajs-vite-plugin": "^1.0.4",
52
52
  "@playwright/test": "^1.58.2",
53
53
  "@types/node": "^25.4.0",
54
54
  "@vitest/coverage-v8": "^4.0.18",
@@ -9,8 +9,8 @@ importers:
9
9
  .:
10
10
  dependencies:
11
11
  '@koppajs/koppajs-core':
12
- specifier: ^3.0.2
13
- version: 3.0.2
12
+ specifier: ^3.0.7
13
+ version: 3.0.7
14
14
  devDependencies:
15
15
  '@commitlint/cli':
16
16
  specifier: ^20.1.0
@@ -22,8 +22,8 @@ importers:
22
22
  specifier: ^10.0.1
23
23
  version: 10.0.1(eslint@10.0.3(jiti@2.6.1))
24
24
  '@koppajs/koppajs-vite-plugin':
25
- specifier: ^1.0.0
26
- version: 1.0.0(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
25
+ specifier: ^1.0.4
26
+ version: 1.0.4(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
27
27
  '@playwright/test':
28
28
  specifier: ^1.58.2
29
29
  version: 1.58.2
@@ -605,13 +605,13 @@ packages:
605
605
  '@jridgewell/trace-mapping@0.3.31':
606
606
  resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
607
607
 
608
- '@koppajs/koppajs-core@3.0.2':
609
- resolution: {integrity: sha512-wvgg6sbWZMSe6Qhqy4WwIdKpzfgdK5f7sTh5rZIJwmBUsvfzJ3mIjl/1xgfDcNWBw9ij9epoW41MzekCgTBbkw==}
610
- engines: {node: '>=20', pnpm: '>=10.24.0'}
608
+ '@koppajs/koppajs-core@3.0.7':
609
+ resolution: {integrity: sha512-ZVaeU93skwDJZU+lWQaIlbExLFXJRC4+lg1Stoi0QUNg3iHUNEm1k8ESfTeF+GIJordpYdRKr1uytAHsT+EXLQ==}
610
+ engines: {node: '>=22', pnpm: '>=10.24.0'}
611
611
 
612
- '@koppajs/koppajs-vite-plugin@1.0.0':
613
- resolution: {integrity: sha512-tO1yyYOcHKTXqpbVOoMhdBmk9qw0DG2RcBUknpxVmPmMEXWysLXRRRFrkz0A/dOv72F1FrMN5OpIMztEvH6Hcg==}
614
- engines: {node: '>=20', pnpm: '>=10.24.0'}
612
+ '@koppajs/koppajs-vite-plugin@1.0.4':
613
+ resolution: {integrity: sha512-lBME5lq80t6Pk1lNDJeI4lOAfvfHR4AVqwpMLHUH5rqP9nbGh6t4ud/0llH4MiLNZAZK2HzNykzqO3+Rb+7tsw==}
614
+ engines: {node: '>=22', pnpm: '>=10.24.0'}
615
615
  peerDependencies:
616
616
  typescript: '>=5.5 <6'
617
617
  vite: ^7.0.0
@@ -944,11 +944,6 @@ packages:
944
944
  peerDependencies:
945
945
  acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
946
946
 
947
- acorn@8.15.0:
948
- resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
949
- engines: {node: '>=0.4.0'}
950
- hasBin: true
951
-
952
947
  acorn@8.16.0:
953
948
  resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
954
949
  engines: {node: '>=0.4.0'}
@@ -2411,11 +2406,11 @@ snapshots:
2411
2406
  '@jridgewell/resolve-uri': 3.1.2
2412
2407
  '@jridgewell/sourcemap-codec': 1.5.5
2413
2408
 
2414
- '@koppajs/koppajs-core@3.0.2': {}
2409
+ '@koppajs/koppajs-core@3.0.7': {}
2415
2410
 
2416
- '@koppajs/koppajs-vite-plugin@1.0.0(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
2411
+ '@koppajs/koppajs-vite-plugin@1.0.4(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
2417
2412
  dependencies:
2418
- acorn: 8.15.0
2413
+ acorn: 8.16.0
2419
2414
  autoprefixer: 10.4.23(postcss@8.5.6)
2420
2415
  postcss: 8.5.6
2421
2416
  sass: 1.97.1
@@ -2726,8 +2721,6 @@ snapshots:
2726
2721
  dependencies:
2727
2722
  acorn: 8.16.0
2728
2723
 
2729
- acorn@8.15.0: {}
2730
-
2731
2724
  acorn@8.16.0: {}
2732
2725
 
2733
2726
  agent-base@7.1.4:
@@ -1,6 +1,4 @@
1
- import type { Plugin, UserConfig } from "vite";
2
-
3
- export declare function normalizeKpaModuleExport(): Plugin;
1
+ import type { UserConfig } from "vite";
4
2
 
5
3
  declare const config: UserConfig;
6
4
 
@@ -1,45 +1,10 @@
1
1
  import koppaPlugin from "@koppajs/koppajs-vite-plugin";
2
2
  import { defineConfig } from "vite";
3
3
 
4
- /**
5
- * Wrap raw `.kpa` object output in a valid ES module export.
6
- *
7
- * @returns {import("vite").Plugin}
8
- */
9
- export function normalizeKpaModuleExport() {
10
- return {
11
- name: "normalize-kpa-module-export",
12
- enforce: "post",
13
- /**
14
- * @param {string} code
15
- * @param {string} id
16
- */
17
- transform(code, id) {
18
- const cleanId = id.split("?")[0];
19
-
20
- if (!cleanId.endsWith(".kpa")) {
21
- return null;
22
- }
23
-
24
- const trimmed = code.trim();
25
-
26
- if (!trimmed.startsWith("{") || trimmed.startsWith("export default")) {
27
- return null;
28
- }
29
-
30
- return {
31
- code: `export default ${trimmed};`,
32
- map: null,
33
- };
34
- },
35
- };
36
- }
37
-
38
4
  export default defineConfig({
39
5
  plugins: [
40
6
  koppaPlugin({
41
7
  tsconfigFile: "./tsconfig.json",
42
8
  }),
43
- normalizeKpaModuleExport(),
44
9
  ],
45
10
  });
@@ -12,7 +12,13 @@ not every internal refactor.
12
12
 
13
13
  ## [Unreleased]
14
14
 
15
- _No unreleased changes yet._
15
+ ### Changed
16
+
17
+ - raised the minimum Node.js version to `>=22` and expanded CI coverage to
18
+ Node 24
19
+ - refreshed the router starter dependency baseline to the current
20
+ `@koppajs/koppajs-core`, `@koppajs/koppajs-vite-plugin`, and
21
+ `@koppajs/koppajs-router` releases
16
22
 
17
23
  ---
18
24
 
@@ -85,12 +85,9 @@ together.
85
85
 
86
86
  ## Requirements
87
87
 
88
- - Node.js 20.19+, 22.13+, or 24+
88
+ - Node.js >= 22
89
89
  - pnpm >= 10
90
90
 
91
- Node 23 is intentionally not treated as supported here because the current
92
- upstream frontend toolchain excludes it.
93
-
94
91
  ---
95
92
 
96
93
  ## Getting Started
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "packageManager": "pnpm@10.12.1",
19
19
  "engines": {
20
- "node": "^20.19.0 || ^22.13.0 || >=24.0.0",
20
+ "node": ">=22",
21
21
  "pnpm": ">=10"
22
22
  },
23
23
  "scripts": {
@@ -43,14 +43,14 @@
43
43
  "prepare": "husky"
44
44
  },
45
45
  "dependencies": {
46
- "@koppajs/koppajs-core": "^3.0.2",
47
- "@koppajs/koppajs-router": "^0.1.0"
46
+ "@koppajs/koppajs-core": "^3.0.7",
47
+ "@koppajs/koppajs-router": "^0.1.2"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@commitlint/cli": "^20.1.0",
51
51
  "@commitlint/config-conventional": "^20.0.0",
52
52
  "@eslint/js": "^10.0.1",
53
- "@koppajs/koppajs-vite-plugin": "^1.0.0",
53
+ "@koppajs/koppajs-vite-plugin": "^1.0.4",
54
54
  "@playwright/test": "^1.58.2",
55
55
  "@types/node": "^25.4.0",
56
56
  "@vitest/coverage-v8": "^4.0.18",
@@ -9,11 +9,11 @@ importers:
9
9
  .:
10
10
  dependencies:
11
11
  '@koppajs/koppajs-core':
12
- specifier: ^3.0.2
13
- version: 3.0.2
12
+ specifier: ^3.0.7
13
+ version: 3.0.7
14
14
  '@koppajs/koppajs-router':
15
- specifier: ^0.1.0
16
- version: 0.1.0
15
+ specifier: ^0.1.2
16
+ version: 0.1.2
17
17
  devDependencies:
18
18
  '@commitlint/cli':
19
19
  specifier: ^20.1.0
@@ -25,8 +25,8 @@ importers:
25
25
  specifier: ^10.0.1
26
26
  version: 10.0.1(eslint@10.0.3(jiti@2.6.1))
27
27
  '@koppajs/koppajs-vite-plugin':
28
- specifier: ^1.0.0
29
- version: 1.0.0(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
28
+ specifier: ^1.0.4
29
+ version: 1.0.4(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
30
30
  '@playwright/test':
31
31
  specifier: ^1.58.2
32
32
  version: 1.58.2
@@ -608,17 +608,17 @@ packages:
608
608
  '@jridgewell/trace-mapping@0.3.31':
609
609
  resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
610
610
 
611
- '@koppajs/koppajs-core@3.0.2':
612
- resolution: {integrity: sha512-wvgg6sbWZMSe6Qhqy4WwIdKpzfgdK5f7sTh5rZIJwmBUsvfzJ3mIjl/1xgfDcNWBw9ij9epoW41MzekCgTBbkw==}
613
- engines: {node: '>=20', pnpm: '>=10.24.0'}
611
+ '@koppajs/koppajs-core@3.0.7':
612
+ resolution: {integrity: sha512-ZVaeU93skwDJZU+lWQaIlbExLFXJRC4+lg1Stoi0QUNg3iHUNEm1k8ESfTeF+GIJordpYdRKr1uytAHsT+EXLQ==}
613
+ engines: {node: '>=22', pnpm: '>=10.24.0'}
614
614
 
615
- '@koppajs/koppajs-router@0.1.0':
616
- resolution: {integrity: sha512-XJclUeB2Nwc/tDviuyFDSupFeOdI0NrkBKAoxwGdXE3vI6TN7AIoV6bfuiFnE8u4vLtVKhJ2Ds0IId7wlpF73Q==}
617
- engines: {node: '>=20', pnpm: '>=10.17.1'}
615
+ '@koppajs/koppajs-router@0.1.2':
616
+ resolution: {integrity: sha512-HJCvG4RDDlTG50UPiyodhtDRO/P2FDZ7c+U7FWyA/l5GtiYiJ02JjuY0ARjC6qCdiNwswNc6oHQGlmlYx3p7fQ==}
617
+ engines: {node: '>=22', pnpm: '>=10.17.1'}
618
618
 
619
- '@koppajs/koppajs-vite-plugin@1.0.0':
620
- resolution: {integrity: sha512-tO1yyYOcHKTXqpbVOoMhdBmk9qw0DG2RcBUknpxVmPmMEXWysLXRRRFrkz0A/dOv72F1FrMN5OpIMztEvH6Hcg==}
621
- engines: {node: '>=20', pnpm: '>=10.24.0'}
619
+ '@koppajs/koppajs-vite-plugin@1.0.4':
620
+ resolution: {integrity: sha512-lBME5lq80t6Pk1lNDJeI4lOAfvfHR4AVqwpMLHUH5rqP9nbGh6t4ud/0llH4MiLNZAZK2HzNykzqO3+Rb+7tsw==}
621
+ engines: {node: '>=22', pnpm: '>=10.24.0'}
622
622
  peerDependencies:
623
623
  typescript: '>=5.5 <6'
624
624
  vite: ^7.0.0
@@ -951,11 +951,6 @@ packages:
951
951
  peerDependencies:
952
952
  acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
953
953
 
954
- acorn@8.15.0:
955
- resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
956
- engines: {node: '>=0.4.0'}
957
- hasBin: true
958
-
959
954
  acorn@8.16.0:
960
955
  resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
961
956
  engines: {node: '>=0.4.0'}
@@ -2418,13 +2413,13 @@ snapshots:
2418
2413
  '@jridgewell/resolve-uri': 3.1.2
2419
2414
  '@jridgewell/sourcemap-codec': 1.5.5
2420
2415
 
2421
- '@koppajs/koppajs-core@3.0.2': {}
2416
+ '@koppajs/koppajs-core@3.0.7': {}
2422
2417
 
2423
- '@koppajs/koppajs-router@0.1.0': {}
2418
+ '@koppajs/koppajs-router@0.1.2': {}
2424
2419
 
2425
- '@koppajs/koppajs-vite-plugin@1.0.0(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
2420
+ '@koppajs/koppajs-vite-plugin@1.0.4(typescript@5.9.3)(vite@7.2.6(@types/node@25.4.0)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
2426
2421
  dependencies:
2427
- acorn: 8.15.0
2422
+ acorn: 8.16.0
2428
2423
  autoprefixer: 10.4.23(postcss@8.5.6)
2429
2424
  postcss: 8.5.6
2430
2425
  sass: 1.97.1
@@ -2735,8 +2730,6 @@ snapshots:
2735
2730
  dependencies:
2736
2731
  acorn: 8.16.0
2737
2732
 
2738
- acorn@8.15.0: {}
2739
-
2740
2733
  acorn@8.16.0: {}
2741
2734
 
2742
2735
  agent-base@7.1.4:
@@ -1,24 +0,0 @@
1
- # ADR 0003: Normalize KPA plugin output
2
-
3
- ## Context
4
-
5
- The installed `@koppajs/koppajs-vite-plugin` currently transforms `.kpa` files into raw object literals during Vite loading. Rollup expects valid ES module syntax, so production builds fail unless the transformed output is wrapped in an export.
6
-
7
- ## Decision
8
-
9
- Keep using the upstream KoppaJS Vite plugin, but add a small repo-local post-transform in `vite.config.mjs` that converts raw `.kpa` object literals into `export default ...` modules.
10
-
11
- This workaround remains in place until the upstream plugin emits valid module syntax on its own.
12
-
13
- ## Consequences
14
-
15
- - The repository builds successfully without changing application source files.
16
- - The workaround is isolated to build configuration.
17
- - Future maintainers must remove or revise the wrapper if the upstream plugin behavior changes.
18
- - Architecture documentation must reflect that the build stack includes this compatibility layer.
19
-
20
- ## Alternatives considered
21
-
22
- - Patching `node_modules` directly
23
- - Rewriting application imports around the plugin defect
24
- - Leaving the repository in a state where `pnpm build` fails
@@ -1,46 +0,0 @@
1
- import type { Plugin } from "vite";
2
- import { describe, expect, it } from "vitest";
3
-
4
- import { normalizeKpaModuleExport } from "../../vite.config.mjs";
5
-
6
- async function transformWith(plugin: Plugin, code: string, id: string) {
7
- const transform = plugin.transform;
8
-
9
- if (!transform) {
10
- return null;
11
- }
12
-
13
- if (typeof transform === "function") {
14
- return transform.call({} as never, code, id);
15
- }
16
-
17
- return transform.handler.call({} as never, code, id);
18
- }
19
-
20
- describe("normalizeKpaModuleExport", () => {
21
- it("wraps raw KPA output in an ES module export", async () => {
22
- const plugin = normalizeKpaModuleExport();
23
-
24
- await expect(
25
- transformWith(plugin, '{ template: "<div></div>" }', "/src/app-view.kpa"),
26
- ).resolves.toEqual({
27
- code: 'export default { template: "<div></div>" };',
28
- map: null,
29
- });
30
- });
31
-
32
- it("ignores non-KPA files and already exported modules", async () => {
33
- const plugin = normalizeKpaModuleExport();
34
-
35
- await expect(
36
- transformWith(plugin, "const count = 0;", "/src/main.ts"),
37
- ).resolves.toBeNull();
38
- await expect(
39
- transformWith(
40
- plugin,
41
- "export default { template: '<div></div>' };",
42
- "/src/app-view.kpa",
43
- ),
44
- ).resolves.toBeNull();
45
- });
46
- });