juniper
Version:
ESM JSON Schema builder for static Typescript inference.
397 lines • 14.7 kB
TypeScript
import { type JsonSchema, type ReservedWords, type SchemaType, type ToJsonParams, type typeCache } from './types.js';
declare const allOfSym: unique symbol;
declare const anyOfSym: unique symbol;
declare const conditionalsSym: unique symbol;
declare const examplesSym: unique symbol;
declare const metadataSym: unique symbol;
declare const notSym: unique symbol;
declare const nullableSym: unique symbol;
declare const oneOfSym: unique symbol;
declare const refSym: unique symbol;
export interface SchemaParams<T> {
default?: T;
deprecated?: boolean;
description?: string | null;
readOnly?: boolean;
writeOnly?: boolean;
title?: string | null;
[allOfSym]?: AbstractSchema<SchemaGenerics<T>>[];
[anyOfSym]?: AbstractSchema<SchemaGenerics<T>>[][];
[conditionalsSym]?: {
if: AbstractSchema<SchemaGenerics<T>>;
then: AbstractSchema<SchemaGenerics<T>> | null;
else: AbstractSchema<SchemaGenerics<T>> | null;
}[];
[examplesSym]?: T[];
[metadataSym]?: Record<string, unknown>;
[notSym]?: AbstractSchema<SchemaGenerics<T>>[];
[nullableSym]?: boolean;
[oneOfSym]?: AbstractSchema<SchemaGenerics<T>>[][];
[refSym]?: {
path: string;
schema: AbstractSchema<SchemaGenerics<T>>;
} | null;
}
export interface SchemaGenerics<T> {
type: T;
params: SchemaParams<this['type']>;
}
export type ConditionalResult<T, E = T> = {
then: T;
else: E;
} | {
then: T;
else?: null;
} | {
then?: null;
else: E;
};
export interface SerializationParams {
/**
* Inside composition (e.g. `allOf`).
*
* Pass base type information to prevent unnecessary duplicates.
*/
composition?: {
type: string | null;
nullable: boolean;
};
/**
* Comply with OpenAPI 3.0 spec.
*/
openApi30: boolean;
}
/**
* Base class for JSON Schema generation and serialization.
*
* @template T
*/
export declare abstract class AbstractSchema<T extends SchemaGenerics<any>> {
#private;
/**
* "Abstract" convenient wrapper around `new` keyword.
*
* Child classes MUST implement method with proper typings.
*
* @param options - constructor parameters
* @returns new schema instance
*/
protected static create: (this: void, options?: any) => AbstractSchema<any>;
protected readonly schemaType?: string;
/**
* Used to store type information.
* Not actually defined and should not be accessed via JS.
*/
readonly [typeCache]: T;
/**
* Create instance of Schema. See `create` for convenient wrapper.
*
* @param [options] - optional
* @param [options.title] - Add title to schema
* @param [options.description] - Add description to schema
* @param [options.deprecated] - flag schema as deprecated
* @param [options.readOnly] - value should not be modified
* @param [options.writeOnly] - value should be hidden
* @returns new schema instance
*/
constructor(options?: T['params']);
/**
* A dictionary of "default" values for a schema. Only need to include
* those that are omitted from a schema when at a certain value.
*
* e.g. StringSchema omits `minProperties` when set to `0`.
*
* Used by `$ref` to ensure defaulted properties are not mistakenly overwritten
* by the referenced schema.
*
* Child classes SHOULD extend this response when implementing default-able properties.
*
* @returns map of property name -> default value.
*/
protected static getDefaultValues(params: SerializationParams): Record<string, unknown>;
/**
* Generate the JSON Schema document.
*
* The output will be an object, but not much else should be inferred about the
* response. It should instead be passed to a validator library like [ajv](https://www.npmjs.com/package/ajv)
* or serialized for export.
*
* The structure being described by the schema can be extracted via `SchemaType`.
*
* @example
* const schema = StringSchema.create().enums(['a', 'b'] as const).toJSON();
* type MyString = SchemaType<typeof schema>; // 'a' | 'b'
*
* @param [options] - optional
* @param [options.id] - $id property of schema
* @param [options.openApi30=false] - Use syntax complaint with OpenAPI 3.0.
* @param [options.schema=false] - Include `$schema` keyword for draft 2020-12.
* @returns serializable JSON Schema
*/
toJSON({ id, openApi30, schema, }?: ToJsonParams): JsonSchema<T['type']>;
/**
* Set the `title` of the schema.
* Use `null` to effectively unset.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.1}
*
* @param this - this instance
* @param title - title property
* @returns cloned schema
*/
title(this: this, title: string | null): this;
/**
* Set the `description` of the schema.
* Use `null` to effectively unset.
*
* While multiline may be supported, whitespace itself is not trimmed.
* Refer to a library like [dedent](https://www.npmjs.com/package/dedent) for this functionality.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.1}
*
* @param this - this instance
* @param description - description property
* @returns cloned schema
*/
description(this: this, description: string | null): this;
/**
* Set the `default` of the schema.
* Omit parameter to unset.
*
* Application of the `default` value is implementation-specific, so does not alter typings.
* Overwrites existing default.
*
* Default is not type checked against future settings, so it is possible to set a valid
* default that becomes invalid with more restrictions.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.2}
*
* @param this - this instance
* @param [val] - default value of schema
* @returns cloned schema
*/
default(this: this, val?: T['type']): this;
/**
* Set the `deprecated` of the schema.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.3}
*
* @param this - this instance
* @param deprecated - deprecated property
* @returns cloned schema
*/
deprecated(this: this, deprecated: boolean): this;
/**
* Append an example literal to the schema.
*
* Convenience method for calling `examples([example])`.
*
* @param this - this instance
* @param example - example literal
* @returns cloned schema
*/
example(this: this, example: T['type']): this;
/**
* Append multiple example values to the schema.
*
* While the example is type-checked, it is not asserted against the schema.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.5}
*
* @param this - this instance
* @param examples - example literal array
* @returns cloned schema
*/
examples(this: this, examples: T['type'][]): this;
/**
* Set the schema as `readOnly`.
*
* Has no impact on validation (or typings), but as a hint that attempts to modify may be rejected/ignored.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.4}
*
* @param this - this instance
* @param readOnly - read only property
* @returns cloned schema
*/
readOnly(this: this, readOnly: boolean): this;
/**
* Set the schema as `writeOnly`.
*
* Has no impact on validation (or typings), but as a hint that data may be omitted when retrieved from authority.
*
* @see {@link https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.4}
*
* @param this - this instance
* @param writeOnly - write only property
* @returns cloned schema
*/
writeOnly(this: this, writeOnly: boolean): this;
/**
* Append custom metadata to schema.
* Any JSON Schema reserved words are forbidden.
*
* Besides ensuring no overlap with reserved words, no content
* validation or type inference occurs. All values are returned unaltered, regardless
* of generation parameters.
*
* Useful to append metadata for implementation specific needs, such as (but not exclusive to)
* [OpenAPI's `x-` prefix](https://swagger.io/specification/#specification-extensions) or self-implementing
* [custom keywords](https://json-schema.org/understanding-json-schema/reference/schema.html#id6).
*
* This method _may_ be used for self-implement missing features
* but such usage may be disabled at any time (via implementation).
*
* @param this - this instance
* @param meta - custom metadata
* @returns cloned schema
* @throws when reserved word is used as keyword
*/
metadata<K extends string, V>(this: this, ...meta: (K & ReservedWords extends never ? unknown[] : [never]) & ([K, V] | [Record<K, V>])): this;
/**
* Reference schema via `$ref`.
* Path to ref must be provided, and is not validated.
*
* Any "edits" to the resulting object are merged into the `$ref` object.
*
* The `$ref` object is expected to be the value of the schema called with `toJSON()`.
*
* Note that this syntax is valid in OpenApi 3.0, but behavior is _generally_
* expected to ignore any sibling properties.
* Actual implementation is up to user (many `$ref` parsers will merge objects).
*
* @see {@link https://json-schema.org/understanding-json-schema/structuring.html#ref}
*
* @param this - this instance
* @param path - $ref path property
* @returns cloned schema
*/
ref(this: this, path: string): this;
/**
* Explicitly cast schema.
*
* Use with caution as any types are not enforced and
* no more type-specific extensions are possible.
*
* Convenience method for tacking on custom symbols or attributes
* that vary by implementation/usage.
*
* @returns typed schema
*/
cast<NewT extends T['type']>(): AbstractSchema<SchemaGenerics<NewT>>;
/**
* Append an `allOf` restriction on schema.
*
* @see {@link https://json-schema.org/understanding-json-schema/reference/combining.html#allof}
*
* @param schema - all of schema must be valid
* @returns cloned schema
*/
protected allOf(schema: never): unknown;
/**
* Define a `anyOf` restriction on schema.
*
* @see {@link https://json-schema.org/understanding-json-schema/reference/combining.html#anyof}
*
* @param schemas - any of schema must be valid
* @returns cloned schema
*/
protected anyOf(schemas: never[]): unknown;
/**
* Apply conditional schemas.
*
* @see {@link https://json-schema.org/understanding-json-schema/reference/conditionals.html#if-then-else}
*
* @param schema - "if" schema property
* @param conditionals - "then" + "else" schemas, at least one is required.
* @returns cloned schema
*/
protected if(schema: never, conditionals: ConditionalResult<never>): unknown;
/**
* A schema definition that would render the schema invalid.
*
* Does not alter types, as the closest typescript equivalent `Exclude`
* doesn't actually ensure excluded types.
*
* ```ts
* type NotReallyExcluded = Exclude<{ abc: string; efg?: number }, { abc: 123 }>;
* const shouldBeInvalid: NotReallyExcluded = { abc: 123 };
* ```
*
* Schemas that support `nullable()` may exclude `null` if appropriate.
*
* @see {@link https://json-schema.org/understanding-json-schema/reference/combining.html#not}
*
* @param schema - schema to validate against
* @returns cloned schema
*/
protected not(schema: never): unknown;
/**
* Set schema as `nullable`.
* Allowing `type=null` as well as existing type.
*
* @returns cloned schema
*/
protected nullable(): unknown;
/**
* Define a `oneOf` restriction on schema.
*
* @see {@link https://json-schema.org/understanding-json-schema/reference/combining.html#oneof}
*
* @param schemas - one of schema must be valid
* @returns cloned schema
*/
protected oneOf(schemas: never[]): unknown;
/**
* Instance method to call static method (using constructor for inheritance).
*
* @param this - this instance
* @param params - serialization params
* @returns JSON Schema
*/
protected getChildSchema<T2>(this: AbstractSchema<SchemaGenerics<T2>>, params: SerializationParams): JsonSchema<T2>;
/**
* Returns default constructor params for child class.
*
* Child classes SHOULD implement, and MUST extend response from `super.getCloneParams()`.
* If no extra parameters are used, do not need to implement.
*
* @returns schema params based on instance
*/
protected getCloneParams(): Required<SchemaParams<T['type']>> & T['params'];
/**
* Creates a new instance of this schema class,
* with parameters to set attributes to same as this instance.
*
* Override existing values via the `overrideParams`.
*
* Child classes MUST NOT override.
*
* @param overrideParams - override constructor params
* @returns schema params
*/
protected clone(overrideParams: Partial<T['params']>): this;
/**
* Generate JSON Schema for this data type.
*
* Child classes SHOULD override and extend value of `super.toSchema()`.
* If no extra schema data is added, do not need to implement.
*
* @param params - serialization params
* @returns JSON Schema
*/
protected toSchema(params: SerializationParams): JsonSchema<SchemaType<this>>;
/**
* Method to get JSON schema of a internal property (e.g. array item).
*
* Child classes MUST NOT override.
*
* @param schema - juniper schema
* @param params - serialization params (stripped of composition context)
* @param params.openApi30 - open api 3.0 compliant
* @returns JSON Schema
*/
protected static getSchema<T2>(schema: AbstractSchema<SchemaGenerics<T2>>, { openApi30 }: SerializationParams): JsonSchema<T2>;
}
export {};
//# sourceMappingURL=schema.d.ts.map