// Minimum TypeScript Version: 4.2 /* * Inspired by Dan Freeman * https://github.com/dfreeman/ * * Source: https://gist.github.com/dfreeman/33fc80164c0ad91d5e9480a94aa6454c#file-tests-model-ts */ declare module "miragejs" { import { FactoryDefinition, ModelDefinition, BelongsTo, HasMany, } from "miragejs/-types"; import IdentityManager from "miragejs/identity-manager"; export { IdentityManager }; export { Server, createServer } from "miragejs/server"; export { Registry, Instantiate, ModelInstance } from "miragejs/-types"; export { Serializer, ActiveModelSerializer, JSONAPISerializer, RestSerializer, } from "miragejs/serializer"; /** * A fake HTTP request */ export class Request { /** The request body, if defined */ readonly requestBody: string; /** The URL of the request */ readonly url: string; /** Any headers associated with the request, with downcased names */ readonly requestHeaders: Record; /** Any parameter specified via dynamic route segments */ readonly params: Record; /** Any query parameters associated with the request */ readonly queryParams: Record; } /** * A fake HTTP response. May be returned from a Mirage route * handler for finer-grained control over the response behavior. */ export class Response { /** * @param code The HTTP status code for this response * @param headers Any custom headers to set in this response * @param body Data to send in the response body */ constructor( code: number, headers?: Record, body?: string | {} ); toRackResponse(): [ number, Record | undefined, string | {} | undefined ]; } /** * The base definition for Mirage models. * * Use `Model.extend({ ... })` to define a model's relationships * (via `belongsTo()` and `hasMany()`) and any static default * attribute values. */ export const Model: ModelDefinition; /** * The base definition for Mirage factories. * * Use `Factory.extend({ ... })` to define methods that * will generate default attribute values when `server.create` * or the corresponding `schema` method is called for this * type. */ export const Factory: FactoryDefinition; /** * A collection of zero or more Mirage model instances. */ export class Collection { /** The number of models in the collection. */ length: number; /** The dasherized model name this Collection represents. */ modelName: string; /** The underlying plain JavaScript array of Models in this Collection. */ models: T[]; /** Adds a model to this collection. */ add(model: T): Collection; /** Destroys the db record for all models in the collection. */ destroy(): Collection; /** Returns a new Collection with its models filtered according to the provided callback function. */ filter(f: (value: T, index: number, models: T[]) => unknown): Collection; /** Checks if the Collection includes the given model. */ includes(model: T): boolean; /** Modifies the Collection by merging the models from another collection. */ mergeCollection(collection: Collection): Collection; /** Reloads each model in the collection. */ reload(): Collection; /** Removes a model from this collection. */ remove(model: T): Collection; /** Saves all models in the collection. */ save(): Collection; /** Returns a new Collection with a subset of its models selected from begin to end. */ slice(begin: number, end: number): Collection; /** Returns a new Collection with its models sorted according to the provided compare function. */ sort(f: (a: T, b: T) => number): Collection; /** Updates each model in the collection, and immediately persists all changes to the db. */ update(key: K, val: T[K]): Collection; } export interface RelationshipOptions { inverse?: string | null; polymorphic?: boolean; } /** Declares a one-to-one relationship to another Mirage model type. */ export function belongsTo( key?: K, options?: RelationshipOptions ): BelongsTo; export function belongsTo( options?: RelationshipOptions ): BelongsTo; /** Declares a one-to-many relationship to another Mirage model type. */ export function hasMany( key?: K, options?: RelationshipOptions ): HasMany; export function hasMany( options?: RelationshipOptions ): HasMany; } declare module "miragejs/-types" { import { Collection, Response } from "miragejs"; /* A 1:1 relationship between models */ export class BelongsTo { private name: Name; } /* A 1:many relationship between models */ export class HasMany { private name: Name; } // Captures the result of a `Model.extend()` call interface ModelDefinition { extend(data: NewData): ModelDefinition>; } // Captures the result of a `Factory.extend()` call interface FactoryDefinition { extend( data: WithFactoryMethods ): FactoryDefinition>>; } type WithFactoryMethods = { [K in keyof T]: T[K] | ((n: number) => T[K]); }; // Extract factory method return values from a factory definition type FlattenFactoryMethods = { [K in keyof T]: T[K] extends (n: number) => infer V ? V : T[K]; }; /** * Given a registry and the name of one of the models defined in it, * returns the type of that model as instantiated by Mirage. */ export type Instantiate< Registry, ModelName extends keyof Registry > = ModelInstance< { // Splitting and rejoining on `ModelName` ensures that unions distribute // properly, so that `Instantiate` expands out like // `Instantiate | Instantiate` rather than something // that only has the intersection of `foo` and `bar`'s keys. [Model in ModelName]: { [Key in keyof Registry[Model]]: InstantiateValue< Registry, Registry[Model][Key] >; }; }[ModelName] >; // Given a registry and value type, checks whether that type represents // if Mirage relationship. If so, returns the corresponding model or // collection type from the registry; otherwise returns the type unchanged. type InstantiateValue = T extends BelongsTo ? InstantiateIfDefined | null : T extends HasMany ? Collection> : T; // Returns the instantiated type of the given model if it exists in the // given registry, or `unknown` otherwise. type InstantiateIfDefined = ModelName extends keyof Registry ? Instantiate : unknown; // The type-level equivalent of `Object.assign` type Assign = U & Omit; // Extracts model definition info for the given key, if a corresponding model is defined type ExtractModelData = K extends keyof Models ? Models[K] extends ModelDefinition ? Data : {} : {}; // Extracts factory definition info for the given key, if a corresponding factory is defined type ExtractFactoryData = K extends keyof Factories ? Factories[K] extends FactoryDefinition ? FlattenFactoryMethods : {} : {}; /** * Models all available information about a given set of model and * factory definitions, determining the behavior of ORM methods on * a `Server` and its corresponding `Schema` instance. */ export type Registry< Models extends AnyModels, Factories extends AnyFactories > = { [K in keyof Models | keyof Factories]: ExtractModelData & ExtractFactoryData; }; export type AnyModels = Record; export type AnyFactories = Record; /** A marker type for easily constraining type parameters that must be shaped like a Registry */ export type AnyRegistry = Registry; type MaybePromise = T | PromiseLike; type ValidResponse = | Record | number | string | boolean | null; export type AnyResponse = MaybePromise< ModelInstance | Response | ValidResponse | ValidResponse[] >; type CollectionOrListValue = Value extends Collection< infer ElementType > ? ElementType[] | Collection : Value; /** Convert any Collection to ElementType[] | Collection */ type CollectionOrList = { [K in keyof Data]: CollectionOrListValue; }; /** Represents the type of an instantiated Mirage model. */ export type ModelInstance = Data & { id?: string; attrs: Data; modelName: string; /** Persists any updates on this model back to the Mirage database. */ save(): void; /** Updates and immediately persists a single or multiple attr(s) on this model. */ update( key: K, value: CollectionOrListValue ): void; update(changes: Partial>): void; /** Removes this model from the Mirage database. */ destroy(): void; /** Reloads this model's data from the Mirage database. */ reload(): void; }; } declare module "miragejs/server" { import { Request, Registry as MirageRegistry } from "miragejs"; import { AnyRegistry, AnyModels, AnyFactories, AnyResponse, Instantiate, } from "miragejs/-types"; import Db from "miragejs/db"; import IdentityManager from "miragejs/identity-manager"; import Schema from "miragejs/orm/schema"; import PretenderServer from "pretender"; /** * Possible HTTP verbs * @see https://github.com/pretenderjs/pretender/blob/master/index.d.ts#L13 **/ type HTTPVerb = | "get" | "put" | "post" | "patch" | "delete" | "options" | "head"; type PassthroughArg = ((request: Request) => any) | string; type PassthroughVerbs = HTTPVerb[]; /** A callback that will be invoked when a given Mirage route is hit. */ export type RouteHandler< Registry extends AnyRegistry, Response extends AnyResponse = AnyResponse > = (schema: Schema, request: Request) => Response; export type Middleware< Registry extends AnyRegistry, Response extends AnyResponse = AnyResponse > = ( schema: Schema, request: Request, next?: (request?: Request) => Response ) => Response; export interface HandlerOptions { /** A number of ms to artificially delay responses to this route. */ timing?: number; } type ShorthandOptions = "index" | "show" | "create" | "update" | "delete"; export interface ResourceOptions { /** Whitelist of shorthand options */ only?: ShorthandOptions[]; /** Exclude list of shorthand options */ except?: ShorthandOptions[]; /** Shorthand route path */ path?: string; } export interface ServerConfig< Models extends AnyModels, Factories extends AnyFactories > { urlPrefix?: string; fixtures?: any; namespace?: string; timing?: number; environment?: string; trackRequests?: boolean; useDefaultPassthroughs?: boolean; logging?: boolean; seeds?: (server: Server>) => void; scenarios?: (server: Server>) => void; routes?: (this: Server>) => void; baseConfig?: (this: Server>) => void; testConfig?: (this: Server>) => void; inflector?: object; identityManagers?: { [modelName in keyof Models]?: typeof IdentityManager; } & { application?: typeof IdentityManager }; models?: Models; serializers?: any; factories?: Factories; pretender?: PretenderServer; } /** * Starts up a Mirage server with the given configuration. */ export function createServer< Models extends AnyModels, Factories extends AnyFactories >( config: ServerConfig ): Server>; export class Server { constructor(options?: ServerConfig); /** The underlying in-memory database instance for this server. */ readonly db: Db; /** An interface to the Mirage ORM that allows for querying and creating records. */ readonly schema: Schema; /** Creates a model of the given type. */ readonly create: Schema["create"]; /** Whether or not Mirage should log all requests/response cycles. */ logging: boolean; /** A default number of ms to artificially delay responses for all routes. */ timing: number; /** A default prefix applied to all subsequent route definitions. */ namespace: string; /** * A set of middleware applied to subsequent route definitions. * * Usage: * ```js * // Example middleware which randomly returns a * // 500 response: * function random500() { * return (schema, req, next) => { * return (Math.random() > 0.7) * ? new Response(500, {}, 'no') * : next(); * } * } * * // Routes which use the middleware defined above: * routes() { * this.middleware = [ * random500(), * // ... * ] * * server.get('/users', (schema, req) => { * return new Response(204, {}, null); * }); * } * ``` */ middleware: Middleware[]; /** Sets a string to prefix all route handler URLs with. */ urlPrefix: string; /** Actual Pretender instance */ pretender: PretenderServer; /** Creates multiple models of the given type. */ createList< K extends keyof Registry, Init extends Instantiate, Data extends Partial >(modelName: K, count: number, data?: Data): Array; /** Handle a GET request to the given path. */ get( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Handle a POST request to the given path. */ post( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Handle a PUT request to the given path. */ put( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Handle a PATCH request to the given path. */ patch( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Handle an OPTIONS request to the given path. */ options( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Handle a DELETE request to the given path. */ del( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; delete( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Handle a HEAD request to the given path. */ head( path: string, handler?: RouteHandler, options?: HandlerOptions ): void; /** Define multiple shorthands for a given resource */ resource( modelName: K, options?: ResourceOptions ): void; /** Pass through one or more URLs to make real requests. */ passthrough(...urls: PassthroughArg[]): void; passthrough( ...args: [PassthroughArg, ...PassthroughArg[], PassthroughVerbs] ): void; /** Load all available fixture data matching the given name(s). */ loadFixtures(...names: string[]): void; seeds(server: Server): void; routes(): void; /** Shutdown the server and stop intercepting network requests. */ shutdown(): void; } } declare module "miragejs/db" { import DbCollection from "miragejs/db-collection"; import IdentityManager from "miragejs/identity-manager"; type DbLookup = { [key: string]: ReturnType & Omit; }; class DbClass { constructor(initialData: [], identityManagers?: IdentityManager[]); createCollection(name: string, initialData?: any[]): void; dump(): void; emptyData(): void; loadData(data: any): void; } /** The in-memory database containing all currently active data keyed by collection name. */ export type Db = DbClass & DbLookup; export const Db: Db; export default Db; } declare module "miragejs/db-collection" { import IdentityManager from "miragejs/identity-manager"; export default class DbCollection { constructor( name: string, initialData: any[], identityManager?: IdentityManager ); /** Returns a copy of the data, to prevent inadvertent data manipulation. */ all(): any[]; /** Returns a single record from the `collection` if `ids` is a single id, or an array of records if `ids` is an array of ids. */ find(id: number | string | number[] | string[]): any; /** Returns the first model from `collection` that matches the key-value pairs in the `query` object. */ findBy(query: object): any; /** Finds the first record matching the provided _query_ in `collection`, or creates a new record using a merge of the `query` and optional `attributesForCreate`. */ firstOrCreate(query: object, attributesForCreate?: object): any; /** Inserts `data` into the collection. `data` can be a single object or an array of objects. */ insert(data: any): any; /** Removes one or more records in *collection*. */ remove(target?: object | number | string): void; /** Updates one or more records in the collection. */ update(target: object | number | string, attrs?: object): any; /** Returns an array of models from `collection` that match the key-value pairs in the `query` object. */ where(query: object): any; } } declare module "miragejs/identity-manager" { /** An IdentityManager is a class that's responsible for generating unique identifiers. You can define a custom identity manager for your entire application, as well as on a per-model basis. */ export default class IdentityManager { constructor(); get?(): number; /** Registers `uniqueIdentifier` as used. */ set(uniqueIdentifier: string | number): void; inc?(): number; /** Returns the next unique identifier. */ fetch(): string; /** Resets the identity manager, marking all unique identifiers as available. */ reset(): void; } } declare module "miragejs/orm/schema" { import { Collection } from "miragejs"; import { AnyRegistry, Instantiate } from "miragejs/-types"; import Db from "miragejs/db"; type ModelInitializer = { [K in keyof Data]: Data[K] extends Collection ? Collection | M[] : Data[K]; }; /** * An interface to the Mirage ORM that allows for querying and creating records. */ export default class Schema { /** Mirage's in-memory database */ readonly db: Db; /** * Creates a model of the given type. * @param modelName The type of model to instantiate * @param data Optional initial values for model attributes/relationships */ create< K extends keyof Registry, Init extends Instantiate, Data extends Partial> >( modelName: K, data?: Data ): Init & { [K in keyof Init & keyof Data]: Exclude; }; /** Locates one or more existing models of the given type by ID(s). */ find( type: K, id: string ): Instantiate | null; find( type: K, ids: string[] ): Collection>; /** Locates an existing model of the given type by attribute value(s), if one exists. */ findBy( type: K, attributes: Partial> ): Instantiate | null; findBy( type: K, predicate: (instance: Instantiate) => boolean ): Instantiate | null; /** Locates an existing model of the given type by attribute value(s), creating one if it doesn't exist. */ findOrCreateBy( type: K, attributes: Partial> ): Instantiate; /** Locates an existing model of the given type by attribute value(s), if one exists. */ where( type: K, attributes: | Partial> | ((item: Instantiate) => unknown) ): Collection>; /** Returns a collection of all known records of the given type */ all( type: K ): Collection>; /** Returns an empty collection of the given type */ none( type: K ): Collection>; /** Returns the first model instance found of the given type */ first(type: K): Instantiate | null; } } declare module "miragejs/serializer" { import Schema from "miragejs/orm/schema"; interface SerializerInterface { schema?: Schema; attrs?: any; embed?: boolean | ((key: string) => boolean); root?: any; serializeIds?: any; include?: any; keyForAttribute?(attr: any): any; keyForCollection?(modelName: any): any; keyForEmbeddedRelationship?(attributeName: any): any; keyForForeignKey?(relationshipName: any): any; keyForModel?(modelName: any): any; keyForPolymorphicForeignKeyId?(relationshipName: string): string; keyForPolymorphicForeignKeyType?(relationshipName: string): string; keyForRelationship?(modelName: any): any; keyForRelationshipIds?(modelName: any): any; normalize?(json: any): any; serialize?(primaryResource: any, request: any): any; extend?(param?: SerializerInterface): SerializerInterface; } class Serializer implements SerializerInterface { static extend(param?: SerializerInterface | {}): SerializerInterface | {}; } interface JSONAPISerializerInterface extends SerializerInterface { alwaysIncludeLinkageData?: boolean; links?(model: any): any; shouldIncludeLinkageData?(relationshipKey: string, model: any): boolean; typeKeyForModel?(model: any): string; } class JSONAPISerializer extends Serializer implements JSONAPISerializerInterface { static extend( param?: JSONAPISerializerInterface | {} ): JSONAPISerializerInterface; } class ActiveModelSerializer extends Serializer {} class RestSerializer extends Serializer {} }