Releases: n1ru4l/envelop
October 10, 2024
@envelop/[email protected]
Patch Changes
October 09, 2024
October 09, 2024
@envelop/[email protected]
Major Changes
-
#2277
9f65fcb
Thanks @trixobird! - dependencies updates:- Updated dependency
@sentry/node@^8.0.0
↗︎ (from
^6 || ^7
, inpeerDependencies
)
- Updated dependency
@envelop/[email protected]
Patch Changes
- #2309
4fd5917
Thanks @n1ru4l! - Strip__responseCacheId
and
__responseCacheTypeName
from incremental delivery execution result.
@envelop/[email protected]
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/[email protected]
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/[email protected]
August 26, 2024
@envelop/[email protected]
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/[email protected]
Patch Changes
@envelop/[email protected]
Patch Changes
-
#2292
c3dd2c3
Thanks @ardatan! - Refactor the plugin to avoid extra promises with
`mapMaybePromise` -
Updated dependencies
[c3dd2c3
]:- @envelop/[email protected]
@envelop/[email protected]
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/[email protected]
- @envelop/[email protected]
August 13, 2024
@envelop/[email protected]
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 labelspath
andphase
ofgraphql_envelop_error_result
metric to the configuration.
July 16, 2024
@envelop/[email protected]
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.
May 30, 2024
@envelop/[email protected]
Minor Changes
- #2238
430ee7d
Thanks @ardatan! - Accept a factory function tocache
that takes
the context and returns the cache implementation
@envelop/[email protected]
Minor Changes
-
#2238
430ee7d
Thanks @ardatan! - BREAKING: Now the cache implementation does not
require theExecutionContext
orKVNamespace
instance but only the name of the namespaceimport { createSchema, createYoga, YogaInitialContext } from 'graphql-yoga' import { useResponseCache } from '@envelop/response-cache' import { createKvCache } from '@envelop/response-cache-cloudflare-kv' import { resolvers } from './graphql-schema/resolvers.generated' import { typeDefs } from './graphql-schema/typeDefs.generated' export type Env = { GRAPHQL_RESPONSE_CACHE: KVNamespace } const graphqlServer = createYoga<Env & ExecutionContext>({ schema: createSchema({ typeDefs, resolvers }), plugins: [ useResponseCache({ cache: createKvCache({ KVName: 'GRAPHQL_RESPONSE_CACHE', keyPrefix: 'graphql' // optional }), session: () => null, includeExtensionMetadata: true, ttl: 1000 * 10 // 10 seconds }) ] }) export default { fetch: graphqlServer }
Patch Changes
- Updated dependencies
[430ee7d
]:- @envelop/[email protected]
May 08, 2024
@envelop/[email protected]
Patch Changes
@envelop/[email protected]
Patch Changes
-
#2218
75b73fb
Thanks @EmrysMyrddin! - dependencies updates:- Updated dependency
@opentelemetry/api@^1.8.0
↗︎
(from^1.0.0
, independencies
)
- Updated dependency
-
Updated dependencies
[dc1222f
]:- @envelop/[email protected]
@envelop/[email protected]
Major Changes
-
#2217
7ac1d3c
Thanks @EmrysMyrddin! - Adds a cache for metrics definition
(Summary, Histogram and Counter).Fixes an issue preventing this plugin to be initialized multiple times, leading to metrics
duplication error (ardatan/graphql-mesh#6545).Behavior Breaking Change:
Due to Prometheus client API limitations, a metric is only defined once for a given registry. This
means that if the configuration of the metrics, it will be silently ignored on plugin
re-initialization.This is to avoid potential loss of metrics data produced between the plugin re-initialization and
the last pull by the prometheus agent.If you need to be sure metrics configuration is up to date after a plugin re-initialization, you
can either:- restart the whole node process instead of just recreating a graphql server at runtime
- clear the registry using
registry.clear()
before plugin re-initialization:function usePrometheusWithReset() { registry.clear() return usePrometheus({ ... }) }
- use a new registry for each plugin instance:
function usePrometheusWithRegistry() { const registry = new Registry() return usePrometheus({ registry, ... }) }
Keep in mind that this implies potential data loss in pull mode.
API Breaking Change:
To ensure metrics from being registered multiple times on the same registry, the signature of
createHistogram
,createSummary
andcreateCounter
have been changed to now include the
registry as a mandatory parameter.If you were customizing metrics parameters, you will need to update the metric definitions
usePrometheus({ execute: createHistogram({ + registry: registry histogram: new Histogram({ name: 'my_custom_name', help: 'HELP ME', labelNames: ['opText'] as const, - registers: [registry], }), fillLabelsFn: () => {} }), requestCount: createCounter({ + registry: registry histogram: new Histogram({ name: 'my_custom_name', help: 'HELP ME', labelNames: ['opText'] as const, - registers: [registry], }), fillLabelsFn: () => {} }), requestSummary: createSummary({ + registry: registry histogram: new Histogram({ name: 'my_custom_name', help: 'HELP ME', labelNames: ['opText'] as const, - registers: [registry], }), fillLabelsFn: () => {} }), })
Patch Changes
- Updated dependencies
[dc1222f
]:- @envelop/[email protected]