Skip to content

Releases: n1ru4l/envelop

December 12, 2024

12 Dec 15:03
58cd3e8
Compare
Choose a tag to compare

@envelop/sentry@12.0.0

Major Changes

  • #2323
    2993773
    Thanks @Karibash! - Make it possible to get the active span in the
    GraphQL resolver

    Breaking Change: With this change, this plugin now wraps the execute function. This plugin
    should be placed last so that the execute function is not overwritten by another plugin.

    const yoga = createYoga({
      plugins: [
        ...otherPlugins,
        useSentry({
          // ...
        })
      ]
    })

December 11, 2024

11 Dec 10:43
f7be09b
Compare
Choose a tag to compare

@envelop/generic-auth@8.0.1

Patch Changes

  • #2347
    8b7e657
    Thanks @ardatan! - dependencies updates:

  • #2347
    8b7e657
    Thanks @ardatan! - Handle operations with `@include` and `@skip`
    correctly when they have default values in the operation definition

    {
        query: /* GraphQL */ `
          query MyQuery($include: Boolean = true) {
            field @include(if: $include)
          }
        `,
        variables: {}
    }

    should be considered same as

    {
        query: /* GraphQL */ `
          query MyQuery($include: Boolean!) {
            field @include(if: $include)
          }
        `,
        variables: {
            include: true
        }
    }

@envelop/response-cache@6.2.5

Patch Changes

@envelop/sentry@11.0.0

Major Changes

  • #2335
    073774c
    Thanks @EmrysMyrddin! - Fix: Update code to better feat the new
    Sentry v8 API

    Breaking Change:

    • startTransaction option has been removed.
    • forceTransaction option has been added, disabled by default.

@envelop/statsd@5.0.1

Patch Changes

November 26, 2024

26 Nov 10:51
40889ca
Compare
Choose a tag to compare

@envelop/prometheus@11.1.0

Minor Changes

  • #2326
    443fc15
    Thanks @EmrysMyrddin! - Allow to explicitly control which
    events and timing should be observe.

    Each metric can now be configured to observe events and timings only for certain GraphQL pipeline
    phases, or depending on the request context.

    Example: trace only execution and subscription errors

    import { execute, parse, specifiedRules, subscribe, validate } from 'graphql'
    import { envelop, useEngine } from '@envelop/core'
    import { usePrometheus } from '@envelop/prometheus'
    
    const TRACKED_OPERATION_NAMES = [
      // make a list of operation that you want to monitor
    ]
    
    const getEnveloped = envelop({
      plugins: [
        useEngine({ parse, validate, specifiedRules, execute, subscribe }),
        usePrometheus({
          metrics: {
            // Here, an array of phases can be provided to enable the metric only on certain phases.
            // In this example, only error happening during the execute and subscribe phases will tracked
            graphql_envelop_phase_error: ['execute', 'subscribe']
          }
        })
      ]
    })

    Example: Monitor timing only of a set of operations by name

    import { execute, parse, specifiedRules, subscribe, validate } from 'graphql'
    import { envelop, useEngine } from '@envelop/core'
    import { usePrometheus } from '@envelop/prometheus'
    
    const TRACKED_OPERATION_NAMES = [
      // make a list of operation that you want to monitor
    ]
    
    const getEnveloped = envelop({
      plugins: [
        useEngine({ parse, validate, specifiedRules, execute, subscribe }),
        usePrometheus({
          metrics: {
            graphql_yoga_http_duration: createHistogram({
              registry,
              histogram: {
                name: 'graphql_envelop_request_duration',
                help: 'Time spent on HTTP connection',
                labelNames: ['operationName']
              },
              fillLabelsFn: ({ operationName }, _rawContext) => ({ operationName }),
              phases: ['execute', 'subscribe'],
    
              // Here `shouldObserve` control if the request timing should be observed, based on context
              shouldObserve: ({ operationName }) => TRACKED_OPERATIONS.includes(operationName)
            })
          }
        })
      ]
    })

    Default Behavior Change

    A metric is enabled using true value in metrics options will observe in every phases available.

    Previously, which phase was observe was depending on which other metric were enabled. For example,
    this config would only trace validation error:

    usePrometheus({
      metrics: {
        graphql_envelop_phase_error: true,
        graphql_envelop_phase_validate: true
      }
    })

    This is no longer the case. If you were relying on this behavior, please use an array of string to
    restrict observed phases.

    usePrometheus({
      metrics: {
        graphql_envelop_phase_error: ['validate']
      }
    })

November 20, 2024

20 Nov 17:24
4d82b34
Compare
Choose a tag to compare

