From c015b02a1aa50e4d760c3fd59f76dc5dfe587664 Mon Sep 17 00:00:00 2001 From: Gil Gardosh Date: Tue, 10 Jan 2023 14:50:58 +0200 Subject: [PATCH] prettier (#4930) run full prettier add prettier to pre-commit and CI --- .changeset/clever-walls-press.md | 81 ++++ .eslintrc.json | 14 +- .github/ISSUE_TEMPLATE/bug_report.md | 12 +- .github/ISSUE_TEMPLATE/config.yml | 4 +- .github/PULL_REQUEST_TEMPLATE.md | 22 +- .github/workflows/tests.yml | 7 + .github/workflows/website.yml | 7 +- .husky/pre-commit | 1 + .prettierignore | 1 + README.md | 34 +- examples/auth0/privateAPI.ts | 2 +- .../frontend/README.md | 39 +- .../frontend/src/index.css | 4 +- .../frontend/src/index.tsx | 2 +- examples/grpc-example/start-server.ts | 7 +- .../grpc-reflection-example/start-server.ts | 7 +- examples/hive-example/.gitignore | 1 - .../hive-example/sources/authors/openapi.yaml | 1 - examples/json-schema-covid/README.md | 10 +- .../scripts/download-fhir-schema.ts | 4 +- examples/json-schema-subscriptions/README.md | 9 +- examples/mongoose-example/src/models.js | 4 +- .../tests/mysql-employees.test.js | 2 +- examples/mysql-rfam/tests/mysql-rfam.test.js | 2 +- examples/nextjs-apollo-example/README.md | 27 +- .../nextjs-apollo-example/server/server.ts | 4 +- .../nextjs-apollo-example/styles/globals.css | 4 +- examples/nextjs-sdk-example/README.md | 27 +- .../nextjs-sdk-example/styles/globals.css | 4 +- examples/odata-microsoft/README.md | 15 +- examples/odata-microsoft/public/index.html | 10 +- .../src/index.ts | 2 +- examples/odata-msgraph-programmatic/index.js | 2 +- .../additional-resolvers.ts | 2 +- .../openapi-location-weather/.meshrc.yaml | 1 - examples/openapi-location-weather/README.md | 4 +- .../openapi-react-weatherbit/src/index.css | 4 +- .../openapi-react-weatherbit/src/index.tsx | 2 +- .../src/serviceWorker.ts | 11 +- .../test/openapi-stackexchange.test.ts | 5 +- .../tests/openapi-subscriptions.test.ts | 14 +- examples/openapi-youtrack/README.md | 10 +- examples/openwhisk-example/README.md | 18 +- examples/openwhisk-example/src/index.ts | 2 +- examples/postgres-geodb/README.md | 21 +- .../tests/soap-country-info.spec.ts | 5 +- .../tests/sqlite-chinook.test.js | 2 +- .../src/codegen/AddRequest.ts | 22 +- .../src/codegen/Calculator.ts | 168 ++++--- .../tests/thrift-calculator.test.ts | 2 +- .../author-service-schema.ts | 3 +- package.json | 1 + packages/apollo-link/src/index.ts | 5 +- packages/apollo-link/test/apollo-link.test.ts | 4 +- .../localforage/src/InMemoryLRUDriver.ts | 8 +- packages/cache/localforage/src/index.ts | 2 +- packages/cache/redis/src/index.ts | 7 +- packages/cache/redis/test/cache.spec.ts | 6 +- .../cli/src/commands/generate-operations.ts | 12 +- packages/cli/src/config.ts | 10 +- .../src/getAdditionalResolversFromTypeDefs.ts | 17 +- packages/config/src/process.ts | 24 +- packages/config/src/utils.ts | 32 +- packages/cross-helpers/browser.js | 2 +- packages/cross-helpers/react-native.js | 7 +- packages/handlers/graphql/src/index.ts | 56 ++- .../handlers/graphql/test/handler.spec.ts | 16 +- packages/handlers/mysql/src/mysql.d.ts | 16 +- packages/handlers/mysql/src/promisify.ts | 15 +- packages/handlers/postgraphile/src/index.ts | 23 +- packages/handlers/soap/src/index.ts | 13 +- packages/handlers/thrift/src/index.ts | 89 +++- packages/handlers/thrift/test/handler.spec.ts | 5 +- packages/handlers/tuql/src/index.ts | 8 +- packages/jit-executor/src/index.ts | 10 +- .../json-machete/src/compareJSONSchemas.ts | 28 +- .../json-machete/src/dereferenceObject.ts | 5 +- .../json-machete/src/referenceJSONSchema.ts | 7 +- packages/json-machete/src/visitJSONSchema.ts | 22 +- .../tests/dereferenceObject.test.ts | 19 +- packages/loaders/README.md | 29 +- .../json-schema/src/getValidTypeName.ts | 4 +- packages/loaders/json-schema/src/utils.ts | 6 +- packages/loaders/openapi/src/utils.ts | 5 +- .../loaders/openapi/tests/calendly.test.ts | 8 +- .../openapi/tests/example_api6_server.ts | 9 +- .../openapi/tests/example_api7_server.ts | 10 +- .../loaders/openapi/tests/explode.test.ts | 2 +- .../openapi/tests/fixtures/calendly.yml | 341 ++++++++++---- .../fixtures/government_social_work.json | 9 +- .../openapi/tests/fixtures/kubernetes.json | 14 +- .../openapi/tests/fixtures/stripe.json | 433 ++++++++++++++++-- .../loaders/openapi/tests/fixtures/toto.yml | 4 +- .../uk_teachers_training_courses.json | 6 +- .../tests/fixtures/weather_underground.json | 25 +- packages/loaders/raml/README.md | 4 +- packages/loaders/soap/test/examples.test.ts | 5 +- packages/mergers/bare/src/index.ts | 18 +- packages/mergers/federation/src/index.ts | 31 +- .../tests/useDeduplicateRequest.test.ts | 26 +- packages/plugins/hive/src/index.ts | 5 +- packages/plugins/http-cache/src/index.ts | 15 +- .../http-details-extensions/src/index.ts | 4 +- packages/plugins/live-query/src/index.ts | 17 +- .../live-query/src/useInvalidateByResult.ts | 14 +- packages/plugins/mock/src/index.ts | 58 ++- packages/plugins/mock/tests/mocking.spec.ts | 25 +- packages/plugins/mock/tests/mocks.ts | 15 +- .../operation-field-permissions/src/index.ts | 4 +- packages/plugins/prometheus/src/index.ts | 8 +- packages/plugins/response-cache/src/index.ts | 40 +- packages/plugins/snapshot/src/index.ts | 16 +- packages/plugins/statsd/src/index.ts | 6 +- packages/runtime/src/types.ts | 6 +- packages/runtime/src/useSubschema.ts | 18 +- packages/runtime/test/getMesh.test.ts | 13 +- packages/runtime/test/useSubschema.test.ts | 2 +- packages/store/src/index.ts | 27 +- packages/store/test/mesh-store.spec.ts | 4 +- packages/string-interpolation/src/index.ts | 7 +- .../src/modifiers/title.js | 3 +- .../src/resolver-data-factory.ts | 21 +- packages/transforms/encapsulate/src/index.ts | 45 +- packages/transforms/extend/src/index.ts | 4 +- packages/transforms/federation/src/index.ts | 21 +- .../filter-schema/src/bareFilter.ts | 10 +- .../filter-schema/src/wrapFilter.ts | 51 ++- .../filter-schema/test/transform.spec.ts | 40 +- packages/transforms/hive/src/index.ts | 4 +- packages/transforms/hoist-field/src/index.ts | 51 ++- .../src/bareNamingConvention.ts | 89 ++-- .../transforms/naming-convention/src/index.ts | 6 +- .../src/wrapNamingConvention.ts | 61 ++- packages/transforms/prefix/src/barePrefix.ts | 2 +- packages/transforms/prefix/src/index.ts | 4 +- packages/transforms/prefix/src/wrapPrefix.ts | 45 +- packages/transforms/rate-limit/src/index.ts | 11 +- packages/transforms/rename/src/bareRename.ts | 73 ++- packages/transforms/rename/src/wrapRename.ts | 47 +- .../transforms/replace-field/src/index.ts | 28 +- .../resolvers-composition/src/index.ts | 10 +- packages/transforms/type-merging/src/index.ts | 7 +- packages/urql/src/index.ts | 21 +- packages/urql/test/urql-exchange.test.ts | 4 +- packages/utils/src/apply-transforms.ts | 16 +- packages/utils/src/fs-operations.ts | 4 +- packages/utils/src/getHeadersObj.ts | 2 +- .../src/load-from-module-export-expression.ts | 6 +- packages/utils/src/logger.ts | 6 +- packages/utils/src/pubsub.ts | 4 +- packages/utils/src/read-file-or-url.ts | 25 +- .../utils/src/resolve-additional-resolvers.ts | 102 +++-- packages/utils/src/with-cancel.ts | 5 +- packages/utils/src/with-filter.ts | 15 +- scripts/fix-bin.js | 2 +- website/README.md | 15 +- website/next.config.mjs | 6 +- website/src/pages/docs/cache/cfwKv.mdx | 6 +- website/src/pages/docs/cache/localforage.mdx | 6 +- website/src/pages/docs/cli-commands.mdx | 24 +- website/src/pages/docs/config-reference.mdx | 31 +- .../combine-multiple-sources.mdx | 136 ++++-- .../pages/docs/getting-started/comparison.mdx | 6 +- .../getting-started/customize-mesh-server.mdx | 20 +- .../getting-started/deploy-mesh-gateway.mdx | 82 ++-- .../docs/getting-started/installation.mdx | 9 +- .../pages/docs/getting-started/overview.mdx | 13 +- .../sources-with-no-definition.mdx | 67 ++- .../your-first-mesh-gateway.mdx | 100 ++-- website/src/pages/docs/guides/auth0.mdx | 86 ++-- website/src/pages/docs/guides/batching.mdx | 17 +- .../src/pages/docs/guides/error-masking.mdx | 10 +- .../docs/guides/extending-unified-schema.mdx | 38 +- .../src/pages/docs/guides/file-uploads.mdx | 12 +- .../docs/guides/graphql-code-generator.mdx | 6 +- website/src/pages/docs/guides/headers.mdx | 20 +- website/src/pages/docs/guides/hive.mdx | 38 +- website/src/pages/docs/guides/mesh-sdk.mdx | 19 +- .../docs/guides/monitoring-and-tracing.mdx | 18 +- .../docs/guides/subscriptions-webhooks.mdx | 15 +- website/src/pages/docs/handlers/graphql.mdx | 37 +- website/src/pages/docs/handlers/grpc.mdx | 3 +- .../src/pages/docs/handlers/json-schema.mdx | 32 +- website/src/pages/docs/handlers/mysql.mdx | 13 +- website/src/pages/docs/handlers/neo4j.mdx | 3 +- website/src/pages/docs/handlers/openapi.mdx | 68 ++- .../src/pages/docs/handlers/postgraphile.mdx | 29 +- website/src/pages/docs/handlers/soap.mdx | 3 +- website/src/pages/docs/handlers/thrift.mdx | 3 +- website/src/pages/docs/handlers/tuql.mdx | 3 +- website/src/pages/docs/index.mdx | 27 +- .../docs/migration/new-openapi-to-openapi.mdx | 10 +- .../docs/migration/openapi-0.31-0.32.mdx | 51 ++- website/src/pages/docs/plugins/http-cache.mdx | 10 +- .../docs/plugins/http-details-extensions.mdx | 3 +- .../src/pages/docs/plugins/live-queries.mdx | 23 +- website/src/pages/docs/plugins/mock.mdx | 20 +- website/src/pages/docs/plugins/new-relic.mdx | 10 +- .../plugins/operation-field-permissions.mdx | 9 +- .../docs/plugins/plugins-introduction.mdx | 28 +- website/src/pages/docs/plugins/prometheus.mdx | 8 +- website/src/pages/docs/plugins/rate-limit.mdx | 3 +- .../pages/docs/plugins/response-caching.mdx | 25 +- website/src/pages/docs/plugins/snapshot.mdx | 7 +- website/src/pages/docs/plugins/statsd.mdx | 3 +- .../src/pages/docs/transforms/encapsulate.mdx | 6 +- website/src/pages/docs/transforms/extend.mdx | 21 +- .../src/pages/docs/transforms/federation.mdx | 5 +- .../pages/docs/transforms/filter-schema.mdx | 8 +- website/src/pages/docs/transforms/hoist.mdx | 7 +- .../docs/transforms/naming-convention.mdx | 8 +- website/src/pages/docs/transforms/prefix.mdx | 8 +- website/src/pages/docs/transforms/rename.mdx | 13 +- .../pages/docs/transforms/replace-field.mdx | 114 +++-- .../transforms/transforms-introduction.mdx | 151 +++--- .../pages/docs/transforms/type-merging.mdx | 18 +- yarn.lock | 66 ++- 217 files changed, 3549 insertions(+), 1382 deletions(-) create mode 100644 .changeset/clever-walls-press.md diff --git a/.changeset/clever-walls-press.md b/.changeset/clever-walls-press.md new file mode 100644 index 0000000000000..9e3ba4e9a09e1 --- /dev/null +++ b/.changeset/clever-walls-press.md @@ -0,0 +1,81 @@ +--- +'frontend': patch +'@graphql-mesh/plugin-operation-field-permissions': patch +'@graphql-mesh/transform-resolvers-composition': patch +'@graphql-mesh/plugin-http-details-extensions': patch +'odata-msgraph-programmatic-ts': patch +'type-merging-batching-example': patch +'authors-service': patch +'@graphql-mesh/transform-naming-convention': patch +'graphql-file-upload-example': patch +'@graphql-mesh/plugin-deduplicate-request': patch +'odata-msgraph-programmatic': patch +'json-schema-subscriptions': patch +'typescript-location-weather-example': patch +'openapi-react-weatherbit': patch +'@graphql-mesh/transform-filter-schema': patch +'@graphql-mesh/transform-replace-field': patch +'javascript-wiki': patch +'@graphql-mesh/transform-type-merging': patch +'@graphql-mesh/plugin-response-cache': patch +'@graphql-mesh/transform-encapsulate': patch +'@graphql-mesh/transform-hoist-field': patch +'nextjs-apollo-example': patch +'openapi-stackexchange': patch +'openapi-subscriptions': patch +'@graphql-mesh/postgraphile': patch +'@graphql-mesh/transform-federation': patch +'@graphql-mesh/transform-rate-limit': patch +'@graphql-mesh/string-interpolation': patch +'@omnigraph/json-schema': patch +'nextjs-sdk-example': patch +'@graphql-mesh/merger-federation': patch +'@graphql-mesh/plugin-http-cache': patch +'@graphql-mesh/plugin-live-query': patch +'@graphql-mesh/plugin-prometheus': patch +'covid-mesh': patch +'openwhisk-example': patch +'country-info-example': patch +'thrift-calculator': patch +'@graphql-mesh/cache-localforage': patch +'@graphql-mesh/transform-extend': patch +'@graphql-mesh/transform-prefix': patch +'@graphql-mesh/transform-rename': patch +'mongoose-example': patch +'openapi-youtrack': patch +'@graphql-mesh/graphql': patch +'@graphql-mesh/plugin-snapshot': patch +'mysql-employees': patch +'odata-microsoft-graph-example': patch +'@graphql-mesh/thrift': patch +'@omnigraph/openapi': patch +'@graphql-mesh/transform-hive': patch +'postgres-geodb-example': patch +'chinook': patch +'@graphql-mesh/mysql': patch +'@graphql-mesh/plugin-statsd': patch +'odata-trippin-example': patch +'@graphql-mesh/cross-helpers': patch +'@graphql-mesh/soap': patch +'@graphql-mesh/tuql': patch +'@graphql-mesh/jit-executor': patch +'json-machete': patch +'@omnigraph/raml': patch +'@omnigraph/soap': patch +'@graphql-mesh/merger-bare': patch +'@graphql-mesh/plugin-hive': patch +'@graphql-mesh/plugin-mock': patch +'@graphql-mesh/apollo-link': patch +'@graphql-mesh/cache-redis': patch +'mysql-rfam': patch +'@graphql-mesh/runtime': patch +'@graphql-mesh/config': patch +'auth0-example': patch +'@graphql-mesh/store': patch +'@graphql-mesh/types': patch +'@graphql-mesh/utils': patch +'@graphql-mesh/urql-exchange': patch +'@graphql-mesh/cli': patch +--- + +Prettier fixes diff --git a/.eslintrc.json b/.eslintrc.json index 094adbf9908a9..bfe9904ae1633 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,12 @@ "parserOptions": { "project": "./tsconfig.json" }, - "extends": ["eslint:recommended", "standard", "prettier", "plugin:@typescript-eslint/recommended"], + "extends": [ + "eslint:recommended", + "standard", + "prettier", + "plugin:@typescript-eslint/recommended" + ], "plugins": ["@typescript-eslint"], "rules": { "no-empty": "off", @@ -28,7 +33,10 @@ "import/no-nodejs-modules": "error", "no-eval": "off", "no-use-before-define": "off", - "import/no-extraneous-dependencies": ["error", { "devDependencies": ["**/*.test.ts", "**/*.spec.ts"] }] + "import/no-extraneous-dependencies": [ + "error", + { "devDependencies": ["**/*.test.ts", "**/*.spec.ts"] } + ] }, "env": { "es6": true, @@ -45,7 +53,7 @@ } } ], - "ignorePatterns": ["dist", "node_modules", "examples", "website", "scripts"], + "ignorePatterns": ["dist", "node_modules", "examples", "website", "scripts", ".bob"], "globals": { "BigInt": true } diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9e537b877fc8c..8c6d4d128e721 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,9 +7,14 @@ about: Create a bug report to help us improve -_Progress of the issue based on the [Contributor Workflow](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md#a-typical-contributor-workflow)_ +_Progress of the issue based on the +[Contributor Workflow](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md#a-typical-contributor-workflow)_ -- [ ] 1. The issue provides a reproduction available on [Github](https://github.com/Urigo/graphql-mesh/tree/master/examples/hello-world), [Stackblitz](https://stackblitz.com/github/Urigo/graphql-mesh/tree/master/examples/hello-world) or [CodeSandbox](https://codesandbox.io/s/github/Urigo/graphql-mesh/tree/master/examples/hello-world) +- [ ] 1. The issue provides a reproduction available on + [Github](https://github.com/Urigo/graphql-mesh/tree/master/examples/hello-world), + [Stackblitz](https://stackblitz.com/github/Urigo/graphql-mesh/tree/master/examples/hello-world) + or + [CodeSandbox](https://codesandbox.io/s/github/Urigo/graphql-mesh/tree/master/examples/hello-world) > Make sure to fork this template and run `yarn generate` in the terminal. > @@ -25,8 +30,7 @@ _Progress of the issue based on the [Contributor Workflow](https://github.com/th -**To Reproduce** -Steps to reproduce the behavior: +**To Reproduce** Steps to reproduce the behavior: diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 4867decdecd16..aae65e0b8bfc3 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,4 +2,6 @@ blank_issues_enabled: false contact_links: - name: Have a question? url: https://github.com/Urigo/graphql-mesh/discussions/new - about: Not sure about something? need help from the community? have a question to our team? please ask and answer questions here. + about: + Not sure about something? need help from the community? have a question to our team? please + ask and answer questions here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 40f0b1feaef8b..8995e4493728e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,12 @@ 🚨 **IMPORTANT: Please do not create a Pull Request without creating an issue first.** -_Any change needs to be discussed before proceeding. Failure to do so may result in the rejection of the pull request._ +_Any change needs to be discussed before proceeding. Failure to do so may result in the rejection of +the pull request._ ## Description -Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. +Please include a summary of the change and which issue is fixed. Please also include relevant +motivation and context. List any dependencies that are required for this change. Fixes # (issue) @@ -14,16 +16,19 @@ Please delete options that are not relevant. - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as + expected) - [ ] This change requires a documentation update ## Screenshots/Sandbox (if appropriate/relevant): -Adding links to sandbox or providing screenshots can help us understand more about this PR and take action on it as appropriate +Adding links to sandbox or providing screenshots can help us understand more about this PR and take +action on it as appropriate ## How Has This Been Tested? -Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration +Please describe the tests that you ran to verify your changes. Provide instructions so we can +reproduce. Please also list any relevant details for your test configuration - [ ] Test A - [ ] Test B @@ -36,7 +41,9 @@ Please describe the tests that you ran to verify your changes. Provide instructi ## Checklist: -- [ ] I have followed the [CONTRIBUTING](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md) doc and the style guidelines of this project +- [ ] I have followed the + [CONTRIBUTING](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md) doc and the + style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation @@ -47,4 +54,5 @@ Please describe the tests that you ran to verify your changes. Provide instructi ## Further comments -If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... +If this is a relatively large or complex change, kick off the discussion by explaining why you chose +the solution you did and what alternatives you considered, etc... diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0b288c4672cc8..4a4a341456a81 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,6 +15,13 @@ jobs: secrets: githubToken: ${{ secrets.GITHUB_TOKEN }} + prettier: + uses: the-guild-org/shared-config/.github/workflows/prettier.yml@main + with: + script: yarn ci:prettier + secrets: + githubToken: ${{ secrets.GITHUB_TOKEN }} + test: name: ${{matrix.os}} / node ${{matrix.node-version}} timeout-minutes: 60 diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 8c3deb3a0d806..f318594d92914 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -11,7 +11,9 @@ on: jobs: deployment: runs-on: ubuntu-latest - if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push' + if: + github.event.pull_request.head.repo.full_name == github.repository || github.event_name == + 'push' steps: - name: checkout uses: actions/checkout@v3 @@ -28,7 +30,8 @@ jobs: name: build and deploy website env: NEXT_BASE_PATH: ${{ github.ref == 'refs/heads/master' && '/graphql/mesh' || '' }} - SITE_URL: ${{ github.ref == 'refs/heads/master' && 'https://the-guild.dev/graphql/mesh' || '' }} + SITE_URL: + ${{ github.ref == 'refs/heads/master' && 'https://the-guild.dev/graphql/mesh' || '' }} NEXT_PUBLIC_ALGOLIA_INDEX_NAME: ${{ secrets.NEXT_PUBLIC_ALGOLIA_INDEX_NAME }} NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY: ${{ secrets.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY }} NEXT_PUBLIC_ALGOLIA_APP_ID: ${{ secrets.NEXT_PUBLIC_ALGOLIA_APP_ID }} diff --git a/.husky/pre-commit b/.husky/pre-commit index d2ae35e84b09c..51dcfe62ac988 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,5 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" +yarn pretty-quick --staged yarn lint-staged diff --git a/.prettierignore b/.prettierignore index 21992fe293982..63ded79da74a4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,4 @@ dist/ .mesh/ /.husky/_/ +.bob/ diff --git a/README.md b/README.md index 7fd3af965de60..4744fef3f78f1 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,24 @@ https://www.graphql-mesh.com -GraphQL Mesh allows you to use GraphQL query language to access data in remote APIs that don't run GraphQL (and also ones that do run GraphQL). -It can be used as a gateway to other services or run as a local GraphQL schema that aggregates data from remote APIs. +GraphQL Mesh allows you to use GraphQL query language to access data in remote APIs that don't run +GraphQL (and also ones that do run GraphQL). It can be used as a gateway to other services or run as +a local GraphQL schema that aggregates data from remote APIs. -The goal of GraphQL Mesh is to let developers easily access services that are written in other APIs specs (such as gRPC, OpenAPI/Swagger, OData, SOAP/WSDL, Apache Thrift, Mongoose, PostgreSQL, Neo4j, and also GraphQL) with GraphQL queries and mutations. +The goal of GraphQL Mesh is to let developers easily access services that are written in other APIs +specs (such as gRPC, OpenAPI/Swagger, OData, SOAP/WSDL, Apache Thrift, Mongoose, PostgreSQL, Neo4j, +and also GraphQL) with GraphQL queries and mutations. -GraphQL Mesh gives the developer the ability to modify the output schemas, link types across schemas and merge schema types. You can even add custom GraphQL types and resolvers that fit your needs. +GraphQL Mesh gives the developer the ability to modify the output schemas, link types across schemas +and merge schema types. You can even add custom GraphQL types and resolvers that fit your needs. -It allows developers to control the way they fetch data, and overcome issues related to backend implementation, legacy API services, chosen schema specification and non-typed APIs. +It allows developers to control the way they fetch data, and overcome issues related to backend +implementation, legacy API services, chosen schema specification and non-typed APIs. -GraphQL Mesh is acting as a proxy to your data, and uses common libraries to wrap your existing API services. You can use this proxy locally in your service or application by running the GraphQL schema locally (with GraphQL `execute`), or you can deploy this as a gateway layer to your internal service. +GraphQL Mesh is acting as a proxy to your data, and uses common libraries to wrap your existing API +services. You can use this proxy locally in your service or application by running the GraphQL +schema locally (with GraphQL `execute`), or you can deploy this as a gateway layer to your internal +service. ## How does it work? @@ -42,7 +50,8 @@ To get started with the basics, install the following: $ yarn add graphql @graphql-mesh/runtime @graphql-mesh/cli ``` -Then, you need to install a Mesh handler, according to your API needs. You can see the list of all available built-in handlers in this README, under the `Supported APIs` section. +Then, you need to install a Mesh handler, according to your API needs. You can see the list of all +available built-in handlers in this README, under the `Supported APIs` section. For example, if you wish to use OpenAPI handler, install the handler that matches your needs: @@ -63,13 +72,18 @@ Then, this handler will be available for you to use in your config file. ## Contributions -Contributions, issues and feature requests are very welcome. If you are using this package and fixed a bug for yourself, please consider submitting a PR! +Contributions, issues and feature requests are very welcome. If you are using this package and fixed +a bug for yourself, please consider submitting a PR! -And if this is your first time contributing to this project, please do read our [Contributor Workflow Guide](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md) before you get started off. +And if this is your first time contributing to this project, please do read our +[Contributor Workflow Guide](https://github.com/the-guild-org/Stack/blob/master/CONTRIBUTING.md) +before you get started off. ### Code of Conduct -Help us keep GraphQL Mesh open and inclusive. Please read and follow our [Code of Conduct](https://github.com/the-guild-org/Stack/blob/master/CODE_OF_CONDUCT.md) as adopted from [Contributor Covenant](https://www.contributor-covenant.org/) +Help us keep GraphQL Mesh open and inclusive. Please read and follow our +[Code of Conduct](https://github.com/the-guild-org/Stack/blob/master/CODE_OF_CONDUCT.md) as adopted +from [Contributor Covenant](https://www.contributor-covenant.org/) ### License diff --git a/examples/auth0/privateAPI.ts b/examples/auth0/privateAPI.ts index 50451e5fea05f..c1b6fd89d9b95 100644 --- a/examples/auth0/privateAPI.ts +++ b/examples/auth0/privateAPI.ts @@ -7,7 +7,7 @@ http JSON.stringify({ code: 'I am a secret code', timestamp: Date.now(), - }) + }), ); }) .listen(3001, 'localhost', () => { diff --git a/examples/graphql-file-upload-example/frontend/README.md b/examples/graphql-file-upload-example/frontend/README.md index 02aac3f6ea17c..a460c41225704 100644 --- a/examples/graphql-file-upload-example/frontend/README.md +++ b/examples/graphql-file-upload-example/frontend/README.md @@ -17,7 +17,8 @@ You will also see any lint errors in the console. ### `yarn test` Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) +for more information. ### `yarn build` @@ -27,44 +28,58 @@ It correctly bundles React in production mode and optimizes the build for the be The build is minified and the filenames include the hashes.\ Your app is ready to be deployed! -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for +more information. ### `yarn eject` **Note: this is a one-way operation. Once you `eject`, you can’t go back!** -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. +This command will remove the single build dependency from your project. -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, +ESLint, etc) right into your project so you have full control over them. All of the commands except +`eject` will still work, but they will point to the copied scripts so you can tweak them. At this +point you’re on your own. -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle +deployments, and you shouldn’t feel obligated to use this feature. However we understand that this +tool wouldn’t be useful if you couldn’t customize it when you are ready for it. ## Learn More -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). +You can learn more in the +[Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). To learn React, check out the [React documentation](https://reactjs.org/). ### Code Splitting -This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) +This section has moved here: +[https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) ### Analyzing the Bundle Size -This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) +This section has moved here: +[https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) ### Making a Progressive Web App -This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) +This section has moved here: +[https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) ### Advanced Configuration -This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) +This section has moved here: +[https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) ### Deployment -This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) +This section has moved here: +[https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) ### `yarn build` fails to minify -This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) +This section has moved here: +[https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) diff --git a/examples/graphql-file-upload-example/frontend/src/index.css b/examples/graphql-file-upload-example/frontend/src/index.css index 7323ae85c542d..89e57c7ccfe1f 100644 --- a/examples/graphql-file-upload-example/frontend/src/index.css +++ b/examples/graphql-file-upload-example/frontend/src/index.css @@ -1,7 +1,7 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', - 'Droid Sans', 'Helvetica Neue', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } diff --git a/examples/graphql-file-upload-example/frontend/src/index.tsx b/examples/graphql-file-upload-example/frontend/src/index.tsx index ef2edf8ea3fc4..b0a768f12c016 100644 --- a/examples/graphql-file-upload-example/frontend/src/index.tsx +++ b/examples/graphql-file-upload-example/frontend/src/index.tsx @@ -8,7 +8,7 @@ ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ); // If you want to start measuring performance in your app, pass a function diff --git a/examples/grpc-example/start-server.ts b/examples/grpc-example/start-server.ts index cea479a6d4f95..09ef91e2aec78 100644 --- a/examples/grpc-example/start-server.ts +++ b/examples/grpc-example/start-server.ts @@ -1,4 +1,9 @@ -import { Server, loadPackageDefinition, ServerCredentials, ServiceClientConstructor } from '@grpc/grpc-js'; +import { + Server, + loadPackageDefinition, + ServerCredentials, + ServiceClientConstructor, +} from '@grpc/grpc-js'; import { load } from '@grpc/proto-loader'; import { join } from 'path'; diff --git a/examples/grpc-reflection-example/start-server.ts b/examples/grpc-reflection-example/start-server.ts index 3643af6092b6e..a82e87d91c0aa 100644 --- a/examples/grpc-reflection-example/start-server.ts +++ b/examples/grpc-reflection-example/start-server.ts @@ -1,4 +1,9 @@ -import { Server, loadPackageDefinition, ServerCredentials, ServiceClientConstructor } from '@grpc/grpc-js'; +import { + Server, + loadPackageDefinition, + ServerCredentials, + ServiceClientConstructor, +} from '@grpc/grpc-js'; import { load } from '@grpc/proto-loader'; import { join } from 'path'; diff --git a/examples/hive-example/.gitignore b/examples/hive-example/.gitignore index a88040bce2fa5..6b46220957e56 100644 --- a/examples/hive-example/.gitignore +++ b/examples/hive-example/.gitignore @@ -1,3 +1,2 @@ hive.json .env - diff --git a/examples/hive-example/sources/authors/openapi.yaml b/examples/hive-example/sources/authors/openapi.yaml index 1777da030cb52..77fb653aa0242 100644 --- a/examples/hive-example/sources/authors/openapi.yaml +++ b/examples/hive-example/sources/authors/openapi.yaml @@ -47,4 +47,3 @@ components: email: type: string format: email - diff --git a/examples/json-schema-covid/README.md b/examples/json-schema-covid/README.md index abb3a226d412c..6ad10e86824a6 100644 --- a/examples/json-schema-covid/README.md +++ b/examples/json-schema-covid/README.md @@ -8,11 +8,15 @@ It's a small test :) ## Why & What? -I want to extend a public [Covid graphQL endpoint](https://covid-19-two-rust.vercel.app/api/graphql) with some other data like the population of the country. Sounds like a good scenario for [graphql-mesh](https://github.com/Urigo/graphql-mesh)! +I want to extend a public [Covid graphQL endpoint](https://covid-19-two-rust.vercel.app/api/graphql) +with some other data like the population of the country. Sounds like a good scenario for +[graphql-mesh](https://github.com/Urigo/graphql-mesh)! -For this I found an API with [country population data](https://datasource.kapsarc.org/explore/dataset/world-population/table/?disjunctive.country_name&rows=1&q=France&sort=year). +For this I found an API with +[country population data](https://datasource.kapsarc.org/explore/dataset/world-population/table/?disjunctive.country_name&rows=1&q=France&sort=year). -I did it in few steps... That you can find in the file [example-query.graphql](./example-query.graphql) +I did it in few steps... That you can find in the file +[example-query.graphql](./example-query.graphql) - STEP1: 2 sources side by side - STEP2: 2 sources combined diff --git a/examples/json-schema-fhir/scripts/download-fhir-schema.ts b/examples/json-schema-fhir/scripts/download-fhir-schema.ts index c16febce97c35..07fec8160b58b 100644 --- a/examples/json-schema-fhir/scripts/download-fhir-schema.ts +++ b/examples/json-schema-fhir/scripts/download-fhir-schema.ts @@ -8,7 +8,9 @@ async function downloadFhirSchema() { await new Promise((resolve, reject) => { res.body .pipe(unzip.Parse()) - .on('entry', (entry: Entry) => entry.pipe(createWriteStream(join(__dirname, `../${entry.path}`)))) + .on('entry', (entry: Entry) => + entry.pipe(createWriteStream(join(__dirname, `../${entry.path}`))), + ) .on('finish', resolve); res.body.on('error', reject); }); diff --git a/examples/json-schema-subscriptions/README.md b/examples/json-schema-subscriptions/README.md index 9a830e3c48da7..e2dfcbb07b3cf 100644 --- a/examples/json-schema-subscriptions/README.md +++ b/examples/json-schema-subscriptions/README.md @@ -2,15 +2,16 @@ This example has a schemaless API Server that has two endpoints and one webhook; -GET `/todos` returns all `Todo` entities kept on inmemory database. -POST `/todo` adds a new `Todo` to the inmemory database and returns it with a generated id +GET `/todos` returns all `Todo` entities kept on inmemory database. POST `/todo` adds a new `Todo` +to the inmemory database and returns it with a generated id Everytime you call `/todo` endpoint, it sends `Todo` as a payload #### How to run -You can run API server with `yarn start:api` command and Mesh with `yarn start:mesh` then you can try the example queries you see in the playground. -You can go to the GraphQL Playground with this URL; `http://localhost:4000/graphql` +You can run API server with `yarn start:api` command and Mesh with `yarn start:mesh` then you can +try the example queries you see in the playground. You can go to the GraphQL Playground with this +URL; `http://localhost:4000/graphql` #### Extra: Live Queries diff --git a/examples/mongoose-example/src/models.js b/examples/mongoose-example/src/models.js index 85f511430ad3b..b69a2c555a26a 100644 --- a/examples/mongoose-example/src/models.js +++ b/examples/mongoose-example/src/models.js @@ -10,7 +10,7 @@ const LanguagesSchema = new Schema( }, { _id: false, // disable `_id` field for `Language` schema - } + }, ); const AddressSchema = new Schema({ @@ -59,7 +59,7 @@ const UserSchema = new Schema( }, { collection: 'user_users', - } + }, ); UserSchema.index({ gender: 1, age: -1 }); diff --git a/examples/mysql-employees/tests/mysql-employees.test.js b/examples/mysql-employees/tests/mysql-employees.test.js index cdc5477944ced..9db2e772d79a3 100644 --- a/examples/mysql-employees/tests/mysql-employees.test.js +++ b/examples/mysql-employees/tests/mysql-employees.test.js @@ -16,7 +16,7 @@ describe('MySQL Employees', () => { expect( printSchema(lexicographicSortSchema(schema), { descriptions: false, - }) + }), ).toMatchSnapshot('mysql-employees-schema'); }); it('should give correct response for example queries', async () => { diff --git a/examples/mysql-rfam/tests/mysql-rfam.test.js b/examples/mysql-rfam/tests/mysql-rfam.test.js index 142376c32ccb6..612076f25fb16 100644 --- a/examples/mysql-rfam/tests/mysql-rfam.test.js +++ b/examples/mysql-rfam/tests/mysql-rfam.test.js @@ -18,7 +18,7 @@ describe.skip('MySQL Rfam', () => { expect( printSchema(lexicographicSortSchema(schema), { descriptions: false, - }) + }), ).toMatchSnapshot('mysql-rfam-schema'); }); it('should give correct response for example queries', async () => { diff --git a/examples/nextjs-apollo-example/README.md b/examples/nextjs-apollo-example/README.md index 8d8bdf763b519..0dd5fde0fd519 100644 --- a/examples/nextjs-apollo-example/README.md +++ b/examples/nextjs-apollo-example/README.md @@ -1,4 +1,5 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +This is a [Next.js](https://nextjs.org/) project bootstrapped with +[`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). ## Getting Started @@ -12,13 +13,19 @@ yarn dev Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the +file. -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on +[http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in +`pages/api/hello.js`. -The GraphQL Playground can be accessed on [http://localhost:3000/api/graphql](http://localhost:3000/api/graphql). This endpoint can be edited in `pages/api/graphql.ts`. +The GraphQL Playground can be accessed on +[http://localhost:3000/api/graphql](http://localhost:3000/api/graphql). This endpoint can be edited +in `pages/api/graphql.ts`. -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as +[API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. ## Learn More @@ -27,10 +34,14 @@ To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your +feedback and contributions are welcome! ## Deploy on Vercel -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +The easiest way to deploy your Next.js app is to use the +[Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) +from the creators of Next.js. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more +details. diff --git a/examples/nextjs-apollo-example/server/server.ts b/examples/nextjs-apollo-example/server/server.ts index 8c1fa55946c14..d68f762d2d8c4 100644 --- a/examples/nextjs-apollo-example/server/server.ts +++ b/examples/nextjs-apollo-example/server/server.ts @@ -13,7 +13,9 @@ export default async function createApolloServer() { introspection: !isProd, cache, executor: async requestContext => { - const { schema, execute, contextFactory } = getEnveloped({ req: requestContext.request.http }); + const { schema, execute, contextFactory } = getEnveloped({ + req: requestContext.request.http, + }); return execute({ schema: schema, diff --git a/examples/nextjs-apollo-example/styles/globals.css b/examples/nextjs-apollo-example/styles/globals.css index e2e6d0f00d203..713c7421f48ad 100644 --- a/examples/nextjs-apollo-example/styles/globals.css +++ b/examples/nextjs-apollo-example/styles/globals.css @@ -2,8 +2,8 @@ html, body { padding: 0; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, - Helvetica Neue, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, + Fira Sans, Droid Sans, Helvetica Neue, sans-serif; } a { diff --git a/examples/nextjs-sdk-example/README.md b/examples/nextjs-sdk-example/README.md index 8d8bdf763b519..0dd5fde0fd519 100644 --- a/examples/nextjs-sdk-example/README.md +++ b/examples/nextjs-sdk-example/README.md @@ -1,4 +1,5 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +This is a [Next.js](https://nextjs.org/) project bootstrapped with +[`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). ## Getting Started @@ -12,13 +13,19 @@ yarn dev Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the +file. -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on +[http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in +`pages/api/hello.js`. -The GraphQL Playground can be accessed on [http://localhost:3000/api/graphql](http://localhost:3000/api/graphql). This endpoint can be edited in `pages/api/graphql.ts`. +The GraphQL Playground can be accessed on +[http://localhost:3000/api/graphql](http://localhost:3000/api/graphql). This endpoint can be edited +in `pages/api/graphql.ts`. -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as +[API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. ## Learn More @@ -27,10 +34,14 @@ To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your +feedback and contributions are welcome! ## Deploy on Vercel -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +The easiest way to deploy your Next.js app is to use the +[Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) +from the creators of Next.js. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more +details. diff --git a/examples/nextjs-sdk-example/styles/globals.css b/examples/nextjs-sdk-example/styles/globals.css index e2e6d0f00d203..713c7421f48ad 100644 --- a/examples/nextjs-sdk-example/styles/globals.css +++ b/examples/nextjs-sdk-example/styles/globals.css @@ -2,8 +2,8 @@ html, body { padding: 0; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, - Helvetica Neue, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, + Fira Sans, Droid Sans, Helvetica Neue, sans-serif; } a { diff --git a/examples/odata-microsoft/README.md b/examples/odata-microsoft/README.md index bf0055998e7e6..7e9d20b162345 100644 --- a/examples/odata-microsoft/README.md +++ b/examples/odata-microsoft/README.md @@ -1,10 +1,18 @@ # GraphQL Mesh for Microsoft Graph -**Note:** This project is based on [Microsoft's GraphQL for Microsoft Graph Demo](https://github.com/microsoftgraph/graphql-demo) +**Note:** This project is based on +[Microsoft's GraphQL for Microsoft Graph Demo](https://github.com/microsoftgraph/graphql-demo) ## About -This is a _demo_ that enables basic, read-only querying of the [Microsoft Graph API](https://developer.microsoft.com/en-us/graph/) using [GraphQL query syntax](http://graphql.org/learn/queries/). GraphQL enables clients to request exactly the resources and properties that they need instead of making REST requests for each resource and consolidating the responses. To create a GraphQL service, this demo translates the [Microsoft Graph OData $metadata document](https://graph.microsoft.com/v1.0/$metadata) to a GraphQL schema and generates the necessary resolvers. Please note we are providing this demo code for evaluation as-is. +This is a _demo_ that enables basic, read-only querying of the +[Microsoft Graph API](https://developer.microsoft.com/en-us/graph/) using +[GraphQL query syntax](http://graphql.org/learn/queries/). GraphQL enables clients to request +exactly the resources and properties that they need instead of making REST requests for each +resource and consolidating the responses. To create a GraphQL service, this demo translates the +[Microsoft Graph OData $metadata document](https://graph.microsoft.com/v1.0/$metadata) to a GraphQL +schema and generates the necessary resolvers. Please note we are providing this demo code for +evaluation as-is. ![Animation of sample request](https://user-images.githubusercontent.com/20847995/81301438-b92aeb00-9081-11ea-8bd3-c9e10d73ac8f.gif) @@ -12,7 +20,8 @@ This is a _demo_ that enables basic, read-only querying of the [Microsoft Graph 1. Clone the repo 2. Install dependencies (`npm install`) -3. Navigate to the [App Registration Portal](https://apps.dev.microsoft.com/), set up a [new web app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration) +3. Navigate to the [App Registration Portal](https://apps.dev.microsoft.com/), set up a + [new web app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration) 4. Configure App Id and redirect URIs in the AppConfiguration of build/index.html 5. Run `npm start` and go to `localhost:4000` diff --git a/examples/odata-microsoft/public/index.html b/examples/odata-microsoft/public/index.html index ff2bcdbd4406d..129194292dbb8 100644 --- a/examples/odata-microsoft/public/index.html +++ b/examples/odata-microsoft/public/index.html @@ -36,7 +36,11 @@ - +

Microsoft Graph GraphQL Demo

@@ -108,7 +112,9 @@

Microsoft Graph GraphQL Demo

authButton.innerHTML = 'logout'; authButton.setAttribute('onclick', 'logout();'); const label = document.getElementById('label'); - document.cookie = `accessToken=${tokenResponse.accessToken};expires=${tokenResponse.expiresOn.toUTCString()}`; + document.cookie = `accessToken=${ + tokenResponse.accessToken + };expires=${tokenResponse.expiresOn.toUTCString()}`; window.location.href = 'graphql/'; } function logout() { diff --git a/examples/odata-msgraph-programmatic-ts/src/index.ts b/examples/odata-msgraph-programmatic-ts/src/index.ts index 144a5e8d335d6..36adbd031b0fe 100644 --- a/examples/odata-msgraph-programmatic-ts/src/index.ts +++ b/examples/odata-msgraph-programmatic-ts/src/index.ts @@ -6,7 +6,7 @@ async function main() { {}, { accessToken: 'someAccessToken', - } + }, ); console.log({ result, diff --git a/examples/odata-msgraph-programmatic/index.js b/examples/odata-msgraph-programmatic/index.js index 1a9dbc6f2c804..1a3122b7e2766 100644 --- a/examples/odata-msgraph-programmatic/index.js +++ b/examples/odata-msgraph-programmatic/index.js @@ -22,7 +22,7 @@ async function main() { {}, { accessToken: 'someAccessToken', - } + }, ); console.log({ result, diff --git a/examples/openapi-javascript-wiki/additional-resolvers.ts b/examples/openapi-javascript-wiki/additional-resolvers.ts index 2f9a8d9dc5f1b..35c1a550af699 100644 --- a/examples/openapi-javascript-wiki/additional-resolvers.ts +++ b/examples/openapi-javascript-wiki/additional-resolvers.ts @@ -27,7 +27,7 @@ export const resolvers: Resolvers = { } } `, - } + }, ); if (result == null || !('items' in result)) { diff --git a/examples/openapi-location-weather/.meshrc.yaml b/examples/openapi-location-weather/.meshrc.yaml index 67120f0032c19..da5cd2dee68e9 100644 --- a/examples/openapi-location-weather/.meshrc.yaml +++ b/examples/openapi-location-weather/.meshrc.yaml @@ -78,4 +78,3 @@ additionalTypeDefs: | documents: - ./example-query.graphql - diff --git a/examples/openapi-location-weather/README.md b/examples/openapi-location-weather/README.md index a7bee0a296c69..f020d6dd7f3e3 100644 --- a/examples/openapi-location-weather/README.md +++ b/examples/openapi-location-weather/README.md @@ -1,4 +1,4 @@ ## Location-Weather Example -This example takes two API sources based on Openapi 3 and Swagger, and links between them. -It allow you to query for cities / locations, and include fields for the weather of in that found place. +This example takes two API sources based on Openapi 3 and Swagger, and links between them. It allow +you to query for cities / locations, and include fields for the weather of in that found place. diff --git a/examples/openapi-react-weatherbit/src/index.css b/examples/openapi-react-weatherbit/src/index.css index 7323ae85c542d..89e57c7ccfe1f 100644 --- a/examples/openapi-react-weatherbit/src/index.css +++ b/examples/openapi-react-weatherbit/src/index.css @@ -1,7 +1,7 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', - 'Droid Sans', 'Helvetica Neue', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } diff --git a/examples/openapi-react-weatherbit/src/index.tsx b/examples/openapi-react-weatherbit/src/index.tsx index a662f96686be9..41e19009aa638 100644 --- a/examples/openapi-react-weatherbit/src/index.tsx +++ b/examples/openapi-react-weatherbit/src/index.tsx @@ -8,7 +8,7 @@ ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ); // If you want your app to work offline and load faster, you can change diff --git a/examples/openapi-react-weatherbit/src/serviceWorker.ts b/examples/openapi-react-weatherbit/src/serviceWorker.ts index acbcb4447a44c..8d74eb9db2c81 100644 --- a/examples/openapi-react-weatherbit/src/serviceWorker.ts +++ b/examples/openapi-react-weatherbit/src/serviceWorker.ts @@ -15,7 +15,7 @@ const isLocalhost = Boolean( // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.0/8 are considered localhost for IPv4. - window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) + window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/), ); type Config = { @@ -46,7 +46,7 @@ export function register(config?: Config) { navigator.serviceWorker.ready.then(() => { console.log( 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA' + 'worker. To learn more, visit https://bit.ly/CRA-PWA', ); }); } else { @@ -74,7 +74,7 @@ function registerValidSW(swUrl: string, config?: Config) { // content until all client tabs are closed. console.log( 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.', ); // Execute callback @@ -109,7 +109,10 @@ function checkValidServiceWorker(swUrl: string, config?: Config) { .then(response => { // Ensure service worker exists, and that we really are getting a JS file. const contentType = response.headers.get('content-type'); - if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then(registration => { registration.unregister().then(() => { diff --git a/examples/openapi-stackexchange/test/openapi-stackexchange.test.ts b/examples/openapi-stackexchange/test/openapi-stackexchange.test.ts index 0b5a6ffbe4590..f46e1ef5dfdbe 100644 --- a/examples/openapi-stackexchange/test/openapi-stackexchange.test.ts +++ b/examples/openapi-stackexchange/test/openapi-stackexchange.test.ts @@ -19,7 +19,10 @@ describe('Stack Exchange', () => { expect(printSchemaWithDirectives(mesh.schema)).toMatchSnapshot(); }); it('should return the correct data', async () => { - const listQuestionsQuery = await readFile(join(__dirname, '..', 'list-questions.query.graphql'), 'utf-8'); + const listQuestionsQuery = await readFile( + join(__dirname, '..', 'list-questions.query.graphql'), + 'utf-8', + ); const result = await mesh.execute(listQuestionsQuery, {}); expect(result).toMatchObject({ data: { diff --git a/examples/openapi-subscriptions/tests/openapi-subscriptions.test.ts b/examples/openapi-subscriptions/tests/openapi-subscriptions.test.ts index 28fc47c187734..86bc723bbb27b 100644 --- a/examples/openapi-subscriptions/tests/openapi-subscriptions.test.ts +++ b/examples/openapi-subscriptions/tests/openapi-subscriptions.test.ts @@ -44,13 +44,17 @@ describe('OpenAPI Subscriptions', () => { }); afterAll(async () => { app.emit('destroy'); - await new Promise((resolve, reject) => meshServer.close(err => (err ? reject(err) : resolve()))); - await new Promise((resolve, reject) => appServer.close(err => (err ? reject(err) : resolve()))); + await new Promise((resolve, reject) => + meshServer.close(err => (err ? reject(err) : resolve())), + ); + await new Promise((resolve, reject) => + appServer.close(err => (err ? reject(err) : resolve())), + ); }); it('should work', async () => { const startWebhookMutation = await readFile( join(__dirname, '..', 'example-queries', 'startWebhook.mutation.graphql'), - 'utf8' + 'utf8', ); const startWebhookResponse = await fetch('http://localhost:4000/graphql', { @@ -75,7 +79,7 @@ describe('OpenAPI Subscriptions', () => { const listenWebhookSubscription = await readFile( join(__dirname, '..', 'example-queries', 'listenWebhook.subscription.graphql'), - 'utf8' + 'utf8', ); const listenWebhookResponse = await fetch('http://localhost:4000/graphql', { @@ -105,7 +109,7 @@ describe('OpenAPI Subscriptions', () => { userData: 'RANDOM_DATA', }, }, - })}` + })}`, ); reader.releaseLock(); diff --git a/examples/openapi-youtrack/README.md b/examples/openapi-youtrack/README.md index 15c8cbffce1ed..4a38a82f8c632 100644 --- a/examples/openapi-youtrack/README.md +++ b/examples/openapi-youtrack/README.md @@ -8,12 +8,16 @@ This example takes YouTrack as API Source and generates GraphQL Schema You should have a YouTrack instance and a valid token. -See here; https://www.jetbrains.com/help/youtrack/standalone/Manage-Permanent-Token.html#obtain-permanent-token +See here; +https://www.jetbrains.com/help/youtrack/standalone/Manage-Permanent-Token.html#obtain-permanent-token You need to pass two environmental variables to run this project with the command `yarn start`; -- `YOUTRACK_SERVICE_URL` is your YouTrack service URL. If you are using the cloud, you have a URL something like this; `https://ardatan.myjetbrains.com/youtrack` -- `YOUTRACK_TOKEN` is your YouTrack token to access YouTrack service using REST API. If it is a permenant token, it should be something like `perm:XXXXXX==XXXXXXX==XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` +- `YOUTRACK_SERVICE_URL` is your YouTrack service URL. If you are using the cloud, you have a URL + something like this; `https://ardatan.myjetbrains.com/youtrack` +- `YOUTRACK_TOKEN` is your YouTrack token to access YouTrack service using REST API. If it is a + permenant token, it should be something like + `perm:XXXXXX==XXXXXXX==XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` Then run this project with the following command; diff --git a/examples/openwhisk-example/README.md b/examples/openwhisk-example/README.md index 72e745a58a3cd..ab2a3ae305275 100644 --- a/examples/openwhisk-example/README.md +++ b/examples/openwhisk-example/README.md @@ -2,15 +2,16 @@ ## Files -- `src/index.ts` is the handler function for the OpenWhisk action that uses GraphQL Mesh's platform agnostic HTTP Handler +- `src/index.ts` is the handler function for the OpenWhisk action that uses GraphQL Mesh's platform + agnostic HTTP Handler - `.meshrc.yml` is the configuration file for GraphQL Mesh - `package.json` is the package.json file that contains all the dependencies and scripts - `build.js` is the code file that runs `ESBuild` to create a bundle for OpenWhisk deployment ## Configuring the project -GraphQL Mesh needs to be aware of the path of the OpenWhisk action endpoint. -So you need to configure `serve.endpoint` in `.meshrc.yml`; +GraphQL Mesh needs to be aware of the path of the OpenWhisk action endpoint. So you need to +configure `serve.endpoint` in `.meshrc.yml`; ```yaml filename=".meshrc.yaml" serve: @@ -19,14 +20,17 @@ serve: endpoint: /api/v1/web/guest/mesh/swapi/graphql ``` -You also need to update the paths inside `index.ts` and `package.json` to match your OpenWhisk action name. +You also need to update the paths inside `index.ts` and `package.json` to match your OpenWhisk +action name. ## Building the project for deployment -You can see an example script to bundle the project with `ESBuild` in `build.js`. -`yarn build` will build the artifacts of GraphQL Mesh first then bundle all the code needed for the OpenWhisk action by taking `index.ts` as an endpoint. +You can see an example script to bundle the project with `ESBuild` in `build.js`. `yarn build` will +build the artifacts of GraphQL Mesh first then bundle all the code needed for the OpenWhisk action +by taking `index.ts` as an endpoint. -You can find the bundle in `dist/index.js` and deploy it either `yarn deploy` or manually with `wsk` like `wsk action update /guest/mesh/swapi --kind nodejs:16 dist/index.js --web raw`. +You can find the bundle in `dist/index.js` and deploy it either `yarn deploy` or manually with `wsk` +like `wsk action update /guest/mesh/swapi --kind nodejs:16 dist/index.js --web raw`. > `--web raw` needs to be added to configure the action as a _raw_ web action. diff --git a/examples/openwhisk-example/src/index.ts b/examples/openwhisk-example/src/index.ts index abc06858cae09..cd9983ee8dc91 100644 --- a/examples/openwhisk-example/src/index.ts +++ b/examples/openwhisk-example/src/index.ts @@ -10,7 +10,7 @@ export const main = async function (params) { headers: params.__ow_headers, body: params.__ow_body ? Buffer.from(params.__ow_body, 'base64') : undefined, }, - params + params, ); const headers = {}; diff --git a/examples/postgres-geodb/README.md b/examples/postgres-geodb/README.md index 01e84e8506158..c823e8deba690 100644 --- a/examples/postgres-geodb/README.md +++ b/examples/postgres-geodb/README.md @@ -2,10 +2,12 @@ This example takes two API sources and merges them together: -1. Postgres GeoDB - a seed database of geo locations and their metadata (uses `postgraphile` handler) +1. Postgres GeoDB - a seed database of geo locations and their metadata (uses `postgraphile` + handler) 2. GitHub GraphQL API - to fetch information about users and developers ((uses `graphql` handler)) -The two schemas are connected and let you search for locations, and then fetch developers that are located in that location according to their GitHub account. +The two schemas are connected and let you search for locations, and then fetch developers that are +located in that location according to their GitHub account. You should be able to run the following query and get the linked data: @@ -27,15 +29,19 @@ query locationsAndDevelopers { ## Getting Started -Because a running Postgres DB is required, you need to setup local Postgres running, and load the schema and data seed. +Because a running Postgres DB is required, you need to setup local Postgres running, and load the +schema and data seed. To do that, run the following: -1. Install and run Postgres using Docker - `docker run --name pg-docker -e POSTGRES_PASSWORD=docker -d -p 5432:5432 postgres` +1. Install and run Postgres using Docker - + `docker run --name pg-docker -e POSTGRES_PASSWORD=docker -d -p 5432:5432 postgres` 2. Install Postgres CLI: `brew upgrade postgresql` (or, you can use any of your favorite tool) -3. Seed the DB with data: `curl https://raw.githubusercontent.com/morenoh149/postgresDBSamples/master/worldDB-1.0/world.sql | psql -h localhost -d postgres -U postgres` +3. Seed the DB with data: + `curl https://raw.githubusercontent.com/morenoh149/postgresDBSamples/master/worldDB-1.0/world.sql | psql -h localhost -d postgres -U postgres` -Now, to have access to the GitHub GraphQL API, start by creating a personal access token here: https://github.com/settings/tokens , and put it in an environment variable called `GH_ACCESS_TOKEN`. +Now, to have access to the GitHub GraphQL API, start by creating a personal access token here: +https://github.com/settings/tokens , and put it in an environment variable called `GH_ACCESS_TOKEN`. Then you should be able to use the `mesh:serve` script to run it: @@ -53,7 +59,8 @@ The following command will generate the fully type-safe SDK for you: GH_ACCESS_TOKEN="your token here" yarn mesh:sdk ``` -You can find the code that uses the generates SDK under `./src/test.ts`, it imports for the generated code and prints the result nicely to the console. You can run it with: +You can find the code that uses the generates SDK under `./src/test.ts`, it imports for the +generated code and prints the result nicely to the console. You can run it with: ```sh GH_ACCESS_TOKEN="your token here" yarn test:sdk diff --git a/examples/soap-country-info/tests/soap-country-info.spec.ts b/examples/soap-country-info/tests/soap-country-info.spec.ts index 6196021d456db..b502add2f599f 100644 --- a/examples/soap-country-info/tests/soap-country-info.spec.ts +++ b/examples/soap-country-info/tests/soap-country-info.spec.ts @@ -23,7 +23,10 @@ describe('SOAP Country Info', () => { expect(printSchemaWithDirectives(lexicographicSortSchema(mesh.schema))).toMatchSnapshot(); }); it('should give correct response for the batched example query', async () => { - const queryStr = await readFile(join(__dirname, '..', 'list-of-languages-by-name.graphql'), 'utf-8'); + const queryStr = await readFile( + join(__dirname, '..', 'list-of-languages-by-name.graphql'), + 'utf-8', + ); const result = await mesh.execute(queryStr, {}); expect(result?.errors?.[0]?.stack).toBeUndefined(); expect(result).toMatchSnapshot('list-of-languages-by-name-result'); diff --git a/examples/sqlite-chinook/tests/sqlite-chinook.test.js b/examples/sqlite-chinook/tests/sqlite-chinook.test.js index 683d3fec832b8..dac959a963b63 100644 --- a/examples/sqlite-chinook/tests/sqlite-chinook.test.js +++ b/examples/sqlite-chinook/tests/sqlite-chinook.test.js @@ -16,7 +16,7 @@ describe('SQLite Chinook', () => { expect( introspectionFromSchema(lexicographicSortSchema(schema), { descriptions: false, - }) + }), ).toMatchSnapshot('sqlite-chinook-schema'); }); it('should give correct response for example queries', async () => { diff --git a/examples/thrift-calculator/src/codegen/AddRequest.ts b/examples/thrift-calculator/src/codegen/AddRequest.ts index f77f3f6a43bd0..42b310a2d328b 100644 --- a/examples/thrift-calculator/src/codegen/AddRequest.ts +++ b/examples/thrift-calculator/src/codegen/AddRequest.ts @@ -25,14 +25,20 @@ export const AddRequestCodec: thrift.IStructCodec output.writeI32(obj.left); output.writeFieldEnd(); } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Required field[left] is unset!'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Required field[left] is unset!', + ); } if (obj.right != null) { output.writeFieldBegin('right', thrift.TType.I32, 2); output.writeI32(obj.right); output.writeFieldEnd(); } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Required field[right] is unset!'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Required field[right] is unset!', + ); } output.writeFieldStop(); output.writeStructEnd(); @@ -80,7 +86,7 @@ export const AddRequestCodec: thrift.IStructCodec } else { throw new thrift.TProtocolException( thrift.TProtocolExceptionType.UNKNOWN, - 'Unable to read AddRequest from input' + 'Unable to read AddRequest from input', ); } }, @@ -96,13 +102,19 @@ export class AddRequest extends thrift.StructLike implements IAddRequest { const value_3: number = args.left; this.left = value_3; } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Required field[left] is unset!'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Required field[left] is unset!', + ); } if (args.right != null) { const value_4: number = args.right; this.right = value_4; } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Required field[right] is unset!'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Required field[right] is unset!', + ); } } public static read(input: thrift.TProtocol): AddRequest { diff --git a/examples/thrift-calculator/src/codegen/Calculator.ts b/examples/thrift-calculator/src/codegen/Calculator.ts index 16b2e78e01bac..a68d1efe9f604 100644 --- a/examples/thrift-calculator/src/codegen/Calculator.ts +++ b/examples/thrift-calculator/src/codegen/Calculator.ts @@ -42,7 +42,10 @@ export const Add__ArgsCodec: thrift.IStructCodec = { AddRequest.AddRequestCodec.encode(obj.request, output); output.writeFieldEnd(); } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Required field[request] is unset!'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Required field[request] is unset!', + ); } output.writeFieldStop(); output.writeStructEnd(); @@ -79,7 +82,10 @@ export const Add__ArgsCodec: thrift.IStructCodec = { request: _args.request, }; } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Unable to read Add__Args from input'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Unable to read Add__Args from input', + ); } }, }; @@ -93,7 +99,10 @@ export class Add__Args extends thrift.StructLike implements IAdd__Args { const value_2: AddRequest.IAddRequest = new AddRequest.AddRequest(args.request); this.request = value_2; } else { - throw new thrift.TProtocolException(thrift.TProtocolExceptionType.UNKNOWN, 'Required field[request] is unset!'); + throw new thrift.TProtocolException( + thrift.TProtocolExceptionType.UNKNOWN, + 'Required field[request] is unset!', + ); } } public static read(input: thrift.TProtocol): Add__Args { @@ -126,14 +135,20 @@ export const Subtract__ArgsCodec: thrift.IStructCodec = { - encode(args: ISubtract__ResultArgs, output: thrift.TProtocol): void { - const obj: any = { - success: args.success, - }; - output.writeStructBegin('Subtract__Result'); - if (obj.success != null) { - output.writeFieldBegin('success', thrift.TType.I32, 0); - output.writeI32(obj.success); - output.writeFieldEnd(); - } - output.writeFieldStop(); - output.writeStructEnd(); - return; - }, - decode(input: thrift.TProtocol): ISubtract__Result { - let _args: any = {}; - input.readStructBegin(); - while (true) { - const ret: thrift.IThriftField = input.readFieldBegin(); - const fieldType: thrift.TType = ret.fieldType; - const fieldId: number = ret.fieldId; - if (fieldType === thrift.TType.STOP) { - break; +export const Subtract__ResultCodec: thrift.IStructCodec = + { + encode(args: ISubtract__ResultArgs, output: thrift.TProtocol): void { + const obj: any = { + success: args.success, + }; + output.writeStructBegin('Subtract__Result'); + if (obj.success != null) { + output.writeFieldBegin('success', thrift.TType.I32, 0); + output.writeI32(obj.success); + output.writeFieldEnd(); } - switch (fieldId) { - case 0: - if (fieldType === thrift.TType.I32) { - const value_9: number = input.readI32(); - _args.success = value_9; - } else { + output.writeFieldStop(); + output.writeStructEnd(); + return; + }, + decode(input: thrift.TProtocol): ISubtract__Result { + let _args: any = {}; + input.readStructBegin(); + while (true) { + const ret: thrift.IThriftField = input.readFieldBegin(); + const fieldType: thrift.TType = ret.fieldType; + const fieldId: number = ret.fieldId; + if (fieldType === thrift.TType.STOP) { + break; + } + switch (fieldId) { + case 0: + if (fieldType === thrift.TType.I32) { + const value_9: number = input.readI32(); + _args.success = value_9; + } else { + input.skip(fieldType); + } + break; + default: { input.skip(fieldType); } - break; - default: { - input.skip(fieldType); } + input.readFieldEnd(); } - input.readFieldEnd(); - } - input.readStructEnd(); - return { - success: _args.success, - }; - }, -}; + input.readStructEnd(); + return { + success: _args.success, + }; + }, + }; export class Subtract__Result extends thrift.StructLike implements ISubtract__Result { public success?: number; public readonly _annotations: thrift.IThriftAnnotations = {}; @@ -385,10 +407,12 @@ export class Client extends thrift.ThriftClient { const reader: thrift.TTransport = this.transport.receiver(data); const input: thrift.TProtocol = new this.protocol(reader); try { - const { fieldName: fieldName, messageType: messageType }: thrift.IThriftMessage = input.readMessageBegin(); + const { fieldName: fieldName, messageType: messageType }: thrift.IThriftMessage = + input.readMessageBegin(); if (fieldName === 'add') { if (messageType === thrift.MessageType.EXCEPTION) { - const err: thrift.TApplicationException = thrift.TApplicationExceptionCodec.decode(input); + const err: thrift.TApplicationException = + thrift.TApplicationExceptionCodec.decode(input); input.readMessageEnd(); return Promise.reject(err); } else { @@ -398,7 +422,10 @@ export class Client extends thrift.ThriftClient { return Promise.resolve(result.success); } else { return Promise.reject( - new thrift.TApplicationException(thrift.TApplicationExceptionType.UNKNOWN, 'add failed: unknown result') + new thrift.TApplicationException( + thrift.TApplicationExceptionType.UNKNOWN, + 'add failed: unknown result', + ), ); } } @@ -406,8 +433,8 @@ export class Client extends thrift.ThriftClient { return Promise.reject( new thrift.TApplicationException( thrift.TApplicationExceptionType.WRONG_METHOD_NAME, - 'Received a response to an unknown RPC function: ' + fieldName - ) + 'Received a response to an unknown RPC function: ' + fieldName, + ), ); } } catch (err) { @@ -426,10 +453,12 @@ export class Client extends thrift.ThriftClient { const reader: thrift.TTransport = this.transport.receiver(data); const input: thrift.TProtocol = new this.protocol(reader); try { - const { fieldName: fieldName, messageType: messageType }: thrift.IThriftMessage = input.readMessageBegin(); + const { fieldName: fieldName, messageType: messageType }: thrift.IThriftMessage = + input.readMessageBegin(); if (fieldName === 'subtract') { if (messageType === thrift.MessageType.EXCEPTION) { - const err: thrift.TApplicationException = thrift.TApplicationExceptionCodec.decode(input); + const err: thrift.TApplicationException = + thrift.TApplicationExceptionCodec.decode(input); input.readMessageEnd(); return Promise.reject(err); } else { @@ -441,8 +470,8 @@ export class Client extends thrift.ThriftClient { return Promise.reject( new thrift.TApplicationException( thrift.TApplicationExceptionType.UNKNOWN, - 'subtract failed: unknown result' - ) + 'subtract failed: unknown result', + ), ); } } @@ -450,8 +479,8 @@ export class Client extends thrift.ThriftClient { return Promise.reject( new thrift.TApplicationException( thrift.TApplicationExceptionType.WRONG_METHOD_NAME, - 'Received a response to an unknown RPC function: ' + fieldName - ) + 'Received a response to an unknown RPC function: ' + fieldName, + ), ); } } catch (err) { @@ -478,7 +507,11 @@ export class Processor extends thrift.ThriftProcessor { + public process( + input: thrift.TProtocol, + output: thrift.TProtocol, + context: Context, + ): Promise { return new Promise((resolve, reject): void => { const metadata: thrift.IThriftMessage = input.readMessageBegin(); const fieldName: string = metadata.fieldName; @@ -497,7 +530,10 @@ export class Processor extends thrift.ThriftProcessor extends thrift.ThriftProcessor { return new Promise((resolve, reject): void => { try { @@ -532,7 +568,7 @@ export class Processor extends thrift.ThriftProcessor { const result: thrift.TApplicationException = new thrift.TApplicationException( thrift.TApplicationExceptionType.UNKNOWN, - err.message + err.message, ); output.writeMessageBegin('add', thrift.MessageType.EXCEPTION, requestId); thrift.TApplicationExceptionCodec.encode(result, output); @@ -544,7 +580,7 @@ export class Processor extends thrift.ThriftProcessor { return new Promise((resolve, reject): void => { try { @@ -565,7 +601,7 @@ export class Processor extends thrift.ThriftProcessor { const result: thrift.TApplicationException = new thrift.TApplicationException( thrift.TApplicationExceptionType.UNKNOWN, - err.message + err.message, ); output.writeMessageBegin('subtract', thrift.MessageType.EXCEPTION, requestId); thrift.TApplicationExceptionCodec.encode(result, output); diff --git a/examples/thrift-calculator/tests/thrift-calculator.test.ts b/examples/thrift-calculator/tests/thrift-calculator.test.ts index c9683c21d9122..7c36d90c87cba 100644 --- a/examples/thrift-calculator/tests/thrift-calculator.test.ts +++ b/examples/thrift-calculator/tests/thrift-calculator.test.ts @@ -26,7 +26,7 @@ describe('Thrift Calculator', () => { expect( introspectionFromSchema(lexicographicSortSchema(schema), { descriptions: false, - }) + }), ).toMatchSnapshot('thrift-calculator-schema'); }); it('should give correct response for example queries', async () => { diff --git a/examples/type-merging-batching-example/author-service-schema.ts b/examples/type-merging-batching-example/author-service-schema.ts index 72a15f4d957a2..119de10fe764b 100644 --- a/examples/type-merging-batching-example/author-service-schema.ts +++ b/examples/type-merging-batching-example/author-service-schema.ts @@ -43,7 +43,8 @@ export default new GraphQLSchema({ type: new GraphQLList(GraphQLID), }, }, - resolve: (_, { ids }) => (ids ? ids.map(id => authors.find(author => author.id === id)) : authors), + resolve: (_, { ids }) => + ids ? ids.map(id => authors.find(author => author.id === id)) : authors, }, }, }), diff --git a/package.json b/package.json index 1f82c45e27276..90ab2883ea047 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "lint-staged": "13.1.0", "patch-package": "6.5.1", "prettier": "2.8.2", + "pretty-quick": "3.1.3", "ts-jest": "29.0.3", "typescript": "4.9.4" }, diff --git a/packages/apollo-link/src/index.ts b/packages/apollo-link/src/index.ts index 6296476217cc9..b5232d5461074 100644 --- a/packages/apollo-link/src/index.ts +++ b/packages/apollo-link/src/index.ts @@ -15,7 +15,8 @@ function createMeshApolloRequestHandler(options: MeshApolloRequestHandlerOptions if (!operationAst) { throw new Error('GraphQL operation not found'); } - const operationFn = operationAst.operation === 'subscription' ? options.subscribe : options.execute; + const operationFn = + operationAst.operation === 'subscription' ? options.subscribe : options.execute; return new Observable(observer => { Promise.resolve() .then(async () => { @@ -24,7 +25,7 @@ function createMeshApolloRequestHandler(options: MeshApolloRequestHandlerOptions operation.variables, operation.getContext(), ROOT_VALUE, - operation.operationName + operation.operationName, ); if (isAsyncIterable(results)) { for await (const result of results) { diff --git a/packages/apollo-link/test/apollo-link.test.ts b/packages/apollo-link/test/apollo-link.test.ts index f05d5a522e66f..56a2cd153f6bc 100644 --- a/packages/apollo-link/test/apollo-link.test.ts +++ b/packages/apollo-link/test/apollo-link.test.ts @@ -41,7 +41,9 @@ describe('GraphApolloLink', () => { `), }); const asyncIterable = - observableToAsyncIterable, Record>>(observable); + observableToAsyncIterable, Record>>( + observable, + ); let i = 0; for await (const result of asyncIterable) { i++; diff --git a/packages/cache/localforage/src/InMemoryLRUDriver.ts b/packages/cache/localforage/src/InMemoryLRUDriver.ts index 65eb4c5f9b3e6..0667c299d7297 100644 --- a/packages/cache/localforage/src/InMemoryLRUDriver.ts +++ b/packages/cache/localforage/src/InMemoryLRUDriver.ts @@ -31,7 +31,11 @@ export function createInMemoryLRUDriver(ttl?: number): LocalForageDriver { } }, - async setItem(key: string, value: T, callback?: (err?: any, value?: any) => void): Promise { + async setItem( + key: string, + value: T, + callback?: (err?: any, value?: any) => void, + ): Promise { try { await nextTick(); lru.set(key, value); @@ -125,7 +129,7 @@ export function createInMemoryLRUDriver(ttl?: number): LocalForageDriver { async iterate( iteratee: (value: T, key: string, iterationNumber: number) => any, - callback?: (err?: any, result?: any) => void + callback?: (err?: any, result?: any) => void, ): Promise { try { await nextTick(); diff --git a/packages/cache/localforage/src/index.ts b/packages/cache/localforage/src/index.ts index 8feead45da729..008c2ed474703 100644 --- a/packages/cache/localforage/src/index.ts +++ b/packages/cache/localforage/src/index.ts @@ -3,7 +3,7 @@ import { createInMemoryLRUDriver } from './InMemoryLRUDriver.js'; import LocalForage from 'localforage'; LocalForage.defineDriver(createInMemoryLRUDriver()).catch(err => - console.error('Failed at defining InMemoryLRU driver', err) + console.error('Failed at defining InMemoryLRU driver', err), ); export default class LocalforageCache implements KeyValueCache { diff --git a/packages/cache/redis/src/index.ts b/packages/cache/redis/src/index.ts index c19fcc761bdb2..a3a8288e6a2e6 100644 --- a/packages/cache/redis/src/index.ts +++ b/packages/cache/redis/src/index.ts @@ -1,4 +1,9 @@ -import { KeyValueCache, KeyValueCacheSetOptions, MeshPubSub, YamlConfig } from '@graphql-mesh/types'; +import { + KeyValueCache, + KeyValueCacheSetOptions, + MeshPubSub, + YamlConfig, +} from '@graphql-mesh/types'; import Redis from 'ioredis'; import { stringInterpolator } from '@graphql-mesh/string-interpolation'; import { process } from '@graphql-mesh/cross-helpers'; diff --git a/packages/cache/redis/test/cache.spec.ts b/packages/cache/redis/test/cache.spec.ts index be751e12a248f..5a047697bc42f 100644 --- a/packages/cache/redis/test/cache.spec.ts +++ b/packages/cache/redis/test/cache.spec.ts @@ -20,7 +20,7 @@ describe('redis', () => { new RedisCache({ url: 'redis://password@localhost:6379', pubsub }); expect(Redis).toHaveBeenCalledWith( - 'redis://password@localhost:6379?lazyConnect=true&enableAutoPipelining=true&enableOfflineQueue=true' + 'redis://password@localhost:6379?lazyConnect=true&enableAutoPipelining=true&enableOfflineQueue=true', ); }); @@ -41,7 +41,7 @@ describe('redis', () => { new RedisCache({ url: 'redis://localhost:6379', host: 'ignoreme', port: '9999', pubsub }); expect(Redis).toHaveBeenCalledWith( - 'redis://localhost:6379?lazyConnect=true&enableAutoPipelining=true&enableOfflineQueue=true' + 'redis://localhost:6379?lazyConnect=true&enableAutoPipelining=true&enableOfflineQueue=true', ); }); @@ -51,7 +51,7 @@ describe('redis', () => { expect(() => { new RedisCache({ url: `${protocol}localhost:6379`, pubsub }); }).toThrowError('Redis URL must use either redis:// or rediss://'); - } + }, ); }); }); diff --git a/packages/cli/src/commands/generate-operations.ts b/packages/cli/src/commands/generate-operations.ts index 9545dc5cc4f67..3010b5b325722 100644 --- a/packages/cli/src/commands/generate-operations.ts +++ b/packages/cli/src/commands/generate-operations.ts @@ -1,8 +1,16 @@ import type { YamlConfig } from '@graphql-mesh/types'; -import { buildOperationNodeForField, getRootTypeMap, parseGraphQLSDL, Source } from '@graphql-tools/utils'; +import { + buildOperationNodeForField, + getRootTypeMap, + parseGraphQLSDL, + Source, +} from '@graphql-tools/utils'; import { GraphQLSchema, print } from 'graphql'; -export function generateOperations(schema: GraphQLSchema, options: YamlConfig.GenerateOperationsConfig): Source[] { +export function generateOperations( + schema: GraphQLSchema, + options: YamlConfig.GenerateOperationsConfig, +): Source[] { const sources: Source[] = []; const rootTypeMap = getRootTypeMap(schema); for (const [operationType, rootType] of rootTypeMap) { diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index 8b5f21a642aff..ce2d4f89b4747 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -10,7 +10,7 @@ export function validateConfig( config: any, filepath: string, initialLoggerPrefix: string, - throwOnInvalidConfig = false + throwOnInvalidConfig = false, ): asserts config is YamlConfig.Config { const ajv = new Ajv({ strict: false, @@ -25,7 +25,7 @@ export function validateConfig( error.stack += `\n at ${filepath}:0:0`; return error; }), - 'Configuration file is not valid' + 'Configuration file is not valid', ); throw aggregateError; } @@ -80,7 +80,11 @@ export async function findAndParseConfig(options?: ConfigProcessOptions) { return processConfig(config, { dir, initialLoggerPrefix, importFn, ...restOptions }); } -function customLoader(ext: 'json' | 'yaml' | 'js', importFn = defaultImportFn, initialLoggerPrefix = '🕸️ Mesh') { +function customLoader( + ext: 'json' | 'yaml' | 'js', + importFn = defaultImportFn, + initialLoggerPrefix = '🕸️ Mesh', +) { const logger = new DefaultLogger(initialLoggerPrefix).child('config'); function loader(filepath: string, content: string) { if (process.env) { diff --git a/packages/config/src/getAdditionalResolversFromTypeDefs.ts b/packages/config/src/getAdditionalResolversFromTypeDefs.ts index 5b214ad9cd4f1..d272d1ef415b2 100644 --- a/packages/config/src/getAdditionalResolversFromTypeDefs.ts +++ b/packages/config/src/getAdditionalResolversFromTypeDefs.ts @@ -1,5 +1,12 @@ import { resolveAdditionalResolvers } from '@graphql-mesh/utils'; -import { ConstValueNode, DocumentNode, Kind, ConstObjectValueNode, visit, FieldDefinitionNode } from 'graphql'; +import { + ConstValueNode, + DocumentNode, + Kind, + ConstObjectValueNode, + visit, + FieldDefinitionNode, +} from 'graphql'; function parseObject(ast: ConstObjectValueNode): any { const value = Object.create(null); @@ -56,10 +63,14 @@ export function getAdditionalResolversFromTypeDefs(additionalTypeDefs: DocumentN objectNode.fields?.forEach(fieldNode => handleFieldNode(objectNode.name.value, fieldNode)); }, InterfaceTypeDefinition(interfaceNode) { - interfaceNode.fields?.forEach(fieldNode => handleFieldNode(interfaceNode.name.value, fieldNode)); + interfaceNode.fields?.forEach(fieldNode => + handleFieldNode(interfaceNode.name.value, fieldNode), + ); }, InterfaceTypeExtension(interfaceNode) { - interfaceNode.fields?.forEach(fieldNode => handleFieldNode(interfaceNode.name.value, fieldNode)); + interfaceNode.fields?.forEach(fieldNode => + handleFieldNode(interfaceNode.name.value, fieldNode), + ); }, }); }); diff --git a/packages/config/src/process.ts b/packages/config/src/process.ts index 87abdaae937c9..c3fdeba01ebc5 100644 --- a/packages/config/src/process.ts +++ b/packages/config/src/process.ts @@ -252,18 +252,18 @@ export async function processConfig( });`); } - return new TransformCtor({ - apiName: source.name, - config: transformConfig, - baseDir: dir, - cache, - pubsub, - importFn, - logger, - }); - }) - ), - ]); + return new TransformCtor({ + apiName: source.name, + config: transformConfig, + baseDir: dir, + cache, + pubsub, + importFn, + logger, + }); + }), + ), + ]); if (options.generateCode) { codes.add(`sources[${sourceIndex}] = { diff --git a/packages/config/src/utils.ts b/packages/config/src/utils.ts index 6d4afef63925f..23908d68bff49 100644 --- a/packages/config/src/utils.ts +++ b/packages/config/src/utils.ts @@ -1,4 +1,11 @@ -import { KeyValueCache, YamlConfig, ImportFn, MeshPubSub, Logger, MeshFetch } from '@graphql-mesh/types'; +import { + KeyValueCache, + YamlConfig, + ImportFn, + MeshPubSub, + Logger, + MeshFetch, +} from '@graphql-mesh/types'; import { path } from '@graphql-mesh/cross-helpers'; import { printSchemaWithDirectives, Source } from '@graphql-tools/utils'; import { paramCase } from 'param-case'; @@ -32,7 +39,12 @@ export async function getPackage({ const casedName = paramCase(name); const casedType = paramCase(type); const prefixes = ['@graphql-mesh/', ...additionalPrefixes]; - const initialPossibleNames = [casedName, `${casedName}-${casedType}`, `${casedType}-${casedName}`, casedType]; + const initialPossibleNames = [ + casedName, + `${casedName}-${casedType}`, + `${casedType}-${casedName}`, + casedType, + ]; const possibleNames: string[] = []; for (const prefix of prefixes) { for (const possibleName of initialPossibleNames) { @@ -62,7 +74,9 @@ export async function getPackage({ !error.message.includes(`Cannot find package '${moduleName}'`) && !error.message.includes(`Could not locate module`) ) { - throw new Error(`Unable to load ${type} matching ${name} while resolving ${moduleName}: ${error.stack}`); + throw new Error( + `Unable to load ${type} matching ${name} while resolving ${moduleName}: ${error.stack}`, + ); } } } @@ -77,7 +91,9 @@ export async function resolveAdditionalTypeDefs(baseDir: string, additionalTypeD loaders: [new CodeFileLoader(), new GraphQLFileLoader()], }); return sources.map( - source => source.document || parseWithCache(source.rawSDL || printSchemaWithDirectives(source.schema)) + source => + source.document || + parseWithCache(source.rawSDL || printSchemaWithDirectives(source.schema)), ); } return undefined; @@ -135,7 +151,7 @@ export async function resolveCache( cwd: string, pubsub: MeshPubSub, logger: Logger, - additionalPackagePrefixes: string[] + additionalPackagePrefixes: string[], ): Promise<{ cache: KeyValueCache; importCode: string; @@ -180,7 +196,7 @@ export async function resolvePubSub( pubsubYamlConfig: YamlConfig.Config['pubsub'], importFn: ImportFn, cwd: string, - additionalPackagePrefixes: string[] + additionalPackagePrefixes: string[], ): Promise<{ importCode: string; code: string; @@ -230,7 +246,7 @@ export async function resolvePubSub( export async function resolveDocuments( documentsConfig: YamlConfig.Config['documents'], - cwd: string + cwd: string, ): Promise { if (!documentsConfig) { return []; @@ -247,7 +263,7 @@ export async function resolveLogger( importFn: ImportFn, cwd: string, additionalPackagePrefixes: string[], - initialLoggerPrefix = '🕸️ Mesh' + initialLoggerPrefix = '🕸️ Mesh', ): Promise<{ importCode: string; code: string; diff --git a/packages/cross-helpers/browser.js b/packages/cross-helpers/browser.js index 6b8b5a929ea05..26234f784a195 100644 --- a/packages/cross-helpers/browser.js +++ b/packages/cross-helpers/browser.js @@ -26,7 +26,7 @@ const processObj = } return globalThis[key]; }, - } + }, ); } }, diff --git a/packages/cross-helpers/react-native.js b/packages/cross-helpers/react-native.js index 914ff3f4ef29e..82e94a2278cdc 100644 --- a/packages/cross-helpers/react-native.js +++ b/packages/cross-helpers/react-native.js @@ -1,6 +1,7 @@ module.exports.fs = require('react-native-fs'); module.exports.path = require('react-native-path'); -module.exports.path.join = (...args) => module.exports.path.normalize(args.filter(x => !!x).join('/')); +module.exports.path.join = (...args) => + module.exports.path.normalize(args.filter(x => !!x).join('/')); Promise.allSettled = Promise.allSettled || @@ -15,8 +16,8 @@ Promise.allSettled = .catch(reason => ({ status: 'rejected', reason, - })) - ) + })), + ), )); module.exports.process = diff --git a/packages/handlers/graphql/src/index.ts b/packages/handlers/graphql/src/index.ts index dc47408d2151f..841fb2bc1e76b 100644 --- a/packages/handlers/graphql/src/index.ts +++ b/packages/handlers/graphql/src/index.ts @@ -60,11 +60,21 @@ export default class GraphQLHandler implements MeshHandler { private logger: Logger; private urlLoader = new UrlLoader(); - constructor({ name, config, baseDir, store, importFn, logger }: MeshHandlerOptions) { + constructor({ + name, + config, + baseDir, + store, + importFn, + logger, + }: MeshHandlerOptions) { this.name = name; this.config = config; this.baseDir = baseDir; - this.nonExecutableSchema = store.proxy('introspectionSchema', PredefinedProxyOptions.GraphQLSchemaWithDiffing); + this.nonExecutableSchema = store.proxy( + 'introspectionSchema', + PredefinedProxyOptions.GraphQLSchemaWithDiffing, + ); this.importFn = importFn; this.logger = logger; } @@ -85,7 +95,7 @@ export default class GraphQLHandler implements MeshHandler { } async getExecutorForHTTPSourceConfig( - httpSourceConfig: YamlConfig.GraphQLHandlerHTTPConfiguration + httpSourceConfig: YamlConfig.GraphQLHandlerHTTPConfiguration, ): Promise { const { endpoint, operationHeaders = {} } = httpSourceConfig; @@ -116,14 +126,16 @@ export default class GraphQLHandler implements MeshHandler { } async getNonExecutableSchemaForHTTPSource( - httpSourceConfig: YamlConfig.GraphQLHandlerHTTPConfiguration + httpSourceConfig: YamlConfig.GraphQLHandlerHTTPConfiguration, ): Promise { this.interpolationStringSet.add(httpSourceConfig.endpoint); Object.keys(httpSourceConfig.schemaHeaders || {}).forEach(headerName => { this.interpolationStringSet.add(headerName.toString()); }); - const schemaHeadersFactory = getInterpolatedHeadersFactory(httpSourceConfig.schemaHeaders || {}); + const schemaHeadersFactory = getInterpolatedHeadersFactory( + httpSourceConfig.schemaHeaders || {}, + ); if (httpSourceConfig.source) { const headers = schemaHeadersFactory({ env: process.env, @@ -137,7 +149,7 @@ export default class GraphQLHandler implements MeshHandler { fetch: this.fetchFn, logger: this.logger, headers, - } + }, ); if (typeof sdlOrIntrospection === 'string') { return buildSchema(sdlOrIntrospection); @@ -188,10 +200,9 @@ export default class GraphQLHandler implements MeshHandler { }; } else { // Loaders logic should be here somehow - const schemaOrStringOrDocumentNode = await loadFromModuleExportExpression( - schemaConfig, - { cwd: this.baseDir, defaultExportName: 'schema', importFn: this.importFn } - ); + const schemaOrStringOrDocumentNode = await loadFromModuleExportExpression< + GraphQLSchema | string | DocumentNode + >(schemaConfig, { cwd: this.baseDir, defaultExportName: 'schema', importFn: this.importFn }); let schema: GraphQLSchema; if (schemaOrStringOrDocumentNode instanceof GraphQLSchema) { schema = schemaOrStringOrDocumentNode; @@ -205,8 +216,8 @@ export default class GraphQLHandler implements MeshHandler { } else { throw new Error( `Provided file '${schemaConfig} exports an unknown type: ${util.inspect( - schemaOrStringOrDocumentNode - )}': expected GraphQLSchema, SDL or DocumentNode.` + schemaOrStringOrDocumentNode, + )}': expected GraphQLSchema, SDL or DocumentNode.`, ); } const { contextVariables } = this.getArgsAndContextVariables(); @@ -263,7 +274,10 @@ export default class GraphQLHandler implements MeshHandler { executorPromises.push(this.getExecutorForHTTPSourceConfig(httpSourceConfig)); } - const [schema, ...executors] = await Promise.all([Promise.race(schemaPromises), ...executorPromises]); + const [schema, ...executors] = await Promise.all([ + Promise.race(schemaPromises), + ...executorPromises, + ]); const executor = this.getRaceExecutor(executors); @@ -299,9 +313,13 @@ export default class GraphQLHandler implements MeshHandler { const executors = await Promise.all(executorPromises); const parsedSelectionSet = parseSelectionSet(this.config.strategyConfig.selectionSet); const valuePath = this.config.strategyConfig.value; - const highestValueExecutor = async function highestValueExecutor(executionRequest: ExecutionRequest) { + const highestValueExecutor = async function highestValueExecutor( + executionRequest: ExecutionRequest, + ) { const operationAST = getOperationASTFromRequest(executionRequest); - (operationAST.selectionSet.selections as SelectionNode[]).push(...parsedSelectionSet.selections); + (operationAST.selectionSet.selections as SelectionNode[]).push( + ...parsedSelectionSet.selections, + ); const results = await Promise.all(executors.map(executor => executor(executionRequest))); let highestValue = -Infinity; let resultWithHighestResult = results[0]; @@ -367,12 +385,16 @@ export default class GraphQLHandler implements MeshHandler { ]); if (schemaResult.status === 'rejected') { throw new Error( - `Failed to fetch introspection from ${this.config.endpoint}: ${util.inspect(schemaResult.reason)}` + `Failed to fetch introspection from ${this.config.endpoint}: ${util.inspect( + schemaResult.reason, + )}`, ); } if (executorResult.status === 'rejected') { throw new Error( - `Failed to create executor for ${this.config.endpoint}: ${util.inspect(executorResult.reason)}` + `Failed to create executor for ${this.config.endpoint}: ${util.inspect( + executorResult.reason, + )}`, ); } const { contextVariables } = this.getArgsAndContextVariables(); diff --git a/packages/handlers/graphql/test/handler.spec.ts b/packages/handlers/graphql/test/handler.spec.ts index fec5d392eec6d..468988b0f73b5 100644 --- a/packages/handlers/graphql/test/handler.spec.ts +++ b/packages/handlers/graphql/test/handler.spec.ts @@ -38,7 +38,9 @@ describe('graphql', () => { const { schema: schemaFromHandler } = await handler.getMeshSource({ fetchFn, }); - expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual(introspectionFromSchema(schemaFromFile)); + expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual( + introspectionFromSchema(schemaFromFile), + ); }); it('handle code files exports GraphQLSchema correctly', async () => { const schemaFilePath = './fixtures/schema.js'; @@ -63,7 +65,9 @@ describe('graphql', () => { const { schema: schemaFromHandler } = await handler.getMeshSource({ fetchFn, }); - expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual(introspectionFromSchema(schemaFromFile)); + expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual( + introspectionFromSchema(schemaFromFile), + ); }); it('handle code files exports DocumentNode correctly', async () => { const schemaFilePath = './fixtures/schema-document.js'; @@ -89,7 +93,9 @@ describe('graphql', () => { const { schema: schemaFromHandler } = await handler.getMeshSource({ fetchFn, }); - expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual(introspectionFromSchema(schemaFromFile)); + expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual( + introspectionFromSchema(schemaFromFile), + ); }); it('handle code files exports string correctly', async () => { const schemaFilePath = './fixtures/schema-str.js'; @@ -115,6 +121,8 @@ describe('graphql', () => { const { schema: schemaFromHandler } = await handler.getMeshSource({ fetchFn, }); - expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual(introspectionFromSchema(schemaFromFile)); + expect(introspectionFromSchema(schemaFromHandler)).toStrictEqual( + introspectionFromSchema(schemaFromFile), + ); }); }); diff --git a/packages/handlers/mysql/src/mysql.d.ts b/packages/handlers/mysql/src/mysql.d.ts index 8533a09748240..0033e61798129 100644 --- a/packages/handlers/mysql/src/mysql.d.ts +++ b/packages/handlers/mysql/src/mysql.d.ts @@ -73,10 +73,20 @@ declare module 'mysql' { limit: number[], where: any, orderBy: any, - callback: Callback + callback: Callback, + ); + select( + tableName: string, + fields: string[], + where: any, + orderBy: any, + callback: Callback, + ); + insert( + tableName: string, + record: Record, + callback: Callback<{ recordId: string | number }>, ); - select(tableName: string, fields: string[], where: any, orderBy: any, callback: Callback); - insert(tableName: string, record: Record, callback: Callback<{ recordId: string | number }>); update(tableName: string, input: any, where: any, callback: Callback<{ affectedRows: any }>); delete(tableName: string, where: any, callback: Callback<{ affectedRows: any }>); count(tableName: string, where: any, callback: Callback); diff --git a/packages/handlers/mysql/src/promisify.ts b/packages/handlers/mysql/src/promisify.ts index c79e8a069da85..0c63a2ff1ffdd 100644 --- a/packages/handlers/mysql/src/promisify.ts +++ b/packages/handlers/mysql/src/promisify.ts @@ -1,23 +1,26 @@ declare module 'util' { - export function promisify(f: (cb: (err: any, res: T) => void) => void, thisContext?: any): () => Promise; + export function promisify( + f: (cb: (err: any, res: T) => void) => void, + thisContext?: any, + ): () => Promise; export function promisify( f: (arg: A, cb: (err: any, res: T) => void) => void, - thisContext?: any + thisContext?: any, ): (arg: A) => Promise; export function promisify( f: (arg: A, arg2: A2, cb: (err: any, res: T) => void) => void, - thisContext?: any + thisContext?: any, ): (arg: A, arg2: A2) => Promise; export function promisify( f: (arg: A, arg2: A2, arg3: A3, cb: (err: any, res: T) => void) => void, - thisContext?: any + thisContext?: any, ): (arg: A, arg2: A2, arg3: A3) => Promise; export function promisify( f: (arg: A, arg2: A2, arg3: A3, arg4: A4, cb: (err: any, res: T) => void) => void, - thisContext?: any + thisContext?: any, ): (arg: A, arg2: A2, arg3: A3, arg4: A4) => Promise; export function promisify( f: (arg: A, arg2: A2, arg3: A3, arg4: A4, arg5: A5, cb: (err: any, res: T) => void) => void, - thisContext?: any + thisContext?: any, ): (arg: A, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Promise; } diff --git a/packages/handlers/postgraphile/src/index.ts b/packages/handlers/postgraphile/src/index.ts index 2aca319c19a56..780c6f5413fce 100644 --- a/packages/handlers/postgraphile/src/index.ts +++ b/packages/handlers/postgraphile/src/index.ts @@ -60,7 +60,9 @@ export default class PostGraphileHandler implements MeshHandler { if (!pgPool || !('connect' in pgPool)) { const pgLogger = this.logger.child('PostgreSQL'); pgPool = new pg.Pool({ - connectionString: stringInterpolator.parse(this.config.connectionString, { env: process.env }), + connectionString: stringInterpolator.parse(this.config.connectionString, { + env: process.env, + }), log: messages => pgLogger.debug(messages), ...this.config?.pool, }); @@ -85,8 +87,8 @@ export default class PostGraphileHandler implements MeshHandler { cwd: this.baseDir, importFn: this.importFn, defaultExportName: 'default', - }) - ) + }), + ), ); const skipPlugins = await Promise.all( (this.config.skipPlugins || []).map(pluginName => @@ -94,8 +96,8 @@ export default class PostGraphileHandler implements MeshHandler { cwd: this.baseDir, importFn: this.importFn, defaultExportName: 'default', - }) - ) + }), + ), ); const options = await loadFromModuleExportExpression(this.config.options, { cwd: this.baseDir, @@ -129,7 +131,14 @@ export default class PostGraphileHandler implements MeshHandler { return { schema, - executor({ document, variables, context: meshContext, rootValue, operationName, extensions }) { + executor({ + document, + variables, + context: meshContext, + rootValue, + operationName, + extensions, + }) { return withPostGraphileContext( { pgPool, @@ -149,7 +158,7 @@ export default class PostGraphileHandler implements MeshHandler { operationName, extensions, }) as any; - } + }, ) as any; }, }; diff --git a/packages/handlers/soap/src/index.ts b/packages/handlers/soap/src/index.ts index 9331935e98c40..066b66337fab0 100644 --- a/packages/handlers/soap/src/index.ts +++ b/packages/handlers/soap/src/index.ts @@ -20,9 +20,18 @@ export default class SoapHandler implements MeshHandler { private importFn: ImportFn; private logger: Logger; - constructor({ config, store, baseDir, importFn, logger }: MeshHandlerOptions) { + constructor({ + config, + store, + baseDir, + importFn, + logger, + }: MeshHandlerOptions) { this.config = config; - this.soapSDLProxy = store.proxy('schemaWithAnnotations.graphql', PredefinedProxyOptions.GraphQLSchemaWithDiffing); + this.soapSDLProxy = store.proxy( + 'schemaWithAnnotations.graphql', + PredefinedProxyOptions.GraphQLSchemaWithDiffing, + ); this.baseDir = baseDir; this.importFn = importFn; this.logger = logger; diff --git a/packages/handlers/thrift/src/index.ts b/packages/handlers/thrift/src/index.ts index 10620a544e842..7e0271fe812cc 100644 --- a/packages/handlers/thrift/src/index.ts +++ b/packages/handlers/thrift/src/index.ts @@ -8,7 +8,13 @@ import { GetMeshSourcePayload, MeshSource, } from '@graphql-mesh/types'; -import { parse, ThriftDocument, SyntaxType, Comment, FunctionType } from '@creditkarma/thrift-parser'; +import { + parse, + ThriftDocument, + SyntaxType, + Comment, + FunctionType, +} from '@creditkarma/thrift-parser'; import { readFileOrUrl } from '@graphql-mesh/utils'; import { GraphQLEnumType, @@ -48,7 +54,10 @@ import { import { pascalCase } from 'pascal-case'; import { PredefinedProxyOptions, StoreProxy } from '@graphql-mesh/store'; import { AggregateError } from '@graphql-tools/utils'; -import { parseInterpolationStrings, getInterpolatedHeadersFactory } from '@graphql-mesh/string-interpolation'; +import { + parseInterpolationStrings, + getInterpolatedHeadersFactory, +} from '@graphql-mesh/string-interpolation'; import { process, util } from '@graphql-mesh/cross-helpers'; export default class ThriftHandler implements MeshHandler { @@ -59,7 +68,13 @@ export default class ThriftHandler implements MeshHandler { private importFn: ImportFn; private logger: Logger; - constructor({ config, baseDir, store, importFn, logger }: MeshHandlerOptions) { + constructor({ + config, + baseDir, + store, + importFn, + logger, + }: MeshHandlerOptions) { this.config = config; this.baseDir = baseDir; this.idl = store.proxy('idl.json', PredefinedProxyOptions.JsonWithoutValidation); @@ -101,10 +116,24 @@ export default class ThriftHandler implements MeshHandler { [methodName: string]: number; } = {}; - type TypeVal = BaseTypeVal | ListTypeVal | SetTypeVal | MapTypeVal | EnumTypeVal | StructTypeVal | VoidTypeVal; + type TypeVal = + | BaseTypeVal + | ListTypeVal + | SetTypeVal + | MapTypeVal + | EnumTypeVal + | StructTypeVal + | VoidTypeVal; type BaseTypeVal = { id?: number; - type: TType.BOOL | TType.BYTE | TType.DOUBLE | TType.I16 | TType.I32 | TType.I64 | TType.STRING; + type: + | TType.BOOL + | TType.BYTE + | TType.DOUBLE + | TType.I16 + | TType.I32 + | TType.I64 + | TType.STRING; }; type ListTypeVal = { id?: number; type: TType.LIST; elementType: TypeVal }; type SetTypeVal = { id?: number; type: TType.SET; elementType: TypeVal }; @@ -282,7 +311,7 @@ export default class ThriftHandler implements MeshHandler { id, }, args, - output + output, ); output.writeMessageEnd(); const data: Buffer = await this.connection.send(writer.flush(), context); @@ -302,14 +331,14 @@ export default class ThriftHandler implements MeshHandler { } else { throw new TApplicationException( TApplicationExceptionType.UNKNOWN, - methodName + ' failed: unknown result' + methodName + ' failed: unknown result', ); } } } else { throw new TApplicationException( TApplicationExceptionType.WRONG_METHOD_NAME, - 'Received a response to an unknown RPC function: ' + fieldName + 'Received a response to an unknown RPC function: ' + fieldName, ); } } @@ -327,7 +356,7 @@ export default class ThriftHandler implements MeshHandler { function getGraphQLFunctionType( functionType: FunctionType, - id = Math.random() + id = Math.random(), ): { outputType: GraphQLOutputType; inputType: GraphQLInputType; typeVal: TypeVal } { let inputType: GraphQLInputType; let outputType: GraphQLOutputType; @@ -397,7 +426,11 @@ export default class ThriftHandler implements MeshHandler { outputType = GraphQLJSON; const ofTypeKey = getGraphQLFunctionType(functionType.keyType, id); const ofTypeValue = getGraphQLFunctionType(functionType.valueType, id); - typeVal = typeVal! || { type: TType.MAP, keyType: ofTypeKey.typeVal, valType: ofTypeValue.typeVal }; + typeVal = typeVal! || { + type: TType.MAP, + keyType: ofTypeKey.typeVal, + valType: ofTypeValue.typeVal, + }; break; } case SyntaxType.Identifier: { @@ -429,7 +462,9 @@ export default class ThriftHandler implements MeshHandler { }; } - const { args: commonArgs, contextVariables } = parseInterpolationStrings(Object.values(operationHeaders || {})); + const { args: commonArgs, contextVariables } = parseInterpolationStrings( + Object.values(operationHeaders || {}), + ); const headersFactory = getInterpolatedHeadersFactory(operationHeaders); @@ -449,9 +484,9 @@ export default class ThriftHandler implements MeshHandler { value: curr.name.value, }, }), - {} as GraphQLEnumValueConfigMap + {} as GraphQLEnumValueConfigMap, ), - }) + }), ); break; case SyntaxType.StructDefinition: { @@ -472,7 +507,10 @@ export default class ThriftHandler implements MeshHandler { let fieldOutputType: GraphQLOutputType; let fieldInputType: GraphQLInputType; const description = processComments(field.comments); - const processedFieldTypes = getGraphQLFunctionType(field.fieldType, field.fieldID?.value); + const processedFieldTypes = getGraphQLFunctionType( + field.fieldType, + field.fieldID?.value, + ); fieldOutputType = processedFieldTypes.outputType; fieldInputType = processedFieldTypes.inputType; @@ -497,7 +535,7 @@ export default class ThriftHandler implements MeshHandler { name: structName, description, fields: objectFields, - }) + }), ); inputTypeMap.set( structName, @@ -505,7 +543,7 @@ export default class ThriftHandler implements MeshHandler { name: structName + 'Input', description, fields: inputObjectFields, - }) + }), ); break; } @@ -514,20 +552,28 @@ export default class ThriftHandler implements MeshHandler { const fn = statement.functions[fnIndex]; const fnName = fn.name.value; const description = processComments(fn.comments); - const { outputType: returnType } = getGraphQLFunctionType(fn.returnType, Number(fnIndex) + 1); + const { outputType: returnType } = getGraphQLFunctionType( + fn.returnType, + Number(fnIndex) + 1, + ); const args: GraphQLFieldConfigArgumentMap = {}; for (const argName in commonArgs) { const typeNameOrType = commonArgs[argName].type; args[argName] = { type: - typeof typeNameOrType === 'string' ? inputTypeMap.get(typeNameOrType) : typeNameOrType || GraphQLID, + typeof typeNameOrType === 'string' + ? inputTypeMap.get(typeNameOrType) + : typeNameOrType || GraphQLID, }; } const fieldTypeMap: TypeMap = {}; for (const field of fn.fields) { const fieldName = field.name.value; const fieldDescription = processComments(field.comments); - let { inputType: fieldType, typeVal } = getGraphQLFunctionType(field.fieldType, field.fieldID?.value); + let { inputType: fieldType, typeVal } = getGraphQLFunctionType( + field.fieldType, + field.fieldID?.value, + ); if (field.requiredness === 'required') { fieldType = new GraphQLNonNull(fieldType); } @@ -552,7 +598,10 @@ export default class ThriftHandler implements MeshHandler { } break; case SyntaxType.TypedefDefinition: { - const { inputType, outputType } = getGraphQLFunctionType(statement.definitionType, Math.random()); + const { inputType, outputType } = getGraphQLFunctionType( + statement.definitionType, + Math.random(), + ); const typeName = statement.name.value; inputTypeMap.set(typeName, inputType); outputTypeMap.set(typeName, outputType); diff --git a/packages/handlers/thrift/test/handler.spec.ts b/packages/handlers/thrift/test/handler.spec.ts index 215e62e8af2bd..33160e0853b60 100644 --- a/packages/handlers/thrift/test/handler.spec.ts +++ b/packages/handlers/thrift/test/handler.spec.ts @@ -21,7 +21,10 @@ describe('thrift', () => { }, cache: new InMemoryLRUCache(), pubsub: new PubSub(), - store: new MeshStore('.mesh', new InMemoryStoreStorageAdapter(), { readonly: false, validate: false }), + store: new MeshStore('.mesh', new InMemoryStoreStorageAdapter(), { + readonly: false, + validate: false, + }), baseDir: __dirname, logger: new DefaultLogger('TEST'), importFn: m => import(m), diff --git a/packages/handlers/tuql/src/index.ts b/packages/handlers/tuql/src/index.ts index 2e4f063613fd5..326113a5417bc 100644 --- a/packages/handlers/tuql/src/index.ts +++ b/packages/handlers/tuql/src/index.ts @@ -13,10 +13,14 @@ export default class TuqlHandler implements MeshHandler { async getMeshSource(): Promise { const schema = await (this.config.infile ? buildSchemaFromInfile( - path.isAbsolute(this.config.infile) ? this.config.db : path.join(this.baseDir, this.config.infile) + path.isAbsolute(this.config.infile) + ? this.config.db + : path.join(this.baseDir, this.config.infile), ) : buildSchemaFromDatabase( - path.isAbsolute(this.config.db) ? this.config.infile : path.join(this.baseDir, this.config.db) + path.isAbsolute(this.config.db) + ? this.config.infile + : path.join(this.baseDir, this.config.db), )); return { diff --git a/packages/jit-executor/src/index.ts b/packages/jit-executor/src/index.ts index 497d679afe709..dbed833f7e31d 100644 --- a/packages/jit-executor/src/index.ts +++ b/packages/jit-executor/src/index.ts @@ -1,4 +1,9 @@ -import { ExecutionRequest, Executor, getOperationASTFromRequest, memoize1 } from '@graphql-tools/utils'; +import { + ExecutionRequest, + Executor, + getOperationASTFromRequest, + memoize1, +} from '@graphql-tools/utils'; import { CompiledQuery, compileQuery, isCompiledQuery } from 'graphql-jit'; import { createLruCache, printWithCache } from '@graphql-mesh/utils'; import { ExecutionResult, GraphQLSchema } from 'graphql'; @@ -15,7 +20,8 @@ export function createJITExecutor(schema: GraphQLSchema, prefix: string, logger: const documentStr = printWithCache(document); logger.debug(`Executing ${documentStr}`); const cacheKey = [prefix, documentStr, operationName].join('_'); - let compiledQueryFn: CompiledQuery['query'] | CompiledQuery['subscribe'] = lruCache.get(cacheKey); + let compiledQueryFn: CompiledQuery['query'] | CompiledQuery['subscribe'] = + lruCache.get(cacheKey); if (!compiledQueryFn) { logger.debug(`Compiling ${documentStr}`); const compiledQuery = compileQuery(schema, document, operationName); diff --git a/packages/json-machete/src/compareJSONSchemas.ts b/packages/json-machete/src/compareJSONSchemas.ts index fbc164e66a20a..b92c48f7cbea0 100644 --- a/packages/json-machete/src/compareJSONSchemas.ts +++ b/packages/json-machete/src/compareJSONSchemas.ts @@ -18,12 +18,16 @@ export async function compareJSONSchemas(oldSchema: JSONSchema, newSchema: JSONS } else { if (oldSubSchema.$ref) { if (newSubSchema?.$ref !== oldSubSchema.$ref) { - breakingChanges.push(`${path}/$ref is changed from ${oldSubSchema.$ref} to ${newSubSchema?.$ref}`); + breakingChanges.push( + `${path}/$ref is changed from ${oldSubSchema.$ref} to ${newSubSchema?.$ref}`, + ); } } if (oldSubSchema.const) { if (newSubSchema?.const !== oldSubSchema.const) { - breakingChanges.push(`${path}/const is changed from ${oldSubSchema.const} to ${newSubSchema?.const}`); + breakingChanges.push( + `${path}/const is changed from ${oldSubSchema.const} to ${newSubSchema?.const}`, + ); } } if (oldSubSchema.enum) { @@ -36,28 +40,28 @@ export async function compareJSONSchemas(oldSchema: JSONSchema, newSchema: JSONS if (oldSubSchema.format) { if (newSubSchema?.format !== oldSubSchema.format) { breakingChanges.push( - `${path}/format is changed from ${oldSubSchema.format} to ${newSubSchema?.format}` + `${path}/format is changed from ${oldSubSchema.format} to ${newSubSchema?.format}`, ); } } if (oldSubSchema.maxLength) { if (oldSubSchema.maxLength > newSubSchema?.maxLength) { breakingChanges.push( - `${path}/maxLength is changed from ${oldSubSchema.maxLength} to ${newSubSchema?.maxLength}` + `${path}/maxLength is changed from ${oldSubSchema.maxLength} to ${newSubSchema?.maxLength}`, ); } } if (oldSubSchema.minLength) { if (oldSubSchema.minLength < newSubSchema?.minLength) { breakingChanges.push( - `${path}/minLength is changed from ${oldSubSchema.minLength} to ${newSubSchema?.minLength}` + `${path}/minLength is changed from ${oldSubSchema.minLength} to ${newSubSchema?.minLength}`, ); } } if (oldSubSchema.pattern) { if (newSubSchema?.pattern?.toString() !== oldSubSchema.pattern.toString()) { breakingChanges.push( - `${path}/pattern is changed from ${oldSubSchema.pattern} to ${newSubSchema?.pattern}` + `${path}/pattern is changed from ${oldSubSchema.pattern} to ${newSubSchema?.pattern}`, ); } } @@ -80,7 +84,9 @@ export async function compareJSONSchemas(oldSchema: JSONSchema, newSchema: JSONS if (oldSubSchema.title) { if (newSubSchema?.title !== oldSubSchema.title) { - breakingChanges.push(`${path}/title is changed from ${oldSubSchema.title} to ${newSubSchema?.title}`); + breakingChanges.push( + `${path}/title is changed from ${oldSubSchema.title} to ${newSubSchema?.title}`, + ); } } @@ -94,7 +100,9 @@ export async function compareJSONSchemas(oldSchema: JSONSchema, newSchema: JSONS : !newSubSchema?.type.includes(oldSubSchema.type) : true ) { - breakingChanges.push(`${path}/type is changed from ${oldSubSchema.type} to ${newSubSchema?.type}`); + breakingChanges.push( + `${path}/type is changed from ${oldSubSchema.type} to ${newSubSchema?.type}`, + ); } } } @@ -105,12 +113,12 @@ export async function compareJSONSchemas(oldSchema: JSONSchema, newSchema: JSONS { visitedSubschemaResultMap: new WeakMap(), path: '', - } + }, ); if (breakingChanges.length > 0) { throw new AggregateError( breakingChanges.map(breakingChange => new Error(breakingChange)), - `Breaking changes are found:\n${breakingChanges.join('\n')}` + `Breaking changes are found:\n${breakingChanges.join('\n')}`, ); } } diff --git a/packages/json-machete/src/dereferenceObject.ts b/packages/json-machete/src/dereferenceObject.ts index 79d7b46e27c51..6706b17732b24 100644 --- a/packages/json-machete/src/dereferenceObject.ts +++ b/packages/json-machete/src/dereferenceObject.ts @@ -59,7 +59,6 @@ export function getCwd(path: string) { return isUrl(path) ? getCwdForUrl(path) : pathModule.dirname(path); } -// eslint-disable-next-line @typescript-eslint/ban-types export async function dereferenceObject( obj: T, { @@ -82,7 +81,7 @@ export async function dereferenceObject( logger?: any; resolvedObjects?: WeakSet; headers?: Record; - } = {} + } = {}, ): Promise { if (obj != null && typeof obj === 'object') { if (isRefObject(obj)) { @@ -149,7 +148,7 @@ export async function dereferenceObject( headers, root: externalFile, resolvedObjects, - } + }, ); refMap.set($ref, result); resolvedObjects.add(result); diff --git a/packages/json-machete/src/referenceJSONSchema.ts b/packages/json-machete/src/referenceJSONSchema.ts index ec13f4a4393d6..7e8f36a06d221 100644 --- a/packages/json-machete/src/referenceJSONSchema.ts +++ b/packages/json-machete/src/referenceJSONSchema.ts @@ -2,7 +2,10 @@ import { JSONSchemaObject } from './types.js'; import { visitJSONSchema } from './visitJSONSchema.js'; import { DefaultLogger } from '@graphql-mesh/utils'; -export async function referenceJSONSchema(schema: JSONSchemaObject, logger = new DefaultLogger('referenceJSONSchema')) { +export async function referenceJSONSchema( + schema: JSONSchemaObject, + logger = new DefaultLogger('referenceJSONSchema'), +) { const initialDefinitions: Record = {}; const { $ref: initialRef } = await visitJSONSchema(schema, { enter: (subSchema, { path }) => { @@ -54,7 +57,7 @@ export async function referenceJSONSchema(schema: JSONSchemaObject, logger = new } return subSchema; }, - } + }, ); return { $ref: initialRef, diff --git a/packages/json-machete/src/visitJSONSchema.ts b/packages/json-machete/src/visitJSONSchema.ts index 67cfd2f99bdc8..d1da496a3cee3 100644 --- a/packages/json-machete/src/visitJSONSchema.ts +++ b/packages/json-machete/src/visitJSONSchema.ts @@ -5,7 +5,10 @@ export interface JSONSchemaVisitorContext { path: string; } -export type JSONSchemaVisitor = (subSchema: any, context: JSONSchemaVisitorContext) => Promise | any; +export type JSONSchemaVisitor = ( + subSchema: any, + context: JSONSchemaVisitorContext, +) => Promise | any; const identicalFn = (a: T) => a; @@ -20,7 +23,14 @@ const objectFields = [ 'then', ] as const; -const dictFields = ['anyOf', 'allOf', 'oneOf', 'definitions', 'properties', 'patternProperties'] as const; +const dictFields = [ + 'anyOf', + 'allOf', + 'oneOf', + 'definitions', + 'properties', + 'patternProperties', +] as const; export async function visitJSONSchema( schema: JSONSchema, @@ -34,7 +44,7 @@ export async function visitJSONSchema( { visitedSubschemaResultMap, path }: JSONSchemaVisitorContext = { visitedSubschemaResultMap: new WeakMap(), path: '', - } + }, ): Promise { if (typeof schema === 'object') { if (!visitedSubschemaResultMap.has(schema)) { @@ -51,7 +61,7 @@ export async function visitJSONSchema( { visitedSubschemaResultMap, path: `${path}/${key}`, - } + }, ); } } @@ -62,7 +72,7 @@ export async function visitJSONSchema( enterResult[key][itemKey] = await visitJSONSchema( itemValue, { enter, leave }, - { visitedSubschemaResultMap, path: `${path}/${key}/${itemKey}` } + { visitedSubschemaResultMap, path: `${path}/${key}/${itemKey}` }, ); } } @@ -74,7 +84,7 @@ export async function visitJSONSchema( enterResult.components.schemas[schemaName] = await visitJSONSchema( subSchema, { enter, leave }, - { visitedSubschemaResultMap, path: `${path}/components/schemas/${schemaName}` } + { visitedSubschemaResultMap, path: `${path}/components/schemas/${schemaName}` }, ); } } diff --git a/packages/json-machete/tests/dereferenceObject.test.ts b/packages/json-machete/tests/dereferenceObject.test.ts index b945edb7f7e62..639b8d4f1cf48 100644 --- a/packages/json-machete/tests/dereferenceObject.test.ts +++ b/packages/json-machete/tests/dereferenceObject.test.ts @@ -60,7 +60,9 @@ describe('dereferenceObject', () => { expect(result.title).toBe('Container'); expect(result.properties.posts.items.title).toBe('Post'); expect(result.properties.posts.items.properties.author.title).toBe('Author'); - expect(result.properties.posts.items.properties.author === result.properties.authors.items).toBeTruthy(); + expect( + result.properties.posts.items.properties.author === result.properties.authors.items, + ).toBeTruthy(); }); it('should dereference external references', async () => { const result = await dereferenceObject( @@ -69,7 +71,7 @@ describe('dereferenceObject', () => { }, { cwd: __dirname, - } + }, ); expect(result.title).toBe('PostsResponse'); expect(result.properties.items.items.title).toBe('Post'); @@ -242,11 +244,12 @@ describe('dereferenceObject', () => { }, }; const dereferencedObject = await dereferenceObject(openapiSchema); - expect(dereferencedObject.paths['/pets/{petId}'].get.responses[200].content['application/json'].schema).toBe( - openapiSchema.components.schemas.Pet - ); - expect(dereferencedObject.paths['/pets'].get.responses[200].content['application/json'].schema).toBe( - openapiSchema.components.schemas.Pets - ); + expect( + dereferencedObject.paths['/pets/{petId}'].get.responses[200].content['application/json'] + .schema, + ).toBe(openapiSchema.components.schemas.Pet); + expect( + dereferencedObject.paths['/pets'].get.responses[200].content['application/json'].schema, + ).toBe(openapiSchema.components.schemas.Pets); }); }); diff --git a/packages/loaders/README.md b/packages/loaders/README.md index 31a375ee5c298..275f9d8a312b3 100644 --- a/packages/loaders/README.md +++ b/packages/loaders/README.md @@ -1,12 +1,17 @@ # Omnigraph -Omnigraph is a set of libraries and tools helps you generate local `GraphQLSchema` instances from different API Schema specifications such as JSON Schema, MySQL, SOAP, OpenAPI and RAML. +Omnigraph is a set of libraries and tools helps you generate local `GraphQLSchema` instances from +different API Schema specifications such as JSON Schema, MySQL, SOAP, OpenAPI and RAML. -You can consume this `GraphQLSchema` inside any tools in GraphQL Ecosystem such as GraphQL Config, GraphQL Code Generator and GraphQL ESLint. You can either bind it to a GraphQL Server like Envelop, Express-GraphQL, GraphQL Helix, Apollo Server or GraphQL Yoga. +You can consume this `GraphQLSchema` inside any tools in GraphQL Ecosystem such as GraphQL Config, +GraphQL Code Generator and GraphQL ESLint. You can either bind it to a GraphQL Server like Envelop, +Express-GraphQL, GraphQL Helix, Apollo Server or GraphQL Yoga. ### GraphQL Config -GraphQL Config is a way of specifying your GraphQL Project in a standard way so the most of the tools around GraphQL Ecosystem can recognize your project such as VSCode GraphQL Extension, GraphQL ESLint and GraphQL Code Generator +GraphQL Config is a way of specifying your GraphQL Project in a standard way so the most of the +tools around GraphQL Ecosystem can recognize your project such as VSCode GraphQL Extension, GraphQL +ESLint and GraphQL Code Generator ```yaml filename=".graphqlrc.yml" schema: ./packages/server/modules/**/*.graphql # Backend @@ -26,7 +31,10 @@ schema: ### GraphQL Code Generator -Let's say we want to create a type-safe SDK from the generated schema using GraphQL Code Generator and remember GraphQL Code Generator has nothing to do except GraphQL so Omnigraph helps GraphQL Config to consume the nonGraphQL source as GraphQL then it provides the schema and operations to GraphQL Code Generator; +Let's say we want to create a type-safe SDK from the generated schema using GraphQL Code Generator +and remember GraphQL Code Generator has nothing to do except GraphQL so Omnigraph helps GraphQL +Config to consume the nonGraphQL source as GraphQL then it provides the schema and operations to +GraphQL Code Generator; Like any other GraphQL project. We can use `extensions.codegen` @@ -64,9 +72,14 @@ export async function getOmnigraphSDK() { ### Bundling -As you can see above, Omnigraph is able to download sources via HTTP on runtime. But this has some downsides. The remote API might be down or we might have some bandwidth concerns to avoid. So Omnigraph has "Bundling" feature that helps to store the downloaded and resolved resources once ahead-of-time. But this needs some extra code files with programmatic usage by splitting buildtime and runtime configurations; +As you can see above, Omnigraph is able to download sources via HTTP on runtime. But this has some +downsides. The remote API might be down or we might have some bandwidth concerns to avoid. So +Omnigraph has "Bundling" feature that helps to store the downloaded and resolved resources once +ahead-of-time. But this needs some extra code files with programmatic usage by splitting buildtime +and runtime configurations; -We can create a script called `generate-bundle.ts` and every time we run `npm run generate-bundle` it will download the sources and generate the bundle. +We can create a script called `generate-bundle.ts` and every time we run `npm run generate-bundle` +it will download the sources and generate the bundle. ```ts filename="generate-bundle.js" import { createBundle } from '@omnigraph/openapi' @@ -121,5 +134,5 @@ schema: ### String interpolation on runtime You can have dynamic values in `operationHeaders` by using interpolation pattern; -`{context.apiToken}` or `{env.BASE_URL}` -In this case, `context` refers to the context you executed your schema with. +`{context.apiToken}` or `{env.BASE_URL}` In this case, `context` refers to the context you executed +your schema with. diff --git a/packages/loaders/json-schema/src/getValidTypeName.ts b/packages/loaders/json-schema/src/getValidTypeName.ts index 6c958dd01f9f1..e83d78f2977c3 100644 --- a/packages/loaders/json-schema/src/getValidTypeName.ts +++ b/packages/loaders/json-schema/src/getValidTypeName.ts @@ -15,7 +15,9 @@ export function getValidTypeName({ if (!subSchema.title) { throw new Error('Missing title for schema; ' + inspect(subSchema)); } - const sanitizedName = sanitizeNameForGraphQL(isInput ? subSchema.title + '_Input' : subSchema.title); + const sanitizedName = sanitizeNameForGraphQL( + isInput ? subSchema.title + '_Input' : subSchema.title, + ); if (schemaComposer.has(sanitizedName)) { let i = 2; while (schemaComposer.has(sanitizedName + i)) { diff --git a/packages/loaders/json-schema/src/utils.ts b/packages/loaders/json-schema/src/utils.ts index 82bde1c7d749a..22f3d5ecde213 100644 --- a/packages/loaders/json-schema/src/utils.ts +++ b/packages/loaders/json-schema/src/utils.ts @@ -2,7 +2,7 @@ import { OperationTypeNode } from 'graphql'; import { JSONSchemaOperationConfig, JSONSchemaPubSubOperationConfig, HTTPMethod } from './types.js'; export function isPubSubOperationConfig( - operationConfig: JSONSchemaOperationConfig + operationConfig: JSONSchemaOperationConfig, ): operationConfig is JSONSchemaPubSubOperationConfig { return 'pubsubTopic' in operationConfig; } @@ -55,7 +55,9 @@ export function cleanObject(obj: any) { return obj; } -export function isFileUpload(obj: any): obj is { createReadStream: () => AsyncIterable; mimetype: string } { +export function isFileUpload( + obj: any, +): obj is { createReadStream: () => AsyncIterable; mimetype: string } { return typeof obj.createReadStream === 'function'; } diff --git a/packages/loaders/openapi/src/utils.ts b/packages/loaders/openapi/src/utils.ts index 3d0b97c71a302..719a9d4b55e32 100644 --- a/packages/loaders/openapi/src/utils.ts +++ b/packages/loaders/openapi/src/utils.ts @@ -11,7 +11,10 @@ export function getFieldNameFromPath(path: string, method: string, responseTypeS let fieldNameWithoutMethod = actualParts.join('_'); // If path doesn't give any field name without identifiers, we can use the return type with HTTP Method name - if ((!fieldNameWithoutMethod || fieldNameWithoutMethod.startsWith('by')) && responseTypeSchemaRef) { + if ( + (!fieldNameWithoutMethod || fieldNameWithoutMethod.startsWith('by')) && + responseTypeSchemaRef + ) { const refArr = responseTypeSchemaRef.split('/'); // lowercase looks better in the schema const prefix = camelCase(refArr[refArr.length - 1]); diff --git a/packages/loaders/openapi/tests/calendly.test.ts b/packages/loaders/openapi/tests/calendly.test.ts index 9511c593a1d1e..f9c8d09e75f7b 100644 --- a/packages/loaders/openapi/tests/calendly.test.ts +++ b/packages/loaders/openapi/tests/calendly.test.ts @@ -26,7 +26,7 @@ describe('Calendly', () => { text: () => Promise.resolve(''), ok: true, - } as Response) + } as Response), ); const createdSchema = await loadGraphQLSchemaFromOpenAPI('calendly', { source: './fixtures/calendly.yml', @@ -35,7 +35,7 @@ describe('Calendly', () => { }); return graphql({ schema: createdSchema, source: query }).then((result: any) => { expect((fetch.mock.calls[0] as string[])[0]).toEqual( - 'https://api.calendly.com/scheduled_events?organization=http%3A%2F%2Fa%2F&count=20' + 'https://api.calendly.com/scheduled_events?organization=http%3A%2F%2Fa%2F&count=20', ); }); }); @@ -54,7 +54,7 @@ describe('Calendly', () => { text: () => Promise.resolve(''), ok: true, - } as Response) + } as Response), ); const createdSchema = await loadGraphQLSchemaFromOpenAPI('calendly', { source: './fixtures/calendly.yml', @@ -64,7 +64,7 @@ describe('Calendly', () => { return graphql({ schema: createdSchema, source: query }).then((result: any) => { expect((fetch.mock.calls[0] as string[])[0]).toEqual( - 'https://api.calendly.com/scheduled_events?invitee_email=a%40b.com&count=20' + 'https://api.calendly.com/scheduled_events?invitee_email=a%40b.com&count=20', ); }); }); diff --git a/packages/loaders/openapi/tests/example_api6_server.ts b/packages/loaders/openapi/tests/example_api6_server.ts index 5a063febfa522..5c2eba365b72c 100644 --- a/packages/loaders/openapi/tests/example_api6_server.ts +++ b/packages/loaders/openapi/tests/example_api6_server.ts @@ -49,7 +49,9 @@ export function startServer(PORT: number | string) { }); app.get('/api/eateries/:eatery/breads/:breadName/dishes/:dishKey', (req, res) => { - res.send(`Parameters combined: ${req.params.eatery} ${req.params.breadName} ${req.params.dishKey}`); + res.send( + `Parameters combined: ${req.params.eatery} ${req.params.breadName} ${req.params.dishKey}`, + ); }); // TODO: better types for this @@ -71,7 +73,10 @@ export function startServer(PORT: number | string) { app.get('/api/strictGetOperation', (req, res) => { if (req.headers['content-type']) { - res.status(400).set('Content-Type', 'text/plain').send('Get request should not have Content-Type'); + res + .status(400) + .set('Content-Type', 'text/plain') + .send('Get request should not have Content-Type'); } else { res.set('Content-Type', 'text/plain').send('Perfect!'); } diff --git a/packages/loaders/openapi/tests/example_api7_server.ts b/packages/loaders/openapi/tests/example_api7_server.ts index 79679b45d895a..81b6354b9014a 100644 --- a/packages/loaders/openapi/tests/example_api7_server.ts +++ b/packages/loaders/openapi/tests/example_api7_server.ts @@ -46,7 +46,10 @@ export function startServer() { if (req.body.userName && req.body.name) { const device = req.body; Devices[device.name] = device; - pubsub.publish(`webhook:post:/api/${device.userName}/devices/${req.method.toUpperCase()}`, device); + pubsub.publish( + `webhook:post:/api/${device.userName}/devices/${req.method.toUpperCase()}`, + device, + ); res.status(200).send(device); } else { res.status(404).send({ @@ -71,7 +74,10 @@ export function startServer() { const device = req.body; delete Devices[req.params.deviceName]; Devices[device.deviceName] = device; - pubsub.publish(`webhook:post:/api/${device.userName}/devices/${req.method.toUpperCase()}`, device); + pubsub.publish( + `webhook:post:/api/${device.userName}/devices/${req.method.toUpperCase()}`, + device, + ); res.status(200).send(device); } else { res.status(404).send({ diff --git a/packages/loaders/openapi/tests/explode.test.ts b/packages/loaders/openapi/tests/explode.test.ts index 411dda8e50620..0b77283b6bb63 100644 --- a/packages/loaders/openapi/tests/explode.test.ts +++ b/packages/loaders/openapi/tests/explode.test.ts @@ -17,7 +17,7 @@ describe('Explode parameter', () => { headers: { 'Content-Type': 'application/json', }, - } + }, ); }, }); diff --git a/packages/loaders/openapi/tests/fixtures/calendly.yml b/packages/loaders/openapi/tests/fixtures/calendly.yml index 3ed0b32d81fd1..b6f1fc65e2365 100644 --- a/packages/loaders/openapi/tests/fixtures/calendly.yml +++ b/packages/loaders/openapi/tests/fixtures/calendly.yml @@ -56,7 +56,9 @@ paths: schema: type: string default: 'created_at:asc' - description: 'Order results by the **created_at** field and direction specified: ascending ("asc") or descending ("desc")' + description: + 'Order results by the **created_at** field and direction specified: ascending ("asc") or + descending ("desc")' - name: email in: query schema: @@ -190,14 +192,16 @@ paths: example: 'https://api.calendly.com/organizations/EBHAAFHDCAEQTSEZ' in: query name: organization - description: Return events that are scheduled with the organization associated with this URI + description: + Return events that are scheduled with the organization associated with this URI - name: invitee_email in: query schema: type: string format: email example: alice@example.com - description: Return events that are scheduled with the invitee associated with this email address + description: + Return events that are scheduled with the invitee associated with this email address - name: status in: query schema: @@ -219,13 +223,17 @@ paths: in: query schema: type: string - description: 'Include events with start times after this time (sample time format: "2020-01-02T03:04:05.678123Z"). This time should use the UTC timezone.' + description: + 'Include events with start times after this time (sample time format: + "2020-01-02T03:04:05.678123Z"). This time should use the UTC timezone.' example: '2020-01-02T12:30:00.000000Z' - name: max_start_time in: query schema: type: string - description: 'Include events with start times prior to this time (sample time format: "2020-01-02T03:04:05.678123Z"). This time should use the UTC timezone.' + description: + 'Include events with start times prior to this time (sample time format: + "2020-01-02T03:04:05.678123Z"). This time should use the UTC timezone.' example: '2020-01-02T12:30:00.000000Z' - $ref: '#/components/parameters/PageToken' - $ref: '#/components/parameters/Count' @@ -309,19 +317,25 @@ paths: - personal_access_token: [] parameters: - name: active - description: 'Return only active event types if true, only inactive if false, or all event types if this parameter is omitted.' + description: + 'Return only active event types if true, only inactive if false, or all event types if + this parameter is omitted.' in: query schema: type: boolean - name: organization - description: "View available personal, team, and organization event types associated with the organization's URI." + description: + "View available personal, team, and organization event types associated with the + organization's URI." in: query schema: type: string format: uri required: false - name: user - description: "View available personal, team, and organization event types associated with the user's URI." + description: + "View available personal, team, and organization event types associated with the user's + URI." in: query schema: type: string @@ -923,7 +937,8 @@ paths: '500': $ref: '#/components/responses/UNKNOWN' operationId: get-organizations-uuid-invitations - description: Returns a list of Organization Invitations that were sent to the organization's members. + description: + Returns a list of Organization Invitations that were sent to the organization's members. security: - oauth2: [] - personal_access_token: [] @@ -935,7 +950,9 @@ paths: default: 'created_at:asc' in: query name: sort - description: Order results by the field name and direction specified (ascending or descending). Returns multiple sets of results in a comma-separated list. + description: + Order results by the field name and direction specified (ascending or descending). + Returns multiple sets of results in a comma-separated list. - schema: type: string format: email @@ -951,7 +968,9 @@ paths: - declined in: query name: status - description: 'Indicates if the results should be filtered by status ("pending", "accepted", or "declined")' + description: + 'Indicates if the results should be filtered by status ("pending", "accepted", or + "declined")' tags: - Organizations post: @@ -1008,7 +1027,9 @@ paths: Race Condition: value: title: Race Condition - message: A race condition occurred when processing the request. Please try the request again. + message: + A race condition occurred when processing the request. Please try the request + again. '401': $ref: '#/components/responses/UNAUTHENTICATED' '403': @@ -1025,7 +1046,9 @@ paths: message: type: string enum: - - You already sent all the invitations you're allotted based upon the number of seats purchased with your account. Please purchase more seats to send more invitations. + - You already sent all the invitations you're allotted based upon the number + of seats purchased with your account. Please purchase more seats to send + more invitations. - You already sent all the invitations allotted to you with a trial account. - You do not have permission - You cannot perform this action for an organization with SCIM enabled. @@ -1033,11 +1056,15 @@ paths: Quantity Overflow: value: title: Permission Denied - message: You already sent all the invitations you're allotted based upon the number of seats purchased with your account. Please purchase more seats to send more invitations. + message: + You already sent all the invitations you're allotted based upon the number of + seats purchased with your account. Please purchase more seats to send more + invitations. Trial Quantity Overflow: value: title: Permission Denied - message: You already sent all the invitations allotted to you with a trial account. + message: + You already sent all the invitations allotted to you with a trial account. '404': $ref: '#/components/responses/NOT_FOUND' '500': @@ -1108,7 +1135,9 @@ paths: '500': $ref: '#/components/responses/UNKNOWN' operationId: revoke-users-organization-invitation - description: 'Use this to revoke an Organization Invitation to an organization. Once revoked, the invitation link that was sent to the invitee is no longer valid.' + description: + 'Use this to revoke an Organization Invitation to an organization. Once revoked, the + invitation link that was sent to the invitee is no longer valid.' security: - oauth2: [] - personal_access_token: [] @@ -1463,7 +1492,9 @@ paths: properties: url: type: string - description: The URL where you want to receive POST requests for events you are subscribed to. + description: + The URL where you want to receive POST requests for events you are subscribed + to. format: uri events: type: array @@ -1477,7 +1508,8 @@ paths: - routing_form_submission.created organization: type: string - description: The unique reference to the organization that the webhook will be tied to. + description: + The unique reference to the organization that the webhook will be tied to. format: uri user: type: string @@ -1488,10 +1520,14 @@ paths: enum: - organization - user - description: Indicates if the webhook subscription scope will be "organization" or "user" + description: + Indicates if the webhook subscription scope will be "organization" or "user" signing_key: type: string - description: 'Optional secret key shared between your application and Calendly. See https://developer.calendly.com/api-docs/ZG9jOjM2MzE2MDM4-webhook-signatures for additional information.' + description: + 'Optional secret key shared between your application and Calendly. See + https://developer.calendly.com/api-docs/ZG9jOjM2MzE2MDM4-webhook-signatures for + additional information.' required: - url - events @@ -1588,7 +1624,9 @@ paths: format: uri in: query name: user - description: Indicates if the results should be filtered by user. This parameter is only required if the `scope` parameter is set to `user`. + description: + Indicates if the results should be filtered by user. This parameter is only required if + the `scope` parameter is set to `user`. - $ref: '#/components/parameters/PageToken' - $ref: '#/components/parameters/Count' - schema: @@ -1704,7 +1742,9 @@ paths: example: 'https://calendly.com/d/abcd-brv8/15-minute-meeting' owner: type: string - description: 'A link to the resource that owns this Scheduling Link (currently, this is always an Event Type)' + description: + 'A link to the resource that owns this Scheduling Link (currently, this is + always an Event Type)' format: uri example: 'https://api.calendly.com/event_types/GBGBDCAADAEDCRZ2' owner_type: @@ -1745,13 +1785,16 @@ paths: properties: max_event_count: type: number - description: The max number of events that can be scheduled using this scheduling link. + description: + The max number of events that can be scheduled using this scheduling link. enum: - 1 example: 1 owner: type: string - description: 'A link to the resource that owns this Scheduling Link (currently, this is always an Event Type)' + description: + 'A link to the resource that owns this Scheduling Link (currently, this is + always an Event Type)' format: uri example: 'https://api.calendly.com/event_types/012345678901234567890' owner_type: @@ -1830,7 +1873,10 @@ paths: Invalid Data Request Permission: value: title: Permission Denied - message: You must be an admin/owner with the data requests permission enabled to use this resource. Contact Calendly support and ask them to grant you data requests permission. + message: + You must be an admin/owner with the data requests permission enabled to use + this resource. Contact Calendly support and ask them to grant you data + requests permission. '404': $ref: '#/components/responses/NOT_FOUND' '500': @@ -2117,7 +2163,10 @@ paths: example: 'created_at:asc' in: query name: sort - description: 'Order results by the specified field and direction. Accepts comma-separated list of {field}:{direction} values. Supported fields are: created_at. Sort direction is specified as: asc, desc.' + description: + 'Order results by the specified field and direction. Accepts comma-separated list of + {field}:{direction} values. Supported fields are: created_at. Sort direction is + specified as: asc, desc.' '/routing_forms/{uuid}': parameters: - schema: @@ -2263,7 +2312,10 @@ paths: example: 'created_at:asc' in: query name: sort - description: 'Order results by the specified field and direction. Accepts comma-separated list of {field}:{direction} values. Supported fields are: created_at. Sort direction is specified as: asc, desc.' + description: + 'Order results by the specified field and direction. Accepts comma-separated list of + {field}:{direction} values. Supported fields are: created_at. Sort direction is + specified as: asc, desc.' x-internal: false '/routing_form_submissions/{uuid}': parameters: @@ -2478,7 +2530,8 @@ paths: - 'occurred_at:desc' default: - 'occurred_at:desc' - description: 'Order results by the specified field and direction. List of {field}:{direction} values.' + description: + 'Order results by the specified field and direction. List of {field}:{direction} values.' example: - 'occurred_at:asc' - name: min_occurred_at @@ -2486,14 +2539,18 @@ paths: schema: type: string format: date-time - description: 'Include entries that occurred after this time (sample time format: "2020-01-02T03:04:05.678Z"). This time should use the UTC timezone.' + description: + 'Include entries that occurred after this time (sample time format: + "2020-01-02T03:04:05.678Z"). This time should use the UTC timezone.' example: '2020-01-02T12:30:00Z' - name: max_occurred_at in: query schema: type: string format: date-time - description: 'Include entries that occurred prior to this time (sample time format: "2020-01-02T03:04:05.678Z"). This time should use the UTC timezone.' + description: + 'Include entries that occurred prior to this time (sample time format: + "2020-01-02T03:04:05.678Z"). This time should use the UTC timezone.' example: '2020-01-02T12:30:00Z' - name: page_token description: The token to pass to get the next portion of the collection @@ -2547,14 +2604,18 @@ paths: type: string format: date-time nullable: true - description: 'The date and time of the newest entry (format: "2020-01-02T03:04:05.678Z") in the collection array.' + description: + 'The date and time of the newest entry (format: "2020-01-02T03:04:05.678Z") in + the collection array.' total_count: type: integer description: Total number of records based on search criteria minimum: 0 exceeds_max_total_count: type: boolean - description: 'If there are more search results than the total_count field indicates, pagination will continue to return results past the total_count field value.' + description: + 'If there are more search results than the total_count field indicates, + pagination will continue to return results past the total_count field value.' required: - collection - pagination @@ -2647,7 +2708,9 @@ components: example: John Doe slug: type: string - description: "The portion of URL for the user's scheduling page (where invitees book sessions), rendered in a human-readable format" + description: + "The portion of URL for the user's scheduling page (where invitees book sessions), + rendered in a human-readable format" example: acmesales email: type: string @@ -2657,7 +2720,8 @@ components: scheduling_url: type: string format: uri - description: The URL of the user's Calendly landing page (that lists all the user's event types) + description: + The URL of the user's Calendly landing page (that lists all the user's event types) example: 'https://calendly.com/acmesales' timezone: type: string @@ -2673,12 +2737,15 @@ components: type: string format: date-time example: '2019-01-02T03:04:05.678123Z' - description: 'The moment when the user''s record was created (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the user''s record was created (e.g. "2020-01-02T03:04:05.678123Z")' updated_at: type: string format: date-time example: '2019-08-07T06:05:04.321123Z' - description: 'The moment when the user''s record was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the user''s record was last updated (e.g. + "2020-01-02T03:04:05.678123Z")' current_organization: type: string description: A unique reference to the user's current organization @@ -2785,7 +2852,9 @@ components: type: boolean slug: type: string - description: The portion of the event type's URL that identifies a specific web page (in a human-readable format) + description: + The portion of the event type's URL that identifies a specific web page (in a + human-readable format) example: acmesales nullable: true scheduling_url: @@ -2798,20 +2867,26 @@ components: type: number example: 30 kind: - description: Indicates if the event type is "solo" (belongs to an individual user) or "group" + description: + Indicates if the event type is "solo" (belongs to an individual user) or "group" type: string enum: - solo - group pooling_type: - description: Indicates if the event type is "round robin" (alternates between hosts) or "collective" (invitees pick a time when all participants are available) or "null" (the event type doesn’t consider the availability of a group participants) + description: + Indicates if the event type is "round robin" (alternates between hosts) or "collective" + (invitees pick a time when all participants are available) or "null" (the event type + doesn’t consider the availability of a group participants) type: string enum: - round_robin - collective nullable: true type: - description: Indicates if the event type is "AdhocEventType" (ad hoc event) or "StandardEventType" (standard event type) + description: + Indicates if the event type is "AdhocEventType" (ad hoc event) or "StandardEventType" + (standard event type) type: string enum: - StandardEventType @@ -2827,7 +2902,8 @@ components: format: date-time example: '2019-01-02T03:04:05.678123Z' updated_at: - description: 'The moment the event type was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment the event type was last updated (e.g. "2020-01-02T03:04:05.678123Z")' type: string format: date-time example: '2019-08-07T06:05:04.321123Z' @@ -2864,7 +2940,10 @@ components: $ref: '#/components/schemas/EventTypeCustomQuestion' deleted_at: type: string - description: 'The moment the event type was deleted (e.g. "2020-01-02T03:04:05.678123Z"). Since event types can be deleted but their scheduled events remain it''s useful to fetch a deleted event type when you still require event type data for a scheduled event.' + description: + 'The moment the event type was deleted (e.g. "2020-01-02T03:04:05.678123Z"). Since event + types can be deleted but their scheduled events remain it''s useful to fetch a deleted + event type when you still require event type data for a scheduled event.' format: date-time example: '2019-01-02T03:04:05.678123Z' nullable: true @@ -2894,7 +2973,9 @@ components: - Event Types type: object nullable: true - description: "The publicly visible profile of a User or a Team that's associated with the Event Type (note: some Event Types don't have profiles)" + description: + "The publicly visible profile of a User or a Team that's associated with the Event Type + (note: some Event Types don't have profiles)" title: Profile properties: type: @@ -2906,7 +2987,8 @@ components: example: User name: type: string - description: Human-readable name for the profile of the user that's associated with the event type + description: + Human-readable name for the profile of the user that's associated with the event type example: Tamara Jones owner: type: string @@ -2971,11 +3053,15 @@ components: start_time: type: string format: date-time - description: 'The moment the event was scheduled to start in UTC time (e.g. "2020-01-02T03:04:05.678123Z").' + description: + 'The moment the event was scheduled to start in UTC time (e.g. + "2020-01-02T03:04:05.678123Z").' end_time: type: string format: date-time - description: 'The moment the event was scheduled to end in UTC time (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment the event was scheduled to end in UTC time (e.g. + "2020-01-02T03:04:05.678123Z")' event_type: type: string description: The event type associated with this event @@ -3007,7 +3093,8 @@ components: updated_at: type: string format: date-time - description: 'The moment when the event was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the event was last updated (e.g. "2020-01-02T03:04:05.678123Z")' example: '2019-01-02T03:04:05.678123Z' event_memberships: type: array @@ -3160,12 +3247,18 @@ components: example: test@example.com first_name: type: string - description: The first name of the invitee who booked the event when the event type is configured to use separate fields for first name and last name. Null when event type is configured to use a single field for name. + description: + The first name of the invitee who booked the event when the event type is configured to + use separate fields for first name and last name. Null when event type is configured to + use a single field for name. example: John nullable: true last_name: type: string - description: The last name of the invitee who booked the event when the event type is configured to use separate fields for first name and last name. Null when event type is configured to use a single field for name. + description: + The last name of the invitee who booked the event when the event type is configured to + use separate fields for first name and last name. Null when event type is configured to + use a single field for name. example: Doe nullable: true name: @@ -3180,7 +3273,9 @@ components: description: Indicates if the invitee is "active" or "canceled" questions_and_answers: type: array - description: A collection of the invitee's responses to questions on the event booking confirmation form + description: + A collection of the invitee's responses to questions on the event booking confirmation + form minItems: 0 uniqueItems: true items: @@ -3203,7 +3298,8 @@ components: type: string format: date-time example: '2019-08-07T06:05:04.321123Z' - description: 'The moment when the event was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the event was last updated (e.g. "2020-01-02T03:04:05.678123Z")' tracking: $ref: '#/components/schemas/InviteeTracking' text_reminder_number: @@ -3213,7 +3309,9 @@ components: nullable: true rescheduled: type: boolean - description: 'Indicates if this invitee has rescheduled. If `true`, a reference to the new Invitee instance is provided in the `new_invitee` field.' + description: + 'Indicates if this invitee has rescheduled. If `true`, a reference to the new Invitee + instance is provided in the `new_invitee` field.' old_invitee: type: string format: uri @@ -3236,7 +3334,8 @@ components: type: string format: uri example: 'https://api.calendly.com/routing_form_submissions/AAAAAAAAAAAAAAAA' - description: Reference to a routing form submission that redirected the invitee to a booking page. + description: + Reference to a routing form submission that redirected the invitee to a booking page. nullable: true cancellation: $ref: '#/components/schemas/Cancellation' @@ -3301,7 +3400,11 @@ components: description: The moment when the no show was created reconfirmation: type: object - description: 'Assuming reconfirmation is enabled for the event type, when reconfirmation is requested this object is present with a `created_at` that reflects when the reconfirmation notification was sent. Once the invitee has reconfirmed the `confirmed_at` attribute will change from `null` to a timestamp that reflects when they took action.' + description: + 'Assuming reconfirmation is enabled for the event type, when reconfirmation is requested + this object is present with a `created_at` that reflects when the reconfirmation + notification was sent. Once the invitee has reconfirmed the `confirmed_at` attribute + will change from `null` to a timestamp that reflects when they took action.' required: - created_at - confirmed_at @@ -3456,7 +3559,9 @@ components: example: John Doe slug: type: string - description: "The portion of URL for the user's scheduling page (where invitees book sessions), rendered in a human-readable format" + description: + "The portion of URL for the user's scheduling page (where invitees book sessions), + rendered in a human-readable format" example: acmesales email: type: string @@ -3466,7 +3571,8 @@ components: scheduling_url: type: string format: uri - description: The URL of the user's Calendly landing page (that lists all the user's event types) + description: + The URL of the user's Calendly landing page (that lists all the user's event types) example: 'https://calendly.com/acmesales' timezone: type: string @@ -3482,12 +3588,15 @@ components: type: string format: date-time example: '2019-01-02T03:04:05.678123Z' - description: 'The moment when the user''s record was created (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the user''s record was created (e.g. "2020-01-02T03:04:05.678123Z")' updated_at: type: string format: date-time example: '2019-08-07T06:05:04.321123Z' - description: 'The moment when the user''s record was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the user''s record was last updated (e.g. + "2020-01-02T03:04:05.678123Z")' organization: type: string format: uri @@ -3497,12 +3606,15 @@ components: type: string format: date-time example: '2019-08-07T06:05:04.321123Z' - description: 'The moment when the membership record was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the membership record was last updated (e.g. + "2020-01-02T03:04:05.678123Z")' created_at: type: string format: date-time example: '2019-01-02T03:04:05.678123Z' - description: 'The moment when the membership record was created (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the membership record was created (e.g. "2020-01-02T03:04:05.678123Z")' required: - uri - role @@ -3565,17 +3677,20 @@ components: type: string format: date-time example: '2019-01-02T03:04:05.678123Z' - description: 'The moment the invitation was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment the invitation was last updated (e.g. "2020-01-02T03:04:05.678123Z")' last_sent_at: type: string nullable: true - description: 'The moment the invitation was last sent (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment the invitation was last sent (e.g. "2020-01-02T03:04:05.678123Z")' format: date-time example: '2019-01-02T03:04:05.678123Z' user: type: string format: uri - description: 'When the invitation is accepted, a reference to the user who accepted the invitation' + description: + 'When the invitation is accepted, a reference to the user who accepted the invitation' example: 'https://api.calendly.com/users/AAAAAAAAAAAAAAAA' required: - uri @@ -3749,11 +3864,15 @@ components: example: 'https://blah.foo/bar' created_at: type: string - description: 'The moment when the webhook subscription was created (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the webhook subscription was created (e.g. + "2020-01-02T03:04:05.678123Z")' format: date-time updated_at: type: string - description: 'The moment when the webhook subscription was last updated (e.g. "2020-01-02T03:04:05.678123Z")' + description: + 'The moment when the webhook subscription was last updated (e.g. + "2020-01-02T03:04:05.678123Z")' format: date-time retry_started_at: type: string @@ -3973,14 +4092,17 @@ components: submitter: type: string example: 'https://calendly.com/scheduled_events/AAAAAAAAAAAAAAAA/invitees/AAAAAAAAAAAAAAAA' - description: The reference to the Invitee resource when routing form submission results in a scheduled meeting. + description: + The reference to the Invitee resource when routing form submission results in a + scheduled meeting. format: uri nullable: true submitter_type: type: string enum: - Invitee - description: Type of the respondent resource that submitted the form and scheduled a meeting. + description: + Type of the respondent resource that submitted the form and scheduled a meeting. nullable: true created_at: type: string @@ -4020,7 +4142,10 @@ components: example: available invitees_remaining: type: number - description: 'Total remaining invitees for this available time. For Group Event Type, more than one invitee can book in this available time. For all other Event Types, only one invitee can book in this available time.' + description: + 'Total remaining invitees for this available time. For Group Event Type, more than one + invitee can book in this available time. For all other Event Types, only one invitee can + book in this available time.' example: 2 start_time: type: string @@ -4125,16 +4250,24 @@ components: - phone_number - single_select - multi_select - description: 'The type of response that the invitee provides to the custom question; can be one or multiple lines of text, a phone number, or single- or multiple-select.' + description: + 'The type of response that the invitee provides to the custom question; can be one or + multiple lines of text, a phone number, or single- or multiple-select.' position: type: number - description: The numerical position of the question on the event booking page after the name and email address fields. + description: + The numerical position of the question on the event booking page after the name and + email address fields. enabled: type: boolean - description: true if the question created by the host is turned ON and visible on the event booking page; false if turned OFF and invisible on the event booking page. + description: + true if the question created by the host is turned ON and visible on the event booking + page; false if turned OFF and invisible on the event booking page. required: type: boolean - description: true if a response to the question created by the host is required for invitees to book the event type; false if not required. + description: + true if a response to the question created by the host is required for invitees to book + the event type; false if not required. answer_choices: type: array description: The invitee’s option(s) for single_select or multi_select type of responses. @@ -4142,7 +4275,9 @@ components: type: string include_other: type: boolean - description: true if the custom question lets invitees record a written response in addition to single-select or multiple-select type of responses; false if it doesn’t. + description: + true if the custom question lets invitees record a written response in addition to + single-select or multiple-select type of responses; false if it doesn’t. required: - name - type @@ -4209,11 +4344,14 @@ components: utm_source: type: string nullable: true - description: The UTM parameter that identifies the source (platform where the traffic originates) + description: + The UTM parameter that identifies the source (platform where the traffic originates) utm_medium: type: string nullable: true - description: 'The UTM parameter that identifies the type of input (e.g. Cost Per Click (CPC), social media, affiliate or QR code)' + description: + 'The UTM parameter that identifies the type of input (e.g. Cost Per Click (CPC), social + media, affiliate or QR code)' utm_content: type: string nullable: true @@ -4269,23 +4407,31 @@ components: type: string nullable: true format: uri - description: URI to return the next page of an ordered list ("null" indicates no additional results are available) + description: + URI to return the next page of an ordered list ("null" indicates no additional results + are available) example: 'https://api.calendly.com/event_types?count=1&page_token=sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi' previous_page: type: string nullable: true format: uri - description: URI to return the previous page of an ordered list ("null" indicates no additional results are available) + description: + URI to return the previous page of an ordered list ("null" indicates no additional + results are available) example: 'https://api.calendly.com/event_types?count=1&page_token=VJs2rfDYeY8ahZpq0QI1O114LJkNjd7H' next_page_token: type: string nullable: true - description: Token to return the next page of an ordered list ("null" indicates no additional results are available) + description: + Token to return the next page of an ordered list ("null" indicates no additional results + are available) example: sNjq4TvMDfUHEl7zHRR0k0E1PCEJWvdi previous_page_token: type: string nullable: true - description: Token to return the previous page of an ordered list ("null" indicates no additional results are available) + description: + Token to return the previous page of an ordered list ("null" indicates no additional + results are available) example: VJs2rfDYeY8ahZpq0QI1O114LJkNjd7H required: - count @@ -4464,7 +4610,9 @@ components: type: string enum: - custom - description: The event location doesn't fall into a standard category defined by the event host (publisher) + description: + The event location doesn't fall into a standard category defined by the event host + (publisher) location: nullable: true description: The location description provided by the event host (publisher) @@ -4473,7 +4621,8 @@ components: - type - location GoogleConference: - description: Details about an Event that will take place using a Google Meet / Hangout conference + description: + Details about an Event that will take place using a Google Meet / Hangout conference type: object title: Google Conference x-examples: @@ -4966,7 +5115,9 @@ components: - textarea - select - radios - description: 'Question type: name, text input, email, phone, textarea input, dropdown list or radio button list.' + description: + 'Question type: name, text input, email, phone, textarea input, dropdown list or radio + button list.' required: type: boolean description: | @@ -5002,7 +5153,8 @@ components: type: string enum: - custom_message - description: Indicates if the routing form submission resulted in a custom "thank you" message. + description: + Indicates if the routing form submission resulted in a custom "thank you" message. value: type: object required: @@ -5038,7 +5190,9 @@ components: type: string enum: - event_type - description: Indicates that the routing form submission resulted in a redirect to an event type booking page. + description: + Indicates that the routing form submission resulted in a redirect to an event type + booking page. value: type: string example: 'https://api.calendly.com/event_types/GBGBDCAADAEDCRZ2' @@ -5064,7 +5218,8 @@ components: type: string enum: - external_url - description: Indicates that the routing form submission resulted in a redirect to an external URL. + description: + Indicates that the routing form submission resulted in a redirect to an external URL. value: type: string format: uri @@ -5140,7 +5295,8 @@ components: utm_content: UTM Content utm_term: UTM Term salesforce_uuid: 5003000000D8cuIQAA - description: The UTM and Salesforce tracking parameters associated with a Routing Form Submission. + description: + The UTM and Salesforce tracking parameters associated with a Routing Form Submission. x-tags: - Routing Forms properties: @@ -5150,11 +5306,14 @@ components: nullable: true utm_source: type: string - description: The UTM parameter that identifies the source (platform where the traffic originates). + description: + The UTM parameter that identifies the source (platform where the traffic originates). nullable: true utm_medium: type: string - description: 'The UTM parameter that identifies the type of input (e.g. Cost Per Click (CPC), social media, affiliate or QR code).' + description: + 'The UTM parameter that identifies the type of input (e.g. Cost Per Click (CPC), social + media, affiliate or QR code).' nullable: true utm_content: type: string @@ -5234,7 +5393,8 @@ components: - You are not allowed to view this event - Please upgrade your Calendly account to Professional - Please upgrade your Calendly account to Enterprise. - - Please also specify organization when requesting events for a user within your organization. + - Please also specify organization when requesting events for a user within + your organization. - Unauthorized - You cannot perform this action for an organization with SCIM enabled. NOT_FOUND: @@ -5278,7 +5438,8 @@ components: message: type: string enum: - - The server encountered an unexpected condition that prevented it from fulfilling the request. + - The server encountered an unexpected condition that prevented it from + fulfilling the request. ALREADY_EXISTS: description: Attempt to create a resource that already exists content: diff --git a/packages/loaders/openapi/tests/fixtures/government_social_work.json b/packages/loaders/openapi/tests/fixtures/government_social_work.json index 966fac9f56c69..ef97007d8f021 100644 --- a/packages/loaders/openapi/tests/fixtures/government_social_work.json +++ b/packages/loaders/openapi/tests/fixtures/government_social_work.json @@ -3312,7 +3312,14 @@ "id": { "type": "string", "description": "server-generated error code", - "enum": ["NO_RESULTS_FOUND", "SAVE_FAILED", "ADD_FAILED", "UPLOAD_FAILED", "SCAN_FAILED", "DELETE_FAILED"] + "enum": [ + "NO_RESULTS_FOUND", + "SAVE_FAILED", + "ADD_FAILED", + "UPLOAD_FAILED", + "SCAN_FAILED", + "DELETE_FAILED" + ] }, "message": { "type": "string", diff --git a/packages/loaders/openapi/tests/fixtures/kubernetes.json b/packages/loaders/openapi/tests/fixtures/kubernetes.json index c86a1efa90dac..33ddc11e247cc 100644 --- a/packages/loaders/openapi/tests/fixtures/kubernetes.json +++ b/packages/loaders/openapi/tests/fixtures/kubernetes.json @@ -728,7 +728,12 @@ "type": "integer" } }, - "required": ["currentNumberScheduled", "numberMisscheduled", "desiredNumberScheduled", "numberReady"], + "required": [ + "currentNumberScheduled", + "numberMisscheduled", + "desiredNumberScheduled", + "numberReady" + ], "type": "object" }, "io.k8s.api.apps.v1.DaemonSetUpdateStrategy": { @@ -20559,7 +20564,12 @@ "consumes": ["*/*"], "description": "read log of the specified Pod", "operationId": "readCoreV1NamespacedPodLog", - "produces": ["text/plain", "application/json", "application/yaml", "application/vnd.kubernetes.protobuf"], + "produces": [ + "text/plain", + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], "responses": { "200": { "description": "OK", diff --git a/packages/loaders/openapi/tests/fixtures/stripe.json b/packages/loaders/openapi/tests/fixtures/stripe.json index 1da5eb3826dd1..36fb07fd39e6d 100644 --- a/packages/loaders/openapi/tests/fixtures/stripe.json +++ b/packages/loaders/openapi/tests/fixtures/stripe.json @@ -697,7 +697,16 @@ "type": "string" } }, - "required": ["created", "fingerprint", "id", "livemode", "object", "reusable", "used", "username"], + "required": [ + "created", + "fingerprint", + "id", + "livemode", + "object", + "reusable", + "used", + "username" + ], "title": "AlipayAccount", "type": "object", "x-expandableFields": ["customer"], @@ -1937,7 +1946,16 @@ "type": "string" } }, - "required": ["brand", "exp_month", "exp_year", "funding", "id", "last4", "metadata", "object"], + "required": [ + "brand", + "exp_month", + "exp_year", + "funding", + "id", + "last4", + "metadata", + "object" + ], "title": "Card", "type": "object", "x-expandableFields": ["account", "customer", "recipient"], @@ -2598,7 +2616,24 @@ }, "locale": { "description": "The IETF language tag of the locale Checkout is displayed in. If blank or `auto`, the browser's locale is used.", - "enum": ["auto", "da", "de", "en", "es", "fi", "fr", "it", "ja", "ms", "nb", "nl", "pl", "pt", "sv", "zh"], + "enum": [ + "auto", + "da", + "de", + "en", + "es", + "fi", + "fr", + "it", + "ja", + "ms", + "nb", + "nl", + "pl", + "pt", + "sv", + "zh" + ], "nullable": true, "type": "string", "x-stripeBypassValidation": true @@ -2694,10 +2729,23 @@ "type": "string" } }, - "required": ["cancel_url", "id", "livemode", "object", "payment_method_types", "success_url"], + "required": [ + "cancel_url", + "id", + "livemode", + "object", + "payment_method_types", + "success_url" + ], "title": "Session", "type": "object", - "x-expandableFields": ["customer", "display_items", "payment_intent", "setup_intent", "subscription"], + "x-expandableFields": [ + "customer", + "display_items", + "payment_intent", + "setup_intent", + "subscription" + ], "x-resourceId": "checkout.session" }, "checkout_session_custom_display_item_description": { @@ -2999,7 +3047,16 @@ "type": "boolean" } }, - "required": ["created", "duration", "id", "livemode", "metadata", "object", "times_redeemed", "valid"], + "required": [ + "created", + "duration", + "id", + "livemode", + "metadata", + "object", + "times_redeemed", + "valid" + ], "title": "Coupon", "type": "object", "x-expandableFields": [], @@ -3611,7 +3668,17 @@ "type": "string" } }, - "required": ["amount", "created", "currency", "customer", "ending_balance", "id", "livemode", "object", "type"], + "required": [ + "amount", + "created", + "currency", + "customer", + "ending_balance", + "id", + "livemode", + "object", + "type" + ], "title": "CustomerBalanceTransaction", "type": "object", "x-expandableFields": ["credit_note", "customer", "invoice"], @@ -4420,7 +4487,13 @@ ], "title": "Dispute", "type": "object", - "x-expandableFields": ["balance_transactions", "charge", "evidence", "evidence_details", "payment_intent"], + "x-expandableFields": [ + "balance_transactions", + "charge", + "evidence", + "evidence_details", + "payment_intent" + ], "x-resourceId": "dispute" }, "dispute_evidence": { @@ -6096,14 +6169,31 @@ ], "title": "InvoiceItem", "type": "object", - "x-expandableFields": ["customer", "invoice", "period", "plan", "subscription", "tax_rates"], + "x-expandableFields": [ + "customer", + "invoice", + "period", + "plan", + "subscription", + "tax_rates" + ], "x-resourceId": "invoiceitem" }, "invoices_resource_invoice_tax_id": { "properties": { "type": { "description": "The type of the tax ID, one of `au_abn`, `ch_vat`, `eu_vat`, `in_gst`, `mx_rfc`, `no_vat`, `nz_gst`, `unknown`, or `za_vat`", - "enum": ["au_abn", "ch_vat", "eu_vat", "in_gst", "mx_rfc", "no_vat", "nz_gst", "unknown", "za_vat"], + "enum": [ + "au_abn", + "ch_vat", + "eu_vat", + "in_gst", + "mx_rfc", + "no_vat", + "nz_gst", + "unknown", + "za_vat" + ], "type": "string" }, "value": { @@ -6524,7 +6614,13 @@ ], "title": "IssuingCard", "type": "object", - "x-expandableFields": ["authorization_controls", "cardholder", "pin", "replacement_for", "shipping"], + "x-expandableFields": [ + "authorization_controls", + "cardholder", + "pin", + "replacement_for", + "shipping" + ], "x-resourceId": "issuing.card" }, "issuing.card_details": { @@ -6695,7 +6791,13 @@ ], "title": "IssuingCardholder", "type": "object", - "x-expandableFields": ["authorization_controls", "billing", "company", "individual", "requirements"], + "x-expandableFields": [ + "authorization_controls", + "billing", + "company", + "individual", + "requirements" + ], "x-resourceId": "issuing.cardholder" }, "issuing.dispute": { @@ -7034,7 +7136,14 @@ }, "type": { "description": "The nature of the transaction.", - "enum": ["capture", "cash_withdrawal", "dispute", "dispute_loss", "refund", "refund_reversal"], + "enum": [ + "capture", + "cash_withdrawal", + "dispute", + "dispute_loss", + "refund", + "refund_reversal" + ], "type": "string" } }, @@ -7102,7 +7211,15 @@ "type": "string" } }, - "required": ["card", "created", "expires_at", "id", "object", "scope", "verification_method"], + "required": [ + "card", + "created", + "expires_at", + "id", + "object", + "scope", + "verification_method" + ], "title": "IssuingVerification", "type": "object", "x-expandableFields": [], @@ -7270,7 +7387,13 @@ }, "name": { "description": "Name of the authorization control. One of `allowed_categories`, `blocked_categories`, `max_amount`, `max_approvals`, or `spending_limits`.", - "enum": ["allowed_categories", "blocked_categories", "max_amount", "max_approvals", "spending_limits"], + "enum": [ + "allowed_categories", + "blocked_categories", + "max_amount", + "max_approvals", + "spending_limits" + ], "type": "string" } }, @@ -10344,7 +10467,17 @@ "type": "string" } }, - "required": ["amount", "created", "currency", "id", "items", "livemode", "metadata", "object", "status"], + "required": [ + "amount", + "created", + "currency", + "id", + "items", + "livemode", + "metadata", + "object", + "status" + ], "title": "Order", "type": "object", "x-expandableFields": [ @@ -11040,7 +11173,14 @@ "required": ["billing_details", "created", "id", "livemode", "metadata", "object", "type"], "title": "PaymentMethod", "type": "object", - "x-expandableFields": ["billing_details", "card", "card_present", "customer", "ideal", "sepa_debit"], + "x-expandableFields": [ + "billing_details", + "card", + "card_present", + "customer", + "ideal", + "sepa_debit" + ], "x-resourceId": "payment_method" }, "payment_method_card": { @@ -11200,7 +11340,14 @@ }, "type": { "description": "The type of the card wallet, one of `amex_express_checkout`, `apple_pay`, `google_pay`, `masterpass`, `samsung_pay`, or `visa_checkout`. An additional hash is included on the Wallet subhash with a name matching this value. It contains additional information specific to the card wallet type.", - "enum": ["amex_express_checkout", "apple_pay", "google_pay", "masterpass", "samsung_pay", "visa_checkout"], + "enum": [ + "amex_express_checkout", + "apple_pay", + "google_pay", + "masterpass", + "samsung_pay", + "visa_checkout" + ], "type": "string" }, "visa_checkout": { @@ -11832,7 +11979,14 @@ }, "type": { "description": "The type of the card wallet, one of `amex_express_checkout`, `apple_pay`, `google_pay`, `masterpass`, `samsung_pay`, or `visa_checkout`. An additional hash is included on the Wallet subhash with a name matching this value. It contains additional information specific to the card wallet type.", - "enum": ["amex_express_checkout", "apple_pay", "google_pay", "masterpass", "samsung_pay", "visa_checkout"], + "enum": [ + "amex_express_checkout", + "apple_pay", + "google_pay", + "masterpass", + "samsung_pay", + "visa_checkout" + ], "type": "string" }, "visa_checkout": { @@ -13086,7 +13240,17 @@ "type": "string" } }, - "required": ["created", "id", "images", "livemode", "metadata", "name", "object", "type", "updated"], + "required": [ + "created", + "id", + "images", + "livemode", + "metadata", + "name", + "object", + "type", + "updated" + ], "title": "Product", "type": "object", "x-expandableFields": ["package_dimensions"], @@ -13512,7 +13676,13 @@ "required": ["created", "id", "livemode", "metadata", "object", "type"], "title": "TransferRecipient", "type": "object", - "x-expandableFields": ["active_account", "cards", "default_card", "migrated_to", "rolled_back_from"], + "x-expandableFields": [ + "active_account", + "cards", + "default_card", + "migrated_to", + "rolled_back_from" + ], "x-resourceId": "recipient" }, "refund": { @@ -13817,7 +13987,15 @@ "type": "integer" } }, - "required": ["data_available_end", "data_available_start", "id", "name", "object", "updated", "version"], + "required": [ + "data_available_end", + "data_available_start", + "id", + "name", + "object", + "updated", + "version" + ], "title": "reporting_report_type", "type": "object", "x-expandableFields": [], @@ -14295,7 +14473,15 @@ "type": "string" } }, - "required": ["created", "id", "livemode", "object", "payment_method_types", "status", "usage"], + "required": [ + "created", + "id", + "livemode", + "object", + "payment_method_types", + "status", + "usage" + ], "title": "SetupIntent", "type": "object", "x-expandableFields": [ @@ -14730,10 +14916,25 @@ "$ref": "#/components/schemas/source_type_wechat" } }, - "required": ["client_secret", "created", "flow", "id", "livemode", "object", "status", "type"], + "required": [ + "client_secret", + "created", + "flow", + "id", + "livemode", + "object", + "status", + "type" + ], "title": "Source", "type": "object", - "x-expandableFields": ["code_verification", "owner", "receiver", "redirect", "source_order"], + "x-expandableFields": [ + "code_verification", + "owner", + "receiver", + "redirect", + "source_order" + ], "x-resourceId": "source" }, "source_code_verification_flow": { @@ -15119,7 +15320,17 @@ "type": "string" } }, - "required": ["amount", "created", "currency", "id", "livemode", "object", "source", "status", "type"], + "required": [ + "amount", + "created", + "currency", + "id", + "livemode", + "object", + "source", + "status", + "type" + ], "title": "SourceTransaction", "type": "object", "x-expandableFields": [ @@ -16215,7 +16426,15 @@ }, "status": { "description": "Possible values are `incomplete`, `incomplete_expired`, `trialing`, `active`, `past_due`, `canceled`, or `unpaid`. \n\nFor `collection_method=charge_automatically` a subscription moves into `incomplete` if the initial payment attempt fails. A subscription in this state can only have metadata and default_source updated. Once the first invoice is paid, the subscription moves into an `active` state. If the first invoice is not paid within 23 hours, the subscription transitions to `incomplete_expired`. This is a terminal state, the open invoice will be voided and no further invoices will be generated. \n\nA subscription that is currently in a trial period is `trialing` and moves to `active` when the trial period is over. \n\nIf subscription `collection_method=charge_automatically` it becomes `past_due` when payment to renew it fails and `canceled` or `unpaid` (depending on your subscriptions settings) when Stripe has exhausted all payment retry attempts. \n\nIf subscription `collection_method=send_invoice` it becomes `past_due` when its invoice is not paid by the due date, and `canceled` or `unpaid` if it is still not paid by an additional deadline after that. Note that when a subscription has a status of `unpaid`, no subsequent invoices will be attempted (invoices will be created, but then immediately automatically closed). After receiving updated payment information from a customer, you may choose to reopen and pay their closed invoices.", - "enum": ["active", "canceled", "incomplete", "incomplete_expired", "past_due", "trialing", "unpaid"], + "enum": [ + "active", + "canceled", + "incomplete", + "incomplete_expired", + "past_due", + "trialing", + "unpaid" + ], "type": "string" }, "tax_percent": { @@ -16517,7 +16736,13 @@ ], "title": "SubscriptionSchedule", "type": "object", - "x-expandableFields": ["current_phase", "customer", "default_settings", "phases", "subscription"], + "x-expandableFields": [ + "current_phase", + "customer", + "default_settings", + "phases", + "subscription" + ], "x-resourceId": "subscription_schedule" }, "subscription_schedule_configuration_item": { @@ -16842,7 +17067,17 @@ }, "type": { "description": "Type of the tax ID, one of `au_abn`, `ch_vat`, `eu_vat`, `in_gst`, `mx_rfc`, `no_vat`, `nz_gst`, `za_vat`, or `unknown`", - "enum": ["au_abn", "ch_vat", "eu_vat", "in_gst", "mx_rfc", "no_vat", "nz_gst", "unknown", "za_vat"], + "enum": [ + "au_abn", + "ch_vat", + "eu_vat", + "in_gst", + "mx_rfc", + "no_vat", + "nz_gst", + "unknown", + "za_vat" + ], "type": "string" }, "value": { @@ -16854,7 +17089,16 @@ "$ref": "#/components/schemas/tax_id_verification" } }, - "required": ["created", "customer", "id", "livemode", "object", "type", "value", "verification"], + "required": [ + "created", + "customer", + "id", + "livemode", + "object", + "type", + "value", + "verification" + ], "title": "tax_id", "type": "object", "x-expandableFields": ["customer", "verification"], @@ -17087,7 +17331,15 @@ "type": "string" } }, - "required": ["device_type", "id", "label", "livemode", "metadata", "object", "serial_number"], + "required": [ + "device_type", + "id", + "label", + "livemode", + "metadata", + "object", + "serial_number" + ], "title": "TerminalReaderReader", "type": "object", "x-expandableFields": [], @@ -17141,7 +17393,17 @@ "type": "string" } }, - "required": ["amount", "authenticated", "card", "created", "currency", "id", "livemode", "object", "status"], + "required": [ + "amount", + "authenticated", + "card", + "created", + "currency", + "id", + "livemode", + "object", + "status" + ], "title": "ThreeDSecure", "type": "object", "x-expandableFields": ["card"], @@ -17331,7 +17593,17 @@ "type": "string" } }, - "required": ["amount", "created", "currency", "id", "livemode", "metadata", "object", "source", "status"], + "required": [ + "amount", + "created", + "currency", + "id", + "livemode", + "metadata", + "object", + "source", + "status" + ], "title": "Topup", "type": "object", "x-expandableFields": ["balance_transaction", "source"], @@ -17679,7 +17951,12 @@ "required": ["amount", "created", "currency", "id", "metadata", "object", "transfer"], "title": "TransferReversal", "type": "object", - "x-expandableFields": ["balance_transaction", "destination_payment_refund", "source_refund", "transfer"], + "x-expandableFields": [ + "balance_transaction", + "destination_payment_refund", + "source_refund", + "transfer" + ], "x-resourceId": "transfer_reversal" }, "transfer_schedule": { @@ -18784,7 +19061,15 @@ "type": "integer" }, "weekly_anchor": { - "enum": ["friday", "monday", "saturday", "sunday", "thursday", "tuesday", "wednesday"], + "enum": [ + "friday", + "monday", + "saturday", + "sunday", + "thursday", + "tuesday", + "wednesday" + ], "maxLength": 5000, "type": "string" } @@ -22892,7 +23177,15 @@ "type": "integer" }, "weekly_anchor": { - "enum": ["friday", "monday", "saturday", "sunday", "thursday", "tuesday", "wednesday"], + "enum": [ + "friday", + "monday", + "saturday", + "sunday", + "thursday", + "tuesday", + "wednesday" + ], "maxLength": 5000, "type": "string" } @@ -23739,7 +24032,15 @@ "type": "integer" }, "weekly_anchor": { - "enum": ["friday", "monday", "saturday", "sunday", "thursday", "tuesday", "wednesday"], + "enum": [ + "friday", + "monday", + "saturday", + "sunday", + "thursday", + "tuesday", + "wednesday" + ], "maxLength": 5000, "type": "string" } @@ -33087,7 +33388,16 @@ "items": { "properties": { "type": { - "enum": ["au_abn", "ch_vat", "eu_vat", "in_gst", "mx_rfc", "no_vat", "nz_gst", "za_vat"], + "enum": [ + "au_abn", + "ch_vat", + "eu_vat", + "in_gst", + "mx_rfc", + "no_vat", + "nz_gst", + "za_vat" + ], "maxLength": 5000, "type": "string", "x-stripeBypassValidation": true @@ -37705,7 +38015,16 @@ }, "type": { "description": "Type of the tax ID, one of `au_abn`, `ch_vat`, `eu_vat`, `in_gst`, `mx_rfc`, `no_vat`, `nz_gst`, or `za_vat`", - "enum": ["au_abn", "ch_vat", "eu_vat", "in_gst", "mx_rfc", "no_vat", "nz_gst", "za_vat"], + "enum": [ + "au_abn", + "ch_vat", + "eu_vat", + "in_gst", + "mx_rfc", + "no_vat", + "nz_gst", + "za_vat" + ], "maxLength": 5000, "type": "string", "x-stripeBypassValidation": true @@ -44194,7 +44513,14 @@ "type": "array" }, "interval": { - "enum": ["all_time", "daily", "monthly", "per_authorization", "weekly", "yearly"], + "enum": [ + "all_time", + "daily", + "monthly", + "per_authorization", + "weekly", + "yearly" + ], "type": "string" } }, @@ -45402,7 +45728,14 @@ "type": "array" }, "interval": { - "enum": ["all_time", "daily", "monthly", "per_authorization", "weekly", "yearly"], + "enum": [ + "all_time", + "daily", + "monthly", + "per_authorization", + "weekly", + "yearly" + ], "type": "string" } }, @@ -46754,7 +47087,14 @@ "type": "array" }, "interval": { - "enum": ["all_time", "daily", "monthly", "per_authorization", "weekly", "yearly"], + "enum": [ + "all_time", + "daily", + "monthly", + "per_authorization", + "weekly", + "yearly" + ], "type": "string" } }, @@ -47914,7 +48254,14 @@ "type": "array" }, "interval": { - "enum": ["all_time", "daily", "monthly", "per_authorization", "weekly", "yearly"], + "enum": [ + "all_time", + "daily", + "monthly", + "per_authorization", + "weekly", + "yearly" + ], "type": "string" } }, diff --git a/packages/loaders/openapi/tests/fixtures/toto.yml b/packages/loaders/openapi/tests/fixtures/toto.yml index 9dae159d7b2c6..6d589a1958533 100644 --- a/packages/loaders/openapi/tests/fixtures/toto.yml +++ b/packages/loaders/openapi/tests/fixtures/toto.yml @@ -607,7 +607,9 @@ components: pattern: '^(FILE_TYPE|NAME|LAST_UPDATE_DATE)(,(ASC|DESC))?$' targetAudience: name: targetAudience - description: Target of the resource (the resource need to have all of the target audience passed in the list) + description: + Target of the resource (the resource need to have all of the target audience passed in the + list) in: query required: false schema: diff --git a/packages/loaders/openapi/tests/fixtures/uk_teachers_training_courses.json b/packages/loaders/openapi/tests/fixtures/uk_teachers_training_courses.json index 2e21324930224..56b1c6263975c 100644 --- a/packages/loaders/openapi/tests/fixtures/uk_teachers_training_courses.json +++ b/packages/loaders/openapi/tests/fixtures/uk_teachers_training_courses.json @@ -811,7 +811,11 @@ "vacancy_status": { "type": "string", "description": "What type of vacancies are available.", - "enum": ["full_time_vacancies", "part_time_vacancies", "both_full_time_and_part_time_vacancies"], + "enum": [ + "full_time_vacancies", + "part_time_vacancies", + "both_full_time_and_part_time_vacancies" + ], "example": "full_time_vacancies" } } diff --git a/packages/loaders/openapi/tests/fixtures/weather_underground.json b/packages/loaders/openapi/tests/fixtures/weather_underground.json index 8db5272824055..315338c5fdd8c 100644 --- a/packages/loaders/openapi/tests/fixtures/weather_underground.json +++ b/packages/loaders/openapi/tests/fixtures/weather_underground.json @@ -260,7 +260,9 @@ "watchers": 1, "forks": 1, "subscribers": 1, - "sources": ["https://github.com/dasmoose/tundra/blob/44bea73bb96d3501e8c3f97666d823041d48f348/lib/constants.rb"] + "sources": [ + "https://github.com/dasmoose/tundra/blob/44bea73bb96d3501e8c3f97666d823041d48f348/lib/constants.rb" + ] }, { "repository": "fplatten/wuapi", @@ -639,7 +641,16 @@ "type": "string" } }, - "required": ["full", "city", "state", "country", "country_iso3166", "latitude", "longitude", "elevation"] + "required": [ + "full", + "city", + "state", + "country", + "country_iso3166", + "latitude", + "longitude", + "elevation" + ] }, "estimated": { "type": "object", @@ -924,7 +935,15 @@ "type": "string" } }, - "required": ["period", "icon", "icon_url", "title", "fcttext", "fcttext_metric", "pop"] + "required": [ + "period", + "icon", + "icon_url", + "title", + "fcttext", + "fcttext_metric", + "pop" + ] } } }, diff --git a/packages/loaders/raml/README.md b/packages/loaders/raml/README.md index 04192283bf496..5528c478d6e33 100644 --- a/packages/loaders/raml/README.md +++ b/packages/loaders/raml/README.md @@ -1,6 +1,8 @@ ## RAML (@omnigraph/raml) -This package generates `GraphQLSchema` instance from **RAML API Document** (`.raml`) file located at a URL or FileSystem by resolving the JSON Schema dependencies. It uses `@omnigraph/json-schema` by generating the necessary configuration. +This package generates `GraphQLSchema` instance from **RAML API Document** (`.raml`) file located at +a URL or FileSystem by resolving the JSON Schema dependencies. It uses `@omnigraph/json-schema` by +generating the necessary configuration. ```yaml filename=".graphqlrc.yml" schema: diff --git a/packages/loaders/soap/test/examples.test.ts b/packages/loaders/soap/test/examples.test.ts index fb58e415ea4fa..becfa933dadff 100644 --- a/packages/loaders/soap/test/examples.test.ts +++ b/packages/loaders/soap/test/examples.test.ts @@ -15,7 +15,10 @@ describe('Examples', () => { const soapLoader = new SOAPLoader({ fetch, }); - const example1Wsdl = await readFile(join(__dirname, './fixtures/' + example + '.wsdl'), 'utf8'); + const example1Wsdl = await readFile( + join(__dirname, './fixtures/' + example + '.wsdl'), + 'utf8', + ); await soapLoader.loadWSDL(example1Wsdl); const schema = soapLoader.buildSchema(); expect(printSchema(schema)).toMatchSnapshot(example); diff --git a/packages/mergers/bare/src/index.ts b/packages/mergers/bare/src/index.ts index 4ec938bf3c438..42a73734580ba 100644 --- a/packages/mergers/bare/src/index.ts +++ b/packages/mergers/bare/src/index.ts @@ -1,4 +1,9 @@ -import { MeshMerger, MeshMergerContext, MeshMergerOptions, RawSourceOutput } from '@graphql-mesh/types'; +import { + MeshMerger, + MeshMergerContext, + MeshMergerOptions, + RawSourceOutput, +} from '@graphql-mesh/types'; import { applySchemaTransforms } from '@graphql-mesh/utils'; import { addResolversToSchema, mergeSchemas } from '@graphql-tools/schema'; import { asArray, mapSchema } from '@graphql-tools/utils'; @@ -13,7 +18,9 @@ export default class BareMerger implements MeshMerger { handleSingleWrappedExtendedSource(mergerCtx: MeshMergerContext) { // switch to stitching merger this.name = 'stitching'; - this.options.logger.debug(`Switching to Stitching merger due to the transforms and additional resolvers`); + this.options.logger.debug( + `Switching to Stitching merger due to the transforms and additional resolvers`, + ); this.options.logger = this.options.logger.child('Stitching Proxy'); this.stitchingMerger = this.stitchingMerger || new StitchingMerger(this.options); return this.stitchingMerger.getUnifiedSchema(mergerCtx); @@ -42,7 +49,12 @@ export default class BareMerger implements MeshMerger { // We should return a version of the schema only with the source-level transforms // But we should prevent the existing schema from being mutated internally const nonExecutableSchema = mapSchema(schema); - return applySchemaTransforms(nonExecutableSchema, rawSource, nonExecutableSchema, rawSource.transforms); + return applySchemaTransforms( + nonExecutableSchema, + rawSource, + nonExecutableSchema, + rawSource.transforms, + ); }, }; }, diff --git a/packages/mergers/federation/src/index.ts b/packages/mergers/federation/src/index.ts index 958a0d7832555..ddbe406e2f2cb 100644 --- a/packages/mergers/federation/src/index.ts +++ b/packages/mergers/federation/src/index.ts @@ -7,12 +7,24 @@ import { MeshPubSub, RawSourceOutput, } from '@graphql-mesh/types'; -import { GraphQLSchema, extendSchema, DocumentNode, parse, execute, ExecutionResult } from 'graphql'; +import { + GraphQLSchema, + extendSchema, + DocumentNode, + parse, + execute, + ExecutionResult, +} from 'graphql'; import { wrapSchema } from '@graphql-tools/wrap'; import { ApolloGateway, LocalGraphQLDataSource, SERVICE_DEFINITION_QUERY } from '@apollo/gateway'; import { addResolversToSchema } from '@graphql-tools/schema'; import { printWithCache } from '@graphql-mesh/utils'; -import { AggregateError, asArray, ExecutionRequest, printSchemaWithDirectives } from '@graphql-tools/utils'; +import { + AggregateError, + asArray, + ExecutionRequest, + printSchemaWithDirectives, +} from '@graphql-tools/utils'; import { MeshStore, PredefinedProxyOptions } from '@graphql-mesh/store'; import { process } from '@graphql-mesh/cross-helpers'; @@ -48,7 +60,10 @@ export default class FederationMerger implements MeshMerger { document: parse(SERVICE_DEFINITION_QUERY), }); if (sdlQueryResult.errors?.length) { - throw new AggregateError(sdlQueryResult.errors, `Failed on fetching Federated SDL for ${rawSource.name}`); + throw new AggregateError( + sdlQueryResult.errors, + `Failed on fetching Federated SDL for ${rawSource.name}`, + ); } return sdlQueryResult.data._service.sdl; }); @@ -56,7 +71,7 @@ export default class FederationMerger implements MeshMerger { name: rawSource.name, typeDefs: parse(sdl), }); - }) + }), ); this.logger.debug(`Creating ApolloGateway`); const gateway = new ApolloGateway({ @@ -76,7 +91,13 @@ export default class FederationMerger implements MeshMerger { const schemaHash: any = printSchemaWithDirectives(schema); let remoteSchema: GraphQLSchema = schema; this.logger.debug(`Wrapping gateway executor in a unified schema`); - const executor = ({ document, info, variables, context, operationName }: ExecutionRequest) => { + const executor = ({ + document, + info, + variables, + context, + operationName, + }: ExecutionRequest) => { const documentStr = printWithCache(document); const { operation } = info; // const operationName = operation.name?.value; diff --git a/packages/plugins/deduplicate-request/tests/useDeduplicateRequest.test.ts b/packages/plugins/deduplicate-request/tests/useDeduplicateRequest.test.ts index 213806fb3d9a4..59604967c3fc7 100644 --- a/packages/plugins/deduplicate-request/tests/useDeduplicateRequest.test.ts +++ b/packages/plugins/deduplicate-request/tests/useDeduplicateRequest.test.ts @@ -21,7 +21,7 @@ describe('useDeduplicateRequest', () => { data: { hello: 'world', }, - }) + }), ); }); server.listen(9856, done); @@ -53,7 +53,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ); await response.text(); const response2 = await fetchFn( @@ -63,7 +63,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ); await response2.text(); expect(reqCount).toBe(1); @@ -87,7 +87,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ), fetchFn( url, @@ -96,7 +96,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ), ]); await Promise.all([response.text(), response2.text()]); @@ -120,7 +120,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ); await response.text(); const response2 = await fetchFn( @@ -130,7 +130,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ); await response2.text(); expect(reqCount).toBe(2); @@ -154,7 +154,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ), fetchFn( url + '2', @@ -163,7 +163,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ), ]); await Promise.all([response.text(), response2.text()]); @@ -188,7 +188,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ); await response.text(); const response2 = await fetchFn( @@ -198,7 +198,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context2 + context2, ); await response2.text(); expect(reqCount).toBe(2); @@ -223,7 +223,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context + context, ), fetchFn( url, @@ -232,7 +232,7 @@ describe('useDeduplicateRequest', () => { Accept: 'application/json', }, }, - context2 + context2, ), ]); await Promise.all([response.text(), response2.text()]); diff --git a/packages/plugins/hive/src/index.ts b/packages/plugins/hive/src/index.ts index 1a32490f73ef4..13ab17ad5eb0a 100644 --- a/packages/plugins/hive/src/index.ts +++ b/packages/plugins/hive/src/index.ts @@ -3,7 +3,10 @@ import { MeshPlugin, MeshPluginOptions, YamlConfig } from '@graphql-mesh/types'; import { process } from '@graphql-mesh/cross-helpers'; import { stringInterpolator } from '@graphql-mesh/string-interpolation'; -export default function useMeshHive(pluginOptions: MeshPluginOptions): MeshPlugin<{}> { +export default function useMeshHive( + pluginOptions: MeshPluginOptions, + // eslint-disable-next-line @typescript-eslint/ban-types +): MeshPlugin<{}> { const token = stringInterpolator.parse(pluginOptions.token, { env: process.env, }); diff --git a/packages/plugins/http-cache/src/index.ts b/packages/plugins/http-cache/src/index.ts index af9cab9845da0..40a423418b52f 100644 --- a/packages/plugins/http-cache/src/index.ts +++ b/packages/plugins/http-cache/src/index.ts @@ -73,13 +73,16 @@ export default function useHTTPCache({ cache }: MeshPluginOptions<{}>): MeshPlug }, }, context, - info + info, ); - const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy(revalidationRequest, { - status: revalidationResponse.status, - headers: getHeadersObj(revalidationResponse.headers as any), - }); + const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy( + revalidationRequest, + { + status: revalidationResponse.status, + headers: getHeadersObj(revalidationResponse.headers as any), + }, + ); const newBody = await revalidationResponse.text(); @@ -134,7 +137,7 @@ export default function useHTTPCache({ cache }: MeshPluginOptions<{}>): MeshPlug new Response(resText, { status: response.status, headers: resHeaders, - }) + }), ); } } diff --git a/packages/plugins/http-details-extensions/src/index.ts b/packages/plugins/http-details-extensions/src/index.ts index b9d2051c3fc31..2e35e03134dbc 100644 --- a/packages/plugins/http-details-extensions/src/index.ts +++ b/packages/plugins/http-details-extensions/src/index.ts @@ -20,7 +20,9 @@ export interface MeshFetchHTTPInformation { responseTime: number; } -export default function useIncludeHttpDetailsInExtensions(opts: MeshPluginOptions<{ if: any }>): MeshPlugin { +export default function useIncludeHttpDetailsInExtensions( + opts: MeshPluginOptions<{ if: any }>, +): MeshPlugin { if ('if' in opts && !opts.if) { return {}; } diff --git a/packages/plugins/live-query/src/index.ts b/packages/plugins/live-query/src/index.ts index a8c510a2c45db..b8a9d41d126a4 100644 --- a/packages/plugins/live-query/src/index.ts +++ b/packages/plugins/live-query/src/index.ts @@ -1,12 +1,17 @@ import { useLiveQuery } from '@envelop/live-query'; import { MeshPluginOptions, YamlConfig } from '@graphql-mesh/types'; -import { defaultResourceIdentifierNormalizer, InMemoryLiveQueryStore } from '@n1ru4l/in-memory-live-query-store'; +import { + defaultResourceIdentifierNormalizer, + InMemoryLiveQueryStore, +} from '@n1ru4l/in-memory-live-query-store'; import { Plugin } from '@envelop/core'; import { useInvalidateByResult } from './useInvalidateByResult.js'; import { process } from '@graphql-mesh/cross-helpers'; import { stringInterpolator } from '@graphql-mesh/string-interpolation'; -export default function useMeshLiveQuery(options: MeshPluginOptions): Plugin { +export default function useMeshLiveQuery( + options: MeshPluginOptions, +): Plugin { options.logger.debug(`Creating Live Query Store`); const liveQueryStore = new InMemoryLiveQueryStore({ buildResourceIdentifier: @@ -20,12 +25,14 @@ export default function useMeshLiveQuery(options: MeshPluginOptions - liveQueryStore.invalidate(identifiers) + liveQueryStore.invalidate(identifiers), ); return { onPluginInit({ addPlugin }) { @@ -36,7 +43,7 @@ export default function useMeshLiveQuery(options: MeshPluginOptions { const rawInvalidationPaths = liveQueryInvalidation.invalidate; const factories = rawInvalidationPaths.map(rawInvalidationPath => - getInterpolatedStringFactory(rawInvalidationPath) + getInterpolatedStringFactory(rawInvalidationPath), ); liveQueryInvalidationFactoryMap.set(liveQueryInvalidation.field, factories); }); @@ -22,7 +25,8 @@ export function useInvalidateByResult(params: InvalidateByResultParams): Plugin onExecute() { return { onExecuteDone({ args: executionArgs, result }) { - const { schema, document, operationName, variableValues, rootValue, contextValue } = executionArgs; + const { schema, document, operationName, variableValues, rootValue, contextValue } = + executionArgs; const operationAST = getOperationAST(document, operationName); if (!operationAST) { throw new Error(`Operation couldn't be found`); @@ -45,12 +49,12 @@ export function useInvalidateByResult(params: InvalidateByResultParams): Plugin context: contextValue, env: process.env, result, - }) + }), ); params.pubsub.publish('live-query:invalidate', invalidationPaths); } }, - }) + }), ); }, }; diff --git a/packages/plugins/mock/src/index.ts b/packages/plugins/mock/src/index.ts index 39e8ffb6593e0..3e6d444f5d8d4 100644 --- a/packages/plugins/mock/src/index.ts +++ b/packages/plugins/mock/src/index.ts @@ -8,8 +8,10 @@ import { GraphQLResolveInfo, GraphQLFieldResolver, GraphQLSchema, execute } from const mockedSchemas = new WeakSet(); -// eslint-disable-next-line @typescript-eslint/ban-types -export default function useMock(config: MeshPluginOptions): MeshPlugin<{}> { +export default function useMock( + config: MeshPluginOptions, + // eslint-disable-next-line @typescript-eslint/ban-types +): MeshPlugin<{}> { const configIf = config != null && 'if' in config ? config.if : true; if (configIf) { @@ -53,38 +55,66 @@ export default function useMock(config: MeshPluginOptions { + resolvers[typeName][fieldName] = ( + root: any, + args: any, + context: any, + info: GraphQLResolveInfo, + ) => { context = context || {}; context.mockStore = store; return exportedVal$.then(exportedVal => - typeof exportedVal === 'function' ? exportedVal(root, args, context, info) : exportedVal + typeof exportedVal === 'function' + ? exportedVal(root, args, context, info) + : exportedVal, ); }; } else if ('length' in fieldConfig) { resolvers[typeName] = resolvers[typeName] || {}; resolvers[typeName][fieldName] = () => new Array(fieldConfig.length).fill({}); } else if ('updateStore' in fieldConfig) { - const getFromStoreKeyFactory = getInterpolatedStringFactory(fieldConfig.store.key); + const getFromStoreKeyFactory = getInterpolatedStringFactory( + fieldConfig.store.key, + ); const updateStoreFactories = fieldConfig.updateStore.map(updateStoreConfig => ({ updateStoreConfig, keyFactory: getInterpolatedStringFactory(updateStoreConfig.key), valueFactory: getInterpolatedStringFactory(updateStoreConfig.value), })); resolvers[typeName] = resolvers[typeName] || {}; - resolvers[typeName][fieldName] = (root: any, args: any, context: any, info: GraphQLResolveInfo) => { - const resolverData = { root, args, context, info, random: Date.now().toString(), env: process.env }; - updateStoreFactories.forEach(({ updateStoreConfig, keyFactory, valueFactory }) => { - const key = keyFactory(resolverData); - const value = valueFactory(resolverData); - store.set(updateStoreConfig.type, key, updateStoreConfig.fieldName, value); - }); + resolvers[typeName][fieldName] = ( + root: any, + args: any, + context: any, + info: GraphQLResolveInfo, + ) => { + const resolverData = { + root, + args, + context, + info, + random: Date.now().toString(), + env: process.env, + }; + updateStoreFactories.forEach( + ({ updateStoreConfig, keyFactory, valueFactory }) => { + const key = keyFactory(resolverData); + const value = valueFactory(resolverData); + store.set(updateStoreConfig.type, key, updateStoreConfig.fieldName, value); + }, + ); const key = getFromStoreKeyFactory(resolverData); return store.get(fieldConfig.store.type, key, fieldConfig.store.fieldName); }; } else if ('store' in fieldConfig) { const keyFactory = getInterpolatedStringFactory(fieldConfig.store.key); resolvers[typeName] = resolvers[typeName] || {}; - resolvers[typeName][fieldName] = (root: any, args: any, context: any, info: GraphQLResolveInfo) => { + resolvers[typeName][fieldName] = ( + root: any, + args: any, + context: any, + info: GraphQLResolveInfo, + ) => { const key = keyFactory({ root, args, context, info, env: process.env }); return store.get(fieldConfig.store.type, key, fieldConfig.store.fieldName); }; @@ -107,7 +137,7 @@ export default function useMock(config: MeshPluginOptions { return exportedVal$.then(exportedVal => - typeof exportedVal === 'function' ? exportedVal(store) : exportedVal + typeof exportedVal === 'function' ? exportedVal(store) : exportedVal, ); }; } diff --git a/packages/plugins/mock/tests/mocking.spec.ts b/packages/plugins/mock/tests/mocking.spec.ts index 88ffdbe575a9b..181cc0c759e66 100644 --- a/packages/plugins/mock/tests/mocking.spec.ts +++ b/packages/plugins/mock/tests/mocking.spec.ts @@ -234,7 +234,10 @@ describe('mocking', () => { } } `); - const getUserResult: any = await enveloped.execute({ schema: enveloped.schema, document: GET_USER }); + const getUserResult: any = await enveloped.execute({ + schema: enveloped.schema, + document: GET_USER, + }); expect(getUserResult?.data?.user?.id).toBe(addedUserId); expect(getUserResult?.data?.user?.name).toBe('John Doe'); const UPDATE_USER = enveloped.parse(/* GraphQL */ ` @@ -245,7 +248,10 @@ describe('mocking', () => { } } `); - const updateUserResult: any = await enveloped.execute({ schema: enveloped.schema, document: UPDATE_USER }); + const updateUserResult: any = await enveloped.execute({ + schema: enveloped.schema, + document: UPDATE_USER, + }); expect(updateUserResult?.data?.updateUser?.id).toBe(addedUserId); expect(updateUserResult?.data?.updateUser?.name).toBe('Jane Doe'); }); @@ -324,7 +330,10 @@ describe('mocking', () => { } } `); - const addUserResult: any = await enveloped.execute({ schema: enveloped.schema, document: ADD_USER }); + const addUserResult: any = await enveloped.execute({ + schema: enveloped.schema, + document: ADD_USER, + }); expect(addUserResult?.data?.addUser?.name).toBe('John Doe'); const addedUserId = addUserResult.data.addUser.id; const GET_USER = enveloped.parse(/* GraphQL */ ` @@ -335,7 +344,10 @@ describe('mocking', () => { } } `); - const getUserResult: any = await enveloped.execute({ schema: enveloped.schema, document: GET_USER }); + const getUserResult: any = await enveloped.execute({ + schema: enveloped.schema, + document: GET_USER, + }); expect(getUserResult?.data?.user?.id).toBe(addedUserId); expect(getUserResult?.data?.user?.name).toBe('John Doe'); const UPDATE_USER = parse(/* GraphQL */ ` @@ -346,7 +358,10 @@ describe('mocking', () => { } } `); - const updateUserResult: any = await enveloped.execute({ schema: enveloped.schema, document: UPDATE_USER }); + const updateUserResult: any = await enveloped.execute({ + schema: enveloped.schema, + document: UPDATE_USER, + }); expect(updateUserResult?.data?.updateUser?.id).toBe(addedUserId); expect(updateUserResult?.data?.updateUser?.name).toBe('Jane Doe'); }); diff --git a/packages/plugins/mock/tests/mocks.ts b/packages/plugins/mock/tests/mocks.ts index 5f0bdb43d4770..5f83e4f58c25d 100644 --- a/packages/plugins/mock/tests/mocks.ts +++ b/packages/plugins/mock/tests/mocks.ts @@ -2,9 +2,16 @@ import { MockStore } from '@graphql-tools/mock'; export const id = 'sample-id'; export const fullName = 'John Snow'; -export const GetUserMock = (_: never, { id }: { id: string }, { mockStore }: { mockStore: MockStore }) => - mockStore.get('User', id); -export const AddUserMock = (_: never, { name }: { name: string }, { mockStore }: { mockStore: MockStore }) => { +export const GetUserMock = ( + _: never, + { id }: { id: string }, + { mockStore }: { mockStore: MockStore }, +) => mockStore.get('User', id); +export const AddUserMock = ( + _: never, + { name }: { name: string }, + { mockStore }: { mockStore: MockStore }, +) => { const newUserId = Date.now().toString(); mockStore.set('User', newUserId, 'name', name); return mockStore.get('User', newUserId); @@ -12,7 +19,7 @@ export const AddUserMock = (_: never, { name }: { name: string }, { mockStore }: export const UpdateUserMock = ( _: never, { id, name }: { id: string; name: string }, - { mockStore }: { mockStore: MockStore } + { mockStore }: { mockStore: MockStore }, ) => { mockStore.set('User', id, { name }); return mockStore.get('User', id); diff --git a/packages/plugins/operation-field-permissions/src/index.ts b/packages/plugins/operation-field-permissions/src/index.ts index 06463481e17e3..562ce18095b45 100644 --- a/packages/plugins/operation-field-permissions/src/index.ts +++ b/packages/plugins/operation-field-permissions/src/index.ts @@ -4,7 +4,7 @@ import { process } from '@graphql-mesh/cross-helpers'; import { useOperationFieldPermissions } from '@envelop/operation-field-permissions'; export default function useMeshOperationFieldPermissions( - options: MeshPluginOptions + options: MeshPluginOptions, ): MeshPlugin { return { onPluginInit({ addPlugin }) { @@ -22,7 +22,7 @@ export default function useMeshOperationFieldPermissions( } return allowedFields; }, - }) + }), ); }, }; diff --git a/packages/plugins/prometheus/src/index.ts b/packages/plugins/prometheus/src/index.ts index 7b50f2b1049d7..e0595460f3870 100644 --- a/packages/plugins/prometheus/src/index.ts +++ b/packages/plugins/prometheus/src/index.ts @@ -5,7 +5,7 @@ import { Histogram, register as defaultRegistry, Registry } from 'prom-client'; import type { Plugin as YogaPlugin } from 'graphql-yoga'; export default async function useMeshPrometheus( - pluginOptions: MeshPluginOptions + pluginOptions: MeshPluginOptions, ): Promise & YogaPlugin> { const registry = pluginOptions.registry ? await loadFromModuleExportExpression(pluginOptions.registry, { @@ -32,7 +32,7 @@ export default async function useMeshPrometheus( usePrometheus({ ...pluginOptions, registry, - }) + }), ); }, onDelegate({ sourceName, typeName, fieldName, args, key }) { @@ -49,7 +49,7 @@ export default async function useMeshPrometheus( args: JSON.stringify(args), key: JSON.stringify(key), }, - duration + duration, ); }; } @@ -70,7 +70,7 @@ export default async function useMeshPrometheus( statusText: response.statusText, responseHeaders: JSON.stringify(getHeadersObj(response.headers)), }, - duration + duration, ); }; } diff --git a/packages/plugins/response-cache/src/index.ts b/packages/plugins/response-cache/src/index.ts index 610f3c57f96f9..862e74e60665c 100644 --- a/packages/plugins/response-cache/src/index.ts +++ b/packages/plugins/response-cache/src/index.ts @@ -4,8 +4,8 @@ import { useResponseCache, UseResponseCacheParameter } from '@graphql-yoga/plugi import { hashObject, stringInterpolator } from '@graphql-mesh/string-interpolation'; import { process } from '@graphql-mesh/cross-helpers'; -const defaultBuildResponseCacheKey: UseResponseCacheParameter['buildResponseCacheKey'] = async params => - hashObject(params); +const defaultBuildResponseCacheKey: UseResponseCacheParameter['buildResponseCacheKey'] = + async params => hashObject(params); function generateSessionIdFactory(sessionIdDef: string) { if (sessionIdDef == null) { @@ -28,7 +28,9 @@ function generateEnabledFactory(ifDef: string) { }; } -function getBuildResponseCacheKey(cacheKeyDef: string): UseResponseCacheParameter['buildResponseCacheKey'] { +function getBuildResponseCacheKey( + cacheKeyDef: string, +): UseResponseCacheParameter['buildResponseCacheKey'] { return function buildResponseCacheKey(cacheKeyParameters) { let cacheKey = stringInterpolator.parse(cacheKeyDef, { ...cacheKeyParameters, @@ -41,7 +43,9 @@ function getBuildResponseCacheKey(cacheKeyDef: string): UseResponseCacheParamete }; } -function getShouldCacheResult(shouldCacheResultDef: string): UseResponseCacheParameter['shouldCacheResult'] { +function getShouldCacheResult( + shouldCacheResultDef: string, +): UseResponseCacheParameter['shouldCacheResult'] { return function shouldCacheResult({ result }) { // eslint-disable-next-line no-new-func return new Function(`return ${shouldCacheResultDef}`)(); @@ -60,7 +64,7 @@ function getCacheForResponseCache(meshCache: KeyValueCache): UseResponseCachePar const entryId = `${typename}.${id}`; await meshCache.set(`response-cache:${entryId}:${responseId}`, {}, ttlConfig); await meshCache.set(`response-cache:${responseId}:${entryId}`, {}, ttlConfig); - }) + }), ); return meshCache.set(`response-cache:${responseId}`, data, ttlConfig); }, @@ -69,15 +73,17 @@ function getCacheForResponseCache(meshCache: KeyValueCache): UseResponseCachePar await Promise.all( [...entitiesToRemove].map(async ({ typename, id }) => { const entryId = `${typename}.${id}`; - const cacheEntriesToDelete = await meshCache.getKeysByPrefix(`response-cache:${entryId}:`); + const cacheEntriesToDelete = await meshCache.getKeysByPrefix( + `response-cache:${entryId}:`, + ); await Promise.all( cacheEntriesToDelete.map(cacheEntryName => { const [, , responseId] = cacheEntryName.split(':'); responseIdsToCheck.add(responseId); return meshCache.delete(entryId); - }) + }), ); - }) + }), ); await Promise.all( [...responseIdsToCheck].map(async responseId => { @@ -85,13 +91,15 @@ function getCacheForResponseCache(meshCache: KeyValueCache): UseResponseCachePar if (cacheEntries.length === 0) { await meshCache.delete(`response-cache:${responseId}`); } - }) + }), ); }, }; } -export default function useMeshResponseCache(options: MeshPluginOptions): Plugin { +export default function useMeshResponseCache( + options: MeshPluginOptions, +): Plugin { const ttlPerType: Record = {}; const ttlPerSchemaCoordinate: Record = {}; if (options.ttlPerCoordinate) { @@ -109,13 +117,19 @@ export default function useMeshResponseCache(options: MeshPluginOptions + pluginOptions: MeshPluginOptions, ): MeshPlugin { if (typeof pluginOptions.if === 'boolean') { if (!pluginOptions.if) { @@ -39,7 +39,11 @@ export default function useSnapshot( async onFetch({ url, options, setFetchFn }) { if (matches.some(matcher => matcher.match(url))) { const snapshotFileName = calculateCacheKey(url, options); - const snapshotPath = path.join(pluginOptions.baseDir, snapshotsDir, `${snapshotFileName}.json`); + const snapshotPath = path.join( + pluginOptions.baseDir, + snapshotsDir, + `${snapshotFileName}.json`, + ); if (await pathExists(snapshotPath)) { setFetchFn(async () => { const snapshotFile = await fs.promises.readFile(snapshotPath, 'utf-8'); @@ -54,7 +58,11 @@ export default function useSnapshot( } return async ({ response, setResponse }) => { const contentType = response.headers.get('content-type'); - if (contentType.includes('json') || contentType.includes('text') || contentType.includes('xml')) { + if ( + contentType.includes('json') || + contentType.includes('text') || + contentType.includes('xml') + ) { const snapshot: SnapshotEntry = { text: await response.text(), headersObj: getHeadersObj(response.headers), @@ -67,7 +75,7 @@ export default function useSnapshot( headers: snapshot.headersObj, status: snapshot.status, statusText: snapshot.statusText, - }) + }), ); } }; diff --git a/packages/plugins/statsd/src/index.ts b/packages/plugins/statsd/src/index.ts index 54f22fe3a0c3f..87772321c06ac 100644 --- a/packages/plugins/statsd/src/index.ts +++ b/packages/plugins/statsd/src/index.ts @@ -12,7 +12,9 @@ const metricNames = { fetchLatency: 'fetch.latency', }; -export default function useMeshStatsd(pluginOptions: MeshPluginOptions): MeshPlugin { +export default function useMeshStatsd( + pluginOptions: MeshPluginOptions, +): MeshPlugin { const client = new StatsD(pluginOptions.client); const prefix = pluginOptions.prefix || 'graphql'; return { @@ -21,7 +23,7 @@ export default function useMeshStatsd(pluginOptions: MeshPluginOptions Promise>; export type SubscribeMeshFn = ( @@ -48,7 +48,7 @@ export type SubscribeMeshFn Promise | AsyncIterable>>; export type MeshContext = { @@ -69,5 +69,5 @@ export type MeshExecutor = ( variables?: TVariables, context?: TContext, rootValue?: TRootValue, - operationName?: string + operationName?: string, ) => Promise>; diff --git a/packages/runtime/src/useSubschema.ts b/packages/runtime/src/useSubschema.ts index f435380701b7c..a928dcef8879f 100644 --- a/packages/runtime/src/useSubschema.ts +++ b/packages/runtime/src/useSubschema.ts @@ -1,5 +1,10 @@ import { applyRequestTransforms, applyResultTransforms } from '@graphql-mesh/utils'; -import { createDefaultExecutor, DelegationContext, applySchemaTransforms, Subschema } from '@graphql-tools/delegate'; +import { + createDefaultExecutor, + DelegationContext, + applySchemaTransforms, + Subschema, +} from '@graphql-tools/delegate'; import { ExecutionRequest, getDefinedRootType, @@ -62,19 +67,24 @@ function getExecuteFn(subschema: Subschema) { originalRequest, delegationContext, transformationContext, - subschema.transforms + subschema.transforms, ); const originalResult = await executor(transformedRequest); if (isAsyncIterable(originalResult)) { return mapAsyncIterator(originalResult, singleResult => - applyResultTransforms(singleResult, delegationContext, transformationContext, subschema.transforms) + applyResultTransforms( + singleResult, + delegationContext, + transformationContext, + subschema.transforms, + ), ); } const transformedResult = applyResultTransforms( originalResult, delegationContext, transformationContext, - subschema.transforms + subschema.transforms, ); return transformedResult; }; diff --git a/packages/runtime/test/getMesh.test.ts b/packages/runtime/test/getMesh.test.ts index 42b5eb4a45325..93495b1edc814 100644 --- a/packages/runtime/test/getMesh.test.ts +++ b/packages/runtime/test/getMesh.test.ts @@ -43,7 +43,9 @@ describe('getMesh', () => { function createGraphQLSchema(config: CreateSchemaConfiguration) { const queryTypeName = config.suffixRootTypeNames ? `Query${config.suffix}` : 'Query'; const mutationTypeName = config.suffixRootTypeNames ? `Mutation${config.suffix}` : 'Mutation'; - const subscriptionTypeName = config.suffixRootTypeNames ? `Subscription${config.suffix}` : 'Subscription'; + const subscriptionTypeName = config.suffixRootTypeNames + ? `Subscription${config.suffix}` + : 'Subscription'; return makeExecutableSchema({ typeDefs: ` @@ -114,7 +116,7 @@ describe('getMesh', () => { suffixRootTypeNames: true, suffixFieldNames: false, suffixResponses: false, - }) + }), ), merger, }); @@ -147,7 +149,7 @@ describe('getMesh', () => { hello2 } `, - {} + {}, ); expect(result).toMatchInlineSnapshot(` @@ -186,7 +188,8 @@ describe('getMesh', () => { ], additionalResolvers: { Mutation: { - strikeBack: (root, args, context, info) => context.serviceFoo.Query.helloFoo({ root, args, context, info }), + strikeBack: (root, args, context, info) => + context.serviceFoo.Query.helloFoo({ root, args, context, info }), }, }, }); @@ -197,7 +200,7 @@ describe('getMesh', () => { strikeBack } `, - {} + {}, ); expect(result).toMatchInlineSnapshot(` diff --git a/packages/runtime/test/useSubschema.test.ts b/packages/runtime/test/useSubschema.test.ts index dc5e8631fd6b2..b06556d9604c4 100644 --- a/packages/runtime/test/useSubschema.test.ts +++ b/packages/runtime/test/useSubschema.test.ts @@ -58,7 +58,7 @@ describe('useSubschema', () => { }, ]), ], - }) + }), ); const getEnveloped = envelop({ plugins: [ diff --git a/packages/store/src/index.ts b/packages/store/src/index.ts index 1195d61df2a3c..d4fccca8dbe81 100644 --- a/packages/store/src/index.ts +++ b/packages/store/src/index.ts @@ -44,16 +44,23 @@ export interface FsStoreStorageAdapterOptions { export class FsStoreStorageAdapter implements StoreStorageAdapter { constructor(private options: FsStoreStorageAdapterOptions) {} private getAbsolutePath(jsFileName: string) { - return pathModule.isAbsolute(jsFileName) ? jsFileName : pathModule.join(this.options.cwd, jsFileName); + return pathModule.isAbsolute(jsFileName) + ? jsFileName + : pathModule.join(this.options.cwd, jsFileName); } - async read(key: string, options: ProxyOptions): Promise { + async read( + key: string, + options: ProxyOptions, + ): Promise { let absoluteModulePath = this.getAbsolutePath(key); if (this.options.fileType !== 'ts') { absoluteModulePath += '.' + this.options.fileType; } try { - const importedData = await this.options.importFn(absoluteModulePath).then(m => m.default || m); + const importedData = await this.options + .importFn(absoluteModulePath) + .then(m => m.default || m); if (this.options.fileType === 'json') { return await options.fromJSON(importedData, key); } @@ -69,7 +76,7 @@ export class FsStoreStorageAdapter implements StoreStorageAdapter { async write( key: string, data: TData, - options: ProxyOptions + options: ProxyOptions, ): Promise { const asString = this.options.fileType === 'json' @@ -162,7 +169,11 @@ export default buildASTSchema(schemaAST, { }; export class MeshStore { - constructor(public identifier: string, protected storage: StoreStorageAdapter, public flags: StoreFlags) {} + constructor( + public identifier: string, + protected storage: StoreStorageAdapter, + public flags: StoreFlags, + ) {} child(childIdentifier: string, flags?: Partial): MeshStore { return new MeshStore(pathModule.join(this.identifier, childIdentifier), this.storage, { @@ -189,7 +200,9 @@ export class MeshStore { try { await options.validate(value, newValue, id); } catch (e) { - throw new ValidationError(`Validation failed for "${id}" under "${this.identifier}": ${e.message}`); + throw new ValidationError( + `Validation failed for "${id}" under "${this.identifier}": ${e.message}`, + ); } } }; @@ -216,7 +229,7 @@ export class MeshStore { set: async newValue => { if (this.flags.readonly) { throw new ReadonlyStoreError( - `Unable to set value for "${id}" under "${this.identifier}" because the store is in read-only mode.` + `Unable to set value for "${id}" under "${this.identifier}" because the store is in read-only mode.`, ); } diff --git a/packages/store/test/mesh-store.spec.ts b/packages/store/test/mesh-store.spec.ts index 959cb6883b051..021b704a1da24 100644 --- a/packages/store/test/mesh-store.spec.ts +++ b/packages/store/test/mesh-store.spec.ts @@ -39,7 +39,7 @@ describe('MeshStore and storage', () => { } catch (e) { expect(e instanceof ReadonlyStoreError).toBeTruthy(); expect(e.message).toBe( - `Unable to set value for "file.json" under "test" because the store is in read-only mode.` + `Unable to set value for "file.json" under "test" because the store is in read-only mode.`, ); } }); @@ -70,7 +70,7 @@ describe('MeshStore and storage', () => { } catch (e) { expect(e instanceof ValidationError).toBeTruthy(); expect(e.message).toBe( - `Validation failed for "file.json" under "test": Validation failed! you changed 1 to 2!` + `Validation failed for "file.json" under "test": Validation failed! you changed 1 to 2!`, ); } diff --git a/packages/string-interpolation/src/index.ts b/packages/string-interpolation/src/index.ts index a50352561872c..d964254db9f9e 100644 --- a/packages/string-interpolation/src/index.ts +++ b/packages/string-interpolation/src/index.ts @@ -1,7 +1,8 @@ import { Interpolator } from './interpolator.js'; import dayjs from 'dayjs'; -const hashCode = (s: string) => s.split('').reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0); +const hashCode = (s: string) => + s.split('').reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0); export function hashObject(value: any): string { return hashCode(JSON.stringify(value)).toString(); @@ -17,7 +18,9 @@ stringInterpolator.addAlias('typeName', 'info.parentType.name'); stringInterpolator.addAlias('type', 'info.parentType.name'); stringInterpolator.addAlias('parentType', 'info.parentType.name'); stringInterpolator.addAlias('fieldName', 'info.fieldName'); -stringInterpolator.registerModifier('date', (formatStr: string) => dayjs(new Date()).format(formatStr)); +stringInterpolator.registerModifier('date', (formatStr: string) => + dayjs(new Date()).format(formatStr), +); stringInterpolator.registerModifier('hash', (value: any) => hashObject(value)); stringInterpolator.registerModifier('base64', (value: any) => { if (globalThis.Buffer.from) { diff --git a/packages/string-interpolation/src/modifiers/title.js b/packages/string-interpolation/src/modifiers/title.js index dd6c306ea0276..67a8406fbf59b 100644 --- a/packages/string-interpolation/src/modifiers/title.js +++ b/packages/string-interpolation/src/modifiers/title.js @@ -1 +1,2 @@ -export const titlecase = value => value.replace(/\w\S*/g, s => s.charAt(0).toUpperCase() + s.substr(1).toLowerCase()); +export const titlecase = value => + value.replace(/\w\S*/g, s => s.charAt(0).toUpperCase() + s.substr(1).toLowerCase()); diff --git a/packages/string-interpolation/src/resolver-data-factory.ts b/packages/string-interpolation/src/resolver-data-factory.ts index a425dc891dbf3..9ef85d992c670 100644 --- a/packages/string-interpolation/src/resolver-data-factory.ts +++ b/packages/string-interpolation/src/resolver-data-factory.ts @@ -13,14 +13,17 @@ export type ResolverDataBasedFactory = (data: ResolverData) => T; export function getInterpolationKeys(...interpolationStrings: string[]) { return interpolationStrings.reduce( - (keys, str) => [...keys, ...(str ? stringInterpolator.parseRules(str).map((match: any) => match.key) : [])], - [] as string[] + (keys, str) => [ + ...keys, + ...(str ? stringInterpolator.parseRules(str).map((match: any) => match.key) : []), + ], + [] as string[], ); } export function parseInterpolationStrings( interpolationStrings: Iterable, - argTypeMap?: Record + argTypeMap?: Record, ) { const interpolationKeys = getInterpolationKeys(...interpolationStrings); @@ -32,7 +35,11 @@ export function parseInterpolationStrings( const varName = interpolationKeyParts[interpolationKeyParts.length - 1]; const initialObject = interpolationKeyParts[0]; const argType = - argTypeMap && varName in argTypeMap ? argTypeMap[varName] : interpolationKeyParts.length > 2 ? 'JSON' : 'ID'; + argTypeMap && varName in argTypeMap + ? argTypeMap[varName] + : interpolationKeyParts.length > 2 + ? 'JSON' + : 'ID'; switch (initialObject) { case 'args': args[varName] = { @@ -51,12 +58,14 @@ export function parseInterpolationStrings( }; } -export function getInterpolatedStringFactory(nonInterpolatedString: string): ResolverDataBasedFactory { +export function getInterpolatedStringFactory( + nonInterpolatedString: string, +): ResolverDataBasedFactory { return resolverData => stringInterpolator.parse(nonInterpolatedString, resolverData); } export function getInterpolatedHeadersFactory( - nonInterpolatedHeaders: Record = {} + nonInterpolatedHeaders: Record = {}, ): ResolverDataBasedFactory> { return resolverData => { const headers: Record = {}; diff --git a/packages/transforms/encapsulate/src/index.ts b/packages/transforms/encapsulate/src/index.ts index 59dbc9800b132..c705b5db479fb 100644 --- a/packages/transforms/encapsulate/src/index.ts +++ b/packages/transforms/encapsulate/src/index.ts @@ -3,7 +3,11 @@ import { MeshTransform, YamlConfig, MeshTransformOptions } from '@graphql-mesh/t import { WrapType } from '@graphql-tools/wrap'; import { ExecutionResult, ExecutionRequest, selectObjectFields } from '@graphql-tools/utils'; import { Transform, SubschemaConfig, DelegationContext } from '@graphql-tools/delegate'; -import { applyRequestTransforms, applyResultTransforms, applySchemaTransforms } from '@graphql-mesh/utils'; +import { + applyRequestTransforms, + applyResultTransforms, + applySchemaTransforms, +} from '@graphql-mesh/utils'; const DEFUALT_APPLY_TO = { query: true, @@ -23,7 +27,7 @@ export default class EncapsulateTransform implements MeshTransform { if (!name) { throw new Error( - `Unable to execute encapsulate transform without a name. Please make sure to use it over a specific schema, or specify a name in your configuration!` + `Unable to execute encapsulate transform without a name. Please make sure to use it over a specific schema, or specify a name in your configuration!`, ); } @@ -36,7 +40,11 @@ export default class EncapsulateTransform implements MeshTransform { this.transformMap.Mutation = new WrapType('Mutation', `${name}Mutation`, name) as any; } if (applyTo.subscription) { - this.transformMap.Subscription = new WrapType('Subscription', `${name}Subscription`, name) as any; + this.transformMap.Subscription = new WrapType( + 'Subscription', + `${name}Subscription`, + name, + ) as any; } } @@ -52,21 +60,40 @@ export default class EncapsulateTransform implements MeshTransform { transformSchema( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, - transformedSchema?: GraphQLSchema + transformedSchema?: GraphQLSchema, ) { this.transforms = [...this.generateSchemaTransforms(originalWrappingSchema)]; - return applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, this.transforms); + return applySchemaTransforms( + originalWrappingSchema, + subschemaConfig, + transformedSchema, + this.transforms, + ); } transformRequest( originalRequest: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: Record + transformationContext: Record, ) { - return applyRequestTransforms(originalRequest, delegationContext, transformationContext, this.transforms); + return applyRequestTransforms( + originalRequest, + delegationContext, + transformationContext, + this.transforms, + ); } - transformResult(originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: any) { - return applyResultTransforms(originalResult, delegationContext, transformationContext, this.transforms); + transformResult( + originalResult: ExecutionResult, + delegationContext: DelegationContext, + transformationContext: any, + ) { + return applyResultTransforms( + originalResult, + delegationContext, + transformationContext, + this.transforms, + ); } } diff --git a/packages/transforms/extend/src/index.ts b/packages/transforms/extend/src/index.ts index b613c191f4e6b..2f7d248afa0d7 100644 --- a/packages/transforms/extend/src/index.ts +++ b/packages/transforms/extend/src/index.ts @@ -30,7 +30,9 @@ function tryRequire(modulePath: string, cwd: string) { return require(modulePath); } catch { if (!pathModule.isAbsolute(modulePath)) { - const absoluteModulePath = pathModule.isAbsolute(modulePath) ? modulePath : pathModule.join(cwd, modulePath); + const absoluteModulePath = pathModule.isAbsolute(modulePath) + ? modulePath + : pathModule.join(cwd, modulePath); return require(absoluteModulePath); } } diff --git a/packages/transforms/federation/src/index.ts b/packages/transforms/federation/src/index.ts index 609986ea0f1e0..b2b255940a24b 100644 --- a/packages/transforms/federation/src/index.ts +++ b/packages/transforms/federation/src/index.ts @@ -15,7 +15,12 @@ export default class FederationTransform implements MeshTransform { noWrap = true; - constructor({ apiName, baseDir, config, importFn }: MeshTransformOptions) { + constructor({ + apiName, + baseDir, + config, + importFn, + }: MeshTransformOptions) { this.apiName = apiName; this.config = config; this.baseDir = baseDir; @@ -31,7 +36,8 @@ export default class FederationTransform implements MeshTransform { rawSource.merge[type.name] = {}; const typeObj = schema.getType(type.name) as GraphQLObjectType; typeObj.extensions = typeObj.extensions || {}; - const typeDirectivesObj: any = ((typeObj.extensions as any).directives = typeObj.extensions.directives || {}); + const typeDirectivesObj: any = ((typeObj.extensions as any).directives = + typeObj.extensions.directives || {}); if (type.config?.key) { typeDirectivesObj.key = type.config.key; } @@ -52,10 +58,13 @@ export default class FederationTransform implements MeshTransform { Object.assign(directivesObj, field.config); } rawSource.merge[type.name].fields = rawSource.merge[type.name].fields || {}; - rawSource.merge[type.name].fields[field.name] = rawSource.merge[type.name].fields[field.name] || {}; + rawSource.merge[type.name].fields[field.name] = + rawSource.merge[type.name].fields[field.name] || {}; if (field.config.requires) { rawSource.merge[type.name].fields[field.name].computed = true; - rawSource.merge[type.name].fields[field.name].selectionSet = `{ ${field.config.requires} }`; + rawSource.merge[type.name].fields[ + field.name + ].selectionSet = `{ ${field.config.requires} }`; } } } @@ -137,7 +146,9 @@ export default class FederationTransform implements MeshTransform { _entities: entitiesField, _service: { ...serviceField, - resolve: (root, args, context, info) => ({ sdl: printSchemaWithDirectives(info.schema) }), + resolve: (root, args, context, info) => ({ + sdl: printSchemaWithDirectives(info.schema), + }), }, }, }); diff --git a/packages/transforms/filter-schema/src/bareFilter.ts b/packages/transforms/filter-schema/src/bareFilter.ts index f6c4e106f3bd5..91f6f21588a71 100644 --- a/packages/transforms/filter-schema/src/bareFilter.ts +++ b/packages/transforms/filter-schema/src/bareFilter.ts @@ -25,7 +25,9 @@ export default class BareFilter implements MeshTransform { const rawGlob = argsGlob || fieldNameOrGlob; const fixedGlob = - rawGlob.includes('{') && !rawGlob.includes(',') ? rawGlob.replace('{', '').replace('}', '') : rawGlob; + rawGlob.includes('{') && !rawGlob.includes(',') + ? rawGlob.replace('{', '').replace('}', '') + : rawGlob; const polishedGlob = fixedGlob.split(', ').join(',').trim(); if (typeName === 'Type') { @@ -68,8 +70,10 @@ export default class BareFilter implements MeshTransform { const fieldArgs = Object.entries(fieldConfig.args).reduce( (args, [argName, argConfig]) => - this.matchInArray(argRules, argName) === null ? args : { ...args, [argName]: argConfig }, - {} + this.matchInArray(argRules, argName) === null + ? args + : { ...args, [argName]: argConfig }, + {}, ); return { ...fieldConfig, args: fieldArgs }; diff --git a/packages/transforms/filter-schema/src/wrapFilter.ts b/packages/transforms/filter-schema/src/wrapFilter.ts index db6186e871f16..9b208d6d1121f 100644 --- a/packages/transforms/filter-schema/src/wrapFilter.ts +++ b/packages/transforms/filter-schema/src/wrapFilter.ts @@ -1,5 +1,9 @@ import { YamlConfig } from '@graphql-mesh/types'; -import { applyRequestTransforms, applyResultTransforms, applySchemaTransforms } from '@graphql-mesh/utils'; +import { + applyRequestTransforms, + applyResultTransforms, + applySchemaTransforms, +} from '@graphql-mesh/utils'; import { DelegationContext, SubschemaConfig, Transform } from '@graphql-tools/delegate'; import { ExecutionResult, ExecutionRequest } from '@graphql-tools/utils'; import { @@ -24,7 +28,7 @@ export default class WrapFilter implements Transform { this.transforms.push( new FilterTypes(type => { return typeMatcher.match(type.name); - }) as any + }) as any, ); continue; } @@ -41,7 +45,7 @@ export default class WrapFilter implements Transform { this.transforms.push( new FilterTypes(type => { return globalTypeMatcher.match(type.name); - }) + }), ); continue; } @@ -55,13 +59,13 @@ export default class WrapFilter implements Transform { const fieldArgs = Object.entries(fieldConfig.args).reduce( (args, [argName, argConfig]) => !globalTypeMatcher.match(argName) ? args : { ...args, [argName]: argConfig }, - {} + {}, ); return { ...fieldConfig, args: fieldArgs }; } return undefined; - }) + }), ); continue; } @@ -73,7 +77,7 @@ export default class WrapFilter implements Transform { return globalTypeMatcher.match(rootFieldName); } return true; - }) + }), ); this.transforms.push( @@ -82,7 +86,7 @@ export default class WrapFilter implements Transform { return globalTypeMatcher.match(objectFieldName); } return true; - }) + }), ); this.transforms.push( @@ -91,7 +95,7 @@ export default class WrapFilter implements Transform { return globalTypeMatcher.match(inputObjectFieldName); } return true; - }) + }), ); } } @@ -99,20 +103,39 @@ export default class WrapFilter implements Transform { transformSchema( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, - transformedSchema?: GraphQLSchema + transformedSchema?: GraphQLSchema, ) { - return applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, this.transforms); + return applySchemaTransforms( + originalWrappingSchema, + subschemaConfig, + transformedSchema, + this.transforms, + ); } transformRequest( originalRequest: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: Record + transformationContext: Record, ) { - return applyRequestTransforms(originalRequest, delegationContext, transformationContext, this.transforms); + return applyRequestTransforms( + originalRequest, + delegationContext, + transformationContext, + this.transforms, + ); } - transformResult(originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: any) { - return applyResultTransforms(originalResult, delegationContext, transformationContext, this.transforms); + transformResult( + originalResult: ExecutionResult, + delegationContext: DelegationContext, + transformationContext: any, + ) { + return applyResultTransforms( + originalResult, + delegationContext, + transformationContext, + this.transforms, + ); } } diff --git a/packages/transforms/filter-schema/test/transform.spec.ts b/packages/transforms/filter-schema/test/transform.spec.ts index 61db29ae9e6fa..0ffb37838c47e 100644 --- a/packages/transforms/filter-schema/test/transform.spec.ts +++ b/packages/transforms/filter-schema/test/transform.spec.ts @@ -56,7 +56,7 @@ type Post { type Query { user(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -112,7 +112,7 @@ type Post { type Query { user(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -195,7 +195,7 @@ type Post { type Query { user(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -236,7 +236,7 @@ type Query { userOne(name: String, age: Int): User userTwo(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -277,7 +277,7 @@ type Query { userOne(name: String): User userTwo(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -318,7 +318,7 @@ type Query { userOne(name: String, age: Int): User userTwo(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -359,7 +359,7 @@ type Query { userOne(name: String): User userTwo(name: String, age: Int): User } -`.trim() +`.trim(), ); }); @@ -414,7 +414,7 @@ type Book { type Query { user: User } -`.trim() +`.trim(), ); }); @@ -444,7 +444,7 @@ type Query { foo: String bar: String } -`.trim() +`.trim(), ); }); it('should filter out fields if array syntax is used only with one element', async () => { @@ -495,7 +495,7 @@ type Book { type Query { user: User } -`.trim() +`.trim(), ); }); @@ -550,7 +550,7 @@ type Query { user: User admin: User } -`.trim() +`.trim(), ); }); @@ -615,7 +615,7 @@ type Post { type Query { user(id: ID!): User } -`.trim() +`.trim(), ); }); @@ -681,7 +681,7 @@ type Post { type Query { user(id: ID!): User } -`.trim() +`.trim(), ); }); @@ -732,7 +732,7 @@ type Book { type Query { book: Book } -`.trim() +`.trim(), ); }); @@ -745,7 +745,13 @@ type Query { rule: String } - directive @auth(query: AuthRule, add: AuthRule, update: AuthRule, delete: AuthRule, role: String!) on OBJECT + directive @auth( + query: AuthRule + add: AuthRule + update: AuthRule + delete: AuthRule + role: String! + ) on OBJECT type User { id: ID @@ -805,7 +811,7 @@ type Query { user: User admin: User } -`.trim() +`.trim(), ); }); @@ -855,7 +861,7 @@ type Query { user(name: String): User book(title: String): Book } -`.trim() +`.trim(), ); }); }); diff --git a/packages/transforms/hive/src/index.ts b/packages/transforms/hive/src/index.ts index 5f1d10315343a..9384905aa7f38 100644 --- a/packages/transforms/hive/src/index.ts +++ b/packages/transforms/hive/src/index.ts @@ -85,7 +85,7 @@ export default class HiveTransform implements MeshTransform { transformRequest( request: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: TransformationContext + transformationContext: TransformationContext, ) { transformationContext.collectUsageCallback = this.hiveClient.collectUsage({ schema: delegationContext.transformedSchema, @@ -101,7 +101,7 @@ export default class HiveTransform implements MeshTransform { transformResult( result: ExecutionResult, _delegationContext: DelegationContext, - transformationContext: TransformationContext + transformationContext: TransformationContext, ) { transformationContext.collectUsageCallback(result); return result; diff --git a/packages/transforms/hoist-field/src/index.ts b/packages/transforms/hoist-field/src/index.ts index 699e7cf1d9d62..68a411448cbdd 100644 --- a/packages/transforms/hoist-field/src/index.ts +++ b/packages/transforms/hoist-field/src/index.ts @@ -1,5 +1,9 @@ import { MeshTransform, MeshTransformOptions, YamlConfig } from '@graphql-mesh/types'; -import { applyRequestTransforms, applyResultTransforms, applySchemaTransforms } from '@graphql-mesh/utils'; +import { + applyRequestTransforms, + applyResultTransforms, + applySchemaTransforms, +} from '@graphql-mesh/utils'; import { DelegationContext, SubschemaConfig, Transform } from '@graphql-tools/delegate'; import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils'; import { HoistField } from '@graphql-tools/wrap'; @@ -13,15 +17,19 @@ export default class MeshHoistField implements MeshTransform { private transforms: Transform[]; constructor({ config }: MeshTransformOptions) { - this.transforms = config.map(({ typeName, pathConfig, newFieldName, alias, filterArgsInPath = false }) => { - const processedPathConfig = pathConfig.map(config => this.getPathConfigItem(config, filterArgsInPath)); - return new HoistField(typeName, processedPathConfig, newFieldName, alias); - }); + this.transforms = config.map( + ({ typeName, pathConfig, newFieldName, alias, filterArgsInPath = false }) => { + const processedPathConfig = pathConfig.map(config => + this.getPathConfigItem(config, filterArgsInPath), + ); + return new HoistField(typeName, processedPathConfig, newFieldName, alias); + }, + ); } private getPathConfigItem( pathConfigItemFromConfig: HoistFieldTransformFieldPathConfig, - filterArgsInPath: boolean + filterArgsInPath: boolean, ): HoistFieldCtorPathConfigItem { if (typeof pathConfigItemFromConfig === 'string') { const pathConfigItem: HoistFieldCtorPathConfigItem = { @@ -58,21 +66,40 @@ export default class MeshHoistField implements MeshTransform { transformSchema( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, - transformedSchema?: GraphQLSchema + transformedSchema?: GraphQLSchema, ) { - return applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, this.transforms); + return applySchemaTransforms( + originalWrappingSchema, + subschemaConfig, + transformedSchema, + this.transforms, + ); } transformRequest( originalRequest: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: Record + transformationContext: Record, ) { - return applyRequestTransforms(originalRequest, delegationContext, transformationContext, this.transforms); + return applyRequestTransforms( + originalRequest, + delegationContext, + transformationContext, + this.transforms, + ); } - transformResult(originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: any) { - return applyResultTransforms(originalResult, delegationContext, transformationContext, this.transforms); + transformResult( + originalResult: ExecutionResult, + delegationContext: DelegationContext, + transformationContext: any, + ) { + return applyResultTransforms( + originalResult, + delegationContext, + transformationContext, + this.transforms, + ); } } diff --git a/packages/transforms/naming-convention/src/bareNamingConvention.ts b/packages/transforms/naming-convention/src/bareNamingConvention.ts index 12b2ea6a2521f..95d33e445660c 100644 --- a/packages/transforms/naming-convention/src/bareNamingConvention.ts +++ b/packages/transforms/naming-convention/src/bareNamingConvention.ts @@ -30,10 +30,13 @@ export declare type GraphQLTypePointer = | GraphQLList >; -const isObject = (input: any) => typeof input === 'object' && input !== null && !Array.isArray(input) && true; +const isObject = (input: any) => + typeof input === 'object' && input !== null && !Array.isArray(input) && true; const getUnderlyingType = (type: GraphQLOutputType): GraphQLOutputType => - (type as GraphQLTypePointer).ofType ? getUnderlyingType((type as GraphQLTypePointer).ofType) : type; + (type as GraphQLTypePointer).ofType + ? getUnderlyingType((type as GraphQLTypePointer).ofType) + : type; // Resolver composer mapping renamed field and arguments const defaultResolverComposer = @@ -41,7 +44,7 @@ const defaultResolverComposer = resolveFn = defaultFieldResolver, originalFieldName: string, argsMap: { [key: string]: string }, - resultMap: { [key: string]: string } + resultMap: { [key: string]: string }, ) => (root: any, args: any, context: any, info: any) => { const originalResult = resolveFn( @@ -70,7 +73,7 @@ const defaultResolverComposer = : args, context, // map renamed field name to its original value - originalFieldName ? { ...info, fieldName: originalFieldName } : info + originalFieldName ? { ...info, fieldName: originalFieldName } : info, ); // map result values from original value to new renamed value @@ -95,7 +98,9 @@ export default class NamingConventionTransform implements MeshTransform { [MapperKind.TYPE]: type => { const oldName = type.name; const namingConventionFn = NAMING_CONVENTIONS[this.config.typeNames]; - const newName = IGNORED_TYPE_NAMES.includes(oldName) ? oldName : namingConventionFn(oldName); + const newName = IGNORED_TYPE_NAMES.includes(oldName) + ? oldName + : namingConventionFn(oldName); if (newName !== undefined && newName !== oldName) { return renameType(type, newName); @@ -107,10 +112,17 @@ export default class NamingConventionTransform implements MeshTransform { const currentName = type.name; const existingResolver = type.resolveType; const namingConventionFn = NAMING_CONVENTIONS[this.config.typeNames]; - const newName = IGNORED_TYPE_NAMES.includes(currentName) ? currentName : namingConventionFn(currentName); + const newName = IGNORED_TYPE_NAMES.includes(currentName) + ? currentName + : namingConventionFn(currentName); type.resolveType = async (data, context, info, abstractType) => { - const originalResolvedTypename = await existingResolver(data, context, info, abstractType); + const originalResolvedTypename = await existingResolver( + data, + context, + info, + abstractType, + ); return IGNORED_TYPE_NAMES.includes(originalResolvedTypename) ? originalResolvedTypename : namingConventionFn(originalResolvedTypename); @@ -151,7 +163,8 @@ export default class NamingConventionTransform implements MeshTransform { ...((this.config.fieldNames || this.config.fieldArgumentNames) && { [MapperKind.COMPOSITE_FIELD]: (fieldConfig, fieldName) => { const enumNamingConventionFn = NAMING_CONVENTIONS[this.config.enumValues]; - const fieldNamingConventionFn = this.config.fieldNames && NAMING_CONVENTIONS[this.config.fieldNames]; + const fieldNamingConventionFn = + this.config.fieldNames && NAMING_CONVENTIONS[this.config.fieldNames]; const argNamingConventionFn = this.config.fieldArgumentNames && NAMING_CONVENTIONS[this.config.fieldArgumentNames]; const argsMap = fieldConfig.args && {}; @@ -178,49 +191,59 @@ export default class NamingConventionTransform implements MeshTransform { }, {}); if (fieldConfig.args) { - fieldConfig.args = Object.entries(fieldConfig.args).reduce((args, [argName, argConfig]) => { - const newArgName = this.config.fieldArgumentNames && argNamingConventionFn(argName); - const useArgName = newArgName || argName; - const argIsInputObjectType = isInputObjectType(argConfig.type); - - if (argName !== useArgName || argIsInputObjectType) { - // take advantage of the loop to map arg name from Old to New - argsMap[useArgName] = !argIsInputObjectType - ? argName - : { - [argName]: Object.keys((argConfig.type as GraphQLInputObjectType).toConfig().fields).reduce( - (inputFields, inputFieldName) => { + fieldConfig.args = Object.entries(fieldConfig.args).reduce( + (args, [argName, argConfig]) => { + const newArgName = this.config.fieldArgumentNames && argNamingConventionFn(argName); + const useArgName = newArgName || argName; + const argIsInputObjectType = isInputObjectType(argConfig.type); + + if (argName !== useArgName || argIsInputObjectType) { + // take advantage of the loop to map arg name from Old to New + argsMap[useArgName] = !argIsInputObjectType + ? argName + : { + [argName]: Object.keys( + (argConfig.type as GraphQLInputObjectType).toConfig().fields, + ).reduce((inputFields, inputFieldName) => { if (Number.isFinite(inputFieldName)) return inputFields; - const newInputFieldName = fieldNamingConventionFn(inputFieldName as string); + const newInputFieldName = fieldNamingConventionFn( + inputFieldName as string, + ); return newInputFieldName === inputFieldName ? inputFields : { ...inputFields, [fieldNamingConventionFn(inputFieldName as string)]: inputFieldName, }; - }, - {} - ), - }; - } + }, {}), + }; + } - return { - ...args, - [useArgName]: argConfig, - }; - }, {}); + return { + ...args, + [useArgName]: argConfig, + }; + }, + {}, + ); } // Wrap resolve fn to handle mapping renamed field and argument names as well as results (for enums) - fieldConfig.resolve = defaultResolverComposer(fieldConfig.resolve, fieldName, argsMap, resultMap); + fieldConfig.resolve = defaultResolverComposer( + fieldConfig.resolve, + fieldName, + argsMap, + resultMap, + ); return [newFieldName || fieldName, fieldConfig]; }, }), ...(this.config.fieldNames && { [MapperKind.INPUT_OBJECT_FIELD]: (inputFieldConfig, fieldName) => { - const namingConventionFn = this.config.fieldNames && NAMING_CONVENTIONS[this.config.fieldNames]; + const namingConventionFn = + this.config.fieldNames && NAMING_CONVENTIONS[this.config.fieldNames]; const newName = namingConventionFn(fieldName); if (newName === fieldName) { diff --git a/packages/transforms/naming-convention/src/index.ts b/packages/transforms/naming-convention/src/index.ts index bb1a5765b39d7..29eda9ce83c95 100644 --- a/packages/transforms/naming-convention/src/index.ts +++ b/packages/transforms/naming-convention/src/index.ts @@ -9,7 +9,9 @@ interface NamingConventionTransformConstructor { } export default (function NamingConventionTransform( - options: MeshTransformOptions + options: MeshTransformOptions, ) { - return options.config.mode === 'bare' ? new BareNamingConvention(options) : new WrapNamingConvention(options); + return options.config.mode === 'bare' + ? new BareNamingConvention(options) + : new WrapNamingConvention(options); } as unknown as NamingConventionTransformConstructor); diff --git a/packages/transforms/naming-convention/src/wrapNamingConvention.ts b/packages/transforms/naming-convention/src/wrapNamingConvention.ts index 725ae1741ae59..7faba636022b7 100644 --- a/packages/transforms/naming-convention/src/wrapNamingConvention.ts +++ b/packages/transforms/naming-convention/src/wrapNamingConvention.ts @@ -10,7 +10,11 @@ import { } from '@graphql-tools/wrap'; import { ExecutionResult, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, SubschemaConfig, DelegationContext } from '@graphql-tools/delegate'; -import { applyRequestTransforms, applyResultTransforms, applySchemaTransforms } from '@graphql-mesh/utils'; +import { + applyRequestTransforms, + applyResultTransforms, + applySchemaTransforms, +} from '@graphql-mesh/utils'; import { NAMING_CONVENTIONS, IGNORED_ROOT_FIELD_NAMES, IGNORED_TYPE_NAMES } from './shared.js'; @@ -22,8 +26,10 @@ export default class NamingConventionTransform implements MeshTransform { const namingConventionFn = NAMING_CONVENTIONS[options.config.typeNames]; this.transforms.push( new RenameTypes(typeName => - IGNORED_TYPE_NAMES.includes(typeName) ? typeName : namingConventionFn(typeName) || typeName - ) as any + IGNORED_TYPE_NAMES.includes(typeName) + ? typeName + : namingConventionFn(typeName) || typeName, + ) as any, ); } if (options.config.fieldNames) { @@ -31,12 +37,18 @@ export default class NamingConventionTransform implements MeshTransform { ? NAMING_CONVENTIONS[options.config.fieldNames] : (s: string) => s; this.transforms.push( - new RenameInputObjectFields((_, fieldName) => fieldNamingConventionFn(fieldName) || fieldName) as any, + new RenameInputObjectFields( + (_, fieldName) => fieldNamingConventionFn(fieldName) || fieldName, + ) as any, new TransformObjectFields((_, fieldName, fieldConfig) => [ - IGNORED_ROOT_FIELD_NAMES.includes(fieldName) ? fieldName : fieldNamingConventionFn(fieldName) || fieldName, + IGNORED_ROOT_FIELD_NAMES.includes(fieldName) + ? fieldName + : fieldNamingConventionFn(fieldName) || fieldName, fieldConfig, ]) as any, - new RenameInterfaceFields((_, fieldName) => fieldNamingConventionFn(fieldName) || fieldName) as any + new RenameInterfaceFields( + (_, fieldName) => fieldNamingConventionFn(fieldName) || fieldName, + ) as any, ); } @@ -46,7 +58,9 @@ export default class NamingConventionTransform implements MeshTransform { : (s: string) => s; this.transforms.push( - new RenameObjectFieldArguments((_typeName, _fieldName, argName) => fieldArgNamingConventionFn(argName)) as any + new RenameObjectFieldArguments((_typeName, _fieldName, argName) => + fieldArgNamingConventionFn(argName), + ) as any, ); } @@ -57,7 +71,7 @@ export default class NamingConventionTransform implements MeshTransform { new TransformEnumValues((typeName, externalValue, enumValueConfig) => { const newEnumValue = namingConventionFn(externalValue) || externalValue; return [newEnumValue, enumValueConfig]; - }) as any + }) as any, ); } } @@ -65,20 +79,39 @@ export default class NamingConventionTransform implements MeshTransform { transformSchema( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, - transformedSchema?: GraphQLSchema + transformedSchema?: GraphQLSchema, ) { - return applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, this.transforms); + return applySchemaTransforms( + originalWrappingSchema, + subschemaConfig, + transformedSchema, + this.transforms, + ); } transformRequest( originalRequest: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: Record + transformationContext: Record, ) { - return applyRequestTransforms(originalRequest, delegationContext, transformationContext, this.transforms); + return applyRequestTransforms( + originalRequest, + delegationContext, + transformationContext, + this.transforms, + ); } - transformResult(originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: any) { - return applyResultTransforms(originalResult, delegationContext, transformationContext, this.transforms); + transformResult( + originalResult: ExecutionResult, + delegationContext: DelegationContext, + transformationContext: any, + ) { + return applyResultTransforms( + originalResult, + delegationContext, + transformationContext, + this.transforms, + ); } } diff --git a/packages/transforms/prefix/src/barePrefix.ts b/packages/transforms/prefix/src/barePrefix.ts index a611903acc142..9ea30bfe5d2b1 100644 --- a/packages/transforms/prefix/src/barePrefix.ts +++ b/packages/transforms/prefix/src/barePrefix.ts @@ -66,7 +66,7 @@ export default class BarePrefix implements MeshTransform { [MapperKind.COMPOSITE_FIELD]: ( fieldConfig: GraphQLFieldConfig, fieldName: string, - typeName: string + typeName: string, ) => { return !rootOperations.has(typeName) || // check we're in a root Type this.ignoreList.includes(typeName) || // check if type is to be ignored diff --git a/packages/transforms/prefix/src/index.ts b/packages/transforms/prefix/src/index.ts index dd8c13581a5f5..09f43ca935a64 100644 --- a/packages/transforms/prefix/src/index.ts +++ b/packages/transforms/prefix/src/index.ts @@ -6,6 +6,8 @@ interface PrefixTransformConstructor { new (options: MeshTransformOptions): BarePrefix | WrapPrefix; } -export default (function PrefixTransform(options: MeshTransformOptions) { +export default (function PrefixTransform( + options: MeshTransformOptions, +) { return options.config.mode === 'bare' ? new BarePrefix(options) : new WrapPrefix(options); } as unknown as PrefixTransformConstructor); diff --git a/packages/transforms/prefix/src/wrapPrefix.ts b/packages/transforms/prefix/src/wrapPrefix.ts index f7c8cd622254f..9690ea277811c 100644 --- a/packages/transforms/prefix/src/wrapPrefix.ts +++ b/packages/transforms/prefix/src/wrapPrefix.ts @@ -3,7 +3,11 @@ import { MeshTransform, YamlConfig, MeshTransformOptions } from '@graphql-mesh/t import { RenameTypes, RenameRootFields } from '@graphql-tools/wrap'; import { ExecutionResult, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, SubschemaConfig, DelegationContext } from '@graphql-tools/delegate'; -import { applyRequestTransforms, applyResultTransforms, applySchemaTransforms } from '@graphql-mesh/utils'; +import { + applyRequestTransforms, + applyResultTransforms, + applySchemaTransforms, +} from '@graphql-mesh/utils'; import { ignoreList as defaultIgnoreList } from './shared.js'; export default class WrapPrefix implements MeshTransform { @@ -29,7 +33,9 @@ export default class WrapPrefix implements MeshTransform { if (includeTypes) { this.transforms.push( - new RenameTypes(typeName => (ignoreList.includes(typeName) ? typeName : `${prefix}${typeName}`)) as any + new RenameTypes(typeName => + ignoreList.includes(typeName) ? typeName : `${prefix}${typeName}`, + ) as any, ); } @@ -40,8 +46,8 @@ export default class WrapPrefix implements MeshTransform { new RenameRootFields((typeName, fieldName) => ignoreList.includes(typeName) || ignoreList.includes(`${typeName}.${fieldName}`) ? fieldName - : `${prefix}${fieldName}` - ) as any + : `${prefix}${fieldName}`, + ) as any, ); } } @@ -49,20 +55,39 @@ export default class WrapPrefix implements MeshTransform { transformSchema( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, - transformedSchema?: GraphQLSchema + transformedSchema?: GraphQLSchema, ) { - return applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, this.transforms); + return applySchemaTransforms( + originalWrappingSchema, + subschemaConfig, + transformedSchema, + this.transforms, + ); } transformRequest( originalRequest: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: Record + transformationContext: Record, ) { - return applyRequestTransforms(originalRequest, delegationContext, transformationContext, this.transforms); + return applyRequestTransforms( + originalRequest, + delegationContext, + transformationContext, + this.transforms, + ); } - transformResult(originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: any) { - return applyResultTransforms(originalResult, delegationContext, transformationContext, this.transforms); + transformResult( + originalResult: ExecutionResult, + delegationContext: DelegationContext, + transformationContext: any, + ) { + return applyResultTransforms( + originalResult, + delegationContext, + transformationContext, + this.transforms, + ); } } diff --git a/packages/transforms/rate-limit/src/index.ts b/packages/transforms/rate-limit/src/index.ts index d1b5d5c213959..731b3a2b8dc4d 100644 --- a/packages/transforms/rate-limit/src/index.ts +++ b/packages/transforms/rate-limit/src/index.ts @@ -25,7 +25,10 @@ export default class RateLimitTransform implements MeshTransform { private errors = new WeakMap(); - transformRequest(executionRequest: ExecutionRequest, delegationContext: DelegationContext): ExecutionRequest { + transformRequest( + executionRequest: ExecutionRequest, + delegationContext: DelegationContext, + ): ExecutionRequest { const { transformedSchema, rootValue, args, context, info } = delegationContext; if (transformedSchema) { const errors: GraphQLError[] = []; @@ -61,7 +64,9 @@ export default class RateLimitTransform implements MeshTransform { } if (remainingTokens === 0) { - errors.push(new GraphQLError(`Rate limit of "${path}" exceeded for "${identifier}"`)); + errors.push( + new GraphQLError(`Rate limit of "${path}" exceeded for "${identifier}"`), + ); // Remove this field from the selection set return null; } else { @@ -71,7 +76,7 @@ export default class RateLimitTransform implements MeshTransform { remainingFields++; return false; }, - }) + }), ); if (remainingFields === 0) { if (errors.length === 1) { diff --git a/packages/transforms/rename/src/bareRename.ts b/packages/transforms/rename/src/bareRename.ts index 82eda69926c35..5ff25fd16641b 100644 --- a/packages/transforms/rename/src/bareRename.ts +++ b/packages/transforms/rename/src/bareRename.ts @@ -1,4 +1,9 @@ -import { GraphQLSchema, defaultFieldResolver, GraphQLFieldConfig, GraphQLAbstractType } from 'graphql'; +import { + GraphQLSchema, + defaultFieldResolver, + GraphQLFieldConfig, + GraphQLAbstractType, +} from 'graphql'; import { MeshTransform, YamlConfig } from '@graphql-mesh/types'; import { renameType, MapperKind, mapSchema } from '@graphql-tools/utils'; import { ignoreList } from './shared.js'; @@ -7,17 +12,24 @@ type RenameMapObject = Map; // Resolver composer mapping renamed field and arguments const defaultResolverComposer = - (resolveFn = defaultFieldResolver, originalFieldName: string, argsMap: { [key: string]: string }) => + ( + resolveFn = defaultFieldResolver, + originalFieldName: string, + argsMap: { [key: string]: string }, + ) => (root: any, args: any, context: any, info: any) => resolveFn( root, // map renamed arguments to their original value argsMap - ? Object.keys(args).reduce((acc, key: string) => ({ ...acc, [argsMap[key] || key]: args[key] }), {}) + ? Object.keys(args).reduce( + (acc, key: string) => ({ ...acc, [argsMap[key] || key]: args[key] }), + {}, + ) : args, context, // map renamed field name to its original value - originalFieldName ? { ...info, fieldName: originalFieldName } : info + originalFieldName ? { ...info, fieldName: originalFieldName } : info, ); export default class BareRename implements MeshTransform { @@ -41,11 +53,28 @@ export default class BareRename implements MeshTransform { const regExpFlags = rename.regExpFlags || undefined; - if (fromTypeName && !fromFieldName && toTypeName && !toFieldName && fromTypeName !== toTypeName) { - this.typesMap.set(useRegExpForTypes ? new RegExp(fromTypeName, regExpFlags) : fromTypeName, toTypeName); + if ( + fromTypeName && + !fromFieldName && + toTypeName && + !toFieldName && + fromTypeName !== toTypeName + ) { + this.typesMap.set( + useRegExpForTypes ? new RegExp(fromTypeName, regExpFlags) : fromTypeName, + toTypeName, + ); } - if (fromTypeName && fromFieldName && toTypeName && toFieldName && fromFieldName !== toFieldName) { - const fromName = useRegExpForFields ? new RegExp(fromFieldName, regExpFlags) : fromFieldName; + if ( + fromTypeName && + fromFieldName && + toTypeName && + toFieldName && + fromFieldName !== toFieldName + ) { + const fromName = useRegExpForFields + ? new RegExp(fromFieldName, regExpFlags) + : fromFieldName; const typeMap = this.fieldsMap.get(fromTypeName) || new Map(); this.fieldsMap.set(fromTypeName, typeMap.set(fromName, toFieldName)); } @@ -68,7 +97,9 @@ export default class BareRename implements MeshTransform { matchInMap(map: RenameMapObject, toMatch: string) { const mapKeyIsString = map.has(toMatch); - const mapKey = mapKeyIsString ? toMatch : [...map.keys()].find(key => typeof key !== 'string' && key.test(toMatch)); + const mapKey = mapKeyIsString + ? toMatch + : [...map.keys()].find(key => typeof key !== 'string' && key.test(toMatch)); if (!mapKey) return null; const newName = mapKeyIsString ? map.get(mapKey) : toMatch.replace(mapKey, map.get(mapKey)); @@ -80,7 +111,9 @@ export default class BareRename implements MeshTransform { } renameType(type: any) { - const newTypeName = ignoreList.includes(type.toString()) ? null : this.matchInMap(this.typesMap, type.toString()); + const newTypeName = ignoreList.includes(type.toString()) + ? null + : this.matchInMap(this.typesMap, type.toString()); return newTypeName ? renameType(type, newTypeName) : undefined; } @@ -90,11 +123,18 @@ export default class BareRename implements MeshTransform { [MapperKind.TYPE]: type => this.renameType(type), [MapperKind.ABSTRACT_TYPE]: type => { const currentName = type.toString(); - const newName = ignoreList.includes(currentName) ? null : this.matchInMap(this.typesMap, currentName); + const newName = ignoreList.includes(currentName) + ? null + : this.matchInMap(this.typesMap, currentName); const existingResolver = type.resolveType; type.resolveType = async (data, context, info, abstractType) => { - const originalResolvedTypename = await existingResolver(data, context, info, abstractType); + const originalResolvedTypename = await existingResolver( + data, + context, + info, + abstractType, + ); const newTypename = ignoreList.includes(originalResolvedTypename) ? null : this.matchInMap(this.typesMap, originalResolvedTypename); @@ -114,14 +154,17 @@ export default class BareRename implements MeshTransform { [MapperKind.COMPOSITE_FIELD]: ( fieldConfig: GraphQLFieldConfig, fieldName: string, - typeName: string + typeName: string, ) => { const typeRules = this.fieldsMap.get(typeName); const fieldRules = this.argsMap.get(`${typeName}.${fieldName}`); const newFieldName = typeRules && this.matchInMap(typeRules, fieldName); const argsMap = fieldRules && - Array.from(fieldRules.entries()).reduce((acc, [orName, newName]) => ({ ...acc, [newName]: orName }), {}); + Array.from(fieldRules.entries()).reduce( + (acc, [orName, newName]) => ({ ...acc, [newName]: orName }), + {}, + ); if (!newFieldName && !fieldRules) return undefined; // Rename rules for type might have been emptied by matchInMap, in which case we can cleanup @@ -133,7 +176,7 @@ export default class BareRename implements MeshTransform { ...args, [this.matchInMap(fieldRules, argName) || argName]: argConfig, }), - {} + {}, ); } diff --git a/packages/transforms/rename/src/wrapRename.ts b/packages/transforms/rename/src/wrapRename.ts index 1be9cea27fec9..4dad11dde3d18 100644 --- a/packages/transforms/rename/src/wrapRename.ts +++ b/packages/transforms/rename/src/wrapRename.ts @@ -8,7 +8,11 @@ import { } from '@graphql-tools/wrap'; import { ExecutionResult, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, SubschemaConfig, DelegationContext } from '@graphql-tools/delegate'; -import { applyRequestTransforms, applyResultTransforms, applySchemaTransforms } from '@graphql-mesh/utils'; +import { + applyRequestTransforms, + applyResultTransforms, + applySchemaTransforms, +} from '@graphql-mesh/utils'; import { ignoreList } from './shared.js'; export default class WrapRename implements Transform { @@ -40,7 +44,7 @@ export default class WrapRename implements Transform { return typeName; } return replaceTypeNameFn(typeName); - }) as any + }) as any, ); } @@ -71,11 +75,15 @@ export default class WrapRename implements Transform { const fieldNameMatch = (fieldName: string) => fieldName === - (useRegExpForFields ? fieldName.replace(new RegExp(fromFieldName, regExpFlags), toFieldName) : toFieldName); + (useRegExpForFields + ? fieldName.replace(new RegExp(fromFieldName, regExpFlags), toFieldName) + : toFieldName); const typeNameMatch = (typeName: string) => typeName === - (useRegExpForTypes ? typeName.replace(new RegExp(fromTypeName, regExpFlags), toTypeName) : toTypeName); + (useRegExpForTypes + ? typeName.replace(new RegExp(fromTypeName, regExpFlags), toTypeName) + : toTypeName); if (useRegExpForArguments) { const argNameRegExp = new RegExp(fromArgumentName, regExpFlags); @@ -98,20 +106,39 @@ export default class WrapRename implements Transform { transformSchema( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, - transformedSchema?: GraphQLSchema + transformedSchema?: GraphQLSchema, ) { - return applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, this.transforms); + return applySchemaTransforms( + originalWrappingSchema, + subschemaConfig, + transformedSchema, + this.transforms, + ); } transformRequest( originalRequest: ExecutionRequest, delegationContext: DelegationContext, - transformationContext: Record + transformationContext: Record, ) { - return applyRequestTransforms(originalRequest, delegationContext, transformationContext, this.transforms); + return applyRequestTransforms( + originalRequest, + delegationContext, + transformationContext, + this.transforms, + ); } - transformResult(originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: any) { - return applyResultTransforms(originalResult, delegationContext, transformationContext, this.transforms); + transformResult( + originalResult: ExecutionResult, + delegationContext: DelegationContext, + transformationContext: any, + ) { + return applyResultTransforms( + originalResult, + delegationContext, + transformationContext, + this.transforms, + ); } } diff --git a/packages/transforms/replace-field/src/index.ts b/packages/transforms/replace-field/src/index.ts index d6ef94f5bf0c3..cb2b4456910e6 100644 --- a/packages/transforms/replace-field/src/index.ts +++ b/packages/transforms/replace-field/src/index.ts @@ -1,4 +1,10 @@ -import { extendSchema, defaultFieldResolver, GraphQLFieldConfig, GraphQLFieldResolver, GraphQLSchema } from 'graphql'; +import { + extendSchema, + defaultFieldResolver, + GraphQLFieldConfig, + GraphQLFieldResolver, + GraphQLSchema, +} from 'graphql'; import { ImportFn, MeshTransform, MeshTransformOptions, YamlConfig } from '@graphql-mesh/types'; import { loadFromModuleExportExpression } from '@graphql-mesh/utils'; import { CodeFileLoader } from '@graphql-tools/code-file-loader'; @@ -53,7 +59,9 @@ export default class ReplaceFieldTransform implements MeshTransform { composer: (fn: any) => (...args: any[]) => - composerFn$.then(composerFn => (composerFn ? composerFn(fn) : fn)).then(fn => fn(...args)), + composerFn$ + .then(composerFn => (composerFn ? composerFn(fn) : fn)) + .then(fn => fn(...args)), name, }); } @@ -66,13 +74,15 @@ export default class ReplaceFieldTransform implements MeshTransform { cwd: this.baseDir, loaders: [new CodeFileLoader(), new GraphQLFileLoader()], }); - const baseSchema = additionalTypeDefs ? extendSchema(schema, additionalTypeDefs[0].document) : schema; + const baseSchema = additionalTypeDefs + ? extendSchema(schema, additionalTypeDefs[0].document) + : schema; const transformedSchema = mapSchema(baseSchema, { [MapperKind.COMPOSITE_FIELD]: ( fieldConfig: GraphQLFieldConfig, currentFieldName: string, - typeName: string + typeName: string, ) => { const fieldKey = `${typeName}.${currentFieldName}`; const newFieldConfig = this.replacementsMap.get(fieldKey); @@ -85,7 +95,7 @@ export default class ReplaceFieldTransform implements MeshTransform { const targetFieldConfig = selectObjectFields( baseSchema, newFieldConfig.type, - fieldName => fieldName === targetFieldName + fieldName => fieldName === targetFieldName, )[targetFieldName]; if (newFieldConfig.scope === 'config') { @@ -100,11 +110,15 @@ export default class ReplaceFieldTransform implements MeshTransform { fieldConfig.type = targetFieldConfig.type; // If renaming fields that don't have a custom resolver, we need to map response to original field name - if (newFieldConfig.name && !fieldConfig.resolve) fieldConfig.resolve = source => source[currentFieldName]; + if (newFieldConfig.name && !fieldConfig.resolve) + fieldConfig.resolve = source => source[currentFieldName]; if (newFieldConfig.scope === 'hoistValue') { // implement value hoisting by wrapping a default composer that hoists the value from resolver result - fieldConfig.resolve = defaultHoistFieldComposer(fieldConfig.resolve || defaultFieldResolver, targetFieldName); + fieldConfig.resolve = defaultHoistFieldComposer( + fieldConfig.resolve || defaultFieldResolver, + targetFieldName, + ); } // wrap user-defined composer to current field resolver or, if not preset, defaultFieldResolver diff --git a/packages/transforms/resolvers-composition/src/index.ts b/packages/transforms/resolvers-composition/src/index.ts index 2bff4fedffc25..79ce28a7bf12e 100644 --- a/packages/transforms/resolvers-composition/src/index.ts +++ b/packages/transforms/resolvers-composition/src/index.ts @@ -10,7 +10,11 @@ export default class ResolversCompositionTransform implements MeshTransform { private baseDir: string; private importFn: ImportFn; - constructor({ baseDir, config, importFn }: MeshTransformOptions) { + constructor({ + baseDir, + config, + importFn, + }: MeshTransformOptions) { this.noWrap = config.mode ? config.mode !== 'wrap' : false; // use config.mode value or default to false this.compositions = Array.isArray(config) ? config : config.compositions; this.baseDir = baseDir; @@ -29,7 +33,9 @@ export default class ResolversCompositionTransform implements MeshTransform { resolversComposition[resolver] = next => (...args) => - composerFn$.then(composerFn => (composerFn ? composerFn(next) : next)).then(next => next(...args)); + composerFn$ + .then(composerFn => (composerFn ? composerFn(next) : next)) + .then(next => next(...args)); } const resolvers = extractResolvers(schema); diff --git a/packages/transforms/type-merging/src/index.ts b/packages/transforms/type-merging/src/index.ts index d20b5980ecb5a..8785c465bfe2a 100644 --- a/packages/transforms/type-merging/src/index.ts +++ b/packages/transforms/type-merging/src/index.ts @@ -36,7 +36,8 @@ export default class TypeMerging implements MeshTransform { for (const mergedTypeConfig of this.config.types) { const type = schema.getType(mergedTypeConfig.typeName); type.extensions = type.extensions || {}; - const typeDirectiveExtensions: any = ((type.extensions.directives as any) = type.extensions.directives || {}); + const typeDirectiveExtensions: any = ((type.extensions.directives as any) = + type.extensions.directives || {}); if (mergedTypeConfig.key) { typeDirectiveExtensions.key = mergedTypeConfig.key; } @@ -45,7 +46,9 @@ export default class TypeMerging implements MeshTransform { } if (mergedTypeConfig.fields) { if (!('getFields' in type)) { - throw new Error('You cannot add field annotations to this type ' + mergedTypeConfig.typeName); + throw new Error( + 'You cannot add field annotations to this type ' + mergedTypeConfig.typeName, + ); } const fieldMap = type.getFields(); for (const fieldConfig of mergedTypeConfig.fields) { diff --git a/packages/urql/src/index.ts b/packages/urql/src/index.ts index e2cb036076697..20a71b0f0e5c8 100644 --- a/packages/urql/src/index.ts +++ b/packages/urql/src/index.ts @@ -14,7 +14,10 @@ import { ExecuteMeshFn, SubscribeMeshFn } from '@graphql-mesh/runtime'; import { isAsyncIterable } from '@graphql-tools/utils'; const ROOT_VALUE = {}; -const makeExecuteSource = (operation: Operation, options: MeshExchangeOptions): Source => { +const makeExecuteSource = ( + operation: Operation, + options: MeshExchangeOptions, +): Source => { const operationFn = operation.kind === 'subscription' ? options.subscribe : options.execute; const operationName = getOperationName(operation.query); return make(observer => { @@ -34,7 +37,9 @@ const makeExecuteSource = (operation: Operation, options: MeshExchangeOptions): function next({ done, value }: { done?: boolean; value: ExecutionResult }): any { if (value) { observer.next( - (prevResult = prevResult ? mergeResultPatch(prevResult, value) : makeResult(operation, value)) + (prevResult = prevResult + ? mergeResultPatch(prevResult, value) + : makeResult(operation, value)), ); } @@ -77,23 +82,27 @@ export const meshExchange = const executedOps$ = pipe( sharedOps$, filter((operation: Operation) => { - return operation.kind === 'query' || operation.kind === 'mutation' || operation.kind === 'subscription'; + return ( + operation.kind === 'query' || + operation.kind === 'mutation' || + operation.kind === 'subscription' + ); }), mergeMap((operation: Operation) => { const { key } = operation; const teardown$ = pipe( sharedOps$, - filter(op => op.kind === 'teardown' && op.key === key) + filter(op => op.kind === 'teardown' && op.key === key), ); return pipe(makeExecuteSource(operation, options), takeUntil(teardown$)); - }) + }), ); const forwardedOps$ = pipe( sharedOps$, filter(operation => operation.kind === 'teardown'), - forward + forward, ); return merge([executedOps$, forwardedOps$]); diff --git a/packages/urql/test/urql-exchange.test.ts b/packages/urql/test/urql-exchange.test.ts index 61617560a5f8d..00535feafe12b 100644 --- a/packages/urql/test/urql-exchange.test.ts +++ b/packages/urql/test/urql-exchange.test.ts @@ -25,7 +25,7 @@ describe('graphExchange', () => { query Greetings { greetings } - ` + `, ) .toPromise(); expect(result.error).toBeUndefined(); @@ -40,7 +40,7 @@ describe('graphExchange', () => { time } `), - toObservable + toObservable, ); const asyncIterable = observableToAsyncIterable>(observable); diff --git a/packages/utils/src/apply-transforms.ts b/packages/utils/src/apply-transforms.ts index df0f7c6337964..96f53ebfd9653 100644 --- a/packages/utils/src/apply-transforms.ts +++ b/packages/utils/src/apply-transforms.ts @@ -6,13 +6,15 @@ export function applySchemaTransforms( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, transformedSchema: GraphQLSchema, - transforms?: Transform[] + transforms?: Transform[], ) { if (transforms?.length) { return transforms.reduce( (schema, transform) => - 'transformSchema' in transform ? transform.transformSchema(schema, subschemaConfig) : schema, - originalWrappingSchema + 'transformSchema' in transform + ? transform.transformSchema(schema, subschemaConfig) + : schema, + originalWrappingSchema, ); } return originalWrappingSchema; @@ -21,7 +23,7 @@ export function applyRequestTransforms( originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record, - transforms: Transform[] + transforms: Transform[], ) { transformationContext.contextMap = transformationContext.contextMap || new WeakMap(); const contextMap: WeakMap> = transformationContext.contextMap; @@ -38,14 +40,14 @@ export function applyRequestTransforms( 'transformRequest' in transform ? transform.transformRequest(request, delegationContext, contextMap.get(transform)) : request, - originalRequest + originalRequest, ); } export function applyResultTransforms( originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: Record, - transforms: Transform[] + transforms: Transform[], ) { const contextMap: WeakMap> = transformationContext.contextMap; return transforms.reduce( @@ -53,6 +55,6 @@ export function applyResultTransforms( 'transformResult' in transform ? transform.transformResult(result, delegationContext, contextMap.get(transform)) : result, - originalResult + originalResult, ); } diff --git a/packages/utils/src/fs-operations.ts b/packages/utils/src/fs-operations.ts index 8afdc9a1f4aba..63af9b58b442d 100644 --- a/packages/utils/src/fs-operations.ts +++ b/packages/utils/src/fs-operations.ts @@ -20,7 +20,7 @@ export function writeJSON( path: string, data: T, replacer?: (this: any, key: string, value: any) => any, - space?: string | number + space?: string | number, ) { const stringified = JSON.stringify(data, replacer, space); return writeFile(path, stringified, 'utf-8'); @@ -54,7 +54,7 @@ export async function rmdirs(dir: string) { } else { return fs.promises.unlink(fullPath); } - }) + }), ); for (const result of results) { if (result.status === 'rejected' && result.reason.code !== 'ENOENT') { diff --git a/packages/utils/src/getHeadersObj.ts b/packages/utils/src/getHeadersObj.ts index 182cd4d367a5b..904dedf05daab 100644 --- a/packages/utils/src/getHeadersObj.ts +++ b/packages/utils/src/getHeadersObj.ts @@ -43,6 +43,6 @@ export function getHeadersObj(headers: Headers): Record { preventExtensions() { return true; }, - } + }, ); } diff --git a/packages/utils/src/load-from-module-export-expression.ts b/packages/utils/src/load-from-module-export-expression.ts index 45d8bd4892acc..6cb97b30bbf30 100644 --- a/packages/utils/src/load-from-module-export-expression.ts +++ b/packages/utils/src/load-from-module-export-expression.ts @@ -11,7 +11,7 @@ type LoadFromModuleExportExpressionOptions = { export async function loadFromModuleExportExpression( expression: T | string, - options: LoadFromModuleExportExpressionOptions + options: LoadFromModuleExportExpressionOptions, ): Promise { if (typeof expression !== 'string') { return Promise.resolve(expression); @@ -28,7 +28,9 @@ async function tryImport(modulePath: string, cwd: string, importFn: ImportFn) { return await importFn(modulePath); } catch { if (!path.isAbsolute(modulePath)) { - const absoluteModulePath = path.isAbsolute(modulePath) ? modulePath : path.join(cwd, modulePath); + const absoluteModulePath = path.isAbsolute(modulePath) + ? modulePath + : path.join(cwd, modulePath); return importFn(absoluteModulePath); } } diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 3bc314fc05235..7523ba5a8346b 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -32,7 +32,11 @@ export class DefaultLogger implements Logger { .map(arg => { if (typeof arg === 'string') { if (trim && arg.length > 100) { - return arg.slice(0, 100) + '...' + ''; + return ( + arg.slice(0, 100) + + '...' + + '' + ); } return arg; } else if (typeof arg === 'object' && arg?.stack != null) { diff --git a/packages/utils/src/pubsub.ts b/packages/utils/src/pubsub.ts index b8e5ae76e3d3c..acd45788bfd99 100644 --- a/packages/utils/src/pubsub.ts +++ b/packages/utils/src/pubsub.ts @@ -15,7 +15,9 @@ export class PubSub implements MeshPubSub { publish(triggerName: THook, detail: AllHooks[THook]): void { const eventNameListeners = this.eventNameListenersMap.get(triggerName); if (eventNameListeners) { - Promise.allSettled([...eventNameListeners].map(listener => listener(detail))).catch(e => console.error(e)); + Promise.allSettled([...eventNameListeners].map(listener => listener(detail))).catch(e => + console.error(e), + ); } } diff --git a/packages/utils/src/read-file-or-url.ts b/packages/utils/src/read-file-or-url.ts index 3c6d91f11f132..f37bbc2bb1b4f 100644 --- a/packages/utils/src/read-file-or-url.ts +++ b/packages/utils/src/read-file-or-url.ts @@ -16,7 +16,10 @@ export function isUrl(str: string): boolean { return /^https?:\/\//.test(str); } -export async function readFileOrUrl(filePathOrUrl: string, config: ReadFileOrUrlOptions): Promise { +export async function readFileOrUrl( + filePathOrUrl: string, + config: ReadFileOrUrlOptions, +): Promise { if (isUrl(filePathOrUrl)) { config.logger.debug(`Fetching ${filePathOrUrl} via HTTP`); return readUrl(filePathOrUrl, config); @@ -37,7 +40,9 @@ function getSchema(filepath: string, logger: Logger): Schema { }, construct(path: string) { const newCwd = pathModule.dirname(filepath); - const absoluteFilePath = pathModule.isAbsolute(path) ? path : pathModule.resolve(newCwd, path); + const absoluteFilePath = pathModule.isAbsolute(path) + ? path + : pathModule.resolve(newCwd, path); const content = fs.readFileSync(absoluteFilePath, 'utf8'); return loadYaml(absoluteFilePath, content, logger); }, @@ -49,7 +54,9 @@ function getSchema(filepath: string, logger: Logger): Schema { }, construct(path: string) { const newCwd = pathModule.dirname(filepath); - const absoluteDirPath = pathModule.isAbsolute(path) ? path : pathModule.resolve(newCwd, path); + const absoluteDirPath = pathModule.isAbsolute(path) + ? path + : pathModule.resolve(newCwd, path); const files = fs.readdirSync(absoluteDirPath); return files.map(filePath => { const absoluteFilePath = pathModule.resolve(absoluteDirPath, filePath); @@ -73,7 +80,7 @@ export function loadYaml(filepath: string, content: string, logger: Logger): any export async function readFile( fileExpression: string, - { allowUnknownExtensions, cwd, fallbackFormat, importFn, logger }: ReadFileOrUrlOptions + { allowUnknownExtensions, cwd, fallbackFormat, importFn, logger }: ReadFileOrUrlOptions, ): Promise { const [filePath] = fileExpression.split('#'); if (/js$/.test(filePath) || /ts$/.test(filePath)) { @@ -103,7 +110,7 @@ export async function readFile( } else if (!allowUnknownExtensions) { throw new Error( `Failed to parse JSON/YAML. Ensure file '${filePath}' has ` + - `the correct extension (i.e. '.json', '.yaml', or '.yml).` + `the correct extension (i.e. '.json', '.yaml', or '.yml).`, ); } return rawResult as unknown as T; @@ -116,7 +123,11 @@ export async function readUrl(path: string, config: ReadFileOrUrlOptions): Pr const contentType = response.headers?.get('content-type') || ''; const responseText = await response.text(); config?.logger?.debug(`${path} returned `, responseText); - if (/json$/.test(path) || contentType.startsWith('application/json') || fallbackFormat === 'json') { + if ( + /json$/.test(path) || + contentType.startsWith('application/json') || + fallbackFormat === 'json' + ) { return JSON.parse(responseText); } else if ( /yaml$/.test(path) || @@ -129,7 +140,7 @@ export async function readUrl(path: string, config: ReadFileOrUrlOptions): Pr } else if (!allowUnknownExtensions) { throw new Error( `Failed to parse JSON/YAML. Ensure URL '${path}' has ` + - `the correct extension (i.e. '.json', '.yaml', or '.yml) or mime type in the response headers.` + `the correct extension (i.e. '.json', '.yaml', or '.yml) or mime type in the response headers.`, ); } return responseText as any; diff --git a/packages/utils/src/resolve-additional-resolvers.ts b/packages/utils/src/resolve-additional-resolvers.ts index aed56c79ffd6c..a4bceb4d33ef3 100644 --- a/packages/utils/src/resolve-additional-resolvers.ts +++ b/packages/utils/src/resolve-additional-resolvers.ts @@ -46,7 +46,9 @@ function getTypeByPath(type: GraphQLType, path: string[]): GraphQLNamedType { function generateSelectionSetFactory( schema: GraphQLSchema, - additionalResolver: YamlConfig.AdditionalStitchingBatchResolverObject | YamlConfig.AdditionalStitchingResolverObject + additionalResolver: + | YamlConfig.AdditionalStitchingBatchResolverObject + | YamlConfig.AdditionalStitchingResolverObject, ) { if (additionalResolver.sourceSelectionSet) { return () => parseSelectionSet(additionalResolver.sourceSelectionSet); @@ -77,9 +79,9 @@ function generateSelectionSetFactory( !schema.isSubType(resultFieldType, abstractResultType) ) { throw new Error( - `${additionalResolver.sourceTypeName}.${additionalResolver.sourceFieldName}.${resultPath.join( - '.' - )} doesn't implement ${abstractResultTypeName}.}` + `${additionalResolver.sourceTypeName}.${ + additionalResolver.sourceFieldName + }.${resultPath.join('.')} doesn't implement ${abstractResultTypeName}.}`, ); } } @@ -92,7 +94,11 @@ function generateSelectionSetFactory( for (const pathElem of resultPathReversed) { // Ensure the path elem is not array index if (Number.isNaN(parseInt(pathElem))) { - if (isLastResult && abstractResultTypeName && abstractResultTypeName !== resultFieldType.name) { + if ( + isLastResult && + abstractResultTypeName && + abstractResultTypeName !== resultFieldType.name + ) { finalSelectionSet = { kind: Kind.SELECTION_SET, selections: [ @@ -148,7 +154,7 @@ export function resolveAdditionalResolversWithoutImport( | YamlConfig.AdditionalStitchingResolverObject | YamlConfig.AdditionalSubscriptionObject | YamlConfig.AdditionalStitchingBatchResolverObject, - pubsub: MeshPubSub + pubsub: MeshPubSub, ): IResolvers { const baseOptions: any = {}; if (additionalResolver.result) { @@ -165,9 +171,11 @@ export function resolveAdditionalResolversWithoutImport( return pubsub.asyncIterator(topic) as AsyncIterableIterator; }, (root, args, context, info) => { - // eslint-disable-next-line no-new-func - return additionalResolver.filterBy ? new Function(`return ${additionalResolver.filterBy}`)() : true; - } + return additionalResolver.filterBy + ? // eslint-disable-next-line no-new-func + new Function(`return ${additionalResolver.filterBy}`)() + : true; + }, ), resolve: (payload: any) => { if (baseOptions.valuesFromResults) { @@ -182,10 +190,14 @@ export function resolveAdditionalResolversWithoutImport( return { [additionalResolver.targetTypeName]: { [additionalResolver.targetFieldName]: { - selectionSet: additionalResolver.requiredSelectionSet || `{ ${additionalResolver.keyField} }`, + selectionSet: + additionalResolver.requiredSelectionSet || `{ ${additionalResolver.keyField} }`, resolve: async (root: any, args: any, context: any, info: any) => { if (!baseOptions.selectionSet) { - baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver); + baseOptions.selectionSet = generateSelectionSetFactory( + info.schema, + additionalResolver, + ); } const resolverData = { root, args, context, info, env: process.env }; const targetArgs: any = {}; @@ -193,7 +205,7 @@ export function resolveAdditionalResolversWithoutImport( lodashSet( targetArgs, argPath, - stringInterpolator.parse(additionalResolver.additionalArgs[argPath], resolverData) + stringInterpolator.parse(additionalResolver.additionalArgs[argPath], resolverData), ); } const options: any = { @@ -229,9 +241,9 @@ export function resolveAdditionalResolversWithoutImport( if (!context[additionalResolver.sourceName][additionalResolver.sourceTypeName]) { throw new Error( `No root type found named "${additionalResolver.sourceTypeName}" exists in the source ${additionalResolver.sourceName}\n` + - `It should be one of the following; ${Object.keys(context[additionalResolver.sourceName]).join( - ',' - )})}}` + `It should be one of the following; ${Object.keys( + context[additionalResolver.sourceName], + ).join(',')})}}`, ); } if ( @@ -240,12 +252,15 @@ export function resolveAdditionalResolversWithoutImport( ] ) { throw new Error( - `No field named "${additionalResolver.sourceFieldName}" exists in the type ${additionalResolver.sourceTypeName} from the source ${additionalResolver.sourceName}` + `No field named "${additionalResolver.sourceFieldName}" exists in the type ${additionalResolver.sourceTypeName} from the source ${additionalResolver.sourceName}`, ); } if (!baseOptions.selectionSet) { - baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver); + baseOptions.selectionSet = generateSelectionSetFactory( + info.schema, + additionalResolver, + ); } const resolverData = { root, args, context, info, env: process.env }; const targetArgs: any = {}; @@ -253,7 +268,10 @@ export function resolveAdditionalResolversWithoutImport( lodashSet( targetArgs, argPath, - stringInterpolator.parse(additionalResolver.sourceArgs[argPath].toString(), resolverData) + stringInterpolator.parse( + additionalResolver.sourceArgs[argPath].toString(), + resolverData, + ), ); } const options: any = { @@ -284,7 +302,7 @@ export function resolveAdditionalResolvers( | YamlConfig.AdditionalStitchingBatchResolverObject )[], importFn: ImportFn, - pubsub: MeshPubSub + pubsub: MeshPubSub, ): Promise { return Promise.all( (additionalResolvers || []).map(async additionalResolver => { @@ -314,13 +332,18 @@ export function resolveAdditionalResolvers( subscribe: withFilter( (root, args, context, info) => { const resolverData = { root, args, context, info, env: process.env }; - const topic = stringInterpolator.parse(additionalResolver.pubsubTopic, resolverData); + const topic = stringInterpolator.parse( + additionalResolver.pubsubTopic, + resolverData, + ); return pubsub.asyncIterator(topic) as AsyncIterableIterator; }, (root, args, context, info) => { - // eslint-disable-next-line no-new-func - return additionalResolver.filterBy ? new Function(`return ${additionalResolver.filterBy}`)() : true; - } + return additionalResolver.filterBy + ? // eslint-disable-next-line no-new-func + new Function(`return ${additionalResolver.filterBy}`)() + : true; + }, ), resolve: (payload: any) => { if (baseOptions.valuesFromResults) { @@ -335,10 +358,14 @@ export function resolveAdditionalResolvers( return { [additionalResolver.targetTypeName]: { [additionalResolver.targetFieldName]: { - selectionSet: additionalResolver.requiredSelectionSet || `{ ${additionalResolver.keyField} }`, + selectionSet: + additionalResolver.requiredSelectionSet || `{ ${additionalResolver.keyField} }`, resolve: async (root: any, args: any, context: any, info: any) => { if (!baseOptions.selectionSet) { - baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver); + baseOptions.selectionSet = generateSelectionSetFactory( + info.schema, + additionalResolver, + ); } const resolverData = { root, args, context, info, env: process.env }; const targetArgs: any = {}; @@ -346,7 +373,10 @@ export function resolveAdditionalResolvers( lodashSet( targetArgs, argPath, - stringInterpolator.parse(additionalResolver.additionalArgs[argPath], resolverData) + stringInterpolator.parse( + additionalResolver.additionalArgs[argPath], + resolverData, + ), ); } const options: any = { @@ -382,9 +412,9 @@ export function resolveAdditionalResolvers( if (!context[additionalResolver.sourceName][additionalResolver.sourceTypeName]) { throw new Error( `No root type found named "${additionalResolver.sourceTypeName}" exists in the source ${additionalResolver.sourceName}\n` + - `It should be one of the following; ${Object.keys(context[additionalResolver.sourceName]).join( - ',' - )})}}` + `It should be one of the following; ${Object.keys( + context[additionalResolver.sourceName], + ).join(',')})}}`, ); } if ( @@ -393,12 +423,15 @@ export function resolveAdditionalResolvers( ] ) { throw new Error( - `No field named "${additionalResolver.sourceFieldName}" exists in the type ${additionalResolver.sourceTypeName} from the source ${additionalResolver.sourceName}` + `No field named "${additionalResolver.sourceFieldName}" exists in the type ${additionalResolver.sourceTypeName} from the source ${additionalResolver.sourceName}`, ); } if (!baseOptions.selectionSet) { - baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver); + baseOptions.selectionSet = generateSelectionSetFactory( + info.schema, + additionalResolver, + ); } const resolverData = { root, args, context, info, env: process.env }; const targetArgs: any = {}; @@ -406,7 +439,10 @@ export function resolveAdditionalResolvers( lodashSet( targetArgs, argPath, - stringInterpolator.parse(additionalResolver.sourceArgs[argPath].toString(), resolverData) + stringInterpolator.parse( + additionalResolver.sourceArgs[argPath].toString(), + resolverData, + ), ); } const options: any = { @@ -427,6 +463,6 @@ export function resolveAdditionalResolvers( return additionalResolver; } } - }) + }), ); } diff --git a/packages/utils/src/with-cancel.ts b/packages/utils/src/with-cancel.ts index fb341704bd157..b2b4c08ef9d24 100644 --- a/packages/utils/src/with-cancel.ts +++ b/packages/utils/src/with-cancel.ts @@ -1,4 +1,7 @@ -export function withCancel(asyncIterable: AsyncIterable, onCancel: () => void): AsyncIterable { +export function withCancel( + asyncIterable: AsyncIterable, + onCancel: () => void, +): AsyncIterable { return new Proxy(asyncIterable, { get(asyncIterable, prop) { if (prop === Symbol.asyncIterator) { diff --git a/packages/utils/src/with-filter.ts b/packages/utils/src/with-filter.ts index 2bfcfea553d9e..8fe37ae5c52a6 100644 --- a/packages/utils/src/with-filter.ts +++ b/packages/utils/src/with-filter.ts @@ -2,13 +2,13 @@ export type FilterFn = ( rootValue?: TSource, args?: TArgs, context?: TContext, - info?: any + info?: any, ) => boolean | Promise; export type ResolverFn = ( rootValue?: TSource, args?: TArgs, context?: TContext, - info?: any + info?: any, ) => AsyncIterator | Promise>; interface IterallAsyncIterator extends AsyncIterableIterator { @@ -17,14 +17,19 @@ interface IterallAsyncIterator extends AsyncIterableIterator { export type WithFilter = ( asyncIteratorFn: ResolverFn, - filterFn: FilterFn + filterFn: FilterFn, ) => ResolverFn; export function withFilter( asyncIteratorFn: ResolverFn, - filterFn: FilterFn + filterFn: FilterFn, ): ResolverFn { - return async (rootValue: TSource, args: TArgs, context: TContext, info: any): Promise> => { + return async ( + rootValue: TSource, + args: TArgs, + context: TContext, + info: any, + ): Promise> => { const asyncIterator = await asyncIteratorFn(rootValue, args, context, info); const getNextPromise = () => { diff --git a/scripts/fix-bin.js b/scripts/fix-bin.js index d2c81cfb2d3bf..2a6300834900c 100644 --- a/scripts/fix-bin.js +++ b/scripts/fix-bin.js @@ -32,7 +32,7 @@ for (const path of dir) { @SET PATHEXT=%PATHEXT:;.JS;=;% node "${absoluteGraphqlMeshBinPath}" %* ) - ` + `, ); chmodSync(targetCmdPath, '755'); } diff --git a/website/README.md b/website/README.md index 95d70079d1613..3e9d1fb9d7f8c 100644 --- a/website/README.md +++ b/website/README.md @@ -6,11 +6,13 @@ yarn --ignore-optional ``` -`--ignore-engines` is required if you are using node versions greater than `14.0` since the `@apollo/subgraph` package being used is incompatible with them. +`--ignore-engines` is required if you are using node versions greater than `14.0` since the +`@apollo/subgraph` package being used is incompatible with them. ## Pre-requisites -In order to run the project successfully in your system, you would require `python 2.x` to be installed (used by `node-pre-gyp` to build some dependencies) +In order to run the project successfully in your system, you would require `python 2.x` to be +installed (used by `node-pre-gyp` to build some dependencies) You can install it in Linux based distributions using `sudo apt update && sudo apt install python` @@ -22,7 +24,8 @@ More about this [here](https://github.com/Urigo/graphql-mesh/issues/1543) yarn start ``` -This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. +This command starts a local development server and open up a browser window. Most changes are +reflected live without having to restart the server. ### Build @@ -30,7 +33,8 @@ This command starts a local development server and open up a browser window. Mos yarn build ``` -This command generates static content into the `build` directory and can be served using any static contents hosting service. +This command generates static content into the `build` directory and can be served using any static +contents hosting service. ### Deployment @@ -38,4 +42,5 @@ This command generates static content into the `build` directory and can be serv GIT_USER= yarn < YOUR_GITHUB_USERNAME > USE_SSH=true deploy ``` -If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. +If you are using GitHub pages for hosting, this command is a convenient way to build the website and +push to the `gh-pages` branch. diff --git a/website/next.config.mjs b/website/next.config.mjs index fe966e3ec5337..e52aa32aa3262 100644 --- a/website/next.config.mjs +++ b/website/next.config.mjs @@ -8,14 +8,16 @@ export default withGuildDocs({ redirects: () => Object.entries({ '/api': '/docs', - '/api/enums/store_src.PredefinedProxyOptionsName': '/docs/getting-started/customize-mesh-server', + '/api/enums/store_src.PredefinedProxyOptionsName': + '/docs/getting-started/customize-mesh-server', '/docs/api/classes/:path*': '/docs', '/docs/api/interfaces/:path*': '/docs', '/docs/api/modules/:path*': '/docs', '/docs/cache': '/docs/cache/cache-introduction', '/docs/getting-started': '/docs/getting-started/overview', '/docs/getting-started/basic-example': '/docs/getting-started/your-first-mesh-gateway', - '/docs/getting-started/combine-many-sources': '/docs/getting-started/combine-multiple-sources', + '/docs/getting-started/combine-many-sources': + '/docs/getting-started/combine-multiple-sources', '/docs/getting-started/introduction': '/docs/getting-started/overview', '/docs/getting-started/mesh-transforms': '/docs/transforms/transforms-introduction', '/docs/getting-started/multiple-apis': '/docs/getting-started/combine-multiple-sources', diff --git a/website/src/pages/docs/cache/cfwKv.mdx b/website/src/pages/docs/cache/cfwKv.mdx index caa630b69979c..b79293f4bc71f 100644 --- a/website/src/pages/docs/cache/cfwKv.mdx +++ b/website/src/pages/docs/cache/cfwKv.mdx @@ -2,7 +2,8 @@ import { PackageCmd } from '@theguild/components' # CloudFlare Workers KV -If you are using Mesh on Cloudflare Workers, you can use [_KV_](https://developers.cloudflare.com/workers/runtime-apis/kv/) as a storage. +If you are using Mesh on Cloudflare Workers, you can use +[_KV_](https://developers.cloudflare.com/workers/runtime-apis/kv/) as a storage. To get started with this caching strategy, install it: @@ -16,7 +17,8 @@ cache: namespace: MY_MESH_CACHE ``` -> If you need help with deploying GraphQL Mesh on CloudFlare Workers, [see our deployment recipes.](/docs/getting-started/deploy-mesh-gateway#deploy-mesh-on-cloudflare-workers) +> If you need help with deploying GraphQL Mesh on CloudFlare Workers, +> [see our deployment recipes.](/docs/getting-started/deploy-mesh-gateway#deploy-mesh-on-cloudflare-workers) ## Config API Reference diff --git a/website/src/pages/docs/cache/localforage.mdx b/website/src/pages/docs/cache/localforage.mdx index 46ae9c80d47b4..1734fa92dd889 100644 --- a/website/src/pages/docs/cache/localforage.mdx +++ b/website/src/pages/docs/cache/localforage.mdx @@ -2,9 +2,11 @@ import { PackageCmd } from '@theguild/components' # LocalForage -LocalForage is a library that improves the existing storage mechanism in the browser by using `IndexedDB`, `WebSQL` and `localStorage`, [see more](https://github.com/localForage/localForage). +LocalForage is a library that improves the existing storage mechanism in the browser by using +`IndexedDB`, `WebSQL` and `localStorage`, [see more](https://github.com/localForage/localForage). -This caching mechanism is only recommended for the browser environments, [see the example](https://github.com/Urigo/graphql-mesh/blob/master/examples/openapi-react-weatherbit/src/mesh/useMeshSdk.ts#L10). +This caching mechanism is only recommended for the browser environments, +[see the example](https://github.com/Urigo/graphql-mesh/blob/master/examples/openapi-react-weatherbit/src/mesh/useMeshSdk.ts#L10). To get started with this caching strategy, install it: diff --git a/website/src/pages/docs/cli-commands.mdx b/website/src/pages/docs/cli-commands.mdx index 823116359ea79..b544c1e1b6c34 100644 --- a/website/src/pages/docs/cli-commands.mdx +++ b/website/src/pages/docs/cli-commands.mdx @@ -52,27 +52,29 @@ yarn graphql-mesh dev --port 4002 Builds artifacts required to use `mesh start` for a gateway (production) server or SDK. -Can have `--throwOnInvalidConfig=true` to make CLI throw in case of an invalid configuration. By default, CLI gives a warning and continues. +Can have `--throwOnInvalidConfig=true` to make CLI throw in case of an invalid configuration. By +default, CLI gives a warning and continues. ### `mesh validate` -Validate the built artifacts (`mesh build`) required to use `mesh start` for a gateway (production) server. -The validation will check the following: +Validate the built artifacts (`mesh build`) required to use `mesh start` for a gateway (production) +server. The validation will check the following: - presence of the `.mesh/` folder -- validation of the mesh configuration (see [`packages/types/src/config-schema.json`](https://github.com/Urigo/graphql-mesh/blob/master/packages/types/src/config-schema.json)) +- validation of the mesh configuration (see + [`packages/types/src/config-schema.json`](https://github.com/Urigo/graphql-mesh/blob/master/packages/types/src/config-schema.json)) - configured sources are valid More information about this on the [Build Artifacts](/docs/recipes/build-mesh-artifacts) page. ### `mesh start` -Serves a GraphQL server using the built artifacts. -`mesh start` compared to `mesh dev` does not rely on the sources to build the schema. -Instead, it uses the built artifacts. -Therefore, `mesh start` is recommended to start a mesh server in production. +Serves a GraphQL server using the built artifacts. `mesh start` compared to `mesh dev` does not rely +on the sources to build the schema. Instead, it uses the built artifacts. Therefore, `mesh start` is +recommended to start a mesh server in production. -More information about `mesh start` on the [Build Artifacts](/docs/recipes/build-mesh-artifacts) page. +More information about `mesh start` on the [Build Artifacts](/docs/recipes/build-mesh-artifacts) +page. Can have an optional `--port` argument. @@ -90,8 +92,8 @@ yarn graphql-mesh start --port 4002 ### `mesh serve-source` -`serve-source` helps with quickly assessing that Mesh properly ingests a source. -Given a source name as the only argument, Mesh will serve a GraphQL API only exposing the given source. +`serve-source` helps with quickly assessing that Mesh properly ingests a source. Given a source name +as the only argument, Mesh will serve a GraphQL API only exposing the given source. This command is handy to debug a source. diff --git a/website/src/pages/docs/config-reference.mdx b/website/src/pages/docs/config-reference.mdx index 1460e142c1f11..4f4dcbdb57c89 100644 --- a/website/src/pages/docs/config-reference.mdx +++ b/website/src/pages/docs/config-reference.mdx @@ -10,7 +10,8 @@ Commonly, configuration file is named `.meshrc.yaml` and placed in the root of y Mandatory field. Defines the list of your external data sources for your API mesh. -Acceptable external sources, with detailed specific configurations, available in the [Handlers](/docs/handlers) section. +Acceptable external sources, with detailed specific configurations, available in the +[Handlers](/docs/handlers) section. ## `transforms` @@ -20,11 +21,13 @@ Available transforms available in the [Transforms](/docs/transforms) section. ## `additionalTypeDefs` -Additional type definitions, or type definitions overrides you wish to add to the schema mesh. [Read more](/docs/getting-started/combine-multiple-sources#setup-hierarchy-with-nested-queries) +Additional type definitions, or type definitions overrides you wish to add to the schema mesh. +[Read more](/docs/getting-started/combine-multiple-sources#setup-hierarchy-with-nested-queries) ## `additionalResolvers` -Additional resolvers, or resolvers overrides you wish to add to the schema mesh. [Read more](/docs/guides/extending-unified-schema#programmatic-additionalresolvers) +Additional resolvers, or resolvers overrides you wish to add to the schema mesh. +[Read more](/docs/guides/extending-unified-schema#programmatic-additionalresolvers) ## `plugins` @@ -32,7 +35,8 @@ Extend the mesh schema's capabilities with additional [plugins](/docs/plugins/pl ## `additionalEnvelopPlugins` -Additional plugins from [Envelop Ecosystem](https://www.envelop.dev/plugins). [Read more](/docs/plugins/plugins-introduction#additional-plugins) +Additional plugins from [Envelop Ecosystem](https://www.envelop.dev/plugins). +[Read more](/docs/plugins/plugins-introduction#additional-plugins) ## `cache` @@ -40,7 +44,8 @@ Configure the [caching strategy](/docs/cache) for your unified schema. ## `serve` -Mesh as a server configuration. [Read more](/docs/getting-started/customize-mesh-server#provide-a-standalone-server-implementation) +Mesh as a server configuration. +[Read more](/docs/getting-started/customize-mesh-server#provide-a-standalone-server-implementation) ### Serve config reference: @@ -60,14 +65,14 @@ import SDK from '../../generated-markdown/SDKConfig.generated.md' ## `documents` -Provide a query or queries for GraphQL Playground, validation and SDK Generation. -The value can be the file path, glob expression for the file paths or the SDL. -`.js`, `.jsx`, `.graphql`, `.gql`, `.ts` and `.tsx` files are supported. -[Read more](/docs/guides/mesh-sdk#getting-started) +Provide a query or queries for GraphQL Playground, validation and SDK Generation. The value can be +the file path, glob expression for the file paths or the SDL. `.js`, `.jsx`, `.graphql`, `.gql`, +`.ts` and `.tsx` files are supported. [Read more](/docs/guides/mesh-sdk#getting-started) ## `customFetch` -Path to a custom W3 Compatible Fetch Implementation. [Example](/docs/handlers/openapi#accepting-one-of-the-cookies-header-or-context-value) +Path to a custom W3 Compatible Fetch Implementation. +[Example](/docs/handlers/openapi#accepting-one-of-the-cookies-header-or-context-value) ## `logger` @@ -87,8 +92,10 @@ Allow connections to an SSL endpoint without certificates (type: `Boolean`). ## `codegen` -GraphQL Code Generator Configuration. [Read more](/docs/guides/graphql-code-generator#customizing-the-graphql-code-generator-configuration +GraphQL Code Generator Configuration. [Read +more](/docs/guides/graphql-code-generator#customizing-the-graphql-code-generator-configuration ## `require` -Loads specific require extensions before running the GraphQL Code Generator and reading the configuration. +Loads specific require extensions before running the GraphQL Code Generator and reading the +configuration. diff --git a/website/src/pages/docs/getting-started/combine-multiple-sources.mdx b/website/src/pages/docs/getting-started/combine-multiple-sources.mdx index 876433f1043c8..7bb03180c93e2 100644 --- a/website/src/pages/docs/getting-started/combine-multiple-sources.mdx +++ b/website/src/pages/docs/getting-started/combine-multiple-sources.mdx @@ -2,7 +2,9 @@ import { Callout } from '@theguild/components' # How to: Combine multiple Sources -All the documentation tutorials and guides rely on the "Books", "Authors" and "Stores" example APIs, available in a dedicated repository: [`graphql-mesh-docs-first-gateway`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway): +All the documentation tutorials and guides rely on the "Books", "Authors" and "Stores" example APIs, +available in a dedicated repository: +[`graphql-mesh-docs-first-gateway`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway): - Books API (REST API) - `GET /books` @@ -15,9 +17,12 @@ All the documentation tutorials and guides rely on the "Books", "Authors" and "S - `stores` Query - `bookSells(storeId: ID!)` Query -The getting started ["Your first Gateway with Mesh"](../../docs/getting-started/your-first-mesh-gateway) introduced the configuration of the Books API Source. +The getting started +["Your first Gateway with Mesh"](../../docs/getting-started/your-first-mesh-gateway) introduced the +configuration of the Books API Source. -This guide will show how to add 2 new sources (Authors and Stores) to achieve the following Gateway setup: +This guide will show how to add 2 new sources (Authors and Stores) to achieve the following Gateway +setup: ```mermaid graph TD; @@ -40,7 +45,8 @@ Z --> F; Z --> G; ``` -We will go further than just add new Sources by shaping the Unified Schema to accept the following query: +We will go further than just add new Sources by shaping the Unified Schema to accept the following +query: ```graphql query bestSellersByStore { @@ -64,9 +70,12 @@ query bestSellersByStore { ## 1. Add the "Authors" Source -The "Authors" Source is a gRPC API: [`authors-service`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/authors-service). +The "Authors" Source is a gRPC API: +[`authors-service`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/authors-service). -We will use the `grpc` Handler with the `@graphql-mesh/grpc` package and configure in our [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) it as follows: +We will use the `grpc` Handler with the `@graphql-mesh/grpc` package and configure in our +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) +it as follows: ```yaml filename=".meshrc.yaml" sources: @@ -82,15 +91,20 @@ sources: source: ../authors-service/proto/authors/v1/authors_service.proto ``` -Similar to the "Books" API configuration, we just need to provide the path to the service definition file (here, a Proto file) and the base URL. +Similar to the "Books" API configuration, we just need to provide the path to the service definition +file (here, a Proto file) and the base URL. -We will "clean" the corresponding "Authors" GraphQL Schema later, in the 3rd step, "_Shaping the Unified Schema_". +We will "clean" the corresponding "Authors" GraphQL Schema later, in the 3rd step, "_Shaping the +Unified Schema_". ## 2. Add the "Stores" Source -The "Stores" Source is a GraphQL API: [`stores-service`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/stores-service). +The "Stores" Source is a GraphQL API: +[`stores-service`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/stores-service). -We will use the `graphql` Handler with the `@graphql-mesh/graphql` package and configure it in our [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) it as follows: +We will use the `graphql` Handler with the `@graphql-mesh/graphql` package and configure it in our +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) +it as follows: ```yaml filename=".meshrc.yaml" sources: @@ -110,11 +124,13 @@ sources: endpoint: http://0.0.0.0:3004/graphql ``` -Since the "Stores" is a GraphQL API, Mesh can leverage introspection to get its schema with just the `endpoint` URL. +Since the "Stores" is a GraphQL API, Mesh can leverage introspection to get its schema with just the +`endpoint` URL. ## 3. Shaping the Unified Schema -The following Mesh Gateway configuration [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): +The following Mesh Gateway configuration +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -134,7 +150,8 @@ sources: endpoint: http://0.0.0.0:3004/graphql ``` -Will gives us a "raw" GraphQL schema design that contains unwanted GraphQL Queries, badly named types, and a lack of hierarchy: +Will gives us a "raw" GraphQL schema design that contains unwanted GraphQL Queries, badly named +types, and a lack of hierarchy: [`.mesh/schema.graphql`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.mesh/schema.graphql) @@ -146,7 +163,9 @@ type Query { categories(limit: Int): [Category] authors_v1_AuthorsService_GetAuthor(input: authors_v1_GetAuthorRequest_Input): authors_v1_Author - authors_v1_AuthorsService_ListAuthors(input: authors_v1_ListAuthorsRequest_Input): authors_v1_ListAuthorsResponse + authors_v1_AuthorsService_ListAuthors( + input: authors_v1_ListAuthorsRequest_Input + ): authors_v1_ListAuthorsResponse authors_v1_AuthorsService_connectivityState(tryToConnect: Boolean): ConnectivityState stores: [Store!]! bookSells(storeId: ID!): [Sells!]! @@ -183,20 +202,27 @@ We will need to configure multiple transforms: - Remove the unnecessary root queries: `author`, `book`, `categories`, `bookSells` - Setup some hierarchy between the queries -**If you have never configured Transforms before**, we advise you to go through the ["Your first Gateway with Mesh"](/docs/getting-started/your-first-mesh-gateway) tutorial first. +**If you have never configured Transforms before**, we advise you to go through the +["Your first Gateway with Mesh"](/docs/getting-started/your-first-mesh-gateway) tutorial first. ### Remove unnecessary Root queries -Also covered in the ["Your first Gateway with Mesh"](/docs/getting-started/your-first-mesh-gateway) tutorial, removing queries from the Unified Schema is achieved with the `@graphql-mesh/transform-filter-schema` transform. +Also covered in the ["Your first Gateway with Mesh"](/docs/getting-started/your-first-mesh-gateway) +tutorial, removing queries from the Unified Schema is achieved with the +`@graphql-mesh/transform-filter-schema` transform. To build a clean Unified Schema, we need to remove unnecessary Queries such as: -- `Query.authors_v1_AuthorsService_GetAuthor` and `Query.authors_v1_AuthorsService_ListAuthors` from the "Authors" Source -- the `Query.!authors_v1_AuthorsService_connectivityState` is automatically generated by the `grpc` handler of the "Authors" Source +- `Query.authors_v1_AuthorsService_GetAuthor` and `Query.authors_v1_AuthorsService_ListAuthors` from + the "Authors" Source +- the `Query.!authors_v1_AuthorsService_connectivityState` is automatically generated by the `grpc` + handler of the "Authors" Source - `Query.book` from the "Books" Source - `Query.bookSells` from the "Stores" Source -Our updated [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) is the following: +Our updated +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) +is the following: ```yaml filename=".meshrc.yaml" sources: @@ -223,11 +249,14 @@ transforms: `filterSchema` takes a `filters` option that accepts an array of filter rules. -By adding `Query.!authors_v1_AuthorsService_connectivityState`, we instruct Mesh to remove the `authors_v1_AuthorsService_connectivityState(...)` Query. +By adding `Query.!authors_v1_AuthorsService_connectivityState`, we instruct Mesh to remove the +`authors_v1_AuthorsService_connectivityState(...)` Query. -You can notice that the `filterSchema` allows using a bash-like syntax to avoid repetitive configuration with the `{..., ...}` syntax. +You can notice that the `filterSchema` allows using a bash-like syntax to avoid repetitive +configuration with the `{..., ...}` syntax. -Another way to achieve the same result would be to instruct Mesh only to keep the `Query.stores` root query as follows: +Another way to achieve the same result would be to instruct Mesh only to keep the `Query.stores` +root query as follows: ```yaml filename=".meshrc.yaml" sources: @@ -238,7 +267,8 @@ transforms: - Query.stores ``` -More information on the `filterSchema` _Transform_ on [its dedicated documentation page](/docs/transforms/filter-schema). +More information on the `filterSchema` _Transform_ on +[its dedicated documentation page](/docs/transforms/filter-schema). ### Setup hierarchy with nested queries @@ -270,19 +300,26 @@ We need to update the schema to add the following fields: - `Sells.book: Book`: to get the book of a given store selling record - `Book.author: authors_v1_Author`: to get the author of a book -To achieve this, we will use the `additionalResolvers` and `additionalTypeDefs` configuration from Mesh's `.meshrc.yaml` API. +To achieve this, we will use the `additionalResolvers` and `additionalTypeDefs` configuration from +Mesh's `.meshrc.yaml` API. **Update our Schema with new fields** -Using `additionalTypeDefs` configuration parameter allows writing GraphQL that will be merged with the Unified Schema definition, allowing us to [extend existing types](https://spec.graphql.org/June2018/#sec-Object-Extensions) and queries. +Using `additionalTypeDefs` configuration parameter allows writing GraphQL that will be merged with +the Unified Schema definition, allowing us to +[extend existing types](https://spec.graphql.org/June2018/#sec-Object-Extensions) and queries. -Let's say we want to add the `Book.author` field. -We first need to know what is the type of Author. +Let's say we want to add the `Book.author` field. We first need to know what is the type of Author. -Since the handlers generate most types, it might be hard to guess their correct spelling (e.g. `authors_v1_Author`). -A quick way to build an `additionalTypeDefs` is to refer to the generated GraphQL Schema file of each Source that can be found in the [`.mesh/sources`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.mesh/sources/) folder. +Since the handlers generate most types, it might be hard to guess their correct spelling (e.g. +`authors_v1_Author`). A quick way to build an `additionalTypeDefs` is to refer to the generated +GraphQL Schema file of each Source that can be found in the +[`.mesh/sources`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.mesh/sources/) +folder. -For example, the GraphQL Schema of the "Authors" Source can be found at [`.mesh/sources/Authors/schema.graphql`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.mesh/sources/Authors/schema.graphql) file: +For example, the GraphQL Schema of the "Authors" Source can be found at +[`.mesh/sources/Authors/schema.graphql`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.mesh/sources/Authors/schema.graphql) +file: ```graphql filename="schema.graphql" schema { @@ -291,7 +328,9 @@ schema { type Query { authors_v1_AuthorsService_GetAuthor(input: authors_v1_GetAuthorRequest_Input): authors_v1_Author - authors_v1_AuthorsService_ListAuthors(input: authors_v1_ListAuthorsRequest_Input): authors_v1_ListAuthorsResponse + authors_v1_AuthorsService_ListAuthors( + input: authors_v1_ListAuthorsRequest_Input + ): authors_v1_ListAuthorsResponse authors_v1_AuthorsService_connectivityState(tryToConnect: Boolean): ConnectivityState } @@ -323,7 +362,9 @@ enum ConnectivityState { Note: Try running the Mesh Gateway first if the `.mesh` folder does not exist. -Here we find that an author is described with the `authors_v1_Author` GraphQL type, which allows us to add the following `additionalTypeDefs` configuration [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): +Here we find that an author is described with the `authors_v1_Author` GraphQL type, which allows us +to add the following `additionalTypeDefs` configuration +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -338,7 +379,9 @@ additionalTypeDefs: | } ``` -By applying the same process for `Store.bookSells` and `Sells.book`, we get the following final `additionalTypeDefs` configuration [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): +By applying the same process for `Store.bookSells` and `Sells.book`, we get the following final +`additionalTypeDefs` configuration +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -359,15 +402,20 @@ additionalTypeDefs: | } ``` -Our Unified Schema definition is now updated; we need to point to Mesh on how to resolve our new field's data. +Our Unified Schema definition is now updated; we need to point to Mesh on how to resolve our new +field's data. **Add resolvers for our new fields** -Now, let's describe **how Mesh should resolve the data on the newly added type definitions** by providing `additionalResolvers`. +Now, let's describe **how Mesh should resolve the data on the newly added type definitions** by +providing `additionalResolvers`. Again, let's start with the `Book.author` field. -We need the `Book.author` field to call the `Query.authors_v1_AuthorsService_GetAuthor(input: authors_v1_GetAuthorRequest_Input): authors_v1_Author` Query by providing the following `additionalResolvers` configuration [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): +We need the `Book.author` field to call the +`Query.authors_v1_AuthorsService_GetAuthor(input: authors_v1_GetAuthorRequest_Input): authors_v1_Author` +Query by providing the following `additionalResolvers` configuration +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -399,14 +447,20 @@ additionalTypeDefs: | Each `additionalResolvers` value is based on 2 main concepts: - the **target** (`targetTypeName`, `targetFieldName`): describes the queried field -- the **source** (`sourceName`, `sourceTypeName`, `sourceFieldName`, `sourceArgs`): describes where is resolved the data for the target field +- the **source** (`sourceName`, `sourceTypeName`, `sourceFieldName`, `sourceArgs`): describes where + is resolved the data for the target field -Here are configured **target**, and **Source** explained that Querying `Book.author` will resolve the data by calling the `Query.authors_v1_AuthorsService_GetAuthor` from the "Authors" source. +Here are configured **target**, and **Source** explained that Querying `Book.author` will resolve +the data by calling the `Query.authors_v1_AuthorsService_GetAuthor` from the "Authors" source. -The `requiredSelectionSet` and `sourceArgs` ensure that the required arguments are provided (`requiredSelectionSet`) and adequately mapped to the Source (`sourceArgs`). -`requiredSelectionSet` ensures that the `Book.author` selection will contains `authorId`, so it can be forward to `Query.authors_v1_AuthorsService_GetAuthor` as the `input.id` argument. +The `requiredSelectionSet` and `sourceArgs` ensure that the required arguments are provided +(`requiredSelectionSet`) and adequately mapped to the Source (`sourceArgs`). `requiredSelectionSet` +ensures that the `Book.author` selection will contains `authorId`, so it can be forward to +`Query.authors_v1_AuthorsService_GetAuthor` as the `input.id` argument. -Applying the same logic to `Stores.bookSells` and `Sells.book` gives us a complete [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) configuration. +Applying the same logic to `Stores.bookSells` and `Sells.book` gives us a complete +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/multiple-sources/.meshrc.yaml) +configuration. Our Gateway is now complete; you can start it (along with the Services APIs) by running: diff --git a/website/src/pages/docs/getting-started/comparison.mdx b/website/src/pages/docs/getting-started/comparison.mdx index 9158b5bd2a9c6..4de7bba3ab43d 100644 --- a/website/src/pages/docs/getting-started/comparison.mdx +++ b/website/src/pages/docs/getting-started/comparison.mdx @@ -9,8 +9,10 @@ As stated in the introduction page, many approaches exist to build a GraphQL Gat The comparison table below evaluates all those solutions based on 3 criteria: -1. How is the solution helping you build Unified Schema Gateway in a **productive and maintainable way**? -2. Is the solution provides all the features to build a **well-designed Unified GraphQL Schema**? (comprehensive, simplified abstraction of a set of sub-services) +1. How is the solution helping you build Unified Schema Gateway in a **productive and maintainable + way**? +2. Is the solution provides all the features to build a **well-designed Unified GraphQL Schema**? + (comprehensive, simplified abstraction of a set of sub-services) 3. Which **sub services types** the solution supports? | | Productivity / Maintainability | Unified Schema design | Sub-services support | diff --git a/website/src/pages/docs/getting-started/customize-mesh-server.mdx b/website/src/pages/docs/getting-started/customize-mesh-server.mdx index 0848c27ecf4f7..744839d6f1ef6 100644 --- a/website/src/pages/docs/getting-started/customize-mesh-server.mdx +++ b/website/src/pages/docs/getting-started/customize-mesh-server.mdx @@ -2,7 +2,9 @@ import { Callout } from '@theguild/components' # How to: Customize the Mesh server -GraphQL Mesh provides a **reliable and production-ready server implementation** built with [GraphQL Yoga](https://graphql-yoga.com) and [Envelop](https://envelop.dev) with, out of the box support for: +GraphQL Mesh provides a **reliable and production-ready server implementation** built with +[GraphQL Yoga](https://graphql-yoga.com) and [Envelop](https://envelop.dev) with, out of the box +support for: - Persisted queries - Live queries @@ -38,14 +40,19 @@ A33 & A34 --> A35 Customizing your GraphQL Mesh Gateway server can be achieved in 2 ways: -- **Configure and provide Envelop plugins**: to add behaviors such as caching, authentication, tracing to your Gateway -- **Provide a standalone server implementation**: to completely replace the server used by the Gateway +- **Configure and provide Envelop plugins**: to add behaviors such as caching, authentication, + tracing to your Gateway +- **Provide a standalone server implementation**: to completely replace the server used by the + Gateway ## Configure and provide plugins -Aided by the capabilities of [Envelop](https://envelop.dev), you can easily add plugins that helps with security and authentication, advanced caching, error handling, monitoring, logging and much more. +Aided by the capabilities of [Envelop](https://envelop.dev), you can easily add plugins that helps +with security and authentication, advanced caching, error handling, monitoring, logging and much +more. -For full list of available plugins, please refer to the [plugins section](/docs/plugins/plugins-introduction). +For full list of available plugins, please refer to the +[plugins section](/docs/plugins/plugins-introduction). ## Configuration: `serve` reference @@ -55,4 +62,5 @@ import API from '../../../generated-markdown/ServeConfig.generated.md' ## Provide a standalone server implementation -Creation of own server with Mesh Gateway and its deployment is described in [Deploy a Mesh Gateway](/docs/getting-started/deploy-mesh-gateway) +Creation of own server with Mesh Gateway and its deployment is described in +[Deploy a Mesh Gateway](/docs/getting-started/deploy-mesh-gateway) diff --git a/website/src/pages/docs/getting-started/deploy-mesh-gateway.mdx b/website/src/pages/docs/getting-started/deploy-mesh-gateway.mdx index 2192fdb0bf348..db3866fa7568f 100644 --- a/website/src/pages/docs/getting-started/deploy-mesh-gateway.mdx +++ b/website/src/pages/docs/getting-started/deploy-mesh-gateway.mdx @@ -2,26 +2,32 @@ import { Callout } from '@theguild/components' # How to: Deploy a GraphQL Mesh Gateway -Thanks to its flexible architecture and embedded server relying on [GraphQL Yoga](https://graphql-yoga.com) and [Envelop](https://envelop.dev), **GraphQL Mesh can be deployed anywhere**! +Thanks to its flexible architecture and embedded server relying on +[GraphQL Yoga](https://graphql-yoga.com) and [Envelop](https://envelop.dev), **GraphQL Mesh can be +deployed anywhere**! We already saw that `mesh dev` could be used for local development. Similarly, Mesh provides a `mesh start` CLI command for production environments. -`mesh start` can be used for all environments supporting starting a web server (Heroku, Digital Ocean, etc). +`mesh start` can be used for all environments supporting starting a web server (Heroku, Digital +Ocean, etc). Setup Mesh on a Serverless environment requires some integration work, detailed below. ## Deploy Mesh with `mesh start` on Node.js -While `mesh dev` handles the generation of the SDK code, `mesh start` expects to load the Gateway schema and runtime from the `.mesh/` folder. +While `mesh dev` handles the generation of the SDK code, `mesh start` expects to load the Gateway +schema and runtime from the `.mesh/` folder. This mechanism helps: - **reducing the start time of the server**: no build step is required -- **preventing starting failure if one of the Sources is unreachable**: we don't fetch the API definition file at startup, ensuring that the fetched definitions are validated at build time +- **preventing starting failure if one of the Sources is unreachable**: we don't fetch the API + definition file at startup, ensuring that the fetched definitions are validated at build time -To deploy a Mesh Gateway, you need to ensure that `mesh build` is called during the deployment, for example, with a `prebuild` step: +To deploy a Mesh Gateway, you need to ensure that `mesh build` is called during the deployment, for +example, with a `prebuild` step: ```jsonc filename="package.json" { @@ -33,18 +39,20 @@ To deploy a Mesh Gateway, you need to ensure that `mesh build` is called during } ``` -For more information about the embedded Mesh server configuration, please [refer to the `serve` reference documentation](/docs/getting-started/customize-mesh-server#configuration-serve-reference). +For more information about the embedded Mesh server configuration, please +[refer to the `serve` reference documentation](/docs/getting-started/customize-mesh-server#configuration-serve-reference). ## Deploy Mesh on Serverless -Serverless deployment requires some integration since we cannot keep the `mesh start` server running. +Serverless deployment requires some integration since we cannot keep the `mesh start` server +running. ### Deploy Mesh on Vercel with Next.js API Routes First, let's ensure that `mesh build` will be run during deployment. -Vercel - list most platforms, and run `yarn build` for deployment. -For this reason, we will add a `prebuild` step: +Vercel - list most platforms, and run `yarn build` for deployment. For this reason, we will add a +`prebuild` step: ```json filename="package.json" { @@ -57,6 +65,7 @@ For this reason, we will add a `prebuild` step: ``` Then, we have to update Mesh configuration to let Mesh know the actual endpoint; + ```yaml filename=".meshrc.yml" serve: endpoint: /api/graphql # This is the actual endpoint to the API route @@ -70,12 +79,13 @@ import { createBuiltMeshHTTPHandler } from './.mesh' export default createBuiltMeshHTTPHandler() ``` -Path `./.mesh` refers to built Mesh folder that should be available in your project root -(together with your project `package.json`) +Path `./.mesh` refers to built Mesh folder that should be available in your project root (together +with your project `package.json`) ### Deploy Mesh on AWS Lambda -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. Then, we can create a Lambda as it follows: @@ -88,7 +98,7 @@ const meshHTTP = createBuiltMeshHTTPHandler() export async function handler( event: APIGatewayEvent, - lambdaContext: Context, + lambdaContext: Context ): Promise { const url = new URL(event.path, 'http://localhost') if (event.queryStringParameters != null) { @@ -107,12 +117,12 @@ export async function handler( headers: event.headers as HeadersInit, body: event.body ? Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8') - : undefined, + : undefined }, { event, - lambdaContext, - }, + lambdaContext + } ) const responseHeaders: Record = {} @@ -125,14 +135,15 @@ export async function handler( statusCode: response.status, headers: responseHeaders, body: await response.text(), - isBase64Encoded: false, + isBase64Encoded: false } } ``` ### Deploy Mesh on Cloudflare Workers -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. Then: @@ -148,7 +159,7 @@ You can see the following examples for more details: - [Response Caching on a REST API](https://github.com/Urigo/graphql-mesh/tree/master/examples/cloudflare-workers) - [Response Caching on a GraphQL API](https://github.com/Urigo/graphql-mesh/tree/master/examples/spacex-cfw) -Also you can see how to setup *KV* as a cache storage in GraphQL Mesh [here](/docs/cache/cfwKv). +Also you can see how to setup _KV_ as a cache storage in GraphQL Mesh [here](/docs/cache/cfwKv). ### Deploy Mesh on Apache OpenWhisk @@ -156,19 +167,22 @@ You can see our example that shows how to setup an OpenWhisk action for GraphQL [OpenWhisk Example](https://github.com/Urigo/graphql-mesh/tree/master/examples/openwhisk-example) ### Deploy Mesh on GCP Cloud Functions -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. + +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. Then assuming that your function's name is `mesh`; + ```ts filename="index.ts" -import type { IncomingMessage, ServerResponse } from 'node:http'; -import { createBuiltMeshHTTPHandler } from './.mesh'; +import type { IncomingMessage, ServerResponse } from 'node:http' +import { createBuiltMeshHTTPHandler } from './.mesh' -const meshHTTP = createBuiltMeshHTTPHandler(); +const meshHTTP = createBuiltMeshHTTPHandler() export function mesh(req: IncomingMessage, res: ServerResponse) { // GCP doesn't expose the full path so we need to patch it - req.url = '/mesh' + req.url; - return meshHTTP(req, res); + req.url = '/mesh' + req.url + return meshHTTP(req, res) } ``` @@ -186,7 +200,8 @@ You can see our example that shows how to setup a Cloud Function for GraphQL Mes ### Mesh as an Express route -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. ```ts filename="index.ts" import { createBuiltMeshHTTPHandler } from './.mesh' @@ -197,7 +212,8 @@ app.use('/graphql', createBuiltMeshHTTPHandler()) ### Mesh as a Fastify route -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. ```ts filename="index.ts" import { createBuiltMeshHTTPHandler } from './.mesh' @@ -230,7 +246,8 @@ app.route({ ### Mesh as a Node.js request handler -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. ```ts filename="index.ts" import { createBuiltMeshHTTPHandler } from './.mesh' @@ -242,7 +259,8 @@ server.listen(4000) ### Mesh as a Koa route -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. ```ts filename="index.ts" import { createBuiltMeshHTTPHandler } from './.mesh' @@ -269,7 +287,8 @@ app.use(async ctx => { ### Mesh and SvelteKit -Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the build step. +Similarly to regular and Vercel deployment, we will need to add the `mesh build` command in the +build step. ```ts filename="index.ts" import { createBuiltMeshHTTPHandler } from './.mesh' @@ -281,7 +300,8 @@ export { meshHttp as get, meshHttp as post } ## Mesh and Docker -A GraphQL Mesh Gateway should be treated like any Node.js project while keeping in mind that a `mesh build` step should be added to the deployment steps. +A GraphQL Mesh Gateway should be treated like any Node.js project while keeping in mind that a +`mesh build` step should be added to the deployment steps. Any Node.js Docker image is suitable for GraphQL Mesh deployment: diff --git a/website/src/pages/docs/getting-started/installation.mdx b/website/src/pages/docs/getting-started/installation.mdx index 107e7ef6c5d29..42a54a33a97ca 100644 --- a/website/src/pages/docs/getting-started/installation.mdx +++ b/website/src/pages/docs/getting-started/installation.mdx @@ -21,8 +21,11 @@ As stated previously, Mesh comes in many packages. Each _Source Handler_ and _Transforms_ are shipped as dedicated packages, for example: - The _Handler_ to configure a REST API Source requires the `@graphql-mesh/openapi` package -- The naming convention _Transforms_ requires the `@graphql-mesh/transform-naming-convention` package +- The naming convention _Transforms_ requires the `@graphql-mesh/transform-naming-convention` + package -Mesh will display a helpful error message when using a _Handler_ or _Transforms_ that is not properly installed. +Mesh will display a helpful error message when using a _Handler_ or _Transforms_ that is not +properly installed. -The full list of [Source Handler packages can be found here](/docs/handlers/handlers-introduction), same for [Transforms packages](/docs/transforms/transforms-introduction). +The full list of [Source Handler packages can be found here](/docs/handlers/handlers-introduction), +same for [Transforms packages](/docs/transforms/transforms-introduction). diff --git a/website/src/pages/docs/getting-started/overview.mdx b/website/src/pages/docs/getting-started/overview.mdx index d265315a81484..ab51d64acdfe7 100644 --- a/website/src/pages/docs/getting-started/overview.mdx +++ b/website/src/pages/docs/getting-started/overview.mdx @@ -1,11 +1,13 @@ # Overview -Working with Mesh means dealing with 4 main concepts: _Sources_, _Handlers_, _Transforms_ and _Unified Schema_: +Working with Mesh means dealing with 4 main concepts: _Sources_, _Handlers_, _Transforms_ and +_Unified Schema_: 1. In Mesh, a sub-service (GraphQL API, REST API) is called a _Source_. 2. Sources are translated to GraphQL Schemas with the appropriate _Handler_. 3. All Sources' GraphQL Schema are merged into a final _Unified Schema_. -4. Finally, if applicable, configured transformations, called _Transforms_, are applied to the _Unified Schema_. +4. Finally, if applicable, configured transformations, called _Transforms_, are applied to the + _Unified Schema_. ```mermaid graph LR; @@ -46,7 +48,8 @@ The above GraphQL Mesh Gateway has 3 configured _Sources_: 2. The "Population" _Source_ configured with the `@graphql-mesh/graphql` _Handler_. 3. The "Weather" _Source_ configured with the `@graphql-mesh/raml` _Handler_. -_Sources_, _Handlers_, _Transforms_ are configured in a `.mesh.yaml` (or `.json`, `.js`) configuration file that defines: +_Sources_, _Handlers_, _Transforms_ are configured in a `.mesh.yaml` (or `.json`, `.js`) +configuration file that defines: - How to fetch the definition of the sub-services (GraphQL API, REST API, and more) - What transformations should be applied to the unified schema (_optional_) @@ -54,4 +57,6 @@ _Sources_, _Handlers_, _Transforms_ are configured in a `.mesh.yaml` (or `.json` - Which cache strategy should be used? (_optional_) - Which envelop plugins should be loaded and configured at the server level? (_optional_) -Let's have a closer look to a `.mesh.yaml` configuration file by [installing Mesh](/docs/getting-started/installation) and [building our first Gateway](/docs/getting-started/your-first-mesh-gateway)! +Let's have a closer look to a `.mesh.yaml` configuration file by +[installing Mesh](/docs/getting-started/installation) and +[building our first Gateway](/docs/getting-started/your-first-mesh-gateway)! diff --git a/website/src/pages/docs/getting-started/sources-with-no-definition.mdx b/website/src/pages/docs/getting-started/sources-with-no-definition.mdx index e4bb98885a87d..2c71581c7553a 100644 --- a/website/src/pages/docs/getting-started/sources-with-no-definition.mdx +++ b/website/src/pages/docs/getting-started/sources-with-no-definition.mdx @@ -2,10 +2,11 @@ import { Callout } from '@theguild/components' # How to: Configure Sources with no definition -GraphQL Mesh provides an extensive range of _Handlers_ (OpenAPI, gRPC, SOAP, GraphQL, and even Databases!), however, -you might try to configure a _Source_ that does not provide an API definition. +GraphQL Mesh provides an extensive range of _Handlers_ (OpenAPI, gRPC, SOAP, GraphQL, and even +Databases!), however, you might try to configure a _Source_ that does not provide an API definition. -We will again use the ["Books" example REST API](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/books-service): +We will again use the +["Books" example REST API](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/books-service): - Books API (REST API) - `GET /books` @@ -23,11 +24,13 @@ Z[Mesh Gateway GraphQL API] Z --> G; ``` -Once again, GraphQL Mesh gets you covered with the `@graphql-mesh/json-schema` handler that will help provide a definition of the API. +Once again, GraphQL Mesh gets you covered with the `@graphql-mesh/json-schema` handler that will +help provide a definition of the API. ## An overview of the `jsonSchema` handler -A `jsonSchema` handler configuration must provide a set of `operations` that define the Query and Mutation to expose. +A `jsonSchema` handler configuration must provide a set of `operations` that define the Query and +Mutation to expose. A standard `jsonSchema` handler configuration will look at the following: @@ -45,21 +48,26 @@ sources: responseSample: ./samples/users.json ``` -`operations` defines a set of GraphQL queries or mutations mapped to some API endpoints (`path`, `method`) +`operations` defines a set of GraphQL queries or mutations mapped to some API endpoints (`path`, +`method`) Above, the `users` Query targets the `GET /users` endpoint. Finally, we provide `responseSample` that points to a sample file of the Query response. -By using the `responseSample` file, GraphQL Mesh will be able to generate a GraphQL definition of the `users` Query. +By using the `responseSample` file, GraphQL Mesh will be able to generate a GraphQL definition of +the `users` Query. Let's put it in practice with our "Books" REST API `GET /book/:id` endpoint. ## Configuring our "Books" REST API -You will find all the source code of the below example in the dedicated repository: [`graphql-mesh-docs-first-gateway`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition). +You will find all the source code of the below example in the dedicated repository: +[`graphql-mesh-docs-first-gateway`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition). -After installing the `@graphql-mesh/json-schema` package, a good starting point for our "Books" REST API `jsonSchema` handler configuration would be the following [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): +After installing the `@graphql-mesh/json-schema` package, a good starting point for our "Books" REST +API `jsonSchema` handler configuration would be the following +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -71,7 +79,8 @@ sources: We need to provide some `operations` for the `GET /book/:id` along with some sample data. -We can get some sample data by running the following commands ([at the root of the project](https://github.com/charlypoly/graphql-mesh-docs-first-gateway)): +We can get some sample data by running the following commands +([at the root of the project](https://github.com/charlypoly/graphql-mesh-docs-first-gateway)): 1. Build and start the Books REST API @@ -86,13 +95,16 @@ yarn workspace books-service run start curl --location --request GET 'http://localhost:3002/books/1' > packages/single-source-no-source-definition/samples/book-1.json ``` -Which will create the following [`packages/single-source-no-source-definition/samples/book-1.json`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/samples/book-1.json) file: +Which will create the following +[`packages/single-source-no-source-definition/samples/book-1.json`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/samples/book-1.json) +file: ```json filename="book-1.json" { "id": "1", "title": "Dune", "authorId": "0", "categoryId": "0" } ``` -We can now provide use this sample file to configure our `Query.book` operation as follows [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): +We can now provide use this sample file to configure our `Query.book` operation as follows +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -116,7 +128,8 @@ Let's build and start our Gateway by running: yarn run single-source-no-source-definition ``` -Once built, you will find the Unified Schema definition at [`packages/single-source-no-source-definition/.mesh/schema.graphql`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.mesh/schema.graphql): +Once built, you will find the Unified Schema definition at +[`packages/single-source-no-source-definition/.mesh/schema.graphql`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.mesh/schema.graphql): ```graphql filename="schema.graphql" type Query { @@ -154,9 +167,12 @@ We successfully added a Source without definition! 🎉 ### Rename generated types -Our `Query.book` `jsonSchema` configuration generates a `query_book` type which is poorly named and using _snake_case_. +Our `Query.book` `jsonSchema` configuration generates a `query_book` type which is poorly named and +using _snake_case_. -The `responseTypeName` allows us to provide a type name that we will be used for the generated type, as follows [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): +The `responseTypeName` allows us to provide a type name that we will be used for the generated type, +as follows +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -192,7 +208,8 @@ The same parameter exists for request: `requestTypeName` (see "_Mutations_"). ### Queries/Mutations arguments -We saw that `operations[].path` can take arguments using syntax similar to string interpolation [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): +We saw that `operations[].path` can take arguments using syntax similar to string interpolation +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source-no-source-definition/.meshrc.yaml): ```yaml filename=".meshrc.yaml" sources: @@ -242,9 +259,11 @@ Now, GraphQL Mesh knows that the type definition of our search query is: ### Mutations -Since Mutations are most likely to rely on `POST` requests, we need to provide both a `requestSample` and a `responseSample` parameters. +Since Mutations are most likely to rely on `POST` requests, we need to provide both a +`requestSample` and a `responseSample` parameters. -For example, if our "Books" API exposed a `POST /books`, we could define the following `Mutation.addBook(…)` mutation: +For example, if our "Books" API exposed a `POST /books`, we could define the following +`Mutation.addBook(…)` mutation: ```yaml filename=".meshrc.yaml" sources: @@ -263,11 +282,13 @@ sources: ### `Query`/`Mutation` with multiple response shapes -Providing `responseSample/requestSample` is an efficient way to configure a Source without API definition. +Providing `responseSample/requestSample` is an efficient way to configure a Source without API +definition. However, the sample files might not always represent all the variants of a given endpoint. -For example, our previous `POST /books` endpoint could return a totally different response shape depending on the scenario: +For example, our previous `POST /books` endpoint could return a totally different response shape +depending on the scenario: **Successfully book creation response** @@ -321,7 +342,8 @@ sources: This guide doesn't provide any materials to learn JSON Schema (this would require multiple guides). -However, you can get started on the official [JSON Schema tutorial](https://json-schema.org/learn/getting-started-step-by-step.html). +However, you can get started on the official +[JSON Schema tutorial](https://json-schema.org/learn/getting-started-step-by-step.html). Our `./schema/add-book-response.json` would look as follows: @@ -418,7 +440,8 @@ type AddBookOutputDuplicate { } ``` -Note that you can also leverage the `responseByStatusCode` parameter to provide a schema per HTTP Status Code, as follows: +Note that you can also leverage the `responseByStatusCode` parameter to provide a schema per HTTP +Status Code, as follows: ```yaml filename=".meshrc.yaml" operations: diff --git a/website/src/pages/docs/getting-started/your-first-mesh-gateway.mdx b/website/src/pages/docs/getting-started/your-first-mesh-gateway.mdx index 30e448018ef24..7e57a294fa314 100644 --- a/website/src/pages/docs/getting-started/your-first-mesh-gateway.mdx +++ b/website/src/pages/docs/getting-started/your-first-mesh-gateway.mdx @@ -1,8 +1,11 @@ # Your first Gateway with Mesh -Mesh [being installed](/docs/getting-started/installation), we can now build our first GraphQL Gateway. +Mesh [being installed](/docs/getting-started/installation), we can now build our first GraphQL +Gateway. -All the documentation tutorials and guides rely on the "Books", "Authors" and "Stores" example APIs, available in a dedicated repository: [`graphql-mesh-docs-first-gateway`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway): +All the documentation tutorials and guides rely on the "Books", "Authors" and "Stores" example APIs, +available in a dedicated repository: +[`graphql-mesh-docs-first-gateway`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway): - Books API (REST API) - `GET /books` @@ -15,7 +18,8 @@ All the documentation tutorials and guides rely on the "Books", "Authors" and "S - `stores` Query - `bookSells(storeId: ID!)` Query -Our goal is to build a Unified GraphQL Schema through a Mesh Gateway that incorporates our 3 example services as follows: +Our goal is to build a Unified GraphQL Schema through a Mesh Gateway that incorporates our 3 example +services as follows: ```mermaid graph TD; @@ -38,7 +42,8 @@ Z --> F; Z --> G; ``` -In this tutorial, **we will first start by creating a Mesh configuration that incorporates the Books REST API**, as follows: +In this tutorial, **we will first start by creating a Mesh configuration that incorporates the Books +REST API**, as follows: ```mermaid graph TD; @@ -57,34 +62,44 @@ C --> Z; Z --> G; ``` -Creating the complete Mesh Gateway that combines "Books", "Authors", and "Stores" APIs in a unified Schema will be covered in the ["Setup a Gateway with many Sources" guide](/docs/guides/combine-many-sources). +Creating the complete Mesh Gateway that combines "Books", "Authors", and "Stores" APIs in a unified +Schema will be covered in the +["Setup a Gateway with many Sources" guide](/docs/guides/combine-many-sources). ## Add the Books REST API to our GraphQL Gateway ### 1. A closer look at our Books REST API -To add the Books API as a _Source_ of our GraphQL Mesh configuration, we will need to get the API's definition. +To add the Books API as a _Source_ of our GraphQL Mesh configuration, we will need to get the API's +definition. -Depending on the API type, many definition types will be available; for example, REST API tends to be described using Open API/Swagger. +Depending on the API type, many definition types will be available; for example, REST API tends to +be described using Open API/Swagger. Open API is a standard based on JSON Schema (JSON-based files standard) to describe APIs. -Our Books REST API provides an Open API definition file: [`packages/books-service/openapi3-definition.json`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/books-service/openapi3-definition.json). +Our Books REST API provides an Open API definition file: +[`packages/books-service/openapi3-definition.json`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/books-service/openapi3-definition.json). -The `openapi3-definition.json` file describes the available endpoints along with their arguments and responses shape: +The `openapi3-definition.json` file describes the available endpoints along with their arguments and +responses shape: - `GET /books` - `GET /books/:id` - `GET /categories` -We now established that our Books API will require the `openapi` Mesh _Handler_ with the `@graphql-mesh/openapi` package. +We now established that our Books API will require the `openapi` Mesh _Handler_ with the +`@graphql-mesh/openapi` package. ### 2. Creating our Mesh configuration file -Let's go to the [`packages/single-source/`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source) where the following dependencies are installed: +Let's go to the +[`packages/single-source/`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source) +where the following dependencies are installed: - `graphql` is a required peer dependency of GraphQL Mesh -- `@graphql-mesh/cli` provides everything to parse the configuration, execute the _Handlers_, _Transforms_ and serve the API +- `@graphql-mesh/cli` provides everything to parse the configuration, execute the _Handlers_, + _Transforms_ and serve the API - `@graphql-mesh/openapi` is the _Handler_ of the "Books" _Source_ The `.meshrc.yaml` configuration file contains the following content: @@ -98,11 +113,14 @@ sources: source: ../books-service/openapi3-definition.json ``` -The configuration is straightforward; we define a _Source_ called "Books" that is configured with the `openapi` _Handler_. +The configuration is straightforward; we define a _Source_ called "Books" that is configured with +the `openapi` _Handler_. -By providing the `source` document path, Mesh will be able to translate the OpenAPI JSON definition to a GraphQL Schema. +By providing the `source` document path, Mesh will be able to translate the OpenAPI JSON definition +to a GraphQL Schema. -**Let's first start our Books API** and **our GraphQL Gateway** by running at the root of the project: +**Let's first start our Books API** and **our GraphQL Gateway** by running at the root of the +project: ```sh yarn start-single-source @@ -113,7 +131,8 @@ And open your favorite web browser at [http://0.0.0.0:4000](http://0.0.0.0:4000) As expected, Mesh translated the Books REST API to a GraphQL Schema, using the following rules: - a `GET /api/helloWorld` endpoint becomes a Query similar to: `helloWorld(): String!{:graphql}` -- a `POST /api/sayHelloAll` endpoint becomes a Mutation similar to: `sayHelloAll(input: [SayHelloAllInput]): String{:graphql}` +- a `POST /api/sayHelloAll` endpoint becomes a Mutation similar to: + `sayHelloAll(input: [SayHelloAllInput]): String{:graphql}` - `PUT` and `DELETE` endpoints are also translated to GraphQL Mutations. This gives us the following Books GraphQL Schema: @@ -137,17 +156,23 @@ You can try out the following Query: We might not want to expose all those Queries in our _Unified Schema_. -Let's say that we want to **remove** the `book(id: ID!)` Query and **rename** the `categories` Query to `booksCategories`. +Let's say that we want to **remove** the `book(id: ID!)` Query and **rename** the `categories` Query +to `booksCategories`. To achieve such a final Schema design, we will leverage _Transforms_. **Remove the `book(id: ID!)` Query** -We will install and configure the `filterSchema` _Transform_ to remove a Query from the Unified Schema. +We will install and configure the `filterSchema` _Transform_ to remove a Query from the Unified +Schema. -Back to the [`packages/single-source/`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source) folder, you will find the following package installed: `@graphql-mesh/transform-filter-schema`. +Back to the +[`packages/single-source/`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source) +folder, you will find the following package installed: `@graphql-mesh/transform-filter-schema`. -And update our [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source/.meshrc.yaml) as follows: +And update our +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source/.meshrc.yaml) +as follows: ```yaml filename=".meshrc.yaml" {7-10} sources: @@ -170,15 +195,21 @@ We added a `transforms` key at the root of the configuration. By adding `Query.!book`, we instruct Mesh to remove the `book(…)` Query. -More information on the `filterSchema` _Transform_ on [its dedicated documentation page](/docs/transforms/filter-schema). +More information on the `filterSchema` _Transform_ on +[its dedicated documentation page](/docs/transforms/filter-schema). **Rename the `categories(…)` Query to `booksCategories(…)`** -Finally, let's rename our `categories(…)` Query to `booksCategories(…)` by using the `rename` _Transform_. +Finally, let's rename our `categories(…)` Query to `booksCategories(…)` by using the `rename` +_Transform_. -Again in the [`packages/single-source/`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source) folder, you will find the following package installed: `@graphql-mesh/transform-rename`. +Again in the +[`packages/single-source/`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source) +folder, you will find the following package installed: `@graphql-mesh/transform-rename`. -And update our [`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source/.meshrc.yaml) as follows: +And update our +[`.meshrc.yaml`](https://github.com/charlypoly/graphql-mesh-docs-first-gateway/tree/master/packages/single-source/.meshrc.yaml) +as follows: ```yaml filename=".meshrc.yaml" {11-18} sources: @@ -205,23 +236,27 @@ transforms: Here, we indicate that `Query.categories` should be renamed `Query.booksCategories`. -More information on the `rename` _Transform_ on [its dedicated documentation page](/docs/transforms/rename). +More information on the `rename` _Transform_ on +[its dedicated documentation page](/docs/transforms/rename). Our final _Unified Schema_ is now ready to be used: ![Books GraphQL Unified Schema](/assets/docs/getting-started/your-first-mesh-gateway/mesh-books-graphql-unified-schema.png) -The power of GraphQL Mesh, on top of providing an extensive range of _Handlers_, is to empower us to create well-designed GraphQL Schema using _Transforms_. +The power of GraphQL Mesh, on top of providing an extensive range of _Handlers_, is to empower us to +create well-designed GraphQL Schema using _Transforms_. Keep in mind that a good GraphQL Schema design should: - provides useful queries (not expose unnecessary ones) - simplify the usage by providing the proper abstractions (ex: proper naming and hierarchy) -- provide specialized mutations that represent specific behaviors instead of CRUD mutations directly linked to an underlying data-schema +- provide specialized mutations that represent specific behaviors instead of CRUD mutations directly + linked to an underlying data-schema ### Our GraphQL Gateway API is ready! -Congratulations! Our Books REST API is now accessible through our Mesh GraphQL Gateway a comprehensive and tailored Schema design. +Congratulations! Our Books REST API is now accessible through our Mesh GraphQL Gateway a +comprehensive and tailored Schema design. You can now start again and play with the GraphQL Schema by running: @@ -229,7 +264,8 @@ You can now start again and play with the GraphQL Schema by running: yarn start-single-source ``` -And open your favorite web browser at [http://0.0.0.0:4000](http://0.0.0.0:4000) and try the following Query: +And open your favorite web browser at [http://0.0.0.0:4000](http://0.0.0.0:4000) and try the +following Query: ```graphql { @@ -247,6 +283,8 @@ And open your favorite web browser at [http://0.0.0.0:4000](http://0.0.0.0:4000) ## Going further -You are now familiar with Mesh's concepts of _Sources_, _Handlers_, _Transforms_, and _Unified Schema_ 🚀. +You are now familiar with Mesh's concepts of _Sources_, _Handlers_, _Transforms_, and _Unified +Schema_ 🚀. -Let's finish our Gateway in the ["Combine multiple Sources" guide](/docs/getting-started/combine-multiple-sources). +Let's finish our Gateway in the +["Combine multiple Sources" guide](/docs/getting-started/combine-multiple-sources). diff --git a/website/src/pages/docs/guides/auth0.mdx b/website/src/pages/docs/guides/auth0.mdx index 872610e351ed0..ab0f408f807c5 100644 --- a/website/src/pages/docs/guides/auth0.mdx +++ b/website/src/pages/docs/guides/auth0.mdx @@ -2,9 +2,14 @@ import { PackageCmd } from '@theguild/components' # Adding Authentication with Auth0 -Authentication in the process of identifying who is trying to access our API. Building our own solution can be hard and cause severe security issue if done wrong. In recent years third-party authentication providers became quite popular. One of those is Auth0, which comes with an exceptional free plan allowing up to 7.000 active users and unlimited logins, making it one of the best available solutions for getting started. +Authentication in the process of identifying who is trying to access our API. Building our own +solution can be hard and cause severe security issue if done wrong. In recent years third-party +authentication providers became quite popular. One of those is Auth0, which comes with an +exceptional free plan allowing up to 7.000 active users and unlimited logins, making it one of the +best available solutions for getting started. -In this guide we will go through all the steps required for integrating authentication into an existing mesh setup using the [`@envelop/auth0`](https://www.envelop.dev/plugins/use-auth0) package. +In this guide we will go through all the steps required for integrating authentication into an +existing mesh setup using the [`@envelop/auth0`](https://www.envelop.dev/plugins/use-auth0) package. ## Installing dependencies @@ -27,26 +32,35 @@ plugins: ## Setting up the Auth0 API -In order to properly configure the Auth0 plugin we need the `domain` and `audience` values. We will retrieve them by setting and configuring Auth0 from scratch! +In order to properly configure the Auth0 plugin we need the `domain` and `audience` values. We will +retrieve them by setting and configuring Auth0 from scratch! -If didn't already sign up for Auth0, you should do it now on [Auth0 Sign Up](https://auth0.com/sign-up). Since you can sign up with your GitHub or Google Account it should be super fast! +If didn't already sign up for Auth0, you should do it now on +[Auth0 Sign Up](https://auth0.com/sign-up). Since you can sign up with your GitHub or Google Account +it should be super fast! -After logging in navigate to the [Auth0 dashboard](https://manage.auth0.com/dashboard) and from there to the APIs page, where we will click the **Create API** button. +After logging in navigate to the [Auth0 dashboard](https://manage.auth0.com/dashboard) and from +there to the APIs page, where we will click the **Create API** button. ![Auth0 Dashboard](https://user-images.githubusercontent.com/20847995/190179311-f5852eed-6d7b-4131-936f-93f779f9bc84.png) -Choose any name for the API, we are going with `Mesh Demo` for this example. -The `Identifier` field should be set to the URL of our GraphQL API. We are hosting our API on localhost and set it to the host and port on which our Mesh server is served, which is `http://localhost:3000/graphql`. For production you should instead set it to the URL of the production server. +Choose any name for the API, we are going with `Mesh Demo` for this example. The `Identifier` field +should be set to the URL of our GraphQL API. We are hosting our API on localhost and set it to the +host and port on which our Mesh server is served, which is `http://localhost:3000/graphql`. For +production you should instead set it to the URL of the production server. ![Auth0 API](https://user-images.githubusercontent.com/20847995/190179485-8715fe8c-4b36-46aa-8cd7-398ad3ffbf2b.png) -We can ignore the Signing Algorithm option and go with the pre-set value. Once everything is filled out properly we can click the `Create` button. +We can ignore the Signing Algorithm option and go with the pre-set value. Once everything is filled +out properly we can click the `Create` button. -Now we already have one of the missing config options we needed `audience` , which is equal to the URL we just entered `http://localhost:3000/graphql`. +Now we already have one of the missing config options we needed `audience` , which is equal to the +URL we just entered `http://localhost:3000/graphql`. ![Auth0 Copy Audience](https://user-images.githubusercontent.com/20847995/190179606-abddf0b2-0ac4-46c7-963e-71f4adb66ace.png) -The `domain` value is a bit hidden, but we can find it on the detail page of the API we just created, on the `Test` tab. +The `domain` value is a bit hidden, but we can find it on the detail page of the API we just +created, on the `Test` tab. ![Auth0 domain](https://user-images.githubusercontent.com/20847995/190179991-8f04cb80-dab4-44ff-b2dc-0315aa987ff0.png) @@ -68,14 +82,15 @@ plugins: extendContextField: '_auth0' ``` -We now have all the information needed for configuring the plugin. However, we did not yet setup an application that is required for users to authenticate in the browser. +We now have all the information needed for configuring the plugin. However, we did not yet setup an +application that is required for users to authenticate in the browser. But before doing so, let's verify that the plugin is doing what it should do. ## Expose authentication information via GraphQL schema -Before we start our server we should add some types and fields to our schema in order to query for the authentication information. -The complete code should look like this: +Before we start our server we should add some types and fields to our schema in order to query for +the authentication information. The complete code should look like this: ```yaml filename=".meshrc.yaml" additionalTypeDefs: | @@ -120,7 +135,8 @@ yarn run v1.22.10 $ mesh dev ``` -Next, we are going to execute a query on the GraphiQL instance exposed on `http:localhost:3000/graphql`. +Next, we are going to execute a query on the GraphiQL instance exposed on +`http:localhost:3000/graphql`. ```graphql query { @@ -132,28 +148,38 @@ query { ![GraphiQL Unauthenticated](https://user-images.githubusercontent.com/20847995/190180110-7d27a469-eb45-457f-a7ac-5f37bc2f96a4.png) -As expected the value of the `authInfo` field is `null`, as we are not passing any authentication headers along with our request. +As expected the value of the `authInfo` field is `null`, as we are not passing any authentication +headers along with our request. ## Generating an Auth0 Access Token -In order to retrieve an access token, we first need to set up an Auth0 application and an authentication route. -For the sake of this guide and in order to reduce complexity we will simply add an route to our Mesh http server that renders some HTML with a `