first commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# `<PackRegistryProvider>` — chassis pack registry
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Mounts the active pack registry, validates every pack against
|
||||
`ComponentPackSchema` plus the no-collision invariant, runs each pack's
|
||||
`onRegister(ctx)` hook in declared order on mount, runs
|
||||
`onUnregister(ctx)` in reverse order on unmount, forwards each pack's
|
||||
translation bundles into the active i18n catalog under the pack's name
|
||||
as the namespace, and emits the OTel signals defined in the proposal.
|
||||
|
||||
## Features
|
||||
|
||||
- Validates packs synchronously at mount; throws
|
||||
`ReactUiError(REACT_UI.PACK_NAME_COLLISION)` when two packs share a
|
||||
`name`
|
||||
- Registration in declared order; teardown in reverse order
|
||||
- Each pack receives a `PackContext` containing the active i18n
|
||||
instance, active theme, a `PackLoggerLike` (defaulting to a
|
||||
console-backed shim), and an `AbortSignal` scoped to the pack's
|
||||
mount lifetime
|
||||
- Pack translations auto-registered via `i18n.catalog.set(locale,
|
||||
packName, bundle)` so consumers reading `t('packName:key')` see the
|
||||
registered values
|
||||
- `peerRange` mismatch logs a structured warning AND increments
|
||||
`react_ui.pack.version_mismatch_total` — the pack still registers
|
||||
(degrades gracefully, never throws)
|
||||
- Runtime override map (`<ReactUiProvider components={...}>`) merges
|
||||
on top of pack defaults at registration time
|
||||
- OTel: counters `react_ui.pack.register_total`,
|
||||
`react_ui.pack.unregister_total`,
|
||||
`react_ui.pack.version_mismatch_total`; span
|
||||
`react_ui.pack.register{name}` around each `onRegister`
|
||||
|
||||
## Usage: Basic example
|
||||
|
||||
```tsx
|
||||
import { PackRegistryProvider } from "@suaveplan/react-ui/pack/pack-registry-provider";
|
||||
|
||||
<PackRegistryProvider i18n={i18n} packs={[authPack]}>
|
||||
<App />
|
||||
</PackRegistryProvider>;
|
||||
```
|
||||
|
||||
## Usage: Advanced example
|
||||
|
||||
```tsx
|
||||
import { PackRegistryProvider } from "@suaveplan/react-ui/pack/pack-registry-provider";
|
||||
|
||||
<PackRegistryProvider
|
||||
i18n={i18n}
|
||||
packs={[authPack, socialPack, billingPack]}
|
||||
components={{
|
||||
auth: { LoginForm: AcmeLoginForm },
|
||||
social: { ShareButton: AcmeShareButton },
|
||||
}}
|
||||
logger={{ warn: log.warn, info: log.info }}
|
||||
>
|
||||
<App />
|
||||
</PackRegistryProvider>;
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `<PackRegistryProvider>` — props per `PackRegistryProviderProps`:
|
||||
- `i18n: I18nInstance` — required; pack translations register here
|
||||
- `packs: ReadonlyArray<ComponentPack>` — required
|
||||
- `components?: RuntimeComponentOverride` — optional override map
|
||||
- `logger?: PackLoggerLike` — optional; defaults to a console-backed
|
||||
shim
|
||||
- `children: ReactNode`
|
||||
|
||||
## Implementation notes
|
||||
|
||||
The provider enforces TWO validation passes at mount time: the
|
||||
collision check (synchronous, throws on duplicate name) and the schema
|
||||
check (synchronous, throws on bad shape). Both run BEFORE any
|
||||
`onRegister` hook fires so a partially-registered registry never
|
||||
exists. `onRegister` runs inside an OTel span so failures inside a
|
||||
pack's hook are attributable to the pack name in trace storage. The
|
||||
teardown loop iterates in reverse so packs that depend on earlier
|
||||
packs (e.g. a `billing` pack assuming `auth` is mounted) tear down in
|
||||
the safe order.
|
||||
Reference in New Issue
Block a user