--- name: project description: Defines the nestia product contract, workspace layout, package boundaries, the Go plugin composition model, and canonical commands. Use when orienting in the repository, working inside any package, or choosing a build, test, or format command. --- # Project Outline ## Product Contract Nestia is a set of NestJS helper libraries built around one idea: a pure TypeScript type definition should replace the stack of decorators, validators, transformers, and Swagger annotations that NestJS normally needs. The compile-time transform reads those types and injects everything else. All eight packages publish from `packages/*` at one shared version and move together on release: - **`@nestia/core`**: typed request/response decorators for NestJS controllers (`TypedRoute`, `TypedBody`, `TypedParam`, `TypedQuery`, `TypedFormData`, `TypedHeaders`, `TypedException`, `WebSocketRoute`, `McpRoute`, and the Swagger customizers). Replaces class-validator and class-transformer with type-driven validation and serialization. Owns the shared Go transform under `native/`. - **`@nestia/sdk`**: generators for Swagger documents, typed SDK libraries, mockup simulators, and automatic e2e suites, driven by the `nestia` CLI. Its Go code under `native/sdk` is a contributor linked into the `@nestia/core` host binary, not a second plugin. `website/src/content/docs/setup.mdx` documents it as a runtime dependency, not a dev dependency: the Go binary must resolve it, and `NestiaSwaggerComposer` consumers need it at runtime anyway. - **`@nestia/fetcher`**: the typed `fetch` runtime that generated SDKs sit on. Plain and AES-encrypted variants, with simulation support for mockup mode. - **`@nestia/migrate`**: converts a Swagger/OpenAPI document into a NestJS project or SDK. Generated templates ship without interactive dependencies. - **`@nestia/e2e`**: test utilities for hand-written and generated e2e suites. `DynamicExecutor` discovers test functions by prefix; `TestValidator`, `ArrayUtil`, and `RandomGenerator` are the shared assertion and data helpers. - **`@nestia/benchmark`**: a published load-test runner (`DynamicBenchmarker`) that drives e2e functions and emits markdown reports for a user's own server. - **`@nestia/editor`**: Swagger UI with an embedded cloud TypeScript editor, shipped as both a static app and a `NestiaEditorModule` library. - **`nestia`**: the CLI binary that drives `@nestia/sdk`. Downstream projects (`@agentica`, `@autobe`) build on this stack but are not part of this repository's contract. Decorator names, `INestiaConfig` options, CLI flags, the `@nestia/fetcher` runtime surface, and the generated SDK / Swagger / e2e output are all public. Renaming or removing any of them is a deliberate, separate change. ## How The Transform Composes A single Go binary performs the compile-time transform that injects validators, stringifiers, and SDK metadata. There is no TypeScript-side transformer, and reintroducing one is out of bounds. `packages/core/package.json` is the only package that registers a `ttsc` plugin: ```json "ttsc": { "plugin": { "transform": "@nestia/core/native/transform.cjs" } } ``` That manifest target, `packages/core/native/transform.cjs`, is the operative descriptor. It declares three things: - **`source`**: the Go entrypoint at `<@nestia/core root>/native/cmd/ttsc-nestia`, which ttsc compiles into a binary on first use. - **`composes: ["typia/lib/transform"]`**: the typia transform is composed in rather than reimplemented. - **`contributors`**: `<@nestia/sdk root>/native/sdk`, resolved and added only when `@nestia/sdk` is resolvable from the consuming project. `@nestia/core/lib/transform`, the plugin path nestia v11 documented, is exported as the same `native/transform.cjs` file, so a v11 plugin list resolves to this one descriptor and ttsc's package auto-discovery deduplicates it; a descriptor of its own built a second native host beside the composed typia entry and failed the build (#1690). `packages/sdk/src/transform.ts` is also a plugin descriptor, not a transformer: it resolves its installed package root through `createRequire(...).resolve("@nestia/sdk/package.json")` and returns the Go entrypoint. `packages/sdk` deliberately has no `ttsc` key: its Go source is `package sdk`, a non-main package that ttsc statically links into the core host binary. Adding a second plugin entry for `@nestia/sdk` is a misconfiguration for new projects, as the plugin descriptor and compatibility tests establish; the SDK's linked plugin still honors such an entry from a v11 plugin list and attaches SDK metadata in every build, as v11 did. Consumers reach the binary through `ttsc` / `ttsx` and the published descriptors. TypeScript test workspace entries use `cross-env` to carry the `NODE_OPTIONS="--no-experimental-strip-types --no-experimental-detect-module"` that Node 24 needs. The Evidence process suite runs plain Node. Canonical test commands and independently invoked SDK and migration integrations resolve `TTSC_CACHE_DIR` and `TTSC_GO_CACHE_DIR` against the repository root before changing workspaces. Defaults use `node_modules/.cache/ttsc` and its `go-build` child for native plugins and Go units; explicit `GOCACHE` and toolchain settings retain caller ownership. Go's own toolchain and input keys govern object reuse. Unit entries consume already-built package artifacts. SDK and migration integration entries own their necessary consumer, compiler and runtime connections; `tests/test-e2e` contains only direct units of `packages/e2e`. Test-language preparation is recorded separately from integration preparation. ## Layout - `packages/*`: the eight published packages. The shared Go plugin lives under `packages/core/native` (module `github.com/samchon/nestia/packages/core/native`, with `cmd/ttsc-nestia` and the `transform/` tree); the SDK contributor lives under `packages/sdk/native/sdk`. Both `native/go.work` files carry the same fifteen `replace` directives: fourteen redirect the `github.com/microsoft/typescript-go/shim/*` modules to a pinned `github.com/samchon/ttsc` pseudo-version, and the fifteenth redirects `github.com/samchon/ttsc/packages/ttsc` itself. - `packages/core/test` and `packages/sdk/test`: the Go unit-test modules, each its own module — core's replaces `../native`, the SDK's replaces both `../native` and `../../core/native`. Native production trees carry no test files. Emitted-validator execution against installed runtimes belongs to SDK integration; pure option and provenance decisions belong to the native unit modules. - `tests/test-*`: the workspaces are `test-benchmark`, `test-cli`, `test-e2e`, `test-editor`, `test-migrate` and `test-sdk`. `test-e2e` owns only direct `packages/e2e` units. SDK and migration workspaces separate direct units from necessary integration execution; the retired transform-options workspace's portable decisions belong to Go units and its installed boundaries share SDK preparation. See [development](../development/SKILL.md#testing) for actual-call-path classification and assertion-preservation rules. - `tests/config/tsconfig.json`: the shared strict base config. Pure unit workspaces and the integrated E2E fixture extend it at their actual relative depth. Not a package. - `config/`: `@nestia/config`, the private workspace holding shared rolldown and tsconfig build configuration and test artifact/cache preparation under `testing/`. - `benchmark/`: `@samchon/nestia-benchmark`, the private measurement workspace, with committed per-CPU results under `benchmark/results/**`. See `.agents/skills/benchmark/SKILL.md`. - `website/`: the Nextra site published at https://nestia.io, with guides under `website/src/content/docs/**`. See `.agents/skills/documentation/SKILL.md`. - `deploy/`: release scripts — `tarballs/index.js` (topologically ordered `pnpm pack`) and `copy-readme.cjs` (copies the root README into every `packages/*` directory; root `package:prepare` runs it after the full build). ## Commands The `build`, `test`, and `release` workflows run Node 24.x with Go taken from `packages/core/native/go.mod`; `website.yml` runs `lts/*` and installs no Go. The workspace pins pnpm exactly to 10.6.4. The `build` and `test` jobs use the same ttsc cache configuration under `node_modules/.cache/ttsc`, including compiled plugin binaries, Go objects and downloaded Go modules. Their workflow names distinguish immutable save keys; test populations restore before build populations so an earlier package build cannot prevent saving newly prepared test artifacts. Master builds seed caches available to later pull requests. Keys include the selected Go version, dependency lock, native sources and Go module inputs; ttsc independently validates binary inputs and Go validates object inputs. Migration templates are generated from their pinned revisions rather than retained in the Actions archive. SDK consumers share the installed public `TtscCompiler` API per producer/consumer phase; configurations and metadata naming scopes remain explicit, and the harness builds no separate Go executable. ```bash pnpm install pnpm format pnpm build pnpm test ``` `pnpm test` runs the ordinary build, Evidence, Go units, TypeScript units and integrations in sequence, stopping on failure. CI follows the same ordinary failure behavior without step conditions. Units call owning operations directly and keep editor SSR/browser initialization in separate processes. The SDK module integration entry prepares one public installation for SDK and migration and retains both owner results; each owner consolidates its actual compiler, generated-consumer, backend and worker preparation. `tests/test-e2e` remains the direct `packages/e2e` unit workspace. Different connection semantics belong to their integration owner and must not preserve obsolete per-feature compiler loops. `test.yml` owns all tests in one job without a matrix or shards: one installation and package build feed Evidence, Go, pure TypeScript units and integrated E2E. Steps use ordinary sequential execution and stop after failure. Target eight minutes through shared preparation and direct unit semantics; record actual full job duration without dropping coverage, retrying away failures or imposing an eight-minute cutoff. `pnpm format` is one Prettier invocation over `packages/**/*.ts` and `tests/**/*.ts`. It does not touch Go, Markdown, MDX, the website, or the benchmark workspace. `.prettierignore` additionally excludes the trees `packages/migrate`'s `prepare` script regenerates, so formatting them cannot produce a change a commit could carry. `pnpm format:check` is the same invocation in read-only mode, and `format.yml` runs it on every pull request. It is its own workflow because a `paths:` filter is per workflow, and neither `build.yml` nor `test.yml` covers the whole formatter target set. Keep those targets in one invocation. A chained `&&` lets an unmatched pattern silently drop every target after it: the script once chained three invocations, the second over an `internals/**/*.ts` directory that does not exist, and because Prettier exits 2 on a glob that matches nothing, `tests/**/*.ts` was never formatted at all. Release-time commands (most contributors skip these): `pnpm package:rc`, `pnpm package:next`, `pnpm package:latest`, and `pnpm release`. Every `package:*` command first runs `package:prepare`, which builds all packages (the `@nestia/migrate` build regenerates its template bundles first) and copies the root README into each of them, and only then publishes or packs; no package declares a publish-time lifecycle hook (`prepack`, `prepare`, `prepublishOnly`), so nothing builds or clones during publish and any failure aborts before anything is uploaded rather than after some packages already went out. `pnpm package:tgz` stages local tarballs in `deploy/tarballs/`, which the website build then installs. See `.agents/skills/pull-request/SKILL.md` for the remote delivery flow.