Skip to content

Releases: n1ru4l/envelop

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

August 13, 2024

13 Aug 09:25
b10a670
Compare
Choose a tag to compare

@envelop/prometheus@11.0.0

Major Changes

  • #2270
    73eb69f
    Thanks @EmrysMyrddin! - Breaking Change: Rename all metrics
    options to their actual metric name to avoid confusion.

    All metric options have been moved under a mandatory metrics key, and the name of each options
    have been renamed to match the default metric name.

    The plugin option argument is also now mandatory.

    export const serveConfig = defineConfig({
      plugins: pluginCtx => [
        usePrometheus({
          ...pluginCtx,
    
          // Enable all available metrics
    
    -     requestSummary: true,
    -     parse: true,
    -     validate: true,
    -     contextBuilding: true,
    -     execute: true,
    -     subscribe: true,
    -     errors: true,
    -     deprecatedFields: true,
    -     requestTotalDuration: true,
    -     schemaChangeCount: true,
    
          // Warning: enabling resolvers level metrics will introduce significant overhead
    -     resolvers: true,
    +     metrics: {
    +       graphql_envelop_request_time_summary: true,
    +       graphql_envelop_phase_parse: true,
    +       graphql_envelop_phase_validate: true,
    +       graphql_envelop_phase_context: true,
    +       graphql_envelop_phase_execute: true,
    +       graphql_envelop_phase_subscribe: true,
    +       graphql_envelop_error_result: true,
    +       graphql_envelop_deprecated_field: true,
    +       graphql_envelop_request_duration: true,
    +       graphql_envelop_schema_change: true,
    
            // Warning: enabling resolvers level metrics will introduce significant overhead
    +       graphql_envelop_execute_resolver: true,
    +     }
        })
      ]
    })

Minor Changes

  • #2270
    73eb69f
    Thanks @EmrysMyrddin! - Add missing labels path and phase
    of graphql_envelop_error_result metric to the configuration.

July 16, 2024

16 Jul 15:11
737f250
Compare
Choose a tag to compare

@envelop/response-cache@6.2.1

Patch Changes

  • #2266
    389d5f6
    Thanks @EmrysMyrddin! - The plugin now try to reduce the size
    of the resulting query by not adding a __typename aliased selection if __typename is already
    selected.