@envelop/graphql-jit@8.0.4

Patch Changes

@envelop/rate-limiter@6.2.1

Patch Changes

October 10, 2024

10 Oct 12:58
1a1dabc
Compare
Choose a tag to compare

@envelop/response-cache@6.2.4

Patch Changes

  • c1720a8
    Thanks @n1ru4l! - Fix handling of primitive list values that was
    introduced in the last release.

October 09, 2024

09 Oct 12:08
4031c59
Compare
Choose a tag to compare

@envelop/response-cache@6.2.3

Patch Changes

October 09, 2024

09 Oct 10:28
625fe9d
Compare
Choose a tag to compare

@envelop/immediate-introspection@4.0.0

Major Changes

@envelop/response-cache@6.2.2

Patch Changes

  • #2309
    4fd5917
    Thanks @n1ru4l! - Strip __responseCacheId and
    __responseCacheTypeName from incremental delivery execution result.

@envelop/sentry@10.0.0

Major Changes

August 26, 2024

26 Aug 10:48
41c8e78
Compare
Choose a tag to compare

@envelop/generic-auth@8.0.0

Major Changes

  • #2281
    70d4d7a
    Thanks @UserType;! - Refactor Generic Auth plugin;

    • [BREAKING] - Now @auth directive is renamed to @authenticated. If you want to keep the old
      name you can configure the plugin to use the old name.
    useGenericAuth({
      // ...
      authDirectiveName: 'auth'
    })
    • [BREAKING] - Now directiveOrExtensionFieldName is renamed to authDirectiveName.
    useGenericAuth({
      // ...
    - directiveOrExtensionFieldName: 'auth',
    + authDirectiveName: 'auth',
    });
    • Now auth directives support OBJECT and INTERFACE locations, so you can use the auth
      directive on types as well.
    directive @authenticated on OBJECT | INTERFACE
    
    type User @authenticated {
      id: ID!
      name: String!
    }
    • validateUser function does not receive fieldAuthDirectiveNode and fieldAuthExtension
      anymore. Instead, it takes fieldAuthArgs which is an object that contains the arguments of the
      auth directive or extension. So you don't need to parse the arguments manually anymore.
    const validateUser: ValidateUserFn = params => {
      if (!params.fieldAuthArgs.roles.includes('admin')) {
        return createUnauthorizedError(params)
      }
    }
    • validateUser's objectType parameter is now renamed to parentType. And it takes the
      original composite type instead of the GraphQLObjectType instance. Now it can be
      GraphQLInterfaceType as well.
    • validateUser's current parameters are now;
    export type ValidateUserFnParams<UserType> = {
      /** The user object. */
    
      /** The field node from the operation that is being validated. */
      fieldNode: FieldNode
      /** The parent type which has the field that is being validated. */
      parentType: GraphQLObjectType | GraphQLInterfaceType
      /** The auth directive arguments for the type */
      typeAuthArgs?: Record<string, any>
      /** The directives for the type */
      typeDirectives?: ReturnType<typeof getDirectiveExtensions>
      /** Scopes that type requires */
      typeScopes?: string[][]
      /** Policies that type requires */
      typePolicies?: string[][]
      /** The object field */
      field: GraphQLField<any, any>
      /** The auth directive arguments for the field */
      fieldAuthArgs?: Record<string, any>
      /** The directives for the field */
      fieldDirectives?: ReturnType<typeof getDirectiveExtensions>
      /** Scopes that field requires */
      fieldScopes?: string[][]
      /** Policies that field requires */
      fieldPolicies?: string[][]
      /** Extracted scopes from the user object */
      userScopes: string[]
      /** Policies for the user */
      userPolicies: string[]
      /** The args passed to the execution function (including operation context and variables) **/
      executionArgs: ExecutionArgs
      /** Resolve path */
      path: ReadonlyArray<string | number>
    }
    • New directives for role-based auth are added @requiresScopes and @policy for more granular
      control over the auth logic.
    directive @requiresScopes(scopes: [String!]!) on OBJECT | INTERFACE | FIELD_DEFINITION
    
    directive @policy(policy: String!) on OBJECT | INTERFACE | FIELD_DEFINITION

    Check README for more information.

Patch Changes

August 26, 2024

26 Aug 10:44
e606ae6
Compare
Choose a tag to compare

@envelop/extended-validation@4.1.0

