gQuery/codegen/codegen.ts

148 lines
4.3 KiB
TypeScript
Raw Normal View History

2021-10-06 21:41:44 +00:00
import type { CodegenPlugin } from "@graphql-codegen/plugin-helpers";
import {
LoadedFragment,
ClientSideBaseVisitor,
} from "@graphql-codegen/visitor-plugin-common";
import {
concatAST,
FragmentDefinitionNode,
Kind,
OperationDefinitionNode,
visit,
} from "graphql";
import { pascalCase } from "pascal-case";
2021-09-30 16:19:53 +00:00
module.exports = {
2021-10-06 21:41:44 +00:00
plugin: (schema, documents, config) => {
const allAst = concatAST(documents.map((d) => d.document));
2021-09-30 16:19:53 +00:00
const allFragments: LoadedFragment[] = [
2021-10-06 21:41:44 +00:00
...(
allAst.definitions.filter(
(d) => d.kind === Kind.FRAGMENT_DEFINITION
) as FragmentDefinitionNode[]
).map((fragmentDef) => ({
node: fragmentDef,
name: fragmentDef.name.value,
onType: fragmentDef.typeCondition.name.value,
isExternal: false,
})),
2021-09-30 16:19:53 +00:00
...(config.externalFragments || []),
2021-10-06 21:41:44 +00:00
];
2021-09-30 16:19:53 +00:00
2021-10-06 21:41:44 +00:00
const visitor = new ClientSideBaseVisitor(
2021-09-30 16:19:53 +00:00
schema,
allFragments,
{},
2021-10-06 21:41:44 +00:00
{ documentVariableSuffix: "Doc" },
2021-09-30 16:19:53 +00:00
documents
2021-10-06 21:41:44 +00:00
);
const visitorResult = visit(allAst, { leave: visitor });
2021-09-30 16:19:53 +00:00
const operations = allAst.definitions.filter(
(d) => d.kind === Kind.OPERATION_DEFINITION
2021-10-06 21:41:44 +00:00
) as OperationDefinitionNode[];
2021-09-30 16:19:53 +00:00
const defaultTypes = `
type FetchWrapperArgs<T> = {
fetch: typeof fetch,
variables?: T,
}
type SubscribeWrapperArgs<T> = {
variables?: T,
}
2021-10-06 21:41:44 +00:00
`;
2021-09-30 16:19:53 +00:00
const ops = operations
.map((o) => {
if (o) {
2021-10-06 21:41:44 +00:00
const name = o?.name?.value || "";
2021-09-30 16:19:53 +00:00
// const dsl = `export const ${pascalCase(op.name.value)}Doc = gql\`
// ${documents.find((d) => d.rawSDL.includes(`${op.operation} ${op.name.value}`)).rawSDL}\``
2021-10-06 21:41:44 +00:00
const op = `${pascalCase(name)}${pascalCase(o.operation)}`;
const opv = `${op}Variables`;
let operations = "";
2021-09-30 16:19:53 +00:00
2021-10-06 21:41:44 +00:00
if (o.operation === "query") {
2021-09-30 16:19:53 +00:00
operations += `
2021-10-06 21:41:44 +00:00
export const ${name} = ({ variables, fetch}: FetchWrapperArgs<${opv}>):
Promise<GFetchReturnWithErrors<${op}>> =>
2021-09-30 16:19:53 +00:00
g.fetch<${op}>({
queries: [{ query: ${pascalCase(name)}Doc, variables }],
fetch
})
2021-10-06 21:41:44 +00:00
`;
2021-09-30 16:19:53 +00:00
// If config is set to have subscription query, also write the
if (config.subscriptionQuery) {
operations += `
2021-10-06 21:41:44 +00:00
export const ${name}Subscribe = ({ variables }: SubscribeWrapperArgs<${opv}>):
Readable<GFetchReturnWithErrors<${op}>> =>
2021-09-30 16:19:53 +00:00
g.oFetch<${op}>({
queries: [{ query: ${pascalCase(name)}Doc, variables }]
})
2021-10-06 21:41:44 +00:00
`;
2021-09-30 16:19:53 +00:00
}
2021-10-06 21:41:44 +00:00
} else if (o.operation === "mutation") {
2021-09-30 16:19:53 +00:00
operations += `
2021-10-06 21:41:44 +00:00
export const ${name} = ({ variables }: SubscribeWrapperArgs<${opv}>):
Promise<GFetchReturnWithErrors<${op}>> =>
2021-09-30 16:19:53 +00:00
g.fetch<${op}>({
queries: [{ query: ${pascalCase(name)}Doc, variables }],
fetch,
})
2021-10-06 21:41:44 +00:00
`;
2021-09-30 16:19:53 +00:00
}
2021-10-06 21:41:44 +00:00
return operations;
2021-09-30 16:19:53 +00:00
}
})
2021-10-06 21:41:44 +00:00
.join("\n");
2021-09-30 16:19:53 +00:00
2021-10-06 21:41:44 +00:00
const imports = [
2021-09-30 16:19:53 +00:00
`import type { Readable } from "svelte/store"`,
`import { g } from '${config.gFetchPath}'`,
`import type { GFetchReturnWithErrors } from '$graphql/gfetchLib'`,
`import gql from "graphql-tag"`,
2021-10-06 21:41:44 +00:00
];
2021-09-30 16:19:53 +00:00
// let schemaInputs = getCachedDocumentNodeFromSchema(schema).definitions.filter((d) => {
// return d.kind === 'InputObjectTypeDefinition'
// })
// let inputs = schemaInputs
// .map((d) => {
// console.log('/* START */')
// // @ts-ignore
// console.log('NAME: ', d.fields[0].name.value)
// // @ts-ignore
// let isReq = d.fields[0]?.type?.kind === 'NonNullType'
// console.log('REQUIRED: ', isReq ? '✅' : '❌')
// // @ts-ignore
// console.log('TYPE: ', isReq ? d.fields[0]?.type?.type?.name?.value : d.fields[0]?.type?.name?.value)
// // @ts-ignore
// // @ts-ignore
// console.log('d.fields[0]', d.fields[0]?.type)
// console.log('/* END */')
// console.log('')
// return `
// const inputName = {
// ${d.fields[0].name.value}: ${isReq ? d.fields[0]?.type?.type?.name?.value : d.fields[0]?.type?.name?.value}
// }
// `
// })
// .join('\n')
// console.log('inputs', inputs)
return {
prepend: imports,
content: [
defaultTypes,
visitor.fragments,
2021-10-06 21:41:44 +00:00
...visitorResult.definitions.filter((t) => typeof t == "string"),
2021-09-30 16:19:53 +00:00
ops,
2021-10-06 21:41:44 +00:00
].join("\n"),
};
2021-09-30 16:19:53 +00:00
},
2021-10-06 21:41:44 +00:00
} as CodegenPlugin;