From 8b7e657997cff286db145502d6d86cf7bc956cd0 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Wed, 11 Dec 2024 13:39:45 +0300 Subject: [PATCH] fix(generic-auth): handle default values in variable defs correctly (#2347) * fix(generic-auth): handle default values in variable defs correctly * Make it version agnostic * chore(dependencies): updated changesets for modified dependencies * Fix CI' * Fix workflow name * Go * Fix * Remove ESM step * Run Redis tests only with v16 --------- Co-authored-by: github-actions[bot] --- ...@envelop_generic-auth-2347-dependencies.md | 5 + .changeset/proud-tomatoes-film.md | 32 ++++++ .github/workflows/tests.yml | 72 ++---------- benchmark/app.js | 3 +- package.json | 1 - packages/plugins/generic-auth/package.json | 1 + packages/plugins/generic-auth/src/index.ts | 22 +++- .../tests/use-generic-auth.spec.ts | 26 +++++ .../plugins/response-cache-redis/package.json | 1 + .../test/response-redis-cache.spec.ts | 5 +- pnpm-lock.yaml | 105 +++++++++++++++++- 11 files changed, 200 insertions(+), 73 deletions(-) create mode 100644 .changeset/@envelop_generic-auth-2347-dependencies.md create mode 100644 .changeset/proud-tomatoes-film.md diff --git a/.changeset/@envelop_generic-auth-2347-dependencies.md b/.changeset/@envelop_generic-auth-2347-dependencies.md new file mode 100644 index 0000000000..bfd8bab020 --- /dev/null +++ b/.changeset/@envelop_generic-auth-2347-dependencies.md @@ -0,0 +1,5 @@ +--- +"@envelop/generic-auth": patch +--- +dependencies updates: + - Added dependency [`@graphql-tools/executor@^1.3.6` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.3.6) (to `dependencies`) diff --git a/.changeset/proud-tomatoes-film.md b/.changeset/proud-tomatoes-film.md new file mode 100644 index 0000000000..3a80aa29b5 --- /dev/null +++ b/.changeset/proud-tomatoes-film.md @@ -0,0 +1,32 @@ +--- +'@envelop/generic-auth': patch +--- + +Handle operations with \`@include\` and \`@skip\` correctly when they have default values in the +operation definition + +```ts +{ + query: /* GraphQL */ ` + query MyQuery($include: Boolean = true) { + field @include(if: $include) + } + `, + variables: {} +} +``` + +should be considered same as + +```ts +{ + query: /* GraphQL */ ` + query MyQuery($include: Boolean!) { + field @include(if: $include) + } + `, + variables: { + include: true + } +} +``` \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6af9c6304b..2eb1dec252 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,26 +7,8 @@ on: pull_request: jobs: - prettier: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup env - uses: the-guild-org/shared-config/setup@v1 - - name: Lint Prettier - run: pnpm run lint:prettier - - lint: - name: Lint - uses: the-guild-org/shared-config/.github/workflows/lint.yml@v1 - with: - script: pnpm run ci:lint && pnpm run lint - secrets: - githubToken: ${{ secrets.GITHUB_TOKEN }} - - build: - name: build / graphql v${{matrix.graphql_version}} + check: + name: check / graphql v${{matrix.graphql_version}} runs-on: ubuntu-latest strategy: matrix: @@ -36,41 +18,22 @@ jobs: uses: actions/checkout@v4 - name: Setup env uses: the-guild-org/shared-config/setup@v1 + - name: Format + run: pnpm run lint:prettier + - name: Lint + run: pnpm run ci:lint && pnpm run lint - name: Use GraphQL v${{matrix.graphql_version}} run: node ./scripts/match-graphql.js ${{matrix.graphql_version}} - name: Install Dependencies using pnpm run: pnpm install --no-frozen-lockfile && git checkout pnpm-lock.yaml - name: Build run: pnpm run ts:check + - name: Test ESM & CJS exports integrity + run: pnpm bob check unit: - name: Unit Test - runs-on: ${{matrix.os}} - strategy: - matrix: - os: [ubuntu-latest] # remove windows to speed up the tests - steps: - - name: Checkout Master - uses: actions/checkout@v4 - - name: Setup env - uses: the-guild-org/shared-config/setup@v1 - - name: Install Dependencies - run: pnpm install --no-frozen-lockfile && git checkout pnpm-lock.yaml - - name: Cache Jest - uses: actions/cache@v4 - with: - path: .cache/jest - key: - ${{ runner.os }}-${{matrix.node-version}}-${{matrix.graphql_version}}-jest-${{ - hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('patches/*.patch') }} - - name: Test - run: pnpm run test - env: - CI: true - - core: name: - Core Test / ${{matrix.os}} / node v${{matrix.node-version}} / graphql + Unit Test / ${{matrix.os}} / node v${{matrix.node-version}} / graphql v${{matrix.graphql_version}} runs-on: ${{matrix.os}} strategy: @@ -94,20 +57,7 @@ jobs: key: ${{ runner.os }}-${{matrix.node-version}}-${{matrix.graphql_version}}-jest-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('patches/*.patch') }} - - name: Test Core - run: pnpm run test:core --ci + - name: Test + run: pnpm run test --ci env: CI: true - - test_esm: - name: esm - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup env - uses: the-guild-org/shared-config/setup@v1 - - name: Build Packages - run: pnpm run build - - name: Test ESM & CJS exports integrity - run: pnpm bob check diff --git a/benchmark/app.js b/benchmark/app.js index 8c459627f2..f38e1e9c61 100644 --- a/benchmark/app.js +++ b/benchmark/app.js @@ -2,7 +2,6 @@ const { makeExecutableSchema } = require('@graphql-tools/schema'); const { envelop, useSchema, useEngine } = require('@envelop/core'); const { useParserCache } = require('@envelop/parser-cache'); -const { usePrometheus } = require('@envelop/prometheus'); const { useGraphQlJit } = require('@envelop/graphql-jit'); const { useValidationCache } = require('@envelop/validation-cache'); const { fastify } = require('fastify'); @@ -143,7 +142,7 @@ app.route({ }, }); -app.listen(3000, (error, address) => { +app.listen({ port: 3000 }, (error, address) => { if (error) { console.error(error); process.exit(1); diff --git a/package.json b/package.json index 021bb61aa0..691e85c23c 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "release": "pnpm build && changeset publish", "test": "NODE_OPTIONS=--experimental-vm-modules jest", "test:ci": "jest --coverage", - "test:core": "jest ./packages/core --coverage", "ts:check": "tsc --noEmit" }, "devDependencies": { diff --git a/packages/plugins/generic-auth/package.json b/packages/plugins/generic-auth/package.json index 3bd3d4b51a..e05ca71989 100644 --- a/packages/plugins/generic-auth/package.json +++ b/packages/plugins/generic-auth/package.json @@ -52,6 +52,7 @@ }, "dependencies": { "@envelop/extended-validation": "^4.1.0", + "@graphql-tools/executor": "^1.3.6", "@graphql-tools/utils": "^10.5.1", "tslib": "^2.5.0" }, diff --git a/packages/plugins/generic-auth/src/index.ts b/packages/plugins/generic-auth/src/index.ts index 3a43657e34..b87eba1498 100644 --- a/packages/plugins/generic-auth/src/index.ts +++ b/packages/plugins/generic-auth/src/index.ts @@ -19,6 +19,7 @@ import { } from 'graphql'; import { DefaultContext, Maybe, Plugin, PromiseOrValue } from '@envelop/core'; import { useExtendedValidation } from '@envelop/extended-validation'; +import { getVariableValues } from '@graphql-tools/executor'; import { createGraphQLError, getDefinedRootType, @@ -318,6 +319,22 @@ export const useGenericAuth = < function AuthorizationExtendedValidationRule(context, args) { const user = (args.contextValue as any)[contextFieldName]; + const schema = context.getSchema(); + const operationAST = getOperationAST(args.document, args.operationName); + const variableDefinitions = operationAST?.variableDefinitions; + let variableValues: typeof args.variableValues | undefined; + if (variableDefinitions?.length) { + const { coerced } = getVariableValues( + schema, + variableDefinitions, + args.variableValues || {}, + ); + variableValues = coerced; + } else { + variableValues = args.variableValues; + } + const operationType = operationAST?.operation ?? ('query' as OperationTypeNode); + const handleField = ( { node: fieldNode, @@ -337,7 +354,6 @@ export const useGenericAuth = < return; } - const schema = context.getSchema(); // @ts-expect-error - Fix this const typeDirectives = parentType && getDirectiveExtensions(parentType, schema); const typeAuthArgs = typeDirectives[authDirectiveName]?.[0]; @@ -354,8 +370,6 @@ export const useGenericAuth = < const resolvePath: (string | number)[] = []; let curr: any = args.document; - const operationAST = getOperationAST(args.document, args.operationName); - const operationType = operationAST?.operation ?? ('query' as OperationTypeNode); let currType: GraphQLOutputType | undefined | null = getDefinedRootType( schema, operationType, @@ -408,7 +422,7 @@ export const useGenericAuth = < return { Field(node, key, parent, path, ancestors) { - if (!shouldIncludeNode(args.variableValues, node)) { + if (variableValues && !shouldIncludeNode(variableValues, node)) { return; } diff --git a/packages/plugins/generic-auth/tests/use-generic-auth.spec.ts b/packages/plugins/generic-auth/tests/use-generic-auth.spec.ts index dd339f075b..2ae5ca4683 100644 --- a/packages/plugins/generic-auth/tests/use-generic-auth.spec.ts +++ b/packages/plugins/generic-auth/tests/use-generic-auth.spec.ts @@ -519,5 +519,31 @@ describe('useGenericAuth', () => { public: 'public', }); }); + it('should not validate fields with @include and @skip directives with default values', async () => { + const testInstance = createTestkit( + [ + useGenericAuth({ + mode: 'protect-granular', + resolveUserFn: invalidresolveUserFn, + }), + ], + schemaWithDirective, + ); + + const result = await testInstance.execute(/* GraphQL */ ` + query ($skip: Boolean! = true, $include: Boolean! = false) { + public + p1: protected @skip(if: $skip) + p2: protected @skip(if: true) + p3: protected @include(if: false) + p4: protected @include(if: $include) + } + `); + assertSingleExecutionValue(result); + expect(result.errors).toBeUndefined(); + expect(result.data).toEqual({ + public: 'public', + }); + }); }); }); diff --git a/packages/plugins/response-cache-redis/package.json b/packages/plugins/response-cache-redis/package.json index 0e27df05b8..4c88cbd6a7 100644 --- a/packages/plugins/response-cache-redis/package.json +++ b/packages/plugins/response-cache-redis/package.json @@ -56,6 +56,7 @@ "@envelop/core": "workspace:^", "@graphql-tools/schema": "10.0.11", "@types/ioredis": "4.28.10", + "graphql": "16.9.0", "ioredis-mock": "5.9.1", "typescript": "5.1.3" }, diff --git a/packages/plugins/response-cache-redis/test/response-redis-cache.spec.ts b/packages/plugins/response-cache-redis/test/response-redis-cache.spec.ts index 77a849d908..49c46fd0f0 100644 --- a/packages/plugins/response-cache-redis/test/response-redis-cache.spec.ts +++ b/packages/plugins/response-cache-redis/test/response-redis-cache.spec.ts @@ -1,3 +1,4 @@ +import { versionInfo } from 'graphql'; import Redis from 'ioredis'; import { useResponseCache } from '@envelop/response-cache'; import { createTestkit } from '@envelop/testing'; @@ -10,7 +11,9 @@ import { jest.mock('ioredis', () => require('ioredis-mock/jest')); -describe('useResponseCache with Redis cache', () => { +const describeIf = (condition: boolean) => (condition ? describe : describe.skip); + +describeIf(versionInfo.major >= 16)('useResponseCache with Redis cache', () => { const redis = new Redis(); const cache = createRedisCache({ redis }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24b708913f..3ba96783a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -958,6 +958,9 @@ importers: '@envelop/extended-validation': specifier: ^4.1.0 version: 4.1.0(@envelop/core@packages+core+dist)(graphql@16.6.0) + '@graphql-tools/executor': + specifier: ^1.3.6 + version: 1.3.6(graphql@16.6.0) '@graphql-tools/utils': specifier: ^10.5.1 version: 10.5.4(graphql@16.6.0) @@ -1450,6 +1453,9 @@ importers: '@types/ioredis': specifier: 4.28.10 version: 4.28.10 + graphql: + specifier: 16.6.0 + version: 16.6.0 ioredis-mock: specifier: 5.9.1 version: 5.9.1(ioredis@4.27.9)(redis-commands@1.7.0) @@ -3174,6 +3180,12 @@ packages: peerDependencies: graphql: 16.6.0 + '@graphql-tools/executor@1.3.6': + resolution: {integrity: sha512-ZmWsWdUhTez2b4w9NkmL4wpPb8n8WZmLOMIPTXH2A2yEe2nHrK/tk653JZXvZFtx2HrBIcoZD4Fe/STYWIR74Q==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: 16.6.0 + '@graphql-tools/merge@8.3.1': resolution: {integrity: sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg==} peerDependencies: @@ -5904,10 +5916,18 @@ packages: resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} engines: {node: '>=0.10.0'} + call-bind-apply-helpers@1.0.1: + resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} + engines: {node: '>= 0.4'} + call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -6545,6 +6565,15 @@ packages: supports-color: optional: true + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decode-named-character-reference@1.0.1: resolution: {integrity: sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==} @@ -6703,6 +6732,10 @@ packages: resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} engines: {node: '>=4'} + dunder-proto@1.0.0: + resolution: {integrity: sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==} + engines: {node: '>= 0.4'} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -6813,6 +6846,10 @@ packages: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} @@ -7474,6 +7511,10 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-intrinsic@1.2.5: + resolution: {integrity: sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==} + engines: {node: '>= 0.4'} + get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} @@ -7591,6 +7632,10 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -7711,6 +7756,10 @@ packages: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} @@ -14124,7 +14173,7 @@ snapshots: '@graphql-tools/delegate@10.0.3(graphql@16.6.0)': dependencies: '@graphql-tools/batch-execute': 9.0.2(graphql@16.6.0) - '@graphql-tools/executor': 1.3.1(graphql@16.6.0) + '@graphql-tools/executor': 1.3.6(graphql@16.6.0) '@graphql-tools/schema': 10.0.11(graphql@16.6.0) '@graphql-tools/utils': 10.6.2(graphql@16.6.0) dataloader: 2.2.2 @@ -14150,6 +14199,15 @@ snapshots: tslib: 2.6.2 value-or-promise: 1.0.12 + '@graphql-tools/executor@1.3.6(graphql@16.6.0)': + dependencies: + '@graphql-tools/utils': 10.6.2(graphql@16.6.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.6.0) + '@repeaterjs/repeater': 3.0.5 + graphql: 16.6.0 + tslib: 2.8.1 + value-or-promise: 1.0.12 + '@graphql-tools/merge@8.3.1(graphql@16.6.0)': dependencies: '@graphql-tools/utils': 8.9.0(graphql@16.6.0) @@ -17654,6 +17712,11 @@ snapshots: union-value: 1.0.1 unset-value: 1.0.0 + call-bind-apply-helpers@1.0.1: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -17662,6 +17725,13 @@ snapshots: get-intrinsic: 1.2.4 set-function-length: 1.2.2 + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-define-property: 1.0.1 + get-intrinsic: 1.2.5 + set-function-length: 1.2.2 + callsites@3.1.0: {} camel-case@4.1.2: @@ -18351,6 +18421,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.0: + dependencies: + ms: 2.1.3 + decode-named-character-reference@1.0.1: dependencies: character-entities: 2.0.1 @@ -18496,6 +18570,12 @@ snapshots: dset@3.1.2: {} + dunder-proto@1.0.0: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + duplexer@0.1.2: {} duplexify@3.7.1: @@ -18667,6 +18747,8 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + es-define-property@1.0.1: {} + es-errors@1.3.0: {} es-get-iterator@1.1.2: @@ -19637,6 +19719,17 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-intrinsic@1.2.5: + dependencies: + call-bind-apply-helpers: 1.0.1 + dunder-proto: 1.0.0 + es-define-property: 1.0.1 + es-errors: 1.3.0 + function-bind: 1.1.2 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + get-package-type@0.1.0: {} get-port@3.2.0: {} @@ -19806,6 +19899,8 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + gopd@1.2.0: {} + graceful-fs@4.2.11: {} graphemer@1.4.0: {} @@ -19926,6 +20021,8 @@ snapshots: has-symbols@1.0.3: {} + has-symbols@1.1.0: {} + has-tostringtag@1.0.0: dependencies: has-symbols: 1.0.3 @@ -20348,7 +20445,7 @@ snapshots: ioredis@4.28.5: dependencies: cluster-key-slot: 1.1.2 - debug: 4.3.7 + debug: 4.4.0 denque: 1.5.1 lodash.defaults: 4.2.0 lodash.flatten: 4.4.0 @@ -22601,9 +22698,9 @@ snapshots: object.assign@4.1.5: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - has-symbols: 1.0.3 + has-symbols: 1.1.0 object-keys: 1.1.1 object.fromentries@2.0.7: