nexus icon indicating copy to clipboard operation
nexus copied to clipboard

typescript compiler 'authorize' does not exist in type 'NexusOutputFieldConfig<"Query","">

Open saostad opened this issue 4 years ago • 13 comments

typescript compiler fails to compile.

Packages:

"nexus": "^0.12.0-rc.5",
"typescript": "^3.7.2",

Error Message:

src/graphql/schema/ad/query.ts:9:7 - error TS2345: Argument of type '{ type: string; nullable: true; authorize: () => boolean; resolve: (_: any, {}: any, { services }: any) => Promise<any>; }' is not assignable to parameter of type 'NexusOutputFieldConfig<"Query", "getCompanyUsers">'.      
  Object literal may only specify known properties, and 'authorize' does not exist in type 'NexusOutputFieldConfig<"Query", "getCompanyUsers">'.

authorize: () => false,

Server Code:

import { makeSchema, fieldAuthorizePlugin } from "nexus";
const schema = makeSchema({
  types,
  outputs: {
    schema: path.join(__dirname + "/generated/schema.graphql"),
    typegen: path.join(__dirname + "/generated/typings.ts"),
  },
  typegenAutoConfig: {
    sources: [
      {
        source: path.join(__dirname, "..", "typings", "types.ts"),
        alias: "t",
      },
    ],
    contextType: "t.Context",
  },
  plugins: [fieldAuthorizePlugin()],
  prettierConfig: path.join(__dirname, "../../.prettierrc"),
});

Query Code:

import { extendType } from "nexus";

export const adQueries = extendType({
  type: "Query",
  definition(t) {
    t.list.field("getCompanyUsers", {
      type: "AdUser",
      nullable: true,
      authorize: () => false,
      resolve: async (_, {}, { services }) => {
        const items = await services.ad.getCompanyUsers("xxxx");
        return items;
      },
    });
  },
});

saostad avatar Nov 20 '19 17:11 saostad

The tsc will always be invalid until the first time you execute the TypeScript. It's a sort of chicken-and-egg problem, the code which executes to emit the types.

Try executing the script with something like ts-node-dev and then see if tsc still complains.

tgriesser avatar Nov 20 '19 21:11 tgriesser

I test it with ts-node and tsc, and also first added plugins: [fieldAuthorizePlugin()], to schema code and after the first compile and make sure it added correct typedefs in generated files I added authorize: () => false, to my query field. after all those steps I am still getting the error above. also, VSCode is ok after the first compilation but the ts-node still complains. it also works with ts-node-dev if I run it like this: ts-node-dev --respawn --transpileOnly src/app.ts please advise.

saostad avatar Nov 20 '19 22:11 saostad

I have the same issue... This error precisely:

Object literal may only specify known properties, and 'authorize' does not exist in type 'NexusOutputFieldConfig<"Account", "administratedProfiles">'.

I also added the plugin.

lcswillems avatar Nov 29 '19 16:11 lcswillems

Note: My code was perfectly working with 0.11.7.

I also tested with the 14th beta. It is also working. It breaks when I upgrade to a rc.

lcswillems avatar Nov 29 '19 17:11 lcswillems

Confirm, same issue for me on 0.12.0-rc.5

LexSwed avatar Dec 03 '19 20:12 LexSwed

I'm working through the issues with some real world examples come up with some potential solutions / advice here, because this is a common pain point when getting started.

I just realized that because of how ts-node transpiles the code, it doesn't pick up the generated type defs file unless you explicitly reference it explicitly (via references or import). It may help if you add this explicitly, e.g. /// <reference path="./path-to-schema-types.ts" /> in the file where you run the makeSchema. See the PR in #348

For reference, at Cypress, we run all code in development with the equivalent of

ts-node-dev --respawn --transpileOnly

during development, and then run tsc in CI to ensure that the types are correct. We then run our production code with node -r ts-node/register/transpile-only path-to-app.ts

tgriesser avatar Dec 04 '19 12:12 tgriesser

Thank you for your answer! This helps! And also, thank you for your work with nexus. It makes GraphQL so simple!

lcswillems avatar Dec 05 '19 10:12 lcswillems

I'm working through the issues with some real world examples come up with some potential solutions / advice here, because this is a common pain point when getting started.

I just realized that because of how ts-node transpiles the code, it doesn't pick up the generated type defs file unless you explicitly reference it explicitly (via references or import). It may help if you add this explicitly, e.g. /// <reference path="./path-to-schema-types.ts" /> in the file where you run the makeSchema. See the PR in #348

For reference, at Cypress, we run all code in development with the equivalent of

ts-node-dev --respawn --transpileOnly

during development, and then run tsc in CI to ensure that the types are correct. We then run our production code with node -r ts-node/register/transpile-only path-to-app.ts

but I have same problem even with tsc, how do you pass the CI step?

saostad avatar Dec 05 '19 14:12 saostad

Can you create a gist with your generated nexus types file, as well as the error you get with tsc?

tgriesser avatar Dec 05 '19 15:12 tgriesser

I don't know what happened exactly but with tsc it is working now.

saostad avatar Dec 05 '19 16:12 saostad

If anyone else is looking for an alternative solution, this helped us get our IDEs (VSCode), Jest tests and serverless-offline/serverless-typescript all working together to be authorize aware. We added this to our own custom typings since we know we will always use this plugin.

In ./typings/index.d.ts:

import { FieldAuthorizeResolver } from '@nexus/schema/dist/plugins/fieldAuthorizePlugin'

declare global {

  interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
    /**
     * Authorization for an individual field. Returning "true"
     * or "Promise<true>" means the field can be accessed.
     * Returning "false" or "Promise<false>" will respond
     * with a "Not Authorized" error for the field.
     * Returning or throwing an error will also prevent the
     * resolver from executing.
     */
    authorize?: FieldAuthorizeResolver<TypeName, FieldName>
  }
}

The in ./tsconfig.json:

{
  "compilerOptions": {
    ...,
    "typeRoots": [
      "typings",
      "./node_modules/@types"
    ],
    "types": [ 
      // Required for custom typings  if using serverless-offline & serverless-typescript:
      "../typings"
    ],
  },
}

jrandeniya avatar Oct 15 '20 21:10 jrandeniya

For me none of the above solutions worked but this SO answer did: https://stackoverflow.com/a/51666714

I'm using ts-node + nodemon but maybe there's a similar option for ts-node-dev. I added --files=$PATH_TO_NEXUS_TYPEGEN to my ts-node command.

Before:

nodemon --watch 'src/**/*.ts' --ignore 'src/**/*.spec.ts' --exec 'ts-node' src/index.ts

After:

nodemon --watch 'src/**/*.ts' --ignore 'src/**/*.spec.ts' --exec 'ts-node' --files=src/generated/nexus-typegen.ts src/index.ts
                                                                           |____________________________________|
                                                                                              |
                                                                                      here's what i added

tom-sherman avatar Dec 28 '20 23:12 tom-sherman

I believe @tgriesser solution is valid since Nexus does mentioned about it in their documentation which related to Nexus Reflection

varvay avatar Sep 15 '22 15:09 varvay