@dudousxd/nestjs-inertia-codegen 1.0.0

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 ADDED
@@ -0,0 +1,82 @@
1
+ # Changelog — @dudousxd/nestjs-inertia-codegen
2
+
3
+ ## 1.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`c5878e3`](https://github.com/DavideCarvalho/nestjs-inertia/commit/c5878e3f8827d9e89710df0154ea76996b6db62a) - First public release — Inertia.js v3 adapter for NestJS.
8
+
9
+ - Core: InertiaModule.forRoot/forRootAsync/forFeature, @Inertia decorator, Inertia.optional/defer/merge/always markers, CSRF with tokenContext, SSR support, Express + Fastify adapters
10
+ - Vite: setupInertiaVite + nestInertia plugin, @inertia/@vite/@inertiaHead shell directives
11
+ - Codegen: nestjs-inertia init (full scaffold + auto-patch), auto-watch in dev, static AST discovery, class-validator DTO support, Route/Path type helpers, @As hierarchical naming
12
+ - Client: defineContract + @ApplyContract, typed Link for React/Vue/Svelte with context providers, createFetcher, SSR hydration, rich error messages
13
+ - Testing: expectInertia matchers, assertInertia, InertiaTestingModule, fakes
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [[`c5878e3`](https://github.com/DavideCarvalho/nestjs-inertia/commit/c5878e3f8827d9e89710df0154ea76996b6db62a)]:
18
+ - @dudousxd/nestjs-inertia@1.0.0
19
+
20
+ ## [Unreleased]
21
+
22
+ ### Removed
23
+
24
+ - **Heavy probe path deleted** — `discoverRoutes` (fork + tsx + real Nest bootstrap) and the associated `probe.ts` child-process script have been removed. Static AST discovery via ts-morph is now the only route-discovery strategy.
25
+ - `useStaticDiscovery` config field removed from `ContractsConfig` / `ResolvedContractsConfig` — there is no longer an alternative.
26
+ - `tsconfig.probe.json` removed from the package.
27
+ - `NESTJS_INERTIA_CODEGEN_PROBE` environment-variable guard removed from `@dudousxd/nestjs-inertia` core module (the probe child process no longer exists).
28
+
29
+ ## 0.9.0-alpha.0 — 2026-05-22
30
+
31
+ ### Changed
32
+
33
+ - Version bump to `0.9.0-alpha.0` (Inertia v3 monorepo coordination; no source changes)
34
+
35
+ ## 0.8.0-alpha.0 — 2026-05-22
36
+
37
+ ### Added
38
+
39
+ - **`RouteParamsMap` emission** — codegen now emits a `RouteParamsMap` mapped type alongside `routes.ts`; `init` augments `InertiaRegistry` with the `routes` property automatically
40
+ - **ts-morph static AST contract discovery** — contract metadata is now extracted via ts-morph's static AST traversal instead of a dynamic child-process bootstrap probe; approximately 20× faster cold start and no side effects from running the NestJS app
41
+ - **Watch covers contracts** — `--watch` mode now monitors controller/contract source files and re-emits `api.ts` on change
42
+ - **`init` augmentation update** — `nestjs-inertia init` now scaffolds `InertiaRegistry` augmentation that includes `routes: RouteParamsMap` for typed `Link` and `route()` usage
43
+
44
+ ### Changed
45
+
46
+ - Version bump to `0.8.0-alpha.0`
47
+
48
+ ## 0.7.0-alpha.0 — 2026-05-22
49
+
50
+ ### Changed
51
+
52
+ - Bundled with example app, CI workflows, Changesets, MIT LICENSE, and slim docs.
53
+
54
+ ## [0.6.0-alpha.0] - 2026-05-22
55
+
56
+ ### Added
57
+
58
+ - **Contract discovery** — `discoverContracts(opts)` reads `CONTRACT_METADATA` via the Nest bootstrap probe to collect all `@ApplyContract`-decorated handler contracts; returns `ContractDescriptor[]` (method, path, name, query/body/response schema shapes)
59
+ - **`api.ts` emission** — `emitApi(contracts, outDir)` writes `.nestjs-inertia/api.ts`: a `createApi(opts?)` factory returning a typed route tree built on `@dudousxd/nestjs-inertia-client`'s `createFetcher`; no file is emitted when no contracts are found
60
+ - `generate(config)` orchestrates contract discovery + `emitApi` alongside existing page/route/index emitters
61
+
62
+ ### Changed
63
+
64
+ - Version bump to `0.6.0-alpha.0`
65
+
66
+ ## [0.5.0-alpha.0] - 2026-05-22
67
+
68
+ ### Added
69
+
70
+ - Initial release of `@dudousxd/nestjs-inertia-codegen`
71
+ - **Config layer** — `defineConfig` helper + `loadConfig(cwd)` with tsx ESM loader; `ConfigError` for missing file / invalid export / validation failure
72
+ - **Page discovery** — `discoverPages(opts)` via fast-glob; extracts `ComponentProps` type body by brace-counting; supports `relative-no-ext`, `kebab`, and custom name strategies
73
+ - **Route discovery** — `discoverRoutes(opts)` via child-process Nest bootstrap (tsx probe); returns `RouteDescriptor[]` with method, path, params
74
+ - **Emitters**
75
+ - `emitPages(pages, outDir)` — writes `pages.d.ts` with `InertiaPages` interface (page name → props type, `unknown` for pages without props)
76
+ - `emitRoutes(routes, outDir)` — writes `routes.ts` with runtime `route(name, params?)` interpolator, `RouteName` union, `RouteParams<K>` template-literal mapped type
77
+ - `emitCache(pages, outDir)` — writes `components.json` cache manifest (name, relativePath, mtime)
78
+ - `emitIndex(outDir)` — writes `index.d.ts` barrel re-exporting pages, shared-props, routes
79
+ - **`generate(config)`** — orchestrates discovery + all emitters in one call
80
+ - **Watch mode** — `watch(config, onChange?)` via chokidar (150 ms debounce); returns `{ close() }`. Lock-file guard (`<outDir>/.watcher.lock`) prevents duplicate watchers in the same directory
81
+ - **CLI** — `nestjs-inertia init` (scaffold config + `.gitignore` patch + `nestjs-inertia.d.ts` augmentation stub, idempotent) and `nestjs-inertia codegen [--watch]` powered by `cac`
82
+ - **Programmatic API** — `loadConfig`, `generate`, `watch`, `defineConfig`, `ConfigError`, `CodegenError` all exported from package root
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Davide Carvalho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # @dudousxd/nestjs-inertia-codegen
2
+
3
+ > CLI + programmatic API that scans a NestJS + Inertia.js app and emits typed artifacts under `.nestjs-inertia/`.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@dudousxd/nestjs-inertia-codegen)](https://www.npmjs.com/package/@dudousxd/nestjs-inertia-codegen)
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add -D @dudousxd/nestjs-inertia-codegen
11
+ pnpm add -D tsx # required for loading nestjs-inertia.config.ts
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ # 1. Scaffold config file + .gitignore patch + nestjs-inertia.d.ts augmentation stub
18
+ pnpm nestjs-inertia init
19
+
20
+ # 2. Generate typed artifacts (one-shot)
21
+ pnpm nestjs-inertia codegen
22
+
23
+ # 3. Watch mode — regenerates on every page file change (150ms debounce)
24
+ pnpm nestjs-inertia codegen --watch
25
+ ```
26
+
27
+ After running `codegen`, the `.nestjs-inertia/` directory will contain:
28
+
29
+ ```
30
+ .nestjs-inertia/
31
+ pages.d.ts # InertiaPages interface (page name → props type)
32
+ routes.ts # route() helper + RouteName union + RouteParams<K>
33
+ api.ts # typed client API (emitted when @ApplyContract handlers are found)
34
+ shared-props.d.ts # (placeholder, future)
35
+ index.d.ts # barrel re-export
36
+ components.json # cache manifest (name, relativePath, mtime)
37
+ ```
38
+
39
+ ### Contract discovery and `api.ts` emission (v0.6.0+)
40
+
41
+ When controllers use `@ApplyContract` from `@dudousxd/nestjs-inertia-client`, codegen discovers the attached contract metadata during the route-discovery probe and emits `.nestjs-inertia/api.ts` — a fully-typed client module built on `createFetcher`:
42
+
43
+ ```ts
44
+ // .nestjs-inertia/api.ts (generated)
45
+ import { createFetcher } from '@dudousxd/nestjs-inertia-client';
46
+ import type { FetcherOptions } from '@dudousxd/nestjs-inertia-client';
47
+
48
+ export function createApi(opts?: FetcherOptions) {
49
+ const fetcher = createFetcher(opts);
50
+ return {
51
+ users: {
52
+ list: (query?: { page?: number }) => fetcher.get('/users', { query }),
53
+ create: (body: { name: string; email: string }) => fetcher.post('/users', { body }),
54
+ },
55
+ };
56
+ }
57
+ ```
58
+
59
+ No `api.ts` is emitted when no `@ApplyContract` handlers are found.
60
+
61
+ Add `.nestjs-inertia/` to `.gitignore` (the `init` command does this automatically).
62
+
63
+ ## Config Reference
64
+
65
+ Create `nestjs-inertia.config.ts` at the repo root (or let `init` scaffold it):
66
+
67
+ ```ts
68
+ import { defineConfig } from '@dudousxd/nestjs-inertia-codegen';
69
+
70
+ export default defineConfig({
71
+ pages: {
72
+ // Glob pattern relative to cwd
73
+ glob: 'inertia/pages/**/*.{tsx,vue,svelte}',
74
+ // Named export that holds the per-page props type (default: 'ComponentProps')
75
+ propsExport: 'ComponentProps',
76
+ // How to derive the Inertia page name from the file path (default: 'relative-no-ext')
77
+ // Options: 'relative-no-ext' | 'kebab' | ((relativePath: string) => string)
78
+ componentNameStrategy: 'relative-no-ext',
79
+ },
80
+ contracts: {
81
+ // Glob for controller files watched in --watch mode (default: 'src/**/*.controller.ts')
82
+ glob: 'src/**/*.controller.ts',
83
+ // Debounce delay in ms before re-running route discovery (default: 500)
84
+ debounceMs: 500,
85
+ },
86
+ codegen: {
87
+ // Output directory for generated artifacts (default: '.nestjs-inertia')
88
+ outDir: '.nestjs-inertia',
89
+ },
90
+ app: {
91
+ // Entry module for route discovery (optional — routes.ts is skipped if absent)
92
+ moduleEntry: 'src/app.module.ts',
93
+ tsconfig: 'tsconfig.json',
94
+ },
95
+ });
96
+ ```
97
+
98
+ Full spec: [`/docs/superpowers/specs/2026-05-22-nestjs-inertia-plan-c-design.md`](../../docs/superpowers/specs/2026-05-22-nestjs-inertia-plan-c-design.md)
99
+
100
+ ## CLI Reference
101
+
102
+ ```
103
+ nestjs-inertia <command> [options]
104
+
105
+ Commands:
106
+ init Scaffold nestjs-inertia.config.ts, nestjs-inertia.d.ts, and
107
+ patch .gitignore. Safe to re-run (idempotent).
108
+ codegen One-shot generate: discover pages (+ routes if app.moduleEntry
109
+ is set) and write typed artifacts to codegen.outDir.
110
+ codegen --watch Watch mode: runs an initial codegen pass, then watches
111
+ pages.glob for changes and regenerates on each event
112
+ (150 ms debounce). Acquires a lock file to prevent duplicate
113
+ watchers in the same outDir.
114
+
115
+ Options:
116
+ --help, -h Show help
117
+ --version, -v Show version
118
+ ```
119
+
120
+ > **Watch mode — two watchers:** `--watch` runs two independent file watchers:
121
+ > 1. **Pages watcher** (`pages.glob`, 150 ms debounce) — regenerates `pages.d.ts` on any page file change.
122
+ > 2. **Contracts watcher** (`contracts.glob`, default `src/**/*.controller.ts`, 500 ms debounce) — re-runs static AST route discovery via ts-morph (~100–500 ms) and regenerates `routes.ts` and `api.ts` whenever a controller file changes.
123
+ >
124
+ > Configure the contracts glob and debounce via the `contracts` key in `nestjs-inertia.config.ts`.
125
+
126
+ ## Programmatic API
127
+
128
+ ```ts
129
+ import { defineConfig, loadConfig, generate, watch } from '@dudousxd/nestjs-inertia-codegen';
130
+ import type { UserConfig, ResolvedConfig } from '@dudousxd/nestjs-inertia-codegen';
131
+
132
+ // --- Config ---
133
+
134
+ // In nestjs-inertia.config.ts — provides type-checking + IDE completion
135
+ export default defineConfig({
136
+ pages: { glob: 'inertia/pages/**/*.tsx' },
137
+ });
138
+
139
+ // Load config from disk (resolves defaults, makes paths absolute)
140
+ const config: ResolvedConfig = await loadConfig(process.cwd());
141
+
142
+ // --- One-shot generation ---
143
+ await generate(config);
144
+
145
+ // --- Watch mode ---
146
+ const watcher = await watch(config, () => {
147
+ console.log('Pages regenerated');
148
+ });
149
+
150
+ // Shut down cleanly (releases lock file)
151
+ await watcher.close();
152
+ ```
153
+
154
+ ### Error classes
155
+
156
+ ```ts
157
+ import { ConfigError, CodegenError } from '@dudousxd/nestjs-inertia-codegen';
158
+ ```
159
+
160
+ - `ConfigError` — config file missing, invalid default export, or validation failure.
161
+ - `CodegenError` — emit or discovery failure.
162
+
163
+ ## Module augmentation
164
+
165
+ After running `init`, a `nestjs-inertia.d.ts` file is created at the repo root:
166
+
167
+ ```ts
168
+ import '@dudousxd/nestjs-inertia';
169
+ import type { InertiaPages } from './.nestjs-inertia/index.js';
170
+
171
+ declare module '@dudousxd/nestjs-inertia' {
172
+ interface InertiaRegistry {
173
+ pages: InertiaPages;
174
+ }
175
+ }
176
+ ```
177
+
178
+ This augments `InertiaRegistry` in core so page names and their prop types are available to the typed client (Plan D).
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('../dist/cli/main.js').then((m) => m.run(process.argv.slice(2)));