prisma-labs / graphql-framework-experiment

Code-First Type-Safe GraphQL Framework
https://nexusjs.org
MIT License
674 stars 66 forks source link

Foolproof way to extend test context from plugin #1069

Open jasonkuhrt opened 4 years ago

jasonkuhrt commented 4 years ago

Perceived Problem

Ideas / Proposed Solution(s)

nexus.addTypes idea (obsolete) A new worktime lens API ```ts export const plugin: WorktimePlugin = (userSettings) => (nexus) => { nexus.addTypes({ to: 'TestContextApp', from: { module: __filename, export: 'NexusTestContextApp', }, }) ``` [Refer to PR for more code context](https://github.com/graphql-nexus/nexus-plugin-prisma/pull/153). This API would allow plugins to declaratively extend core types of Nexus. The `to` property would be a string literal union of those core types. So `Context`, `TestContext`, `TestContextApp`, `Request` (future), and so on. The `from` property as shown here would represent a _static_ source of typing data. Dynamic input could be given with another property name or union member of `from`, e.g. `from.source`. I'm going to focus on the static use-case as its the focus of this PR. I think it's enough to know for now that we have room in the API to handle dynamic in the future. The logic would go something like this: 1. Every time typegen runs, gather the contributions from all plugins 2. Create `@types/typegen-nexus-additions/index.d.ts` 3. For each contribution: ```ts // @types/typegen-nexus-additions/index.d.ts // should be automatically made relative // should have its ext stripped if ends with .js import * as ViaPlugin from '' declare global { interface extends ViaPlugin. {} } ``` #### Goals - minimize IO (or system that has potential to in future, e.g. declarative plugin interface vs procedural one) - minimize complexity for plugin authors - guaranteed correctness for end-users (e.g. no flake like we have today with post-install hook) - while we're here: allow plugin authors to easily set typegen conditional to the settings they receive. While its possible today (see nexus-prisma) I think the proposal here makes it a lot easier, especially for simpler cases.

A new worktime lens API

export const plugin: WorktimePlugin<Settings> = (userSettings) => (nexus) => {
  nexus.testing.addToContext(() => {
    return {
        data: {...},
        type: {
          module: __filename,
          export: 'NexusTestContextApp',
        }
    }
  })

The logic would go something like this:

  1. Every time reflection runs, gather testing contributions from all plugins
  2. Create @types/typegen-nexus-testing/index.d.ts
  3. For each contribution:

    // @types/typegen-nexus-testing/index.d.ts
    
    // <path> should be automatically made relative
    // <path> should have its ext stripped if ends with .js
    
    import * as ViaPlugin<PluginName><PathSlug> from '<path>'
    
    declare global {
      interface NexusTestContext extends ViaPlugin<PluginName><PathSlug>.<ExportName> {}    
    }

Some other things that are expected to be done in the future, to give context of the design direction in this issue:

jasonkuhrt commented 4 years ago

@Weakky wdyt?

jstpierref commented 4 years ago

hello! do you have any update on this issue? Thanks!