diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4ed75c34..00000000 --- a/.editorconfig +++ /dev/null @@ -1,7 +0,0 @@ -root = true - -[*.{js,sql,md}] -indent_style = space -indent_size = 2 -max_line_length = 120 -quote_type = single diff --git a/.eslintrc b/.eslintrc index 04889ec5..08d000ca 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,11 @@ { - "extends": ["airbnb-base"], + "plugins": [ + 'jest', + 'prettier' + ], + "extends": ["airbnb-base", 'prettier'], "rules": { + "prettier/prettier": "error", "no-console": "off", "global-require": "off", "no-plusplus": "off" diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..eea92b34 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,6 @@ +module.exports = { + trailingComma: "all", + singleQuote: true, + printWidth: 120, + tabWidth: 2 +}; diff --git a/generateModule.js b/generateModule.js index 4bc541f9..9a259d27 100755 --- a/generateModule.js +++ b/generateModule.js @@ -2,7 +2,7 @@ const finder = require('find-package-json'); const shelljs = require('shelljs'); const { Source, buildSchema } = require('graphql'); -const path = require("path"); +const path = require('path'); const getModuleInfos = require('./parse-graphql/getModuleInfos'); const getModuleNames = require('./parse-graphql/getModuleNames'); @@ -18,16 +18,16 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const projectMainPath = f .next() .filename.split('/') - .filter((c) => c.indexOf('package.json') == -1) + .filter((c) => c.indexOf('package.json') === -1) .join('/'); - shelljs.mkdir('-p', `${projectMainPath}/generated/graphql`); + shelljs.mkdir('-p', `${projectMainPath}/generated/graphql/helpers`); // "Framework" "generated" files - initial generation const createCombineSchemas = () => { const templateName = './templates/combineSchemas.ts'; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `combineSchemas.ts`; + const fileName = 'combineSchemas.ts'; saveRenderedTemplate(templateName, {}, filePath, fileName); }; @@ -37,7 +37,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createPrintSchema = () => { const templateName = './templates/printSchema.ts'; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `printSchema.ts`; + const fileName = 'printSchema.ts'; saveRenderedTemplate(templateName, {}, filePath, fileName); }; @@ -47,7 +47,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createGenericDataModelSchema = () => { const templateName = './templates/genericDataModelSchema.graphql'; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `genericDataModelSchema.graphql`; + const fileName = 'genericDataModelSchema.graphql'; saveRenderedTemplate(templateName, {}, filePath, fileName); }; @@ -57,7 +57,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createFrameworkSchema = () => { const templateName = './templates/frameworkSchema.graphql'; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `frameworkSchema.graphql`; + const fileName = 'frameworkSchema.graphql'; saveRenderedTemplate(templateName, {}, filePath, fileName); }; @@ -67,13 +67,13 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createGetCodegenConfig = () => { const templateName = './templates/getCodegenConfig.js'; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `getCodegenConfig.js`; + const fileName = 'getCodegenConfig.js'; saveRenderedTemplate(templateName, { appPrefix }, filePath, fileName); }; createGetCodegenConfig(); - const modulesResolvedPath = path.join(projectMainPath, modulesPath) + const modulesResolvedPath = path.join(projectMainPath, modulesPath); const graphqlPaths = shelljs.ls(`${modulesResolvedPath}**/*.graphql`); const moduleNames = getModuleNames(graphqlPaths, projectMainPath); @@ -83,7 +83,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const templateName = './templates/resolvers.handlebars'; const context = { modules }; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `resolvers.ts`; + const fileName = 'resolvers.ts'; saveRenderedTemplate(templateName, context, filePath, fileName); }; @@ -93,7 +93,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath // Initial App Setup files - const { stdout: schemaString, stderr } = shelljs.exec('ts-node ./generated/graphql/printSchema.ts', { + const { stdout: globalSchemaString, stderr } = shelljs.exec('ts-node ./generated/graphql/printSchema.ts', { cwd: projectMainPath, silent: true, }); @@ -104,9 +104,9 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createGlobalSchema = () => { const templateName = './templates/schema.ts'; - const context = { modules, schemaString, generatedPrefix }; + const context = { modules, schemaString: globalSchemaString, generatedPrefix }; const filePath = `${projectMainPath}/generated/graphql/`; - const fileName = `schema.ts`; + const fileName = 'schema.ts'; saveRenderedTemplate(templateName, context, filePath, fileName); }; @@ -117,7 +117,12 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const { graphqlFileRootPath } = module; const createQuery = (queryName, hasArguments) => { const templateName = './templates/query.handlebars'; - const context = { queryName, moduleName, hasArguments, generatedPrefix }; + const context = { + queryName, + moduleName, + hasArguments, + generatedPrefix, + }; const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/queries/`; const fileName = `${queryName}Query.ts`; const keepIfExists = true; @@ -126,24 +131,51 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createQuerySpec = (queryName, hasArguments) => { const templateName = './templates/query.spec.handlebars'; - const context = { queryName, moduleName, hasArguments, generatedPrefix }; + const context = { + queryName, + moduleName, + hasArguments, + generatedPrefix, + }; const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/queries/`; const fileName = `${queryName}Query.spec.ts`; const keepIfExists = true; saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); }; + const createQuerySpecWrapper = (queryName, hasArguments) => { + const templateName = './templates/querySpecWrapper.handlebars'; + const context = { + queryName, + moduleName, + hasArguments, + generatedPrefix, + appPrefix, + graphqlFileRootPath, + }; + const filePath = `${projectMainPath}/generated/graphql/helpers/`; + const fileName = `${queryName}QuerySpecWrapper.ts`; + const keepIfExists = false; + saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); + }; + if (module.queries && module.queries.length) { shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/queries`); - module.queries.forEach(({ name, hasArguments, variables }) => { + module.queries.forEach(({ name, hasArguments }) => { createQuery(name, hasArguments); createQuerySpec(name, hasArguments); + createQuerySpecWrapper(name, hasArguments); }); } const createMutation = (mutationName, hasArguments) => { const templateName = './templates/mutation.handlebars'; - const context = { mutationName, moduleName, hasArguments, generatedPrefix }; + const context = { + mutationName, + moduleName, + hasArguments, + generatedPrefix, + }; const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/mutations/`; const fileName = `${mutationName}Mutation.ts`; const keepIfExists = true; @@ -152,36 +184,63 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createMutationSpec = (mutationName, hasArguments) => { const templateName = './templates/mutation.spec.handlebars'; - const context = { mutationName, moduleName, hasArguments, generatedPrefix }; + const context = { + mutationName, + moduleName, + hasArguments, + generatedPrefix, + appPrefix, + graphqlFileRootPath, + }; const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/mutations/`; const fileName = `${mutationName}Mutation.spec.ts`; const keepIfExists = true; saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); }; + const createMutationSpecWrapper = (mutationName, hasArguments) => { + const templateName = './templates/mutationSpecWrapper.handlebars'; + const context = { + mutationName, + moduleName, + hasArguments, + generatedPrefix, + appPrefix, + graphqlFileRootPath, + }; + const filePath = `${projectMainPath}/generated/graphql/helpers/`; + + const fileName = `${mutationName}MutationSpecWrapper.ts`; + const keepIfExists = false; + saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); + }; + if (module.mutations && module.mutations.length) { shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/mutations`); - module.mutations.forEach(({ name, hasArguments, variables }) => { + module.mutations.forEach(({ name, hasArguments }) => { createMutation(name, hasArguments); createMutationSpec(name, hasArguments); + createMutationSpecWrapper(name, hasArguments); }); } }); const createTypeResolvers = () => { modules.forEach(({ name, typeDefinitions, types, schemaString, queries, mutations, graphqlFileRootPath }) => { - let typeResolvers = []; + const typeResolvers = []; if (types) { const federatedEntities = getFederatedEntities(schemaString); const interfaces = getInterfaces(schemaString); - schemaString = schemaString.replace(/extend type/g, `type`); - let source = new Source(schemaString); - let schema = buildSchema(source); + // Leaving this for now + // eslint-disable-next-line no-param-reassign + schemaString = schemaString.replace(/extend type/g, 'type'); + const source = new Source(schemaString); + const schema = buildSchema(source); shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/types/`); const createInterfaceType = (interfaceName) => { const templateName = './templates/typeTypeResolvers.handlebars'; - let capitalizedFieldName = capitalize('__resolveType'); + const capitalizedFieldName = capitalize('__resolveType'); const context = { typeName: interfaceName, fieldName: '__resolveType', @@ -199,7 +258,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const createInterfaceSpec = (interfaceName) => { const templateName = './templates/typeTypeResolvers.spec.handlebars'; - let capitalizedFieldName = capitalize('__resolveType'); + const capitalizedFieldName = capitalize('__resolveType'); const context = { typeName: interfaceName, fieldName: '__resolveType', @@ -215,9 +274,31 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); }; + + const createInterfaceSpecWrapper = (interfaceName) => { + const templateName = './templates/typeTypeResolversSpecWrapper.handlebars'; + const capitalizedFieldName = capitalize('__resolveType'); + const context = { + typeName: interfaceName, + fieldName: '__resolveType', + moduleName: name, + hasArguments: false, + resolveReferenceType: true, + capitalizedFieldName, + generatedPrefix, + appPrefix, + graphqlFileRootPath, + }; + const filePath = `${projectMainPath}/generated/graphql/helpers/`; + const fileName = `${interfaceName}${capitalizedFieldName}SpecWrapper.ts`; + const keepIfExists = false; + + saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); + }; interfaces.forEach((interfaceName) => { createInterfaceType(interfaceName); createInterfaceSpec(interfaceName); + createInterfaceSpecWrapper(interfaceName); typeResolvers.push({ typeName: interfaceName, fieldName: [{ name: '__resolveType', capitalizedName: capitalize('__resolveType') }], @@ -228,15 +309,13 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath let type = schema.getType(typeDef.name); if (!type) { const newSchemaString = schemaString.replace(`extend type ${typeDef.name}`, `type ${typeDef.name}`); - let source = new Source(newSchemaString); - let schema = buildSchema(source); - type = schema.getType(typeDef.name); + type = buildSchema(new Source(newSchemaString)).getType(typeDef.name); } if (type.astNode) { - filtered = type.astNode.fields.filter((f) => - f.directives.find( - (d) => d.name.value === 'computed' || d.name.value === 'link' || d.name.value === 'requires' - ) + filtered = type.astNode.fields.filter((field) => + field.directives.find( + (d) => d.name.value === 'computed' || d.name.value === 'link' || d.name.value === 'requires', + ), ); } @@ -246,7 +325,7 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath filtered.forEach(({ name: { value }, resolveReferenceType }) => { const templateName = './templates/typeTypeResolvers.handlebars'; - let capitalizedFieldName = capitalize(value); + const capitalizedFieldName = capitalize(value); const context = { typeName: typeDef.name, fieldName: value, @@ -262,14 +341,14 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); }); - filtered.forEach(({ name: { value }, arguments, resolveReferenceType }) => { + const createTypeFieldResolverSpec = (value, resolveReferenceType, resolverArguments) => { const templateName = './templates/typeTypeResolvers.spec.handlebars'; - let capitalizedFieldName = capitalize(value); + const capitalizedFieldName = capitalize(value); const context = { typeName: typeDef.name, fieldName: value, moduleName: name, - hasArguments: arguments && arguments.length, + hasArguments: resolverArguments && resolverArguments.length, resolveReferenceType, capitalizedFieldName, generatedPrefix, @@ -279,6 +358,31 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const keepIfExists = true; saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); + }; + const createTypeFieldResolverSpecWrapper = (value, resolveReferenceType, resolverArguments) => { + const templateName = './templates/typeTypeResolversSpecWrapper.handlebars'; + const capitalizedFieldName = capitalize(value); + const context = { + typeName: typeDef.name, + fieldName: value, + moduleName: name, + hasArguments: resolverArguments && resolverArguments.length, + resolveReferenceType, + capitalizedFieldName, + generatedPrefix, + appPrefix, + graphqlFileRootPath, + }; + const filePath = `${projectMainPath}/generated/graphql/helpers/`; + const fileName = `${typeDef.name}${capitalizedFieldName}SpecWrapper.ts`; + const keepIfExists = true; + + saveRenderedTemplate(templateName, context, filePath, fileName, keepIfExists); + }; + + filtered.forEach(({ name: { value }, arguments: resolverArguments, resolveReferenceType }) => { + createTypeFieldResolverSpec(value, resolveReferenceType, resolverArguments); + createTypeFieldResolverSpecWrapper(value, resolveReferenceType, resolverArguments); }); if (filtered.length) { @@ -292,7 +396,14 @@ const execute = (appPrefix = '@app', generatedPrefix = '@generated', modulesPath const moduleName = name; const createModuleResolvers = () => { const templateName = './templates/moduleResolvers.handlebars'; - const context = { moduleName, queries, mutations, typeResolvers, graphqlFileRootPath, appPrefix }; + const context = { + moduleName, + queries, + mutations, + typeResolvers, + graphqlFileRootPath, + appPrefix, + }; const filePath = `${projectMainPath}/generated/graphql/`; const fileName = `${moduleName}Resolvers.ts`; saveRenderedTemplate(templateName, context, filePath, fileName); diff --git a/package-lock.json b/package-lock.json index cbeae134..0dfd6288 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1949,6 +1949,22 @@ } } }, + "@typescript-eslint/scope-manager": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.14.0.tgz", + "integrity": "sha512-/J+LlRMdbPh4RdL4hfP1eCwHN5bAhFAGOTsvE6SxsrM/47XQiPSgF5MDgLyp/i9kbZV9Lx80DW0OpPkzL+uf8Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.0", + "@typescript-eslint/visitor-keys": "4.14.0" + } + }, + "@typescript-eslint/types": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.14.0.tgz", + "integrity": "sha512-VsQE4VvpldHrTFuVPY1ZnHn/Txw6cZGjL48e+iBxTi2ksa9DmebKjAeFmTVAYoSkTk7gjA7UqJ7pIsyifTsI4A==", + "dev": true + }, "@typescript-eslint/typescript-estree": { "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", @@ -1998,6 +2014,24 @@ } } }, + "@typescript-eslint/visitor-keys": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.0.tgz", + "integrity": "sha512-MeHHzUyRI50DuiPgV9+LxcM52FCJFYjJiWHtXlbyC27b80mfOwKeiKI+MHOTEpcpfmoPFm/vvQS88bYIx6PZTA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.0", + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + } + } + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -3493,6 +3527,12 @@ "object.entries": "^1.0.4" } }, + "eslint-config-prettier": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", + "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "dev": true + }, "eslint-import-resolver-node": { "version": "0.3.2", "resolved": "http://registry.npm.taobao.org/eslint-import-resolver-node/download/eslint-import-resolver-node-0.3.2.tgz", @@ -3613,6 +3653,113 @@ } } }, + "eslint-plugin-jest": { + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz", + "integrity": "sha512-dNGGjzuEzCE3d5EPZQ/QGtmlMotqnYWD/QpCZ1UuZlrMAdhG5rldh0N0haCvhGnUkSeuORS5VNROwF9Hrgn3Lg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^4.0.1" + }, + "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.0.tgz", + "integrity": "sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.14.0", + "@typescript-eslint/types": "4.14.0", + "@typescript-eslint/typescript-estree": "4.14.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.0.tgz", + "integrity": "sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.0", + "@typescript-eslint/visitor-keys": "4.14.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-restricted-globals": { "version": "0.1.1", "resolved": "http://registry.npm.taobao.org/eslint-restricted-globals/download/eslint-restricted-globals-0.1.1.tgz", @@ -3914,6 +4061,12 @@ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", @@ -11418,11 +11571,20 @@ "dev": true }, "prettier": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", - "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "pretty-format": { "version": "26.0.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.0.1.tgz", diff --git a/package.json b/package.json index a726fe74..e7b05880 100644 --- a/package.json +++ b/package.json @@ -41,13 +41,16 @@ "@typescript-eslint/parser": "^2.29.0", "eslint": "^5.5.0", "eslint-config-airbnb-base": "^13.1.0", + "eslint-config-prettier": "^7.2.0", "eslint-import-resolver-typescript": "^2.3.0", "eslint-plugin-import": "^2.14.0", + "eslint-plugin-jest": "^24.1.3", + "eslint-plugin-prettier": "^3.3.1", "jest": "^26.0.1", - "prettier": "^2.0.5", + "prettier": "^2.2.1", + "semantic-release": "^17.1.1", "testdouble": "^3.15.0", - "testdouble-jest": "^2.0.0", - "semantic-release": "^17.1.1" + "testdouble-jest": "^2.0.0" }, "jest": { "testPathIgnorePatterns": [ diff --git a/templates/mutation.spec.handlebars b/templates/mutation.spec.handlebars index 3fcb8c93..98e71d18 100644 --- a/templates/mutation.spec.handlebars +++ b/templates/mutation.spec.handlebars @@ -1,20 +1,16 @@ import td from "testdouble"; -import { GqlContext, {{#if hasArguments}}Mutation{{toUpperCase mutationName}}Args{{/if}} } from "{{generatedPrefix}}/graphql/types"; -import { {{mutationName}}Mutation } from "./{{mutationName}}Mutation"; -const test{{mutationName}} = ({{#if hasArguments}}variables: Mutation{{toUpperCase mutationName}}Args, {{/if}}context: GqlContext) => {{mutationName}}Mutation({}, {{#if hasArguments}}variables{{else}} {} {{/if}}, context, null) +import { GqlContext, {{#if hasArguments}}Mutation{{toUpperCase mutationName}}Args,{{/if}} test{{toUpperCase mutationName}} } from "{{generatedPrefix}}/graphql/helpers/{{mutationName}}MutationSpecWrapper" test("{{mutationName}}", async () => { const context = td.object(); - // td.when(context.{{moduleName}}Repository.findOne()).thenResolve() - {{#if hasArguments}} const variables: Mutation{{toUpperCase mutationName}}Args = {} {{/if}} - const result = await test{{mutationName}}({{#if hasArguments}}variables,{{/if}} context); + const result = await test{{toUpperCase mutationName}}({{#if hasArguments}}variables,{{/if}} context); }); diff --git a/templates/mutationSpecWrapper.handlebars b/templates/mutationSpecWrapper.handlebars new file mode 100644 index 00000000..dd6d3860 --- /dev/null +++ b/templates/mutationSpecWrapper.handlebars @@ -0,0 +1,7 @@ +import { GraphQLResolveInfo } from 'graphql' +import { GqlContext, {{#if hasArguments}}Mutation{{toUpperCase mutationName}}Args{{/if}} } from "{{generatedPrefix}}/graphql/types"; +import { {{mutationName}}Mutation } from "{{appPrefix}}/{{graphqlFileRootPath}}mutations/{{mutationName}}Mutation"; + +export const test{{toUpperCase mutationName}} = ({{#if hasArguments}}variables: Mutation{{toUpperCase mutationName}}Args, {{/if}}context: GqlContext) => {{mutationName}}Mutation?.({}, {{#if hasArguments}}variables{{else}} {} {{/if}}, context, {} as GraphQLResolveInfo) + +export type {GqlContext, {{#if hasArguments}}Mutation{{toUpperCase mutationName}}Args{{/if}} } diff --git a/templates/query.spec.handlebars b/templates/query.spec.handlebars index dbcbcf6e..5e0c3128 100644 --- a/templates/query.spec.handlebars +++ b/templates/query.spec.handlebars @@ -1,10 +1,5 @@ import td from "testdouble"; -import { GqlContext, {{#if hasArguments}}Query{{toUpperCase queryName}}Args{{/if}} } from "{{generatedPrefix}}/graphql/types"; -import { {{queryName}}Query } from "./{{queryName}}Query"; - - -const test{{queryName}} = ({{#if hasArguments}}variables: Query{{toUpperCase queryName}}Args,{{/if}} context: GqlContext) => {{queryName}}Query({}, {{#if hasArguments}}variables{{else}} {} {{/if}}, context, null) - +import { GqlContext, {{#if hasArguments}}Query{{toUpperCase queryName}}Args,{{/if}} test{{toUpperCase queryName}} } from "{{generatedPrefix}}/graphql/helpers/{{queryName}}QuerySpecWrapper" test("{{queryName}}", async () => { @@ -16,6 +11,6 @@ test("{{queryName}}", async () => { const variables: Query{{toUpperCase queryName}}Args = {} {{/if}} - const result = await test{{queryName}}({{#if hasArguments}}variables,{{/if}} context); + const result = await test{{toUpperCase queryName}}({{#if hasArguments}}variables,{{/if}} context); }); diff --git a/templates/querySpecWrapper.handlebars b/templates/querySpecWrapper.handlebars new file mode 100644 index 00000000..6f88f654 --- /dev/null +++ b/templates/querySpecWrapper.handlebars @@ -0,0 +1,9 @@ +import { GraphQLResolveInfo } from 'graphql' +import { GqlContext, {{#if hasArguments}}Query{{toUpperCase queryName}}Args{{/if}} } from "{{generatedPrefix}}/graphql/types"; +import { {{queryName}}Query } from "{{appPrefix}}/{{graphqlFileRootPath}}queries/{{queryName}}Query"; + + +export const test{{toUpperCase queryName}} = ({{#if hasArguments}}variables: Query{{toUpperCase queryName}}Args,{{/if}} context: GqlContext) => {{queryName}}Query?.({}, {{#if hasArguments}}variables{{else}} {} {{/if}}, context, {} as GraphQLResolveInfo) + + +export type {GqlContext, {{#if hasArguments}}Query{{toUpperCase queryName}}Args{{/if}} } diff --git a/templates/typeTypeResolvers.spec.handlebars b/templates/typeTypeResolvers.spec.handlebars index ddb9c5e4..710f3313 100644 --- a/templates/typeTypeResolvers.spec.handlebars +++ b/templates/typeTypeResolvers.spec.handlebars @@ -1,22 +1,12 @@ import td from "testdouble"; - -import { GqlContext, ResolversParentTypes, {{#if hasArguments}}{{typeName}}{{capitalizedFieldName}}Args{{/if}} } from "{{generatedPrefix}}/graphql/types"; -import { {{typeName}}{{capitalizedFieldName}} } from "./{{typeName}}{{capitalizedFieldName}}"; - -{{#if resolveReferenceType}}type ParentType = Parameters[0];{{/if}} - - const test{{typeName}}{{capitalizedFieldName}} = (parent: {{#if resolveReferenceType}}ParentType{{else}}ResolversParentTypes["{{typeName}}"]{{/if}}, {{#if hasArguments}}variables: {{typeName}}{{capitalizedFieldName}}Args,{{/if}} context: GqlContext) => {{typeName}}{{capitalizedFieldName}}(parent, {{#unless resolveReferenceType}}{{#if hasArguments}}variables{{else}} {} {{/if}},{{/unless}} context, null) - +import { GqlContext, ResolversParentTypes, test{{typeName}}{{capitalizedFieldName}} } from "{{generatedPrefix}}/graphql/helpers/{{typeName}}{{capitalizedFieldName}}SpecWrapper" test("{{typeName}}{{capitalizedFieldName}}", async () => { - const context = td.object(); - // td.when(context.{{moduleName}}Repository.findOne()).thenResolve() - - const parent{{#if resolveReferenceType}} = {} as ParentType {{else}}: ResolversParentTypes["{{typeName}}"] = {}{{/if}} + const parent{{#if resolveReferenceType}} = {} as ParentType {{else}} = {} as ResolversParentTypes["{{typeName}}"]{{/if}} {{#if hasArguments}} - const variables: {{typeName}}{{capitalizedFieldName}}Args = {} + const variables = {} as {{typeName}}{{capitalizedFieldName}}Args {{/if}} const result = await test{{typeName}}{{capitalizedFieldName}}(parent, {{#if hasArguments}}variables,{{/if}} context); diff --git a/templates/typeTypeResolversSpecWrapper.handlebars b/templates/typeTypeResolversSpecWrapper.handlebars new file mode 100644 index 00000000..806c847d --- /dev/null +++ b/templates/typeTypeResolversSpecWrapper.handlebars @@ -0,0 +1,9 @@ +import { GraphQLResolveInfo } from 'graphql' +import type { GqlContext, ResolversParentTypes, {{#if hasArguments}}{{typeName}}{{capitalizedFieldName}}Args{{/if}} } from "{{generatedPrefix}}/graphql/types"; +import { {{typeName}}{{capitalizedFieldName}} } from "{{appPrefix}}/{{graphqlFileRootPath}}types/{{typeName}}{{capitalizedFieldName}}"; + +{{#if resolveReferenceType}}type ParentType = Parameters[0];{{/if}} + +export const test{{typeName}}{{capitalizedFieldName}} = (parent: {{#if resolveReferenceType}}ParentType{{else}}ResolversParentTypes["{{typeName}}"]{{/if}}, {{#if hasArguments}}variables: {{typeName}}{{capitalizedFieldName}}Args,{{/if}} context: GqlContext) => {{typeName}}{{capitalizedFieldName}}?.({...parent, __typename: '{{typeName}}'}, {{#unless resolveReferenceType}}{{#if hasArguments}}variables{{else}} {} {{/if}},{{/unless}} context, {} as GraphQLResolveInfo) + +export type {GqlContext, ResolversParentTypes}