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,45 @@
# `satisfies`
## Purpose
Small in-house semver-range matcher used by the dep-graph and capability resolvers. Covers a deliberately narrow subset: pinned (`1.2.3`), caret (`^1.2.3`, `^1.2`, `^1`), tilde (`~1.2.3`, `~1.2`, `~1`), and the wildcards `*` / `latest`. Anything outside that subset throws so the caller can surface a stable error code.
## Features
- Strict SemVer 2.0.0 parse of the candidate version
- Caret semantics match npm's: `^0.x.y` stays inside the `0.x` line
- Tilde semantics: `~1.2.3` matches `1.2.>=3`, `~1.2` matches `1.2.*`
- No external dependency on `semver` — fewer bytes shipped to consumers
## Basic Example
```ts
import { satisfies } from "@suaveplan/api-manifest/dep-graph";
satisfies("1.4.2", "^1"); // true
```
## Advanced Example
```ts
import { satisfies } from "@suaveplan/api-manifest/dep-graph";
function matchAny(version: string, ranges: readonly string[]): boolean {
return ranges.some((r) => {
try { return satisfies(version, r); } catch { return false; }
});
}
```
## API Reference
- `satisfies(version: string, range: string): boolean`
- Throws `Error` (mapped by the dep-graph to `MANIFEST.DEPENDENCY_VERSION_MISMATCH`) on unsupported range syntax.
## Implementation Notes
The matcher uses three regexes (full SemVer, major-only, major.minor) and one comparator. Pre-release ordering follows SemVer 2.0.0 — pre-release strings sort lexically and any pre-release is less than the same `M.M.P` without a pre-release. Build metadata is parsed-but-ignored for comparison, matching npm. The deliberate narrowness keeps the comparator total (no `>=1.2.3 || <2.0.0`-style ambiguity); when v2 ships, range unions can be added without breaking the existing surface.
## Cross-package Notes
This module is part of the `@suaveplan/api-manifest` Stage-1 contract package. It sits beneath every Stage-2 consumer (`api-host`, `api-loader`, the admin CLI, the IDE plugin) and above the foundation packages (`@suaveplan/error`, `@suaveplan/types`). The strict-mode top-level rejection of unknown keys means upgrading from manifest v1 to v2 is an OpenSpec-driven event: a new key landing in a consumer manifest is a parse failure rather than a silent drift, which is exactly the contract this stage exists to guarantee.
When the host reloads a plugin without a full restart, every manifest field this module validates is compared against the install-time `manifestHash`. A mismatch triggers a hard rollback via the `RollbackJournal` because the host's invariants (route mounts, registered capabilities, declared scopes) are derived from these exact bytes. Treat the schemas and validators here as the contract surface, not just an input filter — downstream code reads `manifest.foo.bar` and relies on those keys being present, well-typed, and non-undefined in the documented optionality regions.