Skip to content

Commit

Permalink
Merge branch 'master' into file-class-polyfill
Browse files Browse the repository at this point in the history
  • Loading branch information
chentsulin authored Dec 3, 2021
2 parents 994d8f3 + 67d73bc commit a3e27e7
Show file tree
Hide file tree
Showing 20 changed files with 219 additions and 146 deletions.
17 changes: 9 additions & 8 deletions src/handlers/RestHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,13 @@ export const restContext: RestContext = {
fetch,
}

export type RequestParams = {
[paramName: string]: any
}

export type RequestQuery = {
[queryName: string]: any
[queryName: string]: string
}

export interface RestRequest<
BodyType extends DefaultRequestBody = DefaultRequestBody,
ParamsType extends RequestParams = PathParams,
ParamsType extends PathParams = PathParams,
> extends MockedRequest<BodyType> {
params: ParamsType
}
Expand All @@ -102,7 +98,12 @@ export class RestHandler<
RestHandlerInfo,
RequestType,
ParsedRestRequest,
RestRequest<RequestParams>
RestRequest<
RequestType extends MockedRequest<infer RequestBodyType>
? RequestBodyType
: any,
PathParams
>
> {
constructor(
method: RestHandlerMethod,
Expand Down Expand Up @@ -159,7 +160,7 @@ export class RestHandler<
protected getPublicRequest(
request: RequestType,
parsedResult: ParsedRestRequest,
): RestRequest<any, RequestParams> {
): RestRequest<any, PathParams> {
return {
...request,
params: parsedResult.params || {},
Expand Down
65 changes: 34 additions & 31 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,64 @@ import * as context from './context'
export { context }

export { setupWorker } from './setupWorker/setupWorker'
export { SetupWorkerApi } from './setupWorker/glossary'
export {
response,
defaultResponse,
createResponseComposition,
MockedResponse,
ResponseTransformer,
ResponseComposition,
ResponseCompositionOptions,
ResponseFunction,
} from './response'

/* Request handlers */
export {
RequestHandler,
export { RequestHandler, defaultContext } from './handlers/RequestHandler'
export { rest } from './rest'
export { RestHandler, RESTMethods, restContext } from './handlers/RestHandler'
export { graphql } from './graphql'
export { GraphQLHandler, graphqlContext } from './handlers/GraphQLHandler'

/* Utils */
export { matchRequestUrl } from './utils/matching/matchRequestUrl'
export { compose } from './utils/internal/compose'
export * from './utils/handleRequest'
export * from './utils/request/parseIsomorphicRequest'
export { cleanUrl } from './utils/url/cleanUrl'

/**
* Type definitions.
*/
export type { SetupWorkerApi, StartOptions } from './setupWorker/glossary'
export type { SharedOptions } from './sharedOptions'

export type {
MockedRequest,
ResponseResolver,
ResponseResolverReturnType,
AsyncResponseResolverReturnType,
DefaultRequestBody,
DefaultRequestMultipartBody,
defaultContext,
} from './handlers/RequestHandler'
export { rest } from './rest'
export {
RestHandler,
RESTMethods,

export type {
MockedResponse,
ResponseTransformer,
ResponseComposition,
ResponseCompositionOptions,
ResponseFunction,
} from './response'

export type {
RestContext,
RequestParams,
RequestQuery,
RestRequest,
ParsedRestRequest,
restContext,
} from './handlers/RestHandler'
export { graphql } from './graphql'
export {
GraphQLHandler,

export type {
GraphQLContext,
GraphQLVariables,
GraphQLRequest,
GraphQLRequestBody,
GraphQLJsonRequestBody,
graphqlContext,
} from './handlers/GraphQLHandler'

/* Utils */
export {
Path,
PathParams,
Match,
matchRequestUrl,
} from './utils/matching/matchRequestUrl'
export { compose } from './utils/internal/compose'
export { DelayMode } from './context/delay'
export type { Path, PathParams, Match } from './utils/matching/matchRequestUrl'
export type { DelayMode } from './context/delay'
export { ParsedGraphQLRequest } from './utils/internal/parseGraphQLRequest'
export * from './utils/handleRequest'
export * from './utils/request/parseIsomorphicRequest'
export { cleanUrl } from './utils/url/cleanUrl'
7 changes: 4 additions & 3 deletions src/node/createSetupServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import { handleRequest } from '../utils/handleRequest'
import { mergeRight } from '../utils/internal/mergeRight'
import { devUtils } from '../utils/internal/devUtils'
import { pipeEvents } from '../utils/internal/pipeEvents'
import { RequiredDeep } from '../typeUtils'

const DEFAULT_LISTEN_OPTIONS: SharedOptions = {
const DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {
onUnhandledRequest: 'warn',
}

Expand Down Expand Up @@ -54,7 +55,7 @@ export function createSetupServer(...interceptors: Interceptor[]) {
)
}

let resolvedOptions = {} as SharedOptions
let resolvedOptions = {} as RequiredDeep<SharedOptions>

const interceptor = createInterceptor({
modules: interceptors,
Expand Down Expand Up @@ -98,7 +99,7 @@ export function createSetupServer(...interceptors: Interceptor[]) {
resolvedOptions = mergeRight(
DEFAULT_LISTEN_OPTIONS,
options || {},
) as SharedOptions
) as RequiredDeep<SharedOptions>
interceptor.apply()
},

Expand Down
2 changes: 1 addition & 1 deletion src/node/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { setupServer } from './setupServer'
export { SetupServerApi } from './glossary'
export type { SetupServerApi } from './glossary'
18 changes: 12 additions & 6 deletions src/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import {
RestContext,
RestHandler,
RestRequest,
RequestParams,
} from './handlers/RestHandler'
import { Path } from './utils/matching/matchRequestUrl'
import { Path, PathParams } from './utils/matching/matchRequestUrl'

function createRestHandler(method: RESTMethods | RegExp) {
function createRestHandler<Method extends RESTMethods | RegExp>(
method: Method,
) {
return <
RequestBodyType extends DefaultRequestBody = DefaultRequestBody,
ResponseBody extends DefaultRequestBody = any,
Params extends RequestParams = RequestParams,
Params extends PathParams = PathParams,
ResponseBody extends DefaultRequestBody = DefaultRequestBody,
>(
path: Path,
resolver: ResponseResolver<
RestRequest<RequestBodyType, Params>,
RestRequest<
Method extends RESTMethods.HEAD | RESTMethods.GET
? never
: RequestBodyType,
Params
>,
RestContext,
ResponseBody
>,
Expand Down
22 changes: 11 additions & 11 deletions src/setupWorker/glossary.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { PartialDeep } from 'type-fest'
import { FlatHeadersObject } from 'headers-utils'
import { StrictEventEmitter } from 'strict-event-emitter'
import {
Expand All @@ -10,6 +9,7 @@ import { ServiceWorkerMessage } from '../utils/createBroadcastChannel'
import { RequestHandler } from '../handlers/RequestHandler'
import { InterceptorApi } from '@mswjs/interceptors'
import { Path } from '../utils/matching/matchRequestUrl'
import { RequiredDeep } from '../typeUtils'

export type ResolvedPath = Path | URL

Expand Down Expand Up @@ -85,7 +85,7 @@ export type ServiceWorkerFetchEventTypes =
export type WorkerLifecycleEventsMap = LifeCycleEventsMap<Response>

export interface SetupWorkerInternalContext {
startOptions?: StartOptions
startOptions?: RequiredDeep<StartOptions>
worker: ServiceWorker | null
registration: ServiceWorkerRegistration | null
requestHandlers: RequestHandler[]
Expand Down Expand Up @@ -150,28 +150,28 @@ export interface StartOptions extends SharedOptions {
/**
* Service Worker instance options.
*/
serviceWorker: {
url: string
options: RegistrationOptions
serviceWorker?: {
url?: string
options?: RegistrationOptions
}

/**
* Disables the logging of captured requests
* into browser's console.
*/
quiet: boolean
quiet?: boolean

/**
* Defers any network requests until the Service Worker
* instance is ready. Defaults to `true`.
*/
waitUntilReady: boolean
waitUntilReady?: boolean

/**
* A custom lookup function to find a Mock Service Worker in the list
* of all registered Service Workers on the page.
*/
findWorker: FindWorker
findWorker?: FindWorker
}

export interface SerializedResponse<BodyType = any> {
Expand All @@ -183,8 +183,8 @@ export interface SerializedResponse<BodyType = any> {

export type StartReturnType = Promise<ServiceWorkerRegistration | undefined>
export type StartHandler = (
options: StartOptions,
initialOptions: PartialDeep<StartOptions>,
options: RequiredDeep<StartOptions>,
initialOptions: StartOptions,
) => StartReturnType
export type StopHandler = () => void

Expand All @@ -193,7 +193,7 @@ export interface SetupWorkerApi {
* Registers and activates the mock Service Worker.
* @see {@link https://mswjs.io/docs/api/setup-worker/start `worker.start()`}
*/
start: (options?: PartialDeep<StartOptions>) => StartReturnType
start: (options?: StartOptions) => StartReturnType

/**
* Stops requests interception for the current client.
Expand Down
3 changes: 1 addition & 2 deletions src/setupWorker/start/utils/prepareStartHandler.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { PartialDeep } from 'type-fest'
import { SetupWorkerInternalContext, StartOptions } from '../../glossary'
import {
DEFAULT_START_OPTIONS,
Expand Down Expand Up @@ -39,7 +38,7 @@ describe('prepareStartHandler', () => {
const startHandler = prepareStartHandler(createStartHandler, context)
expect(startHandler).toBeInstanceOf(Function)

const initialOptions: PartialDeep<StartOptions> = {
const initialOptions: StartOptions = {
quiet: true,
serviceWorker: {
url: './custom.js',
Expand Down
13 changes: 8 additions & 5 deletions src/setupWorker/start/utils/prepareStartHandler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PartialDeep } from 'type-fest'
import { RequiredDeep } from '../../../typeUtils'
import { mergeRight } from '../../../utils/internal/mergeRight'
import {
SetupWorkerApi,
Expand All @@ -7,7 +7,7 @@ import {
StartOptions,
} from '../../glossary'

export const DEFAULT_START_OPTIONS: StartOptions = {
export const DEFAULT_START_OPTIONS: RequiredDeep<StartOptions> = {
serviceWorker: {
url: '/mockServiceWorker.js',
options: null as any,
Expand All @@ -25,9 +25,12 @@ export const DEFAULT_START_OPTIONS: StartOptions = {
* with the given custom options.
*/
export function resolveStartOptions(
initialOptions?: PartialDeep<StartOptions>,
): StartOptions {
return mergeRight(DEFAULT_START_OPTIONS, initialOptions || {}) as StartOptions
initialOptions?: StartOptions,
): RequiredDeep<StartOptions> {
return mergeRight(
DEFAULT_START_OPTIONS,
initialOptions || {},
) as RequiredDeep<StartOptions>
}

export function prepareStartHandler(
Expand Down
2 changes: 1 addition & 1 deletion src/sharedOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface SharedOptions {
* @example worker.start({ onUnhandledRequest: 'warn' })
* @example server.listen({ onUnhandledRequest: 'error' })
*/
onUnhandledRequest: UnhandledRequestStrategy
onUnhandledRequest?: UnhandledRequestStrategy
}

export interface LifeCycleEventsMap<ResponseType> {
Expand Down
22 changes: 14 additions & 8 deletions src/typeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ import { ResponseTransformer } from './response'

type Fn = (...arg: any[]) => any

export type DeepRequired<
T,
U extends Record<string, any> | Fn | undefined = undefined,
> = T extends Record<string, any>
export type RequiredDeep<
Type,
U extends Record<string, unknown> | Fn | undefined = undefined,
> = Type extends Fn
? Type
: /**
* @note The "Fn" type satisfies the predicate below.
* It must always come first, before the Record check.
*/
Type extends Record<string, any>
? {
[P in keyof T]-?: NonNullable<T[P]> extends NonNullable<U | Fn>
? NonNullable<T[P]>
: DeepRequired<NonNullable<T[P]>, U>
[Key in keyof Type]-?: NonNullable<Type[Key]> extends NonNullable<U>
? NonNullable<Type[Key]>
: RequiredDeep<NonNullable<Type[Key]>, U>
}
: T
: Type

export type GraphQLPayloadContext<QueryType extends Record<string, unknown>> = (
payload: QueryType,
Expand Down
3 changes: 2 additions & 1 deletion src/utils/handleRequest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { rest } from '../rest'
import { handleRequest } from './handleRequest'
import { response } from '../response'
import { context } from '..'
import { RequiredDeep } from '../typeUtils'

const emitter = new StrictEventEmitter<ServerLifecycleEventsMap>()
const listener = jest.fn()
Expand All @@ -20,7 +21,7 @@ function getEmittedEvents() {
return listener.mock.calls
}

const options: SharedOptions = {
const options: RequiredDeep<SharedOptions> = {
onUnhandledRequest: jest.fn(),
}
const callbacks = {
Expand Down
Loading

0 comments on commit a3e27e7

Please sign in to comment.