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,77 @@
# `"tenant.provider"` — capability id
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`@suaveplan/api-types/capabilities` exports `CapabilityId`, the open
union derived from the `CapabilityIdRegistry` interface. As of the
Stage-1 coherence fixes the foundation registry includes
`"tenant.provider"` directly, so this package no longer maintains a
widening alias — the runtime constant lives here because the
`TenantProvider` interface lives here, and host code needs a stable
sentinel without re-typing the literal everywhere.
The module re-exports the canonical `CapabilityId` from api-types for
source compatibility with consumers that historically imported it from
this package.
## Features
- Runtime constant `TENANT_PROVIDER_CAPABILITY_ID = "tenant.provider"`.
- Type alias `TenantProviderCapabilityId = typeof TENANT_PROVIDER_CAPABILITY_ID`.
- Re-export of `CapabilityId` from `@suaveplan/api-types/capabilities` — source-compatible with callers that imported the widened alias previously.
## Usage: Basic
```ts
import { TENANT_PROVIDER_CAPABILITY_ID } from "@suaveplan/api-tenant-provider/capability-id";
if (manifest.requires?.includes(TENANT_PROVIDER_CAPABILITY_ID)) {
// The plugin opted into per-tenant fan-out.
}
```
## Usage: Advanced
```ts
import {
type CapabilityId,
TENANT_PROVIDER_CAPABILITY_ID,
} from "@suaveplan/api-tenant-provider/capability-id";
// A capability-checker that accepts both foundation and tenant-provider ids.
function describeCapability(id: CapabilityId): string {
switch (id) {
case TENANT_PROVIDER_CAPABILITY_ID:
return "tenant enumeration (per-tenant cron fan-out)";
case "db":
return "tenant-scoped database adapter";
default:
return id;
}
}
```
## API Reference
- `const TENANT_PROVIDER_CAPABILITY_ID = "tenant.provider" as const`.
- `type TenantProviderCapabilityId = "tenant.provider"`.
- `type CapabilityId` — re-export of the canonical union from `@suaveplan/api-types/capabilities`.
## Implementation Notes
Foundation `CapabilityId` is `keyof CapabilityIdRegistry`, and the
foundation registry already contributes `"tenant.provider"` directly,
so a separate widening alias here would be redundant. Any third-party
package adding its own capability id should extend
`CapabilityIdRegistry` from `@suaveplan/api-types/capabilities` via
`declare module` rather than re-introducing a widened type union — the
registry pattern is the documented extension point.
The constant is `as const` so the value type narrows to the exact
string literal `"tenant.provider"`, which is what makes
`expectTypeOf<typeof TENANT_PROVIDER_CAPABILITY_ID>().toEqualTypeOf<TenantProviderCapabilityId>()`
hold at the type level.

View File

@@ -0,0 +1,31 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
type CapabilityId,
TENANT_PROVIDER_CAPABILITY_ID,
type TenantProviderCapabilityId,
} from "./capability-id.js";
describe("TENANT_PROVIDER_CAPABILITY_ID", () => {
it('is the literal "tenant.provider"', { timeout: 5000 }, () => {
expect(TENANT_PROVIDER_CAPABILITY_ID).toBe("tenant.provider");
});
it("narrows as a string literal at the type level", {
timeout: 5000,
}, () => {
const id: TenantProviderCapabilityId = TENANT_PROVIDER_CAPABILITY_ID;
const widened: CapabilityId = id;
expect(widened).toBe("tenant.provider");
});
it("widened CapabilityId accepts both base and tenant.provider", {
timeout: 5000,
}, () => {
// `db` is part of api-types' base CapabilityId union, so the
// widened alias must still accept it.
const fromBase: CapabilityId = "db";
const fromExtension: CapabilityId = TENANT_PROVIDER_CAPABILITY_ID;
expect(fromBase).toBe("db");
expect(fromExtension).toBe("tenant.provider");
});
});

View File

@@ -0,0 +1,24 @@
/**
* Runtime sentinel identifying this capability — string-keyed so it
* survives type erasure and is safe to log / pass through wire formats.
*
* Plugins that declare `perTenant: true` jobs in their manifest
* implicitly require this capability — the host resolves it
* automatically — but the literal MUST exist as a value so
* manifest-shape checks and host-side lookups can compare against it.
*/
export const TENANT_PROVIDER_CAPABILITY_ID = "tenant.provider" as const;
export type TenantProviderCapabilityId = typeof TENANT_PROVIDER_CAPABILITY_ID;
/**
* Re-export of the canonical {@link
* import("@suaveplan/api-types/capabilities").CapabilityId} union.
*
* As of the Stage-1 coherence fixes, `"tenant.provider"` is part of the
* `CapabilityIdRegistry` shipped by `@suaveplan/api-types/capabilities`
* directly, so this package no longer needs a widening alias. The
* re-export remains for source compatibility with consumers that
* imported `CapabilityId` from `@suaveplan/api-tenant-provider`.
*/
export type { CapabilityId } from "@suaveplan/api-types/capabilities";

View File

@@ -0,0 +1,5 @@
export {
type CapabilityId,
TENANT_PROVIDER_CAPABILITY_ID,
type TenantProviderCapabilityId,
} from "./capability-id.js";