first commit
This commit is contained in:
82
docs/devtools/tooling/electrobun/src/config/config.md
Normal file
82
docs/devtools/tooling/electrobun/src/config/config.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Config loader — `config.ts`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`loadConfig(cliArgs, deps?)` builds an `ElectrobunConfig` by layering
|
||||
hard-coded defaults, an optional on-disk `.suaveplan-electrobun.json`,
|
||||
and CLI argument overrides on top of one another. The loader sits on
|
||||
`@suaveplan/config`'s five-layer pipeline (defaults / file / object /
|
||||
env / CLI), wiring three of the five for the scaffolder's needs.
|
||||
|
||||
The `--name`, `--id`, `--icon`, and `--version` CLI flags map to the
|
||||
`name`, `identifier`, `iconSource`, and `version` fields respectively.
|
||||
Defaults fill `version="0.0.1"`, `features=[]`,
|
||||
`networkingComplexity="basic"`, and `r3fModules=[]` so callers can rely
|
||||
on the final shape having those fields populated even when no file or
|
||||
flag supplies them.
|
||||
|
||||
The `ConfigDiscoveryAdapter` seam (defined in `src/fs/fs.ts`) controls
|
||||
where the loader looks for the config file. Tests inject an in-memory
|
||||
adapter; production code uses the default `nodeConfigDiscoveryAdapter`
|
||||
that probes `process.cwd()` then `homedir()` via real `node:fs` calls.
|
||||
|
||||
## Features
|
||||
|
||||
- Three-layer build: defaults → file → CLI.
|
||||
- Synchronous (no async lift required by callers).
|
||||
- Wraps malformed JSON as `ELECTROBUN.CONFIG_PARSE_FAILED`.
|
||||
- Pluggable file discovery through `ConfigDiscoveryAdapter`.
|
||||
- Exported `CLI_MAPPING` constant so consumers can introspect the flag
|
||||
set (used by the `--help` text builder).
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { loadConfig } from "@suaveplan/electrobun/config";
|
||||
|
||||
const cfg = loadConfig(process.argv.slice(2));
|
||||
console.log(cfg.name ?? "(no name set)");
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { loadConfig } from "@suaveplan/electrobun/config";
|
||||
import type { ConfigDiscoveryAdapter } from "@suaveplan/electrobun/fs";
|
||||
|
||||
const inMemory: ConfigDiscoveryAdapter = {
|
||||
cwd: () => "/proj",
|
||||
homedir: () => "/home/user",
|
||||
exists: (p) => p === "/proj/.suaveplan-electrobun.json",
|
||||
readFile: () => JSON.stringify({ name: "ci-app", features: ["api"] }),
|
||||
};
|
||||
const cfg = loadConfig(["--icon", "/icons/app.png"], {
|
||||
discovery: inMemory,
|
||||
});
|
||||
// cfg.name === "ci-app"; cfg.iconSource === "/icons/app.png"
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `loadConfig(cliArgs: readonly string[] = [], deps?: { discovery?:
|
||||
ConfigDiscoveryAdapter }): ElectrobunConfig`.
|
||||
- `HARDCODED_DEFAULTS: ElectrobunConfig` — frozen defaults applied at
|
||||
the bottom of the layer stack.
|
||||
- `CLI_MAPPING: Record<string, string>` — exact flag-to-field mapping
|
||||
used by the CLI layer.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`@suaveplan/config`'s `cliLayer` takes mapping keys without the leading
|
||||
`--`; the constants here mirror that contract verbatim. `coerceValue`
|
||||
inside the cli layer parses booleans, numbers, and JSON literals, so a
|
||||
caller can pass `--features '["api","i18n"]'` and have the array land
|
||||
on the right field without bespoke wiring.
|
||||
|
||||
The file layer is skipped entirely when `findConfigFile` returns
|
||||
`undefined`. This keeps the layer stack short for the common "no config
|
||||
file" case and avoids a no-op fileLayer reload subscription.
|
||||
Reference in New Issue
Block a user