Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: basic mock #37

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 4 additions & 21 deletions src/converters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parse, print } from "https://esm.sh/v90/[email protected]";
import { generateMockData, getDefaultTypeValue, MockResponse } from "./mock.ts";
import { Argument, ObjectField, Outrospection, Query } from "./outrospector.ts";

export interface FormattedArgument {
Expand All @@ -18,33 +19,14 @@ export interface FormattedQuery {
fullQuery: string;
variables: string;
outrospectQuery: Query;
mockResponse: MockResponse;
}

export interface QueryCollection {
queries: FormattedQuery[];
mutations: FormattedQuery[];
}

// @TODO: rework this
function getDefaultValue(type: string) {
switch (type) {
case "ID":
return `"0"`;
case "STRING" || "String":
return `""`;
case "INT" || "Int":
return `0`;
case "FLOAT":
return `0.0`;
case "BOOLEAN":
return `false`;
case "INPUT_OBJECT":
return `{}`;
default:
return `null`;
}
}

function nestedArgToString(arg: Argument, argStr?: string): string {
if (!argStr) argStr = arg.typeName;
if (arg.nesting.length === 0) {
Expand All @@ -64,7 +46,7 @@ function formatArgument(arg: Argument): FormattedArgument {
const formattedType: string = nestedArgToString(arg);

const defaultNonNullValue = formattedType
.replace(arg.typeName, getDefaultValue(arg.typeName))
.replace(arg.typeName, String(getDefaultTypeValue(arg.typeName)))
.replaceAll("!", "");
const defaultValue = formattedType.includes("!")
? defaultNonNullValue
Expand Down Expand Up @@ -152,6 +134,7 @@ function formatQuery(
fullQuery: "",
variables: "",
outrospectQuery: query,
mockResponse: generateMockData(query, outrospection),
};

Array.from(query.args).forEach(([_, arg], index) => {
Expand Down
110 changes: 67 additions & 43 deletions src/format.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
import { FormattedQuery, QueryCollection } from "./converters.ts";

export interface PostmanItem {
name: string;
request: {
method: string;
header: {
key: string;
value: string;
}[];
body: {
mode: string;
graphql: {
query: string;
variables: string;
};
};
url: {
raw: string;
protocol: string;
host: string[];
path: string[];
interface PostmanRequest {
method: string;
header: {
key: string;
value: string;
}[];
body: {
mode: string;
graphql: {
query: string;
variables: string;
};
};
response: null[];
url: {
raw: string;
protocol: string;
host: string[];
path: string[];
};
}

interface PostmanResponse {
name: string;
originalRequest: PostmanRequest;
body: string;
header: null[];
cookie: null[];
_postman_previewlanguage: "json";
status: "OK";
code: 200;
}
export interface PostmanItem {
name: string;
request: PostmanRequest;
response: (PostmanResponse | null)[];
}

export interface PostmanFolder {
Expand All @@ -49,30 +61,42 @@ function queryToItem(
const host = [...rootUrl.split(".")];
const protocol = url.split("://")[0];

const postmanItem: PostmanItem = {
name: query.outrospectQuery.name,
request: {
method: "POST",
header: [
...(authorization
? [{ key: "Authorization", value: authorization }]
: []),
],
body: {
mode: "graphql",
graphql: {
query: query.fullQuery,
variables: query.variables,
},
},
url: {
raw: url,
protocol,
host,
path,
const request: PostmanRequest = {
method: "POST",
header: [
...(authorization
? [{ key: "Authorization", value: authorization }]
: []),
],
body: {
mode: "graphql",
graphql: {
query: query.fullQuery,
variables: query.variables,
},
},
response: [],
url: {
raw: url,
protocol,
host,
path,
},
};

const postmanItem: PostmanItem = {
name: query.outrospectQuery.name,
request: request,
response: [{
name: query.outrospectQuery.name,
originalRequest: request,
body: JSON.stringify(query.mockResponse, null, 2),
//body: query.mockResponse,
header: [],
cookie: [],
_postman_previewlanguage: "json",
status: "OK",
code: 200,
}],
};

return postmanItem;
Expand Down
66 changes: 66 additions & 0 deletions src/mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// The goal of this module is to generate fake data for types, for variables and mock responses

import { Outrospection, Query } from "./outrospector.ts";

const defaultValues = {
ID: "1",
String: "",
STRING: "",
Int: 0,
INT: 0,
Float: 0.0,
FLOAT: 0.0,
Boolean: false,
BOOLEAN: false,
INPUT_OBJECT: {},
OBJECT: {},
};

const defaultScalarValue = "1";

export function getDefaultTypeValue(typeName: string) {
return Object(defaultValues)[typeName] ?? null;
}

export interface MockResponse {
data: {
// deno-lint-ignore no-explicit-any
[key: string]: any;
};
}

export function generateMockData(
query: Query,
outrospection: Outrospection,
): MockResponse {
const mockData = new Map<string, string>();

const type = outrospection.types.get(query.typeName);
if (!type) {
throw new Error(`Type ${query.typeName} not found in outrospection`);
}

if (type.kind === "OBJECT") {
type.fields?.forEach((field) => {
mockData.set(field.name, getDefaultTypeValue(field.typeName));
});
} else if (type.kind === "SCALAR") {
mockData.set(type.name, defaultScalarValue);
} else {
//@TODO: handle other types if needed
mockData.set(
"notImplemented",
`Mock data for return type ${type.kind} is not implemented yet`,
);
}

const mock = {
data: {
[query.name]: {
"__typename": query.typeName,
...Object.fromEntries(mockData),
},
},
};
return mock;
}
2 changes: 1 addition & 1 deletion src/outrospector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { getQueryAndMutationTypes } from "./lib.ts";

// @TODO add real support for "INTERFACE" | "UNION" | "INPUT_OBJECT"
type TypeBaseKind =
export type TypeBaseKind =
| "LIST"
| "NON_NULL"
| "SCALAR"
Expand Down