Initial Commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# Feature templates — `features.ts`
|
||||
|
||||
## Purpose
|
||||
|
||||
Owns every renderer that produces a per-feature file in the scaffolded
|
||||
output: `i18n`, `networking` (basic + full), `api`, `api-schemas`,
|
||||
`storage`, `auth`, `form-builder`, and `r3f`. The renderers are pure
|
||||
functions over `ProjectOptions`; the `r3f` renderer additionally branches
|
||||
on `options.r3fModules` to wire camera / physics / particles / character
|
||||
/ pathfinding subsystems into the emitted scene.
|
||||
|
||||
The companion `templates.ts` module covers the project-level renderers;
|
||||
the two together replace the upstream `src/templates/*.ts` and
|
||||
`src/templates/features/*.ts` blob set. `renderFeature(feature,
|
||||
options)` is the single dispatch entry the generator uses; individual
|
||||
`render*Feature` helpers are exported for tools that want to render a
|
||||
single feature in isolation (for example, a "show me the API skeleton"
|
||||
preview pane in an IDE extension).
|
||||
|
||||
## Features
|
||||
|
||||
- Eight per-feature renderers — every closed `FeatureModule` value has a
|
||||
dedicated implementation.
|
||||
- `renderNetworkFeature` vs `renderNetworkFullFeature` selected by
|
||||
`options.networkingComplexity`.
|
||||
- `renderR3fFeature` composes the camera / physics / particles imports
|
||||
+ scene fragments based on `options.r3fModules`.
|
||||
- `featurePath(feature)` returns the canonical output path for each
|
||||
feature (the generator uses this to assemble the file list).
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { renderFeature, featurePath } from "@suaveplan/electrobun/templates";
|
||||
|
||||
const content = renderFeature("i18n", opts);
|
||||
const path = featurePath("i18n");
|
||||
// path === "src/features/i18n.ts"
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
featurePath,
|
||||
renderFeature,
|
||||
} from "@suaveplan/electrobun/templates";
|
||||
|
||||
const featureFiles = opts.features.map((f) => ({
|
||||
path: featurePath(f),
|
||||
content: renderFeature(f, opts),
|
||||
}));
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `renderI18nFeature()`, `renderNetworkFeature()`,
|
||||
`renderNetworkFullFeature()`, `renderApiFeature()`,
|
||||
`renderApiSchemasFeature()`, `renderStorageFeature()`,
|
||||
`renderAuthFeature()`, `renderFormBuilderFeature()`,
|
||||
`renderR3fFeature(options)`.
|
||||
- `renderFeature(feature: FeatureModule, options: ProjectOptions):
|
||||
string` — dispatch table.
|
||||
- `featurePath(feature: FeatureModule): string`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The `r3f` renderer is the only one whose output is materially shaped by
|
||||
`ProjectOptions` beyond the basic "the feature is enabled" toggle. The
|
||||
imports and scene fragments are assembled by joining arrays of strings,
|
||||
which makes the relative ordering deterministic and the diff-noise low
|
||||
when a new R3F module is added: the test for "r3f renderer emits the
|
||||
requested modules" pins the order so a refactor cannot silently
|
||||
re-shuffle imports.
|
||||
|
||||
The `networking` renderer dispatches on `options.networkingComplexity`
|
||||
rather than `options.networking` because the upstream contract used
|
||||
`"basic"` / `"full"` to gate the full mesh layer. Keeping the same
|
||||
contract means downstream electrobun projects already on the
|
||||
`networkingComplexity` shape do not need to migrate.
|
||||
|
||||
`featurePath` lives here rather than in the generator because the
|
||||
mapping is per-feature; the generator consumes it as a thin lookup. If
|
||||
a future feature lands with a non-default output path, the change is
|
||||
local to `features.ts`.
|
||||
Reference in New Issue
Block a user