From da622286e2da9c27c45165af0c326c80f024a9fe Mon Sep 17 00:00:00 2001 From: Vijay Budhram Date: Mon, 30 Mar 2026 13:06:28 -0400 Subject: [PATCH] chore(admin-server): remove dead GraphQL code, allowlist config, and gql:allowlist build steps Remove unused GraphQL decorators, shared GQL utilities, allowlist generation config, and gql:allowlist calls from build/start scripts. --- _dev/docker/mono/build.sh | 1 - _dev/pm2/start.sh | 4 - configs/gql/allowlist/gql-playground.json | 3 - nx.json | 13 +- package.json | 2 - .../scripts/start-services.sh | 2 + .../tests/admin/adminPanel.spec.ts | 70 ++++ packages/fxa-admin-panel/package.json | 1 - packages/fxa-admin-panel/pm2.config.js | 8 - packages/fxa-admin-server/package.json | 3 +- packages/fxa-admin-server/src/config/index.ts | 17 - .../rest/model/account-delete-task.model.ts | 8 - .../src/rest/model/account-events.model.ts | 8 - .../src/rest/model/account-reset.model.ts | 4 - .../src/rest/model/account.model.ts | 23 -- .../src/rest/model/attached-clients.model.ts | 19 - .../src/rest/model/attached-sessions.model.ts | 11 - .../src/rest/model/backup-code.model.ts | 4 - .../src/rest/model/block-status.model.ts | 11 - .../src/rest/model/cart.model.ts | 22 - .../src/rest/model/email-bounces.model.ts | 15 - .../src/rest/model/emails.model.ts | 6 - .../src/rest/model/linked-account.model.ts | 10 - .../src/rest/model/location.model.ts | 7 - .../src/rest/model/moz-subscription.model.ts | 16 - .../src/rest/model/recovery-keys.model.ts | 5 - .../src/rest/model/recovery-phone.model.ts | 5 - .../src/rest/model/relying-party.model.ts | 28 -- .../src/rest/model/security-events.model.ts | 14 - .../src/rest/model/totp.model.ts | 5 - .../nestjs/gql/example-allowlist.json | 3 - .../nestjs/gql/gql-allowlist.spec.ts | 47 --- .../fxa-shared/nestjs/gql/gql-allowlist.ts | 80 ---- .../fxa-shared/nestjs/sentry/reporting.ts | 44 -- yarn.lock | 389 +----------------- 35 files changed, 84 insertions(+), 824 deletions(-) delete mode 100644 configs/gql/allowlist/gql-playground.json create mode 100644 packages/functional-tests/tests/admin/adminPanel.spec.ts delete mode 100644 packages/fxa-shared/nestjs/gql/example-allowlist.json delete mode 100644 packages/fxa-shared/nestjs/gql/gql-allowlist.spec.ts delete mode 100644 packages/fxa-shared/nestjs/gql/gql-allowlist.ts diff --git a/_dev/docker/mono/build.sh b/_dev/docker/mono/build.sh index 98c698d588c..3620cea6a9c 100755 --- a/_dev/docker/mono/build.sh +++ b/_dev/docker/mono/build.sh @@ -35,7 +35,6 @@ done # `npx yarn` because `npm i -g yarn` needs sudo npx yarn install -npx yarn gql:allowlist NODE_OPTIONS="--max-old-space-size=7168" CHOKIDAR_USEPOLLING=true SKIP_PREFLIGHT_CHECK=true BUILD_TARGETS=stage,prod,dev npx nx run-many -t build --all --verbose --skip-nx-cache # This will reduce packages to only production dependencies diff --git a/_dev/pm2/start.sh b/_dev/pm2/start.sh index 9a7a3b69254..fa1778e805a 100755 --- a/_dev/pm2/start.sh +++ b/_dev/pm2/start.sh @@ -6,10 +6,6 @@ cd "$DIR/../.." # Make sure there is a common docker network fxa, so containers can # communicate with one another if needed _dev/pm2/create-docker-net.sh fxa - -# Searches for and extracts gql queries from code -yarn gql:allowlist - pm2 start _dev/pm2/infrastructure.config.js echo "waiting for containers to start" diff --git a/configs/gql/allowlist/gql-playground.json b/configs/gql/allowlist/gql-playground.json deleted file mode 100644 index d6002616731..00000000000 --- a/configs/gql/allowlist/gql-playground.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "query xIntrospectionQuery {\n __schema {\n queryType {\n name\n }\n mutationType {\n name\n }\n subscriptionType {\n name\n }\n types {\n ...FullType\n }\n directives {\n name\n description\n locations\n args {\n ...InputValue\n }\n }\n }\n}\n\nfragment FullType on __Type {\n kind\n name\n description\n fields(includeDeprecated: true) {\n name\n description\n args {\n ...InputValue\n }\n type {\n ...TypeRef\n }\n isDeprecated\n deprecationReason\n }\n inputFields {\n ...InputValue\n }\n interfaces {\n ...TypeRef\n }\n enumValues(includeDeprecated: true) {\n name\n description\n isDeprecated\n deprecationReason\n }\n possibleTypes {\n ...TypeRef\n }\n}\n\nfragment InputValue on __InputValue {\n name\n description\n type {\n ...TypeRef\n }\n defaultValue\n}\n\nfragment TypeRef on __Type {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n }\n }\n }\n }\n }\n }\n }\n}\n": 1 -} diff --git a/nx.json b/nx.json index bb6ab3b8e4b..8c74865d903 100644 --- a/nx.json +++ b/nx.json @@ -32,24 +32,13 @@ "outputs": ["{projectRoot}/build", "{projectRoot}/dist"], "cache": true }, - "gql-copy": { - "dependsOn": [ - { - "projects": ["fxa-admin-panel"], - "target": "gql-extract" - } - ], - "inputs": ["typescript", "^typescript"], - "outputs": ["{projectRoot}/src/config/gql/allowlist"], - "cache": true - }, "lint": { "inputs": ["lint", "{workspaceRoot}/.eslintrc.json"], "outputs": ["{projectRoot}/.eslintcache"], "cache": true }, "prebuild": { - "dependsOn": ["gql-copy"], + "dependsOn": [], "inputs": [], "outputs": [ "{projectRoot}/public/locales", diff --git a/package.json b/package.json index eae120aec02..f7cf63c1e89 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "l10n:prime": "_scripts/l10n/prime.sh", "l10n:bundle": "_scripts/l10n/bundle.sh", "legal:clone": "_scripts/clone-legal-docs.sh", - "gql:allowlist": "nx run-many -t gql-extract && nx run-many -t gql-copy", "check:mysql": "_scripts/check-mysql.sh", "check:url": "_scripts/check-url.sh", "prepare": "husky", @@ -276,7 +275,6 @@ "mocha-multi": "^1.1.7", "nx": "21.2.4", "nx-cloud": "19.1.0", - "persistgraphql": "^0.3.11", "postcss": "8.5.0", "react-test-renderer": "^18.3.1", "reflect-metadata": "^0.2.1", diff --git a/packages/functional-tests/scripts/start-services.sh b/packages/functional-tests/scripts/start-services.sh index 50be1c644ce..4f1afde245e 100755 --- a/packages/functional-tests/scripts/start-services.sh +++ b/packages/functional-tests/scripts/start-services.sh @@ -18,6 +18,8 @@ NODE_OPTIONS="--max-old-space-size=7168" NODE_ENV=test npx nx run-many \ --verbose \ -p \ 123done \ + fxa-admin-panel \ + fxa-admin-server \ fxa-auth-server \ fxa-content-server \ fxa-payments-server \ diff --git a/packages/functional-tests/tests/admin/adminPanel.spec.ts b/packages/functional-tests/tests/admin/adminPanel.spec.ts new file mode 100644 index 00000000000..f835946e80b --- /dev/null +++ b/packages/functional-tests/tests/admin/adminPanel.spec.ts @@ -0,0 +1,70 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { expect, test } from '../../lib/fixtures/standard'; + +const ADMIN_PANEL_URL = process.env.ADMIN_PANEL_URL ?? 'http://localhost:8091'; +const ADMIN_SERVER_URL = process.env.ADMIN_SERVER_URL ?? 'http://localhost:8095'; + +// Admin panel tests only run locally (stage/prod require SSO) +test.skip(({ target }) => target.name !== 'local'); + +test.describe('Admin Panel', () => { + test('admin panel loads and renders navigation', async ({ page }) => { + await page.goto(ADMIN_PANEL_URL); + await expect( + page.getByRole('link', { name: /account search/i }) + ).toBeVisible(); + }); + + test('admin panel heartbeat is healthy', async () => { + const res = await fetch(`${ADMIN_PANEL_URL}/__lbheartbeat__`); + expect(res.status).toBe(200); + }); + + test('admin server heartbeat is healthy', async () => { + const res = await fetch(`${ADMIN_SERVER_URL}/__lbheartbeat__`); + expect(res.status).toBe(200); + }); + + test('account search by email returns account data via API', async ({ + target, + testAccountTracker, + }) => { + const credentials = testAccountTracker.generateAccountDetails(); + await target.createAccount(credentials.email, credentials.password); + + const res = await fetch( + `${ADMIN_SERVER_URL}/api/account/by-email?email=${encodeURIComponent(credentials.email)}`, + { + headers: { + 'oidc-claim-id-token-email': 'test-admin@mozilla.com', + 'remote-groups': 'vpn_fxa_admin_panel_prod', + }, + } + ); + expect(res.status).toBe(200); + const data = await res.json(); + expect(data.email).toBe(credentials.email); + }); + + test('account search from UI shows results', async ({ + target, + page, + testAccountTracker, + }) => { + const credentials = testAccountTracker.generateAccountDetails(); + await target.createAccount(credentials.email, credentials.password); + + await page.goto(`${ADMIN_PANEL_URL}/account-search`); + + const searchInput = page.getByTestId('email-input'); + await searchInput.fill(credentials.email); + await page.getByTestId('search-button').click(); + + await expect(page.getByText(credentials.email)).toBeVisible({ + timeout: 10000, + }); + }); +}); diff --git a/packages/fxa-admin-panel/package.json b/packages/fxa-admin-panel/package.json index b6ffb9a3445..1cea7c2c200 100644 --- a/packages/fxa-admin-panel/package.json +++ b/packages/fxa-admin-panel/package.json @@ -75,7 +75,6 @@ "jest": "27.5.1", "jest-watch-typeahead": "0.6.5", "nx": "21.2.4", - "persistgraphql": "^0.3.11", "pm2": "^6.0.14", "postcss-import": "^16.1.0", "prettier": "^3.5.3", diff --git a/packages/fxa-admin-panel/pm2.config.js b/packages/fxa-admin-panel/pm2.config.js index 4aed5f36cee..7f6ba40017f 100644 --- a/packages/fxa-admin-panel/pm2.config.js +++ b/packages/fxa-admin-panel/pm2.config.js @@ -71,13 +71,5 @@ module.exports = { ignore_watch: ['src/styles/tailwind.out.css'], time: true, }, - { - name: 'admin-gql-allowlist', - autorestart: false, - script: 'yarn gql:allowlist', - watch: ['src/**/*.ts'], - cwd: __dirname, - filter_env: ['npm_'], - }, ], }; diff --git a/packages/fxa-admin-server/package.json b/packages/fxa-admin-server/package.json index aaeedd9cbae..a6c6e106f79 100644 --- a/packages/fxa-admin-server/package.json +++ b/packages/fxa-admin-server/package.json @@ -4,8 +4,7 @@ "description": "FxA Admin Server", "scripts": { "prebuild": "yarn clean", - "gql-copy": "mkdir -p src/config/gql/allowlist/ && cp ../../configs/gql/allowlist/*.json src/config/gql/allowlist/.", - "build": "nest build && yarn copy-config && yarn gql-copy && yarn copy-email-assets && yarn copy-email-l10n-assets", + "build": "nest build && yarn copy-config && yarn copy-email-assets && yarn copy-email-l10n-assets", "copy-config": "cp ./src/config/*.json ./dist/packages/fxa-admin-server/src/config", "copy-email-assets": "copyfiles --up 1 '../../libs/accounts/email-renderer/**/*.{mjml,ftl,txt,css}' dist/libs/ ", "copy-email-l10n-assets": "copyfiles --up 1 '../../libs/accounts/email-renderer/public/locales' dist/libs/accounts/email-render/public/locales ", diff --git a/packages/fxa-admin-server/src/config/index.ts b/packages/fxa-admin-server/src/config/index.ts index fedb0a537b5..58abe28a94b 100644 --- a/packages/fxa-admin-server/src/config/index.ts +++ b/packages/fxa-admin-server/src/config/index.ts @@ -14,23 +14,6 @@ convict.addFormats(require('convict-format-with-moment')); convict.addFormats(require('convict-format-with-validator')); const conf = convict({ - gql: { - allowlist: { - doc: 'A list of json files holding allowed gql queries', - env: 'GQL_ALLOWLIST', - default: [ - 'src/config/gql/allowlist/fxa-admin-panel.json', - 'src/config/gql/allowlist/gql-playground.json', - ], - format: Array, - }, - enabled: { - doc: 'Toggles whether or not gql queries are checked against the allowlist.', - env: 'GQL_ALLOWLIST_ENABLED', - default: true, - format: Boolean, - }, - }, authHeader: { default: USER_EMAIL_HEADER, doc: 'Authentication header that should be logged for the user', diff --git a/packages/fxa-admin-server/src/rest/model/account-delete-task.model.ts b/packages/fxa-admin-server/src/rest/model/account-delete-task.model.ts index 40cd76d903c..0d6c24e526d 100644 --- a/packages/fxa-admin-server/src/rest/model/account-delete-task.model.ts +++ b/packages/fxa-admin-server/src/rest/model/account-delete-task.model.ts @@ -1,7 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; export enum AccountDeleteStatus { Success = 'Success', @@ -9,28 +8,21 @@ export enum AccountDeleteStatus { NoAccount = 'No account found', } -@ObjectType() export class AccountDeleteResponse { /** Name of task held in the task queue. This can be used to get task's status later. */ - @Field({ nullable: false }) public taskName!: string; /** A valid account email or UID */ - @Field({ nullable: false }) public locator!: string; /** A short status message. */ - @Field({ nullable: false }) status!: AccountDeleteStatus; } -@ObjectType() export class AccountDeleteTaskStatus { /** Name of task held in the task queue.. */ - @Field({ nullable: false }) public taskName!: string; /** A short status message. */ - @Field({ nullable: false }) status!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/account-events.model.ts b/packages/fxa-admin-server/src/rest/model/account-events.model.ts index 187e2185f07..931659475de 100644 --- a/packages/fxa-admin-server/src/rest/model/account-events.model.ts +++ b/packages/fxa-admin-server/src/rest/model/account-events.model.ts @@ -1,27 +1,19 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class AccountEvent { - @Field({ nullable: true }) public name!: string; - @Field({ nullable: true }) public createdAt!: number; - @Field({ nullable: true }) eventType!: string; // Email event based properties - @Field({ nullable: true }) template!: string; // Metrics properties - @Field({ nullable: true }) flowId!: string; - @Field({ nullable: true }) service!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/account-reset.model.ts b/packages/fxa-admin-server/src/rest/model/account-reset.model.ts index 213a2211d81..e1c3347750d 100644 --- a/packages/fxa-admin-server/src/rest/model/account-reset.model.ts +++ b/packages/fxa-admin-server/src/rest/model/account-reset.model.ts @@ -1,7 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; export enum AccountResetStatus { Success = 'Success', @@ -9,11 +8,8 @@ export enum AccountResetStatus { NoAccount = 'No account found', } -@ObjectType() export class AccountResetResponse { - @Field({ nullable: false }) locator!: string; - @Field({ nullable: false }) status!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/account.model.ts b/packages/fxa-admin-server/src/rest/model/account.model.ts index 489809ddc9b..75736669da2 100644 --- a/packages/fxa-admin-server/src/rest/model/account.model.ts +++ b/packages/fxa-admin-server/src/rest/model/account.model.ts @@ -1,7 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ID, ObjectType } from '@nestjs/graphql'; import { AttachedClient } from './attached-clients.model'; import { EmailBounce } from './email-bounces.model'; @@ -16,68 +15,46 @@ import { Cart } from './cart.model'; import { BackupCodes } from './backup-code.model'; import { RecoveryPhone } from './recovery-phone.model'; -@ObjectType() export class Account { - @Field((type) => ID) public uid!: string; - @Field() public email!: string; - @Field() public emailVerified!: boolean; - @Field({ nullable: true }) public clientSalt?: string; - @Field() public createdAt!: number; - @Field({ nullable: true }) public disabledAt?: number; - @Field({ nullable: true }) public locale?: string; - @Field({ nullable: true }) public lockedAt?: number; - @Field({ nullable: true }) public verifierSetAt?: number; - @Field((type) => [Email], { nullable: true }) public emails!: Email[]; - @Field((type) => [EmailBounce], { nullable: true }) public emailBounces!: EmailBounce[]; - @Field((type) => [Totp], { nullable: true }) public totp!: Totp[]; - @Field((type) => [RecoveryKeys], { nullable: true }) public recoveryKeys!: RecoveryKeys[]; - @Field((type) => [SecurityEvents], { nullable: true }) public securityEvents!: SecurityEvents[]; - @Field((type) => [AttachedClient], { nullable: true }) public attachedClients!: AttachedClient[]; - @Field((type) => [MozSubscription], { nullable: true }) public subscriptions!: MozSubscription[]; - @Field((type) => [LinkedAccount], { nullable: true }) public linkedAccounts!: LinkedAccount[]; - @Field((type) => [AccountEvent], { nullable: true }) public accountEvents!: AccountEvent[]; - @Field((type) => [Cart], { nullable: true }) public carts!: Cart[]; - @Field((type) => [BackupCodes], { nullable: true }) public backupCodes!: BackupCodes[]; - @Field((type) => [RecoveryPhone], { nullable: true }) public recoveryPhone!: RecoveryPhone[]; } diff --git a/packages/fxa-admin-server/src/rest/model/attached-clients.model.ts b/packages/fxa-admin-server/src/rest/model/attached-clients.model.ts index b3e2503f42f..de4231b4473 100644 --- a/packages/fxa-admin-server/src/rest/model/attached-clients.model.ts +++ b/packages/fxa-admin-server/src/rest/model/attached-clients.model.ts @@ -1,60 +1,41 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; import { Location } from './location.model'; -@ObjectType() export class AttachedClient { - @Field({ nullable: true }) clientId?: string; - @Field({ nullable: true }) deviceId?: string; - @Field({ nullable: true }) sessionTokenId?: string; - @Field({ nullable: true }) refreshTokenId?: string; - @Field({ nullable: true }) isCurrentSession!: boolean; - @Field({ nullable: true }) deviceType?: string; - @Field({ nullable: true }) name?: string; - @Field((type) => [String], { nullable: true }) scope?: string[]; - @Field({ nullable: true }) location!: Location; - @Field({ nullable: true }) userAgent!: string; - @Field({ nullable: true }) os?: string; - @Field({ nullable: true }) createdTime?: number; - @Field({ nullable: true }) createdTimeFormatted?: string; - @Field({ nullable: true }) lastAccessTime?: number; - @Field({ nullable: true }) lastAccessTimeFormatted?: string; - @Field({ nullable: true }) approximateLastAccessTime?: number; - @Field({ nullable: true }) approximateLastAccessTimeFormatted?: string; } diff --git a/packages/fxa-admin-server/src/rest/model/attached-sessions.model.ts b/packages/fxa-admin-server/src/rest/model/attached-sessions.model.ts index 7efa1dc7058..cc465e513dc 100644 --- a/packages/fxa-admin-server/src/rest/model/attached-sessions.model.ts +++ b/packages/fxa-admin-server/src/rest/model/attached-sessions.model.ts @@ -1,34 +1,23 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ID, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class AttachedSession { - @Field((type) => ID) public id!: string; - @Field() createdAt!: number; - @Field() lastAccessTime!: number; - @Field() location!: Location; - @Field() uaBrowser!: string; - @Field() uaOS!: string; - @Field() uaBrowserVersion!: string; - @Field() uaOSVersion!: string; - @Field() uaFormFactor!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/backup-code.model.ts b/packages/fxa-admin-server/src/rest/model/backup-code.model.ts index 69b641ecdda..7b010f8d520 100644 --- a/packages/fxa-admin-server/src/rest/model/backup-code.model.ts +++ b/packages/fxa-admin-server/src/rest/model/backup-code.model.ts @@ -1,13 +1,9 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class BackupCodes { - @Field() public hasBackupCodes?: boolean; - @Field() public count?: number; } diff --git a/packages/fxa-admin-server/src/rest/model/block-status.model.ts b/packages/fxa-admin-server/src/rest/model/block-status.model.ts index 05315a2e784..33c9e253b28 100644 --- a/packages/fxa-admin-server/src/rest/model/block-status.model.ts +++ b/packages/fxa-admin-server/src/rest/model/block-status.model.ts @@ -2,31 +2,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType, Int, Float } from '@nestjs/graphql'; - -@ObjectType() export class BlockStatus { - @Field(() => Float) public retryAfter!: number; - @Field() public reason!: string; - @Field() public action!: string; - @Field() public blockingOn!: string; - @Field(() => Float) public startTime!: number; - @Field(() => Int) public duration!: number; - @Field(() => Int) public attempt!: number; - @Field() public policy!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/cart.model.ts b/packages/fxa-admin-server/src/rest/model/cart.model.ts index ebf0e97daf7..8a11726a671 100644 --- a/packages/fxa-admin-server/src/rest/model/cart.model.ts +++ b/packages/fxa-admin-server/src/rest/model/cart.model.ts @@ -1,67 +1,45 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class TaxAddress { - @Field() public countryCode!: string; - @Field() public postalCode!: string; } -@ObjectType() export class Cart { - @Field() public id!: string; - @Field({ nullable: true }) public uid?: string; - @Field() public state!: string; - @Field({ nullable: true }) public errorReasonId?: string; - @Field() public offeringConfigId!: string; - @Field() public interval!: string; - @Field({ nullable: true }) public experiment?: string; - @Field((type) => TaxAddress, { nullable: true }) public taxAddress?: TaxAddress; - @Field({ nullable: true }) public currency?: string; - @Field() public createdAt!: number; - @Field() public updatedAt!: number; - @Field({ nullable: true }) public couponCode?: string; - @Field({ nullable: true }) public stripeCustomerId?: string; - @Field({ nullable: true }) public stripeSubscriptionId?: string; - @Field() public amount!: number; - @Field() public version!: number; - @Field() public eligibilityStatus!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/email-bounces.model.ts b/packages/fxa-admin-server/src/rest/model/email-bounces.model.ts index b5db6256382..c7acd33c38c 100644 --- a/packages/fxa-admin-server/src/rest/model/email-bounces.model.ts +++ b/packages/fxa-admin-server/src/rest/model/email-bounces.model.ts @@ -1,7 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; export enum BounceType { unmapped, @@ -30,30 +29,16 @@ export enum BounceSubType { OnAccountSuppressionList, } -registerEnumType(BounceType, { - name: 'BounceType', -}); -registerEnumType(BounceSubType, { - name: 'BounceSubType', -}); - -@ObjectType() export class EmailBounce { - @Field() public email!: string; - @Field() public templateName!: string; - @Field((type) => BounceType) public bounceType!: string; - @Field((type) => BounceSubType) public bounceSubType!: string; - @Field() public createdAt!: number; - @Field({ nullable: true }) public diagnosticCode?: string; } diff --git a/packages/fxa-admin-server/src/rest/model/emails.model.ts b/packages/fxa-admin-server/src/rest/model/emails.model.ts index e82682bb4f7..7316a149cab 100644 --- a/packages/fxa-admin-server/src/rest/model/emails.model.ts +++ b/packages/fxa-admin-server/src/rest/model/emails.model.ts @@ -1,19 +1,13 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class Email { - @Field() public email!: string; - @Field() public isVerified!: boolean; - @Field() public isPrimary!: boolean; - @Field() public createdAt!: number; } diff --git a/packages/fxa-admin-server/src/rest/model/linked-account.model.ts b/packages/fxa-admin-server/src/rest/model/linked-account.model.ts index f1099f1e007..9878e80b87e 100644 --- a/packages/fxa-admin-server/src/rest/model/linked-account.model.ts +++ b/packages/fxa-admin-server/src/rest/model/linked-account.model.ts @@ -1,7 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; export enum ProviderId { unmapped, @@ -9,21 +8,12 @@ export enum ProviderId { APPLE, } -registerEnumType(ProviderId, { - name: 'ProviderId', -}); - -@ObjectType() export class LinkedAccount { - @Field() public uid!: string; - @Field() public authAt!: number; - @Field((type) => ProviderId) public providerId!: string; - @Field() public enabled!: boolean; } diff --git a/packages/fxa-admin-server/src/rest/model/location.model.ts b/packages/fxa-admin-server/src/rest/model/location.model.ts index fb0645a741b..5f70c5de9be 100644 --- a/packages/fxa-admin-server/src/rest/model/location.model.ts +++ b/packages/fxa-admin-server/src/rest/model/location.model.ts @@ -1,22 +1,15 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class Location { - @Field({ nullable: true }) city?: string; - @Field({ nullable: true }) country?: string; - @Field({ nullable: true }) countryCode?: string; - @Field({ nullable: true }) state?: string; - @Field({ nullable: true }) stateCode?: string; } diff --git a/packages/fxa-admin-server/src/rest/model/moz-subscription.model.ts b/packages/fxa-admin-server/src/rest/model/moz-subscription.model.ts index a45bf7402b3..7a8f7cc4c46 100644 --- a/packages/fxa-admin-server/src/rest/model/moz-subscription.model.ts +++ b/packages/fxa-admin-server/src/rest/model/moz-subscription.model.ts @@ -1,45 +1,29 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -/* We can't call this Subscription because it's a reserved word in GQL - * and autogenerated TS interfaces will be incorrect. */ -@ObjectType() export class MozSubscription { - @Field() public created!: number; - @Field() public currentPeriodEnd!: number; - @Field() public currentPeriodStart!: number; - @Field() public cancelAtPeriodEnd!: boolean; - @Field({ nullable: true }) public endedAt?: number; - @Field() public latestInvoice!: string; - @Field({ nullable: true }) public manageSubscriptionLink?: string; - @Field() public planId!: string; - @Field() public productName!: string; - @Field() public productId!: string; - @Field() public status!: string; - @Field() public subscriptionId!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/recovery-keys.model.ts b/packages/fxa-admin-server/src/rest/model/recovery-keys.model.ts index 34768d8cffd..314d832d4b4 100644 --- a/packages/fxa-admin-server/src/rest/model/recovery-keys.model.ts +++ b/packages/fxa-admin-server/src/rest/model/recovery-keys.model.ts @@ -1,16 +1,11 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class RecoveryKeys { - @Field({ nullable: true }) public createdAt!: number; - @Field({ nullable: true }) public verifiedAt!: number; - @Field({ nullable: true }) public enabled!: boolean; } diff --git a/packages/fxa-admin-server/src/rest/model/recovery-phone.model.ts b/packages/fxa-admin-server/src/rest/model/recovery-phone.model.ts index b09028dfd77..d43a6c89bbf 100644 --- a/packages/fxa-admin-server/src/rest/model/recovery-phone.model.ts +++ b/packages/fxa-admin-server/src/rest/model/recovery-phone.model.ts @@ -1,16 +1,11 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class RecoveryPhone { - @Field({ nullable: true }) public phoneNumber!: string; - @Field() public exists!: boolean; - @Field({ nullable: true }) public lastFourDigits?: string; } diff --git a/packages/fxa-admin-server/src/rest/model/relying-party.model.ts b/packages/fxa-admin-server/src/rest/model/relying-party.model.ts index 48b2ac5ba0c..3e0da6b157c 100644 --- a/packages/fxa-admin-server/src/rest/model/relying-party.model.ts +++ b/packages/fxa-admin-server/src/rest/model/relying-party.model.ts @@ -1,85 +1,57 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ID, InputType, ObjectType } from '@nestjs/graphql'; -@InputType() export class RelyingPartyUpdateDto { - @Field() name!: string; - @Field() imageUri!: string; - @Field() redirectUri!: string; - @Field() canGrant!: boolean; - @Field() publicClient!: boolean; - @Field() trusted!: boolean; - @Field() allowedScopes!: string; - @Field() notes!: string; } -@ObjectType() export class RelyingPartyDto { - @Field((type) => ID) id!: string; - @Field() createdAt!: number; - @Field() name!: string; - @Field() imageUri!: string; - @Field() redirectUri!: string; - @Field() canGrant!: boolean; - @Field() publicClient!: boolean; - @Field() trusted!: boolean; - @Field() allowedScopes!: string; - @Field() notes!: string; - @Field() hasSecret!: boolean; - @Field() hasPreviousSecret!: boolean; } -@ObjectType() export class RelyingPartyCreatedDto { - @Field() id!: string; - @Field() secret!: string; } -@ObjectType() export class RotateSecretDto { - @Field() secret!: string; } diff --git a/packages/fxa-admin-server/src/rest/model/security-events.model.ts b/packages/fxa-admin-server/src/rest/model/security-events.model.ts index 6d31c0e3c44..d73546a3fce 100644 --- a/packages/fxa-admin-server/src/rest/model/security-events.model.ts +++ b/packages/fxa-admin-server/src/rest/model/security-events.model.ts @@ -1,37 +1,23 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class SecurityEvents { - @Field({ nullable: true }) public uid!: string; - @Field({ nullable: true }) public nameId!: number; - @Field({ nullable: true }) public verified!: boolean; - @Field({ nullable: true }) public ipAddrHmac!: string; - @Field({ nullable: true }) public createdAt!: number; - @Field({ nullable: true }) public tokenVerificationId!: string; - @Field({ nullable: true }) public name!: string; - @Field({ nullable: true }) public ipAddr!: string; - @Field(() => String, { - nullable: true, - description: 'JSON data for additional info about the security event', - }) additionalInfo?: string; } diff --git a/packages/fxa-admin-server/src/rest/model/totp.model.ts b/packages/fxa-admin-server/src/rest/model/totp.model.ts index 3b87a32af3a..da1c0741bec 100644 --- a/packages/fxa-admin-server/src/rest/model/totp.model.ts +++ b/packages/fxa-admin-server/src/rest/model/totp.model.ts @@ -1,16 +1,11 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Field, ObjectType } from '@nestjs/graphql'; -@ObjectType() export class Totp { - @Field() public verified!: boolean; - @Field() public createdAt!: number; - @Field() public enabled!: boolean; } diff --git a/packages/fxa-shared/nestjs/gql/example-allowlist.json b/packages/fxa-shared/nestjs/gql/example-allowlist.json deleted file mode 100644 index 9f2c8e1a140..00000000000 --- a/packages/fxa-shared/nestjs/gql/example-allowlist.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "query GetUid {\n account {\n uid\n }\n}\n": 1 -} diff --git a/packages/fxa-shared/nestjs/gql/gql-allowlist.spec.ts b/packages/fxa-shared/nestjs/gql/gql-allowlist.spec.ts deleted file mode 100644 index a2121cb099c..00000000000 --- a/packages/fxa-shared/nestjs/gql/gql-allowlist.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { GqlAllowlist } from './gql-allowlist'; - -describe('Gql Allowlist', () => { - let allowlist: GqlAllowlist; - - function runGuard({ body = {}, query = {} }) { - return allowlist.allowed({ - body, - query, - }); - } - - beforeEach(async () => { - allowlist = new GqlAllowlist({ - allowlist: ['nestjs/gql/example-allowlist.json'], - enabled: true, - }); - }); - - it('should be defined', () => { - expect(allowlist).toBeDefined(); - }); - - it('should have parsed allowlist', () => { - expect(allowlist.valid).toBeDefined(); - expect(allowlist.valid.length).toBeGreaterThan(0); - expect(Object.keys(allowlist.valid[0]).length).toBeGreaterThan(0); - }); - - it('allowsValid query', () => { - const body = { - query: 'query GetUid {\n account {\n uid\n }\n}\n', - }; - expect(runGuard({ body })).toBeTruthy(); - }); - - it('denies invalid query', () => { - const body = { - query: - 'query GetRecoveryKeyExists {\n account {\n totp {\n exists\n verified\n }\n }\n}\n', - }; - expect(runGuard({ body })).toBeFalsy(); - }); -}); diff --git a/packages/fxa-shared/nestjs/gql/gql-allowlist.ts b/packages/fxa-shared/nestjs/gql/gql-allowlist.ts deleted file mode 100644 index bae1ef7d367..00000000000 --- a/packages/fxa-shared/nestjs/gql/gql-allowlist.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { readFileSync } from 'fs'; -import { Request, Response, NextFunction } from 'express'; -import { StatsD } from 'hot-shots'; - -/** - * Configuration options for GqlGuard - */ -export type Config = { - /** A list of json files holding queries extracted with the persistgraphql util. */ - allowlist: string[]; - /** Toggles gaurd on / off. */ - enabled: boolean; -}; - -/** - * Guards against the execution of unsanctioned gql queries. A list of allowed queries can be populated by running. - * `yarn gql:allowlist`. - * - * During development it is probably desirable to disable this! - */ -export class GqlAllowlist { - public readonly valid: Array>; - public readonly enabled: boolean; - - constructor(config: Config) { - this.enabled = config.enabled; - if (this.enabled) { - this.valid = config.allowlist.map((x) => { - const raw = readFileSync(x).toString(); - try { - return JSON.parse(raw); - } catch (err) { - console.warn('Failed to parse gql allowlist', raw); - throw err; - } - }); - } else { - this.valid = []; - } - } - - allowed(req: Pick) { - if (!this.enabled) { - return true; - } - - const query = req.query?.query || req.body?.query; - - // If there was no query defined, assume it is not a gql request. - // This allows the gql playground to work. - if (!query) { - return true; - } - - return this.valid.some((x) => x[query] !== undefined); - } -} - -/** - * Express middleware for sanctioning GqlQueries. See: - * https://www.apollographql.com/blog/graphql/security/securing-your-graphql-api-from-malicious-queries/#query-whitelisting - * @param config - * @returns - */ -export function allowlistGqlQueries(config: Config, statsd?: StatsD) { - const guard = new GqlAllowlist(config); - return (req: Request, res: Response, next: NextFunction) => { - if (guard.allowed(req)) { - next(); - } else { - statsd?.increment('gql.unsanctioned_query'); - res - .status(403) - .send({ statusCode: 403, message: 'Unsanctioned Graphql Query' }); - } - }; -} diff --git a/packages/fxa-shared/nestjs/sentry/reporting.ts b/packages/fxa-shared/nestjs/sentry/reporting.ts index 72dd048dbbc..201ab3b5d70 100644 --- a/packages/fxa-shared/nestjs/sentry/reporting.ts +++ b/packages/fxa-shared/nestjs/sentry/reporting.ts @@ -1,10 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { ExecutionContext } from '@nestjs/common'; -import { ApolloServerErrorCode } from '@apollo/server/errors'; -import { GraphQLError } from 'graphql'; -import { GqlContextType, GqlExecutionContext } from '@nestjs/graphql'; import * as Sentry from '@sentry/node'; import { Message } from '@aws-sdk/client-sqs'; import { Request } from 'express'; @@ -14,21 +10,6 @@ export interface ExtraContext { fieldData: Record; } -/** - * Determine if an error is an ApolloError. - * Prior to GQL 16.8 and apollo-server 4.9.3, we used ApolloError from apollo-server. - * Now, we populate fields on GraphQL error to mimic the previous state of ApolloError. - */ -export function isApolloError(err: Error): boolean { - if (err instanceof GraphQLError) { - const code = err.extensions?.code; - if (typeof code === 'string') { - return Object.keys(ApolloServerErrorCode).includes(code); - } - } - return false; -} - /** * Determine if an error originates from auth-server. Auth server responds with error * codes and numbers, and client applications handle these states accordingly. These @@ -107,28 +88,3 @@ export function reportRequestException( exception.reported = true; }); } - -export function processException(context: ExecutionContext, exception: Error) { - // First determine what type of a request this is - let requestType: 'http' | 'graphql' | undefined; - let request: Request | undefined; - let gqlExec: GqlExecutionContext | undefined; - if (context.getType() === 'http') { - requestType = 'http'; - request = context.switchToHttp().getRequest(); - } else if (context.getType() === 'graphql') { - requestType = 'graphql'; - gqlExec = GqlExecutionContext.create(context); - request = gqlExec.getContext().req; - } - let excContexts: ExtraContext[] = []; - if (gqlExec) { - const info = gqlExec.getInfo(); - excContexts.push({ - name: 'graphql', - fieldData: { fieldName: info.fieldName, path: info.path }, - }); - } - - reportRequestException(exception, excContexts, request); -} diff --git a/yarn.lock b/yarn.lock index 627aa7e02cc..643213ed64f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22766,20 +22766,6 @@ __metadata: languageName: node linkType: hard -"@types/graphql@npm:0.10.2": - version: 0.10.2 - resolution: "@types/graphql@npm:0.10.2" - checksum: 10c0/bed98a702010d186f23e87f2d87fe0e9bcb929040ee11695ea0bb95d47ec63aa2df5fa020880c0c427e727aacef87681e481b81a1004a228dd64fc824085f3c4 - languageName: node - linkType: hard - -"@types/graphql@npm:^0.9.0": - version: 0.9.4 - resolution: "@types/graphql@npm:0.9.4" - checksum: 10c0/a880ea7d8613d76cb683d3aea8361b041582f6a63f6a0d6f159ccb43736858941a8f0b5014b8ef7cfc2f79bf61aec42090c55685a03c15c66fbb458993c46fa5 - languageName: node - linkType: hard - "@types/hapi@npm:^18.0.15": version: 18.0.15 resolution: "@types/hapi@npm:18.0.15" @@ -22945,13 +22931,6 @@ __metadata: languageName: node linkType: hard -"@types/isomorphic-fetch@npm:0.0.34": - version: 0.0.34 - resolution: "@types/isomorphic-fetch@npm:0.0.34" - checksum: 10c0/39285fc5c94a9b5e92db3990d533b7afac8468531d136e74ec4c3b51b80abfa81363039b2ad75cd78c82a7596e53c71da0afa38ff6c08f2fa65bbda5d3e0a0e8 - languageName: node - linkType: hard - "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" @@ -26101,36 +26080,6 @@ __metadata: languageName: node linkType: hard -"apollo-client@npm:^1.1": - version: 1.9.3 - resolution: "apollo-client@npm:1.9.3" - dependencies: - "@types/graphql": "npm:0.10.2" - apollo-link-core: "npm:^0.5.0" - graphql: "npm:^0.10.0" - graphql-anywhere: "npm:^3.0.1" - graphql-tag: "npm:^2.0.0" - redux: "npm:^3.4.0" - symbol-observable: "npm:^1.0.2" - whatwg-fetch: "npm:^2.0.0" - dependenciesMeta: - "@types/graphql": - optional: true - checksum: 10c0/06a7050ae3a34e816d285982bb36dd6d41e5668668491d1b01964392b0de84b34e378159de09013a58cde0bcb5364e14994e6aabddcdc62d4b59e10eaa82f4ec - languageName: node - linkType: hard - -"apollo-link-core@npm:^0.5.0": - version: 0.5.4 - resolution: "apollo-link-core@npm:0.5.4" - dependencies: - graphql: "npm:^0.10.3" - graphql-tag: "npm:^2.4.2" - zen-observable-ts: "npm:^0.4.4" - checksum: 10c0/afa84b69f54db2861894135556ac43eaa5fe64f7069345928012f31ce6152556f9a5c2c08f065a69f922eb788a7676304aab9569824d315ffb4d94d7c3a5539d - languageName: node - linkType: hard - "app-root-dir@npm:^1.0.2": version: 1.0.2 resolution: "app-root-dir@npm:1.0.2" @@ -28541,13 +28490,6 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^3.0.0": - version: 3.0.0 - resolution: "camelcase@npm:3.0.0" - checksum: 10c0/98871bb40b936430beca49490d325759f8d8ade32bea538ee63c20b17b326abb6bbd3e1d84daf63d9332b2fc7637f28696bf76da59180b1247051b955cb1da12 - languageName: node - linkType: hard - "camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" @@ -29223,17 +29165,6 @@ __metadata: languageName: node linkType: hard -"cliui@npm:^3.2.0": - version: 3.2.0 - resolution: "cliui@npm:3.2.0" - dependencies: - string-width: "npm:^1.0.1" - strip-ansi: "npm:^3.0.1" - wrap-ansi: "npm:^2.0.0" - checksum: 10c0/07b121fac7fd33ff8dbf3523f0d3dca0329d4e457e57dee54502aa5f27a33cbd9e66aa3e248f0260d8a1431b65b2bad8f510cd97fb8ab6a8e0506310a92e18d5 - languageName: node - linkType: hard - "cliui@npm:^5.0.0": version: 5.0.0 resolution: "cliui@npm:5.0.0" @@ -29374,13 +29305,6 @@ __metadata: languageName: node linkType: hard -"code-point-at@npm:^1.0.0": - version: 1.1.0 - resolution: "code-point-at@npm:1.1.0" - checksum: 10c0/33f6b234084e46e6e369b6f0b07949392651b4dde70fc6a592a8d3dafa08d5bb32e3981a02f31f6fc323a26bc03a4c063a9d56834848695bda7611c2417ea2e6 - languageName: node - linkType: hard - "collect-v8-coverage@npm:^1.0.0": version: 1.0.2 resolution: "collect-v8-coverage@npm:1.0.2" @@ -31329,7 +31253,7 @@ __metadata: languageName: node linkType: hard -"decamelize@npm:^1.1.1, decamelize@npm:^1.2.0": +"decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" checksum: 10c0/85c39fe8fbf0482d4a1e224ef0119db5c1897f8503bcef8b826adff7a1b11414972f6fef2d7dec2ee0b4be3863cf64ac1439137ae9e6af23a3d8dcbe26a5b4b2 @@ -32640,7 +32564,7 @@ __metadata: languageName: node linkType: hard -"error-ex@npm:^1.2.0, error-ex@npm:^1.3.1": +"error-ex@npm:^1.3.1": version: 1.3.2 resolution: "error-ex@npm:1.3.2" dependencies: @@ -35044,16 +34968,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^1.0.0": - version: 1.1.2 - resolution: "find-up@npm:1.1.2" - dependencies: - path-exists: "npm:^2.0.0" - pinkie-promise: "npm:^2.0.0" - checksum: 10c0/51e35c62d9b7efe82d7d5cce966bfe10c2eaa78c769333f8114627e3a8a4a4f50747f5f50bff50b1094cbc6527776f0d3b9ff74d3561ef714a5290a17c80c2bc - languageName: node - linkType: hard - "find-up@npm:^2.1.0": version: 2.1.0 resolution: "find-up@npm:2.1.0" @@ -35897,7 +35811,6 @@ __metadata: mozlog: "npm:^3.0.2" nx: "npm:21.2.4" on-headers: "npm:^1.1.0" - persistgraphql: "npm:^0.3.11" pm2: "npm:^6.0.14" postcss-import: "npm:^16.1.0" prettier: "npm:^3.5.3" @@ -37007,7 +36920,6 @@ __metadata: passport-http-bearer: "npm:^1.0.1" passport-jwt: "npm:^4.0.1" path-browserify: "npm:^1.0.1" - persistgraphql: "npm:^0.3.11" pm2: "npm:^6.0.14" postcss: "npm:8.5.0" prettier: "npm:^3.5.3" @@ -37108,13 +37020,6 @@ __metadata: languageName: node linkType: hard -"get-caller-file@npm:^1.0.1": - version: 1.0.3 - resolution: "get-caller-file@npm:1.0.3" - checksum: 10c0/763dcee2de8ff60ae7e13a4bad8306205a2fbe108e555686344ddd9ef211b8bebfe459d3a739669257014c59e7cc1e7a44003c21af805c1214673e6a45f06c51 - languageName: node - linkType: hard - "get-caller-file@npm:^2.0.1, get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" @@ -37887,13 +37792,6 @@ __metadata: languageName: node linkType: hard -"graphql-anywhere@npm:^3.0.1": - version: 3.1.0 - resolution: "graphql-anywhere@npm:3.1.0" - checksum: 10c0/58a40360fa93f99ad27a7f7c90be16ea094dbf03f96b1d37215aa18bf8fd6f10fc05e6142b43440508a24beb86225cdb6f9594d9ee146c3a16593020f9764f3e - languageName: node - linkType: hard - "graphql-config@npm:^5.0.2": version: 5.1.5 resolution: "graphql-config@npm:5.1.5" @@ -37931,7 +37829,7 @@ __metadata: languageName: node linkType: hard -"graphql-tag@npm:2.12.6, graphql-tag@npm:^2.0.0, graphql-tag@npm:^2.11.0, graphql-tag@npm:^2.12.6, graphql-tag@npm:^2.4.2": +"graphql-tag@npm:2.12.6, graphql-tag@npm:^2.11.0, graphql-tag@npm:^2.12.6": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" dependencies: @@ -37973,15 +37871,6 @@ __metadata: languageName: node linkType: hard -"graphql@npm:>=0.9.4 <0.11, graphql@npm:^0.10.0, graphql@npm:^0.10.3": - version: 0.10.5 - resolution: "graphql@npm:0.10.5" - dependencies: - iterall: "npm:^1.1.0" - checksum: 10c0/0ca1952bc7f9db3de4fad1cdbdb32ff704fa3549ff3e772a78c2398d71852df54eee1f9758a77569ba6a662152d4406e70733553419eb855a400a31980f09a25 - languageName: node - linkType: hard - "graphql@npm:^16.10.0": version: 16.11.0 resolution: "graphql@npm:16.11.0" @@ -39979,13 +39868,6 @@ __metadata: languageName: node linkType: hard -"invert-kv@npm:^1.0.0": - version: 1.0.0 - resolution: "invert-kv@npm:1.0.0" - checksum: 10c0/9ccef12ada8494c56175cc0380b4cea18b6c0a368436f324a30e43a332db90bdfb83cd3a7987b71df359cdf931ce45b7daf35b677da56658565d61068e4bc20b - languageName: node - linkType: hard - "ioredis@npm:4.x.x, ioredis@npm:^4.28.2": version: 4.30.0 resolution: "ioredis@npm:4.30.0" @@ -40363,15 +40245,6 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^1.0.0": - version: 1.0.0 - resolution: "is-fullwidth-code-point@npm:1.0.0" - dependencies: - number-is-nan: "npm:^1.0.0" - checksum: 10c0/12acfcf16142f2d431bf6af25d68569d3198e81b9799b4ae41058247aafcc666b0127d64384ea28e67a746372611fcbe9b802f69175287aba466da3eddd5ba0f - languageName: node - linkType: hard - "is-fullwidth-code-point@npm:^2.0.0": version: 2.0.0 resolution: "is-fullwidth-code-point@npm:2.0.0" @@ -40838,13 +40711,6 @@ __metadata: languageName: node linkType: hard -"is-utf8@npm:^0.2.0": - version: 0.2.1 - resolution: "is-utf8@npm:0.2.1" - checksum: 10c0/3ed45e5b4ddfa04ed7e32c63d29c61b980ecd6df74698f45978b8c17a54034943bcbffb6ae243202e799682a66f90fef526f465dd39438745e9fe70794c1ef09 - languageName: node - linkType: hard - "is-weakmap@npm:^2.0.2": version: 2.0.2 resolution: "is-weakmap@npm:2.0.2" @@ -41104,7 +40970,7 @@ __metadata: languageName: node linkType: hard -"iterall@npm:1.3.0, iterall@npm:^1.1.0, iterall@npm:^1.2.1": +"iterall@npm:1.3.0, iterall@npm:^1.2.1": version: 1.3.0 resolution: "iterall@npm:1.3.0" checksum: 10c0/40de624e5fe937c4c0e511981b91caea9ff2142bfc0316cccc8506eaa03aa253820cc17c5bc5f0a98706c7268a373e5ebee9af9a0c8a359730cf7c05938b57b5 @@ -43534,15 +43400,6 @@ __metadata: languageName: node linkType: hard -"lcid@npm:^1.0.0": - version: 1.0.0 - resolution: "lcid@npm:1.0.0" - dependencies: - invert-kv: "npm:^1.0.0" - checksum: 10c0/87fb32196c3c80458778f34f71c042e114f3134a3c86c0d60ee9c94f0750e467d7ca0c005a5224ffd9d49a6e449b5e5c31e1544f1827765a0ba8747298f5980e - languageName: node - linkType: hard - "legal-docs@https://github.com/mozilla/legal-docs.git#68a02d3a95f22fb10db68893bb54e49bc0604f69": version: 1.0.0 resolution: "legal-docs@https://github.com/mozilla/legal-docs.git#commit=68a02d3a95f22fb10db68893bb54e49bc0604f69" @@ -43813,19 +43670,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^1.0.0": - version: 1.1.0 - resolution: "load-json-file@npm:1.1.0" - dependencies: - graceful-fs: "npm:^4.1.2" - parse-json: "npm:^2.2.0" - pify: "npm:^2.0.0" - pinkie-promise: "npm:^2.0.0" - strip-bom: "npm:^2.0.0" - checksum: 10c0/2a5344c2d88643735a938fdca8582c0504e1c290577faa74f56b9cc187fa443832709a15f36e5771f779ec0878215a03abc8faf97ec57bb86092ceb7e0caef22 - languageName: node - linkType: hard - "loader-runner@npm:^2.4.0": version: 2.4.0 resolution: "loader-runner@npm:2.4.0" @@ -43934,13 +43778,6 @@ __metadata: languageName: node linkType: hard -"lodash-es@npm:^4.2.1": - version: 4.17.21 - resolution: "lodash-es@npm:4.17.21" - checksum: 10c0/fb407355f7e6cd523a9383e76e6b455321f0f153a6c9625e21a8827d10c54c2a2341bd2ae8d034358b60e07325e1330c14c224ff582d04612a46a4f0479ff2f2 - languageName: node - linkType: hard - "lodash.camelcase@npm:^4.3.0": version: 4.3.0 resolution: "lodash.camelcase@npm:4.3.0" @@ -44130,7 +43967,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:4.17.x, lodash@npm:^4.0.0, lodash@npm:^4.15.0, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.2.1, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.19, lodash@npm:~4.17.21": +"lodash@npm:4.17.21, lodash@npm:4.17.x, lodash@npm:^4.0.0, lodash@npm:^4.15.0, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.19, lodash@npm:~4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c @@ -47133,7 +46970,7 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^2.3.2, normalize-package-data@npm:^2.5.0": +"normalize-package-data@npm:^2.5.0": version: 2.5.0 resolution: "normalize-package-data@npm:2.5.0" dependencies: @@ -47605,7 +47442,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.0, object.assign@npm:^4.1.4, object.assign@npm:^4.1.7": +"object.assign@npm:^4.1.4, object.assign@npm:^4.1.7": version: 4.1.7 resolution: "object.assign@npm:4.1.7" dependencies: @@ -47995,15 +47832,6 @@ __metadata: languageName: node linkType: hard -"os-locale@npm:^1.4.0": - version: 1.4.0 - resolution: "os-locale@npm:1.4.0" - dependencies: - lcid: "npm:^1.0.0" - checksum: 10c0/302173159d562000ddf982ed75c493a0d861e91372c9e1b13aab21590ff2e1ba264a41995b29be8dc5278a6127ffcd2ad5591779e8164a570fc5fa6c0787b057 - languageName: node - linkType: hard - "os-tmpdir@npm:^1.0.0, os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -48467,15 +48295,6 @@ __metadata: languageName: node linkType: hard -"parse-json@npm:^2.2.0": - version: 2.2.0 - resolution: "parse-json@npm:2.2.0" - dependencies: - error-ex: "npm:^1.2.0" - checksum: 10c0/7a90132aa76016f518a3d5d746a21b3f1ad0f97a68436ed71b6f995b67c7151141f5464eea0c16c59aec9b7756519a0e3007a8f98cf3714632d509ec07736df6 - languageName: node - linkType: hard - "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -48655,15 +48474,6 @@ __metadata: languageName: node linkType: hard -"path-exists@npm:^2.0.0": - version: 2.1.0 - resolution: "path-exists@npm:2.1.0" - dependencies: - pinkie-promise: "npm:^2.0.0" - checksum: 10c0/87352f1601c085d5a6eb202f60e5c016c1b790bd0bc09398af446ed3f5c4510b4531ff99cf8acac2d91868886e792927b4292f768b35a83dce12588fb7cbb46e - languageName: node - linkType: hard - "path-exists@npm:^3.0.0": version: 3.0.0 resolution: "path-exists@npm:3.0.0" @@ -48793,17 +48603,6 @@ __metadata: languageName: node linkType: hard -"path-type@npm:^1.0.0": - version: 1.1.0 - resolution: "path-type@npm:1.1.0" - dependencies: - graceful-fs: "npm:^4.1.2" - pify: "npm:^2.0.0" - pinkie-promise: "npm:^2.0.0" - checksum: 10c0/2b8c348cb52bbc0c0568afa10a0a5d8f6233adfe5ae75feb56064f6aed6324ab74185c61c2545f4e52ca08acdc76005f615da4e127ed6eecb866002cf491f350 - languageName: node - linkType: hard - "path-type@npm:^3.0.0": version: 3.0.0 resolution: "path-type@npm:3.0.0" @@ -48913,29 +48712,6 @@ __metadata: languageName: node linkType: hard -"persistgraphql@npm:^0.3.11": - version: 0.3.11 - resolution: "persistgraphql@npm:0.3.11" - dependencies: - "@types/graphql": "npm:^0.9.0" - "@types/isomorphic-fetch": "npm:0.0.34" - apollo-client: "npm:^1.1" - graphql: "npm:>=0.9.4 <0.11" - graphql-tag: "npm:^2.0.0" - lodash: "npm:^4.17.4" - whatwg-fetch: "npm:^2.0.3" - yargs: "npm:^7.1.0" - dependenciesMeta: - "@types/graphql": - optional: true - "@types/isomorphic-fetch": - optional: true - bin: - persistgraphql: ./bin/persistgraphql - checksum: 10c0/f5d28b2a5f5bcd15305e7dc9022e3922f512fc3efb873b0fd5b079c97cda1e932783be41feb39525e9342b9864eba56ceef8d6475837c2e2fa040784a8b12b04 - languageName: node - linkType: hard - "pg-connection-string@npm:2.6.2": version: 2.6.2 resolution: "pg-connection-string@npm:2.6.2" @@ -49025,7 +48801,7 @@ __metadata: languageName: node linkType: hard -"pify@npm:^2.0.0, pify@npm:^2.3.0": +"pify@npm:^2.3.0": version: 2.3.0 resolution: "pify@npm:2.3.0" checksum: 10c0/551ff8ab830b1052633f59cb8adc9ae8407a436e06b4a9718bcb27dc5844b83d535c3a8512b388b6062af65a98c49bdc0dd523d8b2617b188f7c8fee457158dc @@ -49046,22 +48822,6 @@ __metadata: languageName: node linkType: hard -"pinkie-promise@npm:^2.0.0": - version: 2.0.1 - resolution: "pinkie-promise@npm:2.0.1" - dependencies: - pinkie: "npm:^2.0.0" - checksum: 10c0/11b5e5ce2b090c573f8fad7b517cbca1bb9a247587306f05ae71aef6f9b2cd2b923c304aa9663c2409cfde27b367286179f1379bc4ec18a3fbf2bb0d473b160a - languageName: node - linkType: hard - -"pinkie@npm:^2.0.0": - version: 2.0.4 - resolution: "pinkie@npm:2.0.4" - checksum: 10c0/25228b08b5597da42dc384221aa0ce56ee0fbf32965db12ba838e2a9ca0193c2f0609c45551ee077ccd2060bf109137fdb185b00c6d7e0ed7e35006d20fdcbc6 - languageName: node - linkType: hard - "pirates@npm:^4.0.1, pirates@npm:^4.0.4, pirates@npm:^4.0.6": version: 4.0.7 resolution: "pirates@npm:4.0.7" @@ -52389,16 +52149,6 @@ __metadata: languageName: node linkType: hard -"read-pkg-up@npm:^1.0.1": - version: 1.0.1 - resolution: "read-pkg-up@npm:1.0.1" - dependencies: - find-up: "npm:^1.0.0" - read-pkg: "npm:^1.0.0" - checksum: 10c0/36c4fc8bd73edf77a4eeb497b6e43010819ea4aef64cbf8e393439fac303398751c5a299feab84e179a74507e3a1416e1ed033a888b1dac3463bf46d1765f7ac - languageName: node - linkType: hard - "read-pkg-up@npm:^7.0.1": version: 7.0.1 resolution: "read-pkg-up@npm:7.0.1" @@ -52410,17 +52160,6 @@ __metadata: languageName: node linkType: hard -"read-pkg@npm:^1.0.0": - version: 1.1.0 - resolution: "read-pkg@npm:1.1.0" - dependencies: - load-json-file: "npm:^1.0.0" - normalize-package-data: "npm:^2.3.2" - path-type: "npm:^1.0.0" - checksum: 10c0/51fce9f7066787dc7688ea7014324cedeb9f38daa7dace4f1147d526f22354a07189ef728710bc97e27fcf5ed3a03b68ad8b60afb4251984640b6f09c180d572 - languageName: node - linkType: hard - "read-pkg@npm:^5.2.0": version: 5.2.0 resolution: "read-pkg@npm:5.2.0" @@ -52681,18 +52420,6 @@ __metadata: languageName: node linkType: hard -"redux@npm:^3.4.0": - version: 3.7.2 - resolution: "redux@npm:3.7.2" - dependencies: - lodash: "npm:^4.2.1" - lodash-es: "npm:^4.2.1" - loose-envify: "npm:^1.1.0" - symbol-observable: "npm:^1.0.3" - checksum: 10c0/544456f95734de33326637b370894addb57d9de2524edf36a20e4a326d0a36a0e223979d027545c5aa8a8d7a2859363981f63d1146401b72df0d16f373dd09cb - languageName: node - linkType: hard - "redux@npm:^4.0.0, redux@npm:^4.2.0": version: 4.2.1 resolution: "redux@npm:4.2.1" @@ -53100,13 +52827,6 @@ __metadata: languageName: node linkType: hard -"require-main-filename@npm:^1.0.1": - version: 1.0.1 - resolution: "require-main-filename@npm:1.0.1" - checksum: 10c0/1ab87efb72a0e223a667154e92f29ca753fd42eb87f22db142b91c86d134e29ecf18af929111ccd255fd340b57d84a9d39489498d8dfd5136b300ded30a5f0b6 - languageName: node - linkType: hard - "require-main-filename@npm:^2.0.0": version: 2.0.0 resolution: "require-main-filename@npm:2.0.0" @@ -55973,17 +55693,6 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^1.0.1, string-width@npm:^1.0.2": - version: 1.0.2 - resolution: "string-width@npm:1.0.2" - dependencies: - code-point-at: "npm:^1.0.0" - is-fullwidth-code-point: "npm:^1.0.0" - strip-ansi: "npm:^3.0.0" - checksum: 10c0/c558438baed23a9ab9370bb6a939acbdb2b2ffc517838d651aad0f5b2b674fb85d460d9b1d0b6a4c210dffd09e3235222d89a5bd4c0c1587f78b2bb7bc00c65e - languageName: node - linkType: hard - "string-width@npm:^2.1.0": version: 2.1.1 resolution: "string-width@npm:2.1.1" @@ -56161,7 +55870,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^3.0.0, strip-ansi@npm:^3.0.1": +"strip-ansi@npm:^3.0.0": version: 3.0.1 resolution: "strip-ansi@npm:3.0.1" dependencies: @@ -56206,15 +55915,6 @@ __metadata: languageName: node linkType: hard -"strip-bom@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-bom@npm:2.0.0" - dependencies: - is-utf8: "npm:^0.2.0" - checksum: 10c0/4fcbb248af1d5c1f2d710022b7d60245077e7942079bfb7ef3fc8c1ae78d61e96278525ba46719b15ab12fced5c7603777105bc898695339d7c97c64d300ed0b - languageName: node - linkType: hard - "strip-bom@npm:^3.0.0": version: 3.0.0 resolution: "strip-bom@npm:3.0.0" @@ -56819,7 +56519,7 @@ __metadata: languageName: node linkType: hard -"symbol-observable@npm:^1.0.2, symbol-observable@npm:^1.0.3, symbol-observable@npm:^1.0.4": +"symbol-observable@npm:^1.0.4": version: 1.2.0 resolution: "symbol-observable@npm:1.2.0" checksum: 10c0/009fee50798ef80ed4b8195048288f108b03de162db07493f2e1fd993b33fafa72d659e832b584da5a2427daa78e5a738fb2a9ab027ee9454252e0bedbcd1fdc @@ -60540,13 +60240,6 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:^2.0.0, whatwg-fetch@npm:^2.0.3": - version: 2.0.4 - resolution: "whatwg-fetch@npm:2.0.4" - checksum: 10c0/bf2bc1617218c63f2be86edefb95ac5e7f967ae402e468ed550729436369725c3b03a5d1110f62ea789b6f7f399969b1ef720b0bb04e8947fdf94eab7ffac829 - languageName: node - linkType: hard - "whatwg-fetch@npm:^3.6.2": version: 3.6.20 resolution: "whatwg-fetch@npm:3.6.20" @@ -60684,13 +60377,6 @@ __metadata: languageName: node linkType: hard -"which-module@npm:^1.0.0": - version: 1.0.0 - resolution: "which-module@npm:1.0.0" - checksum: 10c0/ce5088fb12dae0b6d5997b6221342943ff6275c3b2cd9c569f04ec23847c71013d254c6127d531010dccc22c0fc0f8dce2b6ecf6898941a60b576adb2018af22 - languageName: node - linkType: hard - "which-module@npm:^2.0.0": version: 2.0.1 resolution: "which-module@npm:2.0.1" @@ -61259,16 +60945,6 @@ __metadata: languageName: node linkType: hard -"wrap-ansi@npm:^2.0.0": - version: 2.1.0 - resolution: "wrap-ansi@npm:2.1.0" - dependencies: - string-width: "npm:^1.0.1" - strip-ansi: "npm:^3.0.1" - checksum: 10c0/1a47367eef192fc9ecaf00238bad5de8987c3368082b619ab36c5e2d6d7b0a2aef95a2ca65840be598c56ced5090a3ba487956c7aee0cac7c45017502fa980fb - languageName: node - linkType: hard - "wrap-ansi@npm:^5.1.0": version: 5.1.0 resolution: "wrap-ansi@npm:5.1.0" @@ -61543,13 +61219,6 @@ __metadata: languageName: node linkType: hard -"y18n@npm:^3.2.1": - version: 3.2.2 - resolution: "y18n@npm:3.2.2" - checksum: 10c0/08dc1880f6f766057ed25cd61ef0c7dab3db93639db9a7487a84f75dac7a349dface8dff8d1d8b7bdf50969fcd69ab858ab26b06968b4e4b12ee60d195233c46 - languageName: node - linkType: hard - "y18n@npm:^4.0.0": version: 4.0.3 resolution: "y18n@npm:4.0.3" @@ -61663,16 +61332,6 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^5.0.1": - version: 5.0.1 - resolution: "yargs-parser@npm:5.0.1" - dependencies: - camelcase: "npm:^3.0.0" - object.assign: "npm:^4.1.0" - checksum: 10c0/94f24930da4eb80c6ba1c308e1d187a6cab6206f08cda8654b3ebbd0d20f689c113a5111898e90c5885fdc39ce68de5a59aca703f2578335af644ba8f239166f - languageName: node - linkType: hard - "yargs-unparser@npm:^2.0.0": version: 2.0.0 resolution: "yargs-unparser@npm:2.0.0" @@ -61753,27 +61412,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^7.1.0": - version: 7.1.2 - resolution: "yargs@npm:7.1.2" - dependencies: - camelcase: "npm:^3.0.0" - cliui: "npm:^3.2.0" - decamelize: "npm:^1.1.1" - get-caller-file: "npm:^1.0.1" - os-locale: "npm:^1.4.0" - read-pkg-up: "npm:^1.0.1" - require-directory: "npm:^2.1.1" - require-main-filename: "npm:^1.0.1" - set-blocking: "npm:^2.0.0" - string-width: "npm:^1.0.2" - which-module: "npm:^1.0.0" - y18n: "npm:^3.2.1" - yargs-parser: "npm:^5.0.1" - checksum: 10c0/ca7dc99af8335a731cf8255bc5a8a782e0d591de21ff7e4abc8f65ad58acab638a5760f368d64a8dcc4f8cb2978ecba45f459c8c5368203cf6339be7e395cdb5 - languageName: node - linkType: hard - "yauzl@npm:^2.10.0": version: 2.10.0 resolution: "yauzl@npm:2.10.0" @@ -61872,13 +61510,6 @@ __metadata: languageName: node linkType: hard -"zen-observable-ts@npm:^0.4.4": - version: 0.4.4 - resolution: "zen-observable-ts@npm:0.4.4" - checksum: 10c0/02e3d9849607c27b6c910298eea54c1ac932a51f61ac946cb71a887c37dc1195708fa378ddeb583d0820fe8279a68b312ca687fa9b22301ccdb84f3c53c5c883 - languageName: node - linkType: hard - "zen-observable-ts@npm:^1.2.5": version: 1.2.5 resolution: "zen-observable-ts@npm:1.2.5"