Minor Changes

  • #2281
    70d4d7a
    Thanks @UserType;! - Refactor Generic Auth plugin;

    • [BREAKING] - Now @auth directive is renamed to @authenticated. If you want to keep the old
      name you can configure the plugin to use the old name.
    useGenericAuth({
      // ...
      authDirectiveName: 'auth'
    })
    • [BREAKING] - Now directiveOrExtensionFieldName is renamed to authDirectiveName.
    useGenericAuth({
      // ...
    - directiveOrExtensionFieldName: 'auth',
    + authDirectiveName: 'auth',
    });
    • Now auth directives support OBJECT and INTERFACE locations, so you can use the auth
      directive on types as well.
    directive @authenticated on OBJECT | INTERFACE
    
    type User @authenticated {
      id: ID!
      name: String!
    }
    • validateUser function does not receive fieldAuthDirectiveNode and fieldAuthExtension
      anymore. Instead, it takes fieldAuthArgs which is an object that contains the arguments of the
      auth directive or extension. So you don't need to parse the arguments manually anymore.
    const validateUser: ValidateUserFn = params => {
      if (!params.fieldAuthArgs.roles.includes('admin')) {
        return createUnauthorizedError(params)
      }
    }
    • validateUser's objectType parameter is now renamed to parentType. And it takes the
      original composite type instead of the GraphQLObjectType instance. Now it can be
      GraphQLInterfaceType as well.
    • validateUser's current parameters are now;
    export type ValidateUserFnParams<UserType> = {
      /** The user object. */
    
      /** The field node from the operation that is being validated. */
      fieldNode: FieldNode
      /** The parent type which has the field that is being validated. */
      parentType: GraphQLObjectType | GraphQLInterfaceType
      /** The auth directive arguments for the type */
      typeAuthArgs?: Record<string, any>
      /** The directives for the type */
      typeDirectives?: ReturnType<typeof getDirectiveExtensions>
      /** Scopes that type requires */
      typeScopes?: string[][]
      /** Policies that type requires */
      typePolicies?: string[][]
      /** The object field */
      field: GraphQLField<any, any>
      /** The auth directive arguments for the field */
      fieldAuthArgs?: Record<string, any>
      /** The directives for the field */
      fieldDirectives?: ReturnType<typeof getDirectiveExtensions>
      /** Scopes that field requires */
      fieldScopes?: string[][]
      /** Policies that field requires */
      fieldPolicies?: string[][]
      /** Extracted scopes from the user object */
      userScopes: string[]
      /** Policies for the user */
      userPolicies: string[]
      /** The args passed to the execution function (including operation context and variables) **/
      executionArgs: ExecutionArgs
      /** Resolve path */
      path: ReadonlyArray<string | number>
    }
    • New directives for role-based auth are added @requiresScopes and @policy for more granular
      control over the auth logic.
    directive @requiresScopes(scopes: [String!]!) on OBJECT | INTERFACE | FIELD_DEFINITION
    
    directive @policy(policy: String!) on OBJECT | INTERFACE | FIELD_DEFINITION

    Check README for more information.

August 20, 2024

20 Aug 17:13
04cf1b0
Compare
Choose a tag to compare

@envelop/core@5.0.2

Patch Changes

@envelop/on-resolve@4.1.1

Patch Changes

  • #2292
    c3dd2c3
    Thanks @ardatan! - Refactor the plugin to avoid extra promises with
    `mapMaybePromise`

  • Updated dependencies
    [c3dd2c3]:

    • @envelop/core@5.0.2

@envelop/rate-limiter@6.2.0

Minor Changes

  • #2292
    c3dd2c3
    Thanks @ardatan! - Now you can define a custom string interpolation
    function to be used in the rate limit message. This is useful when you want to include dynamic
    values in the message.

    useRateLimiter({
      configByField: [
        {
          type: 'Query',
          field: 'search', // You can also use glob patterns
          max: 10,
          window: '1m',
          message:
            'My custom message with interpolated values: ${args.searchTerm} and ${context.user.id}'
        }
      ],
      interpolateMessage: (message, args, context) => {
        return message.replace(/\${(.*?)}/g, (_, key) => {
          return key.split('.').reduce((acc, part) => acc[part], { args, context })
        })
      }
    })
  • #2292
    c3dd2c3
    Thanks @ardatan! - New directive SDL;

    directive @rateLimit(
      max: Int
      window: String
      message: String
      identityArgs: [String]
      arrayLengthField: String
      readOnly: Boolean
      uncountRejected: Boolean
    ) on FIELD_DEFINITION
  • #2292
    c3dd2c3
    Thanks @ardatan! - Programmatic API to define rate limit
    configuration in addition to directives

    useRateLimiter({
      configByField: [
        {
          type: 'Query',
          field: 'search', // You can also use glob patterns
          max: 10,
          window: '1m'
        }
      ]
    })

Patch Changes