Releases: n1ru4l/envelop
December 12, 2024
@envelop/sentry@12.0.0
Major Changes
-
#2323
2993773
Thanks @Karibash! - Make it possible to get the active span in the
GraphQL resolverBreaking 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
@envelop/generic-auth@8.0.1
Patch Changes
-
#2347
8b7e657
Thanks @ardatan! - dependencies updates:- Added dependency
@graphql-tools/executor@^1.3.6
↗︎
(todependencies
)
- Added dependency
-
#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
- #2337
931a6da
Thanks @renovate! - dependencies updates:- Updated dependency
@whatwg-node/fetch@^0.10.0
↗︎
(from^0.9.0
, independencies
)
- Updated dependency
@envelop/sentry@11.0.0
Major Changes
-
#2335
073774c
Thanks @EmrysMyrddin! - Fix: Update code to better feat the new
Sentry v8 APIBreaking Change:
startTransaction
option has been removed.forceTransaction
option has been added, disabled by default.
@envelop/statsd@5.0.1
Patch Changes
- #1709
e6aac57
Thanks @renovate! - dependencies updates:- Updated dependency
hot-shots@^10.0.0
↗︎
(from^8.0.0 || ^9.0.0
, inpeerDependencies
)
- Updated dependency
November 26, 2024
@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
@envelop/graphql-jit@8.0.4
Patch Changes
- #2327
b7dc96a
Thanks @renovate! - dependencies updates:- Updated dependency
graphql-jit@0.8.7
↗︎
(from0.8.6
, independencies
)
- Updated dependency
@envelop/rate-limiter@6.2.1
Patch Changes
-
#2330
b1210bc
Thanks @enisdenjo! - dependencies updates:- Added dependency
graphql-middleware@^6.1.35
↗︎
(todependencies
)
- Added dependency
-
#2330
b1210bc
Thanks @enisdenjo! - Add graphql-middleware as a dependency
October 10, 2024
October 09, 2024
October 09, 2024
@envelop/immediate-introspection@4.0.0
Major Changes
-
#2277
9f65fcb
Thanks @trixobird! - dependencies updates:- Updated dependency
@sentry/node@^8.0.0
↗︎ (from
^6 || ^7
, inpeerDependencies
)
- Updated dependency
@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
-
#2277
9f65fcb
Thanks @trixobird! - dependencies updates:- Updated dependency
@sentry/node@^8.0.0
↗︎ (from
^6 || ^7
, inpeerDependencies
)
- Updated dependency
August 26, 2024
@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 toauthDirectiveName
.
useGenericAuth({ // ... - directiveOrExtensionFieldName: 'auth', + authDirectiveName: 'auth', });
- Now auth directives support
OBJECT
andINTERFACE
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 receivefieldAuthDirectiveNode
andfieldAuthExtension
anymore. Instead, it takesfieldAuthArgs
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
'sobjectType
parameter is now renamed toparentType
. And it takes the
original composite type instead of theGraphQLObjectType
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.
- [BREAKING] - Now
Patch Changes
- #2281
70d4d7a
Thanks @ardatan! - dependencies updates:- Updated dependency
@graphql-tools/utils@^10.5.1
↗︎
(from^10.0.6
, independencies
)
- Updated dependency
- Updated dependencies
[70d4d7a
]:- @envelop/extended-validation@4.1.0
August 26, 2024
@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 toauthDirectiveName
.
useGenericAuth({ // ... - directiveOrExtensionFieldName: 'auth', + authDirectiveName: 'auth', });
- Now auth directives support
OBJECT
andINTERFACE
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 receivefieldAuthDirectiveNode
andfieldAuthExtension
anymore. Instead, it takesfieldAuthArgs
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
'sobjectType
parameter is now renamed toparentType
. And it takes the
original composite type instead of theGraphQLObjectType
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.
- [BREAKING] - Now
August 20, 2024
@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 directivesuseRateLimiter({ configByField: [ { type: 'Query', field: 'search', // You can also use glob patterns max: 10, window: '1m' } ] })
Patch Changes
-
#2292
c3dd2c3
Thanks @ardatan! - dependencies updates:- Updated dependency
graphql-rate-limit@^3.3.0
↗︎
(from3.3.0
, independencies
) - Added dependency
@graphql-tools/utils@^10.5.4
↗︎
(todependencies
) - Added dependency
minimatch@^10.0.1
↗︎ (to
dependencies
)
- Updated dependency
-
#2276
ba368ba
Thanks @deggertsen! - useRateLimiter will now accept all options
available to graphql-rate-limit getGraphQLRateLimiter function so that they are usable. -
Updated dependencies
[c3dd2c3
,
c3dd2c3
]:- @envelop/on-resolve@4.1.1
- @envelop/core@5.0.2