Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
# Proposal — Migrate @suaveplan/electrobun to genesis
- **Design**: ./design.md
- **Spec delta**: ./specs/electrobun/spec.md
## Why
Upstream `@suaveplan/electrobun` (`/mnt/s/web/suaveplan/packages/universal/electrobun/`)
is a thin scaffolder: it prompts the user for an app name and a feature list, runs an
`iconz`-backed icon pipeline, and emits a fixed-template Electrobun project to disk.
The genesis `enterprise/electrobun.md` audit highlights five structural gaps:
1. every failure path is either an `Error` literal or a `console.log`, so consumers
cannot discriminate between "icon source missing" and "rollup chain blew up";
2. no OpenTelemetry surface for what is the entry point new contributors hit first;
3. the generator is hard-wired to `node:fs` with no seam for tests or for embedding
in CI;
4. only the `create` step is covered — operators have nothing for `dev` (watch +
restart), `build` (cross-platform packaging), `package` (release-bundle assembly),
`sign` (notarization + entitlements), or the auto-update pipeline; and
5. the `renderXxxFeature()` template functions are inlined-string blobs with no
validation of the render input, so a stale `ProjectOptions` shape silently
produces a broken project.
Genesis cleans up the contract: every failure raises a typed `ElectrobunError`
carrying a stable `ELECTROBUN.*` code; every command and every render-helper takes
an injectable seam (`FsAdapter`, `CommandRunner`, `IconRendererAdapter`,
`Prompter`); every public option is Zod-validated; the CLI grows from one command
(`create`) to five (`create`, `dev`, `build`, `package`, `sign`); and an
OTel surface (5 counters + 2 histograms) makes the package observable in CI.
## What
Land `@suaveplan/electrobun@0.1.0` at `packages/devtools/tooling/electrobun/` with the
following feature modules (one folder per feature, sibling `.md` per implementation
file; no `electrobun-` prefix inside the package):
- `error-codes/` — `ELECTROBUN_CODES = defineCodes("ELECTROBUN", [...])` and
`ElectrobunError`.
- `telemetry/` — OTel counters + histograms (`projects_generated_total`,
`icons_generated_total`, `runner_invocations_total`, `runner_failures_total`,
`prompts_total`, `generate_duration_ms`, `runner_duration_ms`).
- `types/` — shared interfaces (`ProjectOptions`, `ElectrobunConfig`, `GeneratedFile`,
`FsAdapter`, `CommandRunner`, `CommandInput`, `CommandResult`,
`IconRendererAdapter`, `Prompter`, every `*Report` / `*Options`).
- `schemas/` — Zod schemas for every public type; both schema and inferred type
exported.
- `fs/` — `nodeFsAdapter` and seam-driven `ensureDirectory`, `directoryExists`,
`directoryIsEmpty`, `writeFiles`, `findConfigFile`.
- `runner/` — `CommandRunner` contract + `nodeCommandRunner` default (spawn-based).
- `config/` — `loadConfig(cliArgs, opts?)` consuming the
`@suaveplan/config` 5-layer pipeline (defaults / file / CLI) with the
`FsAdapter` injected for file discovery.
- `templates/` — render helpers for every project file
(`electrobun-config`, `main-process`, `package-json`, `tsconfig`, `readme`,
`mainview-html`, `mainview-css`, `mainview-entry`, `shared-types`) plus
`templates/features/` for every feature renderer (`i18n`, `network`,
`network-full`, `api`, `api-schemas`, `storage`, `auth`, `form-builder`, `r3f`).
- `generator/` — `collectFiles(options)`, `generate(options, opts?)` —
orchestrates the renderer table, writes via `FsAdapter`, returns a
`GenerateReport`.
- `icons/` — `generateIcons(opts, deps?)` — wraps `iconz` via the
`IconRendererAdapter` seam.
- `prompts/` — `runPrompts(config, outputDir, prompter?)`.
- `cli/` — five pure functions (`createCommand`, `devCommand`, `buildCommand`,
`packageCommand`, `signCommand`) and `runCli(argv, opts?)`. Each returns a
`*Report`; none call `process.exit`.
- `bin/` — `suaveplan-electrobun` binary wiring `runCli` through
`process.argv.slice(2)`.
## Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
| `ProjectOptions` / `ElectrobunConfig` types | upstream | yes | Preserved; now Zod-validated. |
| `FEATURE_LABELS`, `R3F_MODULE_LABELS` | upstream | yes | Preserved. |
| `FeatureModule`, `NetworkingComplexity`, `R3fModule` unions | upstream | yes | Preserved verbatim. |
| `loadConfig(cliArgs)` layered loader | upstream | yes | Now consumes `@suaveplan/config`'s 5-layer pipeline; `findConfigFile` is `FsAdapter`-driven. |
| `directoryExists` / `directoryIsEmpty` / `ensureDirectory` / `writeFiles` | upstream | yes | Preserved; injectable `FsAdapter`. |
| `collectFiles(options)` core file list | upstream | yes | Preserved with deterministic ordering. |
| `generate(options)` orchestrator | upstream | enhanced | Returns `GenerateReport`; emits OTel histogram. |
| `generateIcons(input, outputDir)` | upstream | enhanced | Takes an `IconRendererAdapter` seam; default = real `iconz`. Returns `IconReport`. |
| Project file renderers (9) | upstream | yes | Same outputs, deterministic. |
| Feature renderers (8) | upstream | yes | Same outputs. |
| Interactive `create` command | upstream | yes | Preserved; Zod-validated; `--skip-prompts` honoured. |
| `dev` / `build` / `package` / `sign` commands | none | added | Orchestrate the upstream `electrobun` binary via `CommandRunner`; report shape + error classification. |
| Auto-update bundling | none | added | Surfaced via `buildOptions.update` → `electrobun build --update` argv. |
| Code-signing options | none | added | `signCommand` exposes identity / entitlements / notarization; the wrapper shapes args + classifies errors. |
| Error-code registry | none | added | `ELECTROBUN.*` namespace, eleven codes. |
| OTel self-telemetry | none | added | 5 counters + 2 histograms. |
| Zod-validated options | none | added | Every public option is Zod-validated. |
| Subpath exports per feature | none | added | One subpath export per feature module. |
## Impact
### Affected dependents
Run `bunx turbo ls --filter=...@suaveplan/electrobun` to enumerate. Net-new package on
genesis — no current dependents.
- No dependents (verified by `bunx turbo ls --filter=...@suaveplan/electrobun`).
## Risks
- **`iconz` ESM resolution.** Upstream loads `iconz/presets` dynamically. The
genesis port keeps the dynamic-import path behind the `IconRendererAdapter` seam
so tests can swap in a fake renderer without paying the `iconz` cost.
- **`electrobun` binary availability.** `dev`/`build`/`package`/`sign` shell out to
the user's local `electrobun` binary (installed in the generated project's
`node_modules`). The wrapper probes for it via the `CommandRunner` seam and
raises `ELECTROBUN.BINARY_UNAVAILABLE` with a remediation hint when missing.
- **Signing requires real certs.** The `sign` command's test surface asserts only
the argument-shape and error-classification contract; the real signing pipeline
runs against the user's keychain / Apple-developer-id / Windows-PFX and is
exercised by an opt-in integration scenario that probes the runner.
- **Cross-platform packaging.** `electrobun build` produces platform-specific
outputs; the wrapper records the requested target triple (`mac` / `linux` /
`windows`) in the `PackageReport` so CI can branch on it.