Skip to content

Commit

Permalink
Merge pull request #69 from kenneth-gray/refactor
Browse files Browse the repository at this point in the history
refactor: refactor
  • Loading branch information
kenneth-gray authored Feb 4, 2023
2 parents 9c83ad6 + 70db9b2 commit 12870b1
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 147 deletions.
2 changes: 1 addition & 1 deletion src/create-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const DEFAULT_STATUS = 200;
const DEFAULT_DELAY = 0;

function createHandler<TInput, TResponse>({
response = { status: DEFAULT_STATUS, delay: DEFAULT_DELAY },
response = {},
updateContext,
getContext,
}: ResponseProps<TInput, TResponse> & {
Expand Down
241 changes: 118 additions & 123 deletions src/graph-ql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Result,
} from './types';

export { getGraphQlMocks, getGraphQlMock, createGraphQlRequestHandler };
export { getGraphQlMocks, getGraphQlMock, graphQlRequestHandler };

type GraphQlHandler = (req: {
operationType: 'query' | 'mutation';
Expand Down Expand Up @@ -77,105 +77,106 @@ function createGraphQlHandler({
};
}

function createInternalGraphQlRequestHandler(handlers: GraphQlHandler[]) {
return async (req: InternalRequest) => {
const query =
req.headers['content-type'] === 'application/graphql'
? req.body
: req.body.query || req.query.query || '';
async function internalGraphQlRequestHandler(
req: InternalRequest,
handlers: GraphQlHandler[],
) {
const query =
req.headers['content-type'] === 'application/graphql'
? req.body
: req.body.query || req.query.query || '';

let graphqlAst;
try {
graphqlAst = gql(query);
} catch (error) {
const result = {
status: 400,
headers: {
'Content-Type': 'application/json',
},
response: { message: `query "${query}" is not a valid GraphQL query` },
};

let graphqlAst;
try {
graphqlAst = gql(query);
} catch (error) {
const result = {
status: 400,
headers: {
'Content-Type': 'application/json',
},
response: { message: `query "${query}" is not a valid GraphQL query` },
};

return result;
}

const operationTypesAndNames = (graphqlAst.definitions as Array<{
kind: string;
operation: 'query' | 'mutation';
name?: { value: string };
}>)
.filter(({ kind }) => kind === 'OperationDefinition')
.map(({ operation, name }) => ({
type: operation,
name: name && name.value,
}));

if (
operationTypesAndNames.length > 1 &&
!req.body.operationName &&
!req.query.operationName
) {
const result = {
status: 400,
headers: {
'Content-Type': 'application/json',
},
response: {
message: `query "${query}" is not a valid GraphQL query`,
},
};
return result;
}

const operationTypesAndNames = (graphqlAst.definitions as Array<{
kind: string;
operation: 'query' | 'mutation';
name?: { value: string };
}>)
.filter(({ kind }) => kind === 'OperationDefinition')
.map(({ operation, name }) => ({
type: operation,
name: name && name.value,
}));

if (
operationTypesAndNames.length > 1 &&
!req.body.operationName &&
!req.query.operationName
) {
const result = {
status: 400,
headers: {
'Content-Type': 'application/json',
},
response: {
message: `query "${query}" is not a valid GraphQL query`,
},
};

return result;
}
return result;
}

const operationName: string =
req.body.operationName ||
req.query.operationName ||
operationTypesAndNames[0].name ||
'';

const operationTypeAndName = operationTypesAndNames.find(
({ name }) => name === operationName,
);

if (!operationTypeAndName) {
const result = {
status: 400,
headers: {
'Content-Type': 'application/json',
},
response: {
message: `operation name "${operationName}" does not exist in GraphQL query`,
},
};

const operationName: string =
req.body.operationName ||
req.query.operationName ||
operationTypesAndNames[0].name ||
'';
return result;
}

const operationTypeAndName = operationTypesAndNames.find(
({ name }) => name === operationName,
);
const operationType = operationTypeAndName.type;

if (!operationTypeAndName) {
const result = {
status: 400,
headers: {
'Content-Type': 'application/json',
},
response: {
message: `operation name "${operationName}" does not exist in GraphQL query`,
},
};
let variables = req.body.variables;
if (variables === undefined && req.query.variables) {
try {
variables = JSON.parse(req.query.variables);
} catch (error) {}
}
variables = variables || {};

for (const handler of handlers) {
const result = await handler({
operationType,
operationName,
variables,
});

if (result) {
return result;
}
}

const operationType = operationTypeAndName.type;

let variables = req.body.variables;
if (variables === undefined && req.query.variables) {
try {
variables = JSON.parse(req.query.variables);
} catch (error) {}
}
variables = variables || {};

for (const handler of handlers) {
const result = await handler({
operationType,
operationName,
variables,
});

if (result) {
return result;
}
}

return { status: 404 };
};
return { status: 404 };
}

function getGraphQlMock(path: string, graphqlMocks: GraphQlMock[]) {
Expand Down Expand Up @@ -222,47 +223,41 @@ function getMutations({
);
}

function createGraphQlRequestHandler({
function graphQlRequestHandler({
req,
graphQlMock,
updateContext,
getContext,
}: {
req: InternalRequest;
graphQlMock: GraphQlMock;
updateContext: UpdateContext;
getContext: GetContext;
}): (req: InternalRequest) => Promise<Result> {
return req => {
if (req.method === 'GET') {
const queries = getQueries({
graphQlMock,
updateContext,
getContext,
});
}): Promise<Result> {
if (req.method === 'GET') {
const queries = getQueries({
graphQlMock,
updateContext,
getContext,
});

const requestHandler = createInternalGraphQlRequestHandler(queries);
return internalGraphQlRequestHandler(req, queries);
}

return requestHandler(req);
}

if (req.method === 'POST') {
const queries = getQueries({
graphQlMock,
updateContext,
getContext,
});
const mutations = getMutations({
graphQlMock,
updateContext,
getContext,
});
if (req.method === 'POST') {
const queries = getQueries({
graphQlMock,
updateContext,
getContext,
});
const mutations = getMutations({
graphQlMock,
updateContext,
getContext,
});

const requestHandler = createInternalGraphQlRequestHandler(
queries.concat(mutations),
);
return internalGraphQlRequestHandler(req, queries.concat(mutations));
}

return requestHandler(req);
}

return Promise.resolve({ status: 404 });
};
return Promise.resolve({ status: 404 });
}
18 changes: 6 additions & 12 deletions src/handle-request.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import {
getGraphQlMocks,
getGraphQlMock,
createGraphQlRequestHandler,
graphQlRequestHandler,
} from './graph-ql';
import {
getHttpMocks,
getHttpMockAndParams,
createHttpRequestHandler,
} from './http';
import { getHttpMocks, getHttpMockAndParams, httpRequestHandler } from './http';
import {
Mock,
ScenarioMap,
Expand Down Expand Up @@ -121,24 +117,22 @@ async function handleRequest({
let result: Result = { status: 404 };

if (graphQlMock) {
const requestHandler = createGraphQlRequestHandler({
result = await graphQlRequestHandler({
req,
graphQlMock,
updateContext: localUpdateContext,
getContext,
});

result = await requestHandler(req);
} else {
const { httpMock, params } = getHttpMockAndParams(req, httpMocks);
if (httpMock) {
const requestHandler = createHttpRequestHandler({
result = await httpRequestHandler({
req,
httpMock,
params,
getContext,
updateContext: localUpdateContext,
});

result = await requestHandler(req);
}
}

Expand Down
22 changes: 11 additions & 11 deletions src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
InternalRequest,
} from './types';

export { getHttpMocks, getHttpMockAndParams, createHttpRequestHandler };
export { getHttpMocks, getHttpMockAndParams, httpRequestHandler };

function getHttpMocks(mocks: Mock[]) {
const initialHttpMocks = mocks.filter(
Expand All @@ -29,26 +29,26 @@ function getHttpMocks(mocks: Mock[]) {
return Object.values(httpMocksByUrlAndMethod);
}

function createHttpRequestHandler({
function httpRequestHandler({
req,
httpMock,
params,
updateContext,
getContext,
}: {
req: InternalRequest;
httpMock: HttpMock;
params: Record<string, any>;
updateContext: UpdateContext;
getContext: GetContext;
}) {
return (req: InternalRequest) => {
const handler = createHandler({
...httpMock,
getContext,
updateContext,
});

return handler({ ...req, params });
};
const handler = createHandler({
...httpMock,
getContext,
updateContext,
});

return handler({ ...req, params });
}

function getHttpMockAndParams(req: InternalRequest, httpMocks: HttpMock[]) {
Expand Down

0 comments on commit 12870b1

Please sign in to comment.