@beignet/core
Version:
Core framework primitives for Beignet
132 lines • 7.36 kB
TypeScript
import { ContractBuilder } from "./contract-builder.js";
import { type ContractDeprecationMeta } from "./lifecycle.js";
import type { ContractErrorResponses, ContractHeaderSchemas, ContractMeta, ContractResponses, MergeContractMeta, MergedContractErrorResponses, OmitMetaKeys, ResponsesFromErrorDefinitions, StandardSchema } from "./types.js";
type TrimLeadingSlash<T extends string> = T extends `/${infer Rest}` ? TrimLeadingSlash<Rest> : T;
type TrimTrailingSlash<T extends string> = T extends "/" ? "" : T extends `${infer Rest}/` ? TrimTrailingSlash<Rest> : T;
type NormalizedPrefix<T extends string> = T extends "" | "/" ? "" : TrimTrailingSlash<T>;
type NormalizedChildPath<T extends string> = TrimTrailingSlash<TrimLeadingSlash<T>>;
type JoinPaths<TPrefix extends string, TPath extends string> = string extends TPrefix | TPath ? string : NormalizedPrefix<TPrefix> extends "" ? TPath : NormalizedChildPath<TPath> extends "" ? NormalizedPrefix<TPrefix> : `${NormalizedPrefix<TPrefix>}/${NormalizedChildPath<TPath>}`;
/**
* Feature-scoped factory for related HTTP contracts.
*
* Contract groups let a feature share a namespace, path prefix, headers,
* responses, errors, and metadata across multiple endpoint contracts. The group
* is immutable: every configuration method returns a new group.
*/
export declare class ContractGroup<TSharedResponses extends ContractResponses = Record<never, never>, TSharedMeta extends ContractMeta = ContractMeta, TSharedHeaders extends ContractHeaderSchemas = null, TPathPrefix extends string = ""> {
private readonly _namespace;
private readonly _meta;
private readonly _responses;
private readonly _headers;
private readonly _pathPrefix;
constructor(state?: {
namespace?: string;
meta?: TSharedMeta;
responses?: TSharedResponses;
headers?: TSharedHeaders;
pathPrefix?: TPathPrefix;
});
/**
* Set the namespace for contracts created from this group.
*
* The namespace prefixes contract names, not paths. Use `prefix(...)` for
* path composition.
*/
namespace(ns: string): ContractGroup<TSharedResponses, TSharedMeta, TSharedHeaders, TPathPrefix>;
/**
* Add a path prefix to contracts created from this group.
*
* Prefixes compose immutably, so `prefix("/api").prefix("/v1")` produces
* paths under `/api/v1`.
*/
prefix<const TNewPrefix extends string>(pathPrefix: TNewPrefix): ContractGroup<TSharedResponses, TSharedMeta, TSharedHeaders, JoinPaths<TPathPrefix, TNewPrefix>>;
/**
* Merge shared metadata into contracts created from this group.
*/
meta<TNewMeta extends ContractMeta>(meta: TNewMeta): ContractGroup<TSharedResponses, MergeContractMeta<TSharedMeta, TNewMeta>, TSharedHeaders, TPathPrefix>;
/**
* Mark every contract created from this group as deprecated.
*/
deprecated<const TDeprecation extends ContractDeprecationMeta>(deprecation: TDeprecation): ContractGroup<TSharedResponses, MergeContractMeta<TSharedMeta, {
deprecation: TDeprecation;
}>, TSharedHeaders, TPathPrefix>;
/**
* Add shared route-owned response schemas to contracts created from this group.
*
* Framework-owned responses, such as validation or auth hook failures, do not
* need to be declared here.
*/
responses<TNewResponses extends ContractResponses>(responseSchemas: TNewResponses): ContractGroup<Omit<TSharedResponses, keyof TNewResponses> & TNewResponses, TSharedMeta, TSharedHeaders, TPathPrefix>;
/**
* Declare shared route-owned application errors for contracts in this group.
*
* Catalog errors use Beignet's standard error envelope and remain separate
* from framework-owned errors. Declarations merge with previously declared
* group errors, and contracts created from the group merge these shared
* errors with route-level `.errors()` declarations; later declarations win
* when the same catalog key is declared twice.
*/
errors<TErrorDefs extends ContractErrorResponses>(errorDefs: TErrorDefs): ContractGroup<Omit<TSharedResponses, keyof ResponsesFromErrorDefinitions<TErrorDefs>> & ResponsesFromErrorDefinitions<TErrorDefs>, OmitMetaKeys<TSharedMeta, "errors"> & {
errors: MergedContractErrorResponses<TSharedMeta, TErrorDefs>;
}, TSharedHeaders, TPathPrefix>;
/**
* Add a shared request header schema to contracts created from this group.
*/
headers<TNewHeaders extends StandardSchema>(schema: TNewHeaders): ContractGroup<TSharedResponses, TSharedMeta, TSharedHeaders extends readonly StandardSchema[] ? readonly [...TSharedHeaders, TNewHeaders] : TSharedHeaders extends StandardSchema ? readonly [TSharedHeaders, TNewHeaders] : readonly [TNewHeaders], TPathPrefix>;
/**
* Create a GET contract under this group.
*/
get<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"GET", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Create a POST contract under this group.
*/
post<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"POST", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Create a PUT contract under this group.
*/
put<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"PUT", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Create a PATCH contract under this group.
*/
patch<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"PATCH", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Create a DELETE contract under this group.
*/
delete<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"DELETE", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Create a HEAD contract under this group.
*/
head<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"HEAD", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Create an OPTIONS contract under this group.
*/
options<const TPath extends string>(path: TPath, name?: string): ContractBuilder<"OPTIONS", null, null, null, TSharedHeaders, TSharedResponses, TSharedMeta, JoinPaths<TPathPrefix, TPath>>;
/**
* Internal helper to create a contract builder with shared config
*/
private createBuilder;
}
/**
* Create a new feature contract group.
*
* Start here for most feature HTTP surfaces, then add a namespace and path
* prefix before defining individual contracts.
*
* @example
* ```ts
* const todos = defineContractGroup()
* .namespace("todos")
* .prefix("/api/todos")
* .meta({ auth: "required" })
* .responses({
* 401: z.object({ message: z.literal("Unauthorized") }),
* });
*
* const getTodo = todos.get("/:id")...
* ```
*
* @returns An empty immutable contract group.
*/
export declare function defineContractGroup(): ContractGroup<Record<never, never>, ContractMeta, null, "">;
export {};
//# sourceMappingURL=contract-group.d.ts.map