diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 082a0a423a..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,13 +0,0 @@ -# Copied from '.gitignore', please keep it in sync. -/.eslintcache -/.docusaurus -/.stryker-tmp -/node_modules -/reports -/npmDist -/npmEsmDist -/denoDist -/websiteDist - -# Ignore TS files inside integration test -/integrationTests/ts/*.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 3262334a41..0000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,842 +0,0 @@ -module.exports = { - parserOptions: { - sourceType: 'script', - }, - env: { - es2022: true, - 'shared-node-browser': true, - }, - reportUnusedDisableDirectives: true, - plugins: ['n', 'import', 'simple-import-sort'], - settings: { - // eslint-plugin-import tries to parse all imported files included huge ones (e.g. 'typescript') - // that leads to very poor perfomance so to fix that we disable all checks on external files. - 'import/ignore': '/node_modules/', - }, - rules: { - ////////////////////////////////////////////////////////////////////////////// - // Internal rules located in 'resources/eslint-internal-rules'. - ////////////////////////////////////////////////////////////////////////////// - - 'only-ascii': 'error', - 'no-dir-import': 'error', - 'require-to-string-tag': 'off', - - ////////////////////////////////////////////////////////////////////////////// - // `eslint-plugin-n` rule list based on `v15.7.x` - ////////////////////////////////////////////////////////////////////////////// - - // Possible Errors - // https://github.com/eslint-community/eslint-plugin-n#possible-errors - 'n/handle-callback-err': ['error', 'error'], - 'n/no-callback-literal': 'error', - 'n/no-exports-assign': 'error', - 'n/no-extraneous-import': 'error', - 'n/no-extraneous-require': 'error', - 'n/no-missing-import': 'error', - 'n/no-missing-require': 'error', - 'n/no-new-require': 'error', - 'n/no-path-concat': 'error', - 'n/no-process-exit': 'off', - 'n/no-unpublished-bin': 'error', - 'n/no-unpublished-import': 'error', - 'n/no-unpublished-require': 'error', - 'n/no-unsupported-features/es-builtins': 'error', - 'n/no-unsupported-features/es-syntax': ['error', { ignores: ['modules'] }], - 'n/no-unsupported-features/node-builtins': 'error', - 'n/process-exit-as-throw': 'error', - 'n/shebang': 'error', - - // Best Practices - // https://github.com/eslint-community/eslint-plugin-n#best-practices - 'n/no-deprecated-api': 'error', - - // Stylistic Issues - // https://github.com/eslint-community/eslint-plugin-n#stylistic-issues - 'n/callback-return': 'error', - 'n/exports-style': 'off', // TODO: consider - 'n/file-extension-in-import': 'error', - 'n/global-require': 'error', - 'n/no-mixed-requires': 'error', - 'n/no-process-env': 'off', - 'n/no-restricted-import': 'off', - 'n/no-restricted-require': 'off', - 'n/no-sync': 'error', - 'n/prefer-global/buffer': 'error', - 'n/prefer-global/console': 'error', - 'n/prefer-global/process': 'error', - 'n/prefer-global/text-decoder': 'error', - 'n/prefer-global/text-encoder': 'error', - 'n/prefer-global/url-search-params': 'error', - 'n/prefer-global/url': 'error', - 'n/prefer-promises/dns': 'off', - 'n/prefer-promises/fs': 'off', - - ////////////////////////////////////////////////////////////////////////////// - // `eslint-plugin-import` rule list based on `v2.27.x` - ////////////////////////////////////////////////////////////////////////////// - - // Static analysis - // https://github.com/benmosher/eslint-plugin-import#static-analysis - 'import/no-unresolved': 'off', // TODO: blocked by https://github.com/import-js/eslint-plugin-import/issues/2170 - 'import/named': 'error', - 'import/default': 'error', - 'import/namespace': 'error', - 'import/no-restricted-paths': [ - 'error', - { - basePath: './', - zones: [{ target: './src', from: 'src/__testUtils__' }], - }, - ], - 'import/no-absolute-path': 'error', - 'import/no-dynamic-require': 'error', - 'import/no-internal-modules': 'off', - 'import/no-webpack-loader-syntax': 'error', - 'import/no-self-import': 'error', - 'import/no-cycle': 'error', - 'import/no-useless-path-segments': 'error', - 'import/no-relative-parent-imports': 'off', - 'import/no-relative-packages': 'off', - - // Helpful warnings - // https://github.com/benmosher/eslint-plugin-import#helpful-warnings - 'import/export': 'error', - 'import/no-named-as-default': 'error', - 'import/no-named-as-default-member': 'error', - 'import/no-deprecated': 'error', - 'import/no-extraneous-dependencies': ['error', { devDependencies: false }], - 'import/no-mutable-exports': 'error', - 'import/no-unused-modules': 'error', - 'import/no-empty-named-blocks': 'error', - - // Module systems - // https://github.com/benmosher/eslint-plugin-import#module-systems - 'import/unambiguous': 'error', - 'import/no-commonjs': 'error', - 'import/no-amd': 'error', - 'import/no-nodejs-modules': 'error', - 'import/no-import-module-exports': 'off', - - // Style guide - // https://github.com/benmosher/eslint-plugin-import#style-guide - 'import/consistent-type-specifier-style': 'error', - 'import/first': 'error', - 'import/exports-last': 'off', - 'import/no-duplicates': 'error', - 'import/no-namespace': 'error', - 'import/extensions': ['error', 'ignorePackages'], - 'import/order': [ - 'error', - { 'newlines-between': 'always-and-inside-groups' }, - ], - 'import/newline-after-import': 'error', - 'import/prefer-default-export': 'off', - 'import/max-dependencies': 'off', - 'import/no-unassigned-import': 'error', - 'import/no-named-default': 'error', - 'import/no-default-export': 'error', - 'import/no-named-export': 'off', - 'import/no-anonymous-default-export': 'error', - 'import/group-exports': 'off', - 'import/dynamic-import-chunkname': 'off', - - ////////////////////////////////////////////////////////////////////////////// - // `eslint-plugin-simple-import-sort` rule list based on `v10.0.x` - // https://github.com/lydell/eslint-plugin-simple-import-sort - ////////////////////////////////////////////////////////////////////////////// - - 'simple-import-sort/imports': [ - 'error', - { - groups: [ - // Node.js builtin modules - ['^node:\\w'], - - // Packages. - // Things that start with a letter (or digit or underscore), or `@` followed by a letter. - ['^@?\\w'], - - // General utilities - ['^(\\./|(\\.\\./)+)__testUtils__/'], - ['^(\\./|(\\.\\./)+)jsutils/'], - - // Top-level directories - ['^(\\./|(\\.\\./)+)error/'], - ['^(\\./|(\\.\\./)+)language/'], - ['^(\\./|(\\.\\./)+)type/'], - ['^(\\./|(\\.\\./)+)validation/'], - ['^(\\./|(\\.\\./)+)execution/'], - ['^(\\./|(\\.\\./)+)utilities/'], - - // Relative imports. - // Anything that starts with a dot. - ['^(\\.\\./){4,}'], - ['^(\\.\\./){3}'], - ['^(\\.\\./){2}'], - ['^(\\.\\./){1}'], - ['^\\./'], - ], - }, - ], - 'simple-import-sort/exports': 'off', // TODO: error - - ////////////////////////////////////////////////////////////////////////////// - // ESLint builtin rules list based on `v8.38.x` - ////////////////////////////////////////////////////////////////////////////// - - // Possible Errors - // https://eslint.org/docs/latest/rules/#possible-problems - 'array-callback-return': 'error', - 'constructor-super': 'error', - 'for-direction': 'error', - 'getter-return': 'error', - 'no-async-promise-executor': 'error', - 'no-await-in-loop': 'error', - 'no-class-assign': 'error', - 'no-compare-neg-zero': 'error', - 'no-cond-assign': 'error', - 'no-const-assign': 'error', - 'no-constant-binary-expression': 'error', - 'no-constant-condition': 'error', - 'no-constructor-return': 'error', - 'no-control-regex': 'error', - 'no-debugger': 'warn', - 'no-dupe-args': 'error', - 'no-dupe-class-members': 'error', - 'no-dupe-else-if': 'error', - 'no-dupe-keys': 'error', - 'no-duplicate-case': 'error', - 'no-duplicate-imports': 'off', // Superseded by `import/no-duplicates` - 'no-empty-character-class': 'error', - 'no-empty-pattern': 'error', - 'no-ex-assign': 'error', - 'no-fallthrough': 'error', - 'no-func-assign': 'error', - 'no-import-assign': 'error', - 'no-inner-declarations': ['error', 'both'], - 'no-invalid-regexp': 'error', - 'no-irregular-whitespace': 'error', - 'no-loss-of-precision': 'error', - 'no-misleading-character-class': 'error', - 'no-new-native-nonconstructor': 'error', - 'no-new-symbol': 'error', - 'no-obj-calls': 'error', - 'no-promise-executor-return': 'off', // TODO: error - 'no-prototype-builtins': 'error', - 'no-self-assign': 'error', - 'no-self-compare': 'off', // TODO: error - 'no-setter-return': 'error', - 'no-sparse-arrays': 'error', - 'no-template-curly-in-string': 'error', - 'no-this-before-super': 'error', - 'no-undef': 'error', - 'no-unexpected-multiline': 'error', - 'no-unmodified-loop-condition': 'error', - 'no-unreachable': 'error', - 'no-unreachable-loop': 'error', - 'no-unsafe-finally': 'error', - 'no-unsafe-negation': 'error', - 'no-unsafe-optional-chaining': [ - 'error', - { disallowArithmeticOperators: true }, - ], - 'no-unused-private-class-members': 'error', - 'no-unused-vars': [ - 'error', - { vars: 'all', args: 'all', argsIgnorePattern: '^_' }, - ], - 'no-use-before-define': 'off', - 'no-useless-backreference': 'error', - 'require-atomic-updates': 'error', - 'use-isnan': 'error', - 'valid-typeof': 'error', - - // Suggestions - // https://eslint.org/docs/latest/rules/#suggestions - 'accessor-pairs': 'error', - 'arrow-body-style': 'error', - 'block-scoped-var': 'error', - camelcase: 'error', - 'capitalized-comments': 'off', // TODO: consider - 'class-methods-use-this': 'off', - complexity: 'off', - 'consistent-return': 'off', - 'consistent-this': 'error', - curly: 'error', - 'default-case': 'off', - 'default-case-last': 'error', - 'default-param-last': 'error', - 'dot-notation': 'error', - eqeqeq: ['error', 'smart'], - 'func-name-matching': 'off', - 'func-names': ['error', 'as-needed'], // improve debug experience - 'func-style': 'off', - 'grouped-accessor-pairs': 'error', - 'guard-for-in': 'error', - 'id-denylist': 'off', - 'id-length': 'off', - 'id-match': ['error', '^(?:_?[a-zA-Z0-9]*)|[_A-Z0-9]+$'], - 'init-declarations': 'off', - 'logical-assignment-operators': 'error', - 'max-classes-per-file': 'off', - 'max-depth': 'off', - 'max-lines': 'off', - 'max-lines-per-function': 'off', - 'max-nested-callbacks': 'off', - 'max-params': ['error', 5], // TODO: drop to default number, which is 3 - 'max-statements': 'off', - 'multiline-comment-style': 'off', - 'new-cap': 'error', - 'no-alert': 'error', - 'no-array-constructor': 'error', - 'no-bitwise': 'off', - 'no-caller': 'error', - 'no-case-declarations': 'error', - 'no-confusing-arrow': 'off', - 'no-console': 'warn', - 'no-continue': 'off', - 'no-delete-var': 'error', - 'no-div-regex': 'error', - 'no-else-return': 'error', - 'no-empty': 'error', - 'no-empty-function': 'error', - 'no-empty-static-block': 'error', - 'no-eq-null': 'off', - 'no-eval': 'error', - 'no-extend-native': 'error', - 'no-extra-bind': 'error', - 'no-extra-boolean-cast': 'error', - 'no-extra-label': 'error', - 'no-extra-semi': 'off', - 'no-floating-decimal': 'off', - 'no-global-assign': 'error', - 'no-implicit-coercion': 'error', - 'no-implicit-globals': 'off', - 'no-implied-eval': 'error', - 'no-inline-comments': 'off', - 'no-invalid-this': 'error', - 'no-iterator': 'error', - 'no-label-var': 'error', - 'no-labels': 'error', - 'no-lone-blocks': 'error', - 'no-lonely-if': 'error', - 'no-loop-func': 'error', - 'no-magic-numbers': 'off', - 'no-mixed-operators': 'off', - 'no-multi-assign': 'off', - 'no-multi-str': 'error', - 'no-negated-condition': 'off', - 'no-nested-ternary': 'off', - 'no-new': 'error', - 'no-new-func': 'error', - 'no-new-object': 'error', - 'no-new-wrappers': 'error', - 'no-nonoctal-decimal-escape': 'error', - 'no-octal': 'error', - 'no-octal-escape': 'error', - 'no-param-reassign': 'error', - 'no-plusplus': 'off', - 'no-proto': 'error', - 'no-redeclare': 'error', - 'no-regex-spaces': 'error', - 'no-restricted-exports': [ - 'error', - { restrictDefaultExports: { direct: true } }, - ], - 'no-restricted-globals': 'off', - 'no-restricted-imports': 'off', - 'no-restricted-properties': 'off', - 'no-restricted-syntax': [ - 'error', - { - selector: 'TemplateElement[value.raw=/ \\n/]', - message: - 'String literals should not contain trailing spaces. If needed for tests please disable locally using eslint comment', - }, - ], - 'no-return-assign': 'error', - 'no-return-await': 'error', - 'no-script-url': 'error', - 'no-sequences': 'error', - 'no-shadow': 'error', - 'no-shadow-restricted-names': 'error', - 'no-ternary': 'off', - 'no-throw-literal': 'error', - 'no-undef-init': 'error', - 'no-undefined': 'off', - 'no-underscore-dangle': 'off', // TODO: error - 'no-unneeded-ternary': 'error', - 'no-unused-expressions': 'error', - 'no-unused-labels': 'error', - 'no-useless-call': 'error', - 'no-useless-catch': 'error', - 'no-useless-computed-key': 'error', - 'no-useless-concat': 'error', - 'no-useless-constructor': 'error', - 'no-useless-escape': 'error', - 'no-useless-rename': 'error', - 'no-useless-return': 'error', - 'no-var': 'error', - 'no-void': 'error', - 'no-warning-comments': 'off', - 'no-with': 'error', - 'object-shorthand': 'error', - 'one-var': ['error', 'never'], - 'one-var-declaration-per-line': 'off', - 'operator-assignment': 'error', - 'prefer-arrow-callback': 'error', - 'prefer-const': 'error', - 'prefer-destructuring': 'off', - 'prefer-exponentiation-operator': 'error', - 'prefer-named-capture-group': 'off', // TODO: needs a better support in TS, see https://github.com/microsoft/TypeScript/issues/32098 - 'prefer-numeric-literals': 'error', - 'prefer-object-has-own': 'error', - 'prefer-object-spread': 'error', - 'prefer-promise-reject-errors': 'error', - 'prefer-regex-literals': 'error', - 'prefer-rest-params': 'off', // TODO: error - 'prefer-spread': 'error', - 'prefer-template': 'off', - 'quote-props': ['error', 'as-needed'], - radix: 'error', - 'require-await': 'error', - 'require-unicode-regexp': 'off', - 'require-yield': 'error', - 'sort-imports': 'off', - 'sort-keys': 'off', - 'sort-vars': 'off', - 'spaced-comment': 'error', - strict: 'error', - 'symbol-description': 'off', - 'vars-on-top': 'error', - yoda: ['error', 'never', { exceptRange: true }], - - // Layout & Formatting - // https://eslint.org/docs/latest/rules/#layout--formatting - 'line-comment-position': 'off', - 'lines-around-comment': 'off', - 'lines-between-class-members': [ - 'error', - 'always', - { exceptAfterSingleLine: true }, - ], - 'max-statements-per-line': 'off', - 'no-tabs': 'error', - 'padding-line-between-statements': 'off', - quotes: ['error', 'single', { avoidEscape: true }], - - // Bellow rules are disabled because coflicts with Prettier, see: - // https://github.com/prettier/eslint-config-prettier/blob/master/index.js - 'array-bracket-newline': 'off', - 'array-bracket-spacing': 'off', - 'array-element-newline': 'off', - 'arrow-parens': 'off', - 'arrow-spacing': 'off', - 'block-spacing': 'off', - 'brace-style': 'off', - 'comma-dangle': 'off', - 'comma-spacing': 'off', - 'comma-style': 'off', - 'computed-property-spacing': 'off', - 'dot-location': 'off', - 'eol-last': 'off', - 'func-call-spacing': 'off', - 'function-call-argument-newline': 'off', - 'function-paren-newline': 'off', - 'generator-star-spacing': 'off', - 'implicit-arrow-linebreak': 'off', - indent: 'off', - 'jsx-quotes': 'off', - 'key-spacing': 'off', - 'keyword-spacing': 'off', - 'linebreak-style': 'off', - 'max-len': 'off', - 'multiline-ternary': 'off', - 'newline-per-chained-call': 'off', - 'new-parens': 'off', - 'no-extra-parens': 'off', - 'no-mixed-spaces-and-tabs': 'off', - 'no-multi-spaces': 'off', - 'no-multiple-empty-lines': 'off', - 'no-trailing-spaces': 'off', - 'no-whitespace-before-property': 'off', - 'nonblock-statement-body-position': 'off', - 'object-curly-newline': 'off', - 'object-curly-spacing': 'off', - 'object-property-newline': 'off', - 'operator-linebreak': 'off', - 'padded-blocks': 'off', - 'rest-spread-spacing': 'off', - semi: 'off', - 'semi-spacing': 'off', - 'semi-style': 'off', - 'space-before-blocks': 'off', - 'space-before-function-paren': 'off', - 'space-in-parens': 'off', - 'space-infix-ops': 'off', - 'space-unary-ops': 'off', - 'switch-colon-spacing': 'off', - 'template-curly-spacing': 'off', - 'template-tag-spacing': 'off', - 'unicode-bom': 'off', - 'wrap-iife': 'off', - 'wrap-regex': 'off', - 'yield-star-spacing': 'off', - }, - overrides: [ - { - files: 'integrationTests/node-esm/**/*.js', - parserOptions: { - sourceType: 'module', - }, - }, - { - files: '**/*.ts', - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - project: ['tsconfig.json'], - }, - plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'], - extends: ['plugin:import/typescript'], - rules: { - ////////////////////////////////////////////////////////////////////////// - // `eslint-plugin-tsdoc` rule list based on `v0.2.x` - // https://github.com/microsoft/tsdoc/tree/master/eslint-plugin - ////////////////////////////////////////////////////////////////////////// - - 'tsdoc/syntax': 'error', - - ////////////////////////////////////////////////////////////////////////// - // `@typescript-eslint/eslint-plugin` rule list based on `v5.58.x` - ////////////////////////////////////////////////////////////////////////// - - // Supported Rules - // https://typescript-eslint.io/rules/#extension-rules - '@typescript-eslint/adjacent-overload-signatures': 'error', - '@typescript-eslint/array-type': ['error', { default: 'generic' }], - '@typescript-eslint/await-thenable': 'error', - '@typescript-eslint/ban-ts-comment': [ - 'error', - { 'ts-expect-error': false }, - ], - '@typescript-eslint/ban-tslint-comment': 'error', - '@typescript-eslint/ban-types': 'off', // TODO: temporarily disabled - '@typescript-eslint/class-literal-property-style': 'off', // TODO: enable after TS conversion - '@typescript-eslint/consistent-generic-constructors': 'error', - '@typescript-eslint/consistent-indexed-object-style': [ - 'error', - 'index-signature', - ], - '@typescript-eslint/consistent-type-assertions': 'off', // TODO: temporarily disable - '@typescript-eslint/consistent-type-definitions': 'error', - '@typescript-eslint/consistent-type-exports': 'error', - '@typescript-eslint/consistent-type-imports': 'error', - '@typescript-eslint/explicit-function-return-type': 'off', // TODO: consider - '@typescript-eslint/explicit-member-accessibility': 'off', // TODO: consider - '@typescript-eslint/explicit-module-boundary-types': 'off', // TODO: consider - '@typescript-eslint/member-ordering': 'error', - '@typescript-eslint/method-signature-style': 'error', - '@typescript-eslint/naming-convention': 'off', // TODO: consider - '@typescript-eslint/no-base-to-string': 'error', - '@typescript-eslint/no-confusing-non-null-assertion': 'error', - '@typescript-eslint/no-confusing-void-expression': 'off', // TODO: enable with ignoreArrowShorthand - '@typescript-eslint/no-duplicate-enum-values': 'error', - '@typescript-eslint/no-duplicate-type-constituents': 'error', - '@typescript-eslint/no-dynamic-delete': 'off', - '@typescript-eslint/no-empty-interface': 'error', - '@typescript-eslint/no-explicit-any': 'off', // TODO: error - '@typescript-eslint/no-extra-non-null-assertion': 'error', - '@typescript-eslint/no-extraneous-class': 'off', // TODO: consider - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/no-for-in-array': 'error', - '@typescript-eslint/no-implicit-any-catch': 'off', // TODO: Enable after TS conversion - '@typescript-eslint/no-import-type-side-effects': 'error', - '@typescript-eslint/no-implied-eval': 'error', - '@typescript-eslint/no-inferrable-types': [ - 'error', - { ignoreParameters: true, ignoreProperties: true }, - ], - '@typescript-eslint/no-misused-new': 'error', - '@typescript-eslint/no-misused-promises': 'error', - '@typescript-eslint/no-mixed-enums': 'error', - '@typescript-eslint/no-namespace': 'error', - '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', - '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', - '@typescript-eslint/no-non-null-assertion': 'error', - '@typescript-eslint/no-redundant-type-constituents': 'error', - '@typescript-eslint/no-invalid-void-type': 'error', - '@typescript-eslint/no-require-imports': 'error', - '@typescript-eslint/no-this-alias': 'error', - '@typescript-eslint/no-type-alias': 'off', // TODO: consider - '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', - '@typescript-eslint/no-unnecessary-condition': 'off', // TODO: temporary disable - '@typescript-eslint/no-unnecessary-qualifier': 'error', - '@typescript-eslint/no-unnecessary-type-arguments': 'error', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unnecessary-type-constraint': 'error', - '@typescript-eslint/no-unsafe-argument': 'off', // TODO: consider - '@typescript-eslint/no-unsafe-assignment': 'off', // TODO: consider - '@typescript-eslint/no-unsafe-call': 'off', // TODO: consider - '@typescript-eslint/no-unsafe-declaration-merging': 'error', - '@typescript-eslint/no-unsafe-enum-comparison': 'off', // TODO: error - '@typescript-eslint/no-unsafe-member-access': 'off', // TODO: consider - '@typescript-eslint/no-unsafe-return': 'off', // TODO: consider - '@typescript-eslint/no-useless-empty-export': 'error', - '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/non-nullable-type-assertion-style': 'off', //TODO: temporarily disabled - '@typescript-eslint/parameter-properties': 'error', - '@typescript-eslint/prefer-as-const': 'error', - '@typescript-eslint/prefer-enum-initializers': 'error', - '@typescript-eslint/prefer-for-of': 'error', - '@typescript-eslint/prefer-function-type': 'error', - '@typescript-eslint/prefer-includes': 'error', - '@typescript-eslint/prefer-literal-enum-member': 'error', - '@typescript-eslint/prefer-namespace-keyword': 'error', - '@typescript-eslint/prefer-nullish-coalescing': 'error', - '@typescript-eslint/prefer-optional-chain': 'error', - '@typescript-eslint/prefer-readonly': 'off', - '@typescript-eslint/prefer-readonly-parameter-types': 'off', // TODO: consider - '@typescript-eslint/prefer-reduce-type-parameter': 'error', - '@typescript-eslint/prefer-regexp-exec': 'off', - '@typescript-eslint/prefer-return-this-type': 'error', - '@typescript-eslint/prefer-string-starts-ends-with': 'error', - '@typescript-eslint/prefer-ts-expect-error': 'error', - '@typescript-eslint/promise-function-async': 'off', - '@typescript-eslint/require-array-sort-compare': 'error', - '@typescript-eslint/restrict-plus-operands': 'off', // TODO: temporarily disabled - '@typescript-eslint/restrict-template-expressions': 'off', // TODO: temporarily disabled - '@typescript-eslint/sort-type-union-intersection-members': 'off', // TODO: consider - '@typescript-eslint/strict-boolean-expressions': [ - 'error', - { allowNullableBoolean: true }, // TODO: consider removing - ], - '@typescript-eslint/switch-exhaustiveness-check': 'error', - '@typescript-eslint/triple-slash-reference': 'error', - '@typescript-eslint/typedef': 'off', - '@typescript-eslint/unbound-method': 'off', // TODO: consider - '@typescript-eslint/unified-signatures': 'error', - - // Extension Rules - // https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#extension-rules - - // Disable conflicting ESLint rules and enable TS-compatible ones - 'default-param-last': 'off', - 'dot-notation': 'off', - 'lines-between-class-members': 'off', - 'no-array-constructor': 'off', - 'no-dupe-class-members': 'off', - 'no-empty-function': 'off', - 'no-invalid-this': 'off', - 'no-loop-func': 'off', - 'no-loss-of-precision': 'off', - 'no-redeclare': 'off', - 'no-throw-literal': 'off', - 'no-shadow': 'off', - 'no-unused-expressions': 'off', - 'no-unused-vars': 'off', - 'no-useless-constructor': 'off', - 'require-await': 'off', - 'no-return-await': 'off', - - '@typescript-eslint/default-param-last': 'error', - '@typescript-eslint/dot-notation': 'error', - '@typescript-eslint/lines-around-comment': 'off', - '@typescript-eslint/lines-between-class-members': [ - 'error', - 'always', - { exceptAfterSingleLine: true }, - ], - '@typescript-eslint/no-array-constructor': 'error', - '@typescript-eslint/no-dupe-class-members': 'error', - '@typescript-eslint/no-empty-function': 'error', - '@typescript-eslint/no-invalid-this': 'error', - '@typescript-eslint/no-loop-func': 'error', - '@typescript-eslint/no-loss-of-precision': 'error', - '@typescript-eslint/no-redeclare': 'error', - '@typescript-eslint/no-throw-literal': 'error', // TODO: [error, { allowThrowingAny: false, allowThrowingUnknown: false }] - '@typescript-eslint/no-shadow': 'error', - '@typescript-eslint/no-unused-expressions': 'error', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - vars: 'all', - args: 'all', - argsIgnorePattern: '^_', - varsIgnorePattern: '^_T', - }, - ], - '@typescript-eslint/no-useless-constructor': 'error', - '@typescript-eslint/require-await': 'error', - '@typescript-eslint/return-await': 'error', - - // Disable for JS and TS - '@typescript-eslint/init-declarations': 'off', - '@typescript-eslint/no-magic-numbers': 'off', - '@typescript-eslint/no-restricted-imports': 'off', - '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-duplicate-imports': 'off', // Superseded by `import/no-duplicates` - - // Below rules are disabled because they conflict with Prettier, see: - // https://github.com/prettier/eslint-config-prettier/blob/main/index.js - '@typescript-eslint/block-spacing': 'off', - '@typescript-eslint/object-curly-spacing': 'off', - '@typescript-eslint/quotes': 'off', - '@typescript-eslint/brace-style': 'off', - '@typescript-eslint/comma-dangle': 'off', - '@typescript-eslint/comma-spacing': 'off', - '@typescript-eslint/func-call-spacing': 'off', - '@typescript-eslint/indent': 'off', - '@typescript-eslint/key-spacing': 'off', - '@typescript-eslint/keyword-spacing': 'off', - '@typescript-eslint/member-delimiter-style': 'off', - '@typescript-eslint/no-extra-parens': 'off', - '@typescript-eslint/no-extra-semi': 'off', - '@typescript-eslint/semi': 'off', - '@typescript-eslint/space-before-blocks': 'off', - '@typescript-eslint/space-before-function-paren': 'off', - '@typescript-eslint/space-infix-ops': 'off', - '@typescript-eslint/type-annotation-spacing': 'off', - }, - }, - { - files: 'src/**', - rules: { - 'require-to-string-tag': 'error', - }, - }, - { - files: 'src/**/__*__/**', - rules: { - 'require-to-string-tag': 'off', - 'n/no-unpublished-import': [ - 'error', - { allowModules: ['chai', 'mocha'] }, - ], - 'import/no-deprecated': 'off', - 'import/no-restricted-paths': 'off', - 'import/no-extraneous-dependencies': [ - 'error', - { devDependencies: true }, - ], - }, - }, - { - files: 'integrationTests/*', - env: { - node: true, - }, - rules: { - 'n/no-sync': 'off', - 'n/no-unpublished-import': ['error', { allowModules: ['mocha'] }], - 'import/no-extraneous-dependencies': [ - 'error', - { devDependencies: true }, - ], - 'import/no-namespace': 'off', - 'import/no-nodejs-modules': 'off', - }, - }, - { - files: 'integrationTests/*/**', - parserOptions: { - sourceType: 'module', - }, - env: { - node: true, - }, - rules: { - 'n/no-sync': 'off', - 'import/no-nodejs-modules': 'off', - 'no-console': 'off', - 'n/no-missing-import': ['error', { allowModules: ['graphql'] }], - }, - }, - { - files: 'benchmark/**', - parserOptions: { - sourceType: 'module', - }, - env: { - node: true, - }, - rules: { - 'n/no-sync': 'off', - 'n/no-missing-import': ['error', { allowModules: ['graphql'] }], - 'n/no-extraneous-import': ['error', { allowModules: ['graphql'] }], - 'import/no-unresolved': 'off', - 'import/no-namespace': 'off', - 'import/no-nodejs-modules': 'off', - 'import/no-extraneous-dependencies': 'off', - }, - }, - { - files: 'resources/**', - env: { - node: true, - }, - rules: { - 'only-ascii': ['error', { allowEmoji: true }], - 'n/no-unpublished-import': 'off', - 'n/no-sync': 'off', - 'import/no-namespace': 'off', - 'import/no-extraneous-dependencies': [ - 'error', - { devDependencies: true }, - ], - 'import/no-nodejs-modules': 'off', - 'no-console': 'off', - }, - }, - { - files: 'resources/eslint-internal-rules/**', - env: { - node: true, - }, - rules: { - 'import/no-commonjs': 'off', - }, - }, - { - files: '**/*.jsx', - parserOptions: { - sourceType: 'module', - ecmaFeatures: { - jsx: true, - }, - }, - rules: { - 'n/no-unpublished-import': 'off', - 'import/no-default-export': 'off', - }, - }, - { - files: 'website/**', - env: { - node: true, - }, - plugins: ['react'], - extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], - settings: { - react: { - version: 'detect', - }, - }, - rules: { - 'no-restricted-exports': 'off', - 'n/no-unpublished-require': 'off', - 'import/no-default-export': 'off', - 'import/no-commonjs': 'off', - 'import/no-nodejs-modules': 'off', - 'import/no-extraneous-dependencies': 'off', - // Ignore docusarus related webpack aliases - 'n/no-missing-import': 'off', - 'import/no-unresolved': [ - 'error', - { ignore: ['^@theme', '^@docusaurus', '^@generated'] }, - ], - }, - }, - ], -}; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..fffb2cb1dc --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @graphql/graphql-js-reviewers diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3b4e6dd2e7..9473508c88 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,14 +2,13 @@ We want to make contributing to this project as easy and transparent as possible. Hopefully this document makes the process for contributing clear and -answers any questions you may have. If not, feel free to open an -[Issue](https://github.com/graphql/graphql-spec/issues/). +answers any questions you may have. ## Issues We use GitHub issues to track public bugs and requests. Please ensure your bug description is clear and has sufficient instructions to be able to reproduce the -issue. The best way is to provide a reduced test case on jsFiddle or jsBin. +issue. The absolute best way to do that is to add a failing test to our test suite via a pull request, but a reduced test case on a site like [StackBlitz](https://stackblitz.com/) or [CodeSandbox](https://codesandbox.io/) is also very helpful. ## Pull Requests @@ -21,8 +20,8 @@ your [pull requests](https://help.github.com/articles/creating-a-pull-request). Since graphql-js is a reference implementation of the [GraphQL spec](https://graphql.github.io/graphql-spec/), only changes which comply with this spec will be considered. If you have a change in mind which requires a -change to the spec, please first open an -[issue](https://github.com/graphql/graphql-spec/issues/) against the spec. +change to the spec, please consider opening an +[issue](https://github.com/graphql/graphql-spec/issues/) against the spec and/or attending a [GraphQL Working Group meeting](https://github.com/graphql/graphql-wg) to discuss your proposed change. See the [contribution guide of the specification](https://github.com/graphql/graphql-spec/blob/main/CONTRIBUTING.md) for further information. Stage 1 and 2 proposals may be implemented within graphql-js behind a feature flag. ### GraphQL Specification Membership Agreement @@ -74,6 +73,17 @@ ensure your pull request matches the style guides, run `npm run prettier`. - Trailing commas, - Avd abbr wrds. +## Review and Merge Process + +- Pull requests are required to pass all tests and checks before they can be merged. +- Ideally, pull requests should be reviewed by _at least two_ members of the [`@graphql/graphql-js-reviewers`](https://github.com/orgs/graphql/teams/graphql-js-reviewers) team before they are merged, preferably from separate organizations. For more complex pull requests, a larger cohort of reviewers is suggested. +- Any reviewer may request that the topic be brought for more in depth discussion at a [GraphQL JS Working Group meeting](https://github.com/graphql/graphql-js-wg/), where decisions will be made by consensus. +- A PR that has been merged without discussion at a GraphQL JS Working Group meeting can be revisited in any subsequent meeting; the PR may be reverted as a result of that discussion. + +## Discussion + +Feel free to reach out via the [graphql-js channel](https://discord.com/channels/625400653321076807/862957336082645006) on the [official Discord server](https://discord.graphql.org/) to discuss issues, pull requests, or anything graphql-js related. + ## Release on NPM _Only core contributors may release to NPM._ @@ -83,18 +93,22 @@ then use `npm version patch|minor|major` in order to increment the version in package.json and tag and commit a release. Then `git push && git push --tags` to sync this change with source control. Then `npm publish npmDist` to actually publish the release to NPM. -Once published, add [release notes](https://github.com/graphql/graphql-js/tags). +Once published, add [release notes](https://github.com/graphql/graphql-js/releases). Use [semver](https://semver.org/) to determine which version part to increment. Example for a patch release: ```sh +npm ci npm test npm version patch git push --follow-tags -npm publish npmDist +cd npmDist && npm publish +npm run changelog ``` +Then upload the changelog to [https://github.com/graphql/graphql-js/releases](https://github.com/graphql/graphql-js/releases). + ## License By contributing to graphql-js, you agree that your contributions will be diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8a257ce01..20cb72df95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,12 +9,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -46,7 +46,7 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false @@ -71,12 +71,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -100,12 +100,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.node-version' # We install bunch of packages during integration tests without locking them @@ -124,12 +124,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -150,12 +150,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js v${{ matrix.node_version_to_setup }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version: ${{ matrix.node_version_to_setup }} @@ -174,17 +174,17 @@ jobs: security-events: write # for codeql-action steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: 'javascript, typescript' - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 build-npm-dist: name: Build 'npmDist' artifact @@ -193,12 +193,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -210,7 +210,7 @@ jobs: run: npm run build:npm - name: Upload npmDist package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: npmDist path: ./npmDist @@ -222,12 +222,12 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -239,36 +239,7 @@ jobs: run: npm run build:deno - name: Upload denoDist package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: denoDist path: ./denoDist - - build-website-dist: - name: Build website - runs-on: ubuntu-latest - permissions: - contents: read # for actions/checkout - steps: - - name: Checkout repo - uses: actions/checkout@v3 - with: - persist-credentials: false - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - cache: npm - node-version-file: '.node-version' - - - name: Install Dependencies - run: npm ci --ignore-scripts - - - name: Build Docs - run: npm run build:website - - - name: Upload denoDist package - uses: actions/upload-artifact@v3 - with: - name: websiteDist - path: ./websiteDist diff --git a/.github/workflows/cmd-publish-pr-on-npm.yml b/.github/workflows/cmd-publish-pr-on-npm.yml index 69a0af1607..57441117c2 100644 --- a/.github/workflows/cmd-publish-pr-on-npm.yml +++ b/.github/workflows/cmd-publish-pr-on-npm.yml @@ -18,13 +18,13 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false ref: ${{ fromJSON(inputs.pull_request_json).merge_commit_sha }} - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -36,7 +36,7 @@ jobs: run: npm run build:npm - name: Upload npmDist package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: npmDist path: ./npmDist @@ -50,19 +50,19 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' # 'registry-url' is required for 'npm publish' registry-url: 'https://registry.npmjs.org' - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: npmDist path: npmDist @@ -70,7 +70,7 @@ jobs: - name: Modify NPM package to be canary release env: PULL_REQUEST_JSON: ${{ inputs.pull_request_json }} - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const fs = require('node:fs'); @@ -113,7 +113,7 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.npm_canary_pr_publish_token }} - name: Upload replyMessage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: replyMessage path: ./replyMessage.txt diff --git a/.github/workflows/cmd-run-benchmark.yml b/.github/workflows/cmd-run-benchmark.yml index 22266d0af8..eec12c4ff2 100644 --- a/.github/workflows/cmd-run-benchmark.yml +++ b/.github/workflows/cmd-run-benchmark.yml @@ -16,7 +16,7 @@ jobs: actions: read # to list workflow runs steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false ref: ${{ fromJSON(inputs.pull_request_json).merge_commit_sha }} @@ -27,7 +27,7 @@ jobs: run: 'git fetch --depth=1 origin "$BASE_SHA:refs/tags/BASE"' - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -40,7 +40,7 @@ jobs: npm run benchmark -- --revs HEAD BASE - name: Create replyMessage - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const fs = require('node:fs'); @@ -63,7 +63,7 @@ jobs: ); - name: Upload replyMessage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: replyMessage path: ./replyMessage.txt diff --git a/.github/workflows/deploy-artifact-as-branch.yml b/.github/workflows/deploy-artifact-as-branch.yml index bdf08290ab..dc17b9093d 100644 --- a/.github/workflows/deploy-artifact-as-branch.yml +++ b/.github/workflows/deploy-artifact-as-branch.yml @@ -29,14 +29,14 @@ jobs: contents: write # for actions/checkout and to push branch steps: - name: Checkout `${{ inputs.target_branch }}` branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ inputs.target_branch }} - name: Remove existing files first run: git rm -r . - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: ${{ inputs.artifact_name }} diff --git a/.github/workflows/github-actions-bot.yml b/.github/workflows/github-actions-bot.yml index a930e29357..94efd23aed 100644 --- a/.github/workflows/github-actions-bot.yml +++ b/.github/workflows/github-actions-bot.yml @@ -38,7 +38,7 @@ jobs: WORKFLOW_ID: ${{github.event.workflow_run.id}} - name: Add comment on PR - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const fs = require('node:fs'); @@ -64,7 +64,7 @@ jobs: cmd: ${{ steps.parse-cmd.outputs.cmd }} pull_request_json: ${{ steps.parse-cmd.outputs.pull_request_json }} steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: script: | await github.rest.reactions.createForIssueComment({ @@ -74,7 +74,7 @@ jobs: }); - id: parse-cmd - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const comment = context.payload.comment.body; @@ -115,12 +115,12 @@ jobs: permissions: pull-requests: write # to add comment to pull request steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: replyMessage - if: failure() - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const fs = require('node:fs'); @@ -144,7 +144,7 @@ jobs: RUN_URL: ${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}} - if: always() - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const fs = require('node:fs'); diff --git a/.github/workflows/mutation-testing.yml b/.github/workflows/mutation-testing.yml deleted file mode 100644 index 3d5b8b97e9..0000000000 --- a/.github/workflows/mutation-testing.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Mutation Testing -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' # run once every day at 00:00 UTC -permissions: {} -jobs: - lint: - name: Run mutation testing - runs-on: ubuntu-latest - permissions: - contents: read # for actions/checkout - steps: - - name: Checkout repo - uses: actions/checkout@v3 - with: - persist-credentials: false - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - cache: npm - node-version-file: '.node-version' - - - name: Install Dependencies - run: npm ci --ignore-scripts - - - name: Run mutation testing - run: npm run testonly:mutate - - - name: Upload mutation testing report - uses: actions/upload-artifact@v3 - with: - name: mutationTestingReport - path: ./reports/mutation/mutation.html diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 35e2973e59..1754218348 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -15,7 +15,7 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false @@ -29,7 +29,7 @@ jobs: contents: read # for actions/checkout steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: persist-credentials: false @@ -39,7 +39,7 @@ jobs: run: 'git fetch --depth=1 origin "$BASE_SHA:refs/tags/BASE"' - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: cache: npm node-version-file: '.node-version' @@ -51,7 +51,7 @@ jobs: run: 'npm run diff:npm BASE HEAD' - name: Upload generated report - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: npm-dist-diff.html path: ./reports/npm-dist-diff.html diff --git a/.github/workflows/pull_request_opened.yml b/.github/workflows/pull_request_opened.yml index 3d77be3b6c..d0e6aef0ac 100644 --- a/.github/workflows/pull_request_opened.yml +++ b/.github/workflows/pull_request_opened.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Upload event.json - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: event.json path: ${{ github.event_path }} diff --git a/.gitignore b/.gitignore index b3a652de18..47311ceece 100644 --- a/.gitignore +++ b/.gitignore @@ -8,11 +8,10 @@ /diff-npm-package.html /.eslintcache /.cspellcache -/.docusaurus -/.stryker-tmp -/node_modules +node_modules /reports /npmDist /npmEsmDist /denoDist -/websiteDist +/website/.next +/website/out diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000000..f27575a8ed --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npm run precommit diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000000..86a7859e7b --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,5 @@ +{ + "*.{js,ts}": ["eslint --max-warnings 0 --fix", "prettier --write"], + "*.json": "prettier --write", + "*.md": "prettier --write" +} diff --git a/.prettierignore b/.prettierignore index 726959a3f2..3368c0197a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,11 +1,12 @@ # Copied from '.gitignore', please keep it in sync. /diff-npm-package.html /.eslintcache -/.docusaurus -/.stryker-tmp /node_modules /reports /npmDist /npmEsmDist /denoDist -/websiteDist +/website/.next +/website/out +/website/**/*.mdx +.next diff --git a/README.md b/README.md index 5e23874914..8908c605f5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![GraphQLConf 2024 Banner: September 10-12, San Francisco. Hosted by the GraphQL Foundation](https://github.com/user-attachments/assets/2d048502-e5b2-4e9d-a02a-50b841824de6)](https://graphql.org/conf/2024/?utm_source=github&utm_medium=graphql_js&utm_campaign=readme) + # GraphQL.js The JavaScript reference implementation for GraphQL, a query language for APIs created by Facebook. diff --git a/benchmark/fixtures.js b/benchmark/fixtures.js index c4a080713a..b93f075534 100644 --- a/benchmark/fixtures.js +++ b/benchmark/fixtures.js @@ -1,4 +1,4 @@ -import fs from 'fs'; +import fs from 'node:fs'; export const bigSchemaSDL = fs.readFileSync( new URL('github-schema.graphql', import.meta.url), diff --git a/benchmark/github-schema.graphql b/benchmark/github-schema.graphql index 7baa42397a..9986fe8715 100644 --- a/benchmark/github-schema.graphql +++ b/benchmark/github-schema.graphql @@ -3363,7 +3363,7 @@ type CreatedIssueContributionEdge { Represents either a issue the viewer can access or a restricted contribution. """ union CreatedIssueOrRestrictedContribution = - CreatedIssueContribution + | CreatedIssueContribution | RestrictedContribution """ @@ -3447,7 +3447,7 @@ type CreatedPullRequestContributionEdge { Represents either a pull request the viewer can access or a restricted contribution. """ union CreatedPullRequestOrRestrictedContribution = - CreatedPullRequestContribution + | CreatedPullRequestContribution | RestrictedContribution """ @@ -3618,7 +3618,7 @@ type CreatedRepositoryContributionEdge { Represents either a repository the viewer can access or a restricted contribution. """ union CreatedRepositoryOrRestrictedContribution = - CreatedRepositoryContribution + | CreatedRepositoryContribution | RestrictedContribution """ @@ -6635,7 +6635,7 @@ type IssueTimelineConnection { An item in an issue timeline """ union IssueTimelineItem = - Commit + | Commit | IssueComment | CrossReferencedEvent | ClosedEvent @@ -6674,7 +6674,7 @@ type IssueTimelineItemEdge { An item in an issue timeline """ union IssueTimelineItems = - IssueComment + | IssueComment | CrossReferencedEvent | AddedToProjectEvent | AssignedEvent @@ -12534,7 +12534,7 @@ type PullRequestTimelineConnection { An item in an pull request timeline """ union PullRequestTimelineItem = - Commit + | Commit | CommitCommentThread | PullRequestReview | PullRequestReviewThread @@ -12586,7 +12586,7 @@ type PullRequestTimelineItemEdge { An item in a pull request timeline """ union PullRequestTimelineItems = - PullRequestCommit + | PullRequestCommit | PullRequestCommitCommentThread | PullRequestReview | PullRequestReviewThread @@ -16467,7 +16467,7 @@ type ReviewRequestRemovedEvent implements Node { The results of a search. """ union SearchResultItem = - Issue + | Issue | PullRequest | Repository | User diff --git a/cspell.yml b/cspell.yml index 6ae58bbd3f..9454626484 100644 --- a/cspell.yml +++ b/cspell.yml @@ -7,19 +7,26 @@ ignorePaths: - package.json - benchmark/github-schema.graphql - benchmark/github-schema.json + - website/icons + - website/css overrides: - - filename: '**/docs-old/APIReference-*.md' - ignoreRegExpList: ['/href="[^"]*"/'] + - filename: 'eslint.config.*' words: - - sublinks - - instanceof + - chunkname + - nonconstructor + - nonoctal - filename: 'website/**' dictionaries: - fullstack - html words: - - clsx - - infima + - noopener + - Vite + - craco + - esbuild + - swcrc + - noreferrer + - xlink validateDirectives: true ignoreRegExpList: @@ -27,6 +34,8 @@ ignoreRegExpList: words: - graphiql + - uncoerce + - uncoerced # Different names used inside tests - Skywalker @@ -43,6 +52,113 @@ words: # TODO: contribute upstream - deno + - hashbang + + # Website tech + - Nextra + - headlessui + - Fastify + - svgr + - ruru + + # used as href anchors + - graphqlerror + - syntaxerror + - formaterror + - graphqlschema + - graphqlscalartype + - graphqlobjecttype + - graphqlinterfacetype + - graphqluniontype + - graphqlenumtype + - graphqlinputobjecttype + - graphqllist + - graphqlnonnull + - graphqlint + - graphqlfloat + - graphqlstring + - graphqlboolean + - graphqlid + - getlocation + - isinputtype + - isoutputtype + - isleaftype + - iscompositetype + - isabstracttype + - getnullabletype + - getnamedtype + - introspectionquery + - buildclientschema + - buildschema + - printschema + - printintrospectionschema + - buildastschema + - typefromast + - astfromvalue + - typeinfo + - isvalidjsvalue + - isvalidliteralvalue + - specifiedrules + - Wordmark + - codeofconduct + - graphqlconf + + # website words + - runtimes + + # Website tech + - Nextra + - headlessui + - Fastify + - tailwindcss + - svgr + - ruru + - oneof + + # used as href anchors + - graphqlerror + - syntaxerror + - formaterror + - graphqlschema + - graphqlscalartype + - graphqlobjecttype + - graphqlinterfacetype + - graphqluniontype + - graphqlenumtype + - graphqlinputobjecttype + - graphqllist + - graphqlnonnull + - graphqlint + - graphqlfloat + - graphqlstring + - graphqlboolean + - graphqlid + - getlocation + - isinputtype + - isoutputtype + - isleaftype + - iscompositetype + - isabstracttype + - getnullabletype + - getnamedtype + - introspectionquery + - buildclientschema + - buildschema + - printschema + - printintrospectionschema + - buildastschema + - typefromast + - astfromvalue + - typeinfo + - isvalidjsvalue + - isvalidliteralvalue + - specifiedrules + - Wordmark + - codeofconduct + - graphqlconf + + # website words + - runtimes # TODO: remove bellow words - QLID # GraphQLID diff --git a/docs-old/APIReference-GraphQL.md b/docs-old/APIReference-GraphQL.md deleted file mode 100644 index 3aea9e87ba..0000000000 --- a/docs-old/APIReference-GraphQL.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: graphql -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/graphql/ -sublinks: graphql -next: /graphql-js/error/ ---- - -The `graphql` module exports a core subset of GraphQL functionality for creation -of GraphQL type systems and servers. - -```js -import { graphql } from 'graphql'; // ES6 -var { graphql } = require('graphql'); // CommonJS -``` - -## Overview - -_Entry Point_ - - - -_Schema_ - - - -_Type Definitions_ - - - -_Scalars_ - - - -_Errors_ - - - -## Entry Point - -### graphql - -```js -graphql( - schema: GraphQLSchema, - requestString: string, - rootValue?: ?any, - contextValue?: ?any, - variableValues?: ?{[key: string]: any}, - operationName?: ?string -): Promise -``` - -The `graphql` function lexes, parses, validates and executes a GraphQL request. -It requires a `schema` and a `requestString`. Optional arguments include a -`rootValue`, which will get passed as the root value to the executor, a `contextValue`, -which will get passed to all resolve functions, -`variableValues`, which will get passed to the executor to provide values for -any variables in `requestString`, and `operationName`, which allows the caller -to specify which operation in `requestString` will be run, in cases where -`requestString` contains multiple top-level operations. - -## Schema - -See the [Type System API Reference](../type#schema). - -## Type Definitions - -See the [Type System API Reference](../type#definitions). - -## Scalars - -See the [Type System API Reference](../type#scalars). - -## Errors - -See the [Errors API Reference](../error) diff --git a/docs-old/APIReference-Utilities.md b/docs-old/APIReference-Utilities.md deleted file mode 100644 index a9455aadd5..0000000000 --- a/docs-old/APIReference-Utilities.md +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: graphql/utilities -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/utilities/ -sublinks: astFromValue,buildASTSchema,buildClientSchema,buildSchema,introspectionQuery,isValidJSValue,isValidLiteralValue,printIntrospectionSchema,printSchema,typeFromAST,TypeInfo -next: /graphql-js/validation/ ---- - -The `graphql/utilities` module contains common useful computations to use with -the GraphQL language and type objects. You can import either from the `graphql/utilities` module, or from the root `graphql` module. For example: - -```js -import { introspectionQuery } from 'graphql'; // ES6 -var { introspectionQuery } = require('graphql'); // CommonJS -``` - -## Overview - -_Introspection_ - - - -_Schema Language_ - - - -_Visitors_ - - - -_Value Validation_ - - - -## Introspection - -### getIntrospectionQuery - -```js -interface IntrospectionOptions { - // Whether to include descriptions in the introspection result. - // Default: true - descriptions?: boolean; - - // Whether to include `specifiedByUrl` in the introspection result. - // Default: false - specifiedByUrl?: boolean; - - // Whether to include `isRepeatable` flag on directives. - // Default: false - directiveIsRepeatable?: boolean; - - // Whether to include `description` field on schema. - // Default: false - schemaDescription?: boolean; -} - -function getIntrospectionQuery( - options: IntrospectionOptions -): string; -``` - -Build a GraphQL query that queries a server's introspection system for enough -information to reproduce that server's type system. - -### buildClientSchema - -```js -function buildClientSchema( - introspection: IntrospectionQuery -): GraphQLSchema -``` - -Build a GraphQLSchema for use by client tools. - -Given the result of a client running the introspection query, creates and -returns a GraphQLSchema instance which can be then used with all GraphQL.js -tools, but cannot be used to execute a query, as introspection does not -represent the "resolver", "parse" or "serialize" functions or any other -server-internal mechanisms. - -## Schema Representation - -### buildSchema - -```js -function buildSchema(source: string | Source): GraphQLSchema { -``` - -Creates a GraphQLSchema object from GraphQL schema language. The schema will use default resolvers. For more detail on the GraphQL schema language, see the [schema language docs](/learn/schema/) or this [schema language cheat sheet](https://wehavefaces.net/graphql-shorthand-notation-cheatsheet-17cd715861b6#.9oztv0a7n). - -### printSchema - -```js -function printSchema(schema: GraphQLSchema): string { -``` - -Prints the provided schema in the Schema Language format. - -### printIntrospectionSchema - -```js -function printIntrospectionSchema(schema: GraphQLSchema): string { -``` - -Prints the built-in introspection schema in the Schema Language format. - -### buildASTSchema - -```js -function buildASTSchema( - ast: SchemaDocument, - queryTypeName: string, - mutationTypeName: ?string -): GraphQLSchema -``` - -This takes the ast of a schema document produced by `parse` in -`graphql/language` and constructs a GraphQLSchema instance which can be -then used with all GraphQL.js tools, but cannot be used to execute a query, as -introspection does not represent the "resolver", "parse" or "serialize" -functions or any other server-internal mechanisms. - -### typeFromAST - -```js -function typeFromAST( - schema: GraphQLSchema, - inputTypeAST: Type -): ?GraphQLType -``` - -Given the name of a Type as it appears in a GraphQL AST and a Schema, return the -corresponding GraphQLType from that schema. - -### astFromValue - -```js -function astFromValue( - value: any, - type?: ?GraphQLType -): ?Value -``` - -Produces a GraphQL Input Value AST given a JavaScript value. - -Optionally, a GraphQL type may be provided, which will be used to -disambiguate between value primitives. - -## Visitors - -### TypeInfo - -```js -class TypeInfo { - constructor(schema: GraphQLSchema) - getType(): ?GraphQLOutputType { - getParentType(): ?GraphQLCompositeType { - getInputType(): ?GraphQLInputType { - getFieldDef(): ?GraphQLFieldDefinition { - getDirective(): ?GraphQLDirective { - getArgument(): ?GraphQLArgument { -} -``` - -TypeInfo is a utility class which, given a GraphQL schema, can keep track -of the current field and type definitions at any point in a GraphQL document -AST during a recursive descent by calling `enter(node)` and `leave(node)`. - -## Value Validation - -### isValidJSValue - -```js -function isValidJSValue(value: any, type: GraphQLInputType): string[] -``` - -Given a JavaScript value and a GraphQL type, determine if the value will be -accepted for that type. This is primarily useful for validating the -runtime values of query variables. - -### isValidLiteralValue - -```js -function isValidLiteralValue( - type: GraphQLInputType, - valueAST: Value -): string[] -``` - -Utility for validators which determines if a value literal AST is valid given -an input type. - -Note that this only validates literal values, variables are assumed to -provide values of the correct type. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..557d75c22b --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,890 @@ +import globals from 'globals'; +import nPlugin from 'eslint-plugin-n'; +import importPlugin from 'eslint-plugin-import'; +import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort'; +import reactPlugin from 'eslint-plugin-react'; +import reactHooksPlugin from 'eslint-plugin-react'; +import { internalRulesPlugin } from './resources/eslint-internal-rules/index.js'; + +import { + config as tsConfig, + parser as tsParser, + plugin as tsPlugin, +} from 'typescript-eslint'; + +export default tsConfig( + { + ignores: [ + 'eslint.config.mjs', + 'node_modules', + 'reports', + 'npmDist', + 'npmEsmDist', + 'denoDist', + 'website/.next', + 'website/out', + 'integrationTests/ts/*.ts', + ], + }, + { + languageOptions: { + globals: { + ...globals['shared-node-browser'], + }, + }, + linterOptions: { + reportUnusedDisableDirectives: true, + }, + plugins: { + 'internal-rules': internalRulesPlugin, + n: nPlugin, + import: importPlugin, + 'simple-import-sort': simpleImportSortPlugin, + }, + settings: { + // eslint-plugin-import tries to parse all imported files included huge ones (e.g. 'typescript') + // that leads to very poor performance so to fix that we disable all checks on external files. + 'import/ignore': '/node_modules/', + }, + rules: { + ////////////////////////////////////////////////////////////////////////////// + // Internal rules located in 'resources/eslint-internal-rules'. + ////////////////////////////////////////////////////////////////////////////// + + 'internal-rules/only-ascii': 'error', + 'internal-rules/no-dir-import': 'error', + 'internal-rules/require-to-string-tag': 'off', + + ////////////////////////////////////////////////////////////////////////////// + // `eslint-plugin-n` rule list based on `v17.14.x` + ////////////////////////////////////////////////////////////////////////////// + + // Rules + // https://github.com/eslint-community/eslint-plugin-n/?tab=readme-ov-file#-rules + 'n/callback-return': 'error', + 'n/exports-style': 'off', // TODO: consider + 'n/file-extension-in-import': 'error', + 'n/global-require': 'error', + 'n/handle-callback-err': ['error', 'error'], + 'n/hashbang': 'error', + 'n/no-callback-literal': 'error', + 'n/no-deprecated-api': 'error', + 'n/no-exports-assign': 'error', + 'n/no-extraneous-import': 'error', + 'n/no-extraneous-require': 'error', + 'n/no-hide-core-modules': 'error', + 'n/no-missing-import': 'error', + 'n/no-missing-require': 'error', + 'n/no-mixed-requires': 'error', + 'n/no-new-require': 'error', + 'n/no-path-concat': 'error', + 'n/no-process-env': 'off', + 'n/no-process-exit': 'off', + 'n/no-restricted-import': 'off', + 'n/no-restricted-require': 'off', + 'n/no-sync': 'off', // TODO: consider enabling, currently triggers with executeSync/graphqlSync, without ability to add exceptions + 'n/no-unpublished-bin': 'error', + 'n/no-unpublished-import': 'error', + 'n/no-unpublished-require': 'error', + 'n/no-unsupported-features/es-builtins': 'error', + 'n/no-unsupported-features/es-syntax': [ + 'error', + { ignores: ['modules'] }, + ], + 'n/no-unsupported-features/node-builtins': 'error', + 'n/prefer-global/buffer': 'error', + 'n/prefer-global/console': 'error', + 'n/prefer-global/process': 'error', + 'n/prefer-global/text-decoder': 'error', + 'n/prefer-global/text-encoder': 'error', + 'n/prefer-global/url': 'error', + 'n/prefer-global/url-search-params': 'error', + 'n/prefer-node-protocol': 'error', + 'n/prefer-promises/dns': 'off', + 'n/prefer-promises/fs': 'off', + 'n/process-exit-as-throw': 'error', + 'n/shebang': 'error', + + ////////////////////////////////////////////////////////////////////////////// + // `eslint-plugin-import` rule list based on `v2.31.x` + ////////////////////////////////////////////////////////////////////////////// + + // Static analysis + // https://github.com/benmosher/eslint-plugin-import#static-analysis + 'import/default': 'error', + 'import/named': 'error', + 'import/namespace': 'error', + 'import/no-absolute-path': 'error', + 'import/no-cycle': 'error', + 'import/no-dynamic-require': 'error', + 'import/no-internal-modules': 'off', + 'import/no-relative-packages': 'off', + 'import/no-relative-parent-imports': 'off', + 'import/no-restricted-paths': [ + 'error', + { + basePath: './', + + zones: [ + { + target: './src', + from: 'src/__testUtils__', + }, + ], + }, + ], + 'import/no-self-import': 'error', + 'import/no-unresolved': 'off', // TODO: blocked by https://github.com/import-js/eslint-plugin-import/issues/2170 + 'import/no-useless-path-segments': 'error', + 'import/no-webpack-loader-syntax': 'error', + + // Helpful warnings + // https://github.com/benmosher/eslint-plugin-import#helpful-warnings + 'import/export': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-deprecated': 'error', + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: false, + }, + ], + 'import/no-mutable-exports': 'error', + 'import/no-unused-modules': 'error', + 'import/no-empty-named-blocks': 'error', + + // Module systems + // https://github.com/benmosher/eslint-plugin-import#module-systems + 'import/unambiguous': 'error', + 'import/no-commonjs': 'error', + 'import/no-amd': 'error', + 'import/no-nodejs-modules': 'error', + 'import/no-import-module-exports': 'off', + + // Style guide + // https://github.com/benmosher/eslint-plugin-import#style-guide + 'import/consistent-type-specifier-style': 'error', + 'import/dynamic-import-chunkname': 'off', + 'import/exports-last': 'off', + 'import/extensions': ['error', 'ignorePackages'], + 'import/first': 'error', + 'import/group-exports': 'off', + 'import/imports-first': 'off', + 'import/max-dependencies': 'off', + 'import/newline-after-import': 'error', + 'import/no-anonymous-default-export': 'error', + 'import/no-default-export': 'error', + 'import/no-duplicates': 'error', + 'import/no-named-default': 'error', + 'import/no-named-export': 'off', + 'import/no-namespace': 'error', + 'import/no-unassigned-import': 'error', + 'import/order': [ + 'error', + { + 'newlines-between': 'always-and-inside-groups', + }, + ], + 'import/prefer-default-export': 'off', + + ////////////////////////////////////////////////////////////////////////////// + // `eslint-plugin-simple-import-sort` rule list based on `v12.1.x` + // https://github.com/lydell/eslint-plugin-simple-import-sort + ////////////////////////////////////////////////////////////////////////////// + + 'simple-import-sort/imports': [ + 'error', + { + groups: [ + // Node.js builtin modules + ['^node:\\w'], + + // Packages. + // Things that start with a letter (or digit or underscore), or `@` followed by a letter. + ['^@?\\w'], + + // General utilities + ['^(\\./|(\\.\\./)+)__testUtils__/'], + ['^(\\./|(\\.\\./)+)jsutils/'], + + // Top-level directories + ['^(\\./|(\\.\\./)+)error/'], + ['^(\\./|(\\.\\./)+)language/'], + ['^(\\./|(\\.\\./)+)type/'], + ['^(\\./|(\\.\\./)+)validation/'], + ['^(\\./|(\\.\\./)+)execution/'], + ['^(\\./|(\\.\\./)+)utilities/'], + + // Relative imports. + // Anything that starts with a dot. + ['^(\\.\\./){4,}'], + ['^(\\.\\./){3}'], + ['^(\\.\\./){2}'], + ['^(\\.\\./){1}'], + ['^\\./'], + ], + }, + ], + 'simple-import-sort/exports': 'off', // TODO: error + + ////////////////////////////////////////////////////////////////////////////// + // ESLint builtin rules list based on `v9.16.x` + ////////////////////////////////////////////////////////////////////////////// + + // Possible Errors + // https://eslint.org/docs/latest/rules/#possible-problems + 'array-callback-return': 'error', + 'constructor-super': 'error', + 'for-direction': 'error', + 'getter-return': 'error', + 'no-async-promise-executor': 'error', + 'no-await-in-loop': 'error', + 'no-class-assign': 'error', + 'no-compare-neg-zero': 'error', + 'no-cond-assign': 'error', + 'no-const-assign': 'error', + 'no-constant-binary-expression': 'error', + 'no-constant-condition': 'error', + 'no-constructor-return': 'error', + 'no-control-regex': 'error', + 'no-debugger': 'warn', + 'no-dupe-args': 'error', + 'no-dupe-class-members': 'error', + 'no-dupe-else-if': 'error', + 'no-dupe-keys': 'error', + 'no-duplicate-case': 'error', + 'no-duplicate-imports': 'off', // Superseded by `import/no-duplicates` + 'no-empty-character-class': 'error', + 'no-empty-pattern': 'error', + 'no-ex-assign': 'error', + 'no-fallthrough': 'error', + 'no-func-assign': 'error', + 'no-import-assign': 'error', + 'no-inner-declarations': ['error', 'both'], + 'no-invalid-regexp': 'error', + 'no-irregular-whitespace': 'error', + 'no-loss-of-precision': 'error', + 'no-misleading-character-class': 'error', + 'no-new-native-nonconstructor': 'error', + 'no-obj-calls': 'error', + 'no-promise-executor-return': 'off', // TODO: error + 'no-prototype-builtins': 'error', + 'no-self-assign': 'error', + 'no-self-compare': 'off', // TODO: error + 'no-setter-return': 'error', + 'no-sparse-arrays': 'error', + 'no-template-curly-in-string': 'error', + 'no-this-before-super': 'error', + 'no-undef': 'error', + 'no-unexpected-multiline': 'error', + 'no-unmodified-loop-condition': 'error', + 'no-unreachable': 'error', + 'no-unreachable-loop': 'error', + 'no-unsafe-finally': 'error', + 'no-unsafe-negation': 'error', + 'no-unsafe-optional-chaining': [ + 'error', + { + disallowArithmeticOperators: true, + }, + ], + 'no-unused-private-class-members': 'error', + 'no-unused-vars': [ + 'error', + { + vars: 'all', + args: 'all', + argsIgnorePattern: '^_', + }, + ], + 'no-use-before-define': 'off', + 'no-useless-assignment': 'error', + 'no-useless-backreference': 'error', + 'require-atomic-updates': 'error', + 'use-isnan': 'error', + 'valid-typeof': 'error', + + // Suggestions + // https://eslint.org/docs/latest/rules/#suggestions + 'accessor-pairs': 'error', + 'arrow-body-style': 'error', + 'block-scoped-var': 'error', + camelcase: 'error', + 'capitalized-comments': 'off', // TODO: consider + 'class-methods-use-this': 'off', + complexity: 'off', + 'consistent-return': 'off', + 'consistent-this': 'error', + curly: 'error', + 'default-case': 'off', + 'default-case-last': 'error', + 'default-param-last': 'error', + 'dot-notation': 'error', + eqeqeq: ['error', 'smart'], + 'func-name-matching': 'off', + 'func-names': ['error', 'as-needed'], // improve debug experience + 'func-style': 'off', + 'grouped-accessor-pairs': 'error', + 'guard-for-in': 'error', + 'id-denylist': 'off', + 'id-length': 'off', + 'id-match': ['error', '^(?:_?[a-zA-Z0-9]*)|[_A-Z0-9]+$'], + 'init-declarations': 'off', + 'logical-assignment-operators': 'error', + 'max-classes-per-file': 'off', + 'max-depth': 'off', + 'max-lines': 'off', + 'max-lines-per-function': 'off', + 'max-nested-callbacks': 'off', + 'max-params': [ + 'error', + { + max: 5, // TODO: drop to default number, which is 3 + }, + ], + 'max-statements': 'off', + 'new-cap': 'error', + 'no-alert': 'error', + 'no-array-constructor': 'error', + 'no-bitwise': 'off', + 'no-caller': 'error', + 'no-case-declarations': 'error', + 'no-console': 'warn', + 'no-continue': 'off', + 'no-delete-var': 'error', + 'no-div-regex': 'error', + 'no-else-return': 'error', + 'no-empty': 'error', + 'no-empty-function': 'error', + 'no-empty-static-block': 'error', + 'no-eq-null': 'off', + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-extra-bind': 'error', + 'no-extra-boolean-cast': 'error', + 'no-extra-label': 'error', + 'no-global-assign': 'error', + 'no-implicit-coercion': 'error', + 'no-implicit-globals': 'off', + 'no-implied-eval': 'error', + 'no-inline-comments': 'off', + 'no-invalid-this': 'error', + 'no-iterator': 'error', + 'no-label-var': 'error', + 'no-labels': 'error', + 'no-lone-blocks': 'error', + 'no-lonely-if': 'error', + 'no-loop-func': 'error', + 'no-magic-numbers': 'off', + 'no-multi-assign': 'off', + 'no-multi-str': 'error', + 'no-negated-condition': 'off', + 'no-nested-ternary': 'off', + 'no-new': 'error', + 'no-new-func': 'error', + 'no-new-wrappers': 'error', + 'no-nonoctal-decimal-escape': 'error', + 'no-object-constructor': 'error', + 'no-octal': 'error', + 'no-octal-escape': 'error', + 'no-param-reassign': 'error', + 'no-plusplus': 'off', + 'no-proto': 'error', + 'no-redeclare': 'error', + 'no-regex-spaces': 'error', + 'no-restricted-exports': [ + 'error', + { + restrictDefaultExports: { + direct: true, + }, + }, + ], + 'no-restricted-globals': 'off', + 'no-restricted-imports': 'off', + 'no-restricted-properties': 'off', + 'no-restricted-syntax': [ + 'error', + { + selector: 'TemplateElement[value.raw=/ \\n/]', + message: + 'String literals should not contain trailing spaces. If needed for tests please disable locally using eslint comment', + }, + ], + 'no-return-assign': 'error', + 'no-script-url': 'error', + 'no-sequences': 'error', + 'no-shadow': 'error', + 'no-shadow-restricted-names': 'error', + 'no-ternary': 'off', + 'no-throw-literal': 'error', + 'no-undef-init': 'error', + 'no-undefined': 'off', + 'no-underscore-dangle': 'off', // TODO: error + 'no-unneeded-ternary': 'error', + 'no-unused-expressions': 'error', + 'no-unused-labels': 'error', + 'no-useless-call': 'error', + 'no-useless-catch': 'error', + 'no-useless-computed-key': 'error', + 'no-useless-concat': 'error', + 'no-useless-constructor': 'error', + 'no-useless-escape': 'error', + 'no-useless-rename': 'error', + 'no-useless-return': 'error', + 'no-var': 'error', + 'no-void': 'error', + 'no-warning-comments': 'off', + 'no-with': 'error', + 'object-shorthand': 'error', + 'one-var': ['error', 'never'], + 'operator-assignment': 'error', + 'prefer-arrow-callback': 'error', + 'prefer-const': 'error', + 'prefer-destructuring': 'off', + 'prefer-exponentiation-operator': 'error', + 'prefer-named-capture-group': 'off', // TODO: needs a better support in TS, see https://github.com/microsoft/TypeScript/issues/32098 + 'prefer-numeric-literals': 'error', + 'prefer-object-has-own': 'error', + 'prefer-object-spread': 'error', + 'prefer-promise-reject-errors': 'error', + 'prefer-regex-literals': 'error', + 'prefer-rest-params': 'off', // TODO: error + 'prefer-spread': 'error', + 'prefer-template': 'off', + radix: 'error', + 'require-await': 'error', + 'require-unicode-regexp': 'off', + 'require-yield': 'error', + 'sort-imports': 'off', + 'sort-keys': 'off', + 'sort-vars': 'off', + strict: 'error', + 'symbol-description': 'off', + 'vars-on-top': 'error', + yoda: [ + 'error', + 'never', + { + exceptRange: true, + }, + ], + + // Layout & Formatting + // https://eslint.org/docs/latest/rules/#layout--formatting + 'unicode-bom': 'off', + }, + }, + { + files: ['integrationTests/node-esm/**/*.js'], + }, + { + files: ['**/*.ts'], + plugins: { + '@typescript-eslint': tsPlugin, + }, + extends: [importPlugin.configs.typescript], + languageOptions: { + parser: tsParser, + parserOptions: { + project: ['tsconfig.json', './website/tsconfig.json'], + }, + }, + rules: { + ////////////////////////////////////////////////////////////////////////// + // `@typescript-eslint/eslint-plugin` rule list based on `v8.16.x` + ////////////////////////////////////////////////////////////////////////// + + // Supported Rules + // https://typescript-eslint.io/rules/?=xdeprecated + '@typescript-eslint/adjacent-overload-signatures': 'error', + '@typescript-eslint/array-type': [ + 'error', + { + default: 'generic', + }, + ], + '@typescript-eslint/await-thenable': 'error', + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-expect-error': false, + }, + ], + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/class-literal-property-style': 'off', // TODO: enable after TS conversion + '@typescript-eslint/class-methods-use-this': 'off', + '@typescript-eslint/consistent-generic-constructors': 'error', + '@typescript-eslint/consistent-indexed-object-style': [ + 'error', + 'index-signature', + ], + '@typescript-eslint/consistent-return': 'off', + '@typescript-eslint/consistent-type-assertions': 'off', // TODO: temporarily disable + '@typescript-eslint/consistent-type-definitions': 'error', + '@typescript-eslint/consistent-type-exports': 'error', + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/default-param-last': 'error', + '@typescript-eslint/dot-notation': 'error', + '@typescript-eslint/explicit-function-return-type': 'off', // TODO: consider + '@typescript-eslint/explicit-member-accessibility': 'off', // TODO: consider + '@typescript-eslint/explicit-module-boundary-types': 'off', // TODO: consider + '@typescript-eslint/init-declarations': 'off', + '@typescript-eslint/max-params': [ + 'error', + { + max: 5, // TODO: drop to default number, which is 3 + }, + ], + '@typescript-eslint/member-ordering': 'error', + '@typescript-eslint/method-signature-style': 'error', + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/no-array-constructor': 'error', + '@typescript-eslint/no-array-delete': 'error', + '@typescript-eslint/no-base-to-string': 'error', + '@typescript-eslint/no-confusing-non-null-assertion': 'error', + '@typescript-eslint/no-confusing-void-expression': 'off', // TODO: enable with ignoreArrowShorthand + '@typescript-eslint/no-deprecated': 'off', + '@typescript-eslint/no-dupe-class-members': 'error', + '@typescript-eslint/no-duplicate-enum-values': 'error', + '@typescript-eslint/no-duplicate-type-constituents': 'error', + '@typescript-eslint/no-dynamic-delete': 'off', + '@typescript-eslint/no-empty-function': 'error', + '@typescript-eslint/no-empty-object-type': 'error', + '@typescript-eslint/no-explicit-any': 'off', // TODO: error + '@typescript-eslint/no-extra-non-null-assertion': 'error', + '@typescript-eslint/no-extraneous-class': 'off', // TODO: error + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-for-in-array': 'error', + '@typescript-eslint/no-implied-eval': 'error', + '@typescript-eslint/no-import-type-side-effects': 'error', + '@typescript-eslint/no-inferrable-types': [ + 'error', + { + ignoreParameters: true, + ignoreProperties: true, + }, + ], + '@typescript-eslint/no-invalid-this': 'error', + '@typescript-eslint/no-invalid-void-type': 'error', + '@typescript-eslint/no-loop-func': 'error', + '@typescript-eslint/no-magic-numbers': 'off', + '@typescript-eslint/no-meaningless-void-operator': 'error', + '@typescript-eslint/no-misused-new': 'error', + '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-mixed-enums': 'error', + '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-redeclare': 'error', + '@typescript-eslint/no-redundant-type-constituents': 'error', + '@typescript-eslint/no-require-imports': 'error', + '@typescript-eslint/no-restricted-imports': 'error', + '@typescript-eslint/no-restricted-types': 'error', + '@typescript-eslint/no-shadow': 'error', + '@typescript-eslint/no-this-alias': 'error', + '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', + '@typescript-eslint/no-unnecessary-condition': 'off', // TODO: temporary disable + '@typescript-eslint/no-unnecessary-parameter-property-assignment': + 'error', + '@typescript-eslint/no-unnecessary-qualifier': 'error', + '@typescript-eslint/no-unnecessary-template-expression': 'error', + '@typescript-eslint/no-unnecessary-type-arguments': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-unnecessary-type-constraint': 'error', + '@typescript-eslint/no-unnecessary-type-parameters': 'error', + '@typescript-eslint/no-unsafe-argument': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-assignment': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-call': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-enum-comparison': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-function-type': 'error', + '@typescript-eslint/no-unsafe-member-access': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-return': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-type-assertion': 'off', // TODO: consider + '@typescript-eslint/no-unsafe-unary-minus': 'error', + '@typescript-eslint/no-unused-expressions': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'all', + argsIgnorePattern: '^_', + caughtErrors: 'all', + caughtErrorsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + varsIgnorePattern: '^_', + ignoreRestSiblings: true, + }, + ], + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-useless-empty-export': 'error', + '@typescript-eslint/no-wrapper-object-types': 'error', + '@typescript-eslint/non-nullable-type-assertion-style': 'off', //TODO: temporarily disabled + '@typescript-eslint/only-throw-error': 'error', + '@typescript-eslint/parameter-properties': 'error', + '@typescript-eslint/prefer-as-const': 'error', + '@typescript-eslint/prefer-destructuring': 'off', + '@typescript-eslint/prefer-enum-initializers': 'error', + '@typescript-eslint/prefer-find': 'error', + '@typescript-eslint/prefer-for-of': 'error', + '@typescript-eslint/prefer-function-type': 'error', + '@typescript-eslint/prefer-includes': 'error', + '@typescript-eslint/prefer-literal-enum-member': 'error', + '@typescript-eslint/prefer-namespace-keyword': 'error', + '@typescript-eslint/prefer-nullish-coalescing': 'error', + '@typescript-eslint/prefer-optional-chain': 'error', + '@typescript-eslint/prefer-promise-reject-errors': 'error', + '@typescript-eslint/prefer-readonly': 'off', + '@typescript-eslint/prefer-readonly-parameter-types': 'off', // TODO: consider + '@typescript-eslint/prefer-reduce-type-parameter': 'error', + '@typescript-eslint/prefer-regexp-exec': 'off', + '@typescript-eslint/prefer-return-this-type': 'error', + '@typescript-eslint/prefer-string-starts-ends-with': 'error', + '@typescript-eslint/promise-function-async': 'off', + '@typescript-eslint/related-getter-setter-pairs': 'error', + '@typescript-eslint/require-array-sort-compare': 'error', + '@typescript-eslint/require-await': 'error', + '@typescript-eslint/restrict-plus-operands': 'off', // TODO: temporarily disabled + '@typescript-eslint/restrict-template-expressions': 'off', // TODO: temporarily disabled + '@typescript-eslint/return-await': 'error', + '@typescript-eslint/strict-boolean-expressions': [ + 'error', + { + allowNullableBoolean: true, // TODO: consider removing + }, + ], + '@typescript-eslint/switch-exhaustiveness-check': [ + 'error', + { + considerDefaultExhaustiveForUnions: true, + }, + ], + '@typescript-eslint/triple-slash-reference': 'error', + '@typescript-eslint/typedef': 'off', + '@typescript-eslint/unbound-method': 'off', // TODO: consider + '@typescript-eslint/unified-signatures': 'error', + '@typescript-eslint/use-unknown-in-catch-callback-variable': 'error', + + // Disable conflicting ESLint rules for Extension Rules + // https://typescript-eslint.io/rules/?=extension-xdeprecated + + // Below list intentionally includes ESLint rules disabled above. + // If any of the above rules are enabled in the future, they must still be disabled for TS files. + 'class-methods-use-this': 'off', + 'consistent-return': 'off', + 'default-param-last': 'off', + 'dot-notation': 'off', + 'init-declarations': 'off', + 'max-params': 'off', + 'no-array-constructor': 'off', + 'no-dupe-class-members': 'off', + 'no-empty-function': 'off', + 'no-implied-eval': 'off', + 'no-invalid-this': 'off', + 'no-loop-func': 'off', + 'no-magic-numbers': 'off', + 'no-redeclare': 'off', + 'no-restricted-imports': 'off', + 'no-shadow': 'off', + 'no-unused-expressions': 'off', + 'no-unused-vars': 'off', + 'no-use-before-define': 'off', + 'no-useless-constructor': 'off', + 'only-throw-error': 'off', + 'prefer-destructuring': 'off', + 'prefer-promise-reject-errors': 'off', + 'require-await': 'off', + 'return-await': 'off', + }, + }, + { + files: ['src/**'], + rules: { + 'internal-rules/require-to-string-tag': 'error', + }, + }, + { + files: ['src/**/__*__/**'], + rules: { + 'local/require-to-string-tag': 'off', + 'n/no-unpublished-import': [ + 'error', + { + allowModules: ['chai', 'mocha'], + }, + ], + 'import/no-deprecated': 'off', + 'import/no-restricted-paths': 'off', + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: true, + }, + ], + }, + }, + { + files: ['integrationTests/*'], + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + 'n/no-sync': 'off', + 'n/no-unpublished-import': [ + 'error', + { + allowModules: ['mocha'], + }, + ], + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: true, + }, + ], + 'import/no-namespace': 'off', + 'import/no-nodejs-modules': 'off', + }, + }, + { + files: ['integrationTests/*/**'], + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + 'n/no-sync': 'off', + 'import/no-nodejs-modules': 'off', + 'no-console': 'off', + 'n/no-missing-import': [ + 'error', + { + allowModules: ['graphql', 'graphql-esm'], + }, + ], + 'n/no-missing-require': [ + 'error', + { + allowModules: ['graphql'], + }, + ], + }, + }, + { + files: ['benchmark/**'], + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + 'n/no-sync': 'off', + 'n/no-missing-import': [ + 'error', + { + allowModules: ['graphql'], + }, + ], + 'n/no-extraneous-import': [ + 'error', + { + allowModules: ['graphql'], + }, + ], + 'import/no-unresolved': 'off', + 'import/no-namespace': 'off', + 'import/no-nodejs-modules': 'off', + 'import/no-extraneous-dependencies': 'off', + }, + }, + { + files: ['resources/**'], + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + 'internal-rules/only-ascii': [ + 'error', + { + allowEmoji: true, + }, + ], + // TODO: remove when fetch/cpSync stabilizes across all node versions + 'n/no-unsupported-features/node-builtins': [ + 'error', + { + ignores: ['fetch', 'fs.cpSync'], + }, + ], + 'n/no-unpublished-import': 'off', + 'n/no-sync': 'off', + 'import/no-namespace': 'off', + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: true, + }, + ], + 'import/no-nodejs-modules': 'off', + 'no-console': 'off', + }, + }, + { + files: ['resources/internal-rules/**'], + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + 'import/no-commonjs': 'off', + }, + }, + { + files: ['**/*.jsx'], + languageOptions: { + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + rules: { + 'n/no-unpublished-import': 'off', + 'import/no-default-export': 'off', + }, + }, + { + files: ['website/**'], + extends: [reactPlugin.configs.flat.recommended], + plugins: { + 'react-hooks': reactHooksPlugin, + }, + languageOptions: { + globals: { + ...globals.node, + }, + }, + settings: { + react: { + version: 'detect', + }, + }, + rules: { + ...reactHooksPlugin.configs.recommended.rules, + 'no-restricted-exports': 'off', + 'import/no-default-export': 'off', + 'import/no-nodejs-modules': 'off', + 'import/unambiguous': 'off', + 'n/no-missing-import': 'off', // allows linting from root of project when website packages are not installed + }, + }, +); diff --git a/integrationTests/node/index.cjs b/integrationTests/node/index.cjs index 5985e49fee..8a7c1f5003 100644 --- a/integrationTests/node/index.cjs +++ b/integrationTests/node/index.cjs @@ -1,5 +1,7 @@ -const assert = require('assert'); -const { readFileSync } = require('fs'); +'use strict'; + +const assert = require('node:assert'); +const { readFileSync } = require('node:fs'); const { experimentalExecuteIncrementally, diff --git a/integrationTests/node/index.mjs b/integrationTests/node/index.mjs index 3039899377..e06bd19de6 100644 --- a/integrationTests/node/index.mjs +++ b/integrationTests/node/index.mjs @@ -1,6 +1,5 @@ -/* eslint-disable simple-import-sort/imports */ -import assert from 'assert'; -import { readFileSync } from 'fs'; +import assert from 'node:assert'; +import { readFileSync } from 'node:fs'; import { experimentalExecuteIncrementally, diff --git a/integrationTests/node/test.js b/integrationTests/node/test.js index 2d4830aa7a..d7f77e51bf 100644 --- a/integrationTests/node/test.js +++ b/integrationTests/node/test.js @@ -1,5 +1,5 @@ -import childProcess from 'child_process'; -import fs from 'fs'; +import childProcess from 'node:child_process'; +import fs from 'node:fs'; const graphqlPackageJSON = JSON.parse( fs.readFileSync('./node_modules/graphql/package.json', 'utf-8'), diff --git a/integrationTests/ts/basic-test.ts b/integrationTests/ts/basic-test.ts index a28bd840e7..368b799cf1 100644 --- a/integrationTests/ts/basic-test.ts +++ b/integrationTests/ts/basic-test.ts @@ -11,7 +11,7 @@ const queryType: GraphQLObjectType = new GraphQLObjectType({ args: { who: { type: GraphQLString, - defaultValue: 'World', + default: { value: 'World' }, }, }, resolve(_root, args: { who: string }) { diff --git a/integrationTests/ts/esm.ts b/integrationTests/ts/esm.ts index 4554d1efec..77d011e847 100644 --- a/integrationTests/ts/esm.ts +++ b/integrationTests/ts/esm.ts @@ -15,7 +15,7 @@ const queryType: GraphQLObjectType = new GraphQLObjectType({ args: { who: { type: GraphQLString, - defaultValue: 'World', + default: { value: 'World' }, }, }, resolve(_root, args: { who: string }) { diff --git a/integrationTests/ts/kitchenSink-test.ts b/integrationTests/ts/kitchenSink-test.ts index 8d27ec0e97..0cf254e80e 100644 --- a/integrationTests/ts/kitchenSink-test.ts +++ b/integrationTests/ts/kitchenSink-test.ts @@ -6,9 +6,9 @@ import { Kind } from 'graphql/language'; // Test subset of public APIs with "exactOptionalPropertyTypes" flag enabled new GraphQLScalarType({ name: 'SomeScalar', - serialize: undefined, - parseValue: undefined, - parseLiteral: undefined, + coerceOutputValue: undefined, + coerceInputValue: undefined, + coerceInputLiteral: undefined, }); new GraphQLError('test', { nodes: undefined }); diff --git a/integrationTests/ts/package.json b/integrationTests/ts/package.json index e003b253fd..6e5bfb367d 100644 --- a/integrationTests/ts/package.json +++ b/integrationTests/ts/package.json @@ -8,12 +8,12 @@ "dependencies": { "graphql": "file:../graphql.tgz", "graphql-esm": "file:../graphql-esm.tgz", - "typescript-4.4": "npm:typescript@4.4.x", - "typescript-4.5": "npm:typescript@4.5.x", - "typescript-4.6": "npm:typescript@4.6.x", - "typescript-4.7": "npm:typescript@4.7.x", - "typescript-4.8": "npm:typescript@4.8.x", "typescript-4.9": "npm:typescript@4.9.x", - "typescript-4.9": "npm:typescript@5.0.x" + "typescript-5.0": "npm:typescript@5.0.x", + "typescript-5.1": "npm:typescript@5.1.x", + "typescript-5.2": "npm:typescript@5.2.x", + "typescript-5.3": "npm:typescript@5.3.x", + "typescript-5.4": "npm:typescript@5.4.x", + "typescript-5.5": "npm:typescript@5.5.x" } } diff --git a/integrationTests/ts/test.js b/integrationTests/ts/test.js index 0d0fb81cbc..c8d1b00a3a 100644 --- a/integrationTests/ts/test.js +++ b/integrationTests/ts/test.js @@ -1,6 +1,6 @@ -import childProcess from 'child_process'; -import fs from 'fs'; -import path from 'path'; +import childProcess from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; const { dependencies } = JSON.parse(fs.readFileSync('./package.json', 'utf-8')); diff --git a/integrationTests/ts/tsconfig.json b/integrationTests/ts/tsconfig.json index e8505c2bb9..3a9475ed29 100644 --- a/integrationTests/ts/tsconfig.json +++ b/integrationTests/ts/tsconfig.json @@ -1,7 +1,13 @@ { "compilerOptions": { "module": "commonjs", - "lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"], + "lib": [ + "es2019", + "es2020.promise", + "es2020.bigint", + "es2020.string", + "DOM" + ], "noEmit": true, "types": [], "strict": true, diff --git a/integrationTests/webpack/entry-esm.mjs b/integrationTests/webpack/entry-esm.mjs index 1dec59e043..5a04dc1ada 100644 --- a/integrationTests/webpack/entry-esm.mjs +++ b/integrationTests/webpack/entry-esm.mjs @@ -1,7 +1,4 @@ -// eslint-disable-next-line node/no-missing-import, import/no-unresolved import { graphqlSync } from 'graphql-esm'; - -// eslint-disable-next-line node/no-missing-import, import/no-unresolved import { buildSchema } from 'graphql-esm/utilities/buildASTSchema'; const schema = buildSchema('type Query { hello: String }'); diff --git a/integrationTests/webpack/test.js b/integrationTests/webpack/test.js index 7abe49a679..db6ba9db84 100644 --- a/integrationTests/webpack/test.js +++ b/integrationTests/webpack/test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import assert from 'node:assert'; /* eslint-disable n/no-missing-import */ import cjs from './dist/main-cjs.cjs'; diff --git a/package-lock.json b/package-lock.json index a8d94f9a0f..c28fe50db7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15279 +1,3835 @@ { "name": "graphql", - "version": "17.0.0-alpha.3", + "version": "17.0.0-alpha.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "graphql", - "version": "17.0.0-alpha.3", + "version": "17.0.0-alpha.7", "license": "MIT", "devDependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/preset-classic": "2.4.0", - "@mdx-js/react": "1.6.22", - "@stryker-mutator/core": "6.4.2", - "@stryker-mutator/mocha-runner": "6.4.2", - "@stryker-mutator/typescript-checker": "6.4.2", - "@svgr/webpack": "6.5.1", - "@types/chai": "4.3.4", - "@types/mocha": "10.0.1", - "@types/node": "18.15.11", - "@types/prettier": "2.7.2", - "@typescript-eslint/eslint-plugin": "5.59.0", - "@typescript-eslint/parser": "5.59.0", - "c8": "7.13.0", - "chai": "4.3.7", - "clsx": "1.2.1", - "cspell": "6.31.1", - "docusaurus-plugin-typedoc-api": "3.0.0", - "eslint": "8.38.0", - "eslint-plugin-import": "2.27.5", - "eslint-plugin-n": "15.7.0", - "eslint-plugin-react": "7.32.2", - "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-simple-import-sort": "10.0.0", - "eslint-plugin-tsdoc": "0.2.17", - "file-loader": "6.2.0", - "mocha": "10.2.0", - "prettier": "2.8.7", - "prism-react-renderer": "1.3.5", - "react": "17.0.2", - "react-dom": "17.0.2", - "ts-node": "10.9.1", - "typedoc": "0.24.4", - "typescript": "5.0.4", - "url-loader": "4.1.1" + "@types/chai": "5.0.1", + "@types/mocha": "10.0.10", + "@types/node": "22.10.1", + "c8": "10.1.2", + "chai": "5.1.2", + "cspell": "8.16.1", + "eslint": "^9.16.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-n": "17.14.0", + "eslint-plugin-react": "7.37.2", + "eslint-plugin-react-hooks": "5.0.0", + "eslint-plugin-simple-import-sort": "12.1.1", + "husky": "^9.1.7", + "lint-staged": "^15.2.10", + "mocha": "11.0.1", + "prettier": "3.4.1", + "ts-node": "10.9.2", + "typescript": "5.7.2", + "typescript-eslint": "^8.17.0" }, "engines": { "node": "^16.19.0 || ^18.14.0 || >=19.7.0" } }, - "node_modules/@algolia/autocomplete-core": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz", - "integrity": "sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, - "dependencies": { - "@algolia/autocomplete-shared": "1.7.4" - } + "license": "MIT" }, - "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.4.tgz", - "integrity": "sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==", + "node_modules/@cspell/cspell-bundled-dicts": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.16.1.tgz", + "integrity": "sha512-EkbtoYpmiN9YPfcOoPcMnIrJBZh13mun64jPyyaYhrPPToiU5+CisZ7ZKUBGnqNaatuciMUxwIudhanQJ7Yhnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.0.5", + "@cspell/dict-al": "^1.0.3", + "@cspell/dict-aws": "^4.0.7", + "@cspell/dict-bash": "^4.1.8", + "@cspell/dict-companies": "^3.1.7", + "@cspell/dict-cpp": "^6.0.2", + "@cspell/dict-cryptocurrencies": "^5.0.3", + "@cspell/dict-csharp": "^4.0.5", + "@cspell/dict-css": "^4.0.16", + "@cspell/dict-dart": "^2.2.4", + "@cspell/dict-django": "^4.1.3", + "@cspell/dict-docker": "^1.1.11", + "@cspell/dict-dotnet": "^5.0.8", + "@cspell/dict-elixir": "^4.0.6", + "@cspell/dict-en_us": "^4.3.28", + "@cspell/dict-en-common-misspellings": "^2.0.7", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.8", + "@cspell/dict-flutter": "^1.0.3", + "@cspell/dict-fonts": "^4.0.3", + "@cspell/dict-fsharp": "^1.0.4", + "@cspell/dict-fullstack": "^3.2.3", + "@cspell/dict-gaming-terms": "^1.0.8", + "@cspell/dict-git": "^3.0.3", + "@cspell/dict-golang": "^6.0.17", + "@cspell/dict-google": "^1.0.4", + "@cspell/dict-haskell": "^4.0.4", + "@cspell/dict-html": "^4.0.10", + "@cspell/dict-html-symbol-entities": "^4.0.3", + "@cspell/dict-java": "^5.0.10", + "@cspell/dict-julia": "^1.0.4", + "@cspell/dict-k8s": "^1.0.9", + "@cspell/dict-latex": "^4.0.3", + "@cspell/dict-lorem-ipsum": "^4.0.3", + "@cspell/dict-lua": "^4.0.6", + "@cspell/dict-makefile": "^1.0.3", + "@cspell/dict-markdown": "^2.0.7", + "@cspell/dict-monkeyc": "^1.0.9", + "@cspell/dict-node": "^5.0.5", + "@cspell/dict-npm": "^5.1.14", + "@cspell/dict-php": "^4.0.13", + "@cspell/dict-powershell": "^5.0.13", + "@cspell/dict-public-licenses": "^2.0.11", + "@cspell/dict-python": "^4.2.12", + "@cspell/dict-r": "^2.0.4", + "@cspell/dict-ruby": "^5.0.7", + "@cspell/dict-rust": "^4.0.10", + "@cspell/dict-scala": "^5.0.6", + "@cspell/dict-software-terms": "^4.1.17", + "@cspell/dict-sql": "^2.1.8", + "@cspell/dict-svelte": "^1.0.5", + "@cspell/dict-swift": "^2.0.4", + "@cspell/dict-terraform": "^1.0.6", + "@cspell/dict-typescript": "^3.1.11", + "@cspell/dict-vue": "^3.0.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-json-reporter": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.16.1.tgz", + "integrity": "sha512-ue1paJ2OE2BjIBQHXFMHnFqJL5xMrE/TLveOntDSCKJw7edCGP4XJA6Q0ZfUgR/ZAP3SYKNPkajEWbDTMfG+XA==", "dev": true, + "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.7.4" + "@cspell/cspell-types": "8.16.1" }, - "peerDependencies": { - "@algolia/client-search": ">= 4.9.1 < 6", - "algoliasearch": ">= 4.9.1 < 6" + "engines": { + "node": ">=18" } }, - "node_modules/@algolia/autocomplete-shared": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.4.tgz", - "integrity": "sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg==", - "dev": true - }, - "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz", - "integrity": "sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==", + "node_modules/@cspell/cspell-pipe": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.16.1.tgz", + "integrity": "sha512-6N+QZ3y65JRgGrQhZHmaBHESR+nC0J8nySGaYKclit8yk3jLZ/ORw9aoSGIj+dMPzImkNEDh+C1B1zdV4X8W6A==", "dev": true, - "dependencies": { - "@algolia/cache-common": "4.17.0" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/@algolia/cache-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.0.tgz", - "integrity": "sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==", - "dev": true - }, - "node_modules/@algolia/cache-in-memory": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz", - "integrity": "sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==", + "node_modules/@cspell/cspell-resolver": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.16.1.tgz", + "integrity": "sha512-CfVI2JFMwh9/n1QuU9niEONbYCX1XGKqmyCcHQUzAapSqGzbAmFrRFnvyKwNL+mmy1bxli9EZV8f5vBco26f9Q==", "dev": true, + "license": "MIT", "dependencies": { - "@algolia/cache-common": "4.17.0" + "global-directory": "^4.0.1" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@algolia/client-account": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.0.tgz", - "integrity": "sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==", + "node_modules/@cspell/cspell-service-bus": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.16.1.tgz", + "integrity": "sha512-URaralJKcdHZH/Lr25L28GJo2Ub07adHPPhOL83BvmPyGkboehmz5arjNrgQFwS+IvGjHLdp5uzEJd0xyeHGdw==", "dev": true, - "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/transporter": "4.17.0" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/@algolia/client-analytics": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.0.tgz", - "integrity": "sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==", + "node_modules/@cspell/cspell-types": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.16.1.tgz", + "integrity": "sha512-B8bHlBaDSMDMEq++H8qO9osKUkzWUrP4CgWQyRqlXZ9EOdnJ469Tp1wghcQ7DezII3aXYrHiVKsUYY9VvjkhIg==", "dev": true, - "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/@algolia/client-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.0.tgz", - "integrity": "sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==", + "node_modules/@cspell/dict-ada": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.5.tgz", + "integrity": "sha512-6/RtZ/a+lhFVmrx/B7bfP7rzC4yjEYe8o74EybXcvu4Oue6J4Ey2WSYj96iuodloj1LWrkNCQyX5h4Pmcj0Iag==", "dev": true, - "dependencies": { - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" - } + "license": "MIT" }, - "node_modules/@algolia/client-personalization": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.0.tgz", - "integrity": "sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==", + "node_modules/@cspell/dict-al": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.0.3.tgz", + "integrity": "sha512-V1HClwlfU/qwSq2Kt+MkqRAsonNu3mxjSCDyGRecdLGIHmh7yeEeaxqRiO/VZ4KP+eVSiSIlbwrb5YNFfxYZbw==", "dev": true, - "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" - } + "license": "MIT" }, - "node_modules/@algolia/client-search": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.0.tgz", - "integrity": "sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==", + "node_modules/@cspell/dict-aws": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.7.tgz", + "integrity": "sha512-PoaPpa2NXtSkhGIMIKhsJUXB6UbtTt6Ao3x9JdU9kn7fRZkwD4RjHDGqulucIOz7KeEX/dNRafap6oK9xHe4RA==", "dev": true, - "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" - } + "license": "MIT" }, - "node_modules/@algolia/events": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", - "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", - "dev": true + "node_modules/@cspell/dict-bash": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.8.tgz", + "integrity": "sha512-I2CM2pTNthQwW069lKcrVxchJGMVQBzru2ygsHCwgidXRnJL/NTjAPOFTxN58Jc1bf7THWghfEDyKX/oyfc0yg==", + "dev": true, + "license": "MIT" }, - "node_modules/@algolia/logger-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.0.tgz", - "integrity": "sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==", - "dev": true + "node_modules/@cspell/dict-companies": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.7.tgz", + "integrity": "sha512-ncVs/efuAkP1/tLDhWbXukBjgZ5xOUfe03neHMWsE8zvXXc5+Lw6TX5jaJXZLOoES/f4j4AhRE20jsPCF5pm+A==", + "dev": true, + "license": "MIT" }, - "node_modules/@algolia/logger-console": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.0.tgz", - "integrity": "sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==", + "node_modules/@cspell/dict-cpp": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.2.tgz", + "integrity": "sha512-yw5eejWvY4bAnc6LUA44m4WsFwlmgPt2uMSnO7QViGMBDuoeopMma4z9XYvs4lSjTi8fIJs/A1YDfM9AVzb8eg==", "dev": true, - "dependencies": { - "@algolia/logger-common": "4.17.0" - } + "license": "MIT" }, - "node_modules/@algolia/requester-browser-xhr": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz", - "integrity": "sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==", + "node_modules/@cspell/dict-cryptocurrencies": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.3.tgz", + "integrity": "sha512-bl5q+Mk+T3xOZ12+FG37dB30GDxStza49Rmoax95n37MTLksk9wBo1ICOlPJ6PnDUSyeuv4SIVKgRKMKkJJglA==", "dev": true, - "dependencies": { - "@algolia/requester-common": "4.17.0" - } + "license": "MIT" }, - "node_modules/@algolia/requester-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.0.tgz", - "integrity": "sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==", - "dev": true + "node_modules/@cspell/dict-csharp": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.5.tgz", + "integrity": "sha512-c/sFnNgtRwRJxtC3JHKkyOm+U3/sUrltFeNwml9VsxKBHVmvlg4tk4ar58PdpW9/zTlGUkWi2i85//DN1EsUCA==", + "dev": true, + "license": "MIT" }, - "node_modules/@algolia/requester-node-http": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz", - "integrity": "sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==", + "node_modules/@cspell/dict-css": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.16.tgz", + "integrity": "sha512-70qu7L9z/JR6QLyJPk38fNTKitlIHnfunx0wjpWQUQ8/jGADIhMCrz6hInBjqPNdtGpYm8d1dNFyF8taEkOgrQ==", "dev": true, - "dependencies": { - "@algolia/requester-common": "4.17.0" - } + "license": "MIT" }, - "node_modules/@algolia/transporter": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.0.tgz", - "integrity": "sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==", + "node_modules/@cspell/dict-dart": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.2.4.tgz", + "integrity": "sha512-of/cVuUIZZK/+iqefGln8G3bVpfyN6ZtH+LyLkHMoR5tEj+2vtilGNk9ngwyR8L4lEqbKuzSkOxgfVjsXf5PsQ==", "dev": true, - "dependencies": { - "@algolia/cache-common": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/requester-common": "4.17.0" - } + "license": "MIT" }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "node_modules/@cspell/dict-data-science": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.5.tgz", + "integrity": "sha512-nNSILXmhSJox9/QoXICPQgm8q5PbiSQP4afpbkBqPi/u/b3K9MbNH5HvOOa6230gxcGdbZ9Argl2hY/U8siBlg==", "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } + "license": "MIT" }, - "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "node_modules/@cspell/dict-django": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.3.tgz", + "integrity": "sha512-yBspeL3roJlO0a1vKKNaWABURuHdHZ9b1L8d3AukX0AsBy9snSggc8xCavPmSzNfeMDXbH+1lgQiYBd3IW03fg==", "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/compat-data": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", - "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", + "node_modules/@cspell/dict-docker": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.11.tgz", + "integrity": "sha512-s0Yhb16/R+UT1y727ekbR/itWQF3Qz275DR1ahOa66wYtPjHUXmhM3B/LT3aPaX+hD6AWmK23v57SuyfYHUjsw==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", + "node_modules/@cspell/dict-dotnet": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.8.tgz", + "integrity": "sha512-MD8CmMgMEdJAIPl2Py3iqrx3B708MbCIXAuOeZ0Mzzb8YmLmiisY7QEYSZPg08D7xuwARycP0Ki+bb0GAkFSqg==", "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } + "license": "MIT" }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@cspell/dict-elixir": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.6.tgz", + "integrity": "sha512-TfqSTxMHZ2jhiqnXlVKM0bUADtCvwKQv2XZL/DI0rx3doG8mEMS8SGPOmiyyGkHpR/pGOq18AFH3BEm4lViHIw==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "node_modules/@cspell/dict-en_us": { + "version": "4.3.28", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.28.tgz", + "integrity": "sha512-BN1PME7cOl7DXRQJ92pEd1f0Xk5sqjcDfThDGkKcsgwbSOY7KnTc/czBW6Pr3WXIchIm6cT12KEfjNqx7U7Rrw==", "dev": true, - "dependencies": { - "@babel/types": "^7.21.4", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "node_modules/@cspell/dict-en-common-misspellings": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.7.tgz", + "integrity": "sha512-qNFo3G4wyabcwnM+hDrMYKN9vNVg/k9QkhqSlSst6pULjdvPyPs1mqz1689xO/v9t8e6sR4IKc3CgUXDMTYOpA==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "CC BY-SA 4.0" }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "node_modules/@cspell/dict-en-gb": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz", + "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==", "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", - "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", + "node_modules/@cspell/dict-filetypes": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.8.tgz", + "integrity": "sha512-D3N8sm/iptzfVwsib/jvpX+K/++rM8SRpLDFUaM4jxm8EyGmSIYRbKZvdIv5BkAWmMlTWoRqlLn7Yb1b11jKJg==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@cspell/dict-flutter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.0.3.tgz", + "integrity": "sha512-52C9aUEU22ptpgYh6gQyIdA4MP6NPwzbEqndfgPh3Sra191/kgs7CVqXiO1qbtZa9gnYHUoVApkoxRE7mrXHfg==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz", - "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==", + "node_modules/@cspell/dict-fonts": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.3.tgz", + "integrity": "sha512-sPd17kV5qgYXLteuHFPn5mbp/oCHKgitNfsZLFC3W2fWEgZlhg4hK+UGig3KzrYhhvQ8wBnmZrAQm0TFKCKzsA==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.4.tgz", - "integrity": "sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==", + "node_modules/@cspell/dict-fsharp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.4.tgz", + "integrity": "sha512-G5wk0o1qyHUNi9nVgdE1h5wl5ylq7pcBjX8vhjHcO4XBq20D5eMoXjwqMo/+szKAqzJ+WV3BgAL50akLKrT9Rw==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "node_modules/@cspell/dict-fullstack": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.3.tgz", + "integrity": "sha512-62PbndIyQPH11mAv0PyiyT0vbwD0AXEocPpHlCHzfb5v9SspzCCbzQ/LIBiFmyRa+q5LMW35CnSVu6OXdT+LKg==", "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } + "license": "MIT" }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@cspell/dict-gaming-terms": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.8.tgz", + "integrity": "sha512-7OL0zTl93WFWhhtpXFrtm9uZXItC3ncAs8d0iQDMMFVNU1rBr6raBNxJskxE5wx2Ant12fgI66ZGVagXfN+yfA==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "node_modules/@cspell/dict-git": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.3.tgz", + "integrity": "sha512-LSxB+psZ0qoj83GkyjeEH/ZViyVsGEF/A6BAo8Nqc0w0HjD2qX/QR4sfA6JHUgQ3Yi/ccxdK7xNIo67L2ScW5A==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "node_modules/@cspell/dict-golang": { + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.17.tgz", + "integrity": "sha512-uDDLEJ/cHdLiqPw4+5BnmIo2i/TSR+uDvYd6JlBjTmjBKpOCyvUgYRztH7nv5e7virsN5WDiUWah4/ATQGz4Pw==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "node_modules/@cspell/dict-google": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.4.tgz", + "integrity": "sha512-JThUT9eiguCja1mHHLwYESgxkhk17Gv7P3b1S7ZJzXw86QyVHPrbpVoMpozHk0C9o+Ym764B7gZGKmw9uMGduQ==", "dev": true, - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "node_modules/@cspell/dict-haskell": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.4.tgz", + "integrity": "sha512-EwQsedEEnND/vY6tqRfg9y7tsnZdxNqOxLXSXTsFA6JRhUlr8Qs88iUUAfsUzWc4nNmmzQH2UbtT25ooG9x4nA==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "node_modules/@cspell/dict-html": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.10.tgz", + "integrity": "sha512-I9uRAcdtHbh0wEtYZlgF0TTcgH0xaw1B54G2CW+tx4vHUwlde/+JBOfIzird4+WcMv4smZOfw+qHf7puFUbI5g==", "dev": true, - "dependencies": { - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "node_modules/@cspell/dict-html-symbol-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.3.tgz", + "integrity": "sha512-aABXX7dMLNFdSE8aY844X4+hvfK7977sOWgZXo4MTGAmOzR8524fjbJPswIBK7GaD3+SgFZ2yP2o0CFvXDGF+A==", "dev": true, - "dependencies": { - "@babel/types": "^7.21.4" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "node_modules/@cspell/dict-java": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.10.tgz", + "integrity": "sha512-pVNcOnmoGiNL8GSVq4WbX/Vs2FGS0Nej+1aEeGuUY9CU14X8yAVCG+oih5ZoLt1jaR8YfR8byUF8wdp4qG4XIw==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "node_modules/@cspell/dict-julia": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.0.4.tgz", + "integrity": "sha512-bFVgNX35MD3kZRbXbJVzdnN7OuEqmQXGpdOi9jzB40TSgBTlJWA4nxeAKV4CPCZxNRUGnLH0p05T/AD7Aom9/w==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "node_modules/@cspell/dict-k8s": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.9.tgz", + "integrity": "sha512-Q7GELSQIzo+BERl2ya/nBEnZeQC+zJP19SN1pI6gqDYraM51uYJacbbcWLYYO2Y+5joDjNt/sd/lJtLaQwoSlA==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "node_modules/@cspell/dict-latex": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.3.tgz", + "integrity": "sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "node_modules/@cspell/dict-lorem-ipsum": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.3.tgz", + "integrity": "sha512-WFpDi/PDYHXft6p0eCXuYnn7mzMEQLVeqpO+wHSUd+kz5ADusZ4cpslAA4wUZJstF1/1kMCQCZM6HLZic9bT8A==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "node_modules/@cspell/dict-lua": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.6.tgz", + "integrity": "sha512-Jwvh1jmAd9b+SP9e1GkS2ACbqKKRo9E1f9GdjF/ijmooZuHU0hPyqvnhZzUAxO1egbnNjxS/J2T6iUtjAUK2KQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "node_modules/@cspell/dict-makefile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.3.tgz", + "integrity": "sha512-R3U0DSpvTs6qdqfyBATnePj9Q/pypkje0Nj26mQJ8TOBQutCRAJbr2ZFAeDjgRx5EAJU/+8txiyVF97fbVRViw==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.0" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "node_modules/@cspell/dict-markdown": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.7.tgz", + "integrity": "sha512-F9SGsSOokFn976DV4u/1eL4FtKQDSgJHSZ3+haPRU5ki6OEqojxKa8hhj4AUrtNFpmBaJx/WJ4YaEzWqG7hgqg==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "peerDependencies": { + "@cspell/dict-css": "^4.0.16", + "@cspell/dict-html": "^4.0.10", + "@cspell/dict-html-symbol-entities": "^4.0.3", + "@cspell/dict-typescript": "^3.1.11" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "node_modules/@cspell/dict-monkeyc": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.9.tgz", + "integrity": "sha512-Jvf6g5xlB4+za3ThvenYKREXTEgzx5gMUSzrAxIiPleVG4hmRb/GBSoSjtkGaibN3XxGx5x809gSTYCA/IHCpA==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "node_modules/@cspell/dict-node": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.5.tgz", + "integrity": "sha512-7NbCS2E8ZZRZwlLrh2sA0vAk9n1kcTUiRp/Nia8YvKaItGXLfxYqD2rMQ3HpB1kEutal6hQLVic3N2Yi1X7AaA==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "node_modules/@cspell/dict-npm": { + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.14.tgz", + "integrity": "sha512-7VV/rrRlxOwy5j0bpw6/Uci+nx/rwSgx45FJdeKq++nHsBx/nEXMFNODknm4Mi6i7t7uOVHExpifrR6w6xTWww==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", + "node_modules/@cspell/dict-php": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.13.tgz", + "integrity": "sha512-P6sREMZkhElzz/HhXAjahnICYIqB/HSGp1EhZh+Y6IhvC15AzgtDP8B8VYCIsQof6rPF1SQrFwunxOv8H1e2eg==", "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "node_modules/@cspell/dict-powershell": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.13.tgz", + "integrity": "sha512-0qdj0XZIPmb77nRTynKidRJKTU0Fl+10jyLbAhFTuBWKMypVY06EaYFnwhsgsws/7nNX8MTEQuewbl9bWFAbsg==", "dev": true, - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "node_modules/@cspell/dict-public-licenses": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.11.tgz", + "integrity": "sha512-rR5KjRUSnVKdfs5G+gJ4oIvQvm8+NJ6cHWY2N+GE69/FSGWDOPHxulCzeGnQU/c6WWZMSimG9o49i9r//lUQyA==", "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@cspell/dict-python": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.12.tgz", + "integrity": "sha512-U25eOFu+RE0aEcF2AsxZmq3Lic7y9zspJ9SzjrC0mfJz+yr3YmSCw4E0blMD3mZoNcf7H/vMshuKIY5AY36U+Q==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" + "@cspell/dict-data-science": "^2.0.5" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@cspell/dict-r": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.4.tgz", + "integrity": "sha512-cBpRsE/U0d9BRhiNRMLMH1PpWgw+N+1A2jumgt1if9nBGmQw4MUpg2u9I0xlFVhstTIdzXiLXMxP45cABuiUeQ==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" + }, + "node_modules/@cspell/dict-ruby": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.7.tgz", + "integrity": "sha512-4/d0hcoPzi5Alk0FmcyqlzFW9lQnZh9j07MJzPcyVO62nYJJAGKaPZL2o4qHeCS/od/ctJC5AHRdoUm0ktsw6Q==", + "dev": true, + "license": "MIT" }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@cspell/dict-rust": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.10.tgz", + "integrity": "sha512-6o5C8566VGTTctgcwfF3Iy7314W0oMlFFSQOadQ0OEdJ9Z9ERX/PDimrzP3LGuOrvhtEFoK8pj+BLnunNwRNrw==", "dev": true, - "dependencies": { - "color-name": "1.1.3" - } + "license": "MIT" }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "node_modules/@cspell/dict-scala": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.6.tgz", + "integrity": "sha512-tl0YWAfjUVb4LyyE4JIMVE8DlLzb1ecHRmIWc4eT6nkyDqQgHKzdHsnusxFEFMVLIQomgSg0Zz6hJ5S1E4W4ww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-software-terms": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.17.tgz", + "integrity": "sha512-QORIk1R5DV8oOQ+oAlUWE7UomaJwUucqu2srrc2+PmkoI6R1fJwwg2uHCPBWlIb4PGDNEdXLv9BAD13H+0wytQ==", + "dev": true, + "license": "MIT" }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "node_modules/@cspell/dict-sql": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.8.tgz", + "integrity": "sha512-dJRE4JV1qmXTbbGm6WIcg1knmR6K5RXnQxF4XHs5HA3LAjc/zf77F95i5LC+guOGppVF6Hdl66S2UyxT+SAF3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-svelte": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.5.tgz", + "integrity": "sha512-sseHlcXOqWE4Ner9sg8KsjxwSJ2yssoJNqFHR9liWVbDV+m7kBiUtn2EB690TihzVsEmDr/0Yxrbb5Bniz70mA==", "dev": true, - "engines": { - "node": ">=0.8.0" - } + "license": "MIT" }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@cspell/dict-swift": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.4.tgz", + "integrity": "sha512-CsFF0IFAbRtYNg0yZcdaYbADF5F3DsM8C4wHnZefQy8YcHP/qjAF/GdGfBFBLx+XSthYuBlo2b2XQVdz3cJZBw==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@cspell/dict-terraform": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.6.tgz", + "integrity": "sha512-Sqm5vGbXuI9hCFcr4w6xWf4Y25J9SdleE/IqfM6RySPnk8lISEmVdax4k6+Kinv9qaxyvnIbUUN4WFLWcBPQAg==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "node_modules/@cspell/dict-typescript": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.11.tgz", + "integrity": "sha512-FwvK5sKbwrVpdw0e9+1lVTl8FPoHYvfHRuQRQz2Ql5XkC0gwPPkpoyD1zYImjIyZRoYXk3yp9j8ss4iz7A7zoQ==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "node_modules/@cspell/dict-vue": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.3.tgz", + "integrity": "sha512-akmYbrgAGumqk1xXALtDJcEcOMYBYMnkjpmGzH13Ozhq1mkPF4VgllFQlm1xYde+BUKNnzMgPEzxrL2qZllgYA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", - "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", + "node_modules/@cspell/dynamic-import": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.16.1.tgz", + "integrity": "sha512-mEfdeS1kFKpJoDsQ8wW6PxO3+ncYuZCWCASR0trbzZDduzO2RcogMUgzP99obHtYbgXadw94qcQWXB8OYTPSwg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.7" + "import-meta-resolve": "^4.1.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "node": ">=18.0" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "node_modules/@cspell/filetypes": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.16.1.tgz", + "integrity": "sha512-zpbNg3n26muR1jdMbylw5YsaVGyS9LU5Lfy20gU7RygAk6kFyx3Yz4C84EihBGQHy2gVEsEeyCCxk+R8RXuPZA==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "node_modules/@cspell/strong-weak-map": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.16.1.tgz", + "integrity": "sha512-jJQS05wg2iUkLKnPR8NEq3LqvqHWKnvUDFoPwaJzYw6ol/O4yi/lv+Me9+XCPrgjpnAz+8APhWkhrR/O71R1Bw==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", + "node_modules/@cspell/url": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.16.1.tgz", + "integrity": "sha512-kGlr7Wdo4xJpXKal/Gqo3Ll5Is7ptlIlLZOB/hzR6R53Fw4N6SdipTDIeHHqC15p2AXTEG6TSNdhk9dA50LY6w==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=18.0" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.21.0.tgz", - "integrity": "sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/plugin-syntax-decorators": "^7.21.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "node_modules/@eslint/config-array": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "*" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "node_modules/@eslint/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "*" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", - "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "node_modules/@eslint/js": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "Apache-2.0", "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@eslint/plugin-kit": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "levn": "^0.4.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.18.0" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.21.0.tgz", - "integrity": "sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=18.18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "node_modules/@types/chai": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.1.tgz", + "integrity": "sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/deep-eql": "*" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "undici-types": "~6.20.0" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz", + "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.17.0", + "@typescript-eslint/type-utils": "8.17.0", + "@typescript-eslint/utils": "8.17.0", + "@typescript-eslint/visitor-keys": "8.17.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "node_modules/@typescript-eslint/parser": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz", + "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@typescript-eslint/scope-manager": "8.17.0", + "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/typescript-estree": "8.17.0", + "@typescript-eslint/visitor-keys": "8.17.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz", + "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" + "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/visitor-keys": "8.17.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz", + "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" + "@typescript-eslint/typescript-estree": "8.17.0", + "@typescript-eslint/utils": "8.17.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", + "node_modules/@typescript-eslint/types": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz", + "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz", + "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/visitor-keys": "8.17.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "node_modules/@typescript-eslint/utils": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz", + "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.17.0", + "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/typescript-estree": "8.17.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz", + "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "8.17.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, + "license": "MIT", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "acorn": "^8.11.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" + "environment": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.21.3.tgz", - "integrity": "sha512-4DVcFeWe/yDYBLp0kBmOGFJ6N2UYg7coGid1gdxb4co62dy/xISDMaYBXBVXEDhfgMk7qkbcYiGtwd5Q/hwDDQ==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", - "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz", - "integrity": "sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.21.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", - "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.18.6" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", - "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.4.tgz", - "integrity": "sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-plugin-utils": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "semver": "^6.3.0" - }, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "fill-range": "^7.1.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/c8": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz", + "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^7.0.1", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "monocart-coverage-reports": "^2" + }, + "peerDependenciesMeta": { + "monocart-coverage-reports": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", - "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", + "node_modules/chai": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-typescript": "^7.20.0" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "node_modules/chalk-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "chalk": "^5.2.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.16" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, - "node_modules/@babel/preset-env": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.4.tgz", - "integrity": "sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==", + "node_modules/chalk-template/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7", - "@babel/plugin-proposal-async-generator-functions": "^7.20.7", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.21.0", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.20.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.21.0", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.21.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.20.7", - "@babel/plugin-transform-async-to-generator": "^7.20.7", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.21.0", - "@babel/plugin-transform-classes": "^7.21.0", - "@babel/plugin-transform-computed-properties": "^7.20.7", - "@babel/plugin-transform-destructuring": "^7.21.3", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.21.0", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.20.11", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", - "@babel/plugin-transform-modules-systemjs": "^7.20.11", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.21.3", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.20.5", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.20.7", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.21.4", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">= 16" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/@babel/preset-react": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", - "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "node_modules/clear-module": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", + "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-pure-annotations": "^7.18.6" + "parent-module": "^2.0.0", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/preset-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.4.tgz", - "integrity": "sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-syntax-jsx": "^7.21.4", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", - "@babel/plugin-transform-typescript": "^7.21.3" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.11" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", - "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.11" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cspell/cspell-bundled-dicts": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-6.31.1.tgz", - "integrity": "sha512-rsIev+dk1Vd8H1OKZhNhXycIVsMfeWJaeW3QUi1l4oIoGwQfJVbs1ZPZPHE5cglzyHOW1jQNStXf34UKaC6siA==", - "dev": true, - "dependencies": { - "@cspell/dict-ada": "^4.0.1", - "@cspell/dict-aws": "^3.0.0", - "@cspell/dict-bash": "^4.1.1", - "@cspell/dict-companies": "^3.0.9", - "@cspell/dict-cpp": "^5.0.2", - "@cspell/dict-cryptocurrencies": "^3.0.1", - "@cspell/dict-csharp": "^4.0.2", - "@cspell/dict-css": "^4.0.5", - "@cspell/dict-dart": "^2.0.2", - "@cspell/dict-django": "^4.0.2", - "@cspell/dict-docker": "^1.1.6", - "@cspell/dict-dotnet": "^5.0.0", - "@cspell/dict-elixir": "^4.0.2", - "@cspell/dict-en_us": "^4.3.2", - "@cspell/dict-en-common-misspellings": "^1.0.2", - "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.0", - "@cspell/dict-fonts": "^3.0.1", - "@cspell/dict-fullstack": "^3.1.5", - "@cspell/dict-gaming-terms": "^1.0.4", - "@cspell/dict-git": "^2.0.0", - "@cspell/dict-golang": "^6.0.1", - "@cspell/dict-haskell": "^4.0.1", - "@cspell/dict-html": "^4.0.3", - "@cspell/dict-html-symbol-entities": "^4.0.0", - "@cspell/dict-java": "^5.0.5", - "@cspell/dict-k8s": "^1.0.1", - "@cspell/dict-latex": "^4.0.0", - "@cspell/dict-lorem-ipsum": "^3.0.0", - "@cspell/dict-lua": "^4.0.1", - "@cspell/dict-node": "^4.0.2", - "@cspell/dict-npm": "^5.0.5", - "@cspell/dict-php": "^4.0.1", - "@cspell/dict-powershell": "^5.0.1", - "@cspell/dict-public-licenses": "^2.0.2", - "@cspell/dict-python": "^4.0.2", - "@cspell/dict-r": "^2.0.1", - "@cspell/dict-ruby": "^5.0.0", - "@cspell/dict-rust": "^4.0.1", - "@cspell/dict-scala": "^5.0.0", - "@cspell/dict-software-terms": "^3.1.6", - "@cspell/dict-sql": "^2.1.0", - "@cspell/dict-svelte": "^1.0.2", - "@cspell/dict-swift": "^2.0.1", - "@cspell/dict-typescript": "^3.1.1", - "@cspell/dict-vue": "^3.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@cspell/cspell-pipe": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-6.31.1.tgz", - "integrity": "sha512-zk1olZi4dr6GLm5PAjvsiZ01HURNSruUYFl1qSicGnTwYN8GaN4RhAwannAytcJ7zJPIcyXlid0YsB58nJf3wQ==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@cspell/cspell-service-bus": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-6.31.1.tgz", - "integrity": "sha512-YyBicmJyZ1uwKVxujXw7sgs9x+Eps43OkWmCtDZmZlnq489HdTSuhF1kTbVi2yeFSeaXIS87+uHo12z97KkQpg==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@cspell/cspell-types": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-6.31.1.tgz", - "integrity": "sha512-1KeTQFiHMssW1eRoF2NZIEg4gPVIfXLsL2+VSD/AV6YN7lBcuf6gRRgV5KWYarhxtEfjxhDdDTmu26l/iJEUtw==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@cspell/dict-ada": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.1.tgz", - "integrity": "sha512-/E9o3nHrXOhYmQE43deKbxZcR3MIJAsa+66IzP9TXGHheKEx8b9dVMVVqydDDH8oom1H0U20NRPtu6KRVbT9xw==", - "dev": true - }, - "node_modules/@cspell/dict-aws": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-3.0.0.tgz", - "integrity": "sha512-O1W6nd5y3Z00AMXQMzfiYrIJ1sTd9fB1oLr+xf/UD7b3xeHeMeYE2OtcWbt9uyeHim4tk+vkSTcmYEBKJgS5bQ==", - "dev": true - }, - "node_modules/@cspell/dict-bash": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.1.tgz", - "integrity": "sha512-8czAa/Mh96wu2xr0RXQEGMTBUGkTvYn/Pb0o+gqOO1YW+poXGQc3gx0YPqILDryP/KCERrNvkWUJz3iGbvwC2A==", - "dev": true - }, - "node_modules/@cspell/dict-companies": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.9.tgz", - "integrity": "sha512-wSkVIJjk33Sm3LhieNv9TsSvUSeP0R/h8xx06NqbMYF43w9J8hZiMHlbB3FzaSOHRpXT5eBIJBVTeFbceZdiqg==", - "dev": true - }, - "node_modules/@cspell/dict-cpp": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.2.tgz", - "integrity": "sha512-Q0ZjfhrHHfm0Y1/7LMCq3Fne/bhiBeBogUw4TV1wX/1tg3m+5BtaW/7GiOzRk+rFsblVj3RFam59VJKMT3vSoQ==", - "dev": true - }, - "node_modules/@cspell/dict-cryptocurrencies": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-3.0.1.tgz", - "integrity": "sha512-Tdlr0Ahpp5yxtwM0ukC13V6+uYCI0p9fCRGMGZt36rWv8JQZHIuHfehNl7FB/Qc09NCF7p5ep0GXbL+sVTd/+w==", - "dev": true - }, - "node_modules/@cspell/dict-csharp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz", - "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==", - "dev": true - }, - "node_modules/@cspell/dict-css": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.5.tgz", - "integrity": "sha512-z5vw8nJSyKd6d3i5UmMNoVcAp0wxvs9OHWOmAeJKT9fO3tok02gK24VZhcJ0NJtiKdHQ2zRuzdfWl51wdAiY6A==", - "dev": true - }, - "node_modules/@cspell/dict-dart": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.0.2.tgz", - "integrity": "sha512-jigcODm7Z4IFZ4vParwwP3IT0fIgRq/9VoxkXfrxBMsLBGGM2QltHBj7pl+joX+c4cOHxfyZktGJK1B1wFtR4Q==", - "dev": true - }, - "node_modules/@cspell/dict-django": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.0.2.tgz", - "integrity": "sha512-L0Yw6+Yh2bE9/FAMG4gy9m752G4V8HEBjEAGeRIQ9qvxDLR9yD6dPOtgEFTjv7SWlKSrLb9wA/W3Q2GKCOusSg==", - "dev": true - }, - "node_modules/@cspell/dict-docker": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.6.tgz", - "integrity": "sha512-zCCiRTZ6EOQpBnSOm0/3rnKW1kCcAUDUA7SxJG3SuH6iZvKi3I8FEg8+O83WQUeXg0SyPNerD9F40JLnnJjJig==", - "dev": true - }, - "node_modules/@cspell/dict-dotnet": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz", - "integrity": "sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==", - "dev": true - }, - "node_modules/@cspell/dict-elixir": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.2.tgz", - "integrity": "sha512-/YeHlpZ1pE9VAyxp3V0xyUPapNyC61WwFuw2RByeoMqqYaIfS3Hw+JxtimOsAKVhUvgUH58zyKl5K5Q6FqgCpw==", - "dev": true - }, - "node_modules/@cspell/dict-en_us": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.2.tgz", - "integrity": "sha512-o8xtHDLPNzW6hK5b1TaDTWt25vVi9lWlL6/dZ9YoS+ZMj+Dy/yuXatqfOgeGyU3a9+2gxC0kbr4oufMUQXI2mQ==", - "dev": true - }, - "node_modules/@cspell/dict-en-common-misspellings": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", - "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==", - "dev": true - }, - "node_modules/@cspell/dict-en-gb": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz", - "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==", - "dev": true - }, - "node_modules/@cspell/dict-filetypes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.0.tgz", - "integrity": "sha512-Fiyp0z5uWaK0d2TfR9GMUGDKmUMAsOhGD5A0kHoqnNGswL2iw0KB0mFBONEquxU65fEnQv4R+jdM2d9oucujuA==", - "dev": true - }, - "node_modules/@cspell/dict-fonts": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-3.0.2.tgz", - "integrity": "sha512-Z5QdbgEI7DV+KPXrAeDA6dDm/vTzyaW53SGlKqz6PI5VhkOjgkBXv3YtZjnxMZ4dY2ZIqq+RUK6qa9Pi8rQdGQ==", - "dev": true - }, - "node_modules/@cspell/dict-fullstack": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.1.5.tgz", - "integrity": "sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==", - "dev": true - }, - "node_modules/@cspell/dict-gaming-terms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.4.tgz", - "integrity": "sha512-hbDduNXlk4AOY0wFxcDMWBPpm34rpqJBeqaySeoUH70eKxpxm+dvjpoRLJgyu0TmymEICCQSl6lAHTHSDiWKZg==", - "dev": true - }, - "node_modules/@cspell/dict-git": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", - "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==", - "dev": true - }, - "node_modules/@cspell/dict-golang": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.1.tgz", - "integrity": "sha512-Z19FN6wgg2M/A+3i1O8qhrGaxUUGOW8S2ySN0g7vp4HTHeFmockEPwYx7gArfssNIruw60JorZv+iLJ6ilTeow==", - "dev": true - }, - "node_modules/@cspell/dict-haskell": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz", - "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==", - "dev": true - }, - "node_modules/@cspell/dict-html": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.3.tgz", - "integrity": "sha512-Gae8i8rrArT0UyG1I6DHDK62b7Be6QEcBSIeWOm4VIIW1CASkN9B0qFgSVnkmfvnu1Y3H7SSaaEynKjdj3cs8w==", - "dev": true - }, - "node_modules/@cspell/dict-html-symbol-entities": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz", - "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==", - "dev": true - }, - "node_modules/@cspell/dict-java": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.5.tgz", - "integrity": "sha512-X19AoJgWIBwJBSWGFqSgHaBR/FEykBHTMjL6EqOnhIGEyE9nvuo32tsSHjXNJ230fQxQptEvRZoaldNLtKxsRg==", - "dev": true - }, - "node_modules/@cspell/dict-k8s": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.1.tgz", - "integrity": "sha512-gc5y4Nm3hVdMZNBZfU2M1AsAmObZsRWjCUk01NFPfGhFBXyVne41T7E62rpnzu5330FV/6b/TnFcPgRmak9lLw==", - "dev": true - }, - "node_modules/@cspell/dict-latex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz", - "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==", - "dev": true - }, - "node_modules/@cspell/dict-lorem-ipsum": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-3.0.0.tgz", - "integrity": "sha512-msEV24qEpzWZs2kcEicqYlhyBpR0amfDkJOs+iffC07si9ftqtQ+yP3lf1VFLpgqw3SQh1M1vtU7RD4sPrNlcQ==", - "dev": true - }, - "node_modules/@cspell/dict-lua": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.1.tgz", - "integrity": "sha512-j0MFmeCouSoC6EdZTbvGe1sJ9V+ruwKSeF+zRkNNNload7R72Co5kX1haW2xLHGdlq0kqSy1ODRZKdVl0e+7hg==", - "dev": true - }, - "node_modules/@cspell/dict-node": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-4.0.2.tgz", - "integrity": "sha512-FEQJ4TnMcXEFslqBQkXa5HposMoCGsiBv2ux4IZuIXgadXeHKHUHk60iarWpjhzNzQLyN2GD7NoRMd12bK3Llw==", - "dev": true - }, - "node_modules/@cspell/dict-npm": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.5.tgz", - "integrity": "sha512-eirZm4XpJNEcbmLGIwI2qXdRRlCKwEsH9mT3qCUytmbj6S6yn63F+8bShMW/yQBedV7+GXq9Td+cJdqiVutOiA==", - "dev": true - }, - "node_modules/@cspell/dict-php": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.1.tgz", - "integrity": "sha512-XaQ/JkSyq2c07MfRG54DjLi2CV+HHwS99DDCAao9Fq2JfkWroTQsUeek7wYZXJATrJVOULoV3HKih12x905AtQ==", - "dev": true - }, - "node_modules/@cspell/dict-powershell": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.1.tgz", - "integrity": "sha512-lLl+syWFgfv2xdsoxHfPIB2FGkn//XahCIKcRaf52AOlm1/aXeaJN579B9HCpvM7wawHzMqJ33VJuL/vb6Lc4g==", - "dev": true - }, - "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.2.tgz", - "integrity": "sha512-baKkbs/WGEV2lCWZoL0KBPh3uiPcul5GSDwmXEBAsR5McEW52LF94/b7xWM0EmSAc/y8ODc5LnPYC7RDRLi6LQ==", - "dev": true - }, - "node_modules/@cspell/dict-python": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.0.3.tgz", - "integrity": "sha512-tUEMEbtV5kjuiX//K1SFo4ayO6q+bY9ghqTAo3bdlraZy59MFx8KVLYHnRndVqGwM8rRwRhp9Kmb6boAnBl+Kw==", - "dev": true - }, - "node_modules/@cspell/dict-r": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz", - "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==", - "dev": true - }, - "node_modules/@cspell/dict-ruby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.0.tgz", - "integrity": "sha512-ssb96QxLZ76yPqFrikWxItnCbUKhYXJ2owkoIYzUGNFl2CHSoHCb5a6Zetum9mQ/oUA3gNeUhd28ZUlXs0la2A==", - "dev": true - }, - "node_modules/@cspell/dict-rust": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.1.tgz", - "integrity": "sha512-xJSSzHDK2z6lSVaOmMxl3PTOtfoffaxMo7fTcbZUF+SCJzfKbO6vnN9TCGX2sx1RHFDz66Js6goz6SAZQdOwaw==", - "dev": true - }, - "node_modules/@cspell/dict-scala": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.0.tgz", - "integrity": "sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==", - "dev": true - }, - "node_modules/@cspell/dict-software-terms": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.1.6.tgz", - "integrity": "sha512-w46+pIMRVtrDuTZXK/YxDP5NL5yVoX0ImEPO0s9WbxdyyfhzAF3sGYHBGN/50OGLHExcqe6Idb9feoRC9mCLxw==", - "dev": true - }, - "node_modules/@cspell/dict-sql": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.0.tgz", - "integrity": "sha512-Bb+TNWUrTNNABO0bmfcYXiTlSt0RD6sB2MIY+rNlaMyIwug43jUjeYmkLz2tPkn3+2uvySeFEOMVYhMVfcuDKg==", - "dev": true - }, - "node_modules/@cspell/dict-svelte": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz", - "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==", - "dev": true - }, - "node_modules/@cspell/dict-swift": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz", - "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==", - "dev": true - }, - "node_modules/@cspell/dict-typescript": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.1.tgz", - "integrity": "sha512-N9vNJZoOXmmrFPR4ir3rGvnqqwmQGgOYoL1+y6D4oIhyr7FhaYiyF/d7QT61RmjZQcATMa6PSL+ZisCeRLx9+A==", - "dev": true - }, - "node_modules/@cspell/dict-vue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz", - "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==", - "dev": true - }, - "node_modules/@cspell/dynamic-import": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-6.31.1.tgz", - "integrity": "sha512-uliIUv9uZlnyYmjUlcw/Dm3p0xJOEnWJNczHAfqAl4Ytg6QZktw0GtUA9b1umbRXLv0KRTPtSC6nMq3cR7rRmQ==", - "dev": true, - "dependencies": { - "import-meta-resolve": "^2.2.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@cspell/strong-weak-map": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-6.31.1.tgz", - "integrity": "sha512-z8AuWvUuSnugFKJOA9Ke0aiFuehcqLFqia9bk8XaQNEWr44ahPVn3sEWnAncTxPbpWuUw5UajoJa0egRAE1CCg==", - "dev": true, - "engines": { - "node": ">=14.6" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@docsearch/css": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.3.3.tgz", - "integrity": "sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==", - "dev": true - }, - "node_modules/@docsearch/react": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.3.3.tgz", - "integrity": "sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==", - "dev": true, - "dependencies": { - "@algolia/autocomplete-core": "1.7.4", - "@algolia/autocomplete-preset-algolia": "1.7.4", - "@docsearch/css": "3.3.3", - "algoliasearch": "^4.0.0" - }, - "peerDependencies": { - "@types/react": ">= 16.8.0 < 19.0.0", - "react": ">= 16.8.0 < 19.0.0", - "react-dom": ">= 16.8.0 < 19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@docusaurus/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.0.tgz", - "integrity": "sha512-J55/WEoIpRcLf3afO5POHPguVZosKmJEQWKBL+K7TAnfuE7i+Y0NPLlkKtnWCehagGsgTqClfQEexH/UT4kELA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.18.6", - "@babel/generator": "^7.18.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.18.6", - "@babel/preset-env": "^7.18.6", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@babel/runtime": "^7.18.6", - "@babel/runtime-corejs3": "^7.18.6", - "@babel/traverse": "^7.18.8", - "@docusaurus/cssnano-preset": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "@slorber/static-site-generator-webpack-plugin": "^4.0.7", - "@svgr/webpack": "^6.2.1", - "autoprefixer": "^10.4.7", - "babel-loader": "^8.2.5", - "babel-plugin-dynamic-import-node": "^2.3.3", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "clean-css": "^5.3.0", - "cli-table3": "^0.6.2", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "copy-webpack-plugin": "^11.0.0", - "core-js": "^3.23.3", - "css-loader": "^6.7.1", - "css-minimizer-webpack-plugin": "^4.0.0", - "cssnano": "^5.1.12", - "del": "^6.1.1", - "detect-port": "^1.3.0", - "escape-html": "^1.0.3", - "eta": "^2.0.0", - "file-loader": "^6.2.0", - "fs-extra": "^10.1.0", - "html-minifier-terser": "^6.1.0", - "html-tags": "^3.2.0", - "html-webpack-plugin": "^5.5.0", - "import-fresh": "^3.3.0", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.6.1", - "postcss": "^8.4.14", - "postcss-loader": "^7.0.0", - "prompts": "^2.4.2", - "react-dev-utils": "^12.0.1", - "react-helmet-async": "^1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.3.3", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.3", - "rtl-detect": "^1.0.4", - "semver": "^7.3.7", - "serve-handler": "^6.1.3", - "shelljs": "^0.8.5", - "terser-webpack-plugin": "^5.3.3", - "tslib": "^2.4.0", - "update-notifier": "^5.1.0", - "url-loader": "^4.1.1", - "wait-on": "^6.0.1", - "webpack": "^5.73.0", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-dev-server": "^4.9.3", - "webpack-merge": "^5.8.0", - "webpackbar": "^5.0.2" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/cssnano-preset": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.0.tgz", - "integrity": "sha512-RmdiA3IpsLgZGXRzqnmTbGv43W4OD44PCo+6Q/aYjEM2V57vKCVqNzuafE94jv0z/PjHoXUrjr69SaRymBKYYw==", - "dev": true, - "dependencies": { - "cssnano-preset-advanced": "^5.3.8", - "postcss": "^8.4.14", - "postcss-sort-media-queries": "^4.2.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@docusaurus/logger": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.0.tgz", - "integrity": "sha512-T8+qR4APN+MjcC9yL2Es+xPJ2923S9hpzDmMtdsOcUGLqpCGBbU1vp3AAqDwXtVgFkq+NsEk7sHdVsfLWR/AXw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@docusaurus/mdx-loader": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.0.tgz", - "integrity": "sha512-GWoH4izZKOmFoC+gbI2/y8deH/xKLvzz/T5BsEexBye8EHQlwsA7FMrVa48N063bJBH4FUOiRRXxk5rq9cC36g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.18.8", - "@babel/traverse": "^7.18.8", - "@docusaurus/logger": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@mdx-js/mdx": "^1.6.22", - "escape-html": "^1.0.3", - "file-loader": "^6.2.0", - "fs-extra": "^10.1.0", - "image-size": "^1.0.1", - "mdast-util-to-string": "^2.0.0", - "remark-emoji": "^2.2.0", - "stringify-object": "^3.3.0", - "tslib": "^2.4.0", - "unified": "^9.2.2", - "unist-util-visit": "^2.0.3", - "url-loader": "^4.1.1", - "webpack": "^5.73.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/module-type-aliases": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.0.tgz", - "integrity": "sha512-YEQO2D3UXs72qCn8Cr+RlycSQXVGN9iEUyuHwTuK4/uL/HFomB2FHSU0vSDM23oLd+X/KibQ3Ez6nGjQLqXcHg==", - "dev": true, - "dependencies": { - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "2.4.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.0.tgz", - "integrity": "sha512-YwkAkVUxtxoBAIj/MCb4ohN0SCtHBs4AS75jMhPpf67qf3j+U/4n33cELq7567hwyZ6fMz2GPJcVmctzlGGThQ==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "cheerio": "^1.0.0-rc.12", - "feed": "^4.2.2", - "fs-extra": "^10.1.0", - "lodash": "^4.17.21", - "reading-time": "^1.5.0", - "tslib": "^2.4.0", - "unist-util-visit": "^2.0.3", - "utility-types": "^3.10.0", - "webpack": "^5.73.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.0.tgz", - "integrity": "sha512-ic/Z/ZN5Rk/RQo+Io6rUGpToOtNbtPloMR2JcGwC1xT2riMu6zzfSwmBi9tHJgdXH6CB5jG+0dOZZO8QS5tmDg==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "@types/react-router-config": "^5.0.6", - "combine-promises": "^1.1.0", - "fs-extra": "^10.1.0", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.4.0", - "utility-types": "^3.10.0", - "webpack": "^5.73.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.0.tgz", - "integrity": "sha512-Pk2pOeOxk8MeU3mrTU0XLIgP9NZixbdcJmJ7RUFrZp1Aj42nd0RhIT14BGvXXyqb8yTQlk4DmYGAzqOfBsFyGw==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "fs-extra": "^10.1.0", - "tslib": "^2.4.0", - "webpack": "^5.73.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.0.tgz", - "integrity": "sha512-KC56DdYjYT7Txyux71vXHXGYZuP6yYtqwClvYpjKreWIHWus5Zt6VNi23rMZv3/QKhOCrN64zplUbdfQMvddBQ==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "fs-extra": "^10.1.0", - "react-json-view": "^1.21.3", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.0.tgz", - "integrity": "sha512-uGUzX67DOAIglygdNrmMOvEp8qG03X20jMWadeqVQktS6nADvozpSLGx4J0xbkblhJkUzN21WiilsP9iVP+zkw==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.0.tgz", - "integrity": "sha512-adj/70DANaQs2+TF/nRdMezDXFAV/O/pjAbUgmKBlyOTq5qoMe0Tk4muvQIwWUmiUQxFJe+sKlZGM771ownyOg==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.0.tgz", - "integrity": "sha512-E66uGcYs4l7yitmp/8kMEVQftFPwV9iC62ORh47Veqzs6ExwnhzBkJmwDnwIysHBF1vlxnzET0Fl2LfL5fRR3A==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.0.tgz", - "integrity": "sha512-pZxh+ygfnI657sN8a/FkYVIAmVv0CGk71QMKqJBOfMmDHNN1FeDeFkBjWP49ejBqpqAhjufkv5UWq3UOu2soCw==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "fs-extra": "^10.1.0", - "sitemap": "^7.1.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/preset-classic": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.0.tgz", - "integrity": "sha512-/5z5o/9bc6+P5ool2y01PbJhoGddEGsC0ej1MF6mCoazk8A+kW4feoUd68l7Bnv01rCnG3xy7kHUQP97Y0grUA==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/plugin-debug": "2.4.0", - "@docusaurus/plugin-google-analytics": "2.4.0", - "@docusaurus/plugin-google-gtag": "2.4.0", - "@docusaurus/plugin-google-tag-manager": "2.4.0", - "@docusaurus/plugin-sitemap": "2.4.0", - "@docusaurus/theme-classic": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-search-algolia": "2.4.0", - "@docusaurus/types": "2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/react-loadable": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", - "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", - "dev": true, - "dependencies": { - "@types/react": "*", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": "*" - } - }, - "node_modules/@docusaurus/theme-classic": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.0.tgz", - "integrity": "sha512-GMDX5WU6Z0OC65eQFgl3iNNEbI9IMJz9f6KnOyuMxNUR6q0qVLsKCNopFUDfFNJ55UU50o7P7o21yVhkwpfJ9w==", - "dev": true, - "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-translations": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "@mdx-js/react": "^1.6.22", - "clsx": "^1.2.1", - "copy-text-to-clipboard": "^3.0.1", - "infima": "0.2.0-alpha.43", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.4.14", - "prism-react-renderer": "^1.3.5", - "prismjs": "^1.28.0", - "react-router-dom": "^5.3.3", - "rtlcss": "^3.5.0", - "tslib": "^2.4.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/theme-common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.0.tgz", - "integrity": "sha512-IkG/l5f/FLY6cBIxtPmFnxpuPzc5TupuqlOx+XDN+035MdQcAh8wHXXZJAkTeYDeZ3anIUSUIvWa7/nRKoQEfg==", - "dev": true, - "dependencies": { - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "clsx": "^1.2.1", - "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^1.3.5", - "tslib": "^2.4.0", - "use-sync-external-store": "^1.2.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.0.tgz", - "integrity": "sha512-pPCJSCL1Qt4pu/Z0uxBAuke0yEBbxh0s4fOvimna7TEcBLPq0x06/K78AaABXrTVQM6S0vdocFl9EoNgU17hqA==", - "dev": true, - "dependencies": { - "@docsearch/react": "^3.1.1", - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-translations": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", - "algoliasearch": "^4.13.1", - "algoliasearch-helper": "^3.10.0", - "clsx": "^1.2.1", - "eta": "^2.0.0", - "fs-extra": "^10.1.0", - "lodash": "^4.17.21", - "tslib": "^2.4.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/theme-translations": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.0.tgz", - "integrity": "sha512-kEoITnPXzDPUMBHk3+fzEzbopxLD3fR5sDoayNH0vXkpUukA88/aDL1bqkhxWZHA3LOfJ3f0vJbOwmnXW5v85Q==", - "dev": true, - "dependencies": { - "fs-extra": "^10.1.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@docusaurus/types": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.0.tgz", - "integrity": "sha512-xaBXr+KIPDkIaef06c+i2HeTqVNixB7yFut5fBXPGI2f1rrmEV2vLMznNGsFwvZ5XmA3Quuefd4OGRkdo97Dhw==", - "dev": true, - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.6.0", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.73.0", - "webpack-merge": "^5.8.0" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, - "node_modules/@docusaurus/utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.0.tgz", - "integrity": "sha512-89hLYkvtRX92j+C+ERYTuSUK6nF9bGM32QThcHPg2EDDHVw6FzYQXmX6/p+pU5SDyyx5nBlE4qXR92RxCAOqfg==", - "dev": true, - "dependencies": { - "@docusaurus/logger": "2.4.0", - "@svgr/webpack": "^6.2.1", - "escape-string-regexp": "^4.0.0", - "file-loader": "^6.2.0", - "fs-extra": "^10.1.0", - "github-slugger": "^1.4.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", - "tslib": "^2.4.0", - "url-loader": "^4.1.1", - "webpack": "^5.73.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } - } - }, - "node_modules/@docusaurus/utils-common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.0.tgz", - "integrity": "sha512-zIMf10xuKxddYfLg5cS19x44zud/E9I7lj3+0bv8UIs0aahpErfNrGhijEfJpAfikhQ8tL3m35nH3hJ3sOG82A==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } - } - }, - "node_modules/@docusaurus/utils-validation": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.0.tgz", - "integrity": "sha512-IrBsBbbAp6y7mZdJx4S4pIA7dUyWSA0GNosPk6ZJ0fX3uYIEQgcQSGIgTeSC+8xPEx3c16o03en1jSDpgQgz/w==", - "dev": true, - "dependencies": { - "@docusaurus/logger": "2.4.0", - "@docusaurus/utils": "2.4.0", - "joi": "^17.6.0", - "js-yaml": "^4.1.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", - "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.1", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.25.16" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "node_modules/@mdx-js/mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", - "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", - "dev": true, - "dependencies": { - "@babel/core": "7.12.9", - "@babel/plugin-syntax-jsx": "7.12.1", - "@babel/plugin-syntax-object-rest-spread": "7.8.3", - "@mdx-js/util": "1.6.22", - "babel-plugin-apply-mdx-type-prop": "1.6.22", - "babel-plugin-extract-import-names": "1.6.22", - "camelcase-css": "2.0.1", - "detab": "2.0.4", - "hast-util-raw": "6.0.1", - "lodash.uniq": "4.5.0", - "mdast-util-to-hast": "10.0.1", - "remark-footnotes": "2.0.0", - "remark-mdx": "1.6.22", - "remark-parse": "8.0.3", - "remark-squeeze-paragraphs": "4.0.0", - "style-to-object": "0.3.0", - "unified": "9.2.0", - "unist-builder": "2.0.3", - "unist-util-visit": "2.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/mdx/node_modules/@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@mdx-js/mdx/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@mdx-js/mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@mdx-js/mdx/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@mdx-js/mdx/node_modules/unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", - "dev": true, - "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/react": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", - "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" - } - }, - "node_modules/@mdx-js/util": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", - "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", - "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", - "dev": true, - "dependencies": { - "eval": "^0.1.8", - "p-map": "^4.0.0", - "webpack-sources": "^3.2.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@stryker-mutator/api": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/api/-/api-6.4.2.tgz", - "integrity": "sha512-b9+h5lC2gdtjALUuu0FvcFCwaja7BVzYwmiR5JkQXr8sMtL3rcaYrX4wfI1uHmPqwx9wwjLKpn+FVuyc69IyuQ==", - "dev": true, - "dependencies": { - "mutation-testing-metrics": "1.7.14", - "mutation-testing-report-schema": "1.7.14", - "tslib": "~2.5.0" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/@stryker-mutator/core": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/core/-/core-6.4.2.tgz", - "integrity": "sha512-ftT7G9FwVItpY/sntQWX/Leh3jwPWRcF8tsTeSjiPkEre7gBYegjKgPoUsR4It6KSZE9HZW8ezqUyWTOI9qhzQ==", - "dev": true, - "dependencies": { - "@stryker-mutator/api": "6.4.2", - "@stryker-mutator/instrumenter": "6.4.2", - "@stryker-mutator/util": "6.4.2", - "ajv": "~8.12.0", - "chalk": "~5.2.0", - "commander": "~10.0.0", - "diff-match-patch": "1.0.5", - "emoji-regex": "~10.2.1", - "execa": "~7.1.0", - "file-url": "~4.0.0", - "get-port": "~6.1.0", - "glob": "~9.3.0", - "inquirer": "~9.1.0", - "lodash.flatmap": "~4.5.0", - "lodash.groupby": "~4.6.0", - "log4js": "~6.9.0", - "minimatch": "~7.4.2", - "mutation-testing-elements": "1.7.14", - "mutation-testing-metrics": "1.7.14", - "mutation-testing-report-schema": "1.7.14", - "npm-run-path": "~5.1.0", - "progress": "~2.0.0", - "rimraf": "~4.4.0", - "rxjs": "~7.8.0", - "semver": "^7.3.5", - "source-map": "~0.7.3", - "tree-kill": "~1.2.2", - "tslib": "~2.5.0", - "typed-inject": "~3.0.0", - "typed-rest-client": "~1.8.0" - }, - "bin": { - "stryker": "bin/stryker.js" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/@stryker-mutator/core/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@stryker-mutator/core/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@stryker-mutator/instrumenter": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/instrumenter/-/instrumenter-6.4.2.tgz", - "integrity": "sha512-rNX7XHtXE/WjtoK3hK7oga0BNObNcqGk3l7W1VVLpUqCwX3SkWNG6DcT68gp3g1/Ha+4ty7aSlVS/cPzHt/3lQ==", - "dev": true, - "dependencies": { - "@babel/core": "~7.21.0", - "@babel/generator": "~7.21.0", - "@babel/parser": "~7.21.0", - "@babel/plugin-proposal-class-properties": "~7.18.0", - "@babel/plugin-proposal-decorators": "~7.21.0", - "@babel/plugin-proposal-private-methods": "~7.18.0", - "@babel/preset-typescript": "~7.21.0", - "@stryker-mutator/api": "6.4.2", - "@stryker-mutator/util": "6.4.2", - "angular-html-parser": "~4.0.0", - "weapon-regex": "~1.0.2" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/@stryker-mutator/mocha-runner": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/mocha-runner/-/mocha-runner-6.4.2.tgz", - "integrity": "sha512-5BLwBVmEmDqOD4EYUAdCrA0zXZ8Xl0AwqbG9erbhmatEouWqiqhqtCbgoqLy0Y0m4BBJrBUq2bDTGdn6jTunrw==", - "dev": true, - "dependencies": { - "@stryker-mutator/api": "6.4.2", - "@stryker-mutator/util": "6.4.2", - "tslib": "~2.5.0" - }, - "engines": { - "node": ">=14.18.0" - }, - "peerDependencies": { - "@stryker-mutator/core": "^6.4.0", - "mocha": ">= 7.2 < 11" - } - }, - "node_modules/@stryker-mutator/typescript-checker": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/typescript-checker/-/typescript-checker-6.4.2.tgz", - "integrity": "sha512-fIbyex4Cx6tQPVJeTGJR6B1TU7kmAWbyx6BWNZjgmAehcpEghz8tWh5gdBDAIrkd6LJAKYJbpxHiE2lVxM3Jhg==", - "dev": true, - "dependencies": { - "@stryker-mutator/api": "6.4.2", - "@stryker-mutator/util": "6.4.2", - "semver": "~7.3.2" - }, - "engines": { - "node": ">=14.18.0" - }, - "peerDependencies": { - "@stryker-mutator/core": "^6.4.0", - "typescript": ">=3.6" - } - }, - "node_modules/@stryker-mutator/typescript-checker/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@stryker-mutator/typescript-checker/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@stryker-mutator/typescript-checker/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@stryker-mutator/util": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@stryker-mutator/util/-/util-6.4.2.tgz", - "integrity": "sha512-L6lf2JddgLS3D8cIN7FxxkRPmZ0PF48sdvn5TPnDhwZ7/1IXRXolzJFtXhQinRnDu6SyKGSJcwNOeJXyCcmuLQ==", - "dev": true, - "dependencies": { - "lodash.flatmap": "~4.5.0" - } - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", - "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz", - "integrity": "sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz", - "integrity": "sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", - "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", - "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", - "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", - "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", - "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-preset": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", - "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", - "dev": true, - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", - "@svgr/babel-plugin-remove-jsx-attribute": "*", - "@svgr/babel-plugin-remove-jsx-empty-expression": "*", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", - "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", - "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", - "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", - "@svgr/babel-plugin-transform-svg-component": "^6.5.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", - "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.19.6", - "@svgr/babel-preset": "^6.5.1", - "@svgr/plugin-jsx": "^6.5.1", - "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", - "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.0", - "entities": "^4.4.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/plugin-jsx": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", - "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.19.6", - "@svgr/babel-preset": "^6.5.1", - "@svgr/hast-util-to-babel-ast": "^6.5.1", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "^6.0.0" - } - }, - "node_modules/@svgr/plugin-svgo": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", - "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "svgo": "^2.8.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/webpack": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", - "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.19.6", - "@babel/plugin-transform-react-constant-elements": "^7.18.12", - "@babel/preset-env": "^7.19.4", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@svgr/core": "^6.5.1", - "@svgr/plugin-jsx": "^6.5.1", - "@svgr/plugin-svgo": "^6.5.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", - "dev": true - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.33", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", - "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/history": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", - "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", - "dev": true - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.10", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.10.tgz", - "integrity": "sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/mdast": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", - "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", - "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", - "dev": true - }, - "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.0.37", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.37.tgz", - "integrity": "sha512-4yaZZtkRN3ZIQD3KSEwkfcik8s0SWV+82dlJot1AbGYHCzJkWP3ENBY6wYeDRmKZ6HkrgoGAmR2HqdwYGp6OEw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", - "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", - "dev": true, - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" - } - }, - "node_modules/@types/react-router-config": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.7.tgz", - "integrity": "sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w==", - "dev": true, - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "^5.1.0" - } - }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", - "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", - "dev": true, - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "node_modules/@types/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", - "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", - "dev": true, - "dependencies": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", - "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", - "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/type-utils": "5.59.0", - "@typescript-eslint/utils": "5.59.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", - "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.0", - "@typescript-eslint/utils": "5.59.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", - "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vscode/codicons": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.32.tgz", - "integrity": "sha512-3lgSTWhAzzWN/EPURoY4ZDBEA80OPmnaknNujA3qnI4Iu7AONWd9xF3iE4L+4prIe8E3TUnLQ4pxoaFTEEZNwg==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/algoliasearch": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.0.tgz", - "integrity": "sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==", - "dev": true, - "dependencies": { - "@algolia/cache-browser-local-storage": "4.17.0", - "@algolia/cache-common": "4.17.0", - "@algolia/cache-in-memory": "4.17.0", - "@algolia/client-account": "4.17.0", - "@algolia/client-analytics": "4.17.0", - "@algolia/client-common": "4.17.0", - "@algolia/client-personalization": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/logger-console": "4.17.0", - "@algolia/requester-browser-xhr": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/requester-node-http": "4.17.0", - "@algolia/transporter": "4.17.0" - } - }, - "node_modules/algoliasearch-helper": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.12.0.tgz", - "integrity": "sha512-/j1U3PEwdan0n6P/QqSnSpNSLC5+cEMvyljd5CnmNmUjDlGrys+vFEOwjVEnqELIiAGMHEA/Nl3CiKVFBUYqyQ==", - "dev": true, - "dependencies": { - "@algolia/events": "^4.0.1" - }, - "peerDependencies": { - "algoliasearch": ">= 3.1 < 6" - } - }, - "node_modules/angular-html-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-4.0.1.tgz", - "integrity": "sha512-x9SLf2jNNh3nG+haVIwKX/GVW8PcvSRmkeT9WqTDYSAVuwT9IzwEyVm09FCZpOo/dtFRxE9vaNXqcAf/MIxphg==", - "dev": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.1.0.tgz", - "integrity": "sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg==", - "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.8.0.tgz", - "integrity": "sha512-FVNSzGQz9Th+/9R6Lvv7WIAkstylfHN2/JYxkyhhmKFYh9At2DST8t6L6Lref9eYO8PXFTfG9Sg1Agg0K3vq3Q==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", - "dev": true - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "dependencies": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", - "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.7" - } - }, - "node_modules/babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", - "dev": true, - "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 8.9" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" - } - }, - "node_modules/babel-plugin-apply-mdx-type-prop": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", - "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "7.10.4", - "@mdx-js/util": "1.6.22" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@babel/core": "^7.11.6" - } - }, - "node_modules/babel-plugin-apply-mdx-type-prop/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/babel-plugin-extract-import-names": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", - "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "7.10.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/babel-plugin-extract-import-names/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base16": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", - "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, - "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/boxen": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", - "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^6.2.0", - "chalk": "^4.1.2", - "cli-boxes": "^3.0.0", - "string-width": "^5.0.1", - "type-fest": "^2.5.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c8": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.13.0.tgz", - "integrity": "sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/c8/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/c8/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/c8/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/c8/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001480", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", - "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/ccount": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", - "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-css": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", - "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/clear-module": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", - "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==", - "dev": true, - "dependencies": { - "parent-module": "^2.0.0", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz", - "integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-width": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", - "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combine-promises": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz", - "integrity": "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/comment-json": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz", - "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==", - "dev": true, - "dependencies": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", - "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compressible/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/copy-text-to-clipboard": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.1.0.tgz", - "integrity": "sha512-PFM6BnjLnOON/lB3ta/Jg7Ywsv+l9kQGD4TWDCSlRBGmqnnTM5MrDkhAFgw+8HZt0wW6Q2BBE4cmy9sq+s9Qng==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.1", - "globby": "^13.1.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/copy-webpack-plugin/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/core-js": { - "version": "3.30.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.1.tgz", - "integrity": "sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.30.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.1.tgz", - "integrity": "sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-pure": { - "version": "3.30.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.30.1.tgz", - "integrity": "sha512-nXBEVpmUnNRhz83cHd9JRQC52cTMcuXAmR56+9dSMpRdpeA4I1PX6yjmhd71Eyc/wXNsdBdUDIj1QTIeZpU5Tg==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig-typescript-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz", - "integrity": "sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==", - "dev": true, - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=7", - "ts-node": ">=10", - "typescript": ">=3" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cspell": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-6.31.1.tgz", - "integrity": "sha512-gyCtpkOpwI/TGibbtIgMBFnAUUp2hnYdvW/9Ky4RcneHtLH0+V/jUEbZD8HbRKz0GVZ6mhKWbNRSEyP9p3Cejw==", - "dev": true, - "dependencies": { - "@cspell/cspell-pipe": "6.31.1", - "@cspell/dynamic-import": "6.31.1", - "chalk": "^4.1.2", - "commander": "^10.0.0", - "cspell-gitignore": "6.31.1", - "cspell-glob": "6.31.1", - "cspell-io": "6.31.1", - "cspell-lib": "6.31.1", - "fast-glob": "^3.2.12", - "fast-json-stable-stringify": "^2.1.0", - "file-entry-cache": "^6.0.1", - "get-stdin": "^8.0.0", - "imurmurhash": "^0.1.4", - "semver": "^7.3.8", - "strip-ansi": "^6.0.1", - "vscode-uri": "^3.0.7" - }, - "bin": { - "cspell": "bin.js", - "cspell-esm": "bin.mjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" - } - }, - "node_modules/cspell-dictionary": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-6.31.1.tgz", - "integrity": "sha512-7+K7aQGarqbpucky26wled7QSCJeg6VkLUWS+hLjyf0Cqc9Zew5xsLa4QjReExWUJx+a97jbiflITZNuWxgMrg==", - "dev": true, - "dependencies": { - "@cspell/cspell-pipe": "6.31.1", - "@cspell/cspell-types": "6.31.1", - "cspell-trie-lib": "6.31.1", - "fast-equals": "^4.0.3", - "gensequence": "^5.0.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell-gitignore": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-6.31.1.tgz", - "integrity": "sha512-PAcmjN6X89Z8qgjem6HYb+VmvVtKuc+fWs4sk21+jv2MiLk23Bkp+8slSaIDVR//58fxJkMx17PHyo2cDO/69A==", - "dev": true, - "dependencies": { - "cspell-glob": "6.31.1", - "find-up": "^5.0.0" - }, - "bin": { - "cspell-gitignore": "bin.mjs" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell-glob": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-6.31.1.tgz", - "integrity": "sha512-ygEmr5hgE4QtO5+L3/ihfMKBhPipbapfS22ilksFSChKMc15Regds0z+z/1ZBoe+OFAPneQfIuBxMwQ/fB00GQ==", - "dev": true, - "dependencies": { - "micromatch": "^4.0.5" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell-grammar": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-6.31.1.tgz", - "integrity": "sha512-AsRVP0idcNFVSb9+p9XjMumFj3BUV67WIPWApaAzJl/dYyiIygQObRE+si0/QtFWGNw873b7hNhWZiKjqIdoaQ==", - "dev": true, - "dependencies": { - "@cspell/cspell-pipe": "6.31.1", - "@cspell/cspell-types": "6.31.1" - }, - "bin": { - "cspell-grammar": "bin.mjs" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell-io": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-6.31.1.tgz", - "integrity": "sha512-deZcpvTYY/NmLfOdOtzcm+nDvJZozKmj4TY3pPpX0HquPX0A/w42bFRT/zZNmRslFl8vvrCZZUog7SOc6ha3uA==", - "dev": true, - "dependencies": { - "@cspell/cspell-service-bus": "6.31.1", - "node-fetch": "^2.6.9" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell-lib": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-6.31.1.tgz", - "integrity": "sha512-KgSiulbLExY+z2jGwkO77+aAkyugsPAw7y07j3hTQLpd+0esPCZqrmbo2ItnkvkDNd/c34PqQCr7/044/rz8gw==", - "dev": true, - "dependencies": { - "@cspell/cspell-bundled-dicts": "6.31.1", - "@cspell/cspell-pipe": "6.31.1", - "@cspell/cspell-types": "6.31.1", - "@cspell/strong-weak-map": "6.31.1", - "clear-module": "^4.1.2", - "comment-json": "^4.2.3", - "configstore": "^5.0.1", - "cosmiconfig": "8.0.0", - "cspell-dictionary": "6.31.1", - "cspell-glob": "6.31.1", - "cspell-grammar": "6.31.1", - "cspell-io": "6.31.1", - "cspell-trie-lib": "6.31.1", - "fast-equals": "^4.0.3", - "find-up": "^5.0.0", - "gensequence": "^5.0.2", - "import-fresh": "^3.3.0", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0", - "vscode-languageserver-textdocument": "^1.0.8", - "vscode-uri": "^3.0.7" - }, - "engines": { - "node": ">=14.6" - } - }, - "node_modules/cspell-lib/node_modules/cosmiconfig": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", - "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", - "dev": true, - "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell-trie-lib": { - "version": "6.31.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-6.31.1.tgz", - "integrity": "sha512-MtYh7s4Sbr1rKT31P2BK6KY+YfOy3dWsuusq9HnqCXmq6aZ1HyFgjH/9p9uvqGi/TboMqn1KOV8nifhXK3l3jg==", - "dev": true, - "dependencies": { - "@cspell/cspell-pipe": "6.31.1", - "@cspell/cspell-types": "6.31.1", - "gensequence": "^5.0.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cspell/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/css-declaration-sorter": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", - "integrity": "sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-loader": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", - "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.19", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", - "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", - "dev": true, - "dependencies": { - "cssnano": "^5.1.8", - "jest-worker": "^29.1.2", - "postcss": "^8.4.17", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "@swc/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "lightningcss": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-advanced": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz", - "integrity": "sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ==", - "dev": true, - "dependencies": { - "autoprefixer": "^10.4.12", - "cssnano-preset-default": "^5.2.14", - "postcss-discard-unused": "^5.1.0", - "postcss-merge-idents": "^5.1.1", - "postcss-reduce-idents": "^5.2.0", - "postcss-zindex": "^5.1.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true - }, - "node_modules/date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/default-gateway/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/default-gateway/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-gateway/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/del/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/del/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detab": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", - "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", - "dev": true, - "dependencies": { - "repeat-string": "^1.5.4" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" - } - }, - "node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port-alt/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port-alt/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "node_modules/dns-packet": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.5.0.tgz", - "integrity": "sha512-USawdAUzRkV6xrqTjiAEp6M9YagZEzWcSUaZTcIFAiyQWW1SoI6KyId8y2+/71wbgHKQAKd+iupLv4YvEwYWvA==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/docusaurus-plugin-typedoc-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/docusaurus-plugin-typedoc-api/-/docusaurus-plugin-typedoc-api-3.0.0.tgz", - "integrity": "sha512-2nYwWFvhSvV9AdJRyVwtVmRGe5PwfnXdSCyIoY8mC4bnEMWsdnFCf2CGO3YjZc+HC6myO7Arovtv+WlJQdsnTA==", - "dev": true, - "dependencies": { - "@docusaurus/plugin-content-docs": "^2.4.0", - "@docusaurus/types": "^2.4.0", - "@docusaurus/utils": "^2.4.0", - "@vscode/codicons": "^0.0.32", - "marked": "^4.3.0", - "typedoc": "^0.23.28" - }, - "engines": { - "node": ">=16.12.0" - }, - "funding": { - "type": "ko-fi", - "url": "https://ko-fi.com/milesjohnson" - }, - "peerDependencies": { - "@docusaurus/core": "^2.0.0", - "react": ">=16.0.0", - "typescript": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/docusaurus-plugin-typedoc-api/node_modules/typedoc": { - "version": "0.23.28", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.28.tgz", - "integrity": "sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==", - "dev": true, - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.2.12", - "minimatch": "^7.1.3", - "shiki": "^0.14.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "dev": true - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.366", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.366.tgz", - "integrity": "sha512-XjC4pyf1no8kJe24nUfyexpWwiGRbZWXU/KbprSEvXcTXUlr3Zr5vK3lQt2to0ttpMhAc3iENccwPSKbnEW2Fg==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", - "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/emoticon": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", - "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-n": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", - "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", - "dev": true, - "dependencies": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.11.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-simple-import-sort": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", - "integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==", - "dev": true, - "peerDependencies": { - "eslint": ">=5.0.0" - } - }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", - "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "0.16.2" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eta": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eta/-/eta-2.0.1.tgz", - "integrity": "sha512-46E2qDPDm7QA+usjffUWz9KfXsxVZclPOuKsXs4ZWZdI/X1wpDF7AO424pt7fdYohCzWsIkXAhNGXSlwo5naAg==", - "dev": true, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "url": "https://github.com/eta-dev/eta?sponsor=1" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eval": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", - "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "require-like": ">= 0.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/express/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/express/node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/express/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-equals": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", - "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dev": true, - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fbemitter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", - "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", - "dev": true, - "dependencies": { - "fbjs": "^3.0.0" - } - }, - "node_modules/fbjs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.4.tgz", - "integrity": "sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ==", - "dev": true, - "dependencies": { - "cross-fetch": "^3.1.5", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.30" - } - }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", - "dev": true - }, - "node_modules/feed": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", - "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", - "dev": true, - "dependencies": { - "xml-js": "^1.6.11" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/file-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/file-loader/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/file-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/file-loader/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/file-url": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-4.0.0.tgz", - "integrity": "sha512-vRCdScQ6j3Ku6Kd7W1kZk9c++5SqD6Xz5Jotrjr/nkY714M14RFHy/AAVA2WQvpsqVAVgTbDrYyBpU205F0cLw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/flux": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.4.tgz", - "integrity": "sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==", - "dev": true, - "dependencies": { - "fbemitter": "^3.0.0", - "fbjs": "^3.0.1" - }, - "peerDependencies": { - "react": "^15.0.2 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensequence": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-5.0.2.tgz", - "integrity": "sha512-JlKEZnFc6neaeSVlkzBGGgkIoIaSxMgvdamRoPN8r3ozm2r9dusqxeKqYQ7lhzmj2UhFQP8nkyfCaiLQxiLrDA==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, - "node_modules/get-port": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", - "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/github-slugger": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", - "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", - "dev": true - }, - "node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "dependencies": { - "ini": "^1.3.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/gray-matter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hast-to-hyperscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", - "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.3", - "comma-separated-tokens": "^1.0.0", - "property-information": "^5.3.0", - "space-separated-tokens": "^1.0.0", - "style-to-object": "^0.3.0", - "unist-util-is": "^4.0.0", - "web-namespaces": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", - "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", - "dev": true, - "dependencies": { - "@types/parse5": "^5.0.0", - "hastscript": "^6.0.0", - "property-information": "^5.0.0", - "vfile": "^4.0.0", - "vfile-location": "^3.2.0", - "web-namespaces": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", - "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", - "dev": true, - "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-from-parse5": "^6.0.0", - "hast-util-to-parse5": "^6.0.0", - "html-void-elements": "^1.0.0", - "parse5": "^6.0.0", - "unist-util-position": "^3.0.0", - "vfile": "^4.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/hast-util-to-parse5": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", - "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", - "dev": true, - "dependencies": { - "hast-to-hyperscript": "^9.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "dev": true, - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dev": true, - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", - "dev": true - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/html-void-elements": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", - "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.1.tgz", - "integrity": "sha512-cTUzZ1+NqjGEKjmVgZKLMdiFg3m9MdRXkZW2OEe69WYVi5ONLMmlnSZdXzGGMOq0C8jGDrL6EWyEDDUioHO/pA==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "webpack": "^5.20.0" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/image-size": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz", - "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==", - "dev": true, - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-meta-resolve": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", - "integrity": "sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infima": { - "version": "0.2.0-alpha.43", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", - "integrity": "sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", - "dev": true - }, - "node_modules/inquirer": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.5.tgz", - "integrity": "sha512-3ygAIh8gcZavV9bj6MTdYddG2zPSYswP808fKS46NOwlF0zZljVpnLCHODDqItWJDbDpLb3aouAxGaJbkxoppA==", - "dev": true, - "dependencies": { - "ansi-escapes": "^6.0.0", - "chalk": "^5.2.0", - "cli-cursor": "^4.0.0", - "cli-width": "^4.0.0", - "external-editor": "^3.0.3", - "figures": "^5.0.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^6.1.2", - "run-async": "^2.4.0", - "rxjs": "^7.8.0", - "string-width": "^5.1.2", - "strip-ansi": "^7.0.1", - "through": "^2.3.6", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dev": true, - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-ci/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-installed-globally/node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-installed-globally/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "dev": true - }, - "node_modules/joi": { - "version": "17.9.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.1.tgz", - "integrity": "sha512-FariIi9j6QODKATGBrEX7HZcja8Bsh3rfdGYy/Sb65sGlZWK/QWesU1ghk7aJWDj95knjXlQfSmzFSPPkLVsfw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.curry": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", - "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.flatmap": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz", - "integrity": "sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg==", - "dev": true - }, - "node_modules/lodash.flow": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", - "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==", - "dev": true - }, - "node_modules/lodash.groupby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", - "dev": true, - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/markdown-escapes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/mdast-squeeze-paragraphs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", - "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", - "dev": true, - "dependencies": { - "unist-util-remove": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", - "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.0.tgz", - "integrity": "sha512-yK6o8xVJlQerz57kvPROwTMgx5WtGwC2ZxDtOUsnGl49rHjYkfQoPNZPCKH73VdLE1BwBu/+Fx/NL8NYMUw2aA==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.3" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, - "dependencies": { - "mime-db": "~1.33.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz", - "integrity": "sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", - "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/mutation-testing-elements": { - "version": "1.7.14", - "resolved": "https://registry.npmjs.org/mutation-testing-elements/-/mutation-testing-elements-1.7.14.tgz", - "integrity": "sha512-/klVQtO0W9Y3zRUf3Xaf4hvzjCpLMKWetg6/bnLDPBrGTySt7JeW+muh2JQcBessDJMFFZyFYKdCTJOL5AhlBw==", - "dev": true - }, - "node_modules/mutation-testing-metrics": { - "version": "1.7.14", - "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.7.14.tgz", - "integrity": "sha512-Y5I6p2gZy7sXYfWn9yR863vd3NA9IhjKccUdbybmHASRy5b7zit6B03DczuYU+cQDqZ7WX38gzQ9IFs/JdbHqQ==", - "dev": true, - "dependencies": { - "mutation-testing-report-schema": "1.7.14" - } - }, - "node_modules/mutation-testing-report-schema": { - "version": "1.7.14", - "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.7.14.tgz", - "integrity": "sha512-vN2Gw5dXWp1I7fj9PSzyBPy7KqNG4wN5qMdHwTV339fbW2pH19qlSU5Qg6VJlAZtlfgUiDJ1NYYgIEjpoqrRZA==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", - "dev": true - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz", - "integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==", - "dev": true, - "dependencies": { - "chalk": "^5.0.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.6.1", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.1.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "strip-ansi": "^7.0.1", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", - "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", - "dev": true, - "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", - "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", - "dev": true, - "dependencies": { - "callsites": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "dev": true, - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-numeric-range": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", - "dev": true - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dev": true, - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", - "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", - "dev": true, - "dependencies": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.0.3.tgz", - "integrity": "sha512-cyjNRew29d4kbgnz1sjDqxg7qg8NW4s+HQzCGjeon7DV5T2yDije16W9HaUFV1dhVEMh+SjrOcK0TomBmf3Egg==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" + "node": ">=12" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { - "find-up": "^3.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8" + "node": ">=7.0.0" } }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/comment-json": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", + "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/postcss": { - "version": "8.4.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.22.tgz", - "integrity": "sha512-XseknLAfRHzVWjCEtdviapiBtfLdgyzExD50Rg2ePaucEesyh8Wv4VPdW0nbyDa1ydbrAxV19jvMT4+LFmcNUA==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } + "license": "MIT" }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" }, - "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 8" } }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "node_modules/cspell": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.16.1.tgz", + "integrity": "sha512-ILuCjnY3JPY2oO62PodTQD6n3DGTKTwB+IU1tE9EC6EP2Xw6z3Ir+hO2DO6QlRUmZlGrkGMek5U06nNmztt4eA==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" + "@cspell/cspell-json-reporter": "8.16.1", + "@cspell/cspell-pipe": "8.16.1", + "@cspell/cspell-types": "8.16.1", + "@cspell/dynamic-import": "8.16.1", + "@cspell/url": "8.16.1", + "chalk": "^5.3.0", + "chalk-template": "^1.1.0", + "commander": "^12.1.0", + "cspell-dictionary": "8.16.1", + "cspell-gitignore": "8.16.1", + "cspell-glob": "8.16.1", + "cspell-io": "8.16.1", + "cspell-lib": "8.16.1", + "fast-json-stable-stringify": "^2.1.0", + "file-entry-cache": "^9.1.0", + "get-stdin": "^9.0.0", + "semver": "^7.6.3", + "tinyglobby": "^0.2.10" }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "bin": { + "cspell": "bin.mjs", + "cspell-esm": "bin.mjs" }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=18" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" } }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "node_modules/cspell-config-lib": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.16.1.tgz", + "integrity": "sha512-ohbSi9sI14rMdFc2g17ogObGGkd/x6zUVOzCH1nEOefC9yJYYfsvaMHqdhk0rOjvmF95j5OK4dm5oid+DKQcpw==", "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "8.16.1", + "comment-json": "^4.2.5", + "yaml": "^2.6.1" }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=18" } }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "node_modules/cspell-config-lib/node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" + "license": "ISC", + "bin": { + "yaml": "bin.mjs" }, - "peerDependencies": { - "postcss": "^8.2.15" + "engines": { + "node": ">= 14" } }, - "node_modules/postcss-discard-unused": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", - "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", + "node_modules/cspell-dictionary": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.16.1.tgz", + "integrity": "sha512-NL/vwf5SjtkWWaEUh+0dogKdEU4UuepJaNh36FX8W1CFtQXj7yEs45x4K7/Fp+pn/4AT7Qe7WpSSWi9z5GcqKg==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "@cspell/cspell-pipe": "8.16.1", + "@cspell/cspell-types": "8.16.1", + "cspell-trie-lib": "8.16.1", + "fast-equals": "^5.0.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=18" } }, - "node_modules/postcss-loader": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.2.4.tgz", - "integrity": "sha512-F88rpxxNspo5hatIc+orYwZDtHFaVFOSIVAx+fBfJC1GmhWbVmPWtmg2gXKE1OxJbneOSGn8PWdIwsZFcruS+w==", + "node_modules/cspell-gitignore": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.16.1.tgz", + "integrity": "sha512-Gg8qvFc8wr1D7TvB+GSfT1jyrUoUmPiG3WdOnQnxOSYKJesOiVvNxLv7YXRFkcUKG1VU6XDUkpb/uzKh3k2rKw==", "dev": true, + "license": "MIT", "dependencies": { - "cosmiconfig": "^8.1.3", - "cosmiconfig-typescript-loader": "^4.3.0", - "klona": "^2.0.6", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 14.15.0" + "@cspell/url": "8.16.1", + "cspell-glob": "8.16.1", + "cspell-io": "8.16.1", + "find-up-simple": "^1.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "ts-node": ">=10", - "typescript": ">=4", - "webpack": "^5.0.0" + "bin": { + "cspell-gitignore": "bin.mjs" }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - }, - "typescript": { - "optional": true - } + "engines": { + "node": ">=18" } }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "node_modules/cspell-glob": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.16.1.tgz", + "integrity": "sha512-EukaXFaUrgrY9G4bB2PguzpkAoOq6ai9acLl6gWD+6DgVEwkLqPmCWjsFJA0MaqVp9QvPsIfCy4KCnx35csG/g==", "dev": true, + "license": "MIT", "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" + "@cspell/url": "8.16.1", + "micromatch": "^4.0.8" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": ">=18" } }, - "node_modules/postcss-merge-idents": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", - "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", + "node_modules/cspell-grammar": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.16.1.tgz", + "integrity": "sha512-7IRYa0O1xfK2HVbhGSpOPPt5HlP2ZHRHtdLU2iOvMSCkh0cSPERu++kdprvcaOf7E7koo0P+bxHSprcYbU/agg==", "dev": true, + "license": "MIT", "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" + "@cspell/cspell-pipe": "8.16.1", + "@cspell/cspell-types": "8.16.1" }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "bin": { + "cspell-grammar": "bin.mjs" }, - "peerDependencies": { - "postcss": "^8.2.15" + "engines": { + "node": ">=18" } }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "node_modules/cspell-io": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.16.1.tgz", + "integrity": "sha512-25MOQfy7EhdVeoNUW/+jyb5ArDYSLbaFwVToakHtLGuYk9cW8q8MAHq1W9GzW06wXswT2sQsRvaozmIOTDIOnw==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" + "@cspell/cspell-service-bus": "8.16.1", + "@cspell/url": "8.16.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=18" } }, - "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "node_modules/cspell-lib": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.16.1.tgz", + "integrity": "sha512-Gn1vJcyhYe78iB+9dms8rnfgDEfJgYocXapFPTOcZV3EUWKcV4wyCiHdbK3j2ElLXmPuSPg4eZSlxxk8ITD0Aw==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" + "@cspell/cspell-bundled-dicts": "8.16.1", + "@cspell/cspell-pipe": "8.16.1", + "@cspell/cspell-resolver": "8.16.1", + "@cspell/cspell-types": "8.16.1", + "@cspell/dynamic-import": "8.16.1", + "@cspell/filetypes": "8.16.1", + "@cspell/strong-weak-map": "8.16.1", + "@cspell/url": "8.16.1", + "clear-module": "^4.1.2", + "comment-json": "^4.2.5", + "cspell-config-lib": "8.16.1", + "cspell-dictionary": "8.16.1", + "cspell-glob": "8.16.1", + "cspell-grammar": "8.16.1", + "cspell-io": "8.16.1", + "cspell-trie-lib": "8.16.1", + "env-paths": "^3.0.0", + "fast-equals": "^5.0.1", + "gensequence": "^7.0.0", + "import-fresh": "^3.3.0", + "resolve-from": "^5.0.0", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-uri": "^3.0.8", + "xdg-basedir": "^5.1.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=18" } }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "node_modules/cspell-trie-lib": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.16.1.tgz", + "integrity": "sha512-T86nszsjQjyZ35dOWk7qN17Hem0cVeXJ4D1v/gIG+Y0Umo7dBW7AwmTvUy8iMFAra29cSdgRH+yk6q1qdpA+ZA==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@cspell/cspell-pipe": "8.16.1", + "@cspell/cspell-types": "8.16.1", + "gensequence": "^7.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=18" } }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "node_modules/cspell/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "node_modules/cspell/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=18" } }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, + "license": "MIT", "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.4" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "dependencies": { - "icss-utils": "^5.0.0" + "ms": "2.1.2" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=6.0" }, - "peerDependencies": { - "postcss": "^8.1.0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=6" } }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } + "license": "MIT" }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.3.1" } }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } + "license": "MIT" }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } + "license": "MIT" }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=10.13.0" } }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", "dev": true, - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-reduce-idents": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", - "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=18" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "node_modules/es-abstract": { + "version": "1.23.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", + "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "get-intrinsic": "^1.2.4" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.4" } }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/postcss-sort-media-queries": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz", - "integrity": "sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg==", + "node_modules/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", "dev": true, + "license": "MIT", "dependencies": { - "sort-css-media-queries": "2.1.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.4.16" + "node": ">= 0.4" } }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" + "es-errors": "^1.3.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.4" } }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.0.5" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.4" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/postcss-zindex": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", - "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" } }, - "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prettier": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", - "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", + "node_modules/eslint": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.5", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, "bin": { - "prettier": "bin-prettier.js" + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=10.13.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", "dev": true, + "license": "MIT", "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", - "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", - "dev": true, + "semver": "^7.5.4" + }, "engines": { - "node": ">=4" - } - }, - "node_modules/prism-react-renderer": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", - "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==", - "dev": true, + "node": ">=12" + }, "peerDependencies": { - "react": ">=0.14.9" - } - }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "dev": true, - "engines": { - "node": ">=6" + "eslint": ">=6.0.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "engines": { - "node": ">=0.4.0" + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { - "asap": "~2.0.3" + "ms": "^2.1.1" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, + "license": "MIT", "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "debug": "^3.2.7" }, "engines": { - "node": ">= 6" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "ms": "^2.1.1" } }, - "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "license": "MIT", "dependencies": { - "xtend": "^4.0.0" + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, + "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">= 0.10" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "engines": { - "node": ">= 0.10" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "ms": "^2.1.1" } }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "escape-goat": "^2.0.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/pure-color": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", - "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==", - "dev": true - }, - "node_modules/qs": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", - "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "side-channel": "^1.0.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dev": true, - "dependencies": { - "inherits": "~2.0.3" + "node": "*" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/eslint-plugin-n": { + "version": "17.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.14.0.tgz", + "integrity": "sha512-maxPLMEA0rPmRpoOlxEclKng4UpDe+N5BJS4t24I3UKnN109Qcivnfs37KMy84G0af3bxjog5lKctP5ObsvcTA==", "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.1.0" + "@eslint-community/eslint-utils": "^4.4.1", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "ignore": "^5.3.2", + "minimatch": "^9.0.5", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": ">=8.23.0" } }, - "node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", + "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, + "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", + "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/react-base16-styling": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz", - "integrity": "sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, + "license": "MIT", "dependencies": { - "base16": "^1.0.0", - "lodash.curry": "^4.0.1", - "lodash.flow": "^3.3.0", - "pure-color": "^1.2.0" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", + "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" } }, - "node_modules/react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">= 12.13.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - }, - "peerDependencies": { - "react": "17.0.2" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/react-error-overlay": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", - "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", - "dev": true - }, - "node_modules/react-fast-compare": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.1.tgz", - "integrity": "sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg==", - "dev": true - }, - "node_modules/react-helmet-async": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", - "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "invariant": "^2.2.4", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.2.0", - "shallowequal": "^1.1.0" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/react-json-view": { - "version": "1.21.3", - "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz", - "integrity": "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==", + "node_modules/eslint/node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flux": "^4.0.1", - "react-base16-styling": "^0.6.0", - "react-lifecycles-compat": "^3.0.4", - "react-textarea-autosize": "^8.3.2" + "flat-cache": "^4.0.0" }, - "peerDependencies": { - "react": "^17.0.0 || ^16.3.0 || ^15.5.4", - "react-dom": "^17.0.0 || ^16.3.0 || ^15.5.4" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", - "dev": true - }, - "node_modules/react-loadable": { - "name": "@docusaurus/react-loadable", - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", - "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "node_modules/eslint/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/react": "*", - "prop-types": "^15.6.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "peerDependencies": { - "react": "*" + "engines": { + "node": ">=16" } }, - "node_modules/react-loadable-ssr-addon-v5-slorber": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/runtime": "^7.10.3" + "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" - }, - "peerDependencies": { - "react-loadable": "*", - "webpack": ">=4.41.1 || 5.x" } }, - "node_modules/react-router": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", - "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "brace-expansion": "^1.1.7" }, - "peerDependencies": { - "react": ">=15" + "engines": { + "node": "*" } }, - "node_modules/react-router-config": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", - "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@babel/runtime": "^7.1.2" + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" }, - "peerDependencies": { - "react": ">=15", - "react-router": ">=5" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/react-router-dom": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", - "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.3.4", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "react": ">=15" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/react-textarea-autosize": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.4.1.tgz", - "integrity": "sha512-aD2C+qK6QypknC+lCMzteOdIjoMbNlgSFmJjCV+DrfTPwp59i/it9mMNf2HDzvRjQgKAyBDPyLJhcrzElf2U4Q==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.20.13", - "use-composed-ref": "^1.3.0", - "use-latest": "^1.2.1" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "node": ">=4" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "estraverse": "^5.1.0" }, "engines": { - "node": ">= 6" + "node": ">=0.10" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "picomatch": "^2.2.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=4.0" } }, - "node_modules/reading-time": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", - "dev": true + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=6.0.0" } }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { - "minimatch": "^3.0.5" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=8.6.0" } }, - "node_modules/recursive-readdir/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/recursive-readdir/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "reusify": "^1.0.4" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "node_modules/file-entry-cache": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", "dev": true, + "license": "MIT", "dependencies": { - "regenerate": "^1.4.2" + "flat-cache": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.4" + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" } }, - "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "node_modules/flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", "dev": true, + "license": "MIT", "dependencies": { - "rc": "1.2.8" + "flatted": "^3.3.1", + "keyv": "^4.5.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" + "is-callable": "^1.1.3" } }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, + "license": "ISC", "dependencies": { - "jsesc": "~0.5.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/remark-emoji": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz", - "integrity": "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "dependencies": { - "emoticon": "^3.2.0", - "node-emoji": "^1.10.0", - "unist-util-visit": "^2.0.3" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/remark-footnotes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", - "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", + "node_modules/gensequence": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-7.0.0.tgz", + "integrity": "sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/remark-mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", - "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "dependencies": { - "@babel/core": "7.12.9", - "@babel/helper-plugin-utils": "7.10.4", - "@babel/plugin-proposal-object-rest-spread": "7.12.1", - "@babel/plugin-syntax-jsx": "7.12.1", - "@mdx-js/util": "1.6.22", - "is-alphabetical": "1.0.4", - "remark-parse": "8.0.3", - "unified": "9.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/remark-mdx/node_modules/@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" + "engines": { + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "node_modules/remark-mdx/node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", - "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.12.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "engines": { + "node": "*" } }, - "node_modules/remark-mdx/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/remark-mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/remark-mdx/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/remark-mdx/node_modules/unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "license": "MIT", "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/remark-parse": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", - "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", "dev": true, + "license": "MIT", "dependencies": { - "ccount": "^1.0.0", - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^2.0.0", - "vfile-location": "^3.0.0", - "xtend": "^4.0.1" + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/remark-squeeze-paragraphs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", - "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { - "mdast-squeeze-paragraphs": "^4.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/renderkid/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", "dev": true, + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/renderkid/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/renderkid/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.2.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { - "node": ">= 4" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/renderkid/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "get-intrinsic": "^1.1.3" }, "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/renderkid/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } + "license": "ISC" }, - "node_modules/renderkid/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">=8" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "engines": { - "node": ">=0.10.0" + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-like": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { - "global-dirs": "^0.1.1" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", - "dev": true - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" + "license": "MIT", + "bin": { + "he": "bin/he" } }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "license": "MIT" + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" @@ -15282,2218 +3838,2169 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/import-fresh/node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/rimraf": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", - "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "^9.2.0" - }, - "bin": { - "rimraf": "dist/cjs/src/bin.js" + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.4" } }, - "node_modules/rtl-detect": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz", - "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==", - "dev": true - }, - "node_modules/rtlcss": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", - "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, + "license": "MIT", "dependencies": { - "find-up": "^5.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.3.11", - "strip-json-comments": "^3.1.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" }, - "bin": { - "rtlcss": "bin/rtlcss.js" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "license": "MIT", "dependencies": { - "queue-microtask": "^1.2.2" + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.1.0" + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">= 8.9.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "node_modules/is-finalizationregistry": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", + "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", "dev": true, + "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" + "call-bind": "^1.0.7" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "node-forge": "^1" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { - "semver": "^6.3.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/send/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "license": "MIT", "dependencies": { - "randombytes": "^2.1.0" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-handler/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-handler/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "which-typed-array": "^1.1.14" }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", - "dev": true - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, - "dependencies": { - "ms": "2.0.0" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, - "engines": { - "node": ">= 0.6" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, + "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" }, - "node_modules/serve-index/node_modules/ms": { + "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "kind-of": "^6.0.2" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dev": true, + "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "engines": { - "node": ">=8" + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "argparse": "^2.0.1" }, "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/shelljs/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/shelljs/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/shelljs/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, "engines": { - "node": "*" + "node": ">=4.0" } }, - "node_modules/shiki": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.1.tgz", - "integrity": "sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" + "json-buffer": "3.0.1" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">= 10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/sitemap": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz", - "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==", + "node_modules/lint-staged": { + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", "dev": true, "dependencies": { - "@types/node": "^17.0.5", - "@types/sax": "^1.2.1", - "arg": "^5.0.0", - "sax": "^1.2.4" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" }, "bin": { - "sitemap": "dist/cli.js" + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=12.0.0", - "npm": ">=5.6.0" + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/sitemap/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/lint-staged/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "engines": { + "node": ">=18" } }, - "node_modules/sort-css-media-queries": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz", - "integrity": "sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA==", + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, "engines": { - "node": ">= 6.3.0" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">= 8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=16.17.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true - }, - "node_modules/state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "engines": { + "node": ">=12" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/std-env": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.2.tgz", - "integrity": "sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==", + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, - "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { - "bl": "^5.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/streamroller": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", - "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "engines": { - "node": ">= 4.0.0" - } + "license": "MIT" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "get-east-asian-width": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, + "license": "MIT", "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "engines": { - "node": ">=4" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/stringify-object/node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "node_modules/loupe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", "dev": true, - "engines": { - "node": ">=0.10.0" + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 8" } }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/style-to-object": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", - "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "dependencies": { - "inline-style-parser": "0.1.1" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, + "license": "ISC", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/mocha": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", + "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" } }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">= 10" + "node": ">=8" } }, - "node_modules/svgo/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": ">=8" } }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/svgo/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.2.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 4" + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/svgo/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/svgo/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "license": "ISC", + "engines": { + "node": ">=10" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/terser": { - "version": "5.16.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", - "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, + "license": "MIT", "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" } }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": "*" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "p-limit": "^3.0.2" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==", - "dev": true - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", - "dev": true + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true, + "license": "BlueOak-1.0.0" }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/parent-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", + "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", "dev": true, + "license": "MIT", "dependencies": { - "os-tmpdir": "~1.0.2" + "callsites": "^3.1.0" }, "engines": { - "node": ">=0.6.0" + "node": ">=8" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "is-number": "^7.0.0" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">= 14.16" } }, - "node_modules/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, "bin": { - "tree-kill": "cli.js" + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "deprecated": "Use String.prototype.trim() instead", - "dev": true - }, - "node_modules/trim-trailing-lines": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", - "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "license": "MIT", + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, + "license": "MIT", "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "prettier": "bin/prettier.cjs" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "safe-buffer": "^5.1.0" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } + "license": "MIT" }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "picomatch": "^2.2.1" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=8.10.0" } }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", + "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "which-builtin-type": "^1.1.4" + }, "engines": { - "node": ">=12.20" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, + "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10" } }, - "node_modules/type-is/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-inject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/typed-inject/-/typed-inject-3.0.1.tgz", - "integrity": "sha512-5yr8inrNos7uo/irp5PZ7WNwmYGfoa0w1NiDdCWW6hhIxYH2NCqYwX9BUOXpZgxk964rb1ElEfvBtftuvIPpvw==", + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.9.tgz", - "integrity": "sha512-uSmjE38B80wjL85UFX3sTYEUlvZ1JgCRhsWj/fJ4rZ0FqDUFoIuodtiVeE+cUqiVTOKPdKrp/sdftD15MDek6g==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" + "node": ">=8" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/typedoc": { - "version": "0.24.4", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.4.tgz", - "integrity": "sha512-vQuliyGhJEGeKzzCFHbkS3m0gHoIL6cfr0fHf6eX658iGELtq2J9mWe0b+X5McEYgFoMuHFt5Py3Zug6Sxjn/Q==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.0", - "shiki": "^0.14.1" - }, - "bin": { - "typedoc": "bin/typedoc" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">= 14.14" + "node": ">=18" }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=12.20" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/ua-parser-js": { - "version": "0.7.35", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", - "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "paypal", - "url": "https://paypal.me/faisalman" + "type": "consulting", + "url": "https://feross.org/support" } ], - "engines": { - "node": "*" + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, - "engines": { - "node": ">=4" + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/unified": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", - "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.4" } }, - "node_modules/unique-string": { + "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { - "crypto-random-string": "^2.0.0" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/unist-builder": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", - "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-generated": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", - "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", - "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/unist-util-remove": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", - "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, + "license": "MIT", "dependencies": { - "unist-util-is": "^4.0.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove-position": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", - "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", - "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "@types/unist": "^2.0.2" + "license": "ISC", + "engines": { + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" + "node": ">=12" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-notifier/node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.6.19" } }, - "node_modules/update-notifier/node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-notifier/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/update-notifier/node_modules/string-width": { + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -17503,889 +6010,601 @@ "node": ">=8" } }, - "node_modules/update-notifier/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/update-notifier/node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^4.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/update-notifier/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, - "node_modules/url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, + "license": "MIT", "dependencies": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "file-loader": "*", - "webpack": "^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "file-loader": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/url-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/url-loader/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/url-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/url-loader/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/url-loader/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/url-loader/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { - "prepend-http": "^2.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/use-composed-ref": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", - "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", - "dev": true, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/use-isomorphic-layout-effect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", - "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", - "dev": true, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/use-latest": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", - "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "use-isomorphic-layout-effect": "^1.1.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "ansi-regex": "^5.0.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "dev": true, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", - "dev": true, "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=8" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, + "license": "MIT", "engines": { - "node": ">=10.12.0" + "node": ">=4" } }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", - "dev": true - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vfile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", - "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-message": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", - "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", - "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==", - "dev": true - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==", - "dev": true - }, - "node_modules/wait-on": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", - "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", - "dev": true, - "dependencies": { - "axios": "^0.25.0", - "joi": "^17.6.0", - "lodash": "^4.17.21", - "minimist": "^1.2.5", - "rxjs": "^7.5.4" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=10.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" + "node": ">=8" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "dependencies": { - "defaults": "^1.0.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/weapon-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/weapon-regex/-/weapon-regex-1.0.3.tgz", - "integrity": "sha512-V8X6hPIzY1juvrSVREmtRhK9AHn/8c2z8XxaibESU+jyG/RinZ9x9x6aw8qEuFAi7R6Kl/EWGbU2Yq/9u6TTjw==", - "dev": true - }, - "node_modules/web-namespaces": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", - "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/webpack": { - "version": "5.79.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", - "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, + "license": "ISC", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "node": ">=18" } }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.8.0.tgz", - "integrity": "sha512-ZzoSBePshOKhr+hd8u6oCkZVwpVaXgpw23ScGLFpR6SjYI7+7iIWYarjN6OEYOfRt8o7ZyZZQk0DuMizJ+LEIg==", + "node_modules/tinyglobby": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", "dev": true, + "license": "MIT", "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" + "fdir": "^6.4.2", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 10.13.0" + "node": ">=12.0.0" } }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", "dev": true, - "engines": { - "node": ">= 10" + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">= 12.13.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-middleware/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" + "node": ">=8.0" } }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, + "license": "MIT", "engines": { - "node": ">= 12.13.0" + "node": ">=16" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/webpack-dev-server": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.13.3.tgz", - "integrity": "sha512-KqqzrzMRSRy5ePz10VhjyL27K2dxqwXQLP5rAKwRJBPUahe7Z2bBWzHw37jeb8GCPKxZRO79ZdQUAPesMh/Nug==", + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" }, "peerDependenciesMeta": { - "webpack": { + "@swc/core": { "optional": true }, - "webpack-cli": { + "@swc/wasm": { "optional": true } } }, - "node_modules/webpack-dev-server/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/webpack-dev-server/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.3.1" } }, - "node_modules/webpack-dev-server/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "minimist": "^1.2.0" }, "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "json5": "lib/cli.js" } }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 0.8.0" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">= 0.4" } }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/webpack/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">= 0.6" + "node": ">=14.17" } }, - "node_modules/webpack/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/typescript-eslint": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.17.0.tgz", + "integrity": "sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==", "dev": true, + "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "@typescript-eslint/eslint-plugin": "8.17.0", + "@typescript-eslint/parser": "8.17.0", + "@typescript-eslint/utils": "8.17.0" }, "engines": { - "node": ">= 0.6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpackbar": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", - "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.3", - "pretty-time": "^1.1.0", - "std-env": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "webpack": "3 || 4 || 5" + "punycode": "^2.1.0" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, + "license": "ISC", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=10.12.0" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", "dev": true, - "engines": { - "node": ">=0.8.0" - } + "license": "MIT" }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -18401,6 +6620,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -18412,18 +6632,26 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/which-builtin-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", + "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -18432,47 +6660,68 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^5.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -18485,112 +6734,94 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "ansi-regex": "^5.0.1" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/xml-js": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", - "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "sax": "^1.2.4" + "license": "MIT", + "engines": { + "node": ">=12" }, - "bin": { - "xml-js": "bin/cli.js" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/y18n": { @@ -18598,50 +6829,51 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -18649,6 +6881,7 @@ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -18659,17 +6892,39 @@ "node": ">=10" } }, + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/yargs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -18679,11 +6934,25 @@ "node": ">=8" } }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -18693,22 +6962,13 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zwitch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", - "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } } } } diff --git a/package.json b/package.json index 1c7208f48b..05c41eeb0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "graphql", - "version": "17.0.0-alpha.3", + "version": "17.0.0-alpha.7", "description": "A Query Language and Runtime which can target any service.", "license": "MIT", "private": true, @@ -29,67 +29,49 @@ "node": "^16.19.0 || ^18.14.0 || >=19.7.0" }, "scripts": { - "preversion": ". ./resources/checkgit.sh && npm ci --ignore-scripts", + "preversion": "bash -c '. ./resources/checkgit.sh && npm ci --ignore-scripts'", "version": "node --loader ts-node/esm resources/gen-version.ts && npm test && git add src/version.ts", "fuzzonly": "mocha --full-trace src/**/__tests__/**/*-fuzz.ts", "changelog": "node --loader ts-node/esm resources/gen-changelog.ts", "benchmark": "node --loader ts-node/esm resources/benchmark.ts", "test": "npm run lint && npm run check && npm run testonly:cover && npm run prettier:check && npm run check:spelling && npm run check:integrations", - "lint": "eslint --cache --max-warnings 0 --rulesdir resources/eslint-internal-rules/ .", + "lint": "eslint --cache --max-warnings 0 .", "check": "tsc --pretty", "testonly": "mocha --full-trace src/**/__tests__/**/*-test.ts", "testonly:cover": "c8 npm run testonly", "testonly:watch": "npm run testonly -- --watch", - "testonly:mutate": "stryker run", "prettier": "prettier --cache --cache-strategy metadata --write --list-different .", "prettier:check": "prettier --cache --cache-strategy metadata --check .", + "precommit": "lint-staged", "check:spelling": "cspell --cache --no-progress \"**/*\"", "check:integrations": "mocha --full-trace resources/integration-test.ts", - "serve": "docusaurus serve --dir websiteDist/ --config website/docusaurus.config.cjs", - "start": "npm run build:website && npm run serve", - "build:website": "node --loader ts-node/esm resources/build-docusaurus.ts", "build:npm": "node --loader ts-node/esm resources/build-npm.ts", "build:deno": "node --loader ts-node/esm resources/build-deno.ts", "diff:npm": "node --loader ts-node/esm resources/diff-npm-package.ts", "gitpublish:npm": "bash ./resources/gitpublish.sh npm npmDist", - "gitpublish:deno": "bash ./resources/gitpublish.sh deno denoDist" + "gitpublish:deno": "bash ./resources/gitpublish.sh deno denoDist", + "prepare": "husky" }, "devDependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/preset-classic": "2.4.0", - "@mdx-js/react": "1.6.22", - "@stryker-mutator/core": "6.4.2", - "@stryker-mutator/mocha-runner": "6.4.2", - "@stryker-mutator/typescript-checker": "6.4.2", - "@svgr/webpack": "6.5.1", - "@types/chai": "4.3.4", - "@types/mocha": "10.0.1", - "@types/node": "18.15.11", - "@types/prettier": "2.7.2", - "@typescript-eslint/eslint-plugin": "5.59.0", - "@typescript-eslint/parser": "5.59.0", - "c8": "7.13.0", - "chai": "4.3.7", - "clsx": "1.2.1", - "cspell": "6.31.1", - "docusaurus-plugin-typedoc-api": "3.0.0", - "eslint": "8.38.0", - "eslint-plugin-import": "2.27.5", - "eslint-plugin-n": "15.7.0", - "eslint-plugin-react": "7.32.2", - "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-simple-import-sort": "10.0.0", - "eslint-plugin-tsdoc": "0.2.17", - "file-loader": "6.2.0", - "mocha": "10.2.0", - "prettier": "2.8.7", - "prism-react-renderer": "1.3.5", - "react": "17.0.2", - "react-dom": "17.0.2", - "ts-node": "10.9.1", - "typedoc": "0.24.4", - "typescript": "5.0.4", - "url-loader": "4.1.1" + "@types/chai": "5.0.1", + "@types/mocha": "10.0.10", + "@types/node": "22.10.1", + "c8": "10.1.2", + "chai": "5.1.2", + "cspell": "8.16.1", + "eslint": "^9.16.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-n": "17.14.0", + "eslint-plugin-react": "7.37.2", + "eslint-plugin-react-hooks": "5.0.0", + "eslint-plugin-simple-import-sort": "12.1.1", + "husky": "^9.1.7", + "lint-staged": "^15.2.10", + "mocha": "11.0.1", + "prettier": "3.4.1", + "ts-node": "10.9.2", + "typescript": "5.7.2", + "typescript-eslint": "^8.17.0" }, "publishConfig": { "tag": "alpha" diff --git a/resources/benchmark.ts b/resources/benchmark.ts index 2d7216c2b1..65d657f060 100644 --- a/resources/benchmark.ts +++ b/resources/benchmark.ts @@ -329,27 +329,27 @@ function findAllBenchmarks() { .map((name) => path.join('benchmark', name)); } -function bold(str: string | number) { +function bold(str: number | string) { return '\u001b[1m' + str + '\u001b[0m'; } -function red(str: string | number) { +function red(str: number | string) { return '\u001b[31m' + str + '\u001b[0m'; } -function green(str: string | number) { +function green(str: number | string) { return '\u001b[32m' + str + '\u001b[0m'; } -function yellow(str: string | number) { +function yellow(str: number | string) { return '\u001b[33m' + str + '\u001b[0m'; } -function cyan(str: string | number) { +function cyan(str: number | string) { return '\u001b[36m' + str + '\u001b[0m'; } -function grey(str: string | number) { +function grey(str: number | string) { return '\u001b[90m' + str + '\u001b[0m'; } @@ -404,7 +404,7 @@ function sampleModule(modulePath: string): BenchmarkSample { // V8 flags '--predictable', '--no-concurrent-sweeping', - '--no-scavenge-task', + '--no-minor-gc-task', '--min-semi-space-size=1024', // 1GB '--max-semi-space-size=1024', // 1GB '--trace-gc', // no gc calls should happen during benchmark, so trace them diff --git a/resources/build-deno.ts b/resources/build-deno.ts index c5da8ce706..43a4b292b1 100644 --- a/resources/build-deno.ts +++ b/resources/build-deno.ts @@ -5,7 +5,12 @@ import ts from 'typescript'; import { changeExtensionInImportPaths } from './change-extension-in-import-paths.js'; import { inlineInvariant } from './inline-invariant.js'; -import { readTSConfig, showDirStats, writeGeneratedFile } from './utils.js'; +import { + prettify, + readTSConfig, + showDirStats, + writeGeneratedFile, +} from './utils.js'; fs.rmSync('./denoDist', { recursive: true, force: true }); fs.mkdirSync('./denoDist'); @@ -32,7 +37,9 @@ for (const sourceFile of tsProgram.getSourceFiles()) { const filepath = path.relative('./src', sourceFile.fileName); const destPath = path.join('./denoDist', filepath); - writeGeneratedFile(destPath, newContent); + // eslint-disable-next-line no-await-in-loop + const prettified = await prettify(destPath, newContent); + writeGeneratedFile(destPath, prettified); } fs.copyFileSync('./LICENSE', './denoDist/LICENSE'); diff --git a/resources/build-docusaurus.ts b/resources/build-docusaurus.ts deleted file mode 100644 index 8928bac07c..0000000000 --- a/resources/build-docusaurus.ts +++ /dev/null @@ -1,39 +0,0 @@ -// The whole script is a hack to allow building Docusaurus in ESM project -// https://github.com/facebook/docusaurus/issues/6520 -// Should be just: `docusaurus build --out-dir ./websiteDist ./website` - -import fs from 'node:fs'; - -import { localRepoPath, makeTmpDir, npm, readPackageJSON } from './utils.js'; - -const { tmpDirPath } = makeTmpDir('graphql-js-run-docusaurus'); - -const packageJSON = readPackageJSON(); -delete packageJSON.type; -fs.writeFileSync(tmpDirPath('package.json'), JSON.stringify(packageJSON)); - -copyToTmpDir('package-lock.json'); -copyToTmpDir('tsconfig.json'); -copyToTmpDir('src'); -copyToTmpDir('website'); - -npm({ cwd: tmpDirPath(), quiet: true }).ci('--ignore-scripts'); - -const env = { - ...process.env, - DOCUSAURUS_GENERATED_FILES_DIR_NAME: tmpDirPath('.docusaurus'), -}; -npm({ env, cwd: tmpDirPath() }).exec( - 'docusaurus', - '--', - 'build', - '--out-dir', - localRepoPath('websiteDist'), - tmpDirPath('website'), -); - -function copyToTmpDir(relativePath: string) { - fs.cpSync(localRepoPath(relativePath), tmpDirPath(relativePath), { - recursive: true, - }); -} diff --git a/resources/build-npm.ts b/resources/build-npm.ts index 4ccd249a76..c29747efb8 100644 --- a/resources/build-npm.ts +++ b/resources/build-npm.ts @@ -7,6 +7,7 @@ import ts from 'typescript'; import { changeExtensionInImportPaths } from './change-extension-in-import-paths.js'; import { inlineInvariant } from './inline-invariant.js'; import { + prettify, readPackageJSON, readTSConfig, showDirStats, @@ -14,14 +15,14 @@ import { } from './utils.js'; console.log('\n./npmDist'); -buildPackage('./npmDist', false); +await buildPackage('./npmDist', false); showDirStats('./npmDist'); console.log('\n./npmEsmDist'); -buildPackage('./npmEsmDist', true); +await buildPackage('./npmEsmDist', true); showDirStats('./npmEsmDist'); -function buildPackage(outDir: string, isESMOnly: boolean): void { +async function buildPackage(outDir: string, isESMOnly: boolean): Promise { fs.rmSync(outDir, { recursive: true, force: true }); fs.mkdirSync(outDir); @@ -111,8 +112,13 @@ function buildPackage(outDir: string, isESMOnly: boolean): void { emitTSFiles({ outDir, module: 'es2020', extension: '.mjs' }); } + const packageJsonPath = `./${outDir}/package.json`; + const prettified = await prettify( + packageJsonPath, + JSON.stringify(packageJSON), + ); // Should be done as the last step so only valid packages can be published - writeGeneratedFile(`./${outDir}/package.json`, JSON.stringify(packageJSON)); + writeGeneratedFile(packageJsonPath, prettified); } // Based on https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#getting-the-dts-from-a-javascript-file @@ -134,8 +140,23 @@ function emitTSFiles(options: { }); const tsHost = ts.createCompilerHost(tsOptions); - tsHost.writeFile = (filepath, body) => - writeGeneratedFile(filepath.replace(/.js$/, extension), body); + tsHost.writeFile = (filepath, body) => { + if (filepath.match(/.js$/) && extension === '.mjs') { + let bodyToWrite = body; + bodyToWrite = bodyToWrite.replace( + '//# sourceMappingURL=graphql.js.map', + '//# sourceMappingURL=graphql.mjs.map', + ); + writeGeneratedFile(filepath.replace(/.js$/, extension), bodyToWrite); + } else if (filepath.match(/.js.map$/) && extension === '.mjs') { + writeGeneratedFile( + filepath.replace(/.js.map$/, extension + '.map'), + body, + ); + } else { + writeGeneratedFile(filepath, body); + } + }; const tsProgram = ts.createProgram(['src/index.ts'], tsOptions, tsHost); const tsResult = tsProgram.emit(undefined, undefined, undefined, undefined, { diff --git a/resources/checkgit.sh b/resources/checkgit.sh index 49449ecdf2..e5e4c67cf2 100644 --- a/resources/checkgit.sh +++ b/resources/checkgit.sh @@ -1,4 +1,5 @@ # Exit immediately if any subcommand terminated +set -e trap "exit 1" ERR # diff --git a/resources/diff-npm-package.ts b/resources/diff-npm-package.ts index 147e4874fe..20fbae14bc 100644 --- a/resources/diff-npm-package.ts +++ b/resources/diff-npm-package.ts @@ -8,6 +8,7 @@ import { localRepoPath, makeTmpDir, npm, + prettify, writeGeneratedFile, } from './utils.js'; @@ -37,7 +38,8 @@ if (diff === '') { console.log('No changes found!'); } else { const reportPath = localRepoPath('reports', 'npm-dist-diff.html'); - writeGeneratedFile(reportPath, generateReport(diff)); + const prettified = await prettify(reportPath, generateReport(diff)); + writeGeneratedFile(reportPath, prettified); console.log('Report saved to: ', reportPath); } diff --git a/resources/eslint-internal-rules/index.js b/resources/eslint-internal-rules/index.js index 4acc530f3a..7d78edfade 100644 --- a/resources/eslint-internal-rules/index.js +++ b/resources/eslint-internal-rules/index.js @@ -1,13 +1,13 @@ -'use strict'; +import { noDirImportRule } from './no-dir-import.js'; +import { onlyAsciiRule } from './only-ascii.js'; +import { requireToStringTagRule } from './require-to-string-tag.js'; -const onlyASCII = require('./only-ascii.js'); -const noDirImport = require('./no-dir-import.js'); -const requireToStringTag = require('./require-to-string-tag.js'); - -module.exports = { +const internalRulesPlugin = { rules: { - 'only-ascii': onlyASCII, - 'no-dir-import': noDirImport, - 'require-to-string-tag': requireToStringTag, + ...onlyAsciiRule, + ...noDirImportRule, + ...requireToStringTagRule, }, }; + +export { internalRulesPlugin }; diff --git a/resources/eslint-internal-rules/no-dir-import.js b/resources/eslint-internal-rules/no-dir-import.js index 5322039875..398b276137 100644 --- a/resources/eslint-internal-rules/no-dir-import.js +++ b/resources/eslint-internal-rules/no-dir-import.js @@ -1,9 +1,15 @@ -'use strict'; +import fs from 'node:fs'; +import path from 'node:path'; -const fs = require('fs'); -const path = require('path'); +const noDirImportRule = { + 'no-dir-import': { + create: noDirImport, + }, +}; + +export { noDirImportRule }; -module.exports = function noDirImportRule(context) { +function noDirImport(context) { return { ImportDeclaration: checkImportPath, ExportNamedDeclaration: checkImportPath, @@ -33,4 +39,4 @@ module.exports = function noDirImportRule(context) { } } } -}; +} diff --git a/resources/eslint-internal-rules/only-ascii.js b/resources/eslint-internal-rules/only-ascii.js index f5ddbe1b68..a11a9e3037 100644 --- a/resources/eslint-internal-rules/only-ascii.js +++ b/resources/eslint-internal-rules/only-ascii.js @@ -1,22 +1,24 @@ -'use strict'; - -module.exports = { - meta: { - schema: [ - { - type: 'object', - properties: { - allowEmoji: { - type: 'boolean', +const onlyAsciiRule = { + 'only-ascii': { + meta: { + schema: [ + { + type: 'object', + properties: { + allowEmoji: { + type: 'boolean', + }, }, + additionalProperties: false, }, - additionalProperties: false, - }, - ], + ], + }, + create: onlyASCII, }, - create: onlyASCII, }; +export { onlyAsciiRule }; + function onlyASCII(context) { const regExp = context.options[0]?.allowEmoji === true diff --git a/resources/eslint-internal-rules/package.json b/resources/eslint-internal-rules/package.json deleted file mode 100644 index 0955c87d52..0000000000 --- a/resources/eslint-internal-rules/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "private": true, - "engines": { - "node": ">= 16.0.0" - } -} diff --git a/resources/eslint-internal-rules/require-to-string-tag.js b/resources/eslint-internal-rules/require-to-string-tag.js index 517fd07eb3..d85ccd1dcd 100644 --- a/resources/eslint-internal-rules/require-to-string-tag.js +++ b/resources/eslint-internal-rules/require-to-string-tag.js @@ -1,6 +1,12 @@ -'use strict'; +const requireToStringTagRule = { + 'require-to-string-tag': { + create: requireToStringTag, + }, +}; + +export { requireToStringTagRule }; -module.exports = function requireToStringTag(context) { +function requireToStringTag(context) { const sourceCode = context.getSourceCode(); return { @@ -10,7 +16,7 @@ module.exports = function requireToStringTag(context) { return; } - const jsDoc = context.getJSDocComment(classNode)?.value; + const jsDoc = context.getSourceCode().getJSDocComment(classNode)?.value; // FIXME: use proper TSDoc parser instead of includes once we fix TSDoc comments if (jsDoc?.includes('@internal') === true) { return; @@ -34,4 +40,4 @@ module.exports = function requireToStringTag(context) { const keyText = sourceCode.getText(propertyNode.key); return keyText === 'Symbol.toStringTag'; } -}; +} diff --git a/resources/gen-version.ts b/resources/gen-version.ts index 9a6ed637af..b4b75ea92c 100644 --- a/resources/gen-version.ts +++ b/resources/gen-version.ts @@ -1,4 +1,4 @@ -import { readPackageJSON, writeGeneratedFile } from './utils.js'; +import { prettify, readPackageJSON, writeGeneratedFile } from './utils.js'; const { version } = readPackageJSON(); const versionMatch = /^(\d+)\.(\d+)\.(\d+)-?(.*)?$/.exec(version); @@ -30,4 +30,5 @@ export const versionInfo = Object.freeze({ }); `; -writeGeneratedFile('./src/version.ts', body); +const prettified = await prettify('./src/version.ts', body); +writeGeneratedFile('./src/version.ts', prettified); diff --git a/resources/utils.ts b/resources/utils.ts index 983acb2752..4291ddc20a 100644 --- a/resources/utils.ts +++ b/resources/utils.ts @@ -34,24 +34,40 @@ interface NPMOptions extends SpawnOptions { export function npm(options?: NPMOptions) { const globalOptions = options?.quiet === true ? ['--quiet'] : []; + + // `npm` points to an executable shell script; so it doesn't require a shell per se. + // On Windows `shell: true` is required or `npm` will be picked rather than `npm.cmd`. + // This could alternatively be handled by manually selecting `npm.cmd` on Windows. + // See: https://github.com/nodejs/node/issues/3675 and in particular + // https://github.com/nodejs/node/issues/3675#issuecomment-308963807. + const npmOptions = { shell: true, ...options }; + return { run(...args: ReadonlyArray): void { - spawn('npm', [...globalOptions, 'run', ...args], options); + spawn('npm', [...globalOptions, 'run', ...args], npmOptions); }, install(...args: ReadonlyArray): void { - spawn('npm', [...globalOptions, 'install', ...args], options); + spawn('npm', [...globalOptions, 'install', ...args], npmOptions); }, ci(...args: ReadonlyArray): void { - spawn('npm', [...globalOptions, 'ci', ...args], options); + spawn('npm', [...globalOptions, 'ci', ...args], npmOptions); }, exec(...args: ReadonlyArray): void { - spawn('npm', [...globalOptions, 'exec', ...args], options); + spawn('npm', [...globalOptions, 'exec', ...args], npmOptions); }, pack(...args: ReadonlyArray): string { - return spawnOutput('npm', [...globalOptions, 'pack', ...args], options); + return spawnOutput( + 'npm', + [...globalOptions, 'pack', ...args], + npmOptions, + ); }, diff(...args: ReadonlyArray): string { - return spawnOutput('npm', [...globalOptions, 'diff', ...args], options); + return spawnOutput( + 'npm', + [...globalOptions, 'diff', ...args], + npmOptions, + ); }, }; } @@ -89,6 +105,7 @@ export function git(options?: GITOptions) { interface SpawnOptions { cwd?: string; env?: typeof process.env; + shell?: boolean; } function spawnOutput( @@ -195,10 +212,19 @@ const prettierConfig = JSON.parse( fs.readFileSync(localRepoPath('.prettierrc'), 'utf-8'), ); +export async function prettify( + filepath: string, + body: string, +): Promise { + return prettier.format(body, { + filepath, + ...prettierConfig, + }); +} + export function writeGeneratedFile(filepath: string, body: string): void { - const formatted = prettier.format(body, { filepath, ...prettierConfig }); fs.mkdirSync(path.dirname(filepath), { recursive: true }); - fs.writeFileSync(filepath, formatted); + fs.writeFileSync(filepath, body); } interface PackageJSON { @@ -236,7 +262,7 @@ export function readTSConfig(overrides?: any): ts.CompilerOptions { ); assert(tsConfigError === undefined, 'Fail to parse config: ' + tsConfigError); assert( - tsConfig.compilerOptions, + tsConfig.compilerOptions !== undefined, '"tsconfig.json" should have `compilerOptions`', ); diff --git a/src/__testUtils__/__tests__/expectPromise-test.ts b/src/__testUtils__/__tests__/expectPromise-test.ts index f54160ad50..cd25624567 100644 --- a/src/__testUtils__/__tests__/expectPromise-test.ts +++ b/src/__testUtils__/__tests__/expectPromise-test.ts @@ -45,7 +45,7 @@ describe('expectPromise', () => { await expectPromise(Promise.reject(new Error('foo'))).toRejectWith( 'foo', ); /* c8 ignore start */ - } catch (err) { + } catch (_err) { // Not reached. expect.fail('promise threw unexpectedly'); } /* c8 ignore stop */ diff --git a/src/__testUtils__/kitchenSinkQuery.ts b/src/__testUtils__/kitchenSinkQuery.ts index 46628b6556..9ed9a7e983 100644 --- a/src/__testUtils__/kitchenSinkQuery.ts +++ b/src/__testUtils__/kitchenSinkQuery.ts @@ -10,21 +10,6 @@ query queryName($foo: ComplexType, $site: Site = MOBILE) @onQuery { ...frag @onFragmentSpread } } - - field3! - field4? - requiredField5: field5! - requiredSelectionSet(first: 10)! @directive { - field - } - - unsetListItemsRequiredList: listField[]! - requiredListItemsUnsetList: listField[!] - requiredListItemsRequiredList: listField[!]! - unsetListItemsOptionalList: listField[]? - optionalListItemsUnsetList: listField[?] - optionalListItemsOptionalList: listField[?]? - multidimensionalList: listField[[[!]!]!]! } ... @skip(unless: $foo) { id diff --git a/src/error/GraphQLError.ts b/src/error/GraphQLError.ts index a3ce229968..a2404d6040 100644 --- a/src/error/GraphQLError.ts +++ b/src/error/GraphQLError.ts @@ -23,6 +23,19 @@ export interface GraphQLErrorExtensions { [attributeName: string]: unknown; } +/** + * Custom formatted extensions + * + * @remarks + * Use a unique identifier name for your extension, for example the name of + * your library or project. Do not use a shortened identifier as this increases + * the risk of conflicts. We recommend you add at most one extension field, + * an object which can contain all the values you need. + */ +export interface GraphQLFormattedErrorExtensions { + [attributeName: string]: unknown; +} + export interface GraphQLErrorOptions { nodes?: ReadonlyArray | ASTNode | null | undefined; source?: Maybe; @@ -238,5 +251,5 @@ export interface GraphQLFormattedError { * Reserved for implementors to extend the protocol however they see fit, * and hence there are no additional restrictions on its contents. */ - readonly extensions?: { [key: string]: unknown }; + readonly extensions?: GraphQLFormattedErrorExtensions; } diff --git a/src/error/index.ts b/src/error/index.ts index ed9e24d241..17e9059dd1 100644 --- a/src/error/index.ts +++ b/src/error/index.ts @@ -3,6 +3,7 @@ export type { GraphQLErrorOptions, GraphQLFormattedError, GraphQLErrorExtensions, + GraphQLFormattedErrorExtensions, } from './GraphQLError.js'; export { syntaxError } from './syntaxError.js'; diff --git a/src/execution/AbortSignalListener.ts b/src/execution/AbortSignalListener.ts new file mode 100644 index 0000000000..3d707ce615 --- /dev/null +++ b/src/execution/AbortSignalListener.ts @@ -0,0 +1,91 @@ +import { promiseWithResolvers } from '../jsutils/promiseWithResolvers.js'; + +/** + * A AbortSignalListener object can be used to trigger multiple responses + * in response to a single AbortSignal. + * + * @internal + */ +export class AbortSignalListener { + abortSignal: AbortSignal; + abort: () => void; + + private _onAborts: Set<() => void>; + + constructor(abortSignal: AbortSignal) { + this.abortSignal = abortSignal; + this._onAborts = new Set<() => void>(); + this.abort = () => { + for (const abort of this._onAborts) { + abort(); + } + }; + + abortSignal.addEventListener('abort', this.abort); + } + + add(onAbort: () => void): void { + this._onAborts.add(onAbort); + } + + delete(onAbort: () => void): void { + this._onAborts.delete(onAbort); + } + + disconnect(): void { + this.abortSignal.removeEventListener('abort', this.abort); + } +} + +export function cancellablePromise( + originalPromise: Promise, + abortSignalListener: AbortSignalListener, +): Promise { + const abortSignal = abortSignalListener.abortSignal; + if (abortSignal.aborted) { + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors + return Promise.reject(abortSignal.reason); + } + + const { promise, resolve, reject } = promiseWithResolvers(); + const onAbort = () => reject(abortSignal.reason); + abortSignalListener.add(onAbort); + originalPromise.then( + (resolved) => { + abortSignalListener.delete(onAbort); + resolve(resolved); + }, + (error: unknown) => { + abortSignalListener.delete(onAbort); + reject(error); + }, + ); + + return promise; +} + +export function cancellableIterable( + iterable: AsyncIterable, + abortSignalListener: AbortSignalListener, +): AsyncIterable { + const iterator = iterable[Symbol.asyncIterator](); + + const _next = iterator.next.bind(iterator); + + if (iterator.return) { + const _return = iterator.return.bind(iterator); + + return { + [Symbol.asyncIterator]: () => ({ + next: () => cancellablePromise(_next(), abortSignalListener), + return: () => cancellablePromise(_return(), abortSignalListener), + }), + }; + } + + return { + [Symbol.asyncIterator]: () => ({ + next: () => cancellablePromise(_next(), abortSignalListener), + }), + }; +} diff --git a/src/execution/IncrementalGraph.ts b/src/execution/IncrementalGraph.ts new file mode 100644 index 0000000000..53b60d2b32 --- /dev/null +++ b/src/execution/IncrementalGraph.ts @@ -0,0 +1,320 @@ +import { BoxedPromiseOrValue } from '../jsutils/BoxedPromiseOrValue.js'; +import { invariant } from '../jsutils/invariant.js'; +import { isPromise } from '../jsutils/isPromise.js'; +import { promiseWithResolvers } from '../jsutils/promiseWithResolvers.js'; + +import type { GraphQLError } from '../error/GraphQLError.js'; + +import type { + DeferredFragmentRecord, + DeliveryGroup, + IncrementalDataRecord, + IncrementalDataRecordResult, + PendingExecutionGroup, + StreamItemRecord, + StreamRecord, + SuccessfulExecutionGroup, +} from './types.js'; +import { isDeferredFragmentRecord, isPendingExecutionGroup } from './types.js'; + +/** + * @internal + */ +export class IncrementalGraph { + private _rootNodes: Set; + + private _completedQueue: Array; + private _nextQueue: Array< + (iterable: Iterable | undefined) => void + >; + + constructor() { + this._rootNodes = new Set(); + this._completedQueue = []; + this._nextQueue = []; + } + + getNewRootNodes( + incrementalDataRecords: ReadonlyArray, + ): ReadonlyArray { + const initialResultChildren = new Set(); + this._addIncrementalDataRecords( + incrementalDataRecords, + undefined, + initialResultChildren, + ); + return this._promoteNonEmptyToRoot(initialResultChildren); + } + + addCompletedSuccessfulExecutionGroup( + successfulExecutionGroup: SuccessfulExecutionGroup, + ): void { + const { pendingExecutionGroup, incrementalDataRecords } = + successfulExecutionGroup; + + const deferredFragmentRecords = + pendingExecutionGroup.deferredFragmentRecords; + + for (const deferredFragmentRecord of deferredFragmentRecords) { + const { pendingExecutionGroups, successfulExecutionGroups } = + deferredFragmentRecord; + pendingExecutionGroups.delete(pendingExecutionGroup); + successfulExecutionGroups.add(successfulExecutionGroup); + } + + if (incrementalDataRecords !== undefined) { + this._addIncrementalDataRecords( + incrementalDataRecords, + deferredFragmentRecords, + ); + } + } + + *currentCompletedBatch(): Generator { + let completed; + while ((completed = this._completedQueue.shift()) !== undefined) { + yield completed; + } + if (this._rootNodes.size === 0) { + for (const resolve of this._nextQueue) { + resolve(undefined); + } + } + } + + nextCompletedBatch(): Promise< + Iterable | undefined + > { + const { promise, resolve } = promiseWithResolvers< + Iterable | undefined + >(); + this._nextQueue.push(resolve); + return promise; + } + + abort(): void { + for (const resolve of this._nextQueue) { + resolve(undefined); + } + } + + hasNext(): boolean { + return this._rootNodes.size > 0; + } + + completeDeferredFragment(deferredFragmentRecord: DeferredFragmentRecord): + | { + newRootNodes: ReadonlyArray; + successfulExecutionGroups: ReadonlyArray; + } + | undefined { + if ( + !this._rootNodes.has(deferredFragmentRecord) || + deferredFragmentRecord.pendingExecutionGroups.size > 0 + ) { + return; + } + const successfulExecutionGroups = Array.from( + deferredFragmentRecord.successfulExecutionGroups, + ); + this._rootNodes.delete(deferredFragmentRecord); + for (const successfulExecutionGroup of successfulExecutionGroups) { + for (const otherDeferredFragmentRecord of successfulExecutionGroup + .pendingExecutionGroup.deferredFragmentRecords) { + otherDeferredFragmentRecord.successfulExecutionGroups.delete( + successfulExecutionGroup, + ); + } + } + const newRootNodes = this._promoteNonEmptyToRoot( + deferredFragmentRecord.children, + ); + return { newRootNodes, successfulExecutionGroups }; + } + + removeDeferredFragment( + deferredFragmentRecord: DeferredFragmentRecord, + ): boolean { + if (!this._rootNodes.has(deferredFragmentRecord)) { + return false; + } + this._rootNodes.delete(deferredFragmentRecord); + return true; + } + + removeStream(streamRecord: StreamRecord): void { + this._rootNodes.delete(streamRecord); + } + + private _addIncrementalDataRecords( + incrementalDataRecords: ReadonlyArray, + parents: ReadonlyArray | undefined, + initialResultChildren?: Set, + ): void { + for (const incrementalDataRecord of incrementalDataRecords) { + if (isPendingExecutionGroup(incrementalDataRecord)) { + for (const deferredFragmentRecord of incrementalDataRecord.deferredFragmentRecords) { + this._addDeferredFragment( + deferredFragmentRecord, + initialResultChildren, + ); + deferredFragmentRecord.pendingExecutionGroups.add( + incrementalDataRecord, + ); + } + if (this._completesRootNode(incrementalDataRecord)) { + this._onExecutionGroup(incrementalDataRecord); + } + } else if (parents === undefined) { + invariant(initialResultChildren !== undefined); + initialResultChildren.add(incrementalDataRecord); + } else { + for (const parent of parents) { + this._addDeferredFragment(parent, initialResultChildren); + parent.children.add(incrementalDataRecord); + } + } + } + } + + private _promoteNonEmptyToRoot( + maybeEmptyNewRootNodes: Set, + ): ReadonlyArray { + const newRootNodes: Array = []; + for (const node of maybeEmptyNewRootNodes) { + if (isDeferredFragmentRecord(node)) { + if (node.pendingExecutionGroups.size > 0) { + for (const pendingExecutionGroup of node.pendingExecutionGroups) { + if (!this._completesRootNode(pendingExecutionGroup)) { + this._onExecutionGroup(pendingExecutionGroup); + } + } + this._rootNodes.add(node); + newRootNodes.push(node); + continue; + } + for (const child of node.children) { + maybeEmptyNewRootNodes.add(child); + } + } else { + this._rootNodes.add(node); + newRootNodes.push(node); + + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this._onStreamItems(node); + } + } + return newRootNodes; + } + + private _completesRootNode( + pendingExecutionGroup: PendingExecutionGroup, + ): boolean { + return pendingExecutionGroup.deferredFragmentRecords.some( + (deferredFragmentRecord) => this._rootNodes.has(deferredFragmentRecord), + ); + } + + private _addDeferredFragment( + deferredFragmentRecord: DeferredFragmentRecord, + initialResultChildren: Set | undefined, + ): void { + if (this._rootNodes.has(deferredFragmentRecord)) { + return; + } + const parent = deferredFragmentRecord.parent; + if (parent === undefined) { + invariant(initialResultChildren !== undefined); + initialResultChildren.add(deferredFragmentRecord); + return; + } + parent.children.add(deferredFragmentRecord); + this._addDeferredFragment(parent, initialResultChildren); + } + + private _onExecutionGroup( + pendingExecutionGroup: PendingExecutionGroup, + ): void { + let completedExecutionGroup = pendingExecutionGroup.result; + if (!(completedExecutionGroup instanceof BoxedPromiseOrValue)) { + completedExecutionGroup = completedExecutionGroup(); + } + const value = completedExecutionGroup.value; + if (isPromise(value)) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + value.then((resolved) => this._enqueue(resolved)); + } else { + this._enqueue(value); + } + } + + private async _onStreamItems(streamRecord: StreamRecord): Promise { + let items: Array = []; + let errors: Array = []; + let incrementalDataRecords: Array = []; + const streamItemQueue = streamRecord.streamItemQueue; + let streamItemRecord: StreamItemRecord | undefined; + while ((streamItemRecord = streamItemQueue.shift()) !== undefined) { + let result = + streamItemRecord instanceof BoxedPromiseOrValue + ? streamItemRecord.value + : streamItemRecord().value; + if (isPromise(result)) { + if (items.length > 0) { + this._enqueue({ + streamRecord, + result: + // TODO add additional test case or rework for coverage + errors.length > 0 /* c8 ignore start */ + ? { items, errors } /* c8 ignore stop */ + : { items }, + incrementalDataRecords, + }); + items = []; + errors = []; + incrementalDataRecords = []; + } + // eslint-disable-next-line no-await-in-loop + result = await result; + // wait an additional tick to coalesce resolving additional promises + // within the queue + // eslint-disable-next-line no-await-in-loop + await Promise.resolve(); + } + if (result.item === undefined) { + if (items.length > 0) { + this._enqueue({ + streamRecord, + result: errors.length > 0 ? { items, errors } : { items }, + incrementalDataRecords, + }); + } + this._enqueue( + result.errors === undefined + ? { streamRecord } + : { + streamRecord, + errors: result.errors, + }, + ); + return; + } + items.push(result.item); + if (result.errors !== undefined) { + errors.push(...result.errors); + } + if (result.incrementalDataRecords !== undefined) { + incrementalDataRecords.push(...result.incrementalDataRecords); + } + } + } + + private _enqueue(completed: IncrementalDataRecordResult): void { + this._completedQueue.push(completed); + const next = this._nextQueue.shift(); + if (next === undefined) { + return; + } + next(this.currentCompletedBatch()); + } +} diff --git a/src/execution/IncrementalPublisher.ts b/src/execution/IncrementalPublisher.ts index 9cda62dea8..b826a9b9c5 100644 --- a/src/execution/IncrementalPublisher.ts +++ b/src/execution/IncrementalPublisher.ts @@ -1,390 +1,111 @@ +import { invariant } from '../jsutils/invariant.js'; import type { ObjMap } from '../jsutils/ObjMap.js'; -import type { Path } from '../jsutils/Path.js'; import { pathToArray } from '../jsutils/Path.js'; -import { promiseWithResolvers } from '../jsutils/promiseWithResolvers.js'; -import type { - GraphQLError, - GraphQLFormattedError, -} from '../error/GraphQLError.js'; - -import type { GroupedFieldSet } from './buildFieldPlan.js'; - -interface IncrementalUpdate> { - pending: ReadonlyArray; - incremental: ReadonlyArray>; - completed: ReadonlyArray; -} - -/** - * The result of GraphQL execution. - * - * - `errors` is included when any errors occurred as a non-empty array. - * - `data` is the result of a successful execution of the query. - * - `hasNext` is true if a future payload is expected. - * - `extensions` is reserved for adding non-standard properties. - * - `incremental` is a list of the results from defer/stream directives. - */ -export interface ExecutionResult< - TData = ObjMap, - TExtensions = ObjMap, -> { - errors?: ReadonlyArray; - data?: TData | null; - extensions?: TExtensions; -} - -export interface FormattedExecutionResult< - TData = ObjMap, - TExtensions = ObjMap, -> { - errors?: ReadonlyArray; - data?: TData | null; - extensions?: TExtensions; -} - -export interface ExperimentalIncrementalExecutionResults< - TData = unknown, - TExtensions = ObjMap, -> { - initialResult: InitialIncrementalExecutionResult; - subsequentResults: AsyncGenerator< - SubsequentIncrementalExecutionResult, - void, - void - >; -} - -export interface InitialIncrementalExecutionResult< - TData = ObjMap, - TExtensions = ObjMap, -> extends ExecutionResult { - data: TData; - pending: ReadonlyArray; - hasNext: true; - extensions?: TExtensions; -} - -export interface FormattedInitialIncrementalExecutionResult< - TData = ObjMap, - TExtensions = ObjMap, -> extends FormattedExecutionResult { - data: TData; - pending: ReadonlyArray; - hasNext: boolean; - extensions?: TExtensions; -} - -export interface SubsequentIncrementalExecutionResult< - TData = unknown, - TExtensions = ObjMap, -> extends Partial> { - hasNext: boolean; - extensions?: TExtensions; -} +import type { GraphQLError } from '../error/GraphQLError.js'; -export interface FormattedSubsequentIncrementalExecutionResult< - TData = unknown, - TExtensions = ObjMap, -> { - hasNext: boolean; - pending?: ReadonlyArray; - incremental?: ReadonlyArray>; - completed?: ReadonlyArray; - extensions?: TExtensions; -} - -export interface IncrementalDeferResult< - TData = ObjMap, - TExtensions = ObjMap, -> { - errors?: ReadonlyArray; - data: TData; - id: string; - subPath?: ReadonlyArray; - extensions?: TExtensions; -} - -export interface FormattedIncrementalDeferResult< - TData = ObjMap, - TExtensions = ObjMap, -> { - errors?: ReadonlyArray; - data: TData; - id: string; - subPath?: ReadonlyArray; - extensions?: TExtensions; -} - -export interface IncrementalStreamResult< - TData = Array, - TExtensions = ObjMap, -> { - errors?: ReadonlyArray; - items: TData; - id: string; - subPath?: ReadonlyArray; - extensions?: TExtensions; -} - -export interface FormattedIncrementalStreamResult< - TData = Array, - TExtensions = ObjMap, -> { - errors?: ReadonlyArray; - items: TData; - id: string; - subPath?: ReadonlyArray; - extensions?: TExtensions; -} - -export type IncrementalResult> = - | IncrementalDeferResult - | IncrementalStreamResult; - -export type FormattedIncrementalResult< - TData = unknown, - TExtensions = ObjMap, -> = - | FormattedIncrementalDeferResult - | FormattedIncrementalStreamResult; - -export interface PendingResult { - id: string; - path: ReadonlyArray; - label?: string; +import type { AbortSignalListener } from './AbortSignalListener.js'; +import { IncrementalGraph } from './IncrementalGraph.js'; +import type { + CancellableStreamRecord, + CompletedExecutionGroup, + CompletedResult, + DeferredFragmentRecord, + DeliveryGroup, + ExperimentalIncrementalExecutionResults, + IncrementalDataRecord, + IncrementalDataRecordResult, + IncrementalDeferResult, + IncrementalResult, + IncrementalStreamResult, + InitialIncrementalExecutionResult, + PendingResult, + StreamItemsResult, + SubsequentIncrementalExecutionResult, +} from './types.js'; +import { + isCancellableStreamRecord, + isCompletedExecutionGroup, + isFailedExecutionGroup, +} from './types.js'; + +export function buildIncrementalResponse( + context: IncrementalPublisherContext, + result: ObjMap, + errors: ReadonlyArray | undefined, + incrementalDataRecords: ReadonlyArray, +): ExperimentalIncrementalExecutionResults { + const incrementalPublisher = new IncrementalPublisher(context); + return incrementalPublisher.buildResponse( + result, + errors, + incrementalDataRecords, + ); } -export interface CompletedResult { - id: string; - errors?: ReadonlyArray; +interface IncrementalPublisherContext { + abortSignalListener: AbortSignalListener | undefined; + cancellableStreams: Set | undefined; } -export interface FormattedCompletedResult { - path: ReadonlyArray; - label?: string; - errors?: ReadonlyArray; +interface SubsequentIncrementalExecutionResultContext { + pending: Array; + incremental: Array; + completed: Array; } /** * This class is used to publish incremental results to the client, enabling semi-concurrent * execution while preserving result order. * - * The internal publishing state is managed as follows: - * - * '_released': the set of Subsequent Result records that are ready to be sent to the client, - * i.e. their parents have completed and they have also completed. - * - * `_pending`: the set of Subsequent Result records that are definitely pending, i.e. their - * parents have completed so that they can no longer be filtered. This includes all Subsequent - * Result records in `released`, as well as the records that have not yet completed. - * * @internal */ -export class IncrementalPublisher { - private _nextId = 0; - private _released: Set; - private _pending: Set; - - // these are assigned within the Promise executor called synchronously within the constructor - private _signalled!: Promise; - private _resolve!: () => void; - - constructor() { - this._released = new Set(); - this._pending = new Set(); - this._reset(); - } - - reportNewDeferFragmentRecord( - deferredFragmentRecord: DeferredFragmentRecord, - parentIncrementalResultRecord: - | InitialResultRecord - | DeferredFragmentRecord - | StreamItemsRecord, - ): void { - parentIncrementalResultRecord.children.add(deferredFragmentRecord); - } +class IncrementalPublisher { + private _context: IncrementalPublisherContext; + private _nextId: number; + private _incrementalGraph: IncrementalGraph; - reportNewDeferredGroupedFieldSetRecord( - deferredGroupedFieldSetRecord: DeferredGroupedFieldSetRecord, - ): void { - for (const deferredFragmentRecord of deferredGroupedFieldSetRecord.deferredFragmentRecords) { - deferredFragmentRecord._pending.add(deferredGroupedFieldSetRecord); - deferredFragmentRecord.deferredGroupedFieldSetRecords.add( - deferredGroupedFieldSetRecord, - ); - } + constructor(context: IncrementalPublisherContext) { + this._context = context; + this._nextId = 0; + this._incrementalGraph = new IncrementalGraph(); } - reportNewStreamItemsRecord( - streamItemsRecord: StreamItemsRecord, - parentIncrementalDataRecord: IncrementalDataRecord, - ): void { - if (isDeferredGroupedFieldSetRecord(parentIncrementalDataRecord)) { - for (const parent of parentIncrementalDataRecord.deferredFragmentRecords) { - parent.children.add(streamItemsRecord); - } - } else { - parentIncrementalDataRecord.children.add(streamItemsRecord); - } - } - - completeDeferredGroupedFieldSet( - deferredGroupedFieldSetRecord: DeferredGroupedFieldSetRecord, + buildResponse( data: ObjMap, - ): void { - deferredGroupedFieldSetRecord.data = data; - for (const deferredFragmentRecord of deferredGroupedFieldSetRecord.deferredFragmentRecords) { - deferredFragmentRecord._pending.delete(deferredGroupedFieldSetRecord); - if (deferredFragmentRecord._pending.size === 0) { - this.completeDeferredFragmentRecord(deferredFragmentRecord); - } - } - } + errors: ReadonlyArray | undefined, + incrementalDataRecords: ReadonlyArray, + ): ExperimentalIncrementalExecutionResults { + const newRootNodes = this._incrementalGraph.getNewRootNodes( + incrementalDataRecords, + ); - markErroredDeferredGroupedFieldSet( - deferredGroupedFieldSetRecord: DeferredGroupedFieldSetRecord, - error: GraphQLError, - ): void { - for (const deferredFragmentRecord of deferredGroupedFieldSetRecord.deferredFragmentRecords) { - deferredFragmentRecord.errors.push(error); - this.completeDeferredFragmentRecord(deferredFragmentRecord); - } - } + const pending = this._toPendingResults(newRootNodes); - completeDeferredFragmentRecord( - deferredFragmentRecord: DeferredFragmentRecord, - ): void { - this._release(deferredFragmentRecord); - } - - completeStreamItemsRecord( - streamItemsRecord: StreamItemsRecord, - items: Array, - ) { - streamItemsRecord.items = items; - streamItemsRecord.isCompleted = true; - this._release(streamItemsRecord); - } - - markErroredStreamItemsRecord( - streamItemsRecord: StreamItemsRecord, - error: GraphQLError, - ) { - streamItemsRecord.streamRecord.errors.push(error); - this.setIsFinalRecord(streamItemsRecord); - streamItemsRecord.isCompleted = true; - streamItemsRecord.streamRecord.earlyReturn?.().catch(() => { - // ignore error - }); - this._release(streamItemsRecord); - } - - setIsFinalRecord(streamItemsRecord: StreamItemsRecord) { - streamItemsRecord.isFinalRecord = true; - } - - setIsCompletedAsyncIterator(streamItemsRecord: StreamItemsRecord) { - streamItemsRecord.isCompletedAsyncIterator = true; - this.setIsFinalRecord(streamItemsRecord); - } - - addFieldError( - incrementalDataRecord: IncrementalDataRecord, - error: GraphQLError, - ) { - incrementalDataRecord.errors.push(error); - } - - buildDataResponse( - initialResultRecord: InitialResultRecord, - data: ObjMap | null, - ): ExecutionResult | ExperimentalIncrementalExecutionResults { - for (const child of initialResultRecord.children) { - if (child.filtered) { - continue; - } - this._publish(child); - } - - const errors = initialResultRecord.errors; - const initialResult = errors.length === 0 ? { data } : { errors, data }; - const pending = this._pending; - if (pending.size > 0) { - const pendingSources = new Set(); - for (const subsequentResultRecord of pending) { - const pendingSource = isStreamItemsRecord(subsequentResultRecord) - ? subsequentResultRecord.streamRecord - : subsequentResultRecord; - pendingSources.add(pendingSource); - } - - return { - initialResult: { - ...initialResult, - pending: this._pendingSourcesToResults(pendingSources), - hasNext: true, - }, - subsequentResults: this._subscribe(), - }; - } - return initialResult; - } - - buildErrorResponse( - initialResultRecord: InitialResultRecord, - error: GraphQLError, - ): ExecutionResult { - const errors = initialResultRecord.errors; - errors.push(error); - return { data: null, errors }; - } - - filter( - nullPath: Path | undefined, - erroringIncrementalDataRecord: IncrementalDataRecord, - ): void { - const nullPathArray = pathToArray(nullPath); + const initialResult: InitialIncrementalExecutionResult = + errors === undefined + ? { data, pending, hasNext: true } + : { errors, data, pending, hasNext: true }; - const streams = new Set(); - - const children = this._getChildren(erroringIncrementalDataRecord); - const descendants = this._getDescendants(children); - - for (const child of descendants) { - if (!this._nullsChildSubsequentResultRecord(child, nullPathArray)) { - continue; - } - - child.filtered = true; - - if (isStreamItemsRecord(child)) { - streams.add(child.streamRecord); - } - } - - streams.forEach((stream) => { - stream.earlyReturn?.().catch(() => { - // ignore error - }); - }); + return { + initialResult, + subsequentResults: this._subscribe(), + }; } - private _pendingSourcesToResults( - pendingSources: ReadonlySet, + private _toPendingResults( + newRootNodes: ReadonlyArray, ): Array { const pendingResults: Array = []; - for (const pendingSource of pendingSources) { - pendingSource.pendingSent = true; - const id = this._getNextId(); - pendingSource.id = id; + for (const node of newRootNodes) { + const id = String(this._getNextId()); + node.id = id; const pendingResult: PendingResult = { id, - path: pendingSource.path, + path: pathToArray(node.path), }; - if (pendingSource.label !== undefined) { - pendingResult.label = pendingSource.label; + if (node.label !== undefined) { + pendingResult.label = node.label; } pendingResults.push(pendingResult); } @@ -405,55 +126,67 @@ export class IncrementalPublisher { const _next = async (): Promise< IteratorResult > => { - // eslint-disable-next-line no-constant-condition - while (true) { - if (isDone) { - return { value: undefined, done: true }; - } + if (isDone) { + this._context.abortSignalListener?.disconnect(); + await this._returnAsyncIteratorsIgnoringErrors(); + return { value: undefined, done: true }; + } + + const context: SubsequentIncrementalExecutionResultContext = { + pending: [], + incremental: [], + completed: [], + }; - for (const item of this._released) { - this._pending.delete(item); + let batch: Iterable | undefined = + this._incrementalGraph.currentCompletedBatch(); + do { + for (const completedResult of batch) { + this._handleCompletedIncrementalData(completedResult, context); } - const released = this._released; - this._released = new Set(); - const result = this._getIncrementalResult(released); + const { incremental, completed } = context; + if (incremental.length > 0 || completed.length > 0) { + const hasNext = this._incrementalGraph.hasNext(); - if (this._pending.size === 0) { - isDone = true; - } + if (!hasNext) { + isDone = true; + } + + const subsequentIncrementalExecutionResult: SubsequentIncrementalExecutionResult = + { hasNext }; - if (result !== undefined) { - return { value: result, done: false }; + const pending = context.pending; + if (pending.length > 0) { + subsequentIncrementalExecutionResult.pending = pending; + } + if (incremental.length > 0) { + subsequentIncrementalExecutionResult.incremental = incremental; + } + if (completed.length > 0) { + subsequentIncrementalExecutionResult.completed = completed; + } + + return { value: subsequentIncrementalExecutionResult, done: false }; } // eslint-disable-next-line no-await-in-loop - await this._signalled; - } - }; + batch = await this._incrementalGraph.nextCompletedBatch(); + } while (batch !== undefined); - const returnStreamIterators = async (): Promise => { - const streams = new Set(); - const descendants = this._getDescendants(this._pending); - for (const subsequentResultRecord of descendants) { - if (isStreamItemsRecord(subsequentResultRecord)) { - streams.add(subsequentResultRecord.streamRecord); - } - } - const promises: Array> = []; - streams.forEach((streamRecord) => { - if (streamRecord.earlyReturn) { - promises.push(streamRecord.earlyReturn()); - } - }); - await Promise.all(promises); + // TODO: add test for this case + /* c8 ignore next */ + this._context.abortSignalListener?.disconnect(); + await this._returnAsyncIteratorsIgnoringErrors(); + return { value: undefined, done: true }; }; const _return = async (): Promise< IteratorResult > => { isDone = true; - await returnStreamIterators(); + this._incrementalGraph.abort(); + await this._returnAsyncIterators(); return { value: undefined, done: true }; }; @@ -461,7 +194,9 @@ export class IncrementalPublisher { error?: unknown, ): Promise> => { isDone = true; - await returnStreamIterators(); + this._incrementalGraph.abort(); + await this._returnAsyncIterators(); + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors return Promise.reject(error); }; @@ -475,382 +210,172 @@ export class IncrementalPublisher { }; } - private _trigger() { - this._resolve(); - this._reset(); - } - - private _reset() { - // promiseWithResolvers uses void only as a generic type parameter - // see: https://typescript-eslint.io/rules/no-invalid-void-type/ - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - const { promise: signalled, resolve } = promiseWithResolvers(); - this._resolve = resolve; - this._signalled = signalled; - } - - private _introduce(item: SubsequentResultRecord) { - this._pending.add(item); - } - - private _release(item: SubsequentResultRecord): void { - if (this._pending.has(item)) { - this._released.add(item); - this._trigger(); - } - } - - private _push(item: SubsequentResultRecord): void { - this._released.add(item); - this._pending.add(item); - this._trigger(); - } - - private _getIncrementalResult( - completedRecords: ReadonlySet, - ): SubsequentIncrementalExecutionResult | undefined { - const { pending, incremental, completed } = - this._processPending(completedRecords); - - const hasNext = this._pending.size > 0; - if (incremental.length === 0 && completed.length === 0 && hasNext) { - return undefined; - } - - const result: SubsequentIncrementalExecutionResult = { hasNext }; - if (pending.length) { - result.pending = pending; - } - if (incremental.length) { - result.incremental = incremental; - } - if (completed.length) { - result.completed = completed; + private _handleCompletedIncrementalData( + completedIncrementalData: IncrementalDataRecordResult, + context: SubsequentIncrementalExecutionResultContext, + ): void { + if (isCompletedExecutionGroup(completedIncrementalData)) { + this._handleCompletedExecutionGroup(completedIncrementalData, context); + } else { + this._handleCompletedStreamItems(completedIncrementalData, context); } - - return result; } - private _processPending( - completedRecords: ReadonlySet, - ): IncrementalUpdate { - const newPendingSources = new Set(); - const incrementalResults: Array = []; - const completedResults: Array = []; - for (const subsequentResultRecord of completedRecords) { - for (const child of subsequentResultRecord.children) { - if (child.filtered) { - continue; - } - const pendingSource = isStreamItemsRecord(child) - ? child.streamRecord - : child; - if (!pendingSource.pendingSent) { - newPendingSources.add(pendingSource); - } - this._publish(child); - } - if (isStreamItemsRecord(subsequentResultRecord)) { - if (subsequentResultRecord.isFinalRecord) { - newPendingSources.delete(subsequentResultRecord.streamRecord); - completedResults.push( - this._completedRecordToResult(subsequentResultRecord.streamRecord), - ); - } - if (subsequentResultRecord.isCompletedAsyncIterator) { - // async iterable resolver just finished but there may be pending payloads - continue; - } - if (subsequentResultRecord.streamRecord.errors.length > 0) { - continue; - } - const incrementalResult: IncrementalStreamResult = { - // safe because `items` is always defined when the record is completed - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - items: subsequentResultRecord.items!, - // safe because `id` is defined once the stream has been released as pending - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - id: subsequentResultRecord.streamRecord.id!, - }; - if (subsequentResultRecord.errors.length > 0) { - incrementalResult.errors = subsequentResultRecord.errors; - } - incrementalResults.push(incrementalResult); - } else { - newPendingSources.delete(subsequentResultRecord); - completedResults.push( - this._completedRecordToResult(subsequentResultRecord), - ); - if (subsequentResultRecord.errors.length > 0) { + private _handleCompletedExecutionGroup( + completedExecutionGroup: CompletedExecutionGroup, + context: SubsequentIncrementalExecutionResultContext, + ): void { + if (isFailedExecutionGroup(completedExecutionGroup)) { + for (const deferredFragmentRecord of completedExecutionGroup + .pendingExecutionGroup.deferredFragmentRecords) { + const id = deferredFragmentRecord.id; + if ( + !this._incrementalGraph.removeDeferredFragment(deferredFragmentRecord) + ) { + // This can occur if multiple deferred grouped field sets error for a fragment. continue; } - for (const deferredGroupedFieldSetRecord of subsequentResultRecord.deferredGroupedFieldSetRecords) { - if (!deferredGroupedFieldSetRecord.sent) { - deferredGroupedFieldSetRecord.sent = true; - const incrementalResult: IncrementalDeferResult = - this._getIncrementalDeferResult(deferredGroupedFieldSetRecord); - if (deferredGroupedFieldSetRecord.errors.length > 0) { - incrementalResult.errors = deferredGroupedFieldSetRecord.errors; - } - incrementalResults.push(incrementalResult); - } - } + invariant(id !== undefined); + context.completed.push({ + id, + errors: completedExecutionGroup.errors, + }); } + return; } - return { - pending: this._pendingSourcesToResults(newPendingSources), - incremental: incrementalResults, - completed: completedResults, - }; - } + this._incrementalGraph.addCompletedSuccessfulExecutionGroup( + completedExecutionGroup, + ); - private _getIncrementalDeferResult( - deferredGroupedFieldSetRecord: DeferredGroupedFieldSetRecord, - ): IncrementalDeferResult { - const { data, deferredFragmentRecords } = deferredGroupedFieldSetRecord; - let maxLength: number | undefined; - let idWithLongestPath: string | undefined; - for (const deferredFragmentRecord of deferredFragmentRecords) { - const id = deferredFragmentRecord.id; - if (id === undefined) { + for (const deferredFragmentRecord of completedExecutionGroup + .pendingExecutionGroup.deferredFragmentRecords) { + const completion = this._incrementalGraph.completeDeferredFragment( + deferredFragmentRecord, + ); + if (completion === undefined) { continue; } - const length = deferredFragmentRecord.path.length; - if (maxLength === undefined || length > maxLength) { - maxLength = length; - idWithLongestPath = id; + const id = deferredFragmentRecord.id; + invariant(id !== undefined); + const incremental = context.incremental; + const { newRootNodes, successfulExecutionGroups } = completion; + context.pending.push(...this._toPendingResults(newRootNodes)); + for (const successfulExecutionGroup of successfulExecutionGroups) { + const { bestId, subPath } = this._getBestIdAndSubPath( + id, + deferredFragmentRecord, + successfulExecutionGroup, + ); + const incrementalEntry: IncrementalDeferResult = { + ...successfulExecutionGroup.result, + id: bestId, + }; + if (subPath !== undefined) { + incrementalEntry.subPath = subPath; + } + incremental.push(incrementalEntry); } + context.completed.push({ id }); } - const subPath = deferredGroupedFieldSetRecord.path.slice(maxLength); - const incrementalDeferResult: IncrementalDeferResult = { - // safe because `data``is always defined when the record is completed - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - data: data!, - // safe because `id` is always defined once the fragment has been released - // as pending and at least one fragment has been completed, so must have been - // released as pending - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - id: idWithLongestPath!, - }; - - if (subPath.length > 0) { - incrementalDeferResult.subPath = subPath; - } - - return incrementalDeferResult; - } - - private _completedRecordToResult( - completedRecord: DeferredFragmentRecord | StreamRecord, - ): CompletedResult { - const result: CompletedResult = { - // safe because `id` is defined once the stream has been released as pending - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - id: completedRecord.id!, - }; - if (completedRecord.errors.length > 0) { - result.errors = completedRecord.errors; - } - return result; } - private _publish(subsequentResultRecord: SubsequentResultRecord): void { - if (isStreamItemsRecord(subsequentResultRecord)) { - if (subsequentResultRecord.isCompleted) { - this._push(subsequentResultRecord); - return; + private _handleCompletedStreamItems( + streamItemsResult: StreamItemsResult, + context: SubsequentIncrementalExecutionResultContext, + ): void { + const streamRecord = streamItemsResult.streamRecord; + const id = streamRecord.id; + invariant(id !== undefined); + if (streamItemsResult.errors !== undefined) { + context.completed.push({ + id, + errors: streamItemsResult.errors, + }); + this._incrementalGraph.removeStream(streamRecord); + if (isCancellableStreamRecord(streamRecord)) { + invariant(this._context.cancellableStreams !== undefined); + this._context.cancellableStreams.delete(streamRecord); + streamRecord.earlyReturn().catch(() => { + /* c8 ignore next 1 */ + // ignore error + }); } - - this._introduce(subsequentResultRecord); - return; - } - - if (subsequentResultRecord._pending.size > 0) { - this._introduce(subsequentResultRecord); - } else if ( - subsequentResultRecord.deferredGroupedFieldSetRecords.size > 0 || - subsequentResultRecord.children.size > 0 - ) { - this._push(subsequentResultRecord); - } - } - - private _getChildren( - erroringIncrementalDataRecord: IncrementalDataRecord, - ): ReadonlySet { - const children = new Set(); - if (isDeferredGroupedFieldSetRecord(erroringIncrementalDataRecord)) { - for (const erroringIncrementalResultRecord of erroringIncrementalDataRecord.deferredFragmentRecords) { - for (const child of erroringIncrementalResultRecord.children) { - children.add(child); - } + } else if (streamItemsResult.result === undefined) { + context.completed.push({ id }); + this._incrementalGraph.removeStream(streamRecord); + if (isCancellableStreamRecord(streamRecord)) { + invariant(this._context.cancellableStreams !== undefined); + this._context.cancellableStreams.delete(streamRecord); } } else { - for (const child of erroringIncrementalDataRecord.children) { - children.add(child); + const incrementalEntry: IncrementalStreamResult = { + id, + ...streamItemsResult.result, + }; + + context.incremental.push(incrementalEntry); + + const incrementalDataRecords = streamItemsResult.incrementalDataRecords; + if (incrementalDataRecords !== undefined) { + const newRootNodes = this._incrementalGraph.getNewRootNodes( + incrementalDataRecords, + ); + context.pending.push(...this._toPendingResults(newRootNodes)); } } - return children; } - private _getDescendants( - children: ReadonlySet, - descendants = new Set(), - ): ReadonlySet { - for (const child of children) { - descendants.add(child); - this._getDescendants(child.children, descendants); - } - return descendants; - } + private _getBestIdAndSubPath( + initialId: string, + initialDeferredFragmentRecord: DeferredFragmentRecord, + completedExecutionGroup: CompletedExecutionGroup, + ): { bestId: string; subPath: ReadonlyArray | undefined } { + let maxLength = pathToArray(initialDeferredFragmentRecord.path).length; + let bestId = initialId; - private _nullsChildSubsequentResultRecord( - subsequentResultRecord: SubsequentResultRecord, - nullPath: ReadonlyArray, - ): boolean { - const incrementalDataRecords = isStreamItemsRecord(subsequentResultRecord) - ? [subsequentResultRecord] - : subsequentResultRecord.deferredGroupedFieldSetRecords; - - for (const incrementalDataRecord of incrementalDataRecords) { - if (this._matchesPath(incrementalDataRecord.path, nullPath)) { - return true; + for (const deferredFragmentRecord of completedExecutionGroup + .pendingExecutionGroup.deferredFragmentRecords) { + if (deferredFragmentRecord === initialDeferredFragmentRecord) { + continue; + } + const id = deferredFragmentRecord.id; + // TODO: add test case for when an fragment has not been released, but might be processed for the shortest path. + /* c8 ignore next 3 */ + if (id === undefined) { + continue; + } + const fragmentPath = pathToArray(deferredFragmentRecord.path); + const length = fragmentPath.length; + if (length > maxLength) { + maxLength = length; + bestId = id; } } - - return false; + const subPath = completedExecutionGroup.path.slice(maxLength); + return { + bestId, + subPath: subPath.length > 0 ? subPath : undefined, + }; } - private _matchesPath( - testPath: ReadonlyArray, - basePath: ReadonlyArray, - ): boolean { - for (let i = 0; i < basePath.length; i++) { - if (basePath[i] !== testPath[i]) { - // testPath points to a path unaffected at basePath - return false; + private async _returnAsyncIterators(): Promise { + const cancellableStreams = this._context.cancellableStreams; + if (cancellableStreams === undefined) { + return; + } + const promises: Array> = []; + for (const streamRecord of cancellableStreams) { + if (streamRecord.earlyReturn !== undefined) { + promises.push(streamRecord.earlyReturn()); } } - return true; + await Promise.all(promises); } -} - -function isDeferredGroupedFieldSetRecord( - incrementalDataRecord: unknown, -): incrementalDataRecord is DeferredGroupedFieldSetRecord { - return incrementalDataRecord instanceof DeferredGroupedFieldSetRecord; -} -function isStreamItemsRecord( - subsequentResultRecord: unknown, -): subsequentResultRecord is StreamItemsRecord { - return subsequentResultRecord instanceof StreamItemsRecord; -} - -/** @internal */ -export class InitialResultRecord { - errors: Array; - children: Set; - constructor() { - this.errors = []; - this.children = new Set(); - } -} - -/** @internal */ -export class DeferredGroupedFieldSetRecord { - path: ReadonlyArray; - deferredFragmentRecords: ReadonlyArray; - groupedFieldSet: GroupedFieldSet; - shouldInitiateDefer: boolean; - errors: Array; - data: ObjMap | undefined; - sent: boolean; - - constructor(opts: { - path: Path | undefined; - deferredFragmentRecords: ReadonlyArray; - groupedFieldSet: GroupedFieldSet; - shouldInitiateDefer: boolean; - }) { - this.path = pathToArray(opts.path); - this.deferredFragmentRecords = opts.deferredFragmentRecords; - this.groupedFieldSet = opts.groupedFieldSet; - this.shouldInitiateDefer = opts.shouldInitiateDefer; - this.errors = []; - this.sent = false; - } -} - -/** @internal */ -export class DeferredFragmentRecord { - path: ReadonlyArray; - label: string | undefined; - id: string | undefined; - children: Set; - deferredGroupedFieldSetRecords: Set; - errors: Array; - filtered: boolean; - pendingSent?: boolean; - _pending: Set; - - constructor(opts: { path: Path | undefined; label: string | undefined }) { - this.path = pathToArray(opts.path); - this.label = opts.label; - this.children = new Set(); - this.filtered = false; - this.deferredGroupedFieldSetRecords = new Set(); - this.errors = []; - this._pending = new Set(); - } -} - -/** @internal */ -export class StreamRecord { - label: string | undefined; - path: ReadonlyArray; - id: string | undefined; - errors: Array; - earlyReturn?: (() => Promise) | undefined; - pendingSent?: boolean; - constructor(opts: { - label: string | undefined; - path: Path; - earlyReturn?: (() => Promise) | undefined; - }) { - this.label = opts.label; - this.path = pathToArray(opts.path); - this.errors = []; - this.earlyReturn = opts.earlyReturn; - } -} - -/** @internal */ -export class StreamItemsRecord { - errors: Array; - streamRecord: StreamRecord; - path: ReadonlyArray; - items: Array | undefined; - children: Set; - isFinalRecord?: boolean; - isCompletedAsyncIterator?: boolean; - isCompleted: boolean; - filtered: boolean; - - constructor(opts: { streamRecord: StreamRecord; path: Path | undefined }) { - this.streamRecord = opts.streamRecord; - this.path = pathToArray(opts.path); - this.children = new Set(); - this.errors = []; - this.isCompleted = false; - this.filtered = false; + private async _returnAsyncIteratorsIgnoringErrors(): Promise { + await this._returnAsyncIterators().catch(() => { + // Ignore errors + }); } } - -export type IncrementalDataRecord = - | InitialResultRecord - | DeferredGroupedFieldSetRecord - | StreamItemsRecord; - -type SubsequentResultRecord = DeferredFragmentRecord | StreamItemsRecord; diff --git a/src/execution/__tests__/AbortSignalListener-test.ts b/src/execution/__tests__/AbortSignalListener-test.ts new file mode 100644 index 0000000000..2b2a0e6273 --- /dev/null +++ b/src/execution/__tests__/AbortSignalListener-test.ts @@ -0,0 +1,170 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { expectPromise } from '../../__testUtils__/expectPromise.js'; + +import { + AbortSignalListener, + cancellableIterable, + cancellablePromise, +} from '../AbortSignalListener.js'; + +describe('AbortSignalListener', () => { + it('works to add a listener', () => { + const abortController = new AbortController(); + + const abortSignalListener = new AbortSignalListener(abortController.signal); + + let called = false; + const onAbort = () => { + called = true; + }; + abortSignalListener.add(onAbort); + + abortController.abort(); + + expect(called).to.equal(true); + }); + + it('works to delete a listener', () => { + const abortController = new AbortController(); + + const abortSignalListener = new AbortSignalListener(abortController.signal); + + let called = false; + /* c8 ignore next 3 */ + const onAbort = () => { + called = true; + }; + abortSignalListener.add(onAbort); + abortSignalListener.delete(onAbort); + + abortController.abort(); + + expect(called).to.equal(false); + }); + + it('works to disconnect a listener from the abortSignal', () => { + const abortController = new AbortController(); + + const abortSignalListener = new AbortSignalListener(abortController.signal); + + let called = false; + /* c8 ignore next 3 */ + const onAbort = () => { + called = true; + }; + abortSignalListener.add(onAbort); + + abortSignalListener.disconnect(); + + abortController.abort(); + + expect(called).to.equal(false); + }); +}); + +describe('cancellablePromise', () => { + it('works to cancel an already resolved promise', async () => { + const abortController = new AbortController(); + + const abortSignalListener = new AbortSignalListener(abortController.signal); + + const promise = Promise.resolve(1); + + const withCancellation = cancellablePromise(promise, abortSignalListener); + + abortController.abort(new Error('Cancelled!')); + + await expectPromise(withCancellation).toRejectWith('Cancelled!'); + }); + + it('works to cancel an already resolved promise after abort signal triggered', async () => { + const abortController = new AbortController(); + const abortSignalListener = new AbortSignalListener(abortController.signal); + + abortController.abort(new Error('Cancelled!')); + + const promise = Promise.resolve(1); + + const withCancellation = cancellablePromise(promise, abortSignalListener); + + await expectPromise(withCancellation).toRejectWith('Cancelled!'); + }); + + it('works to cancel a hanging promise', async () => { + const abortController = new AbortController(); + const abortSignalListener = new AbortSignalListener(abortController.signal); + + const promise = new Promise(() => { + /* never resolves */ + }); + + const withCancellation = cancellablePromise(promise, abortSignalListener); + + abortController.abort(new Error('Cancelled!')); + + await expectPromise(withCancellation).toRejectWith('Cancelled!'); + }); + + it('works to cancel a hanging promise created after abort signal triggered', async () => { + const abortController = new AbortController(); + const abortSignalListener = new AbortSignalListener(abortController.signal); + + abortController.abort(new Error('Cancelled!')); + + const promise = new Promise(() => { + /* never resolves */ + }); + + const withCancellation = cancellablePromise(promise, abortSignalListener); + + await expectPromise(withCancellation).toRejectWith('Cancelled!'); + }); +}); + +describe('cancellableAsyncIterable', () => { + it('works to abort a next call', async () => { + const abortController = new AbortController(); + const abortSignalListener = new AbortSignalListener(abortController.signal); + + const asyncIterable = { + [Symbol.asyncIterator]: () => ({ + next: () => Promise.resolve({ value: 1, done: false }), + }), + }; + + const withCancellation = cancellableIterable( + asyncIterable, + abortSignalListener, + ); + + const nextPromise = withCancellation[Symbol.asyncIterator]().next(); + + abortController.abort(new Error('Cancelled!')); + + await expectPromise(nextPromise).toRejectWith('Cancelled!'); + }); + + it('works to abort a next call when already aborted', async () => { + const abortController = new AbortController(); + const abortSignalListener = new AbortSignalListener(abortController.signal); + + abortController.abort(new Error('Cancelled!')); + + const asyncIterable = { + [Symbol.asyncIterator]: () => ({ + next: () => Promise.resolve({ value: 1, done: false }), + }), + }; + + const withCancellation = cancellableIterable( + asyncIterable, + abortSignalListener, + ); + + const nextPromise = withCancellation[Symbol.asyncIterator]().next(); + + await expectPromise(nextPromise).toRejectWith('Cancelled!'); + }); +}); diff --git a/src/execution/__tests__/abstract-test.ts b/src/execution/__tests__/abstract-test.ts index fde551b88d..422f99c0c2 100644 --- a/src/execution/__tests__/abstract-test.ts +++ b/src/execution/__tests__/abstract-test.ts @@ -633,15 +633,7 @@ describe('Execute: Handles execution of abstract types', () => { // @ts-expect-error assertInterfaceType(schema.getType('Pet')).resolveType = () => []; expectError({ forTypeName: undefined }).toEqual( - 'Abstract type "Pet" must resolve to an Object type at runtime for field "Query.pet" with value { __typename: undefined }, received "[]".', - ); - - // FIXME: workaround since we can't inject resolveType into SDL - // @ts-expect-error - assertInterfaceType(schema.getType('Pet')).resolveType = () => - schema.getType('Cat'); - expectError({ forTypeName: undefined }).toEqual( - 'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.', + 'Abstract type "Pet" must resolve to an Object type at runtime for field "Query.pet" with value { __typename: undefined }, received "[]", which is not a valid Object type name.', ); }); }); diff --git a/src/execution/__tests__/cancellation-test.ts b/src/execution/__tests__/cancellation-test.ts new file mode 100644 index 0000000000..3c2f41553f --- /dev/null +++ b/src/execution/__tests__/cancellation-test.ts @@ -0,0 +1,948 @@ +import { assert, expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { expectJSON } from '../../__testUtils__/expectJSON.js'; +import { expectPromise } from '../../__testUtils__/expectPromise.js'; +import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js'; + +import { isAsyncIterable } from '../../jsutils/isAsyncIterable.js'; + +import type { DocumentNode } from '../../language/ast.js'; +import { parse } from '../../language/parser.js'; + +import { buildSchema } from '../../utilities/buildASTSchema.js'; + +import { + execute, + experimentalExecuteIncrementally, + subscribe, +} from '../execute.js'; +import type { + InitialIncrementalExecutionResult, + SubsequentIncrementalExecutionResult, +} from '../types.js'; + +async function complete( + document: DocumentNode, + rootValue: unknown, + abortSignal: AbortSignal, +) { + const result = await experimentalExecuteIncrementally({ + schema, + document, + rootValue, + abortSignal, + }); + + if ('initialResult' in result) { + const results: Array< + InitialIncrementalExecutionResult | SubsequentIncrementalExecutionResult + > = [result.initialResult]; + for await (const patch of result.subsequentResults) { + results.push(patch); + } + return results; + } +} + +const schema = buildSchema(` + type Todo { + id: ID + items: [String] + author: User + } + + type User { + id: ID + name: String + } + + type Query { + todo: Todo + nonNullableTodo: Todo! + } + + type Mutation { + foo: String + bar: String + } + + type Subscription { + foo: String + } +`); + +describe('Execute: Cancellation', () => { + it('should stop the execution when aborted during object field completion', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: async () => + Promise.resolve({ + id: '1', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expect(result.errors?.[0].originalError?.name).to.equal('AbortError'); + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should provide access to the abort signal within resolvers', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + } + } + `); + + const cancellableAsyncFn = async (abortSignal: AbortSignal) => { + await resolveOnNextTick(); + abortSignal.throwIfAborted(); + }; + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: { + id: (_args: any, _context: any, _info: any, signal: AbortSignal) => + cancellableAsyncFn(signal), + }, + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + todo: { + id: null, + }, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo', 'id'], + locations: [{ line: 4, column: 11 }], + }, + ], + }); + }); + + it('should stop the execution when aborted during object field completion with a custom error', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: async () => + Promise.resolve({ + id: '1', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + }); + + const customError = new Error('Custom abort error'); + abortController.abort(customError); + + const result = await resultPromise; + + expect(result.errors?.[0].originalError).to.equal(customError); + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'Custom abort error', + path: ['todo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should stop the execution when aborted during object field completion with a custom string', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: async () => + Promise.resolve({ + id: '1', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + }); + + abortController.abort('Custom abort error message'); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'Unexpected error value: "Custom abort error message"', + path: ['todo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should stop the execution when aborted during nested object field completion', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: { + id: '1', + /* c8 ignore next 3 */ + author: async () => + Promise.resolve(() => expect.fail('Should not be called')), + }, + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + todo: { + id: '1', + author: null, + }, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo', 'author'], + locations: [{ line: 5, column: 11 }], + }, + ], + }); + }); + + it('should stop the execution when aborted despite a hanging resolver', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: () => + new Promise(() => { + /* will never resolve */ + }), + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expect(result.errors?.[0].originalError?.name).to.equal('AbortError'); + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should stop the execution when aborted despite a hanging item', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + items + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: () => ({ + id: '1', + items: [ + new Promise(() => { + /* will never resolve */ + }), + ], + }), + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expect(result.errors?.[0].originalError?.name).to.equal('AbortError'); + + expectJSON(result).toDeepEqual({ + data: { + todo: { + id: '1', + items: [null], + }, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo', 'items', 0], + locations: [{ line: 5, column: 11 }], + }, + ], + }); + }); + + it('should stop the execution when aborted despite a hanging async item', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + items + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: () => ({ + id: '1', + async *items() { + yield await new Promise(() => { + /* will never resolve */ + }); /* c8 ignore start */ + } /* c8 ignore stop */, + }), + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expect(result.errors?.[0].originalError?.name).to.equal('AbortError'); + + expectJSON(result).toDeepEqual({ + data: { + todo: { + id: '1', + items: null, + }, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo', 'items'], + locations: [{ line: 5, column: 11 }], + }, + ], + }); + }); + + it('should stop the execution when aborted with proper null bubbling', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + nonNullableTodo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + nonNullableTodo: async () => + Promise.resolve({ + id: '1', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + }); + + abortController.abort(); + + const result = await resultPromise; + + expect(result.errors?.[0].originalError?.name).to.equal('AbortError'); + + expectJSON(result).toDeepEqual({ + data: null, + errors: [ + { + message: 'This operation was aborted', + path: ['nonNullableTodo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should stop deferred execution when aborted', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + ... on Todo @defer { + author { + id + } + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + rootValue: { + todo: async () => + Promise.resolve({ + id: '1', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + abortSignal: abortController.signal, + }); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should stop deferred execution when aborted mid-execution', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + ... on Query @defer { + todo { + id + author { + id + } + } + } + } + `); + + const resultPromise = complete( + document, + { + todo: async () => + Promise.resolve({ + id: '1', + /* c8 ignore next 2 */ + author: async () => + Promise.resolve(() => expect.fail('Should not be called')), + }), + }, + abortController.signal, + ); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual([ + { + data: {}, + pending: [{ id: '0', path: [] }], + hasNext: true, + }, + { + incremental: [ + { + data: { + todo: null, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['todo'], + locations: [{ line: 4, column: 11 }], + }, + ], + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + }); + + it('should stop streamed execution when aborted', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + items @stream + } + } + `); + + const resultPromise = complete( + document, + { + todo: { + id: '1', + items: [Promise.resolve('item')], + }, + }, + abortController.signal, + ); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual([ + { + data: { + todo: { + id: '1', + items: [], + }, + }, + pending: [{ id: '0', path: ['todo', 'items'] }], + hasNext: true, + }, + { + incremental: [ + { + items: [null], + errors: [ + { + message: 'This operation was aborted', + path: ['todo', 'items', 0], + locations: [{ line: 5, column: 11 }], + }, + ], + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + }); + + it('should stop streamed execution when aborted', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + items @stream + } + } + `); + + const resultPromise = complete( + document, + { + todo: { + id: '1', + items: [Promise.resolve('item')], + }, + }, + abortController.signal, + ); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual([ + { + data: { + todo: { + id: '1', + items: [], + }, + }, + pending: [{ id: '0', path: ['todo', 'items'] }], + hasNext: true, + }, + { + incremental: [ + { + items: [null], + errors: [ + { + message: 'This operation was aborted', + path: ['todo', 'items', 0], + locations: [{ line: 5, column: 11 }], + }, + ], + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + }); + + it('should stop the execution when aborted mid-mutation', async () => { + const abortController = new AbortController(); + const document = parse(` + mutation { + foo + bar + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + foo: async () => Promise.resolve('baz'), + /* c8 ignore next */ + bar: () => expect.fail('Should not be called'), + }, + }); + + await resolveOnNextTick(); + await resolveOnNextTick(); + await resolveOnNextTick(); + + abortController.abort(); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + foo: 'baz', + bar: null, + }, + errors: [ + { + message: 'This operation was aborted', + path: ['bar'], + locations: [{ line: 4, column: 9 }], + }, + ], + }); + }); + + it('should stop the execution when aborted pre-execute', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + abortController.abort(); + const result = await execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + /* c8 ignore next */ + todo: () => expect.fail('Should not be called'), + }, + }); + + expectJSON(result).toDeepEqual({ + errors: [ + { + message: 'This operation was aborted', + }, + ], + }); + }); + + it('should stop the execution when aborted prior to return of a subscription resolver', async () => { + const abortController = new AbortController(); + const document = parse(` + subscription { + foo + } + `); + + const subscriptionPromise = subscribe({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + foo: async () => + new Promise(() => { + /* will never resolve */ + }), + }, + }); + + abortController.abort(); + + const result = await subscriptionPromise; + + expectJSON(result).toDeepEqual({ + errors: [ + { + message: 'This operation was aborted', + path: ['foo'], + locations: [{ line: 3, column: 9 }], + }, + ], + }); + }); + + it('should successfully wrap the subscription', async () => { + const abortController = new AbortController(); + const document = parse(` + subscription { + foo + } + `); + + async function* foo() { + yield await Promise.resolve({ foo: 'foo' }); + } + + const subscription = await subscribe({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + foo: Promise.resolve(foo()), + }, + }); + + assert(isAsyncIterable(subscription)); + + expectJSON(await subscription.next()).toDeepEqual({ + value: { + data: { + foo: 'foo', + }, + }, + done: false, + }); + + expectJSON(await subscription.next()).toDeepEqual({ + value: undefined, + done: true, + }); + }); + + it('should stop the execution when aborted during subscription', async () => { + const abortController = new AbortController(); + const document = parse(` + subscription { + foo + } + `); + + async function* foo() { + yield await Promise.resolve({ foo: 'foo' }); + } + + const subscription = subscribe({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + foo: foo(), + }, + }); + + assert(isAsyncIterable(subscription)); + + expectJSON(await subscription.next()).toDeepEqual({ + value: { + data: { + foo: 'foo', + }, + }, + done: false, + }); + + abortController.abort(); + + await expectPromise(subscription.next()).toRejectWith( + 'This operation was aborted', + ); + }); + + it('should stop the execution when aborted during subscription returned asynchronously', async () => { + const abortController = new AbortController(); + const document = parse(` + subscription { + foo + } + `); + + async function* foo() { + yield await Promise.resolve({ foo: 'foo' }); + } + + const subscription = await subscribe({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + foo: Promise.resolve(foo()), + }, + }); + + assert(isAsyncIterable(subscription)); + + expectJSON(await subscription.next()).toDeepEqual({ + value: { + data: { + foo: 'foo', + }, + }, + done: false, + }); + + abortController.abort(); + + await expectPromise(subscription.next()).toRejectWith( + 'This operation was aborted', + ); + }); +}); diff --git a/src/execution/__tests__/defer-test.ts b/src/execution/__tests__/defer-test.ts index 261db67df9..97dcfeceb6 100644 --- a/src/execution/__tests__/defer-test.ts +++ b/src/execution/__tests__/defer-test.ts @@ -1,10 +1,12 @@ -import { expect } from 'chai'; +import { assert, expect } from 'chai'; import { describe, it } from 'mocha'; import { expectJSON } from '../../__testUtils__/expectJSON.js'; import { expectPromise } from '../../__testUtils__/expectPromise.js'; import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js'; +import { promiseWithResolvers } from '../../jsutils/promiseWithResolvers.js'; + import type { DocumentNode } from '../../language/ast.js'; import { parse } from '../../language/parser.js'; @@ -20,7 +22,7 @@ import { execute, experimentalExecuteIncrementally } from '../execute.js'; import type { InitialIncrementalExecutionResult, SubsequentIncrementalExecutionResult, -} from '../IncrementalPublisher.js'; +} from '../types.js'; const friendType = new GraphQLObjectType({ fields: { @@ -135,11 +137,16 @@ const query = new GraphQLObjectType({ const schema = new GraphQLSchema({ query }); -async function complete(document: DocumentNode, rootValue: unknown = { hero }) { +async function complete( + document: DocumentNode, + rootValue: unknown = { hero }, + enableEarlyExecution = false, +) { const result = await experimentalExecuteIncrementally({ schema, document, rootValue, + enableEarlyExecution, }); if ('initialResult' in result) { @@ -247,6 +254,118 @@ describe('Execute: defer directive', () => { }, ]); }); + it('Does not execute deferred fragments early when not specified', async () => { + const document = parse(` + query HeroNameQuery { + hero { + id + ...NameFragment @defer + } + } + fragment NameFragment on Hero { + name + } + `); + const order: Array = []; + const result = await complete(document, { + hero: { + ...hero, + id: async () => { + await resolveOnNextTick(); + await resolveOnNextTick(); + order.push('slow-id'); + return hero.id; + }, + name: () => { + order.push('fast-name'); + return hero.name; + }, + }, + }); + + expectJSON(result).toDeepEqual([ + { + data: { + hero: { + id: '1', + }, + }, + pending: [{ id: '0', path: ['hero'] }], + hasNext: true, + }, + { + incremental: [ + { + data: { + name: 'Luke', + }, + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + expect(order).to.deep.equal(['slow-id', 'fast-name']); + }); + it('Does execute deferred fragments early when specified', async () => { + const document = parse(` + query HeroNameQuery { + hero { + id + ...NameFragment @defer + } + } + fragment NameFragment on Hero { + name + } + `); + const order: Array = []; + const result = await complete( + document, + { + hero: { + ...hero, + id: async () => { + await resolveOnNextTick(); + await resolveOnNextTick(); + order.push('slow-id'); + return hero.id; + }, + name: () => { + order.push('fast-name'); + return hero.name; + }, + }, + }, + true, + ); + + expectJSON(result).toDeepEqual([ + { + data: { + hero: { + id: '1', + }, + }, + pending: [{ id: '0', path: ['hero'] }], + hasNext: true, + }, + { + incremental: [ + { + data: { + name: 'Luke', + }, + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + expect(order).to.deep.equal(['fast-name', 'slow-id']); + }); it('Can defer fragments on the top level Query field', async () => { const document = parse(` query HeroNameQuery { @@ -355,13 +474,11 @@ describe('Execute: defer directive', () => { data: { hero: {}, }, - pending: [ - { id: '0', path: ['hero'], label: 'DeferTop' }, - { id: '1', path: ['hero'], label: 'DeferNested' }, - ], + pending: [{ id: '0', path: ['hero'], label: 'DeferTop' }], hasNext: true, }, { + pending: [{ id: '1', path: ['hero'], label: 'DeferNested' }], incremental: [ { data: { @@ -472,6 +589,35 @@ describe('Execute: defer directive', () => { }); }); + it('Emits children of empty defer fragments', async () => { + const document = parse(` + query HeroNameQuery { + hero { + ... @defer { + ... @defer { + name + } + } + } + } + `); + const result = await complete(document); + expectJSON(result).toDeepEqual([ + { + data: { + hero: {}, + }, + pending: [{ id: '0', path: ['hero'] }], + hasNext: true, + }, + { + incremental: [{ data: { name: 'Luke' }, id: '0' }], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + }); + it('Can separately emit defer fragments with different labels with varying fields', async () => { const document = parse(` query HeroNameQuery { @@ -641,8 +787,8 @@ describe('Execute: defer directive', () => { hero: {}, }, pending: [ - { id: '0', path: [], label: 'DeferName' }, - { id: '1', path: ['hero'], label: 'DeferID' }, + { id: '0', path: ['hero'], label: 'DeferID' }, + { id: '1', path: [], label: 'DeferName' }, ], hasNext: true, }, @@ -652,17 +798,17 @@ describe('Execute: defer directive', () => { data: { id: '1', }, - id: '1', + id: '0', }, { data: { name: 'Luke', }, - id: '0', + id: '1', subPath: ['hero'], }, ], - completed: [{ id: '1' }, { id: '0' }], + completed: [{ id: '0' }, { id: '1' }], hasNext: false, }, ]); @@ -699,12 +845,6 @@ describe('Execute: defer directive', () => { }, id: '0', }, - ], - completed: [{ id: '0' }], - hasNext: true, - }, - { - incremental: [ { data: { id: '1', @@ -712,12 +852,259 @@ describe('Execute: defer directive', () => { id: '1', }, ], - completed: [{ id: '1' }], + completed: [{ id: '0' }, { id: '1' }], hasNext: false, }, ]); }); + it('Initiates deferred grouped field sets only if they have been released as pending', async () => { + const document = parse(` + query { + ... @defer { + a { + ... @defer { + b { + c { d } + } + } + } + } + ... @defer { + a { + someField + ... @defer { + b { + e { f } + } + } + } + } + } + `); + + const { promise: slowFieldPromise, resolve: resolveSlowField } = + promiseWithResolvers(); + let cResolverCalled = false; + let eResolverCalled = false; + const executeResult = experimentalExecuteIncrementally({ + schema, + document, + rootValue: { + a: { + someField: slowFieldPromise, + b: { + c: () => { + cResolverCalled = true; + return { d: 'd' }; + }, + e: () => { + eResolverCalled = true; + return { f: 'f' }; + }, + }, + }, + }, + enableEarlyExecution: false, + }); + + assert('initialResult' in executeResult); + + const result1 = executeResult.initialResult; + expectJSON(result1).toDeepEqual({ + data: {}, + pending: [ + { id: '0', path: [] }, + { id: '1', path: [] }, + ], + hasNext: true, + }); + + const iterator = executeResult.subsequentResults[Symbol.asyncIterator](); + + expect(cResolverCalled).to.equal(false); + expect(eResolverCalled).to.equal(false); + + const result2 = await iterator.next(); + expectJSON(result2).toDeepEqual({ + value: { + pending: [{ id: '2', path: ['a'] }], + incremental: [ + { + data: { a: {} }, + id: '0', + }, + { + data: { b: {} }, + id: '2', + }, + { + data: { c: { d: 'd' } }, + id: '2', + subPath: ['b'], + }, + ], + completed: [{ id: '0' }, { id: '2' }], + hasNext: true, + }, + done: false, + }); + + expect(cResolverCalled).to.equal(true); + expect(eResolverCalled).to.equal(false); + + resolveSlowField('someField'); + + const result3 = await iterator.next(); + expectJSON(result3).toDeepEqual({ + value: { + pending: [{ id: '3', path: ['a'] }], + incremental: [ + { + data: { someField: 'someField' }, + id: '1', + subPath: ['a'], + }, + { + data: { e: { f: 'f' } }, + id: '3', + subPath: ['b'], + }, + ], + completed: [{ id: '1' }, { id: '3' }], + hasNext: false, + }, + done: false, + }); + + expect(eResolverCalled).to.equal(true); + + const result4 = await iterator.next(); + expectJSON(result4).toDeepEqual({ + value: undefined, + done: true, + }); + }); + + it('Initiates unique deferred grouped field sets after those that are common to sibling defers', async () => { + const document = parse(` + query { + ... @defer { + a { + ... @defer { + b { + c { d } + } + } + } + } + ... @defer { + a { + ... @defer { + b { + c { d } + e { f } + } + } + } + } + } + `); + + const { promise: cPromise, resolve: resolveC } = + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + promiseWithResolvers(); + let cResolverCalled = false; + let eResolverCalled = false; + const executeResult = experimentalExecuteIncrementally({ + schema, + document, + rootValue: { + a: { + b: { + c: async () => { + cResolverCalled = true; + await cPromise; + return { d: 'd' }; + }, + e: () => { + eResolverCalled = true; + return { f: 'f' }; + }, + }, + }, + }, + enableEarlyExecution: false, + }); + + assert('initialResult' in executeResult); + + const result1 = executeResult.initialResult; + expectJSON(result1).toDeepEqual({ + data: {}, + pending: [ + { id: '0', path: [] }, + { id: '1', path: [] }, + ], + hasNext: true, + }); + + const iterator = executeResult.subsequentResults[Symbol.asyncIterator](); + + expect(cResolverCalled).to.equal(false); + expect(eResolverCalled).to.equal(false); + + const result2 = await iterator.next(); + expectJSON(result2).toDeepEqual({ + value: { + pending: [ + { id: '2', path: ['a'] }, + { id: '3', path: ['a'] }, + ], + incremental: [ + { + data: { a: {} }, + id: '0', + }, + ], + completed: [{ id: '0' }, { id: '1' }], + hasNext: true, + }, + done: false, + }); + + resolveC(); + + expect(cResolverCalled).to.equal(true); + expect(eResolverCalled).to.equal(false); + + const result3 = await iterator.next(); + expectJSON(result3).toDeepEqual({ + value: { + incremental: [ + { + data: { b: { c: { d: 'd' } } }, + id: '2', + }, + { + data: { e: { f: 'f' } }, + id: '3', + subPath: ['b'], + }, + ], + completed: [{ id: '2' }, { id: '3' }], + hasNext: false, + }, + done: false, + }); + + const result4 = await iterator.next(); + expectJSON(result4).toDeepEqual({ + value: undefined, + done: true, + }); + }); + it('Can deduplicate multiple defers on the same object', async () => { const document = parse(` query { @@ -876,12 +1263,6 @@ describe('Execute: defer directive', () => { }, id: '0', }, - ], - completed: [{ id: '0' }], - hasNext: true, - }, - { - incremental: [ { data: { bar: 'bar', @@ -889,7 +1270,7 @@ describe('Execute: defer directive', () => { id: '1', }, ], - completed: [{ id: '1' }], + completed: [{ id: '0' }, { id: '1' }], hasNext: false, }, ]); @@ -950,37 +1331,27 @@ describe('Execute: defer directive', () => { hasNext: true, }, { - pending: [{ id: '1', path: ['hero', 'nestedObject'] }], + pending: [ + { id: '1', path: ['hero', 'nestedObject'] }, + { id: '2', path: ['hero', 'nestedObject', 'deeperObject'] }, + ], incremental: [ { data: { bar: 'bar' }, id: '0', subPath: ['nestedObject', 'deeperObject'], }, - ], - completed: [{ id: '0' }], - hasNext: true, - }, - { - pending: [{ id: '2', path: ['hero', 'nestedObject', 'deeperObject'] }], - incremental: [ { data: { baz: 'baz' }, id: '1', subPath: ['deeperObject'], }, - ], - hasNext: true, - completed: [{ id: '1' }], - }, - { - incremental: [ { data: { bak: 'bak' }, id: '2', }, ], - completed: [{ id: '2' }], + completed: [{ id: '0' }, { id: '1' }, { id: '2' }], hasNext: false, }, ]); @@ -1023,34 +1394,27 @@ describe('Execute: defer directive', () => { }, }, pending: [ - { id: '0', path: ['hero'] }, + { id: '0', path: ['hero', 'nestedObject', 'deeperObject'] }, { id: '1', path: ['hero', 'nestedObject', 'deeperObject'] }, ], hasNext: true, }, { - pending: [{ id: '2', path: ['hero', 'nestedObject', 'deeperObject'] }], incremental: [ { data: { foo: 'foo', }, - id: '1', + id: '0', }, - ], - completed: [{ id: '0' }, { id: '1' }], - hasNext: true, - }, - { - incremental: [ { data: { bar: 'bar', }, - id: '2', + id: '1', }, ], - completed: [{ id: '2' }], + completed: [{ id: '0' }, { id: '1' }], hasNext: false, }, ]); @@ -1106,8 +1470,8 @@ describe('Execute: defer directive', () => { }, }, pending: [ - { id: '0', path: [] }, - { id: '1', path: ['a', 'b'] }, + { id: '0', path: ['a', 'b'] }, + { id: '1', path: [] }, ], hasNext: true, }, @@ -1115,14 +1479,69 @@ describe('Execute: defer directive', () => { incremental: [ { data: { e: { f: 'f' } }, - id: '1', + id: '0', }, { data: { g: { h: 'h' } }, + id: '1', + }, + ], + completed: [{ id: '0' }, { id: '1' }], + hasNext: false, + }, + ]); + }); + + it('Correctly bundles varying subfields into incremental data records unique by defer combination, ignoring fields in a fragment masked by a parent defer', async () => { + const document = parse(` + query HeroNameQuery { + ... @defer { + hero { + id + } + } + ... @defer { + hero { + name + shouldBeWithNameDespiteAdditionalDefer: name + ... @defer { + shouldBeWithNameDespiteAdditionalDefer: name + } + } + } + } + `); + const result = await complete(document); + expectJSON(result).toDeepEqual([ + { + data: {}, + pending: [ + { id: '0', path: [] }, + { id: '1', path: [] }, + ], + hasNext: true, + }, + { + incremental: [ + { + data: { hero: {} }, + id: '0', + }, + { + data: { id: '1' }, id: '0', + subPath: ['hero'], + }, + { + data: { + name: 'Luke', + shouldBeWithNameDespiteAdditionalDefer: 'Luke', + }, + id: '1', + subPath: ['hero'], }, ], - completed: [{ id: '1' }, { id: '0' }], + completed: [{ id: '0' }, { id: '1' }], hasNext: false, }, ]); @@ -1251,6 +1670,7 @@ describe('Execute: defer directive', () => { }, ], completed: [ + { id: '0' }, { id: '1', errors: [ @@ -1262,6 +1682,151 @@ describe('Execute: defer directive', () => { }, ], }, + ], + hasNext: false, + }, + ]); + }); + + it('Handles multiple erroring deferred grouped field sets', async () => { + const document = parse(` + query { + ... @defer { + a { + b { + c { + someError: nonNullErrorField + } + } + } + } + ... @defer { + a { + b { + c { + anotherError: nonNullErrorField + } + } + } + } + } + `); + const result = await complete(document, { + a: { + b: { c: { nonNullErrorField: null } }, + }, + }); + expectJSON(result).toDeepEqual([ + { + data: {}, + pending: [ + { id: '0', path: [] }, + { id: '1', path: [] }, + ], + hasNext: true, + }, + { + completed: [ + { + id: '0', + errors: [ + { + message: + 'Cannot return null for non-nullable field c.nonNullErrorField.', + locations: [{ line: 7, column: 17 }], + path: ['a', 'b', 'c', 'someError'], + }, + ], + }, + { + id: '1', + errors: [ + { + message: + 'Cannot return null for non-nullable field c.nonNullErrorField.', + locations: [{ line: 16, column: 17 }], + path: ['a', 'b', 'c', 'anotherError'], + }, + ], + }, + ], + hasNext: false, + }, + ]); + }); + + it('Handles multiple erroring deferred grouped field sets for the same fragment', async () => { + const document = parse(` + query { + ... @defer { + a { + b { + someC: c { + d: d + } + anotherC: c { + d: d + } + } + } + } + ... @defer { + a { + b { + someC: c { + someError: nonNullErrorField + } + anotherC: c { + anotherError: nonNullErrorField + } + } + } + } + } + `); + const result = await complete(document, { + a: { + b: { c: { d: 'd', nonNullErrorField: null } }, + }, + }); + expectJSON(result).toDeepEqual([ + { + data: {}, + pending: [ + { id: '0', path: [] }, + { id: '1', path: [] }, + ], + hasNext: true, + }, + { + incremental: [ + { + data: { a: { b: { someC: {}, anotherC: {} } } }, + id: '0', + }, + { + data: { d: 'd' }, + id: '0', + subPath: ['a', 'b', 'someC'], + }, + { + data: { d: 'd' }, + id: '0', + subPath: ['a', 'b', 'anotherC'], + }, + ], + completed: [ + { + id: '1', + errors: [ + { + message: + 'Cannot return null for non-nullable field c.nonNullErrorField.', + locations: [{ line: 19, column: 17 }], + path: ['a', 'b', 'someC', 'someError'], + }, + ], + }, { id: '0' }, ], hasNext: false, @@ -1293,20 +1858,24 @@ describe('Execute: defer directive', () => { } } `); - const result = await complete(document, { - a: { - b: { - c: { - d: 'd', - nonNullErrorField: async () => { - await resolveOnNextTick(); - return null; + const result = await complete( + document, + { + a: { + b: { + c: { + d: 'd', + nonNullErrorField: async () => { + await resolveOnNextTick(); + return null; + }, }, }, + someField: 'someField', }, - someField: 'someField', }, - }); + true, + ); expectJSON(result).toDeepEqual([ { data: { @@ -1365,12 +1934,16 @@ describe('Execute: defer directive', () => { } } `); - const result = await complete(document, { - hero: { - ...hero, - nonNullName: () => null, + const result = await complete( + document, + { + hero: { + ...hero, + nonNullName: () => null, + }, }, - }); + true, + ); expectJSON(result).toDeepEqual({ data: { hero: null, @@ -1397,12 +1970,16 @@ describe('Execute: defer directive', () => { } } `); - const result = await complete(document, { - hero: { - ...hero, - nonNullName: () => null, + const result = await complete( + document, + { + hero: { + ...hero, + nonNullName: () => null, + }, }, - }); + true, + ); expectJSON(result).toDeepEqual([ { data: {}, @@ -1853,17 +2430,11 @@ describe('Execute: defer directive', () => { data: { name: 'slow', friends: [{}, {}, {}] }, id: '0', }, - ], - completed: [{ id: '0' }], - hasNext: true, - }, - { - incremental: [ { data: { name: 'Han' }, id: '1' }, { data: { name: 'Leia' }, id: '2' }, { data: { name: 'C-3PO' }, id: '3' }, ], - completed: [{ id: '1' }, { id: '2' }, { id: '3' }], + completed: [{ id: '0' }, { id: '1' }, { id: '2' }, { id: '3' }], hasNext: false, }, ]); @@ -1909,17 +2480,11 @@ describe('Execute: defer directive', () => { }, id: '0', }, - ], - completed: [{ id: '0' }], - hasNext: true, - }, - { - incremental: [ { data: { name: 'Han' }, id: '1' }, { data: { name: 'Leia' }, id: '2' }, { data: { name: 'C-3PO' }, id: '3' }, ], - completed: [{ id: '1' }, { id: '2' }, { id: '3' }], + completed: [{ id: '0' }, { id: '1' }, { id: '2' }, { id: '3' }], hasNext: false, }, ]); diff --git a/src/execution/__tests__/executor-test.ts b/src/execution/__tests__/executor-test.ts index c29b4ae60d..6e72609fec 100644 --- a/src/execution/__tests__/executor-test.ts +++ b/src/execution/__tests__/executor-test.ts @@ -240,7 +240,19 @@ describe('Execute: Handles basic execution tasks', () => { expect(resolvedInfo).to.deep.include({ fieldNodes: [field], path: { prev: undefined, key: 'result', typename: 'Test' }, - variableValues: { var: 'abc' }, + variableValues: { + sources: { + var: { + signature: { + name: 'var', + type: GraphQLString, + default: undefined, + }, + value: 'abc', + }, + }, + coerced: { var: 'abc' }, + }, }); }); @@ -405,7 +417,7 @@ describe('Execute: Handles basic execution tasks', () => { throw new Error('Error getting syncError'); }, syncRawError() { - // eslint-disable-next-line @typescript-eslint/no-throw-literal + // eslint-disable-next-line no-throw-literal, @typescript-eslint/only-throw-error throw 'Error getting syncRawError'; }, syncReturnError() { @@ -428,11 +440,11 @@ describe('Execute: Handles basic execution tasks', () => { ); }, asyncRawReject() { - // eslint-disable-next-line prefer-promise-reject-errors + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors return Promise.reject('Error getting asyncRawReject'); }, asyncEmptyReject() { - // eslint-disable-next-line prefer-promise-reject-errors + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors return Promise.reject(); }, asyncError() { @@ -442,7 +454,7 @@ describe('Execute: Handles basic execution tasks', () => { }, asyncRawError() { return new Promise(() => { - // eslint-disable-next-line @typescript-eslint/no-throw-literal + // eslint-disable-next-line no-throw-literal, @typescript-eslint/only-throw-error throw 'Error getting asyncRawError'; }); }, @@ -635,6 +647,57 @@ describe('Execute: Handles basic execution tasks', () => { expect(isAsyncResolverFinished).to.equal(true); }); + it('handles async bubbling errors combined with non-bubbling errors', async () => { + const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + asyncNonNullError: { + type: new GraphQLNonNull(GraphQLString), + async resolve() { + await resolveOnNextTick(); + return null; + }, + }, + asyncError: { + type: GraphQLString, + async resolve() { + await resolveOnNextTick(); + throw new Error('Oops'); + }, + }, + }, + }), + }); + + // Order is important here, as the nullable error should resolve first + const document = parse(` + { + asyncError + asyncNonNullError + } + `); + + const result = execute({ schema, document }); + + expectJSON(await result).toDeepEqual({ + data: null, + errors: [ + { + message: 'Oops', + locations: [{ line: 3, column: 9 }], + path: ['asyncError'], + }, + { + message: + 'Cannot return null for non-nullable field Query.asyncNonNullError.', + locations: [{ line: 4, column: 9 }], + path: ['asyncNonNullError'], + }, + ], + }); + }); + it('Full response path is included for non-nullable fields', () => { const A: GraphQLObjectType = new GraphQLObjectType({ name: 'A', @@ -1195,10 +1258,10 @@ describe('Execute: Handles basic execution tasks', () => { expect(asyncResult).to.deep.equal(result); }); - it('fails when serialize of custom scalar does not return a value', () => { + it('fails when coerceOutputValue of custom scalar does not return a value', () => { const customScalar = new GraphQLScalarType({ name: 'CustomScalar', - serialize() { + coerceOutputValue() { /* returns nothing */ }, }); @@ -1220,7 +1283,7 @@ describe('Execute: Handles basic execution tasks', () => { errors: [ { message: - 'Expected `CustomScalar.serialize("CUSTOM_VALUE")` to return non-nullable value, returned: undefined', + 'Expected `CustomScalar.coerceOutputValue("CUSTOM_VALUE")` to return non-nullable value, returned: undefined', locations: [{ line: 1, column: 3 }], path: ['customScalar'], }, diff --git a/src/execution/__tests__/lists-test.ts b/src/execution/__tests__/lists-test.ts index 167d580ef5..147520baca 100644 --- a/src/execution/__tests__/lists-test.ts +++ b/src/execution/__tests__/lists-test.ts @@ -1,4 +1,4 @@ -import { expect } from 'chai'; +import { assert, expect } from 'chai'; import { describe, it } from 'mocha'; import { expectJSON } from '../../__testUtils__/expectJSON.js'; @@ -19,7 +19,7 @@ import { GraphQLSchema } from '../../type/schema.js'; import { buildSchema } from '../../utilities/buildASTSchema.js'; import { execute, executeSync } from '../execute.js'; -import type { ExecutionResult } from '../IncrementalPublisher.js'; +import type { ExecutionResult } from '../types.js'; describe('Execute: Accepts any iterable as list value', () => { function complete(rootValue: unknown) { @@ -245,6 +245,34 @@ describe('Execute: Accepts async iterables as list value', () => { errors, }); }); + + it('Returns async iterable when list nulls', async () => { + const values = [1, null, 2]; + let i = 0; + let returned = false; + const listField = { + [Symbol.asyncIterator]: () => ({ + next: () => Promise.resolve({ value: values[i++], done: false }), + return: () => { + returned = true; + return Promise.resolve({ value: undefined, done: true }); + }, + }), + }; + const errors = [ + { + message: 'Cannot return null for non-nullable field Query.listField.', + locations: [{ line: 1, column: 3 }], + path: ['listField', 1], + }, + ]; + + expectJSON(await complete({ listField }, '[Int!]')).toDeepEqual({ + data: { listField: null }, + errors, + }); + assert(returned); + }); }); describe('Execute: Handles list nullability', () => { diff --git a/src/execution/__tests__/mapAsyncIterable-test.ts b/src/execution/__tests__/mapAsyncIterable-test.ts index 0b26ab7327..599e15f05e 100644 --- a/src/execution/__tests__/mapAsyncIterable-test.ts +++ b/src/execution/__tests__/mapAsyncIterable-test.ts @@ -89,6 +89,54 @@ describe('mapAsyncIterable', () => { }); }); + it('calls done when completes', async () => { + async function* source() { + yield 1; + yield 2; + yield 3; + } + + let done = false; + const doubles = mapAsyncIterable( + source(), + (x) => Promise.resolve(x + x), + () => { + done = true; + }, + ); + + expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); + expect(await doubles.next()).to.deep.equal({ value: 4, done: false }); + expect(await doubles.next()).to.deep.equal({ value: 6, done: false }); + expect(done).to.equal(false); + expect(await doubles.next()).to.deep.equal({ + value: undefined, + done: true, + }); + expect(done).to.equal(true); + }); + + it('calls done when completes with error', async () => { + async function* source() { + yield 1; + throw new Error('Oops'); + } + + let done = false; + const doubles = mapAsyncIterable( + source(), + (x) => Promise.resolve(x + x), + () => { + done = true; + }, + ); + + expect(await doubles.next()).to.deep.equal({ value: 2, done: false }); + expect(done).to.equal(false); + await expectPromise(doubles.next()).toRejectWith('Oops'); + expect(done).to.equal(true); + }); + it('allows returning early from mapped async generator', async () => { async function* source() { try { @@ -265,6 +313,7 @@ describe('mapAsyncIterable', () => { await expectPromise(doubles.next()).toRejectWith('Goodbye'); }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters async function testClosesSourceWithMapper(mapper: (value: number) => T) { let didVisitFinally = false; diff --git a/src/execution/__tests__/nonnull-test.ts b/src/execution/__tests__/nonnull-test.ts index 12b223a622..ac92de1a30 100644 --- a/src/execution/__tests__/nonnull-test.ts +++ b/src/execution/__tests__/nonnull-test.ts @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; import { expectJSON } from '../../__testUtils__/expectJSON.js'; +import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js'; import type { PromiseOrValue } from '../../jsutils/PromiseOrValue.js'; @@ -14,7 +15,7 @@ import { GraphQLSchema } from '../../type/schema.js'; import { buildSchema } from '../../utilities/buildASTSchema.js'; import { execute, executeSync } from '../execute.js'; -import type { ExecutionResult } from '../IncrementalPublisher.js'; +import type { ExecutionResult } from '../types.js'; const syncError = new Error('sync'); const syncNonNullError = new Error('syncNonNull'); @@ -526,6 +527,68 @@ describe('Execute: handles non-nullable types', () => { }); }); + describe('cancellation with null bubbling', () => { + function nestedPromise(n: number): string { + return n > 0 ? `promiseNest { ${nestedPromise(n - 1)} }` : 'promise'; + } + + it('returns an single error without cancellation', async () => { + const query = ` + { + promiseNonNull, + ${nestedPromise(4)} + } + `; + + const result = await executeQuery(query, throwingData); + expectJSON(result).toDeepEqual({ + data: null, + errors: [ + // does not include syncNullError because result returns prior to it being added + { + message: 'promiseNonNull', + path: ['promiseNonNull'], + locations: [{ line: 3, column: 11 }], + }, + ], + }); + }); + + it('stops running despite error', async () => { + const query = ` + { + promiseNonNull, + ${nestedPromise(10)} + } + `; + + let counter = 0; + const rootValue = { + ...throwingData, + promiseNest() { + return new Promise((resolve) => { + counter++; + resolve(rootValue); + }); + }, + }; + const result = await executeQuery(query, rootValue); + expectJSON(result).toDeepEqual({ + data: null, + errors: [ + { + message: 'promiseNonNull', + path: ['promiseNonNull'], + locations: [{ line: 3, column: 11 }], + }, + ], + }); + const counterAtExecutionEnd = counter; + await resolveOnNextTick(); + expect(counter).to.equal(counterAtExecutionEnd); + }); + }); + describe('Handles non-null argument', () => { const schemaWithNonNullArg = new GraphQLSchema({ query: new GraphQLObjectType({ @@ -620,7 +683,7 @@ describe('Execute: handles non-nullable types', () => { errors: [ { message: - 'Argument "cannotBeNull" of required type "String!" was not provided.', + 'Argument "Query.withNonNullArg(cannotBeNull:)" of required type "String!" was not provided.', locations: [{ line: 3, column: 13 }], path: ['withNonNullArg'], }, @@ -647,7 +710,7 @@ describe('Execute: handles non-nullable types', () => { errors: [ { message: - 'Argument "cannotBeNull" of non-null type "String!" must not be null.', + 'Argument "Query.withNonNullArg(cannotBeNull:)" has invalid value: Expected value of non-null type "String!" not to be null.', locations: [{ line: 3, column: 42 }], path: ['withNonNullArg'], }, @@ -677,7 +740,7 @@ describe('Execute: handles non-nullable types', () => { errors: [ { message: - 'Argument "cannotBeNull" of required type "String!" was provided the variable "$testVar" which was not provided a runtime value.', + 'Argument "Query.withNonNullArg(cannotBeNull:)" has invalid value: Expected variable "$testVar" provided to type "String!" to provide a runtime value.', locations: [{ line: 3, column: 42 }], path: ['withNonNullArg'], }, @@ -705,7 +768,7 @@ describe('Execute: handles non-nullable types', () => { errors: [ { message: - 'Argument "cannotBeNull" of non-null type "String!" must not be null.', + 'Argument "Query.withNonNullArg(cannotBeNull:)" has invalid value: Expected variable "$testVar" provided to non-null type "String!" not to be null.', locations: [{ line: 3, column: 43 }], path: ['withNonNullArg'], }, diff --git a/src/execution/__tests__/oneof-test.ts b/src/execution/__tests__/oneof-test.ts index af0e0580ab..c010a21b72 100644 --- a/src/execution/__tests__/oneof-test.ts +++ b/src/execution/__tests__/oneof-test.ts @@ -7,7 +7,7 @@ import { parse } from '../../language/parser.js'; import { buildSchema } from '../../utilities/buildASTSchema.js'; import { execute } from '../execute.js'; -import type { ExecutionResult } from '../IncrementalPublisher.js'; +import type { ExecutionResult } from '../types.js'; const schema = buildSchema(` type Query { @@ -30,7 +30,12 @@ function executeQuery( rootValue: unknown, variableValues?: { [variable: string]: unknown }, ): ExecutionResult | Promise { - return execute({ schema, document: parse(query), rootValue, variableValues }); + return execute({ + schema, + document: parse(query, { experimentalFragmentArguments: true }), + rootValue, + variableValues, + }); } describe('Execute: Handles OneOf Input Objects', () => { @@ -83,7 +88,7 @@ describe('Execute: Handles OneOf Input Objects', () => { message: // This type of error would be caught at validation-time // hence the vague error message here. - 'Argument "input" of non-null type "TestInputObject!" must not be null.', + 'Argument "Query.test(input:)" has invalid value: Expected variable "$input" provided to type "TestInputObject!" to provide a runtime value.', path: ['test'], }, ], @@ -134,6 +139,28 @@ describe('Execute: Handles OneOf Input Objects', () => { }); }); + it('rejects a variable with a nulled key', () => { + const query = ` + query ($input: TestInputObject!) { + test(input: $input) { + a + b + } + } + `; + const result = executeQuery(query, rootValue, { input: { a: null } }); + + expectJSON(result).toDeepEqual({ + errors: [ + { + message: + 'Variable "$input" has invalid value: Field "a" for OneOf type "TestInputObject" must be non-null.', + locations: [{ line: 2, column: 16 }], + }, + ], + }); + }); + it('rejects a variable with multiple non-null keys', () => { const query = ` query ($input: TestInputObject!) { @@ -152,7 +179,7 @@ describe('Execute: Handles OneOf Input Objects', () => { { locations: [{ column: 16, line: 2 }], message: - 'Variable "$input" got invalid value { a: "abc", b: 123 }; Exactly one key must be specified for OneOf type "TestInputObject".', + 'Variable "$input" has invalid value: Exactly one key must be specified for OneOf type "TestInputObject".', }, ], }); @@ -176,7 +203,125 @@ describe('Execute: Handles OneOf Input Objects', () => { { locations: [{ column: 16, line: 2 }], message: - 'Variable "$input" got invalid value { a: "abc", b: null }; Exactly one key must be specified for OneOf type "TestInputObject".', + 'Variable "$input" has invalid value: Exactly one key must be specified for OneOf type "TestInputObject".', + }, + ], + }); + }); + + it('errors with nulled variable for field', () => { + const query = ` + query ($a: String) { + test(input: { a: $a }) { + a + b + } + } + `; + const result = executeQuery(query, rootValue, { a: null }); + + expectJSON(result).toDeepEqual({ + data: { + test: null, + }, + errors: [ + { + // A nullable variable in a oneOf field position would be caught at validation-time + // hence the vague error message here. + message: + 'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" not to be null.', + locations: [{ line: 3, column: 23 }], + path: ['test'], + }, + ], + }); + }); + + it('errors with missing variable for field', () => { + const query = ` + query ($a: String) { + test(input: { a: $a }) { + a + b + } + } + `; + const result = executeQuery(query, rootValue); + + expectJSON(result).toDeepEqual({ + data: { + test: null, + }, + errors: [ + { + // A nullable variable in a oneOf field position would be caught at validation-time + // hence the vague error message here. + message: + 'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" to provide a runtime value.', + locations: [{ line: 3, column: 23 }], + path: ['test'], + }, + ], + }); + }); + + it('errors with nulled fragment variable for field', () => { + const query = ` + query { + ...TestFragment(a: null) + } + fragment TestFragment($a: String) on Query { + test(input: { a: $a }) { + a + b + } + } + `; + const result = executeQuery(query, rootValue, { a: null }); + + expectJSON(result).toDeepEqual({ + data: { + test: null, + }, + errors: [ + { + // A nullable variable in a oneOf field position would be caught at validation-time + // hence the vague error message here. + message: + 'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" not to be null.', + locations: [{ line: 6, column: 23 }], + path: ['test'], + }, + ], + }); + }); + + it('errors with missing fragment variable for field', () => { + const query = ` + query { + ...TestFragment + } + fragment TestFragment($a: String) on Query { + test(input: { a: $a }) { + a + b + } + } + `; + const result = executeQuery(query, rootValue); + + expectJSON(result).toDeepEqual({ + data: { + test: null, + }, + errors: [ + { + // A nullable variable in a oneOf field position would be caught at validation-time + // hence the vague error message here. + message: + 'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" to provide a runtime value.', + locations: [{ line: 6, column: 23 }], + path: ['test'], }, ], }); diff --git a/src/execution/__tests__/simplePubSub.ts b/src/execution/__tests__/simplePubSub.ts index f535ac454b..ae5899aff5 100644 --- a/src/execution/__tests__/simplePubSub.ts +++ b/src/execution/__tests__/simplePubSub.ts @@ -3,6 +3,8 @@ import { assert } from 'chai'; /** * Create an AsyncIterator from an EventEmitter. Useful for mocking a * PubSub system for tests. + * + * @internal */ export class SimplePubSub { private _subscribers: Set<(value: T) => void>; @@ -53,6 +55,7 @@ export class SimplePubSub { }, throw(error: unknown) { emptyQueue(); + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors return Promise.reject(error); }, [Symbol.asyncIterator]() { diff --git a/src/execution/__tests__/stream-test.ts b/src/execution/__tests__/stream-test.ts index 6e1928f945..d7bd7a6b48 100644 --- a/src/execution/__tests__/stream-test.ts +++ b/src/execution/__tests__/stream-test.ts @@ -2,6 +2,7 @@ import { assert, expect } from 'chai'; import { describe, it } from 'mocha'; import { expectJSON } from '../../__testUtils__/expectJSON.js'; +import { expectPromise } from '../../__testUtils__/expectPromise.js'; import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js'; import type { PromiseOrValue } from '../../jsutils/PromiseOrValue.js'; @@ -22,7 +23,7 @@ import { experimentalExecuteIncrementally } from '../execute.js'; import type { InitialIncrementalExecutionResult, SubsequentIncrementalExecutionResult, -} from '../IncrementalPublisher.js'; +} from '../types.js'; const friendType = new GraphQLObjectType({ fields: { @@ -84,11 +85,16 @@ const query = new GraphQLObjectType({ const schema = new GraphQLSchema({ query }); -async function complete(document: DocumentNode, rootValue: unknown = {}) { +async function complete( + document: DocumentNode, + rootValue: unknown = {}, + enableEarlyExecution = false, +) { const result = await experimentalExecuteIncrementally({ schema, document, rootValue, + enableEarlyExecution, }); if ('initialResult' in result) { @@ -146,11 +152,7 @@ describe('Execute: stream directive', () => { hasNext: true, }, { - incremental: [{ items: ['banana'], id: '0' }], - hasNext: true, - }, - { - incremental: [{ items: ['coconut'], id: '0' }], + incremental: [{ items: ['banana', 'coconut'], id: '0' }], completed: [{ id: '0' }], hasNext: false, }, @@ -170,15 +172,7 @@ describe('Execute: stream directive', () => { hasNext: true, }, { - incremental: [{ items: ['apple'], id: '0' }], - hasNext: true, - }, - { - incremental: [{ items: ['banana'], id: '0' }], - hasNext: true, - }, - { - incremental: [{ items: ['coconut'], id: '0' }], + incremental: [{ items: ['apple', 'banana', 'coconut'], id: '0' }], completed: [{ id: '0' }], hasNext: false, }, @@ -225,16 +219,7 @@ describe('Execute: stream directive', () => { { incremental: [ { - items: ['banana'], - id: '0', - }, - ], - hasNext: true, - }, - { - incremental: [ - { - items: ['coconut'], + items: ['banana', 'coconut'], id: '0', }, ], @@ -294,16 +279,10 @@ describe('Execute: stream directive', () => { { incremental: [ { - items: [['banana', 'banana', 'banana']], - id: '0', - }, - ], - hasNext: true, - }, - { - incremental: [ - { - items: [['coconut', 'coconut', 'coconut']], + items: [ + ['banana', 'banana', 'banana'], + ['coconut', 'coconut', 'coconut'], + ], id: '0', }, ], @@ -408,6 +387,116 @@ describe('Execute: stream directive', () => { }, ]); }); + it('Does not execute early if not specified', async () => { + const document = parse(` + query { + friendList @stream(initialCount: 0) { + id + } + } + `); + const order: Array = []; + const result = await complete(document, { + friendList: () => + friends.map((f, i) => ({ + id: async () => { + const slowness = 3 - i; + for (let j = 0; j < slowness; j++) { + // eslint-disable-next-line no-await-in-loop + await resolveOnNextTick(); + } + order.push(i); + return f.id; + }, + })), + }); + expectJSON(result).toDeepEqual([ + { + data: { + friendList: [], + }, + pending: [{ id: '0', path: ['friendList'] }], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '1' }], + id: '0', + }, + ], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '2' }], + id: '0', + }, + ], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '3' }], + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + expect(order).to.deep.equal([0, 1, 2]); + }); + it('Executes early if specified', async () => { + const document = parse(` + query { + friendList @stream(initialCount: 0) { + id + } + } + `); + const order: Array = []; + const result = await complete( + document, + { + friendList: () => + friends.map((f, i) => ({ + id: async () => { + const slowness = 3 - i; + for (let j = 0; j < slowness; j++) { + // eslint-disable-next-line no-await-in-loop + await resolveOnNextTick(); + } + order.push(i); + return f.id; + }, + })), + }, + true, + ); + expectJSON(result).toDeepEqual([ + { + data: { + friendList: [], + }, + pending: [{ id: '0', path: ['friendList'] }], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '1' }, { id: '2' }, { id: '3' }], + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + expect(order).to.deep.equal([2, 1, 0]); + }); it('Can stream a field that returns a list with nested promises', async () => { const document = parse(` query { @@ -682,6 +771,128 @@ describe('Execute: stream directive', () => { }, }); }); + it('Does not execute early if not specified, when streaming from an async iterable', async () => { + const document = parse(` + query { + friendList @stream(initialCount: 0) { + id + } + } + `); + const order: Array = []; + // eslint-disable-next-line @typescript-eslint/require-await + const slowFriend = async (n: number) => ({ + id: async () => { + const slowness = (3 - n) * 10; + for (let j = 0; j < slowness; j++) { + // eslint-disable-next-line no-await-in-loop + await resolveOnNextTick(); + } + order.push(n); + return friends[n].id; + }, + }); + const result = await complete(document, { + async *friendList() { + yield await Promise.resolve(slowFriend(0)); + yield await Promise.resolve(slowFriend(1)); + yield await Promise.resolve(slowFriend(2)); + }, + }); + expectJSON(result).toDeepEqual([ + { + data: { + friendList: [], + }, + pending: [{ id: '0', path: ['friendList'] }], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '1' }], + id: '0', + }, + ], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '2' }], + id: '0', + }, + ], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '3' }], + id: '0', + }, + ], + hasNext: true, + }, + { + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + expect(order).to.deep.equal([0, 1, 2]); + }); + it('Executes early if specified when streaming from an async iterable', async () => { + const document = parse(` + query { + friendList @stream(initialCount: 0) { + id + } + } + `); + const order: Array = []; + const slowFriend = (n: number) => ({ + id: async () => { + const slowness = (3 - n) * 10; + for (let j = 0; j < slowness; j++) { + // eslint-disable-next-line no-await-in-loop + await resolveOnNextTick(); + } + order.push(n); + return friends[n].id; + }, + }); + const result = await complete( + document, + { + async *friendList() { + yield await Promise.resolve(slowFriend(0)); + yield await Promise.resolve(slowFriend(1)); + yield await Promise.resolve(slowFriend(2)); + }, + }, + true, + ); + expectJSON(result).toDeepEqual([ + { + data: { + friendList: [], + }, + pending: [{ id: '0', path: ['friendList'] }], + hasNext: true, + }, + { + incremental: [ + { + items: [{ id: '1' }, { id: '2' }, { id: '3' }], + id: '0', + }, + ], + completed: [{ id: '0' }], + hasNext: false, + }, + ]); + expect(order).to.deep.equal([2, 1, 0]); + }); it('Can handle concurrent calls to .next() without waiting', async () => { const document = parse(` query { @@ -811,7 +1022,7 @@ describe('Execute: stream directive', () => { } `); const result = await complete(document, { - nonNullFriendList: () => [friends[0], null], + nonNullFriendList: () => [friends[0], null, friends[1]], }); expectJSON(result).toDeepEqual([ @@ -1178,9 +1389,6 @@ describe('Execute: stream directive', () => { yield await Promise.resolve({ nonNullName: friends[0].name }); yield await Promise.resolve({ nonNullName: () => Promise.reject(new Error('Oops')), - }); - yield await Promise.resolve({ - nonNullName: friends[1].name, }); /* c8 ignore start */ } /* c8 ignore stop */, }); @@ -1235,17 +1443,12 @@ describe('Execute: stream directive', () => { nonNullName: () => Promise.reject(new Error('Oops')), }, }); - case 2: - return Promise.resolve({ - done: false, - value: { nonNullName: friends[1].name }, - }); // Not reached /* c8 ignore next 5 */ - case 3: + case 2: return Promise.resolve({ done: false, - value: { nonNullName: friends[2].name }, + value: { nonNullName: friends[1].name }, }); } }, @@ -1308,17 +1511,12 @@ describe('Execute: stream directive', () => { nonNullName: () => Promise.reject(new Error('Oops')), }, }); - case 2: - return Promise.resolve({ - done: false, - value: { nonNullName: friends[1].name }, - }); // Not reached /* c8 ignore next 5 */ - case 3: + case 2: return Promise.resolve({ done: false, - value: { nonNullName: friends[2].name }, + value: { nonNullName: friends[1].name }, }); } }, @@ -1459,6 +1657,10 @@ describe('Execute: stream directive', () => { }, { incremental: [ + { + items: [{ name: 'Luke' }], + id: '1', + }, { data: { scalarField: null }, id: '0', @@ -1470,10 +1672,6 @@ describe('Execute: stream directive', () => { }, ], }, - { - items: [{ name: 'Luke' }], - id: '1', - }, ], completed: [{ id: '0' }], hasNext: true, @@ -1649,6 +1847,7 @@ describe('Execute: stream directive', () => { }, }, }, + enableEarlyExecution: true, }); assert('initialResult' in executeResult); const iterator = executeResult.subsequentResults[Symbol.asyncIterator](); @@ -1865,6 +2064,7 @@ describe('Execute: stream directive', () => { }, done: false, }); + const result3 = await iterator.next(); expectJSON(result3).toDeepEqual({ value: { @@ -1878,6 +2078,7 @@ describe('Execute: stream directive', () => { }, done: false, }); + const result4 = await iterator.next(); expectJSON(result4).toDeepEqual({ value: { @@ -1891,6 +2092,7 @@ describe('Execute: stream directive', () => { }, done: false, }); + const result5 = await iterator.next(); expectJSON(result5).toDeepEqual({ value: { @@ -1915,7 +2117,7 @@ describe('Execute: stream directive', () => { const document = parse(` query { - friendList @stream(initialCount: 1, label:"stream-label") { + friendList @stream(label:"stream-label") { ...NameFragment @defer(label: "DeferName") @defer(label: "DeferName") id } @@ -1945,12 +2147,9 @@ describe('Execute: stream directive', () => { const result1 = executeResult.initialResult; expectJSON(result1).toDeepEqual({ data: { - friendList: [{ id: '1' }], + friendList: [], }, - pending: [ - { id: '0', path: ['friendList', 0], label: 'DeferName' }, - { id: '1', path: ['friendList'], label: 'stream-label' }, - ], + pending: [{ id: '0', path: ['friendList'], label: 'stream-label' }], hasNext: true, }); @@ -1959,18 +2158,18 @@ describe('Execute: stream directive', () => { const result2 = await result2Promise; expectJSON(result2).toDeepEqual({ value: { - pending: [{ id: '2', path: ['friendList', 1], label: 'DeferName' }], + pending: [{ id: '1', path: ['friendList', 0], label: 'DeferName' }], incremental: [ { - data: { name: 'Luke' }, + items: [{ id: '1' }], id: '0', }, { - items: [{ id: '2' }], + data: { name: 'Luke' }, id: '1', }, ], - completed: [{ id: '0' }], + completed: [{ id: '1' }], hasNext: true, }, done: false, @@ -1981,13 +2180,27 @@ describe('Execute: stream directive', () => { const result3 = await result3Promise; expectJSON(result3).toDeepEqual({ value: { - completed: [{ id: '1' }], + pending: [{ id: '2', path: ['friendList', 1], label: 'DeferName' }], + incremental: [ + { + items: [{ id: '2' }], + id: '0', + }, + ], hasNext: true, }, done: false, }); const result4 = await iterator.next(); expectJSON(result4).toDeepEqual({ + value: { + completed: [{ id: '0' }], + hasNext: true, + }, + done: false, + }); + const result5 = await iterator.next(); + expectJSON(result5).toDeepEqual({ value: { incremental: [ { @@ -2000,8 +2213,8 @@ describe('Execute: stream directive', () => { }, done: false, }); - const result5 = await iterator.next(); - expectJSON(result5).toDeepEqual({ + const result6 = await iterator.next(); + expectJSON(result6).toDeepEqual({ value: undefined, done: true, }); @@ -2060,25 +2273,35 @@ describe('Execute: stream directive', () => { const result2 = await result2Promise; expectJSON(result2).toDeepEqual({ value: { - pending: [{ id: '2', path: ['friendList', 1], label: 'DeferName' }], incremental: [ { data: { name: 'Luke' }, id: '0', }, + ], + completed: [{ id: '0' }], + hasNext: true, + }, + done: false, + }); + + const result3 = await iterator.next(); + expectJSON(result3).toDeepEqual({ + value: { + pending: [{ id: '2', path: ['friendList', 1], label: 'DeferName' }], + incremental: [ { items: [{ id: '2' }], id: '1', }, ], - completed: [{ id: '0' }], hasNext: true, }, done: false, }); - const result3 = await iterator.next(); - expectJSON(result3).toDeepEqual({ + const result4 = await iterator.next(); + expectJSON(result4).toDeepEqual({ value: { incremental: [ { @@ -2091,10 +2314,11 @@ describe('Execute: stream directive', () => { }, done: false, }); - const result4Promise = iterator.next(); + + const result5Promise = iterator.next(); resolveIterableCompletion(null); - const result4 = await result4Promise; - expectJSON(result4).toDeepEqual({ + const result5 = await result5Promise; + expectJSON(result5).toDeepEqual({ value: { completed: [{ id: '1' }], hasNext: false, @@ -2102,24 +2326,20 @@ describe('Execute: stream directive', () => { done: false, }); - const result5 = await iterator.next(); - expectJSON(result5).toDeepEqual({ + const result6 = await iterator.next(); + expectJSON(result6).toDeepEqual({ value: undefined, done: true, }); }); it('Returns underlying async iterables when returned generator is returned', async () => { let returned = false; - let index = 0; const iterable = { [Symbol.asyncIterator]: () => ({ - next: () => { - const friend = friends[index++]; - if (friend == null) { - return Promise.resolve({ done: true, value: undefined }); - } - return Promise.resolve({ done: false, value: friend }); - }, + next: () => + new Promise(() => { + /* never resolves */ + }), return: () => { returned = true; }, @@ -2128,11 +2348,8 @@ describe('Execute: stream directive', () => { const document = parse(` query { - friendList @stream(initialCount: 1) { + friendList @stream(initialCount: 0) { id - ... @defer { - name - } } } `); @@ -2150,21 +2367,16 @@ describe('Execute: stream directive', () => { const result1 = executeResult.initialResult; expectJSON(result1).toDeepEqual({ data: { - friendList: [ - { - id: '1', - }, - ], + friendList: [], }, - pending: [ - { id: '0', path: ['friendList', 0] }, - { id: '1', path: ['friendList'] }, - ], + pending: [{ id: '0', path: ['friendList'] }], hasNext: true, }); + + const result2Promise = iterator.next(); const returnPromise = iterator.return(); - const result2 = await iterator.next(); + const result2 = await result2Promise; expectJSON(result2).toDeepEqual({ done: true, value: undefined, @@ -2289,13 +2501,7 @@ describe('Execute: stream directive', () => { done: true, value: undefined, }); - try { - await throwPromise; /* c8 ignore start */ - // Not reachable, always throws - /* c8 ignore stop */ - } catch (e) { - // ignore error - } + await expectPromise(throwPromise).toRejectWith('bad'); assert(returned); }); }); diff --git a/src/execution/__tests__/subscribe-test.ts b/src/execution/__tests__/subscribe-test.ts index eff5032811..ffa1c85276 100644 --- a/src/execution/__tests__/subscribe-test.ts +++ b/src/execution/__tests__/subscribe-test.ts @@ -21,8 +21,12 @@ import { import { GraphQLSchema } from '../../type/schema.js'; import type { ExecutionArgs } from '../execute.js'; -import { createSourceEventStream, subscribe } from '../execute.js'; -import type { ExecutionResult } from '../IncrementalPublisher.js'; +import { + createSourceEventStream, + executeSubscriptionEvent, + subscribe, +} from '../execute.js'; +import type { ExecutionResult } from '../types.js'; import { SimplePubSub } from './simplePubSub.js'; @@ -335,6 +339,45 @@ describe('Subscription Initialization Phase', () => { }); }); + it('uses a custom default perEventExecutor', async () => { + const schema = new GraphQLSchema({ + query: DummyQueryType, + subscription: new GraphQLObjectType({ + name: 'Subscription', + fields: { + foo: { type: GraphQLString }, + }, + }), + }); + + async function* fooGenerator() { + yield { foo: 'FooValue' }; + } + + let count = 0; + const subscription = subscribe({ + schema, + document: parse('subscription { foo }'), + rootValue: { foo: fooGenerator }, + perEventExecutor: (validatedArgs) => { + count++; + return executeSubscriptionEvent(validatedArgs); + }, + }); + assert(isAsyncIterable(subscription)); + + expect(await subscription.next()).to.deep.equal({ + done: false, + value: { data: { foo: 'FooValue' } }, + }); + + expect(await subscription.next()).to.deep.equal({ + done: true, + value: undefined, + }); + expect(count).to.equal(1); + }); + it('should only resolve the first field of invalid multi-field', async () => { async function* fooGenerator() { yield { foo: 'FooValue' }; @@ -524,7 +567,7 @@ describe('Subscription Initialization Phase', () => { errors: [ { message: - 'Variable "$arg" got invalid value "meow"; Int cannot represent non-integer value: "meow"', + 'Variable "$arg" has invalid value: Int cannot represent non-integer value: "meow"', locations: [{ line: 2, column: 21 }], }, ], diff --git a/src/execution/__tests__/union-interface-test.ts b/src/execution/__tests__/union-interface-test.ts index b7691fa689..6f8408c487 100644 --- a/src/execution/__tests__/union-interface-test.ts +++ b/src/execution/__tests__/union-interface-test.ts @@ -1,6 +1,8 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; +import { expectJSON } from '../../__testUtils__/expectJSON.js'; + import { parse } from '../../language/parser.js'; import { @@ -12,7 +14,7 @@ import { import { GraphQLBoolean, GraphQLString } from '../../type/scalars.js'; import { GraphQLSchema } from '../../type/schema.js'; -import { executeSync } from '../execute.js'; +import { execute, executeSync } from '../execute.js'; class Dog { name: string; @@ -42,19 +44,30 @@ class Cat { } } +class Plant { + name: string; + + constructor(name: string) { + this.name = name; + } +} + class Person { name: string; pets: ReadonlyArray | undefined; friends: ReadonlyArray | undefined; + responsibilities: ReadonlyArray | undefined; constructor( name: string, pets?: ReadonlyArray, friends?: ReadonlyArray, + responsibilities?: ReadonlyArray, ) { this.name = name; this.pets = pets; this.friends = friends; + this.responsibilities = responsibilities; } } @@ -108,6 +121,18 @@ const CatType: GraphQLObjectType = new GraphQLObjectType({ isTypeOf: (value) => value instanceof Cat, }); +const PlantType: GraphQLObjectType = new GraphQLObjectType({ + name: 'Plant', + interfaces: [NamedType], + fields: () => ({ + name: { type: GraphQLString }, + }), + // eslint-disable-next-line @typescript-eslint/require-await + isTypeOf: async () => { + throw new Error('Not sure if this is a plant'); + }, +}); + const PetType = new GraphQLUnionType({ name: 'Pet', types: [DogType, CatType], @@ -124,6 +149,11 @@ const PetType = new GraphQLUnionType({ }, }); +const PetOrPlantType = new GraphQLUnionType({ + name: 'PetOrPlantType', + types: [PlantType, DogType, CatType], +}); + const PersonType: GraphQLObjectType = new GraphQLObjectType({ name: 'Person', interfaces: [NamedType, MammalType, LifeType], @@ -131,6 +161,7 @@ const PersonType: GraphQLObjectType = new GraphQLObjectType({ name: { type: GraphQLString }, pets: { type: new GraphQLList(PetType) }, friends: { type: new GraphQLList(NamedType) }, + responsibilities: { type: new GraphQLList(PetOrPlantType) }, progeny: { type: new GraphQLList(PersonType) }, mother: { type: PersonType }, father: { type: PersonType }, @@ -151,8 +182,14 @@ const odie = new Dog('Odie', true); odie.mother = new Dog("Odie's Mom", true); odie.mother.progeny = [odie]; +const fern = new Plant('Fern'); const liz = new Person('Liz'); -const john = new Person('John', [garfield, odie], [liz, odie]); +const john = new Person( + 'John', + [garfield, odie], + [liz, odie], + [garfield, fern], +); describe('Execute: Union and intersection types', () => { it('can introspect on union and intersection types', () => { @@ -195,7 +232,12 @@ describe('Execute: Union and intersection types', () => { name: 'Named', fields: [{ name: 'name' }], interfaces: [], - possibleTypes: [{ name: 'Dog' }, { name: 'Cat' }, { name: 'Person' }], + possibleTypes: [ + { name: 'Dog' }, + { name: 'Cat' }, + { name: 'Person' }, + { name: 'Plant' }, + ], enumValues: null, inputFields: null, }, @@ -545,4 +587,50 @@ describe('Execute: Union and intersection types', () => { expect(encounteredRootValue).to.equal(rootValue); expect(encounteredContext).to.equal(contextValue); }); + + it('it handles rejections from isTypeOf after after an isTypeOf returns true', async () => { + const document = parse(` + { + responsibilities { + __typename + ... on Dog { + name + barks + } + ... on Cat { + name + meows + } + } + } + `); + + const rootValue = new Person('John', [], [liz], [garfield]); + const contextValue = { authToken: '123abc' }; + + /* c8 ignore next 4 */ + // eslint-disable-next-line no-undef + process.on('unhandledRejection', () => { + expect.fail('Unhandled rejection'); + }); + + const result = await execute({ + schema, + document, + rootValue, + contextValue, + }); + + expectJSON(result).toDeepEqual({ + data: { + responsibilities: [ + { + __typename: 'Cat', + meows: false, + name: 'Garfield', + }, + ], + }, + }); + }); }); diff --git a/src/execution/__tests__/variables-test.ts b/src/execution/__tests__/variables-test.ts index 6e4b39e810..eec35c99bc 100644 --- a/src/execution/__tests__/variables-test.ts +++ b/src/execution/__tests__/variables-test.ts @@ -7,6 +7,7 @@ import { inspect } from '../../jsutils/inspect.js'; import { GraphQLError } from '../../error/GraphQLError.js'; +import { DirectiveLocation } from '../../language/directiveLocation.js'; import { Kind } from '../../language/kinds.js'; import { parse } from '../../language/parser.js'; @@ -22,10 +23,14 @@ import { GraphQLObjectType, GraphQLScalarType, } from '../../type/definition.js'; -import { GraphQLString } from '../../type/scalars.js'; +import { + GraphQLDirective, + GraphQLIncludeDirective, +} from '../../type/directives.js'; +import { GraphQLBoolean, GraphQLString } from '../../type/scalars.js'; import { GraphQLSchema } from '../../type/schema.js'; -import { executeSync } from '../execute.js'; +import { executeSync, experimentalExecuteIncrementally } from '../execute.js'; import { getVariableValues } from '../values.js'; const TestFaultyScalarGraphQLError = new GraphQLError( @@ -39,23 +44,30 @@ const TestFaultyScalarGraphQLError = new GraphQLError( const TestFaultyScalar = new GraphQLScalarType({ name: 'FaultyScalar', - parseValue() { + coerceInputValue() { throw TestFaultyScalarGraphQLError; }, - parseLiteral() { + coerceInputLiteral() { throw TestFaultyScalarGraphQLError; }, }); const TestComplexScalar = new GraphQLScalarType({ name: 'ComplexScalar', - parseValue(value) { - expect(value).to.equal('SerializedValue'); - return 'DeserializedValue'; + coerceInputValue(value) { + expect(value).to.equal('ExternalValue'); + return 'InternalValue'; + }, + coerceInputLiteral(ast) { + expect(ast).to.include({ kind: 'StringValue', value: 'ExternalValue' }); + return 'InternalValue'; }, - parseLiteral(ast) { - expect(ast).to.include({ kind: 'StringValue', value: 'SerializedValue' }); - return 'DeserializedValue'; +}); + +const NestedType: GraphQLObjectType = new GraphQLObjectType({ + name: 'NestedType', + fields: { + echo: fieldWithInputArg({ type: GraphQLString }), }, }); @@ -70,6 +82,15 @@ const TestInputObject = new GraphQLInputObjectType({ }, }); +const TestOneOfInputObject = new GraphQLInputObjectType({ + name: 'TestOneOfInputObject', + fields: { + a: { type: GraphQLString }, + b: { type: GraphQLString }, + }, + isOneOf: true, +}); + const TestNestedInputObject = new GraphQLInputObjectType({ name: 'TestNestedInputObject', fields: { @@ -112,23 +133,29 @@ const TestType = new GraphQLObjectType({ type: new GraphQLNonNull(TestEnum), }), fieldWithObjectInput: fieldWithInputArg({ type: TestInputObject }), + fieldWithOneOfObjectInput: fieldWithInputArg({ + type: TestOneOfInputObject, + }), fieldWithNullableStringInput: fieldWithInputArg({ type: GraphQLString }), fieldWithNonNullableStringInput: fieldWithInputArg({ type: new GraphQLNonNull(GraphQLString), }), fieldWithDefaultArgumentValue: fieldWithInputArg({ type: GraphQLString, - defaultValue: 'Hello World', + default: { value: 'Hello World' }, }), fieldWithNonNullableStringInputAndDefaultArgumentValue: fieldWithInputArg({ type: new GraphQLNonNull(GraphQLString), - defaultValue: 'Hello World', + default: { value: 'Hello World' }, }), fieldWithNestedInputObject: fieldWithInputArg({ type: TestNestedInputObject, - defaultValue: 'Hello World', }), list: fieldWithInputArg({ type: new GraphQLList(GraphQLString) }), + nested: { + type: NestedType, + resolve: () => ({}), + }, nnList: fieldWithInputArg({ type: new GraphQLNonNull(new GraphQLList(GraphQLString)), }), @@ -143,7 +170,30 @@ const TestType = new GraphQLObjectType({ }, }); -const schema = new GraphQLSchema({ query: TestType }); +const schema = new GraphQLSchema({ + query: TestType, + directives: [ + new GraphQLDirective({ + name: 'skip', + description: + 'Directs the executor to skip this field or fragment when the `if` argument is true.', + locations: [ + DirectiveLocation.FIELD, + DirectiveLocation.FRAGMENT_SPREAD, + DirectiveLocation.INLINE_FRAGMENT, + ], + args: { + if: { + type: new GraphQLNonNull(GraphQLBoolean), + description: 'Skipped when true.', + // default values will override operation variables in the setting of defined fragment variables that are not provided + default: { value: true }, + }, + }, + }), + GraphQLIncludeDirective, + ], +}); function executeQuery( query: string, @@ -153,6 +203,14 @@ function executeQuery( return executeSync({ schema, document, variableValues }); } +function executeQueryWithFragmentArguments( + query: string, + variableValues?: { [variable: string]: unknown }, +) { + const document = parse(query, { experimentalFragmentArguments: true }); + return executeSync({ schema, document, variableValues }); +} + describe('Execute: Handles inputs', () => { describe('Handles objects and nullability', () => { describe('using inline structs', () => { @@ -226,7 +284,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Argument "input" has invalid value ["foo", "bar", "baz"].', + 'Argument "TestType.fieldWithObjectInput(input:)" has invalid value: Expected value of type "TestInputObject" to be an object, found: ["foo", "bar", "baz"].', path: ['fieldWithObjectInput'], locations: [{ line: 3, column: 41 }], }, @@ -234,16 +292,16 @@ describe('Execute: Handles inputs', () => { }); }); - it('properly runs parseLiteral on complex scalar types', () => { + it('properly runs coerceInputLiteral on complex scalar types', () => { const result = executeQuery(` { - fieldWithObjectInput(input: {c: "foo", d: "SerializedValue"}) + fieldWithObjectInput(input: {c: "foo", d: "ExternalValue"}) } `); expect(result).to.deep.equal({ data: { - fieldWithObjectInput: '{ c: "foo", d: "DeserializedValue" }', + fieldWithObjectInput: '{ c: "foo", d: "InternalValue" }', }, }); }); @@ -262,9 +320,10 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Argument "input" has invalid value { c: "foo", e: "bar" }.', + 'Argument "TestType.fieldWithObjectInput(input:)" has invalid value at .e: FaultyScalarErrorMessage', path: ['fieldWithObjectInput'], - locations: [{ line: 3, column: 41 }], + locations: [{ line: 3, column: 13 }], + extensions: { code: 'FaultyScalarErrorExtensionCode' }, }, ], }); @@ -400,25 +459,25 @@ describe('Execute: Handles inputs', () => { }); it('executes with complex scalar input', () => { - const params = { input: { c: 'foo', d: 'SerializedValue' } }; + const params = { input: { c: 'foo', d: 'ExternalValue' } }; const result = executeQuery(doc, params); expect(result).to.deep.equal({ data: { - fieldWithObjectInput: '{ c: "foo", d: "DeserializedValue" }', + fieldWithObjectInput: '{ c: "foo", d: "InternalValue" }', }, }); }); it('errors on faulty scalar type input', () => { - const params = { input: { c: 'foo', e: 'SerializedValue' } }; + const params = { input: { c: 'foo', e: 'ExternalValue' } }; const result = executeQuery(doc, params); expectJSON(result).toDeepEqual({ errors: [ { message: - 'Variable "$input" got invalid value "SerializedValue" at "input.e"; FaultyScalarErrorMessage', + 'Variable "$input" has invalid value at .e: Argument "TestType.fieldWithObjectInput(input:)" has invalid value at .e: FaultyScalarErrorMessage', locations: [{ line: 2, column: 16 }], extensions: { code: 'FaultyScalarErrorExtensionCode' }, }, @@ -434,7 +493,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value null at "input.c"; Expected non-nullable type "String!" not to be null.', + 'Variable "$input" has invalid value at .c: Expected value of non-null type "String!" not to be null.', locations: [{ line: 2, column: 16 }], }, ], @@ -448,7 +507,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value "foo bar"; Expected type "TestInputObject" to be an object.', + 'Variable "$input" has invalid value: Expected value of type "TestInputObject" to be an object, found: "foo bar".', locations: [{ line: 2, column: 16 }], }, ], @@ -462,7 +521,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value { a: "foo", b: "bar" }; Field "c" of required type "String!" was not provided.', + 'Variable "$input" has invalid value: Expected value of type "TestInputObject" to include required field "c", found: { a: "foo", b: "bar" }.', locations: [{ line: 2, column: 16 }], }, ], @@ -481,12 +540,12 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value { a: "foo" } at "input.na"; Field "c" of required type "String!" was not provided.', + 'Variable "$input" has invalid value at .na: Expected value of type "TestInputObject" to include required field "c", found: { a: "foo" }.', locations: [{ line: 2, column: 18 }], }, { message: - 'Variable "$input" got invalid value { na: { a: "foo" } }; Field "nb" of required type "String!" was not provided.', + 'Variable "$input" has invalid value: Expected value of type "TestNestedInputObject" to include required field "nb", found: { na: { a: "foo" } }.', locations: [{ line: 2, column: 18 }], }, ], @@ -503,7 +562,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value { a: "foo", b: "bar", c: "baz", extra: "dog" }; Field "extra" is not defined by type "TestInputObject".', + 'Variable "$input" has invalid value: Expected value of type "TestInputObject" not to include unknown field "extra", found: { a: "foo", b: "bar", c: "baz", extra: "dog" }.', locations: [{ line: 2, column: 16 }], }, ], @@ -678,7 +737,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$value" of required type "String!" was not provided.', + 'Variable "$value" has invalid value: Expected a value of non-null type "String!" to be provided.', locations: [{ line: 2, column: 16 }], }, ], @@ -697,7 +756,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$value" of non-null type "String!" must not be null.', + 'Variable "$value" has invalid value: Expected value of non-null type "String!" not to be null.', locations: [{ line: 2, column: 16 }], }, ], @@ -743,7 +802,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Argument "input" of required type "String!" was not provided.', + 'Argument "TestType.fieldWithNonNullableStringInput(input:)" of required type "String!" was not provided.', locations: [{ line: 1, column: 3 }], path: ['fieldWithNonNullableStringInput'], }, @@ -763,7 +822,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$value" got invalid value [1, 2, 3]; String cannot represent a non string value: [1, 2, 3]', + 'Variable "$value" has invalid value: String cannot represent a non string value: [1, 2, 3]', locations: [{ line: 2, column: 16 }], }, ], @@ -791,7 +850,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Argument "input" of required type "String!" was provided the variable "$foo" which was not provided a runtime value.', + 'Argument "TestType.fieldWithNonNullableStringInput(input:)" has invalid value: Expected variable "$foo" provided to type "String!" to provide a runtime value.', locations: [{ line: 3, column: 50 }], path: ['fieldWithNonNullableStringInput'], }, @@ -846,7 +905,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" of non-null type "[String]!" must not be null.', + 'Variable "$input" has invalid value: Expected value of non-null type "[String]!" not to be null.', locations: [{ line: 2, column: 16 }], }, ], @@ -909,7 +968,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value null at "input[1]"; Expected non-nullable type "String!" not to be null.', + 'Variable "$input" has invalid value at [1]: Expected value of non-null type "String!" not to be null.', locations: [{ line: 2, column: 16 }], }, ], @@ -928,7 +987,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" of non-null type "[String!]!" must not be null.', + 'Variable "$input" has invalid value: Expected value of non-null type "[String!]!" not to be null.', locations: [{ line: 2, column: 16 }], }, ], @@ -958,7 +1017,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Variable "$input" got invalid value null at "input[1]"; Expected non-nullable type "String!" not to be null.', + 'Variable "$input" has invalid value at [1]: Expected value of non-null type "String!" not to be null.', locations: [{ line: 2, column: 16 }], }, ], @@ -1042,7 +1101,8 @@ describe('Execute: Handles inputs', () => { }, errors: [ { - message: 'Argument "input" has invalid value WRONG_TYPE.', + message: + 'Argument "TestType.fieldWithDefaultArgumentValue(input:)" has invalid value: String cannot represent a non string value: WRONG_TYPE', locations: [{ line: 3, column: 48 }], path: ['fieldWithDefaultArgumentValue'], }, @@ -1082,7 +1142,7 @@ describe('Execute: Handles inputs', () => { function invalidValueError(value: number, index: number) { return { - message: `Variable "$input" got invalid value ${value} at "input[${index}]"; String cannot represent a non string value: ${value}`, + message: `Variable "$input" has invalid value at [${index}]: String cannot represent a non string value: ${value}`, locations: [{ line: 2, column: 14 }], }; } @@ -1136,4 +1196,368 @@ describe('Execute: Handles inputs', () => { }); }); }); + + describe('using fragment arguments', () => { + it('when there are no fragment arguments', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a + } + fragment a on TestType { + fieldWithNonNullableStringInput(input: "A") + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInput: '"A"', + }, + }); + }); + + it('when a value is required and provided', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: "A") + } + fragment a($value: String!) on TestType { + fieldWithNonNullableStringInput(input: $value) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInput: '"A"', + }, + }); + }); + + it('when a value is required and not provided', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a + } + fragment a($value: String!) on TestType { + fieldWithNullableStringInput(input: $value) + } + `); + + expect(result).to.have.property('errors'); + expect(result.errors).to.have.length(1); + expect(result.errors?.at(0)?.message).to.match( + /Argument "value" of required type "String!"/, + ); + }); + + it('when the definition has a default and is provided', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: "A") + } + fragment a($value: String! = "B") on TestType { + fieldWithNonNullableStringInput(input: $value) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInput: '"A"', + }, + }); + }); + + it('when the definition has a default and is not provided', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a + } + fragment a($value: String! = "B") on TestType { + fieldWithNonNullableStringInput(input: $value) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInput: '"B"', + }, + }); + }); + + it('when a definition has a default, is not provided, and spreads another fragment', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a + } + fragment a($a: String! = "B") on TestType { + ...b(b: $a) + } + fragment b($b: String!) on TestType { + fieldWithNonNullableStringInput(input: $b) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInput: '"B"', + }, + }); + }); + + it('when the definition has a non-nullable default and is provided null', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: null) + } + fragment a($value: String! = "B") on TestType { + fieldWithNullableStringInput(input: $value) + } + `); + + expect(result).to.have.property('errors'); + expect(result.errors).to.have.length(1); + expect(result.errors?.at(0)?.message).to.match( + /Argument "value" has invalid value: Expected value of non-null type "String!" not to be null./, + ); + }); + + it('when the definition has no default and is not provided', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a + } + fragment a($value: String) on TestType { + fieldWithNonNullableStringInputAndDefaultArgumentValue(input: $value) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInputAndDefaultArgumentValue: + '"Hello World"', + }, + }); + }); + + it('when an argument is shadowed by an operation variable', () => { + const result = executeQueryWithFragmentArguments(` + query($x: String! = "A") { + ...a(x: "B") + } + fragment a($x: String) on TestType { + fieldWithNullableStringInput(input: $x) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNullableStringInput: '"B"', + }, + }); + }); + + it('when a nullable argument without a field default is not provided and shadowed by an operation variable', () => { + const result = executeQueryWithFragmentArguments(` + query($x: String = "A") { + ...a + } + fragment a($x: String) on TestType { + fieldWithNullableStringInput(input: $x) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNullableStringInput: null, + }, + }); + }); + + it('when a nullable argument with a field default is not provided and shadowed by an operation variable', () => { + const result = executeQueryWithFragmentArguments(` + query($x: String = "A") { + ...a + } + fragment a($x: String) on TestType { + fieldWithNonNullableStringInputAndDefaultArgumentValue(input: $x) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNonNullableStringInputAndDefaultArgumentValue: + '"Hello World"', + }, + }); + }); + + it('when a fragment-variable is shadowed by an intermediate fragment-spread but defined in the operation-variables', () => { + const result = executeQueryWithFragmentArguments(` + query($x: String = "A") { + ...a + } + fragment a($x: String) on TestType { + ...b + } + + fragment b on TestType { + fieldWithNullableStringInput(input: $x) + } + `); + expect(result).to.deep.equal({ + data: { + fieldWithNullableStringInput: '"A"', + }, + }); + }); + + it('when a fragment is used with different args', () => { + const result = executeQueryWithFragmentArguments(` + query($x: String = "Hello") { + a: nested { + ...a(x: "a") + } + b: nested { + ...a(x: "b", b: true) + } + hello: nested { + ...a(x: $x) + } + } + fragment a($x: String, $b: Boolean = false) on NestedType { + a: echo(input: $x) @skip(if: $b) + b: echo(input: $x) @include(if: $b) + } + `); + expect(result).to.deep.equal({ + data: { + a: { + a: '"a"', + }, + b: { + b: '"b"', + }, + hello: { + a: '"Hello"', + }, + }, + }); + }); + + it('when the argument variable is nested in a complex type', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: "C") + } + fragment a($value: String) on TestType { + list(input: ["A", "B", $value, "D"]) + } + `); + expect(result).to.deep.equal({ + data: { + list: '["A", "B", "C", "D"]', + }, + }); + }); + + it('when argument variables are used recursively', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(aValue: "C") + } + fragment a($aValue: String) on TestType { + ...b(bValue: $aValue) + } + fragment b($bValue: String) on TestType { + list(input: ["A", "B", $bValue, "D"]) + } + `); + expect(result).to.deep.equal({ + data: { + list: '["A", "B", "C", "D"]', + }, + }); + }); + + it('when argument variables with the same name are used directly and recursively', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: "A") + } + fragment a($value: String!) on TestType { + ...b(value: "B") + fieldInFragmentA: fieldWithNonNullableStringInput(input: $value) + } + fragment b($value: String!) on TestType { + fieldInFragmentB: fieldWithNonNullableStringInput(input: $value) + } + `); + expect(result).to.deep.equal({ + data: { + fieldInFragmentA: '"A"', + fieldInFragmentB: '"B"', + }, + }); + }); + + it('when argument passed in as list', () => { + const result = executeQueryWithFragmentArguments(` + query Q($opValue: String = "op") { + ...a(aValue: "A") + } + fragment a($aValue: String, $bValue: String) on TestType { + ...b(aValue: [$aValue, "B"], bValue: [$bValue, $opValue]) + } + fragment b($aValue: [String], $bValue: [String], $cValue: String) on TestType { + aList: list(input: $aValue) + bList: list(input: $bValue) + cList: list(input: [$cValue]) + } + `); + expect(result).to.deep.equal({ + data: { + aList: '["A", "B"]', + bList: '[null, "op"]', + cList: '[null]', + }, + }); + }); + + it('when argument passed to a directive', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: true) + } + fragment a($value: Boolean!) on TestType { + fieldWithNonNullableStringInput @skip(if: $value) + } + `); + expect(result).to.deep.equal({ + data: {}, + }); + }); + + it('when argument passed to a directive on a nested field', () => { + const result = executeQueryWithFragmentArguments(` + query { + ...a(value: true) + } + fragment a($value: Boolean!) on TestType { + nested { echo(input: "echo") @skip(if: $value) } + } + `); + expect(result).to.deep.equal({ + data: { nested: {} }, + }); + }); + + it('when a nullable argument to a directive with a field default is not provided and shadowed by an operation variable', () => { + // this test uses the @defer directive and incremental delivery because the `if` argument for skip/include have no field defaults + const document = parse( + ` + query($shouldDefer: Boolean = false) { + ...a + } + fragment a($shouldDefer: Boolean) on TestType { + ... @defer(if: $shouldDefer) { + fieldWithDefaultArgumentValue + } + } + `, + { experimentalFragmentArguments: true }, + ); + const result = experimentalExecuteIncrementally({ schema, document }); + expect(result).to.include.keys('initialResult', 'subsequentResults'); + }); + }); }); diff --git a/src/execution/buildExecutionPlan.ts b/src/execution/buildExecutionPlan.ts new file mode 100644 index 0000000000..f3990f9174 --- /dev/null +++ b/src/execution/buildExecutionPlan.ts @@ -0,0 +1,75 @@ +import { getBySet } from '../jsutils/getBySet.js'; +import { isSameSet } from '../jsutils/isSameSet.js'; + +import type { + DeferUsage, + FieldDetailsList, + GroupedFieldSet, +} from './collectFields.js'; + +export type DeferUsageSet = ReadonlySet; + +export interface ExecutionPlan { + groupedFieldSet: GroupedFieldSet; + newGroupedFieldSets: Map; +} + +export function buildExecutionPlan( + originalGroupedFieldSet: GroupedFieldSet, + parentDeferUsages: DeferUsageSet = new Set(), +): ExecutionPlan { + const groupedFieldSet = new Map(); + const newGroupedFieldSets = new Map< + DeferUsageSet, + Map + >(); + for (const [responseKey, fieldDetailsList] of originalGroupedFieldSet) { + const filteredDeferUsageSet = getFilteredDeferUsageSet(fieldDetailsList); + + if (isSameSet(filteredDeferUsageSet, parentDeferUsages)) { + groupedFieldSet.set(responseKey, fieldDetailsList); + continue; + } + + let newGroupedFieldSet = getBySet( + newGroupedFieldSets, + filteredDeferUsageSet, + ); + if (newGroupedFieldSet === undefined) { + newGroupedFieldSet = new Map(); + newGroupedFieldSets.set(filteredDeferUsageSet, newGroupedFieldSet); + } + newGroupedFieldSet.set(responseKey, fieldDetailsList); + } + + return { + groupedFieldSet, + newGroupedFieldSets, + }; +} + +function getFilteredDeferUsageSet( + fieldDetailsList: FieldDetailsList, +): ReadonlySet { + const filteredDeferUsageSet = new Set(); + for (const fieldDetails of fieldDetailsList) { + const deferUsage = fieldDetails.deferUsage; + if (deferUsage === undefined) { + filteredDeferUsageSet.clear(); + return filteredDeferUsageSet; + } + filteredDeferUsageSet.add(deferUsage); + } + + for (const deferUsage of filteredDeferUsageSet) { + let parentDeferUsage: DeferUsage | undefined = deferUsage.parentDeferUsage; + while (parentDeferUsage !== undefined) { + if (filteredDeferUsageSet.has(parentDeferUsage)) { + filteredDeferUsageSet.delete(deferUsage); + break; + } + parentDeferUsage = parentDeferUsage.parentDeferUsage; + } + } + return filteredDeferUsageSet; +} diff --git a/src/execution/buildFieldPlan.ts b/src/execution/buildFieldPlan.ts deleted file mode 100644 index 7f9f6bc98e..0000000000 --- a/src/execution/buildFieldPlan.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { getBySet } from '../jsutils/getBySet.js'; -import { isSameSet } from '../jsutils/isSameSet.js'; - -import type { DeferUsage, FieldDetails } from './collectFields.js'; - -export type DeferUsageSet = ReadonlySet; - -export interface FieldGroup { - fields: ReadonlyArray; - deferUsages?: DeferUsageSet | undefined; - knownDeferUsages?: DeferUsageSet | undefined; -} - -export type GroupedFieldSet = Map; - -export interface NewGroupedFieldSetDetails { - groupedFieldSet: GroupedFieldSet; - shouldInitiateDefer: boolean; -} - -export function buildFieldPlan( - fields: Map>, - parentDeferUsages: DeferUsageSet = new Set(), - knownDeferUsages: DeferUsageSet = new Set(), -): { - groupedFieldSet: GroupedFieldSet; - newGroupedFieldSetDetailsMap: Map; - newDeferUsages: ReadonlyArray; -} { - const newDeferUsages: Set = new Set(); - const newKnownDeferUsages = new Set(knownDeferUsages); - - const groupedFieldSet = new Map< - string, - { - fields: Array; - deferUsages: DeferUsageSet; - knownDeferUsages: DeferUsageSet; - } - >(); - - const newGroupedFieldSetDetailsMap = new Map< - DeferUsageSet, - { - groupedFieldSet: Map< - string, - { - fields: Array; - deferUsages: DeferUsageSet; - knownDeferUsages: DeferUsageSet; - } - >; - shouldInitiateDefer: boolean; - } - >(); - - const map = new Map< - string, - { - deferUsageSet: DeferUsageSet; - fieldDetailsList: ReadonlyArray; - } - >(); - - for (const [responseKey, fieldDetailsList] of fields) { - const deferUsageSet = new Set(); - let inOriginalResult = false; - for (const fieldDetails of fieldDetailsList) { - const deferUsage = fieldDetails.deferUsage; - if (deferUsage === undefined) { - inOriginalResult = true; - continue; - } - deferUsageSet.add(deferUsage); - if (!knownDeferUsages.has(deferUsage)) { - newDeferUsages.add(deferUsage); - newKnownDeferUsages.add(deferUsage); - } - } - if (inOriginalResult) { - deferUsageSet.clear(); - } else { - deferUsageSet.forEach((deferUsage) => { - const ancestors = getAncestors(deferUsage); - for (const ancestor of ancestors) { - if (deferUsageSet.has(ancestor)) { - deferUsageSet.delete(deferUsage); - } - } - }); - } - map.set(responseKey, { deferUsageSet, fieldDetailsList }); - } - - for (const [responseKey, { deferUsageSet, fieldDetailsList }] of map) { - if (isSameSet(deferUsageSet, parentDeferUsages)) { - let fieldGroup = groupedFieldSet.get(responseKey); - if (fieldGroup === undefined) { - fieldGroup = { - fields: [], - deferUsages: deferUsageSet, - knownDeferUsages: newKnownDeferUsages, - }; - groupedFieldSet.set(responseKey, fieldGroup); - } - fieldGroup.fields.push(...fieldDetailsList); - continue; - } - - let newGroupedFieldSetDetails = getBySet( - newGroupedFieldSetDetailsMap, - deferUsageSet, - ); - let newGroupedFieldSet; - if (newGroupedFieldSetDetails === undefined) { - newGroupedFieldSet = new Map< - string, - { - fields: Array; - deferUsages: DeferUsageSet; - knownDeferUsages: DeferUsageSet; - } - >(); - - newGroupedFieldSetDetails = { - groupedFieldSet: newGroupedFieldSet, - shouldInitiateDefer: Array.from(deferUsageSet).some( - (deferUsage) => !parentDeferUsages.has(deferUsage), - ), - }; - newGroupedFieldSetDetailsMap.set( - deferUsageSet, - newGroupedFieldSetDetails, - ); - } else { - newGroupedFieldSet = newGroupedFieldSetDetails.groupedFieldSet; - } - let fieldGroup = newGroupedFieldSet.get(responseKey); - if (fieldGroup === undefined) { - fieldGroup = { - fields: [], - deferUsages: deferUsageSet, - knownDeferUsages: newKnownDeferUsages, - }; - newGroupedFieldSet.set(responseKey, fieldGroup); - } - fieldGroup.fields.push(...fieldDetailsList); - } - - return { - groupedFieldSet, - newGroupedFieldSetDetailsMap, - newDeferUsages: Array.from(newDeferUsages), - }; -} - -function getAncestors(deferUsage: DeferUsage): ReadonlyArray { - const ancestors: Array = []; - let parentDeferUsage: DeferUsage | undefined = deferUsage.parentDeferUsage; - while (parentDeferUsage !== undefined) { - ancestors.unshift(parentDeferUsage); - parentDeferUsage = parentDeferUsage.parentDeferUsage; - } - return ancestors; -} diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index 7625e1af18..bdca1ba9e0 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -1,5 +1,4 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap.js'; -import { invariant } from '../jsutils/invariant.js'; import type { ObjMap } from '../jsutils/ObjMap.js'; import type { @@ -7,10 +6,8 @@ import type { FragmentDefinitionNode, FragmentSpreadNode, InlineFragmentNode, - OperationDefinitionNode, SelectionSetNode, } from '../language/ast.js'; -import { OperationTypeNode } from '../language/ast.js'; import { Kind } from '../language/kinds.js'; import type { GraphQLObjectType } from '../type/definition.js'; @@ -24,7 +21,9 @@ import type { GraphQLSchema } from '../type/schema.js'; import { typeFromAST } from '../utilities/typeFromAST.js'; -import { getDirectiveValues } from './values.js'; +import type { GraphQLVariableSignature } from './getVariableSignature.js'; +import type { VariableValues } from './values.js'; +import { getDirectiveValues, getFragmentVariableValues } from './values.js'; export interface DeferUsage { label: string | undefined; @@ -33,16 +32,26 @@ export interface DeferUsage { export interface FieldDetails { node: FieldNode; - deferUsage: DeferUsage | undefined; + deferUsage?: DeferUsage | undefined; + fragmentVariableValues?: VariableValues | undefined; +} + +export type FieldDetailsList = ReadonlyArray; + +export type GroupedFieldSet = ReadonlyMap; + +export interface FragmentDetails { + definition: FragmentDefinitionNode; + variableSignatures?: ObjMap | undefined; } interface CollectFieldsContext { schema: GraphQLSchema; - fragments: ObjMap; - variableValues: { [variable: string]: unknown }; - operation: OperationDefinitionNode; + fragments: ObjMap; + variableValues: VariableValues; runtimeType: GraphQLObjectType; visitedFragmentNames: Set; + hideSuggestions: boolean; } /** @@ -54,25 +63,31 @@ interface CollectFieldsContext { * * @internal */ +// eslint-disable-next-line @typescript-eslint/max-params export function collectFields( schema: GraphQLSchema, - fragments: ObjMap, - variableValues: { [variable: string]: unknown }, + fragments: ObjMap, + variableValues: VariableValues, runtimeType: GraphQLObjectType, - operation: OperationDefinitionNode, -): Map> { + selectionSet: SelectionSetNode, + hideSuggestions: boolean, +): { + groupedFieldSet: GroupedFieldSet; + newDeferUsages: ReadonlyArray; +} { const groupedFieldSet = new AccumulatorMap(); + const newDeferUsages: Array = []; const context: CollectFieldsContext = { schema, fragments, variableValues, runtimeType, - operation, visitedFragmentNames: new Set(), + hideSuggestions, }; - collectFieldsImpl(context, operation.selectionSet, groupedFieldSet); - return groupedFieldSet; + collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsages); + return { groupedFieldSet, newDeferUsages }; } /** @@ -85,107 +100,131 @@ export function collectFields( * * @internal */ -// eslint-disable-next-line max-params +// eslint-disable-next-line @typescript-eslint/max-params export function collectSubfields( schema: GraphQLSchema, - fragments: ObjMap, - variableValues: { [variable: string]: unknown }, - operation: OperationDefinitionNode, + fragments: ObjMap, + variableValues: VariableValues, returnType: GraphQLObjectType, - fieldDetails: ReadonlyArray, -): Map> { + fieldDetailsList: FieldDetailsList, + hideSuggestions: boolean, +): { + groupedFieldSet: GroupedFieldSet; + newDeferUsages: ReadonlyArray; +} { const context: CollectFieldsContext = { schema, fragments, variableValues, runtimeType: returnType, - operation, visitedFragmentNames: new Set(), + hideSuggestions, }; const subGroupedFieldSet = new AccumulatorMap(); + const newDeferUsages: Array = []; - for (const fieldDetail of fieldDetails) { - const node = fieldDetail.node; - if (node.selectionSet) { + for (const fieldDetail of fieldDetailsList) { + const selectionSet = fieldDetail.node.selectionSet; + if (selectionSet) { + const { deferUsage, fragmentVariableValues } = fieldDetail; collectFieldsImpl( context, - node.selectionSet, + selectionSet, subGroupedFieldSet, - fieldDetail.deferUsage, + newDeferUsages, + deferUsage, + fragmentVariableValues, ); } } - return subGroupedFieldSet; + return { + groupedFieldSet: subGroupedFieldSet, + newDeferUsages, + }; } +// eslint-disable-next-line @typescript-eslint/max-params function collectFieldsImpl( context: CollectFieldsContext, selectionSet: SelectionSetNode, groupedFieldSet: AccumulatorMap, - parentDeferUsage?: DeferUsage, + newDeferUsages: Array, deferUsage?: DeferUsage, + fragmentVariableValues?: VariableValues, ): void { const { schema, fragments, variableValues, runtimeType, - operation, visitedFragmentNames, + hideSuggestions, } = context; for (const selection of selectionSet.selections) { switch (selection.kind) { case Kind.FIELD: { - if (!shouldIncludeNode(variableValues, selection)) { + if ( + !shouldIncludeNode(selection, variableValues, fragmentVariableValues) + ) { continue; } groupedFieldSet.add(getFieldEntryKey(selection), { node: selection, - deferUsage: deferUsage ?? parentDeferUsage, + deferUsage, + fragmentVariableValues, }); break; } case Kind.INLINE_FRAGMENT: { if ( - !shouldIncludeNode(variableValues, selection) || + !shouldIncludeNode( + selection, + variableValues, + fragmentVariableValues, + ) || !doesFragmentConditionMatch(schema, selection, runtimeType) ) { continue; } const newDeferUsage = getDeferUsage( - operation, variableValues, + fragmentVariableValues, selection, - parentDeferUsage, + deferUsage, ); - collectFieldsImpl( - context, - selection.selectionSet, - groupedFieldSet, - parentDeferUsage, - newDeferUsage ?? deferUsage, - ); + if (!newDeferUsage) { + collectFieldsImpl( + context, + selection.selectionSet, + groupedFieldSet, + newDeferUsages, + deferUsage, + fragmentVariableValues, + ); + } else { + newDeferUsages.push(newDeferUsage); + collectFieldsImpl( + context, + selection.selectionSet, + groupedFieldSet, + newDeferUsages, + newDeferUsage, + fragmentVariableValues, + ); + } break; } case Kind.FRAGMENT_SPREAD: { const fragName = selection.name.value; - const newDeferUsage = getDeferUsage( - operation, - variableValues, - selection, - parentDeferUsage, - ); - if ( - !newDeferUsage && - (visitedFragmentNames.has(fragName) || - !shouldIncludeNode(variableValues, selection)) + visitedFragmentNames.has(fragName) || + !shouldIncludeNode(selection, variableValues, fragmentVariableValues) ) { continue; } @@ -193,21 +232,51 @@ function collectFieldsImpl( const fragment = fragments[fragName]; if ( fragment == null || - !doesFragmentConditionMatch(schema, fragment, runtimeType) + !doesFragmentConditionMatch(schema, fragment.definition, runtimeType) ) { continue; } + + const newDeferUsage = getDeferUsage( + variableValues, + fragmentVariableValues, + selection, + deferUsage, + ); + + const fragmentVariableSignatures = fragment.variableSignatures; + let newFragmentVariableValues: VariableValues | undefined; + if (fragmentVariableSignatures) { + newFragmentVariableValues = getFragmentVariableValues( + selection, + fragmentVariableSignatures, + variableValues, + fragmentVariableValues, + hideSuggestions, + ); + } + if (!newDeferUsage) { visitedFragmentNames.add(fragName); + collectFieldsImpl( + context, + fragment.definition.selectionSet, + groupedFieldSet, + newDeferUsages, + deferUsage, + newFragmentVariableValues, + ); + } else { + newDeferUsages.push(newDeferUsage); + collectFieldsImpl( + context, + fragment.definition.selectionSet, + groupedFieldSet, + newDeferUsages, + newDeferUsage, + newFragmentVariableValues, + ); } - - collectFieldsImpl( - context, - fragment.selectionSet, - groupedFieldSet, - parentDeferUsage, - newDeferUsage ?? deferUsage, - ); break; } } @@ -220,12 +289,17 @@ function collectFieldsImpl( * not disabled by the "if" argument. */ function getDeferUsage( - operation: OperationDefinitionNode, - variableValues: { [variable: string]: unknown }, + variableValues: VariableValues, + fragmentVariableValues: VariableValues | undefined, node: FragmentSpreadNode | InlineFragmentNode, parentDeferUsage: DeferUsage | undefined, ): DeferUsage | undefined { - const defer = getDirectiveValues(GraphQLDeferDirective, node, variableValues); + const defer = getDirectiveValues( + GraphQLDeferDirective, + node, + variableValues, + fragmentVariableValues, + ); if (!defer) { return; @@ -235,11 +309,6 @@ function getDeferUsage( return; } - invariant( - operation.operation !== OperationTypeNode.SUBSCRIPTION, - '`@defer` directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', - ); - return { label: typeof defer.label === 'string' ? defer.label : undefined, parentDeferUsage, @@ -251,10 +320,16 @@ function getDeferUsage( * directives, where `@skip` has higher precedence than `@include`. */ function shouldIncludeNode( - variableValues: { [variable: string]: unknown }, node: FragmentSpreadNode | FieldNode | InlineFragmentNode, + variableValues: VariableValues, + fragmentVariableValues: VariableValues | undefined, ): boolean { - const skip = getDirectiveValues(GraphQLSkipDirective, node, variableValues); + const skip = getDirectiveValues( + GraphQLSkipDirective, + node, + variableValues, + fragmentVariableValues, + ); if (skip?.if === true) { return false; } @@ -263,6 +338,7 @@ function shouldIncludeNode( GraphQLIncludeDirective, node, variableValues, + fragmentVariableValues, ); if (include?.if === false) { return false; diff --git a/src/execution/execute.ts b/src/execution/execute.ts index baf6b41ea1..6fd3fc5b4a 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -1,3 +1,4 @@ +import { BoxedPromiseOrValue } from '../jsutils/BoxedPromiseOrValue.js'; import { inspect } from '../jsutils/inspect.js'; import { invariant } from '../jsutils/invariant.js'; import { isAsyncIterable } from '../jsutils/isAsyncIterable.js'; @@ -47,62 +48,70 @@ import { GraphQLStreamDirective } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; import { assertValidSchema } from '../type/validate.js'; +import { + AbortSignalListener, + cancellableIterable, + cancellablePromise, +} from './AbortSignalListener.js'; +import type { DeferUsageSet, ExecutionPlan } from './buildExecutionPlan.js'; +import { buildExecutionPlan } from './buildExecutionPlan.js'; import type { - DeferUsageSet, - FieldGroup, + DeferUsage, + FieldDetailsList, + FragmentDetails, GroupedFieldSet, - NewGroupedFieldSetDetails, -} from './buildFieldPlan.js'; -import { buildFieldPlan } from './buildFieldPlan.js'; -import type { DeferUsage, FieldDetails } from './collectFields.js'; -import { collectFields, collectSubfields } from './collectFields.js'; +} from './collectFields.js'; +import { + collectFields, + collectSubfields as _collectSubfields, +} from './collectFields.js'; +import { getVariableSignature } from './getVariableSignature.js'; +import { buildIncrementalResponse } from './IncrementalPublisher.js'; +import { mapAsyncIterable } from './mapAsyncIterable.js'; import type { + CancellableStreamRecord, + CompletedExecutionGroup, ExecutionResult, ExperimentalIncrementalExecutionResults, IncrementalDataRecord, -} from './IncrementalPublisher.js'; -import { - DeferredFragmentRecord, - DeferredGroupedFieldSetRecord, - IncrementalPublisher, - InitialResultRecord, - StreamItemsRecord, + PendingExecutionGroup, + StreamItemRecord, + StreamItemResult, StreamRecord, -} from './IncrementalPublisher.js'; -import { mapAsyncIterable } from './mapAsyncIterable.js'; +} from './types.js'; +import { DeferredFragmentRecord } from './types.js'; +import type { VariableValues } from './values.js'; import { + experimentalGetArgumentValues, getArgumentValues, getDirectiveValues, getVariableValues, } from './values.js'; -/* eslint-disable max-params */ +/* eslint-disable @typescript-eslint/max-params */ // This file contains a lot of such errors but we plan to refactor it anyway // so just disable it for entire file. /** - * A memoized function for building subfield plans with regard to the return - * type. Memoizing ensures the subfield plans are not repeatedly calculated, which + * A memoized collection of relevant subfields with regard to the return + * type. Memoizing ensures the subfields are not repeatedly calculated, which * saves overhead when resolving lists of values. */ -const buildSubFieldPlan = memoize3( +const collectSubfields = memoize3( ( - exeContext: ExecutionContext, + validatedExecutionArgs: ValidatedExecutionArgs, returnType: GraphQLObjectType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, ) => { - const subFields = collectSubfields( - exeContext.schema, - exeContext.fragments, - exeContext.variableValues, - exeContext.operation, + const { schema, fragments, variableValues, hideSuggestions } = + validatedExecutionArgs; + return _collectSubfields( + schema, + fragments, + variableValues, returnType, - fieldGroup.fields, - ); - return buildFieldPlan( - subFields, - fieldGroup.deferUsages, - fieldGroup.knownDeferUsages, + fieldDetailsList, + hideSuggestions, ); }, ); @@ -133,17 +142,40 @@ const buildSubFieldPlan = memoize3( * Namely, schema of the type system that is currently executing, * and the fragments defined in the query document */ -export interface ExecutionContext { +export interface ValidatedExecutionArgs { schema: GraphQLSchema; - fragments: ObjMap; + // TODO: consider deprecating/removing fragmentDefinitions if/when fragment + // arguments are officially supported and/or the full fragment details are + // exposed within GraphQLResolveInfo. + fragmentDefinitions: ObjMap; + fragments: ObjMap; rootValue: unknown; contextValue: unknown; operation: OperationDefinitionNode; - variableValues: { [variable: string]: unknown }; + variableValues: VariableValues; fieldResolver: GraphQLFieldResolver; typeResolver: GraphQLTypeResolver; subscribeFieldResolver: GraphQLFieldResolver; - incrementalPublisher: IncrementalPublisher; + perEventExecutor: ( + validatedExecutionArgs: ValidatedExecutionArgs, + ) => PromiseOrValue; + enableEarlyExecution: boolean; + hideSuggestions: boolean; + abortSignal: AbortSignal | undefined; +} + +export interface ExecutionContext { + validatedExecutionArgs: ValidatedExecutionArgs; + errors: Array | undefined; + abortSignalListener: AbortSignalListener | undefined; + completed: boolean; + cancellableStreams: Set | undefined; +} + +interface IncrementalContext { + errors: Array | undefined; + completed: boolean; + deferUsageSet?: DeferUsageSet | undefined; } export interface ExecutionArgs { @@ -156,12 +188,25 @@ export interface ExecutionArgs { fieldResolver?: Maybe>; typeResolver?: Maybe>; subscribeFieldResolver?: Maybe>; + perEventExecutor?: Maybe< + ( + validatedExecutionArgs: ValidatedExecutionArgs, + ) => PromiseOrValue + >; + enableEarlyExecution?: Maybe; + hideSuggestions?: Maybe; + abortSignal?: Maybe; } export interface StreamUsage { label: string | undefined; initialCount: number; - fieldGroup: FieldGroup; + fieldDetailsList: FieldDetailsList; +} + +interface GraphQLWrappedResult { + rawResult: T; + incrementalDataRecords: Array | undefined; } const UNEXPECTED_EXPERIMENTAL_DIRECTIVES = @@ -192,23 +237,28 @@ export function execute(args: ExecutionArgs): PromiseOrValue { } const result = experimentalExecuteIncrementally(args); - if (!isPromise(result)) { - if ('initialResult' in result) { - // This can happen if the operation contains @defer or @stream directives - // and is not validated prior to execution - throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS); - } - return result; - } + // Multiple payloads could be encountered if the operation contains @defer or + // @stream directives and is not validated prior to execution + return ensureSinglePayload(result); +} - return result.then((incrementalResult) => { - if ('initialResult' in incrementalResult) { - // This can happen if the operation contains @defer or @stream directives - // and is not validated prior to execution - throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS); - } - return incrementalResult; - }); +function ensureSinglePayload( + result: PromiseOrValue< + ExecutionResult | ExperimentalIncrementalExecutionResults + >, +): PromiseOrValue { + if (isPromise(result)) { + return result.then((resolved) => { + if ('initialResult' in resolved) { + throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS); + } + return resolved; + }); + } + if ('initialResult' in result) { + throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS); + } + return result; } /** @@ -228,46 +278,144 @@ export function experimentalExecuteIncrementally( ): PromiseOrValue { // If a valid execution context cannot be created due to incorrect arguments, // a "Response" with only errors is returned. - const exeContext = buildExecutionContext(args); + const validatedExecutionArgs = validateExecutionArgs(args); // Return early errors if execution context failed. - if (!('schema' in exeContext)) { - return { errors: exeContext }; + if (!('schema' in validatedExecutionArgs)) { + return { errors: validatedExecutionArgs }; } - return executeImpl(exeContext); + return experimentalExecuteQueryOrMutationOrSubscriptionEvent( + validatedExecutionArgs, + ); } -function executeImpl( - exeContext: ExecutionContext, +/** + * Implements the "Executing operations" section of the spec. + * + * Returns a Promise that will eventually resolve to the data described by + * The "Response" section of the GraphQL specification. + * + * If errors are encountered while executing a GraphQL field, only that + * field and its descendants will be omitted, and sibling fields will still + * be executed. An execution which encounters errors will still result in a + * resolved Promise. + * + * Errors from sub-fields of a NonNull type may propagate to the top level, + * at which point we still log the error and null the parent field, which + * in this case is the entire response. + */ +export function executeQueryOrMutationOrSubscriptionEvent( + validatedExecutionArgs: ValidatedExecutionArgs, +): PromiseOrValue { + const result = experimentalExecuteQueryOrMutationOrSubscriptionEvent( + validatedExecutionArgs, + ); + return ensureSinglePayload(result); +} + +export function experimentalExecuteQueryOrMutationOrSubscriptionEvent( + validatedExecutionArgs: ValidatedExecutionArgs, ): PromiseOrValue { - // Return a Promise that will eventually resolve to the data described by - // The "Response" section of the GraphQL specification. - // - // If errors are encountered while executing a GraphQL field, only that - // field and its descendants will be omitted, and sibling fields will still - // be executed. An execution which encounters errors will still result in a - // resolved Promise. - // - // Errors from sub-fields of a NonNull type may propagate to the top level, - // at which point we still log the error and null the parent field, which - // in this case is the entire response. - const incrementalPublisher = exeContext.incrementalPublisher; - const initialResultRecord = new InitialResultRecord(); + const abortSignal = validatedExecutionArgs.abortSignal; + const exeContext: ExecutionContext = { + validatedExecutionArgs, + errors: undefined, + abortSignalListener: abortSignal + ? new AbortSignalListener(abortSignal) + : undefined, + completed: false, + cancellableStreams: undefined, + }; try { - const data = executeOperation(exeContext, initialResultRecord); - if (isPromise(data)) { - return data.then( - (resolved) => - incrementalPublisher.buildDataResponse(initialResultRecord, resolved), - (error) => - incrementalPublisher.buildErrorResponse(initialResultRecord, error), + const { + schema, + fragments, + rootValue, + operation, + variableValues, + hideSuggestions, + } = validatedExecutionArgs; + + const { operation: operationType, selectionSet } = operation; + + const rootType = schema.getRootType(operationType); + if (rootType == null) { + throw new GraphQLError( + `Schema is not configured to execute ${operationType} operation.`, + { nodes: operation }, + ); + } + + const { groupedFieldSet, newDeferUsages } = collectFields( + schema, + fragments, + variableValues, + rootType, + selectionSet, + hideSuggestions, + ); + + const graphqlWrappedResult = executeRootExecutionPlan( + exeContext, + operation.operation, + rootType, + rootValue, + groupedFieldSet, + newDeferUsages, + ); + + if (isPromise(graphqlWrappedResult)) { + return graphqlWrappedResult.then( + (resolved) => { + exeContext.completed = true; + return buildDataResponse(exeContext, resolved); + }, + (error: unknown) => { + exeContext.completed = true; + exeContext.abortSignalListener?.disconnect(); + return { + data: null, + errors: withError(exeContext.errors, error as GraphQLError), + }; + }, ); } - return incrementalPublisher.buildDataResponse(initialResultRecord, data); + exeContext.completed = true; + return buildDataResponse(exeContext, graphqlWrappedResult); } catch (error) { - return incrementalPublisher.buildErrorResponse(initialResultRecord, error); + exeContext.completed = true; + // TODO: add test case for synchronous null bubbling to root with cancellation + /* c8 ignore next */ + exeContext.abortSignalListener?.disconnect(); + return { data: null, errors: withError(exeContext.errors, error) }; + } +} + +function withError( + errors: Array | undefined, + error: GraphQLError, +): ReadonlyArray { + return errors === undefined ? [error] : [...errors, error]; +} + +function buildDataResponse( + exeContext: ExecutionContext, + graphqlWrappedResult: GraphQLWrappedResult>, +): ExecutionResult | ExperimentalIncrementalExecutionResults { + const { rawResult: data, incrementalDataRecords } = graphqlWrappedResult; + const errors = exeContext.errors; + if (incrementalDataRecords === undefined) { + exeContext.abortSignalListener?.disconnect(); + return errors !== undefined ? { errors, data } : { data }; } + + return buildIncrementalResponse( + exeContext, + data, + errors, + incrementalDataRecords, + ); } /** @@ -295,9 +443,9 @@ export function executeSync(args: ExecutionArgs): ExecutionResult { * TODO: consider no longer exporting this function * @internal */ -export function buildExecutionContext( +export function validateExecutionArgs( args: ExecutionArgs, -): ReadonlyArray | ExecutionContext { +): ReadonlyArray | ValidatedExecutionArgs { const { schema, document, @@ -308,13 +456,22 @@ export function buildExecutionContext( fieldResolver, typeResolver, subscribeFieldResolver, + perEventExecutor, + enableEarlyExecution, + abortSignal, } = args; + if (abortSignal?.aborted) { + return [locatedError(abortSignal.reason, undefined)]; + } + // If the schema used for execution is invalid, throw an error. assertValidSchema(schema); let operation: OperationDefinitionNode | undefined; - const fragments: ObjMap = Object.create(null); + const fragmentDefinitions: ObjMap = + Object.create(null); + const fragments: ObjMap = Object.create(null); for (const definition of document.definitions) { switch (definition.kind) { case Kind.OPERATION_DEFINITION: @@ -331,9 +488,19 @@ export function buildExecutionContext( operation = definition; } break; - case Kind.FRAGMENT_DEFINITION: - fragments[definition.name.value] = definition; + case Kind.FRAGMENT_DEFINITION: { + fragmentDefinitions[definition.name.value] = definition; + let variableSignatures; + if (definition.variableDefinitions) { + variableSignatures = Object.create(null); + for (const varDef of definition.variableDefinitions) { + const signature = getVariableSignature(schema, varDef); + variableSignatures[signature.name] = signature; + } + } + fragments[definition.name.value] = { definition, variableSignatures }; break; + } default: // ignore non-executable definitions } @@ -346,141 +513,150 @@ export function buildExecutionContext( return [new GraphQLError('Must provide an operation.')]; } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const variableDefinitions = operation.variableDefinitions ?? []; + const hideSuggestions = args.hideSuggestions ?? false; - const coercedVariableValues = getVariableValues( + const variableValuesOrErrors = getVariableValues( schema, variableDefinitions, rawVariableValues ?? {}, - { maxErrors: 50 }, + { + maxErrors: 50, + hideSuggestions, + }, ); - if (coercedVariableValues.errors) { - return coercedVariableValues.errors; + if (variableValuesOrErrors.errors) { + return variableValuesOrErrors.errors; } return { schema, + fragmentDefinitions, fragments, rootValue, contextValue, operation, - variableValues: coercedVariableValues.coerced, + variableValues: variableValuesOrErrors.variableValues, fieldResolver: fieldResolver ?? defaultFieldResolver, typeResolver: typeResolver ?? defaultTypeResolver, subscribeFieldResolver: subscribeFieldResolver ?? defaultFieldResolver, - incrementalPublisher: new IncrementalPublisher(), - }; -} - -function buildPerEventExecutionContext( - exeContext: ExecutionContext, - payload: unknown, -): ExecutionContext { - return { - ...exeContext, - rootValue: payload, + perEventExecutor: perEventExecutor ?? executeSubscriptionEvent, + enableEarlyExecution: enableEarlyExecution === true, + hideSuggestions, + abortSignal: args.abortSignal ?? undefined, }; } -/** - * Implements the "Executing operations" section of the spec. - */ -function executeOperation( +function executeRootExecutionPlan( exeContext: ExecutionContext, - initialResultRecord: InitialResultRecord, -): PromiseOrValue> { - const { - operation, - schema, - fragments, - variableValues, - rootValue, - incrementalPublisher, - } = exeContext; - const rootType = schema.getRootType(operation.operation); - if (rootType == null) { - throw new GraphQLError( - `Schema is not configured to execute ${operation.operation} operation.`, - { nodes: operation }, + operation: OperationTypeNode, + rootType: GraphQLObjectType, + rootValue: unknown, + originalGroupedFieldSet: GroupedFieldSet, + newDeferUsages: ReadonlyArray, +): PromiseOrValue>> { + if (newDeferUsages.length === 0) { + return executeRootGroupedFieldSet( + exeContext, + operation, + rootType, + rootValue, + originalGroupedFieldSet, + undefined, ); } + const newDeferMap = getNewDeferMap(newDeferUsages, undefined, undefined); - const fields = collectFields( - schema, - fragments, - variableValues, - rootType, - operation, + const { groupedFieldSet, newGroupedFieldSets } = buildExecutionPlan( + originalGroupedFieldSet, ); - const { groupedFieldSet, newGroupedFieldSetDetailsMap, newDeferUsages } = - buildFieldPlan(fields); - const newDeferMap = addNewDeferredFragments( - incrementalPublisher, - newDeferUsages, - initialResultRecord, + const graphqlWrappedResult = executeRootGroupedFieldSet( + exeContext, + operation, + rootType, + rootValue, + groupedFieldSet, + newDeferMap, ); - const path = undefined; + if (newGroupedFieldSets.size > 0) { + const newPendingExecutionGroups = collectExecutionGroups( + exeContext, + rootType, + rootValue, + undefined, + undefined, + newGroupedFieldSets, + newDeferMap, + ); - const newDeferredGroupedFieldSetRecords = addNewDeferredGroupedFieldSets( - incrementalPublisher, - newGroupedFieldSetDetailsMap, - newDeferMap, - path, - ); + return withNewExecutionGroups( + graphqlWrappedResult, + newPendingExecutionGroups, + ); + } + return graphqlWrappedResult; +} - let result; - switch (operation.operation) { +function withNewExecutionGroups( + result: PromiseOrValue>>, + newPendingExecutionGroups: ReadonlyArray, +): PromiseOrValue>> { + if (isPromise(result)) { + return result.then((resolved) => { + addIncrementalDataRecords(resolved, newPendingExecutionGroups); + return resolved; + }); + } + + addIncrementalDataRecords(result, newPendingExecutionGroups); + return result; +} + +function executeRootGroupedFieldSet( + exeContext: ExecutionContext, + operation: OperationTypeNode, + rootType: GraphQLObjectType, + rootValue: unknown, + groupedFieldSet: GroupedFieldSet, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { + switch (operation) { case OperationTypeNode.QUERY: - result = executeFields( + return executeFields( exeContext, rootType, rootValue, - path, + undefined, groupedFieldSet, - initialResultRecord, - newDeferMap, + undefined, + deferMap, ); - break; case OperationTypeNode.MUTATION: - result = executeFieldsSerially( + return executeFieldsSerially( exeContext, rootType, rootValue, - path, + undefined, groupedFieldSet, - initialResultRecord, - newDeferMap, + undefined, + deferMap, ); - break; case OperationTypeNode.SUBSCRIPTION: // TODO: deprecate `subscribe` and move all logic here // Temporary solution until we finish merging execute and subscribe together - result = executeFields( + return executeFields( exeContext, rootType, rootValue, - path, + undefined, groupedFieldSet, - initialResultRecord, - newDeferMap, + undefined, + deferMap, ); } - - executeDeferredGroupedFieldSets( - exeContext, - rootType, - rootValue, - path, - newDeferredGroupedFieldSetRecords, - newDeferMap, - ); - - return result; } /** @@ -493,38 +669,78 @@ function executeFieldsSerially( sourceValue: unknown, path: Path | undefined, groupedFieldSet: GroupedFieldSet, - incrementalDataRecord: InitialResultRecord, - deferMap: ReadonlyMap, -): PromiseOrValue> { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { + const abortSignal = exeContext.validatedExecutionArgs.abortSignal; return promiseReduce( groupedFieldSet, - (results, [responseName, fieldGroup]) => { + (graphqlWrappedResult, [responseName, fieldDetailsList]) => { const fieldPath = addPath(path, responseName, parentType.name); + + if (abortSignal?.aborted) { + handleFieldError( + abortSignal.reason, + exeContext, + parentType, + fieldDetailsList, + fieldPath, + incrementalContext, + ); + graphqlWrappedResult.rawResult[responseName] = null; + return graphqlWrappedResult; + } + const result = executeField( exeContext, parentType, sourceValue, - fieldGroup, + fieldDetailsList, fieldPath, - incrementalDataRecord, + incrementalContext, deferMap, ); if (result === undefined) { - return results; + return graphqlWrappedResult; } if (isPromise(result)) { - return result.then((resolvedResult) => { - results[responseName] = resolvedResult; - return results; + return result.then((resolved) => { + graphqlWrappedResult.rawResult[responseName] = resolved.rawResult; + addIncrementalDataRecords( + graphqlWrappedResult, + resolved.incrementalDataRecords, + ); + return graphqlWrappedResult; }); } - results[responseName] = result; - return results; + graphqlWrappedResult.rawResult[responseName] = result.rawResult; + addIncrementalDataRecords( + graphqlWrappedResult, + result.incrementalDataRecords, + ); + return graphqlWrappedResult; + }, + { + rawResult: Object.create(null), + incrementalDataRecords: undefined, }, - Object.create(null), ); } +function addIncrementalDataRecords( + graphqlWrappedResult: GraphQLWrappedResult, + incrementalDataRecords: ReadonlyArray | undefined, +): void { + if (incrementalDataRecords === undefined) { + return; + } + if (graphqlWrappedResult.incrementalDataRecords === undefined) { + graphqlWrappedResult.incrementalDataRecords = [...incrementalDataRecords]; + } else { + graphqlWrappedResult.incrementalDataRecords.push(...incrementalDataRecords); + } +} + /** * Implements the "Executing selection sets" section of the spec * for fields that may be executed in parallel. @@ -535,85 +751,109 @@ function executeFields( sourceValue: unknown, path: Path | undefined, groupedFieldSet: GroupedFieldSet, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue> { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { const results = Object.create(null); + const graphqlWrappedResult: GraphQLWrappedResult> = { + rawResult: results, + incrementalDataRecords: undefined, + }; let containsPromise = false; try { - for (const [responseName, fieldGroup] of groupedFieldSet) { + for (const [responseName, fieldDetailsList] of groupedFieldSet) { const fieldPath = addPath(path, responseName, parentType.name); const result = executeField( exeContext, parentType, sourceValue, - fieldGroup, + fieldDetailsList, fieldPath, - incrementalDataRecord, + incrementalContext, deferMap, ); if (result !== undefined) { - results[responseName] = result; if (isPromise(result)) { + results[responseName] = result.then((resolved) => { + addIncrementalDataRecords( + graphqlWrappedResult, + resolved.incrementalDataRecords, + ); + return resolved.rawResult; + }); containsPromise = true; + } else { + results[responseName] = result.rawResult; + addIncrementalDataRecords( + graphqlWrappedResult, + result.incrementalDataRecords, + ); } } } } catch (error) { if (containsPromise) { // Ensure that any promises returned by other fields are handled, as they may also reject. - return promiseForObject(results).finally(() => { + return promiseForObject(results, () => { + /* noop */ + }).finally(() => { throw error; - }); + }) as never; } throw error; } - // If there are no promises, we can just return the object + // If there are no promises, we can just return the object and any incrementalDataRecords if (!containsPromise) { - return results; + return graphqlWrappedResult; } // Otherwise, results is a map from field name to the result of resolving that // field, which is possibly a promise. Return a promise that will return this // same map, but with any promises replaced with the values they resolved to. - return promiseForObject(results); + return promiseForObject(results, (resolved) => ({ + rawResult: resolved, + incrementalDataRecords: graphqlWrappedResult.incrementalDataRecords, + })); } -function toNodes(fieldGroup: FieldGroup): ReadonlyArray { - return fieldGroup.fields.map((fieldDetails) => fieldDetails.node); +function toNodes(fieldDetailsList: FieldDetailsList): ReadonlyArray { + return fieldDetailsList.map((fieldDetails) => fieldDetails.node); } /** * Implements the "Executing fields" section of the spec * In particular, this function figures out the value that the field returns by * calling its resolve function, then calls completeValue to complete promises, - * serialize scalars, or execute the sub-selection-set for objects. + * coercing scalars, or execute the sub-selection-set for objects. */ function executeField( exeContext: ExecutionContext, parentType: GraphQLObjectType, source: unknown, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, path: Path, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue { - const fieldName = fieldGroup.fields[0].node.name.value; - const fieldDef = exeContext.schema.getField(parentType, fieldName); + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue> | undefined { + const { validatedExecutionArgs, abortSignalListener } = exeContext; + const { schema, contextValue, variableValues, hideSuggestions, abortSignal } = + validatedExecutionArgs; + const fieldName = fieldDetailsList[0].node.name.value; + const fieldDef = schema.getField(parentType, fieldName); if (!fieldDef) { return; } const returnType = fieldDef.type; - const resolveFn = fieldDef.resolve ?? exeContext.fieldResolver; + const resolveFn = fieldDef.resolve ?? validatedExecutionArgs.fieldResolver; const info = buildResolveInfo( - exeContext, + validatedExecutionArgs, fieldDef, - toNodes(fieldGroup), + toNodes(fieldDetailsList), parentType, path, ); @@ -623,28 +863,30 @@ function executeField( // Build a JS object of arguments from the field.arguments AST, using the // variables scope to fulfill any variable references. // TODO: find a way to memoize, in case this field is within a List type. - const args = getArgumentValues( - fieldDef, - fieldGroup.fields[0].node, - exeContext.variableValues, + const args = experimentalGetArgumentValues( + fieldDetailsList[0].node, + fieldDef.args, + variableValues, + fieldDetailsList[0].fragmentVariableValues, + hideSuggestions, ); // The resolve function's optional third argument is a context value that // is provided to every resolve function within an execution. It is commonly // used to represent an authenticated user, or request-specific caches. - const contextValue = exeContext.contextValue; - - const result = resolveFn(source, args, contextValue, info); + const result = resolveFn(source, args, contextValue, info, abortSignal); if (isPromise(result)) { return completePromisedValue( exeContext, returnType, - fieldGroup, + fieldDetailsList, info, path, - result, - incrementalDataRecord, + abortSignalListener + ? cancellablePromise(result, abortSignalListener) + : result, + incrementalContext, deferMap, ); } @@ -652,28 +894,27 @@ function executeField( const completed = completeValue( exeContext, returnType, - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); if (isPromise(completed)) { // Note: we don't rely on a `catch` method, but we do expect "thenable" // to take a second callback for the error case. - return completed.then(undefined, (rawError) => { + return completed.then(undefined, (rawError: unknown) => { handleFieldError( rawError, exeContext, returnType, - fieldGroup, + fieldDetailsList, path, - incrementalDataRecord, + incrementalContext, ); - exeContext.incrementalPublisher.filter(path, incrementalDataRecord); - return null; + return { rawResult: null, incrementalDataRecords: undefined }; }); } return completed; @@ -682,12 +923,11 @@ function executeField( rawError, exeContext, returnType, - fieldGroup, + fieldDetailsList, path, - incrementalDataRecord, + incrementalContext, ); - exeContext.incrementalPublisher.filter(path, incrementalDataRecord); - return null; + return { rawResult: null, incrementalDataRecords: undefined }; } } @@ -696,12 +936,14 @@ function executeField( * @internal */ export function buildResolveInfo( - exeContext: ExecutionContext, + validatedExecutionArgs: ValidatedExecutionArgs, fieldDef: GraphQLField, fieldNodes: ReadonlyArray, parentType: GraphQLObjectType, path: Path, ): GraphQLResolveInfo { + const { schema, fragmentDefinitions, rootValue, operation, variableValues } = + validatedExecutionArgs; // The resolve function's optional fourth argument is a collection of // information about the current execution state. return { @@ -710,11 +952,11 @@ export function buildResolveInfo( returnType: fieldDef.type, parentType, path, - schema: exeContext.schema, - fragments: exeContext.fragments, - rootValue: exeContext.rootValue, - operation: exeContext.operation, - variableValues: exeContext.variableValues, + schema, + fragments: fragmentDefinitions, + rootValue, + operation, + variableValues, }; } @@ -722,11 +964,15 @@ function handleFieldError( rawError: unknown, exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, path: Path, - incrementalDataRecord: IncrementalDataRecord, + incrementalContext: IncrementalContext | undefined, ): void { - const error = locatedError(rawError, toNodes(fieldGroup), pathToArray(path)); + const error = locatedError( + rawError, + toNodes(fieldDetailsList), + pathToArray(path), + ); // If the field type is non-nullable, then it is resolved without any // protection from errors, however it still properly locates the error. @@ -736,7 +982,13 @@ function handleFieldError( // Otherwise, error protection is applied, logging the error and resolving // a null value for this field if one is encountered. - exeContext.incrementalPublisher.addFieldError(incrementalDataRecord, error); + const context = incrementalContext ?? exeContext; + let errors = context.errors; + if (errors === undefined) { + errors = []; + context.errors = errors; + } + errors.push(error); } /** @@ -751,7 +1003,7 @@ function handleFieldError( * for the inner type on each item in the list. * * If the field type is a Scalar or Enum, ensures the completed value is a legal - * value of the type by calling the `serialize` method of GraphQL type + * value of the type by calling the `coerceOutputValue` method of GraphQL type * definition. * * If the field is an abstract type, determine the runtime type of the value @@ -763,13 +1015,13 @@ function handleFieldError( function completeValue( exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, path: Path, result: unknown, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue> { // If result is an Error, throw a located error. if (result instanceof Error) { throw result; @@ -781,16 +1033,16 @@ function completeValue( const completed = completeValue( exeContext, returnType.ofType, - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); - if (completed === null) { + if ((completed as GraphQLWrappedResult).rawResult === null) { throw new Error( - `Cannot return null for non-nullable field ${info.parentType.name}.${info.fieldName}.`, + `Cannot return null for non-nullable field ${info.parentType}.${info.fieldName}.`, ); } return completed; @@ -798,7 +1050,7 @@ function completeValue( // If result value is null or undefined then return null. if (result == null) { - return null; + return { rawResult: null, incrementalDataRecords: undefined }; } // If field type is List, complete each item in the list with the inner type @@ -806,19 +1058,22 @@ function completeValue( return completeListValue( exeContext, returnType, - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); } - // If field type is a leaf type, Scalar or Enum, serialize to a valid value, - // returning null if serialization is not possible. + // If field type is a leaf type, Scalar or Enum, coerce to a valid value, + // returning null if coercion is not possible. if (isLeafType(returnType)) { - return completeLeafValue(returnType, result); + return { + rawResult: completeLeafValue(returnType, result), + incrementalDataRecords: undefined, + }; } // If field type is an abstract type, Interface or Union, determine the @@ -827,11 +1082,11 @@ function completeValue( return completeAbstractValue( exeContext, returnType, - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); } @@ -841,11 +1096,11 @@ function completeValue( return completeObjectValue( exeContext, returnType, - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); } @@ -860,40 +1115,41 @@ function completeValue( async function completePromisedValue( exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, path: Path, result: Promise, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): Promise { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): Promise> { try { const resolved = await result; let completed = completeValue( exeContext, returnType, - fieldGroup, + fieldDetailsList, info, path, resolved, - incrementalDataRecord, + incrementalContext, deferMap, ); + if (isPromise(completed)) { completed = await completed; } + return completed; } catch (rawError) { handleFieldError( rawError, exeContext, returnType, - fieldGroup, + fieldDetailsList, path, - incrementalDataRecord, + incrementalContext, ); - exeContext.incrementalPublisher.filter(path, incrementalDataRecord); - return null; + return { rawResult: null, incrementalDataRecords: undefined }; } } @@ -903,8 +1159,8 @@ async function completePromisedValue( * not disabled by the "if" argument. */ function getStreamUsage( - exeContext: ExecutionContext, - fieldGroup: FieldGroup, + validatedExecutionArgs: ValidatedExecutionArgs, + fieldDetailsList: FieldDetailsList, path: Path, ): StreamUsage | undefined { // do not stream inner lists of multi-dimensional lists @@ -915,19 +1171,21 @@ function getStreamUsage( // TODO: add test for this case (a streamed list nested under a list). /* c8 ignore next 7 */ if ( - (fieldGroup as unknown as { _streamUsage: StreamUsage })._streamUsage !== - undefined + (fieldDetailsList as unknown as { _streamUsage: StreamUsage }) + ._streamUsage !== undefined ) { - return (fieldGroup as unknown as { _streamUsage: StreamUsage }) + return (fieldDetailsList as unknown as { _streamUsage: StreamUsage }) ._streamUsage; } + const { operation, variableValues } = validatedExecutionArgs; // validation only allows equivalent streams on multiple fields, so it is // safe to only check the first fieldNode for the stream directive const stream = getDirectiveValues( GraphQLStreamDirective, - fieldGroup.fields[0].node, - exeContext.variableValues, + fieldDetailsList[0].node, + variableValues, + fieldDetailsList[0].fragmentVariableValues, ); if (!stream) { @@ -949,28 +1207,30 @@ function getStreamUsage( ); invariant( - exeContext.operation.operation !== OperationTypeNode.SUBSCRIPTION, + operation.operation !== OperationTypeNode.SUBSCRIPTION, '`@stream` directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.', ); - const streamedFieldGroup: FieldGroup = { - fields: fieldGroup.fields.map((fieldDetails) => ({ + const streamedFieldDetailsList: FieldDetailsList = fieldDetailsList.map( + (fieldDetails) => ({ node: fieldDetails.node, deferUsage: undefined, - })), - }; + fragmentVariableValues: fieldDetails.fragmentVariableValues, + }), + ); const streamUsage = { initialCount: stream.initialCount, label: typeof stream.label === 'string' ? stream.label : undefined, - fieldGroup: streamedFieldGroup, + fieldDetailsList: streamedFieldDetailsList, }; - (fieldGroup as unknown as { _streamUsage: StreamUsage })._streamUsage = + (fieldDetailsList as unknown as { _streamUsage: StreamUsage })._streamUsage = streamUsage; return streamUsage; } + /** * Complete a async iterator value by completing the result and calling * recursively until all the results are completed. @@ -978,74 +1238,141 @@ function getStreamUsage( async function completeAsyncIteratorValue( exeContext: ExecutionContext, itemType: GraphQLOutputType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, path: Path, asyncIterator: AsyncIterator, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): Promise> { - const streamUsage = getStreamUsage(exeContext, fieldGroup, path); + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): Promise>> { let containsPromise = false; const completedResults: Array = []; + const graphqlWrappedResult: GraphQLWrappedResult> = { + rawResult: completedResults, + incrementalDataRecords: undefined, + }; let index = 0; - // eslint-disable-next-line no-constant-condition - while (true) { - if (streamUsage && index >= streamUsage.initialCount) { - const earlyReturn = asyncIterator.return; - const streamRecord = new StreamRecord({ - label: streamUsage.label, - path, - earlyReturn: - earlyReturn === undefined - ? undefined - : earlyReturn.bind(asyncIterator), - }); - // eslint-disable-next-line @typescript-eslint/no-floating-promises - executeStreamAsyncIterator( - index, - asyncIterator, - exeContext, - streamUsage.fieldGroup, - info, - itemType, - path, - incrementalDataRecord, - streamRecord, - ); - break; - } + const streamUsage = getStreamUsage( + exeContext.validatedExecutionArgs, + fieldDetailsList, + path, + ); + const earlyReturn = + asyncIterator.return === undefined + ? undefined + : asyncIterator.return.bind(asyncIterator); + try { + while (true) { + if (streamUsage && index >= streamUsage.initialCount) { + const streamItemQueue = buildAsyncStreamItemQueue( + index, + path, + asyncIterator, + exeContext, + streamUsage.fieldDetailsList, + info, + itemType, + ); - const itemPath = addPath(path, index, undefined); - let iteration; - try { - // eslint-disable-next-line no-await-in-loop - iteration = await asyncIterator.next(); + let streamRecord: StreamRecord | CancellableStreamRecord; + if (earlyReturn === undefined) { + streamRecord = { + label: streamUsage.label, + path, + streamItemQueue, + }; + } else { + streamRecord = { + label: streamUsage.label, + path, + earlyReturn, + streamItemQueue, + }; + if (exeContext.cancellableStreams === undefined) { + exeContext.cancellableStreams = new Set(); + } + exeContext.cancellableStreams.add(streamRecord); + } + + addIncrementalDataRecords(graphqlWrappedResult, [streamRecord]); + break; + } + + const itemPath = addPath(path, index, undefined); + let iteration; + try { + // eslint-disable-next-line no-await-in-loop + iteration = await asyncIterator.next(); + } catch (rawError) { + throw locatedError( + rawError, + toNodes(fieldDetailsList), + pathToArray(path), + ); + } + + // TODO: add test case for stream returning done before initialCount + /* c8 ignore next 3 */ if (iteration.done) { break; } - } catch (rawError) { - throw locatedError(rawError, toNodes(fieldGroup), pathToArray(path)); - } - if ( - completeListItemValue( - iteration.value, - completedResults, - exeContext, - itemType, - fieldGroup, - info, - itemPath, - incrementalDataRecord, - deferMap, - ) - ) { - containsPromise = true; + const item = iteration.value; + // TODO: add tests for stream backed by asyncIterator that returns a promise + /* c8 ignore start */ + if (isPromise(item)) { + completedResults.push( + completePromisedListItemValue( + item, + graphqlWrappedResult, + exeContext, + itemType, + fieldDetailsList, + info, + itemPath, + incrementalContext, + deferMap, + ), + ); + containsPromise = true; + } else if ( + /* c8 ignore stop */ + completeListItemValue( + item, + completedResults, + graphqlWrappedResult, + exeContext, + itemType, + fieldDetailsList, + info, + itemPath, + incrementalContext, + deferMap, + ) + // TODO: add tests for stream backed by asyncIterator that completes to a promise + /* c8 ignore start */ + ) { + containsPromise = true; + } + /* c8 ignore stop */ + index++; } - index += 1; + } catch (error) { + if (earlyReturn !== undefined) { + earlyReturn().catch(() => { + /* c8 ignore next 1 */ + // ignore error + }); + } + throw error; } - return containsPromise ? Promise.all(completedResults) : completedResults; + + return containsPromise + ? /* c8 ignore start */ Promise.all(completedResults).then((resolved) => ({ + rawResult: resolved, + incrementalDataRecords: graphqlWrappedResult.incrementalDataRecords, + })) + : /* c8 ignore stop */ graphqlWrappedResult; } /** @@ -1055,95 +1382,147 @@ async function completeAsyncIteratorValue( function completeListValue( exeContext: ExecutionContext, returnType: GraphQLList, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, path: Path, result: unknown, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue> { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { const itemType = returnType.ofType; if (isAsyncIterable(result)) { - const asyncIterator = result[Symbol.asyncIterator](); + const abortSignalListener = exeContext.abortSignalListener; + const maybeCancellableIterable = abortSignalListener + ? cancellableIterable(result, abortSignalListener) + : result; + const asyncIterator = maybeCancellableIterable[Symbol.asyncIterator](); return completeAsyncIteratorValue( exeContext, itemType, - fieldGroup, + fieldDetailsList, info, path, asyncIterator, - incrementalDataRecord, + incrementalContext, deferMap, ); } if (!isIterableObject(result)) { throw new GraphQLError( - `Expected Iterable, but did not find one for field "${info.parentType.name}.${info.fieldName}".`, + `Expected Iterable, but did not find one for field "${info.parentType}.${info.fieldName}".`, ); } - const streamUsage = getStreamUsage(exeContext, fieldGroup, path); + return completeIterableValue( + exeContext, + itemType, + fieldDetailsList, + info, + path, + result, + incrementalContext, + deferMap, + ); +} +function completeIterableValue( + exeContext: ExecutionContext, + itemType: GraphQLOutputType, + fieldDetailsList: FieldDetailsList, + info: GraphQLResolveInfo, + path: Path, + items: Iterable, + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { // This is specified as a simple map, however we're optimizing the path // where the list contains no Promises by avoiding creating another Promise. let containsPromise = false; - let currentParents = incrementalDataRecord; const completedResults: Array = []; + const graphqlWrappedResult: GraphQLWrappedResult> = { + rawResult: completedResults, + incrementalDataRecords: undefined, + }; let index = 0; - let streamRecord: StreamRecord | undefined; - for (const item of result) { - // No need to modify the info object containing the path, - // since from here on it is not ever accessed by resolver functions. - const itemPath = addPath(path, index, undefined); + const streamUsage = getStreamUsage( + exeContext.validatedExecutionArgs, + fieldDetailsList, + path, + ); + const iterator = items[Symbol.iterator](); + let iteration = iterator.next(); + while (!iteration.done) { + const item = iteration.value; if (streamUsage && index >= streamUsage.initialCount) { - if (streamRecord === undefined) { - streamRecord = new StreamRecord({ label: streamUsage.label, path }); - } - currentParents = executeStreamField( + const syncStreamRecord: StreamRecord = { + label: streamUsage.label, path, - itemPath, - item, - exeContext, - streamUsage.fieldGroup, - info, - itemType, - currentParents, - streamRecord, - ); - index++; - continue; + streamItemQueue: buildSyncStreamItemQueue( + item, + index, + path, + iterator, + exeContext, + streamUsage.fieldDetailsList, + info, + itemType, + ), + }; + + addIncrementalDataRecords(graphqlWrappedResult, [syncStreamRecord]); + break; } - if ( + // No need to modify the info object containing the path, + // since from here on it is not ever accessed by resolver functions. + const itemPath = addPath(path, index, undefined); + + if (isPromise(item)) { + completedResults.push( + completePromisedListItemValue( + item, + graphqlWrappedResult, + exeContext, + itemType, + fieldDetailsList, + info, + itemPath, + incrementalContext, + deferMap, + ), + ); + containsPromise = true; + } else if ( completeListItemValue( item, completedResults, + graphqlWrappedResult, exeContext, itemType, - fieldGroup, + fieldDetailsList, info, itemPath, - incrementalDataRecord, + incrementalContext, deferMap, ) ) { containsPromise = true; } - index++; - } - if (streamRecord !== undefined) { - exeContext.incrementalPublisher.setIsFinalRecord( - currentParents as StreamItemsRecord, - ); + iteration = iterator.next(); } - return containsPromise ? Promise.all(completedResults) : completedResults; + return containsPromise + ? Promise.all(completedResults).then((resolved) => ({ + rawResult: resolved, + incrementalDataRecords: graphqlWrappedResult.incrementalDataRecords, + })) + : graphqlWrappedResult; } /** @@ -1154,40 +1533,24 @@ function completeListValue( function completeListItemValue( item: unknown, completedResults: Array, + parent: GraphQLWrappedResult>, exeContext: ExecutionContext, itemType: GraphQLOutputType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, itemPath: Path, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, ): boolean { - if (isPromise(item)) { - completedResults.push( - completePromisedValue( - exeContext, - itemType, - fieldGroup, - info, - itemPath, - item, - incrementalDataRecord, - deferMap, - ), - ); - - return true; - } - try { const completedItem = completeValue( exeContext, itemType, - fieldGroup, + fieldDetailsList, info, itemPath, item, - incrementalDataRecord, + incrementalContext, deferMap, ); @@ -1195,43 +1558,88 @@ function completeListItemValue( // Note: we don't rely on a `catch` method, but we do expect "thenable" // to take a second callback for the error case. completedResults.push( - completedItem.then(undefined, (rawError) => { - handleFieldError( - rawError, - exeContext, - itemType, - fieldGroup, - itemPath, - incrementalDataRecord, - ); - exeContext.incrementalPublisher.filter( - itemPath, - incrementalDataRecord, - ); - return null; - }), + completedItem.then( + (resolved) => { + addIncrementalDataRecords(parent, resolved.incrementalDataRecords); + return resolved.rawResult; + }, + (rawError: unknown) => { + handleFieldError( + rawError, + exeContext, + itemType, + fieldDetailsList, + itemPath, + incrementalContext, + ); + return null; + }, + ), ); - return true; } - completedResults.push(completedItem); + completedResults.push(completedItem.rawResult); + addIncrementalDataRecords(parent, completedItem.incrementalDataRecords); } catch (rawError) { handleFieldError( rawError, exeContext, itemType, - fieldGroup, + fieldDetailsList, itemPath, - incrementalDataRecord, + incrementalContext, ); - exeContext.incrementalPublisher.filter(itemPath, incrementalDataRecord); completedResults.push(null); } - return false; } +async function completePromisedListItemValue( + item: Promise, + parent: GraphQLWrappedResult>, + exeContext: ExecutionContext, + itemType: GraphQLOutputType, + fieldDetailsList: FieldDetailsList, + info: GraphQLResolveInfo, + itemPath: Path, + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): Promise { + try { + const abortSignalListener = exeContext.abortSignalListener; + const maybeCancellableItem = abortSignalListener + ? cancellablePromise(item, abortSignalListener) + : item; + const resolved = await maybeCancellableItem; + let completed = completeValue( + exeContext, + itemType, + fieldDetailsList, + info, + itemPath, + resolved, + incrementalContext, + deferMap, + ); + if (isPromise(completed)) { + completed = await completed; + } + addIncrementalDataRecords(parent, completed.incrementalDataRecords); + return completed.rawResult; + } catch (rawError) { + handleFieldError( + rawError, + exeContext, + itemType, + fieldDetailsList, + itemPath, + incrementalContext, + ); + return null; + } +} + /** * Complete a Scalar or Enum by serializing to a valid value, returning * null if serialization is not possible. @@ -1240,14 +1648,14 @@ function completeLeafValue( returnType: GraphQLLeafType, result: unknown, ): unknown { - const serializedResult = returnType.serialize(result); - if (serializedResult == null) { + const coerced = returnType.coerceOutputValue(result); + if (coerced == null) { throw new Error( - `Expected \`${inspect(returnType)}.serialize(${inspect(result)})\` to ` + - `return non-nullable value, returned: ${inspect(serializedResult)}`, + `Expected \`${inspect(returnType)}.coerceOutputValue(${inspect(result)})\` to ` + + `return non-nullable value, returned: ${inspect(coerced)}`, ); } - return serializedResult; + return coerced; } /** @@ -1257,15 +1665,17 @@ function completeLeafValue( function completeAbstractValue( exeContext: ExecutionContext, returnType: GraphQLAbstractType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, path: Path, result: unknown, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue> { - const resolveTypeFn = returnType.resolveType ?? exeContext.typeResolver; - const contextValue = exeContext.contextValue; + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { + const validatedExecutionArgs = exeContext.validatedExecutionArgs; + const { schema, contextValue } = validatedExecutionArgs; + const resolveTypeFn = + returnType.resolveType ?? validatedExecutionArgs.typeResolver; const runtimeType = resolveTypeFn(result, contextValue, info, returnType); if (isPromise(runtimeType)) { @@ -1274,17 +1684,17 @@ function completeAbstractValue( exeContext, ensureValidRuntimeType( resolvedRuntimeType, - exeContext, + schema, returnType, - fieldGroup, + fieldDetailsList, info, result, ), - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ), ); @@ -1294,70 +1704,64 @@ function completeAbstractValue( exeContext, ensureValidRuntimeType( runtimeType, - exeContext, + schema, returnType, - fieldGroup, + fieldDetailsList, info, result, ), - fieldGroup, + fieldDetailsList, info, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); } function ensureValidRuntimeType( runtimeTypeName: unknown, - exeContext: ExecutionContext, + schema: GraphQLSchema, returnType: GraphQLAbstractType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, result: unknown, ): GraphQLObjectType { if (runtimeTypeName == null) { throw new GraphQLError( - `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, - { nodes: toNodes(fieldGroup) }, - ); - } - - // releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType` - // TODO: remove in 17.0.0 release - if (isObjectType(runtimeTypeName)) { - throw new GraphQLError( - 'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.', + `Abstract type "${returnType}" must resolve to an Object type at runtime for field "${info.parentType}.${info.fieldName}". Either the "${returnType}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, + { nodes: toNodes(fieldDetailsList) }, ); } if (typeof runtimeTypeName !== 'string') { throw new GraphQLError( - `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}" with ` + - `value ${inspect(result)}, received "${inspect(runtimeTypeName)}".`, + `Abstract type "${returnType}" must resolve to an Object type at runtime for field "${info.parentType}.${info.fieldName}" with ` + + `value ${inspect(result)}, received "${inspect( + runtimeTypeName, + )}", which is not a valid Object type name.`, ); } - const runtimeType = exeContext.schema.getType(runtimeTypeName); + const runtimeType = schema.getType(runtimeTypeName); if (runtimeType == null) { throw new GraphQLError( - `Abstract type "${returnType.name}" was resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`, - { nodes: toNodes(fieldGroup) }, + `Abstract type "${returnType}" was resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`, + { nodes: toNodes(fieldDetailsList) }, ); } if (!isObjectType(runtimeType)) { throw new GraphQLError( - `Abstract type "${returnType.name}" was resolved to a non-object type "${runtimeTypeName}".`, - { nodes: toNodes(fieldGroup) }, + `Abstract type "${returnType}" was resolved to a non-object type "${runtimeTypeName}".`, + { nodes: toNodes(fieldDetailsList) }, ); } - if (!exeContext.schema.isSubType(returnType, runtimeType)) { + if (!schema.isSubType(returnType, runtimeType)) { throw new GraphQLError( - `Runtime Object type "${runtimeType.name}" is not a possible type for "${returnType.name}".`, - { nodes: toNodes(fieldGroup) }, + `Runtime Object type "${runtimeType}" is not a possible type for "${returnType}".`, + { nodes: toNodes(fieldDetailsList) }, ); } @@ -1370,48 +1774,56 @@ function ensureValidRuntimeType( function completeObjectValue( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, path: Path, result: unknown, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue> { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { + if ((incrementalContext ?? exeContext).completed) { + throw new Error('Completed, aborting.'); + } + // If there is an isTypeOf predicate function, call it with the // current result. If isTypeOf returns false, then raise an error rather // than continuing execution. if (returnType.isTypeOf) { - const isTypeOf = returnType.isTypeOf(result, exeContext.contextValue, info); + const isTypeOf = returnType.isTypeOf( + result, + exeContext.validatedExecutionArgs.contextValue, + info, + ); if (isPromise(isTypeOf)) { return isTypeOf.then((resolvedIsTypeOf) => { if (!resolvedIsTypeOf) { - throw invalidReturnTypeError(returnType, result, fieldGroup); + throw invalidReturnTypeError(returnType, result, fieldDetailsList); } return collectAndExecuteSubfields( exeContext, returnType, - fieldGroup, + fieldDetailsList, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); }); } if (!isTypeOf) { - throw invalidReturnTypeError(returnType, result, fieldGroup); + throw invalidReturnTypeError(returnType, result, fieldDetailsList); } } return collectAndExecuteSubfields( exeContext, returnType, - fieldGroup, + fieldDetailsList, path, result, - incrementalDataRecord, + incrementalContext, deferMap, ); } @@ -1419,11 +1831,11 @@ function completeObjectValue( function invalidReturnTypeError( returnType: GraphQLObjectType, result: unknown, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, ): GraphQLError { return new GraphQLError( - `Expected value of type "${returnType.name}" but got: ${inspect(result)}.`, - { nodes: toNodes(fieldGroup) }, + `Expected value of type "${returnType}" but got: ${inspect(result)}.`, + { nodes: toNodes(fieldDetailsList) }, ); } @@ -1434,55 +1846,27 @@ function invalidReturnTypeError( * * Note: As defer directives may be used with operations returning lists, * a DeferUsage object may correspond to many DeferredFragmentRecords. - * - * DeferredFragmentRecord creation includes the following steps: - * 1. The new DeferredFragmentRecord is instantiated at the given path. - * 2. The parent result record is calculated from the given incremental data - * record. - * 3. The IncrementalPublisher is notified that a new DeferredFragmentRecord - * with the calculated parent has been added; the record will be released only - * after the parent has completed. - * */ -function addNewDeferredFragments( - incrementalPublisher: IncrementalPublisher, +function getNewDeferMap( newDeferUsages: ReadonlyArray, - incrementalDataRecord: IncrementalDataRecord, deferMap?: ReadonlyMap, - path?: Path | undefined, + path?: Path, ): ReadonlyMap { - if (newDeferUsages.length === 0) { - // Given no DeferUsages, return the existing map, creating one if necessary. - return deferMap ?? new Map(); - } - - // Create a copy of the old map. - const newDeferMap = - deferMap === undefined - ? new Map() - : new Map(deferMap); + const newDeferMap = new Map(deferMap); // For each new deferUsage object: for (const newDeferUsage of newDeferUsages) { const parentDeferUsage = newDeferUsage.parentDeferUsage; - // If the parent defer usage is not defined, the parent result record is either: - // - the InitialResultRecord, or - // - a StreamItemsRecord, as `@defer` may be nested under `@stream`. const parent = parentDeferUsage === undefined - ? (incrementalDataRecord as InitialResultRecord | StreamItemsRecord) + ? undefined : deferredFragmentRecordFromDeferUsage(parentDeferUsage, newDeferMap); // Instantiate the new record. - const deferredFragmentRecord = new DeferredFragmentRecord({ + const deferredFragmentRecord = new DeferredFragmentRecord( path, - label: newDeferUsage.label, - }); - - // Report the new record to the Incremental Publisher. - incrementalPublisher.reportNewDeferFragmentRecord( - deferredFragmentRecord, + newDeferUsage.label, parent, ); @@ -1501,97 +1885,118 @@ function deferredFragmentRecordFromDeferUsage( return deferMap.get(deferUsage)!; } -function addNewDeferredGroupedFieldSets( - incrementalPublisher: IncrementalPublisher, - newGroupedFieldSetDetailsMap: Map, - deferMap: ReadonlyMap, - path?: Path | undefined, -): ReadonlyArray { - const newDeferredGroupedFieldSetRecords: Array = - []; - - for (const [ - deferUsageSet, - { groupedFieldSet, shouldInitiateDefer }, - ] of newGroupedFieldSetDetailsMap) { - const deferredFragmentRecords = getDeferredFragmentRecords( - deferUsageSet, - deferMap, - ); - const deferredGroupedFieldSetRecord = new DeferredGroupedFieldSetRecord({ - path, - deferredFragmentRecords, - groupedFieldSet, - shouldInitiateDefer, - }); - incrementalPublisher.reportNewDeferredGroupedFieldSetRecord( - deferredGroupedFieldSetRecord, - ); - newDeferredGroupedFieldSetRecords.push(deferredGroupedFieldSetRecord); - } - - return newDeferredGroupedFieldSetRecords; -} - -function getDeferredFragmentRecords( - deferUsages: DeferUsageSet, - deferMap: ReadonlyMap, -): ReadonlyArray { - return Array.from(deferUsages).map((deferUsage) => - deferredFragmentRecordFromDeferUsage(deferUsage, deferMap), - ); -} - function collectAndExecuteSubfields( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldGroup: FieldGroup, + fieldDetailsList: FieldDetailsList, path: Path, result: unknown, - incrementalDataRecord: IncrementalDataRecord, - deferMap: ReadonlyMap, -): PromiseOrValue> { + incrementalContext: IncrementalContext | undefined, + deferMap: ReadonlyMap | undefined, +): PromiseOrValue>> { + const validatedExecutionArgs = exeContext.validatedExecutionArgs; + // Collect sub-fields to execute to complete this value. - const { groupedFieldSet, newGroupedFieldSetDetailsMap, newDeferUsages } = - buildSubFieldPlan(exeContext, returnType, fieldGroup); + const collectedSubfields = collectSubfields( + validatedExecutionArgs, + returnType, + fieldDetailsList, + ); + const { groupedFieldSet, newDeferUsages } = collectedSubfields; - const incrementalPublisher = exeContext.incrementalPublisher; + if (newDeferUsages.length > 0) { + invariant( + validatedExecutionArgs.operation.operation !== + OperationTypeNode.SUBSCRIPTION, + '`@defer` directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', + ); + } - const newDeferMap = addNewDeferredFragments( - incrementalPublisher, + return executeSubExecutionPlan( + exeContext, + returnType, + result, + groupedFieldSet, newDeferUsages, - incrementalDataRecord, - deferMap, path, + incrementalContext, + deferMap, ); +} - const newDeferredGroupedFieldSetRecords = addNewDeferredGroupedFieldSets( - incrementalPublisher, - newGroupedFieldSetDetailsMap, - newDeferMap, - path, +function executeSubExecutionPlan( + exeContext: ExecutionContext, + returnType: GraphQLObjectType, + sourceValue: unknown, + originalGroupedFieldSet: GroupedFieldSet, + newDeferUsages: ReadonlyArray, + path?: Path, + incrementalContext?: IncrementalContext, + deferMap?: ReadonlyMap, +): PromiseOrValue>> { + if (deferMap === undefined && newDeferUsages.length === 0) { + return executeFields( + exeContext, + returnType, + sourceValue, + path, + originalGroupedFieldSet, + incrementalContext, + deferMap, + ); + } + + const newDeferMap = getNewDeferMap(newDeferUsages, deferMap, path); + + const { groupedFieldSet, newGroupedFieldSets } = buildSubExecutionPlan( + originalGroupedFieldSet, + incrementalContext?.deferUsageSet, ); - const subFields = executeFields( + const graphqlWrappedResult = executeFields( exeContext, returnType, - result, + sourceValue, path, groupedFieldSet, - incrementalDataRecord, + incrementalContext, newDeferMap, ); - executeDeferredGroupedFieldSets( - exeContext, - returnType, - result, - path, - newDeferredGroupedFieldSetRecords, - newDeferMap, - ); + if (newGroupedFieldSets.size > 0) { + const newPendingExecutionGroups = collectExecutionGroups( + exeContext, + returnType, + sourceValue, + path, + incrementalContext?.deferUsageSet, + newGroupedFieldSets, + newDeferMap, + ); + + return withNewExecutionGroups( + graphqlWrappedResult, + newPendingExecutionGroups, + ); + } + return graphqlWrappedResult; +} - return subFields; +function buildSubExecutionPlan( + originalGroupedFieldSet: GroupedFieldSet, + deferUsageSet: DeferUsageSet | undefined, +): ExecutionPlan { + let executionPlan = ( + originalGroupedFieldSet as unknown as { _executionPlan: ExecutionPlan } + )._executionPlan; + if (executionPlan !== undefined) { + return executionPlan; + } + executionPlan = buildExecutionPlan(originalGroupedFieldSet, deferUsageSet); + ( + originalGroupedFieldSet as unknown as { _executionPlan: ExecutionPlan } + )._executionPlan = executionPlan; + return executionPlan; } /** @@ -1624,6 +2029,12 @@ export const defaultTypeResolver: GraphQLTypeResolver = if (isPromise(isTypeOfResult)) { promisedIsTypeOfResults[i] = isTypeOfResult; } else if (isTypeOfResult) { + if (promisedIsTypeOfResults.length > 0) { + Promise.all(promisedIsTypeOfResults).then(undefined, () => { + /* ignore errors */ + }); + } + return type.name; } } @@ -1647,12 +2058,12 @@ export const defaultTypeResolver: GraphQLTypeResolver = * of calling that function while passing along args and context value. */ export const defaultFieldResolver: GraphQLFieldResolver = - function (source: any, args, contextValue, info) { + function (source: any, args, contextValue, info, abortSignal) { // ensure source is a value for which property access is acceptable. if (isObjectLike(source) || typeof source === 'function') { const property = source[info.fieldName]; if (typeof property === 'function') { - return source[info.fieldName](args, contextValue, info); + return source[info.fieldName](args, contextValue, info, abortSignal); } return property; } @@ -1691,50 +2102,62 @@ export function subscribe( > { // If a valid execution context cannot be created due to incorrect arguments, // a "Response" with only errors is returned. - const exeContext = buildExecutionContext(args); + const validatedExecutionArgs = validateExecutionArgs(args); // Return early errors if execution context failed. - if (!('schema' in exeContext)) { - return { errors: exeContext }; + if (!('schema' in validatedExecutionArgs)) { + return { errors: validatedExecutionArgs }; } - const resultOrStream = createSourceEventStreamImpl(exeContext); + const resultOrStream = createSourceEventStreamImpl(validatedExecutionArgs); if (isPromise(resultOrStream)) { return resultOrStream.then((resolvedResultOrStream) => - mapSourceToResponse(exeContext, resolvedResultOrStream), + mapSourceToResponse(validatedExecutionArgs, resolvedResultOrStream), ); } - return mapSourceToResponse(exeContext, resultOrStream); + return mapSourceToResponse(validatedExecutionArgs, resultOrStream); } function mapSourceToResponse( - exeContext: ExecutionContext, + validatedExecutionArgs: ValidatedExecutionArgs, resultOrStream: ExecutionResult | AsyncIterable, ): AsyncGenerator | ExecutionResult { if (!isAsyncIterable(resultOrStream)) { return resultOrStream; } + const abortSignal = validatedExecutionArgs.abortSignal; + const abortSignalListener = abortSignal + ? new AbortSignalListener(abortSignal) + : undefined; + // For each payload yielded from a subscription, map it over the normal // GraphQL `execute` function, with `payload` as the rootValue. // This implements the "MapSourceToResponseEvent" algorithm described in - // the GraphQL specification. The `execute` function provides the - // "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the - // "ExecuteQuery" algorithm, for which `execute` is also used. + // the GraphQL specification.. return mapAsyncIterable( - resultOrStream, - (payload: unknown) => - executeImpl( - buildPerEventExecutionContext(exeContext, payload), - // typecast to ExecutionResult, not possible to return - // ExperimentalIncrementalExecutionResults when - // exeContext.operation is 'subscription'. - ) as ExecutionResult, + abortSignalListener + ? cancellableIterable(resultOrStream, abortSignalListener) + : resultOrStream, + (payload: unknown) => { + const perEventExecutionArgs: ValidatedExecutionArgs = { + ...validatedExecutionArgs, + rootValue: payload, + }; + return validatedExecutionArgs.perEventExecutor(perEventExecutionArgs); + }, + () => abortSignalListener?.disconnect(), ); } +export function executeSubscriptionEvent( + validatedExecutionArgs: ValidatedExecutionArgs, +): PromiseOrValue { + return executeQueryOrMutationOrSubscriptionEvent(validatedExecutionArgs); +} + /** * Implements the "CreateSourceEventStream" algorithm described in the * GraphQL specification, resolving the subscription source event stream. @@ -1768,23 +2191,25 @@ export function createSourceEventStream( ): PromiseOrValue | ExecutionResult> { // If a valid execution context cannot be created due to incorrect arguments, // a "Response" with only errors is returned. - const exeContext = buildExecutionContext(args); + const validatedExecutionArgs = validateExecutionArgs(args); // Return early errors if execution context failed. - if (!('schema' in exeContext)) { - return { errors: exeContext }; + if (!('schema' in validatedExecutionArgs)) { + return { errors: validatedExecutionArgs }; } - return createSourceEventStreamImpl(exeContext); + return createSourceEventStreamImpl(validatedExecutionArgs); } function createSourceEventStreamImpl( - exeContext: ExecutionContext, + validatedExecutionArgs: ValidatedExecutionArgs, ): PromiseOrValue | ExecutionResult> { try { - const eventStream = executeSubscription(exeContext); + const eventStream = executeSubscription(validatedExecutionArgs); if (isPromise(eventStream)) { - return eventStream.then(undefined, (error) => ({ errors: [error] })); + return eventStream.then(undefined, (error: unknown) => ({ + errors: [error as GraphQLError], + })); } return eventStream; @@ -1794,10 +2219,18 @@ function createSourceEventStreamImpl( } function executeSubscription( - exeContext: ExecutionContext, + validatedExecutionArgs: ValidatedExecutionArgs, ): PromiseOrValue> { - const { schema, fragments, operation, variableValues, rootValue } = - exeContext; + const { + schema, + fragments, + rootValue, + contextValue, + operation, + variableValues, + hideSuggestions, + abortSignal, + } = validatedExecutionArgs; const rootType = schema.getSubscriptionType(); if (rootType == null) { @@ -1807,17 +2240,18 @@ function executeSubscription( ); } - const fields = collectFields( + const { groupedFieldSet } = collectFields( schema, fragments, variableValues, rootType, - operation, + operation.selectionSet, + hideSuggestions, ); - const firstRootField = fields.entries().next().value as [ + const firstRootField = groupedFieldSet.entries().next().value as [ string, - ReadonlyArray, + FieldDetailsList, ]; const [responseName, fieldDetailsList] = firstRootField; const fieldName = fieldDetailsList[0].node.name.value; @@ -1833,7 +2267,7 @@ function executeSubscription( const path = addPath(undefined, responseName, rootType.name); const info = buildResolveInfo( - exeContext, + validatedExecutionArgs, fieldDef, fieldNodes, rootType, @@ -1846,22 +2280,41 @@ function executeSubscription( // Build a JS object of arguments from the field.arguments AST, using the // variables scope to fulfill any variable references. - const args = getArgumentValues(fieldDef, fieldNodes[0], variableValues); + const args = getArgumentValues( + fieldDef, + fieldNodes[0], + variableValues, + hideSuggestions, + ); + + // Call the `subscribe()` resolver or the default resolver to produce an + // AsyncIterable yielding raw payloads. + const resolveFn = + fieldDef.subscribe ?? validatedExecutionArgs.subscribeFieldResolver; // The resolve function's optional third argument is a context value that // is provided to every resolve function within an execution. It is commonly // used to represent an authenticated user, or request-specific caches. - const contextValue = exeContext.contextValue; - - // Call the `subscribe()` resolver or the default resolver to produce an - // AsyncIterable yielding raw payloads. - const resolveFn = fieldDef.subscribe ?? exeContext.subscribeFieldResolver; - const result = resolveFn(rootValue, args, contextValue, info); + const result = resolveFn(rootValue, args, contextValue, info, abortSignal); if (isPromise(result)) { - return result.then(assertEventStream).then(undefined, (error) => { - throw locatedError(error, fieldNodes, pathToArray(path)); - }); + const abortSignalListener = abortSignal + ? new AbortSignalListener(abortSignal) + : undefined; + + const promise = abortSignalListener + ? cancellablePromise(result, abortSignalListener) + : result; + return promise.then(assertEventStream).then( + (resolved) => { + abortSignalListener?.disconnect(); + return resolved; + }, + (error: unknown) => { + abortSignalListener?.disconnect(); + throw locatedError(error, fieldNodes, pathToArray(path)); + }, + ); } return assertEventStream(result); @@ -1886,147 +2339,382 @@ function assertEventStream(result: unknown): AsyncIterable { return result; } -function executeDeferredGroupedFieldSets( +function collectExecutionGroups( exeContext: ExecutionContext, parentType: GraphQLObjectType, sourceValue: unknown, path: Path | undefined, - newDeferredGroupedFieldSetRecords: ReadonlyArray, + parentDeferUsages: DeferUsageSet | undefined, + newGroupedFieldSets: Map, deferMap: ReadonlyMap, -): void { - for (const deferredGroupedFieldSetRecord of newDeferredGroupedFieldSetRecords) { - if (deferredGroupedFieldSetRecord.shouldInitiateDefer) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - Promise.resolve().then(() => - executeDeferredGroupedFieldSet( - exeContext, - parentType, - sourceValue, - path, - deferredGroupedFieldSetRecord, - deferMap, - ), - ); - continue; - } +): ReadonlyArray { + const newPendingExecutionGroups: Array = []; - executeDeferredGroupedFieldSet( - exeContext, - parentType, - sourceValue, - path, - deferredGroupedFieldSetRecord, + for (const [deferUsageSet, groupedFieldSet] of newGroupedFieldSets) { + const deferredFragmentRecords = getDeferredFragmentRecords( + deferUsageSet, deferMap, ); + + const pendingExecutionGroup: PendingExecutionGroup = { + deferredFragmentRecords, + result: + undefined as unknown as BoxedPromiseOrValue, + }; + + const executor = () => + executeExecutionGroup( + pendingExecutionGroup, + exeContext, + parentType, + sourceValue, + path, + groupedFieldSet, + { + errors: undefined, + completed: false, + deferUsageSet, + }, + deferMap, + ); + + if (exeContext.validatedExecutionArgs.enableEarlyExecution) { + pendingExecutionGroup.result = new BoxedPromiseOrValue( + shouldDefer(parentDeferUsages, deferUsageSet) + ? Promise.resolve().then(executor) + : executor(), + ); + } else { + pendingExecutionGroup.result = () => new BoxedPromiseOrValue(executor()); + } + + newPendingExecutionGroups.push(pendingExecutionGroup); } + + return newPendingExecutionGroups; } -function executeDeferredGroupedFieldSet( +function shouldDefer( + parentDeferUsages: undefined | DeferUsageSet, + deferUsages: DeferUsageSet, +): boolean { + // If we have a new child defer usage, defer. + // Otherwise, this defer usage was already deferred when it was initially + // encountered, and is now in the midst of executing early, so the new + // deferred grouped fields set can be executed immediately. + return ( + parentDeferUsages === undefined || + !Array.from(deferUsages).every((deferUsage) => + parentDeferUsages.has(deferUsage), + ) + ); +} + +function executeExecutionGroup( + pendingExecutionGroup: PendingExecutionGroup, exeContext: ExecutionContext, parentType: GraphQLObjectType, sourceValue: unknown, path: Path | undefined, - deferredGroupedFieldSetRecord: DeferredGroupedFieldSetRecord, + groupedFieldSet: GroupedFieldSet, + incrementalContext: IncrementalContext, deferMap: ReadonlyMap, -): void { +): PromiseOrValue { + let result; try { - const incrementalResult = executeFields( + result = executeFields( exeContext, parentType, sourceValue, path, - deferredGroupedFieldSetRecord.groupedFieldSet, - deferredGroupedFieldSetRecord, + groupedFieldSet, + incrementalContext, deferMap, ); + } catch (error) { + incrementalContext.completed = true; + return { + pendingExecutionGroup, + path: pathToArray(path), + errors: withError(incrementalContext.errors, error), + }; + } + + if (isPromise(result)) { + return result.then( + (resolved) => { + incrementalContext.completed = true; + return buildCompletedExecutionGroup( + incrementalContext.errors, + pendingExecutionGroup, + path, + resolved, + ); + }, + (error: unknown) => { + incrementalContext.completed = true; + return { + pendingExecutionGroup, + path: pathToArray(path), + errors: withError(incrementalContext.errors, error as GraphQLError), + }; + }, + ); + } - if (isPromise(incrementalResult)) { - incrementalResult.then( - (resolved) => - exeContext.incrementalPublisher.completeDeferredGroupedFieldSet( - deferredGroupedFieldSetRecord, - resolved, - ), - (error) => - exeContext.incrementalPublisher.markErroredDeferredGroupedFieldSet( - deferredGroupedFieldSetRecord, - error, - ), - ); - return; + incrementalContext.completed = true; + return buildCompletedExecutionGroup( + incrementalContext.errors, + pendingExecutionGroup, + path, + result, + ); +} + +function buildCompletedExecutionGroup( + errors: ReadonlyArray | undefined, + pendingExecutionGroup: PendingExecutionGroup, + path: Path | undefined, + result: GraphQLWrappedResult>, +): CompletedExecutionGroup { + const { rawResult: data, incrementalDataRecords } = result; + return { + pendingExecutionGroup, + path: pathToArray(path), + result: errors === undefined ? { data } : { data, errors }, + incrementalDataRecords, + }; +} + +function getDeferredFragmentRecords( + deferUsages: DeferUsageSet, + deferMap: ReadonlyMap, +): ReadonlyArray { + return Array.from(deferUsages).map((deferUsage) => + deferredFragmentRecordFromDeferUsage(deferUsage, deferMap), + ); +} + +function buildSyncStreamItemQueue( + initialItem: PromiseOrValue, + initialIndex: number, + streamPath: Path, + iterator: Iterator, + exeContext: ExecutionContext, + fieldDetailsList: FieldDetailsList, + info: GraphQLResolveInfo, + itemType: GraphQLOutputType, +): Array { + const streamItemQueue: Array = []; + + const enableEarlyExecution = + exeContext.validatedExecutionArgs.enableEarlyExecution; + + const firstExecutor = () => { + const initialPath = addPath(streamPath, initialIndex, undefined); + const firstStreamItem = new BoxedPromiseOrValue( + completeStreamItem( + initialPath, + initialItem, + exeContext, + { errors: undefined, completed: false }, + fieldDetailsList, + info, + itemType, + ), + ); + + let iteration = iterator.next(); + let currentIndex = initialIndex + 1; + let currentStreamItem: + | BoxedPromiseOrValue + | (() => BoxedPromiseOrValue) = firstStreamItem; + while (!iteration.done) { + // TODO: add test case for early sync termination + /* c8 ignore next 6 */ + if (currentStreamItem instanceof BoxedPromiseOrValue) { + const result = currentStreamItem.value; + if (!isPromise(result) && result.errors !== undefined) { + break; + } + } + + const itemPath = addPath(streamPath, currentIndex, undefined); + + const value = iteration.value; + + const currentExecutor = () => + completeStreamItem( + itemPath, + value, + exeContext, + { errors: undefined, completed: false }, + fieldDetailsList, + info, + itemType, + ); + + currentStreamItem = enableEarlyExecution + ? new BoxedPromiseOrValue(currentExecutor()) + : () => new BoxedPromiseOrValue(currentExecutor()); + + streamItemQueue.push(currentStreamItem); + + iteration = iterator.next(); + currentIndex = initialIndex + 1; } - exeContext.incrementalPublisher.completeDeferredGroupedFieldSet( - deferredGroupedFieldSetRecord, - incrementalResult, + streamItemQueue.push(new BoxedPromiseOrValue({})); + + return firstStreamItem.value; + }; + + streamItemQueue.push( + enableEarlyExecution + ? new BoxedPromiseOrValue(Promise.resolve().then(firstExecutor)) + : () => new BoxedPromiseOrValue(firstExecutor()), + ); + + return streamItemQueue; +} + +function buildAsyncStreamItemQueue( + initialIndex: number, + streamPath: Path, + asyncIterator: AsyncIterator, + exeContext: ExecutionContext, + fieldDetailsList: FieldDetailsList, + info: GraphQLResolveInfo, + itemType: GraphQLOutputType, +): Array { + const streamItemQueue: Array = []; + const executor = () => + getNextAsyncStreamItemResult( + streamItemQueue, + streamPath, + initialIndex, + asyncIterator, + exeContext, + fieldDetailsList, + info, + itemType, ); + + streamItemQueue.push( + exeContext.validatedExecutionArgs.enableEarlyExecution + ? new BoxedPromiseOrValue(executor()) + : () => new BoxedPromiseOrValue(executor()), + ); + + return streamItemQueue; +} + +async function getNextAsyncStreamItemResult( + streamItemQueue: Array, + streamPath: Path, + index: number, + asyncIterator: AsyncIterator, + exeContext: ExecutionContext, + fieldDetailsList: FieldDetailsList, + info: GraphQLResolveInfo, + itemType: GraphQLOutputType, +): Promise { + let iteration; + try { + iteration = await asyncIterator.next(); } catch (error) { - exeContext.incrementalPublisher.markErroredDeferredGroupedFieldSet( - deferredGroupedFieldSetRecord, - error, - ); + return { + errors: [ + locatedError(error, toNodes(fieldDetailsList), pathToArray(streamPath)), + ], + }; } + + if (iteration.done) { + return {}; + } + + const itemPath = addPath(streamPath, index, undefined); + + const result = completeStreamItem( + itemPath, + iteration.value, + exeContext, + { errors: undefined, completed: false }, + fieldDetailsList, + info, + itemType, + ); + + const executor = () => + getNextAsyncStreamItemResult( + streamItemQueue, + streamPath, + index + 1, + asyncIterator, + exeContext, + fieldDetailsList, + info, + itemType, + ); + + streamItemQueue.push( + exeContext.validatedExecutionArgs.enableEarlyExecution + ? new BoxedPromiseOrValue(executor()) + : () => new BoxedPromiseOrValue(executor()), + ); + + return result; } -function executeStreamField( - path: Path, +function completeStreamItem( itemPath: Path, - item: PromiseOrValue, + item: unknown, exeContext: ExecutionContext, - fieldGroup: FieldGroup, + incrementalContext: IncrementalContext, + fieldDetailsList: FieldDetailsList, info: GraphQLResolveInfo, itemType: GraphQLOutputType, - incrementalDataRecord: IncrementalDataRecord, - streamRecord: StreamRecord, -): StreamItemsRecord { - const incrementalPublisher = exeContext.incrementalPublisher; - const streamItemsRecord = new StreamItemsRecord({ - streamRecord, - path: itemPath, - }); - incrementalPublisher.reportNewStreamItemsRecord( - streamItemsRecord, - incrementalDataRecord, - ); - +): PromiseOrValue { if (isPromise(item)) { - completePromisedValue( + const abortSignalListener = exeContext.abortSignalListener; + const maybeCancellableItem = abortSignalListener + ? cancellablePromise(item, abortSignalListener) + : item; + return completePromisedValue( exeContext, itemType, - fieldGroup, + fieldDetailsList, info, itemPath, - item, - streamItemsRecord, + maybeCancellableItem, + incrementalContext, new Map(), ).then( - (value) => - incrementalPublisher.completeStreamItemsRecord(streamItemsRecord, [ - value, - ]), - (error) => { - incrementalPublisher.filter(path, streamItemsRecord); - incrementalPublisher.markErroredStreamItemsRecord( - streamItemsRecord, - error, - ); + (resolvedItem) => { + incrementalContext.completed = true; + return buildStreamItemResult(incrementalContext.errors, resolvedItem); + }, + (error: unknown) => { + incrementalContext.completed = true; + return { + errors: withError(incrementalContext.errors, error as GraphQLError), + }; }, ); - - return streamItemsRecord; } - let completedItem: PromiseOrValue; + let result: PromiseOrValue>; try { try { - completedItem = completeValue( + result = completeValue( exeContext, itemType, - fieldGroup, + fieldDetailsList, info, itemPath, item, - streamItemsRecord, + incrementalContext, new Map(), ); } catch (rawError) { @@ -2034,200 +2722,58 @@ function executeStreamField( rawError, exeContext, itemType, - fieldGroup, + fieldDetailsList, itemPath, - streamItemsRecord, + incrementalContext, ); - completedItem = null; - incrementalPublisher.filter(itemPath, streamItemsRecord); + result = { rawResult: null, incrementalDataRecords: undefined }; } } catch (error) { - incrementalPublisher.filter(path, streamItemsRecord); - incrementalPublisher.markErroredStreamItemsRecord(streamItemsRecord, error); - return streamItemsRecord; + incrementalContext.completed = true; + return { + errors: withError(incrementalContext.errors, error), + }; } - if (isPromise(completedItem)) { - completedItem - .then(undefined, (rawError) => { + if (isPromise(result)) { + return result + .then(undefined, (rawError: unknown) => { handleFieldError( rawError, exeContext, itemType, - fieldGroup, + fieldDetailsList, itemPath, - streamItemsRecord, + incrementalContext, ); - incrementalPublisher.filter(itemPath, streamItemsRecord); - return null; + return { rawResult: null, incrementalDataRecords: undefined }; }) .then( - (value) => - incrementalPublisher.completeStreamItemsRecord(streamItemsRecord, [ - value, - ]), - (error) => { - incrementalPublisher.filter(path, streamItemsRecord); - incrementalPublisher.markErroredStreamItemsRecord( - streamItemsRecord, - error, - ); + (resolvedItem) => { + incrementalContext.completed = true; + return buildStreamItemResult(incrementalContext.errors, resolvedItem); + }, + (error: unknown) => { + incrementalContext.completed = true; + return { + errors: withError(incrementalContext.errors, error as GraphQLError), + }; }, ); - - return streamItemsRecord; - } - - incrementalPublisher.completeStreamItemsRecord(streamItemsRecord, [ - completedItem, - ]); - return streamItemsRecord; -} - -async function executeStreamAsyncIteratorItem( - asyncIterator: AsyncIterator, - exeContext: ExecutionContext, - fieldGroup: FieldGroup, - info: GraphQLResolveInfo, - itemType: GraphQLOutputType, - streamItemsRecord: StreamItemsRecord, - itemPath: Path, -): Promise> { - let item; - try { - const iteration = await asyncIterator.next(); - if (streamItemsRecord.streamRecord.errors.length > 0) { - return { done: true, value: undefined }; - } - if (iteration.done) { - exeContext.incrementalPublisher.setIsCompletedAsyncIterator( - streamItemsRecord, - ); - return { done: true, value: undefined }; - } - item = iteration.value; - } catch (rawError) { - throw locatedError( - rawError, - toNodes(fieldGroup), - streamItemsRecord.streamRecord.path, - ); } - let completedItem; - try { - completedItem = completeValue( - exeContext, - itemType, - fieldGroup, - info, - itemPath, - item, - streamItemsRecord, - new Map(), - ); - if (isPromise(completedItem)) { - completedItem = completedItem.then(undefined, (rawError) => { - handleFieldError( - rawError, - exeContext, - itemType, - fieldGroup, - itemPath, - streamItemsRecord, - ); - exeContext.incrementalPublisher.filter(itemPath, streamItemsRecord); - return null; - }); - } - return { done: false, value: completedItem }; - } catch (rawError) { - handleFieldError( - rawError, - exeContext, - itemType, - fieldGroup, - itemPath, - streamItemsRecord, - ); - exeContext.incrementalPublisher.filter(itemPath, streamItemsRecord); - return { done: false, value: null }; - } + incrementalContext.completed = true; + return buildStreamItemResult(incrementalContext.errors, result); } -async function executeStreamAsyncIterator( - initialIndex: number, - asyncIterator: AsyncIterator, - exeContext: ExecutionContext, - fieldGroup: FieldGroup, - info: GraphQLResolveInfo, - itemType: GraphQLOutputType, - path: Path, - incrementalDataRecord: IncrementalDataRecord, - streamRecord: StreamRecord, -): Promise { - const incrementalPublisher = exeContext.incrementalPublisher; - let index = initialIndex; - let currentIncrementalDataRecord = incrementalDataRecord; - // eslint-disable-next-line no-constant-condition - while (true) { - const itemPath = addPath(path, index, undefined); - const streamItemsRecord = new StreamItemsRecord({ - streamRecord, - path: itemPath, - }); - incrementalPublisher.reportNewStreamItemsRecord( - streamItemsRecord, - currentIncrementalDataRecord, - ); - - let iteration; - try { - // eslint-disable-next-line no-await-in-loop - iteration = await executeStreamAsyncIteratorItem( - asyncIterator, - exeContext, - fieldGroup, - info, - itemType, - streamItemsRecord, - itemPath, - ); - } catch (error) { - incrementalPublisher.filter(path, streamItemsRecord); - incrementalPublisher.markErroredStreamItemsRecord( - streamItemsRecord, - error, - ); - return; - } - - const { done, value: completedItem } = iteration; - - if (isPromise(completedItem)) { - completedItem.then( - (value) => - incrementalPublisher.completeStreamItemsRecord(streamItemsRecord, [ - value, - ]), - (error) => { - incrementalPublisher.filter(path, streamItemsRecord); - incrementalPublisher.markErroredStreamItemsRecord( - streamItemsRecord, - error, - ); - }, - ); - } else { - incrementalPublisher.completeStreamItemsRecord(streamItemsRecord, [ - completedItem, - ]); - } - - if (done) { - break; - } - currentIncrementalDataRecord = streamItemsRecord; - index++; - } +function buildStreamItemResult( + errors: ReadonlyArray | undefined, + result: GraphQLWrappedResult, +): StreamItemResult { + const { rawResult: item, incrementalDataRecords } = result; + return { + item, + errors, + incrementalDataRecords, + }; } diff --git a/src/execution/getVariableSignature.ts b/src/execution/getVariableSignature.ts new file mode 100644 index 0000000000..ab1ef4ff78 --- /dev/null +++ b/src/execution/getVariableSignature.ts @@ -0,0 +1,51 @@ +import { GraphQLError } from '../error/GraphQLError.js'; + +import type { + ConstValueNode, + VariableDefinitionNode, +} from '../language/ast.js'; +import { print } from '../language/printer.js'; + +import { isInputType } from '../type/definition.js'; +import type { GraphQLInputType, GraphQLSchema } from '../type/index.js'; + +import { typeFromAST } from '../utilities/typeFromAST.js'; + +/** + * A GraphQLVariableSignature is required to coerce a variable value. + * + * Designed to have comparable interface to GraphQLArgument so that + * getArgumentValues() can be reused for fragment arguments. + * */ +export interface GraphQLVariableSignature { + name: string; + type: GraphQLInputType; + defaultValue?: never; + default: { literal: ConstValueNode } | undefined; +} + +export function getVariableSignature( + schema: GraphQLSchema, + varDefNode: VariableDefinitionNode, +): GraphQLVariableSignature | GraphQLError { + const varName = varDefNode.variable.name.value; + const varType = typeFromAST(schema, varDefNode.type); + + if (!isInputType(varType)) { + // Must use input types for variables. This should be caught during + // validation, however is checked again here for safety. + const varTypeStr = print(varDefNode.type); + return new GraphQLError( + `Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`, + { nodes: varDefNode.type }, + ); + } + + const defaultValue = varDefNode.defaultValue; + + return { + name: varName, + type: varType, + default: defaultValue && { literal: defaultValue }, + }; +} diff --git a/src/execution/index.ts b/src/execution/index.ts index 9d481ea6af..fe9764c64f 100644 --- a/src/execution/index.ts +++ b/src/execution/index.ts @@ -3,14 +3,17 @@ export { pathToArray as responsePathAsArray } from '../jsutils/Path.js'; export { createSourceEventStream, execute, + executeQueryOrMutationOrSubscriptionEvent, + executeSubscriptionEvent, experimentalExecuteIncrementally, + experimentalExecuteQueryOrMutationOrSubscriptionEvent, executeSync, defaultFieldResolver, defaultTypeResolver, subscribe, } from './execute.js'; -export type { ExecutionArgs } from './execute.js'; +export type { ExecutionArgs, ValidatedExecutionArgs } from './execute.js'; export type { ExecutionResult, @@ -26,7 +29,7 @@ export type { FormattedIncrementalDeferResult, FormattedIncrementalStreamResult, FormattedIncrementalResult, -} from './IncrementalPublisher.js'; +} from './types.js'; export { getArgumentValues, diff --git a/src/execution/mapAsyncIterable.ts b/src/execution/mapAsyncIterable.ts index 0f6fd78c2d..01810141d5 100644 --- a/src/execution/mapAsyncIterable.ts +++ b/src/execution/mapAsyncIterable.ts @@ -7,18 +7,28 @@ import type { PromiseOrValue } from '../jsutils/PromiseOrValue.js'; export function mapAsyncIterable( iterable: AsyncGenerator | AsyncIterable, callback: (value: T) => PromiseOrValue, + onDone?: () => void, ): AsyncGenerator { const iterator = iterable[Symbol.asyncIterator](); async function mapResult( - result: IteratorResult, + promise: Promise>, ): Promise> { - if (result.done) { - return result; + let value: T; + try { + const result = await promise; + if (result.done) { + onDone?.(); + return result; + } + value = result.value; + } catch (error) { + onDone?.(); + throw error; } try { - return { value: await callback(result.value), done: false }; + return { value: await callback(value), done: false }; } catch (error) { /* c8 ignore start */ // FIXME: add test case @@ -36,17 +46,17 @@ export function mapAsyncIterable( return { async next() { - return mapResult(await iterator.next()); + return mapResult(iterator.next()); }, async return(): Promise> { // If iterator.return() does not exist, then type R must be undefined. return typeof iterator.return === 'function' - ? mapResult(await iterator.return()) + ? mapResult(iterator.return()) : { value: undefined as any, done: true }; }, async throw(error?: unknown) { if (typeof iterator.throw === 'function') { - return mapResult(await iterator.throw(error)); + return mapResult(iterator.throw(error)); } throw error; }, diff --git a/src/execution/types.ts b/src/execution/types.ts new file mode 100644 index 0000000000..87d47e3efc --- /dev/null +++ b/src/execution/types.ts @@ -0,0 +1,284 @@ +import type { BoxedPromiseOrValue } from '../jsutils/BoxedPromiseOrValue.js'; +import type { ObjMap } from '../jsutils/ObjMap.js'; +import type { Path } from '../jsutils/Path.js'; + +import type { + GraphQLError, + GraphQLFormattedError, +} from '../error/GraphQLError.js'; + +/** + * The result of GraphQL execution. + * + * - `errors` is included when any errors occurred as a non-empty array. + * - `data` is the result of a successful execution of the query. + * - `hasNext` is true if a future payload is expected. + * - `extensions` is reserved for adding non-standard properties. + * - `incremental` is a list of the results from defer/stream directives. + */ +export interface ExecutionResult< + TData = ObjMap, + TExtensions = ObjMap, +> { + errors?: ReadonlyArray; + data?: TData | null; + extensions?: TExtensions; +} + +export interface FormattedExecutionResult< + TData = ObjMap, + TExtensions = ObjMap, +> { + errors?: ReadonlyArray; + data?: TData | null; + extensions?: TExtensions; +} + +export interface ExperimentalIncrementalExecutionResults< + TInitial = ObjMap, + TSubsequent = unknown, + TExtensions = ObjMap, +> { + initialResult: InitialIncrementalExecutionResult; + subsequentResults: AsyncGenerator< + SubsequentIncrementalExecutionResult, + void, + void + >; +} + +export interface InitialIncrementalExecutionResult< + TData = ObjMap, + TExtensions = ObjMap, +> extends ExecutionResult { + data: TData; + pending: ReadonlyArray; + hasNext: true; + extensions?: TExtensions; +} + +export interface FormattedInitialIncrementalExecutionResult< + TData = ObjMap, + TExtensions = ObjMap, +> extends FormattedExecutionResult { + data: TData; + pending: ReadonlyArray; + hasNext: boolean; + extensions?: TExtensions; +} + +export interface SubsequentIncrementalExecutionResult< + TData = unknown, + TExtensions = ObjMap, +> { + pending?: ReadonlyArray; + incremental?: ReadonlyArray>; + completed?: ReadonlyArray; + hasNext: boolean; + extensions?: TExtensions; +} + +export interface FormattedSubsequentIncrementalExecutionResult< + TData = unknown, + TExtensions = ObjMap, +> { + hasNext: boolean; + pending?: ReadonlyArray; + incremental?: ReadonlyArray>; + completed?: ReadonlyArray; + extensions?: TExtensions; +} + +interface ExecutionGroupResult> { + errors?: ReadonlyArray; + data: TData; +} + +export interface IncrementalDeferResult< + TData = ObjMap, + TExtensions = ObjMap, +> extends ExecutionGroupResult { + id: string; + subPath?: ReadonlyArray; + extensions?: TExtensions; +} + +export interface FormattedIncrementalDeferResult< + TData = ObjMap, + TExtensions = ObjMap, +> { + errors?: ReadonlyArray; + data: TData; + id: string; + subPath?: ReadonlyArray; + extensions?: TExtensions; +} + +interface StreamItemsRecordResult> { + errors?: ReadonlyArray; + items: TData; +} + +export interface IncrementalStreamResult< + TData = ReadonlyArray, + TExtensions = ObjMap, +> extends StreamItemsRecordResult { + id: string; + subPath?: ReadonlyArray; + extensions?: TExtensions; +} + +export interface FormattedIncrementalStreamResult< + TData = Array, + TExtensions = ObjMap, +> { + errors?: ReadonlyArray; + items: TData; + id: string; + subPath?: ReadonlyArray; + extensions?: TExtensions; +} + +export type IncrementalResult> = + | IncrementalDeferResult + | IncrementalStreamResult; + +export type FormattedIncrementalResult< + TData = unknown, + TExtensions = ObjMap, +> = + | FormattedIncrementalDeferResult + | FormattedIncrementalStreamResult; + +export interface PendingResult { + id: string; + path: ReadonlyArray; + label?: string; +} + +export interface CompletedResult { + id: string; + errors?: ReadonlyArray; +} + +export interface FormattedCompletedResult { + path: ReadonlyArray; + label?: string; + errors?: ReadonlyArray; +} + +export function isPendingExecutionGroup( + incrementalDataRecord: IncrementalDataRecord, +): incrementalDataRecord is PendingExecutionGroup { + return 'deferredFragmentRecords' in incrementalDataRecord; +} + +export type CompletedExecutionGroup = + | SuccessfulExecutionGroup + | FailedExecutionGroup; + +export function isCompletedExecutionGroup( + incrementalDataRecordResult: IncrementalDataRecordResult, +): incrementalDataRecordResult is CompletedExecutionGroup { + return 'pendingExecutionGroup' in incrementalDataRecordResult; +} + +export interface SuccessfulExecutionGroup { + pendingExecutionGroup: PendingExecutionGroup; + path: Array; + result: ExecutionGroupResult; + incrementalDataRecords: ReadonlyArray | undefined; + errors?: never; +} + +interface FailedExecutionGroup { + pendingExecutionGroup: PendingExecutionGroup; + path: Array; + errors: ReadonlyArray; + result?: never; +} + +export function isFailedExecutionGroup( + completedExecutionGroup: CompletedExecutionGroup, +): completedExecutionGroup is FailedExecutionGroup { + return completedExecutionGroup.errors !== undefined; +} + +type ThunkIncrementalResult = + | BoxedPromiseOrValue + | (() => BoxedPromiseOrValue); + +export interface PendingExecutionGroup { + deferredFragmentRecords: ReadonlyArray; + result: ThunkIncrementalResult; +} + +export type DeliveryGroup = DeferredFragmentRecord | StreamRecord; + +/** @internal */ +export class DeferredFragmentRecord { + path: Path | undefined; + label: string | undefined; + id?: string | undefined; + parent: DeferredFragmentRecord | undefined; + pendingExecutionGroups: Set; + successfulExecutionGroups: Set; + children: Set; + + constructor( + path: Path | undefined, + label: string | undefined, + parent: DeferredFragmentRecord | undefined, + ) { + this.path = path; + this.label = label; + this.parent = parent; + this.pendingExecutionGroups = new Set(); + this.successfulExecutionGroups = new Set(); + this.children = new Set(); + } +} + +export function isDeferredFragmentRecord( + deliveryGroup: DeliveryGroup, +): deliveryGroup is DeferredFragmentRecord { + return deliveryGroup instanceof DeferredFragmentRecord; +} + +export interface StreamItemResult { + item?: unknown; + incrementalDataRecords?: ReadonlyArray | undefined; + errors?: ReadonlyArray | undefined; +} + +export type StreamItemRecord = ThunkIncrementalResult; + +export interface StreamRecord { + path: Path; + label: string | undefined; + id?: string | undefined; + streamItemQueue: Array; +} + +export interface StreamItemsResult { + streamRecord: StreamRecord; + errors?: ReadonlyArray; + result?: StreamItemsRecordResult; + incrementalDataRecords?: ReadonlyArray | undefined; +} + +export interface CancellableStreamRecord extends StreamRecord { + earlyReturn: () => Promise; +} + +export function isCancellableStreamRecord( + deliveryGroup: DeliveryGroup, +): deliveryGroup is CancellableStreamRecord { + return 'earlyReturn' in deliveryGroup; +} + +export type IncrementalDataRecord = PendingExecutionGroup | StreamRecord; + +export type IncrementalDataRecordResult = + | CompletedExecutionGroup + | StreamItemsResult; diff --git a/src/execution/values.ts b/src/execution/values.ts index 5511911c78..8e0485ae18 100644 --- a/src/execution/values.ts +++ b/src/execution/values.ts @@ -1,6 +1,6 @@ -import { inspect } from '../jsutils/inspect.js'; +import { invariant } from '../jsutils/invariant.js'; import type { Maybe } from '../jsutils/Maybe.js'; -import type { ObjMap } from '../jsutils/ObjMap.js'; +import type { ObjMap, ReadOnlyObjMap } from '../jsutils/ObjMap.js'; import { printPathArray } from '../jsutils/printPathArray.js'; import { GraphQLError } from '../error/GraphQLError.js'; @@ -8,23 +8,46 @@ import { GraphQLError } from '../error/GraphQLError.js'; import type { DirectiveNode, FieldNode, + FragmentSpreadNode, VariableDefinitionNode, } from '../language/ast.js'; import { Kind } from '../language/kinds.js'; -import { print } from '../language/printer.js'; -import type { GraphQLField } from '../type/definition.js'; -import { isInputType, isNonNullType } from '../type/definition.js'; +import type { GraphQLArgument, GraphQLField } from '../type/definition.js'; +import { + isArgument, + isNonNullType, + isRequiredArgument, +} from '../type/definition.js'; import type { GraphQLDirective } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; -import { coerceInputValue } from '../utilities/coerceInputValue.js'; -import { typeFromAST } from '../utilities/typeFromAST.js'; -import { valueFromAST } from '../utilities/valueFromAST.js'; +import { + coerceDefaultValue, + coerceInputLiteral, + coerceInputValue, +} from '../utilities/coerceInputValue.js'; +import { + validateInputLiteral, + validateInputValue, +} from '../utilities/validateInputValue.js'; -type CoercedVariableValues = - | { errors: ReadonlyArray; coerced?: never } - | { coerced: { [variable: string]: unknown }; errors?: never }; +import type { GraphQLVariableSignature } from './getVariableSignature.js'; +import { getVariableSignature } from './getVariableSignature.js'; + +export interface VariableValues { + readonly sources: ReadOnlyObjMap; + readonly coerced: ReadOnlyObjMap; +} + +interface VariableValueSource { + readonly signature: GraphQLVariableSignature; + readonly value?: unknown; +} + +type VariableValuesOrErrors = + | { variableValues: VariableValues; errors?: never } + | { errors: ReadonlyArray; variableValues?: never }; /** * Prepares an object map of variableValues of the correct type based on the @@ -39,12 +62,12 @@ export function getVariableValues( schema: GraphQLSchema, varDefNodes: ReadonlyArray, inputs: { readonly [variable: string]: unknown }, - options?: { maxErrors?: number }, -): CoercedVariableValues { - const errors = []; + options?: { maxErrors?: number; hideSuggestions?: boolean }, +): VariableValuesOrErrors { + const errors: Array = []; const maxErrors = options?.maxErrors; try { - const coerced = coerceVariableValues( + const variableValues = coerceVariableValues( schema, varDefNodes, inputs, @@ -56,10 +79,11 @@ export function getVariableValues( } errors.push(error); }, + options?.hideSuggestions, ); if (errors.length === 0) { - return { coerced }; + return { variableValues }; } } catch (error) { errors.push(error); @@ -73,71 +97,87 @@ function coerceVariableValues( varDefNodes: ReadonlyArray, inputs: { readonly [variable: string]: unknown }, onError: (error: GraphQLError) => void, -): { [variable: string]: unknown } { - const coercedValues: { [variable: string]: unknown } = {}; + hideSuggestions?: Maybe, +): VariableValues { + const sources: ObjMap = Object.create(null); + const coerced: ObjMap = Object.create(null); for (const varDefNode of varDefNodes) { - const varName = varDefNode.variable.name.value; - const varType = typeFromAST(schema, varDefNode.type); - if (!isInputType(varType)) { - // Must use input types for variables. This should be caught during - // validation, however is checked again here for safety. - const varTypeStr = print(varDefNode.type); - onError( - new GraphQLError( - `Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`, - { nodes: varDefNode.type }, - ), - ); + const varSignature = getVariableSignature(schema, varDefNode); + + if (varSignature instanceof GraphQLError) { + onError(varSignature); continue; } + const { name: varName, type: varType } = varSignature; + let value: unknown; if (!Object.hasOwn(inputs, varName)) { + sources[varName] = { signature: varSignature }; if (varDefNode.defaultValue) { - coercedValues[varName] = valueFromAST(varDefNode.defaultValue, varType); - } else if (isNonNullType(varType)) { - const varTypeStr = inspect(varType); - onError( - new GraphQLError( - `Variable "$${varName}" of required type "${varTypeStr}" was not provided.`, - { nodes: varDefNode }, - ), - ); + coerced[varName] = coerceInputLiteral(varDefNode.defaultValue, varType); + continue; + } else if (!isNonNullType(varType)) { + // Non-provided values for nullable variables are omitted. + continue; } - continue; + } else { + value = inputs[varName]; + sources[varName] = { signature: varSignature, value }; } - const value = inputs[varName]; - if (value === null && isNonNullType(varType)) { - const varTypeStr = inspect(varType); - onError( - new GraphQLError( - `Variable "$${varName}" of non-null type "${varTypeStr}" must not be null.`, - { nodes: varDefNode }, - ), + const coercedValue = coerceInputValue(value, varType); + if (coercedValue !== undefined) { + coerced[varName] = coercedValue; + } else { + validateInputValue( + value, + varType, + (error, path) => { + onError( + new GraphQLError( + `Variable "$${varName}" has invalid value${printPathArray(path)}: ${ + error.message + }`, + { nodes: varDefNode, originalError: error }, + ), + ); + }, + hideSuggestions, ); - continue; } + } - coercedValues[varName] = coerceInputValue( - value, - varType, - (path, invalidValue, error) => { - let prefix = - `Variable "$${varName}" got invalid value ` + inspect(invalidValue); - if (path.length > 0) { - prefix += ` at "${varName}${printPathArray(path)}"`; - } - onError( - new GraphQLError(prefix + '; ' + error.message, { - nodes: varDefNode, - originalError: error, - }), - ); - }, - ); + return { sources, coerced }; +} + +export function getFragmentVariableValues( + fragmentSpreadNode: FragmentSpreadNode, + fragmentSignatures: ReadOnlyObjMap, + variableValues: VariableValues, + fragmentVariableValues?: Maybe, + hideSuggestions?: Maybe, +): VariableValues { + const varSignatures: Array = []; + const sources = Object.create(null); + for (const [varName, varSignature] of Object.entries(fragmentSignatures)) { + varSignatures.push(varSignature); + sources[varName] = { + signature: varSignature, + value: + fragmentVariableValues?.sources[varName]?.value ?? + variableValues.sources[varName]?.value, + }; } - return coercedValues; + const coerced = experimentalGetArgumentValues( + fragmentSpreadNode, + varSignatures, + variableValues, + fragmentVariableValues, + hideSuggestions, + ); + + return { sources, coerced }; } /** @@ -151,73 +191,100 @@ function coerceVariableValues( export function getArgumentValues( def: GraphQLField | GraphQLDirective, node: FieldNode | DirectiveNode, - variableValues?: Maybe>, + variableValues?: Maybe, + hideSuggestions?: Maybe, +): { [argument: string]: unknown } { + return experimentalGetArgumentValues( + node, + def.args, + variableValues, + undefined, + hideSuggestions, + ); +} + +export function experimentalGetArgumentValues( + node: FieldNode | DirectiveNode | FragmentSpreadNode, + argDefs: ReadonlyArray, + variableValues: Maybe, + fragmentVariableValues?: Maybe, + hideSuggestions?: Maybe, ): { [argument: string]: unknown } { const coercedValues: { [argument: string]: unknown } = {}; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argumentNodes = node.arguments ?? []; const argNodeMap = new Map(argumentNodes.map((arg) => [arg.name.value, arg])); - for (const argDef of def.args) { + for (const argDef of argDefs) { const name = argDef.name; const argType = argDef.type; const argumentNode = argNodeMap.get(name); - if (argumentNode == null) { - if (argDef.defaultValue !== undefined) { - coercedValues[name] = argDef.defaultValue; - } else if (isNonNullType(argType)) { + if (!argumentNode) { + if (isRequiredArgument(argDef)) { + // Note: ProvidedRequiredArgumentsRule validation should catch this before + // execution. This is a runtime check to ensure execution does not + // continue with an invalid argument value. throw new GraphQLError( - `Argument "${name}" of required type "${inspect(argType)}" ` + - 'was not provided.', + // TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged + `Argument "${isArgument(argDef) ? argDef : argDef.name}" of required type "${argType}" was not provided.`, { nodes: node }, ); } + const coercedDefaultValue = coerceDefaultValue(argDef); + if (coercedDefaultValue !== undefined) { + coercedValues[name] = coercedDefaultValue; + } continue; } const valueNode = argumentNode.value; - let isNull = valueNode.kind === Kind.NULL; + // Variables without a value are treated as if no argument was provided if + // the argument is not required. if (valueNode.kind === Kind.VARIABLE) { const variableName = valueNode.name.value; + const scopedVariableValues = fragmentVariableValues?.sources[variableName] + ? fragmentVariableValues + : variableValues; if ( - variableValues == null || - !Object.hasOwn(variableValues, variableName) + (scopedVariableValues == null || + !Object.hasOwn(scopedVariableValues.coerced, variableName)) && + !isRequiredArgument(argDef) ) { - if (argDef.defaultValue !== undefined) { - coercedValues[name] = argDef.defaultValue; - } else if (isNonNullType(argType)) { - throw new GraphQLError( - `Argument "${name}" of required type "${inspect(argType)}" ` + - `was provided the variable "$${variableName}" which was not provided a runtime value.`, - { nodes: valueNode }, - ); + const coercedDefaultValue = coerceDefaultValue(argDef); + if (coercedDefaultValue !== undefined) { + coercedValues[name] = coercedDefaultValue; } continue; } - isNull = variableValues[variableName] == null; } - - if (isNull && isNonNullType(argType)) { - throw new GraphQLError( - `Argument "${name}" of non-null type "${inspect(argType)}" ` + - 'must not be null.', - { nodes: valueNode }, - ); - } - - const coercedValue = valueFromAST(valueNode, argType, variableValues); + const coercedValue = coerceInputLiteral( + valueNode, + argType, + variableValues, + fragmentVariableValues, + ); if (coercedValue === undefined) { // Note: ValuesOfCorrectTypeRule validation should catch this before // execution. This is a runtime check to ensure execution does not // continue with an invalid argument value. - throw new GraphQLError( - `Argument "${name}" has invalid value ${print(valueNode)}.`, - { nodes: valueNode }, + validateInputLiteral( + valueNode, + argType, + (error, path) => { + // TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged + error.message = `Argument "${isArgument(argDef) ? argDef : argDef.name}" has invalid value${printPathArray( + path, + )}: ${error.message}`; + throw error; + }, + variableValues, + fragmentVariableValues, + hideSuggestions, ); + /* c8 ignore next */ + invariant(false, 'Invalid argument'); } coercedValues[name] = coercedValue; } @@ -238,13 +305,21 @@ export function getArgumentValues( export function getDirectiveValues( directiveDef: GraphQLDirective, node: { readonly directives?: ReadonlyArray | undefined }, - variableValues?: Maybe>, + variableValues?: Maybe, + fragmentVariableValues?: Maybe, + hideSuggestions?: Maybe, ): undefined | { [argument: string]: unknown } { const directiveNode = node.directives?.find( (directive) => directive.name.value === directiveDef.name, ); if (directiveNode) { - return getArgumentValues(directiveDef, directiveNode, variableValues); + return experimentalGetArgumentValues( + directiveNode, + directiveDef.args, + variableValues, + fragmentVariableValues, + hideSuggestions, + ); } } diff --git a/src/graphql.ts b/src/graphql.ts index 0c8187ae0e..ff11025968 100644 --- a/src/graphql.ts +++ b/src/graphql.ts @@ -15,7 +15,7 @@ import { validateSchema } from './type/validate.js'; import { validate } from './validation/validate.js'; import { execute } from './execution/execute.js'; -import type { ExecutionResult } from './execution/IncrementalPublisher.js'; +import type { ExecutionResult } from './execution/types.js'; /** * This is the primary entry point function for fulfilling GraphQL operations @@ -61,12 +61,14 @@ import type { ExecutionResult } from './execution/IncrementalPublisher.js'; export interface GraphQLArgs { schema: GraphQLSchema; source: string | Source; + hideSuggestions?: Maybe; rootValue?: unknown; contextValue?: unknown; variableValues?: Maybe<{ readonly [variable: string]: unknown }>; operationName?: Maybe; fieldResolver?: Maybe>; typeResolver?: Maybe>; + abortSignal?: Maybe; } export function graphql(args: GraphQLArgs): Promise { @@ -101,6 +103,7 @@ function graphqlImpl(args: GraphQLArgs): PromiseOrValue { operationName, fieldResolver, typeResolver, + hideSuggestions, } = args; // Validate Schema @@ -118,7 +121,9 @@ function graphqlImpl(args: GraphQLArgs): PromiseOrValue { } // Validate - const validationErrors = validate(schema, document); + const validationErrors = validate(schema, document, undefined, { + hideSuggestions, + }); if (validationErrors.length > 0) { return { errors: validationErrors }; } @@ -133,5 +138,6 @@ function graphqlImpl(args: GraphQLArgs): PromiseOrValue { operationName, fieldResolver, typeResolver, + hideSuggestions, }); } diff --git a/src/index.ts b/src/index.ts index 1a0f1b4c82..7bba9d8eee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,12 @@ export type { GraphQLArgs } from './graphql.js'; export { graphql, graphqlSync } from './graphql.js'; // Create and operate on GraphQL type definitions and schema. +export type { + GraphQLField, + GraphQLArgument, + GraphQLEnumValue, + GraphQLInputField, +} from './type/index.js'; export { resolveObjMapThunk, resolveReadonlyArrayThunk, @@ -91,10 +97,14 @@ export { isType, isScalarType, isObjectType, + isField, + isArgument, isInterfaceType, isUnionType, isEnumType, + isEnumValue, isInputObjectType, + isInputField, isListType, isNonNullType, isInputType, @@ -116,10 +126,14 @@ export { assertType, assertScalarType, assertObjectType, + assertField, + assertArgument, assertInterfaceType, assertUnionType, assertEnumType, + assertEnumValue, assertInputObjectType, + assertInputField, assertListType, assertNonNullType, assertInputType, @@ -161,23 +175,19 @@ export type { GraphQLSchemaExtensions, GraphQLDirectiveConfig, GraphQLDirectiveExtensions, - GraphQLArgument, GraphQLArgumentConfig, GraphQLArgumentExtensions, GraphQLEnumTypeConfig, GraphQLEnumTypeExtensions, - GraphQLEnumValue, GraphQLEnumValueConfig, GraphQLEnumValueConfigMap, GraphQLEnumValueExtensions, - GraphQLField, GraphQLFieldConfig, GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldExtensions, GraphQLFieldMap, GraphQLFieldResolver, - GraphQLInputField, GraphQLInputFieldConfig, GraphQLInputFieldConfigMap, GraphQLInputFieldExtensions, @@ -199,9 +209,16 @@ export type { GraphQLScalarSerializer, GraphQLScalarValueParser, GraphQLScalarLiteralParser, + GraphQLScalarOutputValueCoercer, + GraphQLScalarInputValueCoercer, + GraphQLScalarInputLiteralCoercer, + GraphQLDefaultInput, } from './type/index.js'; // Parse and operate on GraphQL language source files. +// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313 +// eslint-disable-next-line @typescript-eslint/consistent-type-exports +export { Kind } from './language/kinds.js'; export { Token, Source, @@ -226,13 +243,11 @@ export { visitInParallel, getEnterLeaveForKind, BREAK, - Kind, DirectiveLocation, // Predicates isDefinitionNode, isExecutableDefinitionNode, isSelectionNode, - isNullabilityAssertionNode, isValueNode, isConstValueNode, isTypeNode, @@ -264,10 +279,7 @@ export type { SelectionNode, FieldNode, ArgumentNode, - NullabilityAssertionNode, - NonNullAssertionNode, - ErrorBoundaryNode, - ListNullabilityOperatorNode, + FragmentArgumentNode, ConstArgumentNode, FragmentSpreadNode, InlineFragmentNode, @@ -320,7 +332,10 @@ export type { // Execute GraphQL queries. export { execute, + executeQueryOrMutationOrSubscriptionEvent, + executeSubscriptionEvent, experimentalExecuteIncrementally, + experimentalExecuteQueryOrMutationOrSubscriptionEvent, executeSync, defaultFieldResolver, defaultTypeResolver, @@ -334,6 +349,7 @@ export { export type { ExecutionArgs, + ValidatedExecutionArgs, ExecutionResult, ExperimentalIncrementalExecutionResults, InitialIncrementalExecutionResult, @@ -355,6 +371,7 @@ export { ValidationContext, // All validation rules in the GraphQL Specification. specifiedRules, + recommendedRules, // Individual validation rules. ExecutableDefinitionsRule, FieldsOnCorrectTypeRule, @@ -362,6 +379,7 @@ export { KnownArgumentNamesRule, KnownDirectivesRule, KnownFragmentNamesRule, + KnownOperationTypesRule, KnownTypeNamesRule, LoneAnonymousOperationRule, NoFragmentCyclesRule, @@ -382,6 +400,7 @@ export { ValuesOfCorrectTypeRule, VariablesAreInputTypesRule, VariablesInAllowedPositionRule, + MaxIntrospectionDepthRule, // SDL-specific validation rules LoneSchemaDefinitionRule, UniqueOperationTypesRule, @@ -405,6 +424,7 @@ export type { GraphQLErrorOptions, GraphQLFormattedError, GraphQLErrorExtensions, + GraphQLFormattedErrorExtensions, } from './error/index.js'; // Utilities for operating on GraphQL type schema and parsed sources. @@ -437,16 +457,28 @@ export { // Create a GraphQLType from a GraphQL language AST. typeFromAST, // Create a JavaScript value from a GraphQL language AST with a Type. + /** @deprecated use `coerceInputLiteral()` instead - will be removed in v18 */ valueFromAST, // Create a JavaScript value from a GraphQL language AST without a Type. valueFromASTUntyped, // Create a GraphQL language AST from a JavaScript value. + /** @deprecated use `valueToLiteral()` instead with care to operate on external values - `astFromValue()` will be removed in v18 */ astFromValue, // A helper to use within recursive-descent visitors which need to be aware of the GraphQL type system. TypeInfo, visitWithTypeInfo, - // Coerces a JavaScript value to a GraphQL type, or produces errors. + // Converts a value to a const value by replacing variables. + replaceVariables, + // Create a GraphQL literal (AST) from a JavaScript input value. + valueToLiteral, + // Coerces a JavaScript value to a GraphQL type, or returns undefined. coerceInputValue, + // Coerces a GraphQL literal (AST) to a GraphQL type, or returns undefined. + coerceInputLiteral, + // Validate a JavaScript value with a GraphQL type, collecting all errors. + validateInputValue, + // Validate a GraphQL literal (AST) with a GraphQL type, collecting all errors. + validateInputLiteral, // Concatenates multiple AST together. concatAST, // Separates an AST into an AST per Operation. @@ -460,8 +492,10 @@ export { // Compares two GraphQLSchemas and detects breaking changes. BreakingChangeType, DangerousChangeType, + SafeChangeType, findBreakingChanges, findDangerousChanges, + findSchemaChanges, } from './utilities/index.js'; export type { @@ -489,6 +523,7 @@ export type { IntrospectionDirective, BuildSchemaOptions, BreakingChange, + SafeChange, DangerousChange, TypedQueryDocumentNode, } from './utilities/index.js'; diff --git a/src/jsutils/AccumulatorMap.ts b/src/jsutils/AccumulatorMap.ts index 156fe71c20..94c7ee26ec 100644 --- a/src/jsutils/AccumulatorMap.ts +++ b/src/jsutils/AccumulatorMap.ts @@ -2,7 +2,7 @@ * ES6 Map with additional `add` method to accumulate items. */ export class AccumulatorMap extends Map> { - get [Symbol.toStringTag]() { + override get [Symbol.toStringTag]() { return 'AccumulatorMap'; } diff --git a/src/jsutils/BoxedPromiseOrValue.ts b/src/jsutils/BoxedPromiseOrValue.ts new file mode 100644 index 0000000000..7f6f758270 --- /dev/null +++ b/src/jsutils/BoxedPromiseOrValue.ts @@ -0,0 +1,26 @@ +import { isPromise } from './isPromise.js'; +import type { PromiseOrValue } from './PromiseOrValue.js'; + +/** + * A BoxedPromiseOrValue is a container for a value or promise where the value + * will be updated when the promise resolves. + * + * A BoxedPromiseOrValue may only be used with promises whose possible + * rejection has already been handled, otherwise this will lead to unhandled + * promise rejections. + * + * @internal + * */ +export class BoxedPromiseOrValue { + value: PromiseOrValue; + + constructor(value: PromiseOrValue) { + this.value = value; + if (isPromise(value)) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + value.then((resolved) => { + this.value = resolved; + }); + } + } +} diff --git a/src/jsutils/ObjMap.ts b/src/jsutils/ObjMap.ts index 2c20282187..c717da6070 100644 --- a/src/jsutils/ObjMap.ts +++ b/src/jsutils/ObjMap.ts @@ -8,6 +8,14 @@ export interface ReadOnlyObjMap { readonly [key: string]: T; } +export interface ReadOnlyObjMapWithSymbol { + readonly [key: string | symbol]: T; +} + export type ReadOnlyObjMapLike = | ReadOnlyObjMap | { readonly [key: string]: T }; + +export type ReadOnlyObjMapSymbolLike = + | ReadOnlyObjMapWithSymbol + | { readonly [key: string | symbol]: T }; diff --git a/src/jsutils/__tests__/BoxedPromiseOrValue-test.ts b/src/jsutils/__tests__/BoxedPromiseOrValue-test.ts new file mode 100644 index 0000000000..19bc79a4bb --- /dev/null +++ b/src/jsutils/__tests__/BoxedPromiseOrValue-test.ts @@ -0,0 +1,30 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js'; + +import { BoxedPromiseOrValue } from '../BoxedPromiseOrValue.js'; + +describe('BoxedPromiseOrValue', () => { + it('can box a value', () => { + const boxed = new BoxedPromiseOrValue(42); + + expect(boxed.value).to.equal(42); + }); + + it('can box a promise', () => { + const promise = Promise.resolve(42); + const boxed = new BoxedPromiseOrValue(promise); + + expect(boxed.value).to.equal(promise); + }); + + it('resets the boxed value when the passed promise resolves', async () => { + const promise = Promise.resolve(42); + const boxed = new BoxedPromiseOrValue(promise); + + await resolveOnNextTick(); + + expect(boxed.value).to.equal(42); + }); +}); diff --git a/src/jsutils/__tests__/suggestionList-test.ts b/src/jsutils/__tests__/suggestionList-test.ts index 06719d8a1e..8a9a05c438 100644 --- a/src/jsutils/__tests__/suggestionList-test.ts +++ b/src/jsutils/__tests__/suggestionList-test.ts @@ -57,13 +57,44 @@ describe('suggestionList', () => { 'ab', 'a', ]); + + expectSuggestions('GraphQl', [ + 'graphics', + 'SQL', + 'GraphQL', + 'quarks', + 'mark', + ]).to.deep.equal(['GraphQL', 'graphics']); }); - it('Returns options with the same lexical distance sorted lexicographically', () => { + it('Returns options with the same lexical distance sorted naturally', () => { expectSuggestions('a', ['az', 'ax', 'ay']).to.deep.equal([ 'ax', 'ay', 'az', ]); + + expectSuggestions('boo', ['moo', 'foo', 'zoo']).to.deep.equal([ + 'foo', + 'moo', + 'zoo', + ]); + + expectSuggestions('abc', ['a1', 'a12', 'a2']).to.deep.equal([ + 'a1', + 'a2', + 'a12', + ]); + }); + + it('Returns options sorted first by lexical distance then naturally', () => { + // cSpell:ignore csutomer, stomer + expectSuggestions('csutomer', [ + 'store', + 'customer', + 'stomer', + 'some', + 'more', + ]).to.deep.equal(['customer', 'stomer', 'some', 'store']); }); }); diff --git a/src/jsutils/instanceOf.ts b/src/jsutils/instanceOf.ts index c84bcb2afc..66811433ae 100644 --- a/src/jsutils/instanceOf.ts +++ b/src/jsutils/instanceOf.ts @@ -1,5 +1,11 @@ import { inspect } from './inspect.js'; +/* c8 ignore next 3 */ +const isProduction = + globalThis.process != null && + // eslint-disable-next-line no-undef + process.env.NODE_ENV === 'production'; + /** * A replacement for instanceof which includes an error warning when multi-realm * constructors are detected. @@ -9,7 +15,7 @@ import { inspect } from './inspect.js'; export const instanceOf: (value: unknown, constructor: Constructor) => boolean = /* c8 ignore next 6 */ // FIXME: https://github.com/graphql/graphql-js/issues/2317 - globalThis.process != null && globalThis.process.env.NODE_ENV === 'production' + isProduction ? function instanceOf(value: unknown, constructor: Constructor): boolean { return value instanceof constructor; } @@ -46,8 +52,9 @@ spurious results.`, return false; }; -interface Constructor extends Function { +interface Constructor { prototype: { [Symbol.toStringTag]: string; }; + new (...args: Array): any; } diff --git a/src/jsutils/invariant.ts b/src/jsutils/invariant.ts index 3d3f8cbe8d..22be960228 100644 --- a/src/jsutils/invariant.ts +++ b/src/jsutils/invariant.ts @@ -3,8 +3,6 @@ export function invariant( message?: string, ): asserts condition { if (!condition) { - throw new Error( - message != null ? message : 'Unexpected invariant triggered.', - ); + throw new Error(message ?? 'Unexpected invariant triggered.'); } } diff --git a/src/jsutils/printPathArray.ts b/src/jsutils/printPathArray.ts index 0d9fcc2b19..e51abf67dc 100644 --- a/src/jsutils/printPathArray.ts +++ b/src/jsutils/printPathArray.ts @@ -2,9 +2,10 @@ * Build a string describing the path. */ export function printPathArray(path: ReadonlyArray): string { - return path - .map((key) => - typeof key === 'number' ? '[' + key.toString() + ']' : '.' + key, - ) - .join(''); + if (path.length === 0) { + return ''; + } + return ` at ${path + .map((key) => (typeof key === 'number' ? `[${key}]` : `.${key}`)) + .join('')}`; } diff --git a/src/jsutils/promiseForObject.ts b/src/jsutils/promiseForObject.ts index ff48d9f218..25b3413923 100644 --- a/src/jsutils/promiseForObject.ts +++ b/src/jsutils/promiseForObject.ts @@ -7,9 +7,10 @@ import type { ObjMap } from './ObjMap.js'; * This is akin to bluebird's `Promise.props`, but implemented only using * `Promise.all` so it will work with any implementation of ES6 promises. */ -export async function promiseForObject( +export async function promiseForObject( object: ObjMap>, -): Promise> { + callback: (object: ObjMap) => U, +): Promise { const keys = Object.keys(object); const values = Object.values(object); @@ -18,5 +19,5 @@ export async function promiseForObject( for (let i = 0; i < keys.length; ++i) { resolvedObject[keys[i]] = resolvedValues[i]; } - return resolvedObject; + return callback(resolvedObject); } diff --git a/src/jsutils/toObjMap.ts b/src/jsutils/toObjMap.ts index c7adab7b34..ef1d475e94 100644 --- a/src/jsutils/toObjMap.ts +++ b/src/jsutils/toObjMap.ts @@ -1,5 +1,10 @@ import type { Maybe } from './Maybe.js'; -import type { ReadOnlyObjMap, ReadOnlyObjMapLike } from './ObjMap.js'; +import type { + ReadOnlyObjMap, + ReadOnlyObjMapLike, + ReadOnlyObjMapSymbolLike, + ReadOnlyObjMapWithSymbol, +} from './ObjMap.js'; export function toObjMap( obj: Maybe>, @@ -16,5 +21,29 @@ export function toObjMap( for (const [key, value] of Object.entries(obj)) { map[key] = value; } + + return map; +} + +export function toObjMapWithSymbols( + obj: Maybe>, +): ReadOnlyObjMapWithSymbol { + if (obj == null) { + return Object.create(null); + } + + if (Object.getPrototypeOf(obj) === null) { + return obj; + } + + const map = Object.create(null); + for (const [key, value] of Object.entries(obj)) { + map[key] = value; + } + + for (const key of Object.getOwnPropertySymbols(obj)) { + map[key] = obj[key]; + } + return map; } diff --git a/src/language/__tests__/kind-test.ts b/src/language/__tests__/kind-test.ts new file mode 100644 index 0000000000..febea2414f --- /dev/null +++ b/src/language/__tests__/kind-test.ts @@ -0,0 +1,30 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions */ +import { describe, it } from 'mocha'; + +import { Kind } from '../index.js'; + +describe('Kind', () => { + it('is a term level namespace with term level enum members', () => { + const a: Kind.NAME = Kind.NAME; + a; + const b: Kind = Kind.NAME; + b; + const c: Kind = Kind.ARGUMENT; + c; + }); + + it('is a type level namespace with type level enum members', () => { + // @ts-expect-error + const a: Kind.NAME = 'bad'; + a; + const b: Kind.NAME = 'Name'; + b; + // @ts-expect-error + const c: Kind = 'bad'; + c; + const d: Kind = 'Name'; + d; + const e: Kind = 'Argument'; + e; + }); +}); diff --git a/src/language/__tests__/lexer-test.ts b/src/language/__tests__/lexer-test.ts index 8ec91df52f..85603dfaaa 100644 --- a/src/language/__tests__/lexer-test.ts +++ b/src/language/__tests__/lexer-test.ts @@ -165,6 +165,13 @@ describe('Lexer', () => { }); }); + it('reports unexpected characters', () => { + expectSyntaxError('.').to.deep.equal({ + message: 'Syntax Error: Unexpected character: ".".', + locations: [{ line: 1, column: 1 }], + }); + }); + it('errors respect whitespace', () => { let caughtError; try { @@ -852,7 +859,8 @@ describe('Lexer', () => { }); expectSyntaxError('.123').to.deep.equal({ - message: 'Syntax Error: Unexpected character: ".".', + message: + 'Syntax Error: Invalid number, expected digit before ".", did you mean "0.123"?', locations: [{ line: 1, column: 1 }], }); @@ -936,13 +944,6 @@ describe('Lexer', () => { value: undefined, }); - expect(lexOne('?')).to.contain({ - kind: TokenKind.QUESTION_MARK, - start: 0, - end: 1, - value: undefined, - }); - expect(lexOne('$')).to.contain({ kind: TokenKind.DOLLAR, start: 0, @@ -1030,7 +1031,7 @@ describe('Lexer', () => { it('lex reports useful unknown character error', () => { expectSyntaxError('..').to.deep.equal({ - message: 'Syntax Error: Unexpected character: ".".', + message: 'Syntax Error: Unexpected "..", did you mean "..."?', locations: [{ line: 1, column: 1 }], }); @@ -1188,7 +1189,6 @@ describe('isPunctuatorTokenKind', () => { it('returns true for punctuator tokens', () => { expect(isPunctuatorToken('!')).to.equal(true); - expect(isPunctuatorToken('?')).to.equal(true); expect(isPunctuatorToken('$')).to.equal(true); expect(isPunctuatorToken('&')).to.equal(true); expect(isPunctuatorToken('(')).to.equal(true); diff --git a/src/language/__tests__/parser-test.ts b/src/language/__tests__/parser-test.ts index 34e9dff4b9..d98b6a6f41 100644 --- a/src/language/__tests__/parser-test.ts +++ b/src/language/__tests__/parser-test.ts @@ -15,10 +15,6 @@ import { parse, parseConstValue, parseType, parseValue } from '../parser.js'; import { Source } from '../source.js'; import { TokenKind } from '../tokenKind.js'; -function parseCCN(source: string) { - return parse(source, { experimentalClientControlledNullability: true }); -} - function expectSyntaxError(text: string) { return expectToThrowJSON(() => parse(text)); } @@ -104,6 +100,11 @@ describe('Parser', () => { ); }); + it('exposes the tokenCount', () => { + expect(parse('{ foo }').tokenCount).to.equal(3); + expect(parse('{ foo(bar: "baz") }').tokenCount).to.equal(8); + }); + it('parses variable inline values', () => { expect(() => parse('{ field(complex: { a: { b: [ $var ] } }) }'), @@ -173,7 +174,7 @@ describe('Parser', () => { }); it('parses kitchen sink', () => { - expect(() => parseCCN(kitchenSinkQuery)).to.not.throw(); + expect(() => parse(kitchenSinkQuery)).to.not.throw(); }); it('allows non-keywords anywhere a Name is allowed', () => { @@ -244,206 +245,6 @@ describe('Parser', () => { ).to.not.throw(); }); - it('parses required field', () => { - const result = parseCCN('{ requiredField! }'); - - expectJSON(result).toDeepNestedProperty( - 'definitions[0].selectionSet.selections[0].nullabilityAssertion', - { - kind: Kind.NON_NULL_ASSERTION, - loc: { start: 15, end: 16 }, - nullabilityAssertion: undefined, - }, - ); - }); - - it('parses optional field', () => { - expect(() => parseCCN('{ optionalField? }')).to.not.throw(); - }); - - it('does not parse field with multiple designators', () => { - expect(() => parseCCN('{ optionalField?! }')).to.throw( - 'Syntax Error: Expected Name, found "!".', - ); - - expect(() => parseCCN('{ optionalField!? }')).to.throw( - 'Syntax Error: Expected Name, found "?".', - ); - }); - - it('parses required with alias', () => { - expect(() => parseCCN('{ requiredField: field! }')).to.not.throw(); - }); - - it('parses optional with alias', () => { - expect(() => parseCCN('{ requiredField: field? }')).to.not.throw(); - }); - - it('does not parse aliased field with bang on left of colon', () => { - expect(() => parseCCN('{ requiredField!: field }')).to.throw(); - }); - - it('does not parse aliased field with question mark on left of colon', () => { - expect(() => parseCCN('{ requiredField?: field }')).to.throw(); - }); - - it('does not parse aliased field with bang on left and right of colon', () => { - expect(() => parseCCN('{ requiredField!: field! }')).to.throw(); - }); - - it('does not parse aliased field with question mark on left and right of colon', () => { - expect(() => parseCCN('{ requiredField?: field? }')).to.throw(); - }); - - it('does not parse designator on query', () => { - expect(() => parseCCN('query? { field }')).to.throw(); - }); - - it('parses required within fragment', () => { - expect(() => - parseCCN('fragment MyFragment on Query { field! }'), - ).to.not.throw(); - }); - - it('parses optional within fragment', () => { - expect(() => - parseCCN('fragment MyFragment on Query { field? }'), - ).to.not.throw(); - }); - - it('parses field with required list elements', () => { - const result = parseCCN('{ field[!] }'); - - expectJSON(result).toDeepNestedProperty( - 'definitions[0].selectionSet.selections[0].nullabilityAssertion', - { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 7, end: 10 }, - nullabilityAssertion: { - kind: Kind.NON_NULL_ASSERTION, - loc: { start: 8, end: 9 }, - nullabilityAssertion: undefined, - }, - }, - ); - }); - - it('parses field with optional list elements', () => { - const result = parseCCN('{ field[?] }'); - - expectJSON(result).toDeepNestedProperty( - 'definitions[0].selectionSet.selections[0].nullabilityAssertion', - { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 7, end: 10 }, - nullabilityAssertion: { - kind: Kind.ERROR_BOUNDARY, - loc: { start: 8, end: 9 }, - nullabilityAssertion: undefined, - }, - }, - ); - }); - - it('parses field with required list', () => { - const result = parseCCN('{ field[]! }'); - - expectJSON(result).toDeepNestedProperty( - 'definitions[0].selectionSet.selections[0].nullabilityAssertion', - { - kind: Kind.NON_NULL_ASSERTION, - loc: { start: 7, end: 10 }, - nullabilityAssertion: { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 7, end: 9 }, - nullabilityAssertion: undefined, - }, - }, - ); - }); - - it('parses field with optional list', () => { - const result = parseCCN('{ field[]? }'); - - expectJSON(result).toDeepNestedProperty( - 'definitions[0].selectionSet.selections[0].nullabilityAssertion', - { - kind: Kind.ERROR_BOUNDARY, - loc: { start: 7, end: 10 }, - nullabilityAssertion: { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 7, end: 9 }, - nullabilityAssertion: undefined, - }, - }, - ); - }); - - it('parses multidimensional field with mixed list elements', () => { - const result = parseCCN('{ field[[[?]!]]! }'); - - expectJSON(result).toDeepNestedProperty( - 'definitions[0].selectionSet.selections[0].nullabilityAssertion', - { - kind: Kind.NON_NULL_ASSERTION, - loc: { start: 7, end: 16 }, - nullabilityAssertion: { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 7, end: 15 }, - nullabilityAssertion: { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 8, end: 14 }, - nullabilityAssertion: { - kind: Kind.NON_NULL_ASSERTION, - loc: { start: 9, end: 13 }, - nullabilityAssertion: { - kind: Kind.LIST_NULLABILITY_OPERATOR, - loc: { start: 9, end: 12 }, - nullabilityAssertion: { - kind: Kind.ERROR_BOUNDARY, - loc: { start: 10, end: 11 }, - nullabilityAssertion: undefined, - }, - }, - }, - }, - }, - }, - ); - }); - - it('does not parse field with unbalanced brackets', () => { - expect(() => parseCCN('{ field[[] }')).to.throw( - 'Syntax Error: Expected "]", found "}".', - ); - - expect(() => parseCCN('{ field[]] }')).to.throw( - 'Syntax Error: Expected Name, found "]".', - ); - - expect(() => parse('{ field] }')).to.throw( - 'Syntax Error: Expected Name, found "]".', - ); - - expect(() => parseCCN('{ field[ }')).to.throw( - 'Syntax Error: Expected "]", found "}".', - ); - }); - - it('does not parse field with assorted invalid nullability designators', () => { - expect(() => parseCCN('{ field[][] }')).to.throw( - 'Syntax Error: Expected Name, found "[".', - ); - - expect(() => parseCCN('{ field[!!] }')).to.throw( - 'Syntax Error: Expected "]", found "!".', - ); - - expect(() => parseCCN('{ field[]?! }')).to.throw( - 'Syntax Error: Expected Name, found "!".', - ); - }); - it('creates ast', () => { const result = parse(dedent` { @@ -463,8 +264,8 @@ describe('Parser', () => { loc: { start: 0, end: 40 }, operation: 'query', name: undefined, - variableDefinitions: [], - directives: [], + variableDefinitions: undefined, + directives: undefined, selectionSet: { kind: Kind.SELECTION_SET, loc: { start: 0, end: 40 }, @@ -494,8 +295,7 @@ describe('Parser', () => { loc: { start: 9, end: 14 }, }, ], - nullabilityAssertion: undefined, - directives: [], + directives: undefined, selectionSet: { kind: Kind.SELECTION_SET, loc: { start: 16, end: 38 }, @@ -509,9 +309,8 @@ describe('Parser', () => { loc: { start: 22, end: 24 }, value: 'id', }, - arguments: [], - nullabilityAssertion: undefined, - directives: [], + arguments: undefined, + directives: undefined, selectionSet: undefined, }, { @@ -523,9 +322,8 @@ describe('Parser', () => { loc: { start: 30, end: 34 }, value: 'name', }, - arguments: [], - nullabilityAssertion: undefined, - directives: [], + arguments: undefined, + directives: undefined, selectionSet: undefined, }, ], @@ -556,8 +354,8 @@ describe('Parser', () => { loc: { start: 0, end: 29 }, operation: 'query', name: undefined, - variableDefinitions: [], - directives: [], + variableDefinitions: undefined, + directives: undefined, selectionSet: { kind: Kind.SELECTION_SET, loc: { start: 6, end: 29 }, @@ -571,9 +369,8 @@ describe('Parser', () => { loc: { start: 10, end: 14 }, value: 'node', }, - arguments: [], - nullabilityAssertion: undefined, - directives: [], + arguments: undefined, + directives: undefined, selectionSet: { kind: Kind.SELECTION_SET, loc: { start: 15, end: 27 }, @@ -587,9 +384,8 @@ describe('Parser', () => { loc: { start: 21, end: 23 }, value: 'id', }, - arguments: [], - nullabilityAssertion: undefined, - directives: [], + arguments: undefined, + directives: undefined, selectionSet: undefined, }, ], @@ -607,13 +403,32 @@ describe('Parser', () => { expect('loc' in result).to.equal(false); }); - it('Legacy: allows parsing fragment defined variables', () => { + it('allows parsing fragment defined variables', () => { const document = 'fragment a($v: Boolean = false) on t { f(v: $v) }'; expect(() => - parse(document, { allowLegacyFragmentVariables: true }), + parse(document, { experimentalFragmentArguments: true }), ).to.not.throw(); - expect(() => parse(document)).to.throw('Syntax Error'); + }); + + it('disallows parsing fragment defined variables without experimental flag', () => { + const document = 'fragment a($v: Boolean = false) on t { f(v: $v) }'; + + expect(() => parse(document)).to.throw(); + }); + + it('allows parsing fragment spread arguments', () => { + const document = 'fragment a on t { ...b(v: $v) }'; + + expect(() => + parse(document, { experimentalFragmentArguments: true }), + ).to.not.throw(); + }); + + it('disallows parsing fragment spread arguments without experimental flag', () => { + const document = 'fragment a on t { ...b(v: $v) }'; + + expect(() => parse(document)).to.throw(); }); it('contains location that can be Object.toStringified, JSON.stringified, or jsutils.inspected', () => { diff --git a/src/language/__tests__/predicates-test.ts b/src/language/__tests__/predicates-test.ts index 55e5782648..7eeb682f3f 100644 --- a/src/language/__tests__/predicates-test.ts +++ b/src/language/__tests__/predicates-test.ts @@ -8,7 +8,6 @@ import { isConstValueNode, isDefinitionNode, isExecutableDefinitionNode, - isNullabilityAssertionNode, isSelectionNode, isTypeDefinitionNode, isTypeExtensionNode, @@ -28,30 +27,30 @@ function filterNodes(predicate: (node: ASTNode) => boolean): Array { describe('AST node predicates', () => { it('isDefinitionNode', () => { expect(filterNodes(isDefinitionNode)).to.deep.equal([ - 'OperationDefinition', - 'FragmentDefinition', - 'SchemaDefinition', - 'ScalarTypeDefinition', - 'ObjectTypeDefinition', - 'InterfaceTypeDefinition', - 'UnionTypeDefinition', + 'DirectiveDefinition', 'EnumTypeDefinition', + 'EnumTypeExtension', + 'FragmentDefinition', 'InputObjectTypeDefinition', - 'DirectiveDefinition', - 'SchemaExtension', - 'ScalarTypeExtension', - 'ObjectTypeExtension', + 'InputObjectTypeExtension', + 'InterfaceTypeDefinition', 'InterfaceTypeExtension', + 'ObjectTypeDefinition', + 'ObjectTypeExtension', + 'OperationDefinition', + 'ScalarTypeDefinition', + 'ScalarTypeExtension', + 'SchemaDefinition', + 'SchemaExtension', + 'UnionTypeDefinition', 'UnionTypeExtension', - 'EnumTypeExtension', - 'InputObjectTypeExtension', ]); }); it('isExecutableDefinitionNode', () => { expect(filterNodes(isExecutableDefinitionNode)).to.deep.equal([ - 'OperationDefinition', 'FragmentDefinition', + 'OperationDefinition', ]); }); @@ -63,25 +62,17 @@ describe('AST node predicates', () => { ]); }); - it('isNullabilityAssertionNode', () => { - expect(filterNodes(isNullabilityAssertionNode)).to.deep.equal([ - 'ListNullabilityOperator', - 'NonNullAssertion', - 'ErrorBoundary', - ]); - }); - it('isValueNode', () => { expect(filterNodes(isValueNode)).to.deep.equal([ - 'Variable', - 'IntValue', - 'FloatValue', - 'StringValue', 'BooleanValue', - 'NullValue', 'EnumValue', + 'FloatValue', + 'IntValue', 'ListValue', + 'NullValue', 'ObjectValue', + 'StringValue', + 'Variable', ]); }); @@ -98,56 +89,56 @@ describe('AST node predicates', () => { it('isTypeNode', () => { expect(filterNodes(isTypeNode)).to.deep.equal([ - 'NamedType', 'ListType', + 'NamedType', 'NonNullType', ]); }); it('isTypeSystemDefinitionNode', () => { expect(filterNodes(isTypeSystemDefinitionNode)).to.deep.equal([ - 'SchemaDefinition', - 'ScalarTypeDefinition', - 'ObjectTypeDefinition', - 'InterfaceTypeDefinition', - 'UnionTypeDefinition', + 'DirectiveDefinition', 'EnumTypeDefinition', 'InputObjectTypeDefinition', - 'DirectiveDefinition', + 'InterfaceTypeDefinition', + 'ObjectTypeDefinition', + 'ScalarTypeDefinition', + 'SchemaDefinition', + 'UnionTypeDefinition', ]); }); it('isTypeDefinitionNode', () => { expect(filterNodes(isTypeDefinitionNode)).to.deep.equal([ - 'ScalarTypeDefinition', - 'ObjectTypeDefinition', - 'InterfaceTypeDefinition', - 'UnionTypeDefinition', 'EnumTypeDefinition', 'InputObjectTypeDefinition', + 'InterfaceTypeDefinition', + 'ObjectTypeDefinition', + 'ScalarTypeDefinition', + 'UnionTypeDefinition', ]); }); it('isTypeSystemExtensionNode', () => { expect(filterNodes(isTypeSystemExtensionNode)).to.deep.equal([ - 'SchemaExtension', - 'ScalarTypeExtension', - 'ObjectTypeExtension', - 'InterfaceTypeExtension', - 'UnionTypeExtension', 'EnumTypeExtension', 'InputObjectTypeExtension', + 'InterfaceTypeExtension', + 'ObjectTypeExtension', + 'ScalarTypeExtension', + 'SchemaExtension', + 'UnionTypeExtension', ]); }); it('isTypeExtensionNode', () => { expect(filterNodes(isTypeExtensionNode)).to.deep.equal([ - 'ScalarTypeExtension', - 'ObjectTypeExtension', - 'InterfaceTypeExtension', - 'UnionTypeExtension', 'EnumTypeExtension', 'InputObjectTypeExtension', + 'InterfaceTypeExtension', + 'ObjectTypeExtension', + 'ScalarTypeExtension', + 'UnionTypeExtension', ]); }); }); diff --git a/src/language/__tests__/printer-test.ts b/src/language/__tests__/printer-test.ts index 7eea508458..624dc75ca2 100644 --- a/src/language/__tests__/printer-test.ts +++ b/src/language/__tests__/printer-test.ts @@ -168,46 +168,68 @@ describe('Printer: Query document', () => { `); }); - it('Legacy: prints fragment with variable directives', () => { - const queryASTWithVariableDirective = parse( + it('prints fragment with argument definition directives', () => { + const fragmentWithArgumentDefinitionDirective = parse( 'fragment Foo($foo: TestType @test) on TestType @testDirective { id }', - { allowLegacyFragmentVariables: true }, + { experimentalFragmentArguments: true }, ); - expect(print(queryASTWithVariableDirective)).to.equal(dedent` + expect(print(fragmentWithArgumentDefinitionDirective)).to.equal(dedent` fragment Foo($foo: TestType @test) on TestType @testDirective { id } `); }); - it('Legacy: correctly prints fragment defined variables', () => { - const fragmentWithVariable = parse( + it('correctly prints fragment defined arguments', () => { + const fragmentWithArgumentDefinition = parse( ` fragment Foo($a: ComplexType, $b: Boolean = false) on TestType { id } `, - { allowLegacyFragmentVariables: true }, + { experimentalFragmentArguments: true }, ); - expect(print(fragmentWithVariable)).to.equal(dedent` + expect(print(fragmentWithArgumentDefinition)).to.equal(dedent` fragment Foo($a: ComplexType, $b: Boolean = false) on TestType { id } `); }); + it('prints fragment spread with arguments', () => { + const fragmentSpreadWithArguments = parse( + 'fragment Foo on TestType { ...Bar(a: {x: $x}, b: true) }', + { experimentalFragmentArguments: true }, + ); + expect(print(fragmentSpreadWithArguments)).to.equal(dedent` + fragment Foo on TestType { + ...Bar(a: { x: $x }, b: true) + } + `); + }); + + it('prints fragment spread with multi-line arguments', () => { + const fragmentSpreadWithArguments = parse( + 'fragment Foo on TestType { ...Bar(a: {x: $x, y: $y, z: $z, xy: $xy}, b: true, c: "a long string extending arguments over max length") }', + { experimentalFragmentArguments: true }, + ); + expect(print(fragmentSpreadWithArguments)).to.equal(dedent` + fragment Foo on TestType { + ...Bar( + a: { x: $x, y: $y, z: $z, xy: $xy } + b: true + c: "a long string extending arguments over max length" + ) + } + `); + }); + it('prints kitchen sink without altering ast', () => { - const ast = parse(kitchenSinkQuery, { - noLocation: true, - experimentalClientControlledNullability: true, - }); + const ast = parse(kitchenSinkQuery, { noLocation: true }); const astBeforePrintCall = JSON.stringify(ast); const printed = print(ast); - const printedAST = parse(printed, { - noLocation: true, - experimentalClientControlledNullability: true, - }); + const printedAST = parse(printed, { noLocation: true }); expect(printedAST).to.deep.equal(ast); expect(JSON.stringify(ast)).to.equal(astBeforePrintCall); @@ -225,19 +247,6 @@ describe('Printer: Query document', () => { ...frag @onFragmentSpread } } - field3! - field4? - requiredField5: field5! - requiredSelectionSet(first: 10)! @directive { - field - } - unsetListItemsRequiredList: listField[]! - requiredListItemsUnsetList: listField[!] - requiredListItemsRequiredList: listField[!]! - unsetListItemsOptionalList: listField[]? - optionalListItemsUnsetList: listField[?] - optionalListItemsOptionalList: listField[?]? - multidimensionalList: listField[[[!]!]!]! } ... @skip(unless: $foo) { id diff --git a/src/language/__tests__/schema-parser-test.ts b/src/language/__tests__/schema-parser-test.ts index 27ac5c1bfb..3780c8330f 100644 --- a/src/language/__tests__/schema-parser-test.ts +++ b/src/language/__tests__/schema-parser-test.ts @@ -31,7 +31,7 @@ function nameNode(name: unknown, loc: unknown) { } function fieldNode(name: unknown, type: unknown, loc: unknown) { - return fieldNodeWithArgs(name, type, [], loc); + return fieldNodeWithArgs(name, type, undefined, loc); } function fieldNodeWithArgs( @@ -46,7 +46,7 @@ function fieldNodeWithArgs( name, arguments: args, type, - directives: [], + directives: undefined, loc, }; } @@ -56,7 +56,7 @@ function enumValueNode(name: unknown, loc: unknown) { kind: 'EnumValueDefinition', name: nameNode(name, loc), description: undefined, - directives: [], + directives: undefined, loc, }; } @@ -73,7 +73,7 @@ function inputValueNode( description: undefined, type, defaultValue, - directives: [], + directives: undefined, loc, }; } @@ -93,8 +93,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNode( nameNode('world', { start: 15, end: 20 }), @@ -180,8 +180,8 @@ describe('Schema Parser', () => { { kind: 'ObjectTypeExtension', name: nameNode('Hello', { start: 12, end: 17 }), - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNode( nameNode('world', { start: 22, end: 27 }), @@ -206,8 +206,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeExtension', name: nameNode('Hello', { start: 12, end: 17 }), interfaces: [typeNode('Greeting', { start: 29, end: 37 })], - directives: [], - fields: [], + directives: undefined, + fields: undefined, loc: { start: 0, end: 37 }, }, ], @@ -224,8 +224,8 @@ describe('Schema Parser', () => { kind: 'InterfaceTypeExtension', name: nameNode('Hello', { start: 17, end: 22 }), interfaces: [typeNode('Greeting', { start: 34, end: 42 })], - directives: [], - fields: [], + directives: undefined, + fields: undefined, loc: { start: 0, end: 42 }, }, ], @@ -247,16 +247,16 @@ describe('Schema Parser', () => { kind: 'ObjectTypeExtension', name: nameNode('Hello', { start: 19, end: 24 }), interfaces: [typeNode('Greeting', { start: 36, end: 44 })], - directives: [], - fields: [], + directives: undefined, + fields: undefined, loc: { start: 7, end: 44 }, }, { kind: 'ObjectTypeExtension', name: nameNode('Hello', { start: 64, end: 69 }), interfaces: [typeNode('SecondGreeting', { start: 81, end: 95 })], - directives: [], - fields: [], + directives: undefined, + fields: undefined, loc: { start: 52, end: 95 }, }, ], @@ -309,16 +309,16 @@ describe('Schema Parser', () => { kind: 'InterfaceTypeExtension', name: nameNode('Hello', { start: 24, end: 29 }), interfaces: [typeNode('Greeting', { start: 41, end: 49 })], - directives: [], - fields: [], + directives: undefined, + fields: undefined, loc: { start: 7, end: 49 }, }, { kind: 'InterfaceTypeExtension', name: nameNode('Hello', { start: 74, end: 79 }), interfaces: [typeNode('SecondGreeting', { start: 91, end: 105 })], - directives: [], - fields: [], + directives: undefined, + fields: undefined, loc: { start: 57, end: 105 }, }, ], @@ -381,7 +381,7 @@ describe('Schema Parser', () => { definitions: [ { kind: 'SchemaExtension', - directives: [], + directives: undefined, operationTypes: [ { kind: 'OperationTypeDefinition', @@ -409,11 +409,11 @@ describe('Schema Parser', () => { { kind: 'Directive', name: nameNode('directive', { start: 15, end: 24 }), - arguments: [], + arguments: undefined, loc: { start: 14, end: 24 }, }, ], - operationTypes: [], + operationTypes: undefined, loc: { start: 0, end: 24 }, }, ], @@ -449,8 +449,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNode( nameNode('world', { start: 15, end: 20 }), @@ -479,7 +479,7 @@ describe('Schema Parser', () => { name: nameNode('Hello', { start: 10, end: 15 }), description: undefined, interfaces: [typeNode('World', { start: 27, end: 32 })], - directives: [], + directives: undefined, fields: [ fieldNode( nameNode('field', { start: 35, end: 40 }), @@ -505,7 +505,7 @@ describe('Schema Parser', () => { name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, interfaces: [typeNode('World', { start: 22, end: 27 })], - directives: [], + directives: undefined, fields: [ fieldNode( nameNode('field', { start: 30, end: 35 }), @@ -534,7 +534,7 @@ describe('Schema Parser', () => { typeNode('Wo', { start: 22, end: 24 }), typeNode('rld', { start: 27, end: 30 }), ], - directives: [], + directives: undefined, fields: [ fieldNode( nameNode('field', { start: 33, end: 38 }), @@ -562,7 +562,7 @@ describe('Schema Parser', () => { typeNode('Wo', { start: 27, end: 29 }), typeNode('rld', { start: 32, end: 35 }), ], - directives: [], + directives: undefined, fields: [ fieldNode( nameNode('field', { start: 38, end: 43 }), @@ -591,7 +591,7 @@ describe('Schema Parser', () => { typeNode('Wo', { start: 24, end: 26 }), typeNode('rld', { start: 29, end: 32 }), ], - directives: [], + directives: undefined, fields: [ fieldNode( nameNode('field', { start: 35, end: 40 }), @@ -621,7 +621,7 @@ describe('Schema Parser', () => { typeNode('Wo', { start: 29, end: 31 }), typeNode('rld', { start: 34, end: 37 }), ], - directives: [], + directives: undefined, fields: [ fieldNode( nameNode('field', { start: 40, end: 45 }), @@ -646,7 +646,7 @@ describe('Schema Parser', () => { kind: 'EnumTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - directives: [], + directives: undefined, values: [enumValueNode('WORLD', { start: 13, end: 18 })], loc: { start: 0, end: 20 }, }, @@ -665,7 +665,7 @@ describe('Schema Parser', () => { kind: 'EnumTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - directives: [], + directives: undefined, values: [ enumValueNode('WO', { start: 13, end: 15 }), enumValueNode('RLD', { start: 17, end: 20 }), @@ -691,8 +691,8 @@ describe('Schema Parser', () => { kind: 'InterfaceTypeDefinition', name: nameNode('Hello', { start: 10, end: 15 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNode( nameNode('world', { start: 20, end: 25 }), @@ -721,8 +721,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNodeWithArgs( nameNode('world', { start: 15, end: 20 }), @@ -759,8 +759,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNodeWithArgs( nameNode('world', { start: 15, end: 20 }), @@ -801,8 +801,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNodeWithArgs( nameNode('world', { start: 15, end: 20 }), @@ -843,8 +843,8 @@ describe('Schema Parser', () => { kind: 'ObjectTypeDefinition', name: nameNode('Hello', { start: 5, end: 10 }), description: undefined, - interfaces: [], - directives: [], + interfaces: undefined, + directives: undefined, fields: [ fieldNodeWithArgs( nameNode('world', { start: 15, end: 20 }), @@ -883,7 +883,7 @@ describe('Schema Parser', () => { kind: 'UnionTypeDefinition', name: nameNode('Hello', { start: 6, end: 11 }), description: undefined, - directives: [], + directives: undefined, types: [typeNode('World', { start: 14, end: 19 })], loc: { start: 0, end: 19 }, }, @@ -902,7 +902,7 @@ describe('Schema Parser', () => { kind: 'UnionTypeDefinition', name: nameNode('Hello', { start: 6, end: 11 }), description: undefined, - directives: [], + directives: undefined, types: [ typeNode('Wo', { start: 14, end: 16 }), typeNode('Rld', { start: 19, end: 22 }), @@ -924,7 +924,7 @@ describe('Schema Parser', () => { kind: 'UnionTypeDefinition', name: nameNode('Hello', { start: 6, end: 11 }), description: undefined, - directives: [], + directives: undefined, types: [ typeNode('Wo', { start: 16, end: 18 }), typeNode('Rld', { start: 21, end: 24 }), @@ -974,7 +974,7 @@ describe('Schema Parser', () => { kind: 'ScalarTypeDefinition', name: nameNode('Hello', { start: 7, end: 12 }), description: undefined, - directives: [], + directives: undefined, loc: { start: 0, end: 12 }, }, ], @@ -995,7 +995,7 @@ input Hello { kind: 'InputObjectTypeDefinition', name: nameNode('Hello', { start: 7, end: 12 }), description: undefined, - directives: [], + directives: undefined, fields: [ inputValueNode( nameNode('world', { start: 17, end: 22 }), @@ -1037,7 +1037,7 @@ input Hello { value: 'foo', loc: { start: 11, end: 14 }, }, - arguments: [], + arguments: undefined, repeatable: false, locations: [ { @@ -1073,7 +1073,7 @@ input Hello { value: 'foo', loc: { start: 11, end: 14 }, }, - arguments: [], + arguments: undefined, repeatable: true, locations: [ { diff --git a/src/language/__tests__/visitor-test.ts b/src/language/__tests__/visitor-test.ts index c70cb783d5..6aceec88b6 100644 --- a/src/language/__tests__/visitor-test.ts +++ b/src/language/__tests__/visitor-test.ts @@ -455,10 +455,10 @@ describe('Visitor', () => { ]); }); - it('Legacy: visits variables defined in fragments', () => { + it('visits arguments defined on fragments', () => { const ast = parse('fragment a($v: Boolean = false) on t { f }', { noLocation: true, - allowLegacyFragmentVariables: true, + experimentalFragmentArguments: true, }); const visited: Array = []; @@ -505,11 +505,53 @@ describe('Visitor', () => { ]); }); - it('properly visits the kitchen sink query', () => { - const ast = parse(kitchenSinkQuery, { - experimentalClientControlledNullability: true, + it('visits arguments on fragment spreads', () => { + const ast = parse('fragment a on t { ...s(v: false) }', { + noLocation: true, + experimentalFragmentArguments: true, }); const visited: Array = []; + + visit(ast, { + enter(node) { + checkVisitorFnArgs(ast, arguments); + visited.push(['enter', node.kind, getValue(node)]); + }, + leave(node) { + checkVisitorFnArgs(ast, arguments); + visited.push(['leave', node.kind, getValue(node)]); + }, + }); + + expect(visited).to.deep.equal([ + ['enter', 'Document', undefined], + ['enter', 'FragmentDefinition', undefined], + ['enter', 'Name', 'a'], + ['leave', 'Name', 'a'], + ['enter', 'NamedType', undefined], + ['enter', 'Name', 't'], + ['leave', 'Name', 't'], + ['leave', 'NamedType', undefined], + ['enter', 'SelectionSet', undefined], + ['enter', 'FragmentSpread', undefined], + ['enter', 'Name', 's'], + ['leave', 'Name', 's'], + ['enter', 'FragmentArgument', { kind: 'BooleanValue', value: false }], + ['enter', 'Name', 'v'], + ['leave', 'Name', 'v'], + ['enter', 'BooleanValue', false], + ['leave', 'BooleanValue', false], + ['leave', 'FragmentArgument', { kind: 'BooleanValue', value: false }], + ['leave', 'FragmentSpread', undefined], + ['leave', 'SelectionSet', undefined], + ['leave', 'FragmentDefinition', undefined], + ['leave', 'Document', undefined], + ]); + }); + + it('properly visits the kitchen sink query', () => { + const ast = parse(kitchenSinkQuery); + const visited: Array = []; const argsStack: Array = []; visit(ast, { @@ -656,272 +698,6 @@ describe('Visitor', () => { ['leave', 'Field', 1, undefined], ['leave', 'SelectionSet', 'selectionSet', 'Field'], ['leave', 'Field', 0, undefined], - ['enter', 'Field', 1, undefined], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 1, undefined], - ['enter', 'Field', 2, undefined], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'ErrorBoundary', 'nullabilityAssertion', 'Field'], - ['leave', 'ErrorBoundary', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 2, undefined], - ['enter', 'Field', 3, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 3, undefined], - ['enter', 'Field', 4, undefined], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'Argument', 0, undefined], - ['enter', 'Name', 'name', 'Argument'], - ['leave', 'Name', 'name', 'Argument'], - ['enter', 'IntValue', 'value', 'Argument'], - ['leave', 'IntValue', 'value', 'Argument'], - ['leave', 'Argument', 0, undefined], - ['enter', 'Directive', 0, undefined], - ['enter', 'Name', 'name', 'Directive'], - ['leave', 'Name', 'name', 'Directive'], - ['leave', 'Directive', 0, undefined], - ['enter', 'SelectionSet', 'selectionSet', 'Field'], - ['enter', 'Field', 0, undefined], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['leave', 'Field', 0, undefined], - ['leave', 'SelectionSet', 'selectionSet', 'Field'], - ['enter', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 4, undefined], - ['enter', 'Field', 5, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - ['leave', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 5, undefined], - ['enter', 'Field', 6, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'ListNullabilityOperator', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - ['leave', 'ListNullabilityOperator', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 6, undefined], - ['enter', 'Field', 7, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'enter', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - ['leave', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 7, undefined], - ['enter', 'Field', 8, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'ErrorBoundary', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'ErrorBoundary', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'ErrorBoundary', - ], - ['leave', 'ErrorBoundary', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 8, undefined], - ['enter', 'Field', 9, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'ListNullabilityOperator', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'ErrorBoundary', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ErrorBoundary', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - ['leave', 'ListNullabilityOperator', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 9, undefined], - ['enter', 'Field', 10, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'ErrorBoundary', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'ErrorBoundary', - ], - [ - 'enter', - 'ErrorBoundary', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ErrorBoundary', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'ErrorBoundary', - ], - ['leave', 'ErrorBoundary', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 10, undefined], - ['enter', 'Field', 11, undefined], - ['enter', 'Name', 'alias', 'Field'], - ['leave', 'Name', 'alias', 'Field'], - ['enter', 'Name', 'name', 'Field'], - ['leave', 'Name', 'name', 'Field'], - ['enter', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'enter', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'enter', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'enter', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'enter', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'leave', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - [ - 'leave', - 'NonNullAssertion', - 'nullabilityAssertion', - 'ListNullabilityOperator', - ], - [ - 'leave', - 'ListNullabilityOperator', - 'nullabilityAssertion', - 'NonNullAssertion', - ], - ['leave', 'NonNullAssertion', 'nullabilityAssertion', 'Field'], - ['leave', 'Field', 11, undefined], ['leave', 'SelectionSet', 'selectionSet', 'InlineFragment'], ['leave', 'InlineFragment', 1, undefined], ['enter', 'InlineFragment', 2, undefined], diff --git a/src/language/ast.ts b/src/language/ast.ts index 22a7cc253c..bce69a6e19 100644 --- a/src/language/ast.ts +++ b/src/language/ast.ts @@ -95,7 +95,7 @@ export class Token { readonly prev: Token | null; readonly next: Token | null; - // eslint-disable-next-line max-params + // eslint-disable-next-line @typescript-eslint/max-params constructor( kind: TokenKind, start: number, @@ -146,6 +146,7 @@ export type ASTNode = | SelectionSetNode | FieldNode | ArgumentNode + | FragmentArgumentNode | FragmentSpreadNode | InlineFragmentNode | FragmentDefinitionNode @@ -180,10 +181,7 @@ export type ASTNode = | InterfaceTypeExtensionNode | UnionTypeExtensionNode | EnumTypeExtensionNode - | InputObjectTypeExtensionNode - | NonNullAssertionNode - | ErrorBoundaryNode - | ListNullabilityOperatorNode; + | InputObjectTypeExtensionNode; /** * Utility type listing all nodes indexed by their kind. @@ -210,28 +208,22 @@ export const QueryDocumentKeys: { VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'], Variable: ['name'], SelectionSet: ['selections'], - Field: [ - 'alias', + Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'], + Argument: ['name', 'value'], + FragmentArgument: ['name', 'value'], + + FragmentSpread: [ 'name', + // Note: Fragment arguments are experimental and may be changed or removed + // in the future. 'arguments', 'directives', - 'selectionSet', - // Note: Client Controlled Nullability is experimental and may be changed - // or removed in the future. - 'nullabilityAssertion', ], - Argument: ['name', 'value'], - // Note: Client Controlled Nullability is experimental and may be changed - // or removed in the future. - ListNullabilityOperator: ['nullabilityAssertion'], - NonNullAssertion: ['nullabilityAssertion'], - ErrorBoundary: ['nullabilityAssertion'], - - FragmentSpread: ['name', 'directives'], InlineFragment: ['typeCondition', 'directives', 'selectionSet'], FragmentDefinition: [ 'name', - // Note: fragment variable definitions are deprecated and will removed in v17.0.0 + // Note: Fragment variables are experimental and may be changed or removed + // in the future. 'variableDefinitions', 'typeCondition', 'directives', @@ -309,7 +301,7 @@ export function isNode(maybeNode: any): maybeNode is ASTNode { /** Name */ export interface NameNode { - readonly kind: Kind.NAME; + readonly kind: typeof Kind.NAME; readonly loc?: Location | undefined; readonly value: string; } @@ -317,9 +309,10 @@ export interface NameNode { /** Document */ export interface DocumentNode { - readonly kind: Kind.DOCUMENT; + readonly kind: typeof Kind.DOCUMENT; readonly loc?: Location | undefined; readonly definitions: ReadonlyArray; + readonly tokenCount?: number | undefined; } export type DefinitionNode = @@ -332,7 +325,7 @@ export type ExecutableDefinitionNode = | FragmentDefinitionNode; export interface OperationDefinitionNode { - readonly kind: Kind.OPERATION_DEFINITION; + readonly kind: typeof Kind.OPERATION_DEFINITION; readonly loc?: Location | undefined; readonly operation: OperationTypeNode; readonly name?: NameNode | undefined; @@ -343,14 +336,17 @@ export interface OperationDefinitionNode { readonly selectionSet: SelectionSetNode; } -export enum OperationTypeNode { - QUERY = 'query', - MUTATION = 'mutation', - SUBSCRIPTION = 'subscription', -} +export const OperationTypeNode = { + QUERY: 'query' as const, + MUTATION: 'mutation' as const, + SUBSCRIPTION: 'subscription' as const, +} as const; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type OperationTypeNode = + (typeof OperationTypeNode)[keyof typeof OperationTypeNode]; export interface VariableDefinitionNode { - readonly kind: Kind.VARIABLE_DEFINITION; + readonly kind: typeof Kind.VARIABLE_DEFINITION; readonly loc?: Location | undefined; readonly variable: VariableNode; readonly type: TypeNode; @@ -359,13 +355,13 @@ export interface VariableDefinitionNode { } export interface VariableNode { - readonly kind: Kind.VARIABLE; + readonly kind: typeof Kind.VARIABLE; readonly loc?: Location | undefined; readonly name: NameNode; } export interface SelectionSetNode { - kind: Kind.SELECTION_SET; + kind: typeof Kind.SELECTION_SET; loc?: Location | undefined; selections: ReadonlyArray; } @@ -373,66 +369,48 @@ export interface SelectionSetNode { export type SelectionNode = FieldNode | FragmentSpreadNode | InlineFragmentNode; export interface FieldNode { - readonly kind: Kind.FIELD; + readonly kind: typeof Kind.FIELD; readonly loc?: Location | undefined; readonly alias?: NameNode | undefined; readonly name: NameNode; readonly arguments?: ReadonlyArray | undefined; - // Note: Client Controlled Nullability is experimental - // and may be changed or removed in the future. - readonly nullabilityAssertion?: NullabilityAssertionNode | undefined; readonly directives?: ReadonlyArray | undefined; readonly selectionSet?: SelectionSetNode | undefined; } -export type NullabilityAssertionNode = - | NonNullAssertionNode - | ErrorBoundaryNode - | ListNullabilityOperatorNode; - -export interface ListNullabilityOperatorNode { - readonly kind: Kind.LIST_NULLABILITY_OPERATOR; - readonly loc?: Location | undefined; - readonly nullabilityAssertion?: NullabilityAssertionNode | undefined; -} - -export interface NonNullAssertionNode { - readonly kind: Kind.NON_NULL_ASSERTION; - readonly loc?: Location | undefined; - readonly nullabilityAssertion?: ListNullabilityOperatorNode | undefined; -} - -export interface ErrorBoundaryNode { - readonly kind: Kind.ERROR_BOUNDARY; - readonly loc?: Location | undefined; - readonly nullabilityAssertion?: ListNullabilityOperatorNode | undefined; -} - export interface ArgumentNode { - readonly kind: Kind.ARGUMENT; + readonly kind: typeof Kind.ARGUMENT; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ValueNode; } export interface ConstArgumentNode { - readonly kind: Kind.ARGUMENT; + readonly kind: typeof Kind.ARGUMENT; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ConstValueNode; } +export interface FragmentArgumentNode { + readonly kind: typeof Kind.FRAGMENT_ARGUMENT; + readonly loc?: Location | undefined; + readonly name: NameNode; + readonly value: ValueNode; +} + /** Fragments */ export interface FragmentSpreadNode { - readonly kind: Kind.FRAGMENT_SPREAD; + readonly kind: typeof Kind.FRAGMENT_SPREAD; readonly loc?: Location | undefined; readonly name: NameNode; + readonly arguments?: ReadonlyArray | undefined; readonly directives?: ReadonlyArray | undefined; } export interface InlineFragmentNode { - readonly kind: Kind.INLINE_FRAGMENT; + readonly kind: typeof Kind.INLINE_FRAGMENT; readonly loc?: Location | undefined; readonly typeCondition?: NamedTypeNode | undefined; readonly directives?: ReadonlyArray | undefined; @@ -440,10 +418,9 @@ export interface InlineFragmentNode { } export interface FragmentDefinitionNode { - readonly kind: Kind.FRAGMENT_DEFINITION; + readonly kind: typeof Kind.FRAGMENT_DEFINITION; readonly loc?: Location | undefined; readonly name: NameNode; - /** @deprecated variableDefinitions will be removed in v17.0.0 */ readonly variableDefinitions?: | ReadonlyArray | undefined; @@ -476,74 +453,74 @@ export type ConstValueNode = | ConstObjectValueNode; export interface IntValueNode { - readonly kind: Kind.INT; + readonly kind: typeof Kind.INT; readonly loc?: Location | undefined; readonly value: string; } export interface FloatValueNode { - readonly kind: Kind.FLOAT; + readonly kind: typeof Kind.FLOAT; readonly loc?: Location | undefined; readonly value: string; } export interface StringValueNode { - readonly kind: Kind.STRING; + readonly kind: typeof Kind.STRING; readonly loc?: Location | undefined; readonly value: string; readonly block?: boolean | undefined; } export interface BooleanValueNode { - readonly kind: Kind.BOOLEAN; + readonly kind: typeof Kind.BOOLEAN; readonly loc?: Location | undefined; readonly value: boolean; } export interface NullValueNode { - readonly kind: Kind.NULL; + readonly kind: typeof Kind.NULL; readonly loc?: Location | undefined; } export interface EnumValueNode { - readonly kind: Kind.ENUM; + readonly kind: typeof Kind.ENUM; readonly loc?: Location | undefined; readonly value: string; } export interface ListValueNode { - readonly kind: Kind.LIST; + readonly kind: typeof Kind.LIST; readonly loc?: Location | undefined; readonly values: ReadonlyArray; } export interface ConstListValueNode { - readonly kind: Kind.LIST; + readonly kind: typeof Kind.LIST; readonly loc?: Location | undefined; readonly values: ReadonlyArray; } export interface ObjectValueNode { - readonly kind: Kind.OBJECT; + readonly kind: typeof Kind.OBJECT; readonly loc?: Location | undefined; readonly fields: ReadonlyArray; } export interface ConstObjectValueNode { - readonly kind: Kind.OBJECT; + readonly kind: typeof Kind.OBJECT; readonly loc?: Location | undefined; readonly fields: ReadonlyArray; } export interface ObjectFieldNode { - readonly kind: Kind.OBJECT_FIELD; + readonly kind: typeof Kind.OBJECT_FIELD; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ValueNode; } export interface ConstObjectFieldNode { - readonly kind: Kind.OBJECT_FIELD; + readonly kind: typeof Kind.OBJECT_FIELD; readonly loc?: Location | undefined; readonly name: NameNode; readonly value: ConstValueNode; @@ -552,14 +529,14 @@ export interface ConstObjectFieldNode { /** Directives */ export interface DirectiveNode { - readonly kind: Kind.DIRECTIVE; + readonly kind: typeof Kind.DIRECTIVE; readonly loc?: Location | undefined; readonly name: NameNode; readonly arguments?: ReadonlyArray | undefined; } export interface ConstDirectiveNode { - readonly kind: Kind.DIRECTIVE; + readonly kind: typeof Kind.DIRECTIVE; readonly loc?: Location | undefined; readonly name: NameNode; readonly arguments?: ReadonlyArray | undefined; @@ -570,19 +547,19 @@ export interface ConstDirectiveNode { export type TypeNode = NamedTypeNode | ListTypeNode | NonNullTypeNode; export interface NamedTypeNode { - readonly kind: Kind.NAMED_TYPE; + readonly kind: typeof Kind.NAMED_TYPE; readonly loc?: Location | undefined; readonly name: NameNode; } export interface ListTypeNode { - readonly kind: Kind.LIST_TYPE; + readonly kind: typeof Kind.LIST_TYPE; readonly loc?: Location | undefined; readonly type: TypeNode; } export interface NonNullTypeNode { - readonly kind: Kind.NON_NULL_TYPE; + readonly kind: typeof Kind.NON_NULL_TYPE; readonly loc?: Location | undefined; readonly type: NamedTypeNode | ListTypeNode; } @@ -595,7 +572,7 @@ export type TypeSystemDefinitionNode = | DirectiveDefinitionNode; export interface SchemaDefinitionNode { - readonly kind: Kind.SCHEMA_DEFINITION; + readonly kind: typeof Kind.SCHEMA_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly directives?: ReadonlyArray | undefined; @@ -603,7 +580,7 @@ export interface SchemaDefinitionNode { } export interface OperationTypeDefinitionNode { - readonly kind: Kind.OPERATION_TYPE_DEFINITION; + readonly kind: typeof Kind.OPERATION_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly operation: OperationTypeNode; readonly type: NamedTypeNode; @@ -620,7 +597,7 @@ export type TypeDefinitionNode = | InputObjectTypeDefinitionNode; export interface ScalarTypeDefinitionNode { - readonly kind: Kind.SCALAR_TYPE_DEFINITION; + readonly kind: typeof Kind.SCALAR_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -628,7 +605,7 @@ export interface ScalarTypeDefinitionNode { } export interface ObjectTypeDefinitionNode { - readonly kind: Kind.OBJECT_TYPE_DEFINITION; + readonly kind: typeof Kind.OBJECT_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -638,7 +615,7 @@ export interface ObjectTypeDefinitionNode { } export interface FieldDefinitionNode { - readonly kind: Kind.FIELD_DEFINITION; + readonly kind: typeof Kind.FIELD_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -648,7 +625,7 @@ export interface FieldDefinitionNode { } export interface InputValueDefinitionNode { - readonly kind: Kind.INPUT_VALUE_DEFINITION; + readonly kind: typeof Kind.INPUT_VALUE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -658,7 +635,7 @@ export interface InputValueDefinitionNode { } export interface InterfaceTypeDefinitionNode { - readonly kind: Kind.INTERFACE_TYPE_DEFINITION; + readonly kind: typeof Kind.INTERFACE_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -668,7 +645,7 @@ export interface InterfaceTypeDefinitionNode { } export interface UnionTypeDefinitionNode { - readonly kind: Kind.UNION_TYPE_DEFINITION; + readonly kind: typeof Kind.UNION_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -677,7 +654,7 @@ export interface UnionTypeDefinitionNode { } export interface EnumTypeDefinitionNode { - readonly kind: Kind.ENUM_TYPE_DEFINITION; + readonly kind: typeof Kind.ENUM_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -686,7 +663,7 @@ export interface EnumTypeDefinitionNode { } export interface EnumValueDefinitionNode { - readonly kind: Kind.ENUM_VALUE_DEFINITION; + readonly kind: typeof Kind.ENUM_VALUE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -694,7 +671,7 @@ export interface EnumValueDefinitionNode { } export interface InputObjectTypeDefinitionNode { - readonly kind: Kind.INPUT_OBJECT_TYPE_DEFINITION; + readonly kind: typeof Kind.INPUT_OBJECT_TYPE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -705,7 +682,7 @@ export interface InputObjectTypeDefinitionNode { /** Directive Definitions */ export interface DirectiveDefinitionNode { - readonly kind: Kind.DIRECTIVE_DEFINITION; + readonly kind: typeof Kind.DIRECTIVE_DEFINITION; readonly loc?: Location | undefined; readonly description?: StringValueNode | undefined; readonly name: NameNode; @@ -719,7 +696,7 @@ export interface DirectiveDefinitionNode { export type TypeSystemExtensionNode = SchemaExtensionNode | TypeExtensionNode; export interface SchemaExtensionNode { - readonly kind: Kind.SCHEMA_EXTENSION; + readonly kind: typeof Kind.SCHEMA_EXTENSION; readonly loc?: Location | undefined; readonly directives?: ReadonlyArray | undefined; readonly operationTypes?: @@ -738,14 +715,14 @@ export type TypeExtensionNode = | InputObjectTypeExtensionNode; export interface ScalarTypeExtensionNode { - readonly kind: Kind.SCALAR_TYPE_EXTENSION; + readonly kind: typeof Kind.SCALAR_TYPE_EXTENSION; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; } export interface ObjectTypeExtensionNode { - readonly kind: Kind.OBJECT_TYPE_EXTENSION; + readonly kind: typeof Kind.OBJECT_TYPE_EXTENSION; readonly loc?: Location | undefined; readonly name: NameNode; readonly interfaces?: ReadonlyArray | undefined; @@ -754,7 +731,7 @@ export interface ObjectTypeExtensionNode { } export interface InterfaceTypeExtensionNode { - readonly kind: Kind.INTERFACE_TYPE_EXTENSION; + readonly kind: typeof Kind.INTERFACE_TYPE_EXTENSION; readonly loc?: Location | undefined; readonly name: NameNode; readonly interfaces?: ReadonlyArray | undefined; @@ -763,7 +740,7 @@ export interface InterfaceTypeExtensionNode { } export interface UnionTypeExtensionNode { - readonly kind: Kind.UNION_TYPE_EXTENSION; + readonly kind: typeof Kind.UNION_TYPE_EXTENSION; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; @@ -771,7 +748,7 @@ export interface UnionTypeExtensionNode { } export interface EnumTypeExtensionNode { - readonly kind: Kind.ENUM_TYPE_EXTENSION; + readonly kind: typeof Kind.ENUM_TYPE_EXTENSION; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; @@ -779,7 +756,7 @@ export interface EnumTypeExtensionNode { } export interface InputObjectTypeExtensionNode { - readonly kind: Kind.INPUT_OBJECT_TYPE_EXTENSION; + readonly kind: typeof Kind.INPUT_OBJECT_TYPE_EXTENSION; readonly loc?: Location | undefined; readonly name: NameNode; readonly directives?: ReadonlyArray | undefined; diff --git a/src/language/directiveLocation.ts b/src/language/directiveLocation.ts index b10214d47f..fd4871826d 100644 --- a/src/language/directiveLocation.ts +++ b/src/language/directiveLocation.ts @@ -1,26 +1,30 @@ /** * The set of allowed directive location values. */ -export enum DirectiveLocation { +export const DirectiveLocation = { /** Request Definitions */ - QUERY = 'QUERY', - MUTATION = 'MUTATION', - SUBSCRIPTION = 'SUBSCRIPTION', - FIELD = 'FIELD', - FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION', - FRAGMENT_SPREAD = 'FRAGMENT_SPREAD', - INLINE_FRAGMENT = 'INLINE_FRAGMENT', - VARIABLE_DEFINITION = 'VARIABLE_DEFINITION', + QUERY: 'QUERY' as const, + MUTATION: 'MUTATION' as const, + SUBSCRIPTION: 'SUBSCRIPTION' as const, + FIELD: 'FIELD' as const, + FRAGMENT_DEFINITION: 'FRAGMENT_DEFINITION' as const, + FRAGMENT_SPREAD: 'FRAGMENT_SPREAD' as const, + INLINE_FRAGMENT: 'INLINE_FRAGMENT' as const, + VARIABLE_DEFINITION: 'VARIABLE_DEFINITION' as const, /** Type System Definitions */ - SCHEMA = 'SCHEMA', - SCALAR = 'SCALAR', - OBJECT = 'OBJECT', - FIELD_DEFINITION = 'FIELD_DEFINITION', - ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION', - INTERFACE = 'INTERFACE', - UNION = 'UNION', - ENUM = 'ENUM', - ENUM_VALUE = 'ENUM_VALUE', - INPUT_OBJECT = 'INPUT_OBJECT', - INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION', -} + SCHEMA: 'SCHEMA' as const, + SCALAR: 'SCALAR' as const, + OBJECT: 'OBJECT' as const, + FIELD_DEFINITION: 'FIELD_DEFINITION' as const, + ARGUMENT_DEFINITION: 'ARGUMENT_DEFINITION' as const, + INTERFACE: 'INTERFACE' as const, + UNION: 'UNION' as const, + ENUM: 'ENUM' as const, + ENUM_VALUE: 'ENUM_VALUE' as const, + INPUT_OBJECT: 'INPUT_OBJECT' as const, + INPUT_FIELD_DEFINITION: 'INPUT_FIELD_DEFINITION' as const, + FRAGMENT_VARIABLE_DEFINITION: 'FRAGMENT_VARIABLE_DEFINITION' as const, +} as const; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type DirectiveLocation = + (typeof DirectiveLocation)[keyof typeof DirectiveLocation]; diff --git a/src/language/index.ts b/src/language/index.ts index fc87a566cc..706072a75b 100644 --- a/src/language/index.ts +++ b/src/language/index.ts @@ -5,6 +5,8 @@ export type { SourceLocation } from './location.js'; export { printLocation, printSourceLocation } from './printLocation.js'; +// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313 +// eslint-disable-next-line @typescript-eslint/consistent-type-exports export { Kind } from './kinds.js'; export { TokenKind } from './tokenKind.js'; @@ -39,11 +41,8 @@ export type { SelectionSetNode, SelectionNode, FieldNode, - NullabilityAssertionNode, - NonNullAssertionNode, - ErrorBoundaryNode, - ListNullabilityOperatorNode, ArgumentNode, + FragmentArgumentNode /* for experimental fragment arguments */, ConstArgumentNode, FragmentSpreadNode, InlineFragmentNode, @@ -97,7 +96,6 @@ export { isDefinitionNode, isExecutableDefinitionNode, isSelectionNode, - isNullabilityAssertionNode, isValueNode, isConstValueNode, isTypeNode, diff --git a/src/language/kinds.ts b/src/language/kinds.ts index d606c12cbe..36231d3135 100644 --- a/src/language/kinds.ts +++ b/src/language/kinds.ts @@ -1,74 +1,6 @@ -/** - * The set of allowed kind values for AST nodes. - */ -export enum Kind { - /** Name */ - NAME = 'Name', +/* eslint-disable import/no-namespace */ +import type * as Kind_ from './kinds_.js'; - /** Document */ - DOCUMENT = 'Document', - OPERATION_DEFINITION = 'OperationDefinition', - VARIABLE_DEFINITION = 'VariableDefinition', - SELECTION_SET = 'SelectionSet', - FIELD = 'Field', - ARGUMENT = 'Argument', +export * as Kind from './kinds_.js'; - /** Nullability Modifiers */ - LIST_NULLABILITY_OPERATOR = 'ListNullabilityOperator', - NON_NULL_ASSERTION = 'NonNullAssertion', - ERROR_BOUNDARY = 'ErrorBoundary', - - /** Fragments */ - FRAGMENT_SPREAD = 'FragmentSpread', - INLINE_FRAGMENT = 'InlineFragment', - FRAGMENT_DEFINITION = 'FragmentDefinition', - - /** Values */ - VARIABLE = 'Variable', - INT = 'IntValue', - FLOAT = 'FloatValue', - STRING = 'StringValue', - BOOLEAN = 'BooleanValue', - NULL = 'NullValue', - ENUM = 'EnumValue', - LIST = 'ListValue', - OBJECT = 'ObjectValue', - OBJECT_FIELD = 'ObjectField', - - /** Directives */ - DIRECTIVE = 'Directive', - - /** Types */ - NAMED_TYPE = 'NamedType', - LIST_TYPE = 'ListType', - NON_NULL_TYPE = 'NonNullType', - - /** Type System Definitions */ - SCHEMA_DEFINITION = 'SchemaDefinition', - OPERATION_TYPE_DEFINITION = 'OperationTypeDefinition', - - /** Type Definitions */ - SCALAR_TYPE_DEFINITION = 'ScalarTypeDefinition', - OBJECT_TYPE_DEFINITION = 'ObjectTypeDefinition', - FIELD_DEFINITION = 'FieldDefinition', - INPUT_VALUE_DEFINITION = 'InputValueDefinition', - INTERFACE_TYPE_DEFINITION = 'InterfaceTypeDefinition', - UNION_TYPE_DEFINITION = 'UnionTypeDefinition', - ENUM_TYPE_DEFINITION = 'EnumTypeDefinition', - ENUM_VALUE_DEFINITION = 'EnumValueDefinition', - INPUT_OBJECT_TYPE_DEFINITION = 'InputObjectTypeDefinition', - - /** Directive Definitions */ - DIRECTIVE_DEFINITION = 'DirectiveDefinition', - - /** Type System Extensions */ - SCHEMA_EXTENSION = 'SchemaExtension', - - /** Type Extensions */ - SCALAR_TYPE_EXTENSION = 'ScalarTypeExtension', - OBJECT_TYPE_EXTENSION = 'ObjectTypeExtension', - INTERFACE_TYPE_EXTENSION = 'InterfaceTypeExtension', - UNION_TYPE_EXTENSION = 'UnionTypeExtension', - ENUM_TYPE_EXTENSION = 'EnumTypeExtension', - INPUT_OBJECT_TYPE_EXTENSION = 'InputObjectTypeExtension', -} +export type Kind = (typeof Kind_)[keyof typeof Kind_]; diff --git a/src/language/kinds_.ts b/src/language/kinds_.ts new file mode 100644 index 0000000000..0389c60c75 --- /dev/null +++ b/src/language/kinds_.ts @@ -0,0 +1,110 @@ +/* eslint-disable @typescript-eslint/no-redeclare */ + +/** Name */ +export const NAME = 'Name'; +export type NAME = typeof NAME; + +/** Document */ +export const DOCUMENT = 'Document'; +export type DOCUMENT = typeof DOCUMENT; +export const OPERATION_DEFINITION = 'OperationDefinition'; +export type OPERATION_DEFINITION = typeof OPERATION_DEFINITION; +export const VARIABLE_DEFINITION = 'VariableDefinition'; +export type VARIABLE_DEFINITION = typeof VARIABLE_DEFINITION; +export const SELECTION_SET = 'SelectionSet'; +export type SELECTION_SET = typeof SELECTION_SET; +export const FIELD = 'Field'; +export type FIELD = typeof FIELD; +export const ARGUMENT = 'Argument'; +export type ARGUMENT = typeof ARGUMENT; +export const FRAGMENT_ARGUMENT = 'FragmentArgument'; +export type FRAGMENT_ARGUMENT = typeof FRAGMENT_ARGUMENT; + +/** Fragments */ +export const FRAGMENT_SPREAD = 'FragmentSpread'; +export type FRAGMENT_SPREAD = typeof FRAGMENT_SPREAD; +export const INLINE_FRAGMENT = 'InlineFragment'; +export type INLINE_FRAGMENT = typeof INLINE_FRAGMENT; +export const FRAGMENT_DEFINITION = 'FragmentDefinition'; +export type FRAGMENT_DEFINITION = typeof FRAGMENT_DEFINITION; + +/** Values */ +export const VARIABLE = 'Variable'; +export type VARIABLE = typeof VARIABLE; +export const INT = 'IntValue'; +export type INT = typeof INT; +export const FLOAT = 'FloatValue'; +export type FLOAT = typeof FLOAT; +export const STRING = 'StringValue'; +export type STRING = typeof STRING; +export const BOOLEAN = 'BooleanValue'; +export type BOOLEAN = typeof BOOLEAN; +export const NULL = 'NullValue'; +export type NULL = typeof NULL; +export const ENUM = 'EnumValue'; +export type ENUM = typeof ENUM; +export const LIST = 'ListValue'; +export type LIST = typeof LIST; +export const OBJECT = 'ObjectValue'; +export type OBJECT = typeof OBJECT; +export const OBJECT_FIELD = 'ObjectField'; +export type OBJECT_FIELD = typeof OBJECT_FIELD; + +/** Directives */ +export const DIRECTIVE = 'Directive'; +export type DIRECTIVE = typeof DIRECTIVE; + +/** Types */ +export const NAMED_TYPE = 'NamedType'; +export type NAMED_TYPE = typeof NAMED_TYPE; +export const LIST_TYPE = 'ListType'; +export type LIST_TYPE = typeof LIST_TYPE; +export const NON_NULL_TYPE = 'NonNullType'; +export type NON_NULL_TYPE = typeof NON_NULL_TYPE; + +/** Type System Definitions */ +export const SCHEMA_DEFINITION = 'SchemaDefinition'; +export type SCHEMA_DEFINITION = typeof SCHEMA_DEFINITION; +export const OPERATION_TYPE_DEFINITION = 'OperationTypeDefinition'; +export type OPERATION_TYPE_DEFINITION = typeof OPERATION_TYPE_DEFINITION; + +/** Type Definitions */ +export const SCALAR_TYPE_DEFINITION = 'ScalarTypeDefinition'; +export type SCALAR_TYPE_DEFINITION = typeof SCALAR_TYPE_DEFINITION; +export const OBJECT_TYPE_DEFINITION = 'ObjectTypeDefinition'; +export type OBJECT_TYPE_DEFINITION = typeof OBJECT_TYPE_DEFINITION; +export const FIELD_DEFINITION = 'FieldDefinition'; +export type FIELD_DEFINITION = typeof FIELD_DEFINITION; +export const INPUT_VALUE_DEFINITION = 'InputValueDefinition'; +export type INPUT_VALUE_DEFINITION = typeof INPUT_VALUE_DEFINITION; +export const INTERFACE_TYPE_DEFINITION = 'InterfaceTypeDefinition'; +export type INTERFACE_TYPE_DEFINITION = typeof INTERFACE_TYPE_DEFINITION; +export const UNION_TYPE_DEFINITION = 'UnionTypeDefinition'; +export type UNION_TYPE_DEFINITION = typeof UNION_TYPE_DEFINITION; +export const ENUM_TYPE_DEFINITION = 'EnumTypeDefinition'; +export const ENUM_VALUE_DEFINITION = 'EnumValueDefinition'; +export type ENUM_VALUE_DEFINITION = typeof ENUM_VALUE_DEFINITION; +export const INPUT_OBJECT_TYPE_DEFINITION = 'InputObjectTypeDefinition'; +export type INPUT_OBJECT_TYPE_DEFINITION = typeof INPUT_OBJECT_TYPE_DEFINITION; + +/** Directive Definitions */ +export const DIRECTIVE_DEFINITION = 'DirectiveDefinition'; +export type DIRECTIVE_DEFINITION = typeof DIRECTIVE_DEFINITION; + +/** Type System Extensions */ +export const SCHEMA_EXTENSION = 'SchemaExtension'; +export type SCHEMA_EXTENSION = typeof SCHEMA_EXTENSION; + +/** Type Extensions */ +export const SCALAR_TYPE_EXTENSION = 'ScalarTypeExtension'; +export type SCALAR_TYPE_EXTENSION = typeof SCALAR_TYPE_EXTENSION; +export const OBJECT_TYPE_EXTENSION = 'ObjectTypeExtension'; +export type OBJECT_TYPE_EXTENSION = typeof OBJECT_TYPE_EXTENSION; +export const INTERFACE_TYPE_EXTENSION = 'InterfaceTypeExtension'; +export type INTERFACE_TYPE_EXTENSION = typeof INTERFACE_TYPE_EXTENSION; +export const UNION_TYPE_EXTENSION = 'UnionTypeExtension'; +export type UNION_TYPE_EXTENSION = typeof UNION_TYPE_EXTENSION; +export const ENUM_TYPE_EXTENSION = 'EnumTypeExtension'; +export type ENUM_TYPE_EXTENSION = typeof ENUM_TYPE_EXTENSION; +export const INPUT_OBJECT_TYPE_EXTENSION = 'InputObjectTypeExtension'; +export type INPUT_OBJECT_TYPE_EXTENSION = typeof INPUT_OBJECT_TYPE_EXTENSION; diff --git a/src/language/lexer.ts b/src/language/lexer.ts index c20c879700..841f25e786 100644 --- a/src/language/lexer.ts +++ b/src/language/lexer.ts @@ -62,7 +62,7 @@ export class Lexer { /** * Looks ahead and returns the next non-ignored token, but does not change - * the state of Lexer. + * the current Lexer token. */ lookahead(): Token { let token = this.token; @@ -91,7 +91,6 @@ export class Lexer { export function isPunctuatorTokenKind(kind: TokenKind): boolean { return ( kind === TokenKind.BANG || - kind === TokenKind.QUESTION_MARK || kind === TokenKind.DOLLAR || kind === TokenKind.AMP || kind === TokenKind.PAREN_L || @@ -258,14 +257,31 @@ function readNextToken(lexer: Lexer, start: number): Token { return createToken(lexer, TokenKind.PAREN_L, position, position + 1); case 0x0029: // ) return createToken(lexer, TokenKind.PAREN_R, position, position + 1); - case 0x002e: // . - if ( - body.charCodeAt(position + 1) === 0x002e && - body.charCodeAt(position + 2) === 0x002e - ) { + case 0x002e: { + // . + const nextCode = body.charCodeAt(position + 1); + if (nextCode === 0x002e && body.charCodeAt(position + 2) === 0x002e) { return createToken(lexer, TokenKind.SPREAD, position, position + 3); } + if (nextCode === 0x002e) { + throw syntaxError( + lexer.source, + position, + 'Unexpected "..", did you mean "..."?', + ); + } else if (isDigit(nextCode)) { + const digits = lexer.source.body.slice( + position + 1, + readDigits(lexer, position + 1, nextCode), + ); + throw syntaxError( + lexer.source, + position, + `Invalid number, expected digit before ".", did you mean "0.${digits}"?`, + ); + } break; + } case 0x003a: // : return createToken(lexer, TokenKind.COLON, position, position + 1); case 0x003d: // = @@ -282,13 +298,6 @@ function readNextToken(lexer: Lexer, start: number): Token { return createToken(lexer, TokenKind.PIPE, position, position + 1); case 0x007d: // } return createToken(lexer, TokenKind.BRACE_R, position, position + 1); - case 0x003f: // ? - return createToken( - lexer, - TokenKind.QUESTION_MARK, - position, - position + 1, - ); // StringValue case 0x0022: // " if ( @@ -316,8 +325,8 @@ function readNextToken(lexer: Lexer, start: number): Token { code === 0x0027 ? 'Unexpected single quote character (\'), did you mean to use a double quote (")?' : isUnicodeScalarValue(code) || isSupplementaryCodePoint(body, position) - ? `Unexpected character: ${printCodePointAt(lexer, position)}.` - : `Invalid character: ${printCodePointAt(lexer, position)}.`, + ? `Unexpected character: ${printCodePointAt(lexer, position)}.` + : `Invalid character: ${printCodePointAt(lexer, position)}.`, ); } @@ -683,10 +692,10 @@ function readHexDigit(code: number): number { return code >= 0x0030 && code <= 0x0039 // 0-9 ? code - 0x0030 : code >= 0x0041 && code <= 0x0046 // A-F - ? code - 0x0037 - : code >= 0x0061 && code <= 0x0066 // a-f - ? code - 0x0057 - : -1; + ? code - 0x0037 + : code >= 0x0061 && code <= 0x0066 // a-f + ? code - 0x0057 + : -1; } /** diff --git a/src/language/parser.ts b/src/language/parser.ts index cd9345f6dd..8b12cafb29 100644 --- a/src/language/parser.ts +++ b/src/language/parser.ts @@ -20,10 +20,10 @@ import type { EnumTypeExtensionNode, EnumValueDefinitionNode, EnumValueNode, - ErrorBoundaryNode, FieldDefinitionNode, FieldNode, FloatValueNode, + FragmentArgumentNode, FragmentDefinitionNode, FragmentSpreadNode, InlineFragmentNode, @@ -33,14 +33,11 @@ import type { InterfaceTypeDefinitionNode, InterfaceTypeExtensionNode, IntValueNode, - ListNullabilityOperatorNode, ListTypeNode, ListValueNode, NamedTypeNode, NameNode, - NonNullAssertionNode, NonNullTypeNode, - NullabilityAssertionNode, NullValueNode, ObjectFieldNode, ObjectTypeDefinitionNode, @@ -92,44 +89,25 @@ export interface ParseOptions { maxTokens?: number | undefined; /** - * @deprecated will be removed in the v17.0.0 + * EXPERIMENTAL: * - * If enabled, the parser will understand and parse variable definitions - * contained in a fragment definition. They'll be represented in the - * `variableDefinitions` field of the FragmentDefinitionNode. + * If enabled, the parser will understand and parse fragment variable definitions + * and arguments on fragment spreads. Fragment variable definitions will be represented + * in the `variableDefinitions` field of the FragmentDefinitionNode. + * Fragment spread arguments will be represented in the `arguments` field of FragmentSpreadNode. * - * The syntax is identical to normal, query-defined variables. For example: + * For example: * * ```graphql + * { + * t { ...A(var: true) } + * } * fragment A($var: Boolean = false) on T { - * ... + * ...B(x: $var) * } * ``` */ - allowLegacyFragmentVariables?: boolean | undefined; - - /** - * EXPERIMENTAL: - * - * If enabled, the parser will understand and parse Client Controlled Nullability - * Designators contained in Fields. They'll be represented in the - * `nullabilityAssertion` field of the FieldNode. - * - * The syntax looks like the following: - * - * ```graphql - * { - * nullableField! - * nonNullableField? - * nonNullableSelectionSet? { - * childField! - * } - * } - * ``` - * Note: this feature is experimental and may change or be removed in the - * future. - */ - experimentalClientControlledNullability?: boolean | undefined; + experimentalFragmentArguments?: boolean | undefined; } /** @@ -138,10 +116,15 @@ export interface ParseOptions { */ export function parse( source: string | Source, - options?: ParseOptions | undefined, + options?: ParseOptions, ): DocumentNode { const parser = new Parser(source, options); - return parser.parseDocument(); + const document = parser.parseDocument(); + Object.defineProperty(document, 'tokenCount', { + enumerable: false, + value: parser.tokenCount, + }); + return document; } /** @@ -151,12 +134,10 @@ export function parse( * * This is useful within tools that operate upon GraphQL Values directly and * in isolation of complete GraphQL documents. - * - * Consider providing the results to the utility function: valueFromAST(). */ export function parseValue( source: string | Source, - options?: ParseOptions | undefined, + options?: ParseOptions, ): ValueNode { const parser = new Parser(source, options); parser.expectToken(TokenKind.SOF); @@ -171,7 +152,7 @@ export function parseValue( */ export function parseConstValue( source: string | Source, - options?: ParseOptions | undefined, + options?: ParseOptions, ): ConstValueNode { const parser = new Parser(source, options); parser.expectToken(TokenKind.SOF); @@ -192,7 +173,7 @@ export function parseConstValue( */ export function parseType( source: string | Source, - options?: ParseOptions | undefined, + options?: ParseOptions, ): TypeNode { const parser = new Parser(source, options); parser.expectToken(TokenKind.SOF); @@ -225,6 +206,10 @@ export class Parser { this._tokenCounter = 0; } + get tokenCount(): number { + return this._tokenCounter; + } + /** * Converts a name lex token into a name parse node. */ @@ -343,8 +328,8 @@ export class Parser { kind: Kind.OPERATION_DEFINITION, operation: OperationTypeNode.QUERY, name: undefined, - variableDefinitions: [], - directives: [], + variableDefinitions: undefined, + directives: undefined, selectionSet: this.parseSelectionSet(), }); } @@ -383,7 +368,7 @@ export class Parser { /** * VariableDefinitions : ( VariableDefinition+ ) */ - parseVariableDefinitions(): Array { + parseVariableDefinitions(): Array | undefined { return this.optionalMany( TokenKind.PAREN_L, this.parseVariableDefinition, @@ -469,9 +454,6 @@ export class Parser { alias, name, arguments: this.parseArguments(false), - // Experimental support for Client Controlled Nullability changes - // the grammar of Field: - nullabilityAssertion: this.parseNullabilityAssertion(), directives: this.parseDirectives(false), selectionSet: this.peek(TokenKind.BRACE_L) ? this.parseSelectionSet() @@ -479,51 +461,22 @@ export class Parser { }); } - // TODO: add grammar comment after it finalizes - parseNullabilityAssertion(): NullabilityAssertionNode | undefined { - // Note: Client Controlled Nullability is experimental and may be changed or - // removed in the future. - if (this._options.experimentalClientControlledNullability !== true) { - return undefined; - } - - const start = this._lexer.token; - let nullabilityAssertion; - - if (this.expectOptionalToken(TokenKind.BRACKET_L)) { - const innerModifier = this.parseNullabilityAssertion(); - this.expectToken(TokenKind.BRACKET_R); - nullabilityAssertion = this.node(start, { - kind: Kind.LIST_NULLABILITY_OPERATOR, - nullabilityAssertion: innerModifier, - }); - } - - if (this.expectOptionalToken(TokenKind.BANG)) { - nullabilityAssertion = this.node(start, { - kind: Kind.NON_NULL_ASSERTION, - nullabilityAssertion, - }); - } else if (this.expectOptionalToken(TokenKind.QUESTION_MARK)) { - nullabilityAssertion = this.node(start, { - kind: Kind.ERROR_BOUNDARY, - nullabilityAssertion, - }); - } - - return nullabilityAssertion; - } - /** * Arguments[Const] : ( Argument[?Const]+ ) */ - parseArguments(isConst: true): Array; - parseArguments(isConst: boolean): Array; - parseArguments(isConst: boolean): Array { + parseArguments(isConst: true): Array | undefined; + parseArguments(isConst: boolean): Array | undefined; + parseArguments(isConst: boolean): Array | undefined { const item = isConst ? this.parseConstArgument : this.parseArgument; return this.optionalMany(TokenKind.PAREN_L, item, TokenKind.PAREN_R); } + /* experimental */ + parseFragmentArguments(): Array | undefined { + const item = this.parseFragmentArgument; + return this.optionalMany(TokenKind.PAREN_L, item, TokenKind.PAREN_R); + } + /** * Argument[Const] : Name : Value[?Const] */ @@ -545,12 +498,25 @@ export class Parser { return this.parseArgument(true); } + /* experimental */ + parseFragmentArgument(): FragmentArgumentNode { + const start = this._lexer.token; + const name = this.parseName(); + + this.expectToken(TokenKind.COLON); + return this.node(start, { + kind: Kind.FRAGMENT_ARGUMENT, + name, + value: this.parseValueLiteral(false), + }); + } + // Implements the parsing rules in the Fragments section. /** * Corresponds to both FragmentSpread and InlineFragment in the spec. * - * FragmentSpread : ... FragmentName Directives? + * FragmentSpread : ... FragmentName Arguments? Directives? * * InlineFragment : ... TypeCondition? Directives? SelectionSet */ @@ -560,9 +526,21 @@ export class Parser { const hasTypeCondition = this.expectOptionalKeyword('on'); if (!hasTypeCondition && this.peek(TokenKind.NAME)) { + const name = this.parseFragmentName(); + if ( + this.peek(TokenKind.PAREN_L) && + this._options.experimentalFragmentArguments + ) { + return this.node(start, { + kind: Kind.FRAGMENT_SPREAD, + name, + arguments: this.parseFragmentArguments(), + directives: this.parseDirectives(false), + }); + } return this.node(start, { kind: Kind.FRAGMENT_SPREAD, - name: this.parseFragmentName(), + name, directives: this.parseDirectives(false), }); } @@ -576,17 +554,14 @@ export class Parser { /** * FragmentDefinition : - * - fragment FragmentName on TypeCondition Directives? SelectionSet + * - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet * * TypeCondition : NamedType */ parseFragmentDefinition(): FragmentDefinitionNode { const start = this._lexer.token; this.expectKeyword('fragment'); - // Legacy support for defining variables within fragments changes - // the grammar of FragmentDefinition: - // - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet - if (this._options.allowLegacyFragmentVariables === true) { + if (this._options.experimentalFragmentArguments === true) { return this.node(start, { kind: Kind.FRAGMENT_DEFINITION, name: this.parseFragmentName(), @@ -767,17 +742,20 @@ export class Parser { /** * Directives[Const] : Directive[?Const]+ */ - parseDirectives(isConst: true): Array; - parseDirectives(isConst: boolean): Array; - parseDirectives(isConst: boolean): Array { + parseDirectives(isConst: true): Array | undefined; + parseDirectives(isConst: boolean): Array | undefined; + parseDirectives(isConst: boolean): Array | undefined { const directives = []; while (this.peek(TokenKind.AT)) { directives.push(this.parseDirective(isConst)); } - return directives; + if (directives.length) { + return directives; + } + return undefined; } - parseConstDirectives(): Array { + parseConstDirectives(): Array | undefined { return this.parseDirectives(true); } @@ -938,10 +916,10 @@ export class Parser { * - implements `&`? NamedType * - ImplementsInterfaces & NamedType */ - parseImplementsInterfaces(): Array { + parseImplementsInterfaces(): Array | undefined { return this.expectOptionalKeyword('implements') ? this.delimitedMany(TokenKind.AMP, this.parseNamedType) - : []; + : undefined; } /** @@ -949,7 +927,7 @@ export class Parser { * FieldsDefinition : { FieldDefinition+ } * ``` */ - parseFieldsDefinition(): Array { + parseFieldsDefinition(): Array | undefined { return this.optionalMany( TokenKind.BRACE_L, this.parseFieldDefinition, @@ -982,7 +960,7 @@ export class Parser { /** * ArgumentsDefinition : ( InputValueDefinition+ ) */ - parseArgumentDefs(): Array { + parseArgumentDefs(): Array | undefined { return this.optionalMany( TokenKind.PAREN_L, this.parseInputValueDef, @@ -1062,10 +1040,10 @@ export class Parser { * - = `|`? NamedType * - UnionMemberTypes | NamedType */ - parseUnionMemberTypes(): Array { + parseUnionMemberTypes(): Array | undefined { return this.expectOptionalToken(TokenKind.EQUALS) ? this.delimitedMany(TokenKind.PIPE, this.parseNamedType) - : []; + : undefined; } /** @@ -1093,7 +1071,7 @@ export class Parser { * EnumValuesDefinition : { EnumValueDefinition+ } * ``` */ - parseEnumValuesDefinition(): Array { + parseEnumValuesDefinition(): Array | undefined { return this.optionalMany( TokenKind.BRACE_L, this.parseEnumValueDefinition, @@ -1162,7 +1140,7 @@ export class Parser { * InputFieldsDefinition : { InputValueDefinition+ } * ``` */ - parseInputFieldsDefinition(): Array { + parseInputFieldsDefinition(): Array | undefined { return this.optionalMany( TokenKind.BRACE_L, this.parseInputValueDef, @@ -1225,7 +1203,7 @@ export class Parser { this.parseOperationTypeDefinition, TokenKind.BRACE_R, ); - if (directives.length === 0 && operationTypes.length === 0) { + if (directives === undefined && operationTypes === undefined) { throw this.unexpected(); } return this.node(start, { @@ -1245,7 +1223,7 @@ export class Parser { this.expectKeyword('scalar'); const name = this.parseName(); const directives = this.parseConstDirectives(); - if (directives.length === 0) { + if (directives === undefined) { throw this.unexpected(); } return this.node(start, { @@ -1270,9 +1248,9 @@ export class Parser { const directives = this.parseConstDirectives(); const fields = this.parseFieldsDefinition(); if ( - interfaces.length === 0 && - directives.length === 0 && - fields.length === 0 + interfaces === undefined && + directives === undefined && + fields === undefined ) { throw this.unexpected(); } @@ -1300,9 +1278,9 @@ export class Parser { const directives = this.parseConstDirectives(); const fields = this.parseFieldsDefinition(); if ( - interfaces.length === 0 && - directives.length === 0 && - fields.length === 0 + interfaces === undefined && + directives === undefined && + fields === undefined ) { throw this.unexpected(); } @@ -1327,7 +1305,7 @@ export class Parser { const name = this.parseName(); const directives = this.parseConstDirectives(); const types = this.parseUnionMemberTypes(); - if (directives.length === 0 && types.length === 0) { + if (directives === undefined && types === undefined) { throw this.unexpected(); } return this.node(start, { @@ -1350,7 +1328,7 @@ export class Parser { const name = this.parseName(); const directives = this.parseConstDirectives(); const values = this.parseEnumValuesDefinition(); - if (directives.length === 0 && values.length === 0) { + if (directives === undefined && values === undefined) { throw this.unexpected(); } return this.node(start, { @@ -1373,7 +1351,7 @@ export class Parser { const name = this.parseName(); const directives = this.parseConstDirectives(); const fields = this.parseInputFieldsDefinition(); - if (directives.length === 0 && fields.length === 0) { + if (directives === undefined && fields === undefined) { throw this.unexpected(); } return this.node(start, { @@ -1584,7 +1562,7 @@ export class Parser { openKind: TokenKind, parseFn: () => T, closeKind: TokenKind, - ): Array { + ): Array | undefined { if (this.expectOptionalToken(openKind)) { const nodes = []; do { @@ -1592,7 +1570,7 @@ export class Parser { } while (!this.expectOptionalToken(closeKind)); return nodes; } - return []; + return undefined; } /** @@ -1632,9 +1610,9 @@ export class Parser { const { maxTokens } = this._options; const token = this._lexer.advance(); - if (maxTokens !== undefined && token.kind !== TokenKind.EOF) { + if (token.kind !== TokenKind.EOF) { ++this._tokenCounter; - if (this._tokenCounter > maxTokens) { + if (maxTokens !== undefined && this._tokenCounter > maxTokens) { throw syntaxError( this._lexer.source, token.start, diff --git a/src/language/predicates.ts b/src/language/predicates.ts index 2c1b6a2ef3..29ad5bf289 100644 --- a/src/language/predicates.ts +++ b/src/language/predicates.ts @@ -3,7 +3,6 @@ import type { ConstValueNode, DefinitionNode, ExecutableDefinitionNode, - NullabilityAssertionNode, SelectionNode, TypeDefinitionNode, TypeExtensionNode, @@ -39,16 +38,6 @@ export function isSelectionNode(node: ASTNode): node is SelectionNode { ); } -export function isNullabilityAssertionNode( - node: ASTNode, -): node is NullabilityAssertionNode { - return ( - node.kind === Kind.LIST_NULLABILITY_OPERATOR || - node.kind === Kind.NON_NULL_ASSERTION || - node.kind === Kind.ERROR_BOUNDARY - ); -} - export function isValueNode(node: ASTNode): node is ValueNode { return ( node.kind === Kind.VARIABLE || @@ -69,8 +58,8 @@ export function isConstValueNode(node: ASTNode): node is ConstValueNode { (node.kind === Kind.LIST ? node.values.some(isConstValueNode) : node.kind === Kind.OBJECT - ? node.fields.some((field) => isConstValueNode(field.value)) - : node.kind !== Kind.VARIABLE) + ? node.fields.some((field) => isConstValueNode(field.value)) + : node.kind !== Kind.VARIABLE) ); } diff --git a/src/language/printer.ts b/src/language/printer.ts index 28bb25da17..bf2959e59c 100644 --- a/src/language/printer.ts +++ b/src/language/printer.ts @@ -55,58 +55,28 @@ const printDocASTReducer: ASTReducer = { SelectionSet: { leave: ({ selections }) => block(selections) }, Field: { - leave({ - alias, - name, - arguments: args, - nullabilityAssertion, - directives, - selectionSet, - }) { + leave({ alias, name, arguments: args, directives, selectionSet }) { const prefix = join([wrap('', alias, ': '), name], ''); - let argsLine = prefix + wrap('(', join(args, ', '), ')'); - - if (argsLine.length > MAX_LINE_LENGTH) { - argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)'); - } return join([ - argsLine, - // Note: Client Controlled Nullability is experimental and may be - // changed or removed in the future. - nullabilityAssertion, + wrappedLineAndArgs(prefix, args), wrap(' ', join(directives, ' ')), wrap(' ', selectionSet), ]); }, }, Argument: { leave: ({ name, value }) => name + ': ' + value }, - - // Nullability Modifiers - - ListNullabilityOperator: { - leave({ nullabilityAssertion }) { - return join(['[', nullabilityAssertion, ']']); - }, - }, - - NonNullAssertion: { - leave({ nullabilityAssertion }) { - return join([nullabilityAssertion, '!']); - }, - }, - - ErrorBoundary: { - leave({ nullabilityAssertion }) { - return join([nullabilityAssertion, '?']); - }, - }, + FragmentArgument: { leave: ({ name, value }) => name + ': ' + value }, // Fragments FragmentSpread: { - leave: ({ name, directives }) => - '...' + name + wrap(' ', join(directives, ' ')), + leave: ({ name, arguments: args, directives }) => { + const prefix = '...' + name; + return ( + wrappedLineAndArgs(prefix, args) + wrap(' ', join(directives, ' ')) + ); + }, }, InlineFragment: { @@ -388,7 +358,17 @@ function indent(str: string): string { } function hasMultilineItems(maybeArray: Maybe>): boolean { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ return maybeArray?.some((str) => str.includes('\n')) ?? false; } + +function wrappedLineAndArgs( + prefix: string, + args: ReadonlyArray | undefined, +): string { + let argsLine = prefix + wrap('(', join(args, ', '), ')'); + + if (argsLine.length > MAX_LINE_LENGTH) { + argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)'); + } + return argsLine; +} diff --git a/src/language/tokenKind.ts b/src/language/tokenKind.ts index 1bba933d50..d1c7129b04 100644 --- a/src/language/tokenKind.ts +++ b/src/language/tokenKind.ts @@ -2,28 +2,29 @@ * An exported enum describing the different kinds of tokens that the * lexer emits. */ -export enum TokenKind { - SOF = '', - EOF = '', - BANG = '!', - QUESTION_MARK = '?', - DOLLAR = '$', - AMP = '&', - PAREN_L = '(', - PAREN_R = ')', - SPREAD = '...', - COLON = ':', - EQUALS = '=', - AT = '@', - BRACKET_L = '[', - BRACKET_R = ']', - BRACE_L = '{', - PIPE = '|', - BRACE_R = '}', - NAME = 'Name', - INT = 'Int', - FLOAT = 'Float', - STRING = 'String', - BLOCK_STRING = 'BlockString', - COMMENT = 'Comment', -} +export const TokenKind = { + SOF: '' as const, + EOF: '' as const, + BANG: '!' as const, + DOLLAR: '$' as const, + AMP: '&' as const, + PAREN_L: '(' as const, + PAREN_R: ')' as const, + SPREAD: '...' as const, + COLON: ':' as const, + EQUALS: '=' as const, + AT: '@' as const, + BRACKET_L: '[' as const, + BRACKET_R: ']' as const, + BRACE_L: '{' as const, + PIPE: '|' as const, + BRACE_R: '}' as const, + NAME: 'Name' as const, + INT: 'Int' as const, + FLOAT: 'Float' as const, + STRING: 'String' as const, + BLOCK_STRING: 'BlockString' as const, + COMMENT: 'Comment' as const, +} as const; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type TokenKind = (typeof TokenKind)[keyof typeof TokenKind]; diff --git a/src/language/visitor.ts b/src/language/visitor.ts index 65df78d099..7fbb703909 100644 --- a/src/language/visitor.ts +++ b/src/language/visitor.ts @@ -74,8 +74,8 @@ type ASTReducerFn = ( type ReducedField = T extends ASTNode ? R : T extends ReadonlyArray - ? ReadonlyArray - : T; + ? ReadonlyArray + : T; /** * A KeyMap describes each the traversable properties of each kind of node. @@ -284,7 +284,7 @@ export function visit( } else { stack = { inArray, index, keys, edits, prev: stack }; inArray = Array.isArray(node); - keys = inArray ? node : (visitorKeys as any)[node.kind] ?? []; + keys = inArray ? node : ((visitorKeys as any)[node.kind] ?? []); index = -1; edits = []; if (parent != null) { diff --git a/src/type/__tests__/definition-test.ts b/src/type/__tests__/definition-test.ts index 9a491fc31f..8d9eeb4044 100644 --- a/src/type/__tests__/definition-test.ts +++ b/src/type/__tests__/definition-test.ts @@ -4,9 +4,19 @@ import { describe, it } from 'mocha'; import { identityFunc } from '../../jsutils/identityFunc.js'; import { inspect } from '../../jsutils/inspect.js'; -import { parseValue } from '../../language/parser.js'; +import { Kind } from '../../language/kinds.js'; +import { parseConstValue } from '../../language/parser.js'; -import type { GraphQLNullableType, GraphQLType } from '../definition.js'; +import type { + GraphQLEnumTypeConfig, + GraphQLInputObjectTypeConfig, + GraphQLInterfaceTypeConfig, + GraphQLNullableType, + GraphQLObjectTypeConfig, + GraphQLScalarTypeConfig, + GraphQLType, + GraphQLUnionTypeConfig, +} from '../definition.js'; import { GraphQLEnumType, GraphQLInputObjectType, @@ -17,9 +27,18 @@ import { GraphQLScalarType, GraphQLUnionType, } from '../definition.js'; +import { GraphQLString } from '../scalars.js'; const ScalarType = new GraphQLScalarType({ name: 'Scalar' }); -const ObjectType = new GraphQLObjectType({ name: 'Object', fields: {} }); +const ObjectType = new GraphQLObjectType({ + name: 'Object', + fields: { + someField: { + type: GraphQLString, + args: { someArg: { type: GraphQLString } }, + }, + }, +}); const InterfaceType = new GraphQLInterfaceType({ name: 'Interface', fields: {}, @@ -28,7 +47,7 @@ const UnionType = new GraphQLUnionType({ name: 'Union', types: [ObjectType] }); const EnumType = new GraphQLEnumType({ name: 'Enum', values: { foo: {} } }); const InputObjectType = new GraphQLInputObjectType({ name: 'InputObject', - fields: {}, + fields: { someInputField: { type: GraphQLString } }, }); const ListOfScalarsType = new GraphQLList(ScalarType); @@ -37,32 +56,68 @@ const ListOfNonNullScalarsType = new GraphQLList(NonNullScalarType); const NonNullListOfScalars = new GraphQLNonNull(ListOfScalarsType); /* c8 ignore next */ -const dummyFunc = () => expect.fail('Never called and used as a placeholder'); +const passThroughFunc = (arg: any) => arg; +const dummyAny = {} as any; describe('Type System: Scalars', () => { - it('accepts a Scalar type defining serialize', () => { - expect(() => new GraphQLScalarType({ name: 'SomeScalar' })).to.not.throw(); + it('can be converted from a minimal configuration object', () => { + const someScalar = new GraphQLScalarType({ name: 'SomeScalar' }); + expect(someScalar.toConfig()).to.deep.equal({ + name: 'SomeScalar', + description: undefined, + specifiedByURL: undefined, + serialize: someScalar.serialize, + parseValue: someScalar.parseValue, + parseLiteral: someScalar.parseLiteral, + coerceOutputValue: someScalar.coerceOutputValue, + coerceInputValue: someScalar.coerceInputValue, + coerceInputLiteral: undefined, + valueToLiteral: undefined, + extensions: {}, + astNode: undefined, + extensionASTNodes: [], + }); }); - it('accepts a Scalar type defining specifiedByURL', () => { - expect( - () => - new GraphQLScalarType({ - name: 'SomeScalar', - specifiedByURL: 'https://example.com/foo_spec', - }), - ).not.to.throw(); + it('can be converted to a configuration object', () => { + const someScalarConfig: GraphQLScalarTypeConfig = { + name: 'SomeScalar', + description: 'SomeScalar description.', + specifiedByURL: 'https://example.com/foo_spec', + serialize: passThroughFunc, + parseValue: passThroughFunc, + parseLiteral: passThroughFunc, + coerceOutputValue: passThroughFunc, + coerceInputValue: passThroughFunc, + coerceInputLiteral: passThroughFunc, + valueToLiteral: passThroughFunc, + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + extensionASTNodes: [dummyAny], + }; + const someScalar = new GraphQLScalarType(someScalarConfig); + expect(someScalar.toConfig()).to.deep.equal(someScalarConfig); }); - it('accepts a Scalar type defining parseValue and parseLiteral', () => { - expect( - () => - new GraphQLScalarType({ - name: 'SomeScalar', - parseValue: dummyFunc, - parseLiteral: dummyFunc, - }), - ).to.not.throw(); + it('supports symbol extensions', () => { + const test = Symbol.for('test'); + const someScalarConfig: GraphQLScalarTypeConfig = { + name: 'SomeScalar', + description: 'SomeScalar description.', + specifiedByURL: 'https://example.com/foo_spec', + serialize: passThroughFunc, + parseValue: passThroughFunc, + parseLiteral: passThroughFunc, + coerceOutputValue: passThroughFunc, + coerceInputValue: passThroughFunc, + coerceInputLiteral: passThroughFunc, + valueToLiteral: passThroughFunc, + extensions: { [test]: 'extension' }, + astNode: dummyAny, + extensionASTNodes: [dummyAny], + }; + const someScalar = new GraphQLScalarType(someScalarConfig); + expect(someScalar.toConfig()).to.deep.equal(someScalarConfig); }); it('provides default methods if omitted', () => { @@ -70,7 +125,11 @@ describe('Type System: Scalars', () => { expect(scalar.serialize).to.equal(identityFunc); expect(scalar.parseValue).to.equal(identityFunc); + expect(scalar.coerceOutputValue).to.equal(identityFunc); + expect(scalar.coerceInputValue).to.equal(identityFunc); expect(scalar.parseLiteral).to.be.a('function'); + /* default will be provided in v18 when parseLiteral is removed */ + // expect(scalar.coerceInputLiteral).to.be.a('function'); }); it('use parseValue for parsing literals if parseLiteral omitted', () => { @@ -81,15 +140,12 @@ describe('Type System: Scalars', () => { }, }); - expect(scalar.parseLiteral(parseValue('null'))).to.equal( + expect(scalar.parseLiteral(parseConstValue('null'), undefined)).to.equal( 'parseValue: null', ); - expect(scalar.parseLiteral(parseValue('{ foo: "bar" }'))).to.equal( - 'parseValue: { foo: "bar" }', - ); expect( - scalar.parseLiteral(parseValue('{ foo: { bar: $var } }'), { var: 'baz' }), - ).to.equal('parseValue: { foo: { bar: "baz" } }'); + scalar.parseLiteral(parseConstValue('{ foo: "bar" }'), undefined), + ).to.equal('parseValue: { foo: "bar" }'); }); it('rejects a Scalar type defining parseLiteral but not parseValue', () => { @@ -97,15 +153,80 @@ describe('Type System: Scalars', () => { () => new GraphQLScalarType({ name: 'SomeScalar', - parseLiteral: dummyFunc, + parseLiteral: passThroughFunc, }), ).to.throw( 'SomeScalar must provide both "parseValue" and "parseLiteral" functions.', ); }); + + it('rejects a Scalar type defining coerceInputLiteral but not coerceInputValue', () => { + expect( + () => + new GraphQLScalarType({ + name: 'SomeScalar', + coerceInputLiteral: passThroughFunc, + }), + ).to.throw( + 'SomeScalar must provide both "coerceInputValue" and "coerceInputLiteral" functions.', + ); + }); }); describe('Type System: Objects', () => { + it('can be converted from a minimal configuration object', () => { + const someObject = new GraphQLObjectType({ + name: 'SomeObject', + fields: {}, + }); + expect(someObject.toConfig()).to.deep.equal({ + name: 'SomeObject', + description: undefined, + interfaces: [], + fields: {}, + isTypeOf: undefined, + extensions: {}, + astNode: undefined, + extensionASTNodes: [], + }); + }); + + it('can be converted to a configuration object', () => { + const someObjectConfig: GraphQLObjectTypeConfig = { + name: 'SomeObject', + description: 'SomeObject description.', + interfaces: [InterfaceType], + fields: { + f: { + description: 'Field description.', + type: ScalarType, + args: { + input: { + description: 'Argument description.', + type: ScalarType, + defaultValue: undefined, + default: { value: 'DefaultValue' }, + deprecationReason: 'Argument deprecation reason.', + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + }, + }, + resolve: passThroughFunc, + subscribe: passThroughFunc, + deprecationReason: 'Field deprecation reason.', + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + }, + }, + isTypeOf: passThroughFunc, + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + extensionASTNodes: [dummyAny], + }; + const someObject = new GraphQLObjectType(someObjectConfig); + expect(someObject.toConfig()).to.deep.equal(someObjectConfig); + }); + it('does not mutate passed field definitions', () => { const outputFields = { field1: { type: ScalarType }, @@ -125,7 +246,15 @@ describe('Type System: Objects', () => { fields: outputFields, }); - expect(testObject1.getFields()).to.deep.equal(testObject2.getFields()); + const testObject1Fields = testObject1.getFields(); + const testObject2Fields = testObject2.getFields(); + + expect(testObject1Fields.field1.toConfig()).to.deep.equal( + testObject2Fields.field1.toConfig(), + ); + expect(testObject1Fields.field2.toConfig()).to.deep.equal( + testObject2Fields.field2.toConfig(), + ); expect(outputFields).to.deep.equal({ field1: { type: ScalarType, @@ -151,8 +280,14 @@ describe('Type System: Objects', () => { fields: inputFields, }); - expect(testInputObject1.getFields()).to.deep.equal( - testInputObject2.getFields(), + const testInputObject1Fields = testInputObject1.getFields(); + const testInputObject2Fields = testInputObject2.getFields(); + + expect(testInputObject1Fields.field1.toConfig()).to.deep.equal( + testInputObject2Fields.field1.toConfig(), + ); + expect(testInputObject1Fields.field2.toConfig()).to.deep.equal( + testInputObject2Fields.field2.toConfig(), ); expect(inputFields).to.deep.equal({ field1: { type: ScalarType }, @@ -193,18 +328,17 @@ describe('Type System: Objects', () => { f: { type: ScalarType }, }), }); - expect(objType.getFields()).to.deep.equal({ - f: { - name: 'f', - description: undefined, - type: ScalarType, - args: [], - resolve: undefined, - subscribe: undefined, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, + expect(objType.getFields().f).to.deep.include({ + parentType: objType, + name: 'f', + description: undefined, + type: ScalarType, + args: [], + resolve: undefined, + subscribe: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, }); }); @@ -220,28 +354,33 @@ describe('Type System: Objects', () => { }, }, }); - expect(objType.getFields()).to.deep.equal({ - f: { - name: 'f', - description: undefined, - type: ScalarType, - args: [ - { - name: 'arg', - description: undefined, - type: ScalarType, - defaultValue: undefined, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - ], - resolve: undefined, - subscribe: undefined, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, + + const f = objType.getFields().f; + + expect(f).to.deep.include({ + parentType: objType, + name: 'f', + description: undefined, + type: ScalarType, + resolve: undefined, + subscribe: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + + expect(f.args).to.have.lengthOf(1); + + expect(f.args[0]).to.deep.include({ + parent: f, + name: 'arg', + description: undefined, + type: ScalarType, + defaultValue: undefined, + default: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, }); }); @@ -269,7 +408,7 @@ describe('Type System: Objects', () => { fields: { f: { type: ScalarType, - resolve: dummyFunc, + resolve: passThroughFunc, }, }, }); @@ -324,7 +463,60 @@ describe('Type System: Objects', () => { }); describe('Type System: Interfaces', () => { - it('accepts an Interface type defining resolveType', () => { + it('can be converted from a minimal configuration object', () => { + const someInterface = new GraphQLInterfaceType({ + name: 'SomeInterface', + fields: {}, + }); + expect(someInterface.toConfig()).to.deep.equal({ + name: 'SomeInterface', + description: undefined, + interfaces: [], + fields: {}, + resolveType: undefined, + extensions: {}, + astNode: undefined, + extensionASTNodes: [], + }); + }); + + it('can be converted to a configuration object', () => { + const someInterfaceConfig: GraphQLInterfaceTypeConfig = { + name: 'SomeInterface', + description: 'SomeInterface description.', + interfaces: [InterfaceType], + fields: { + f: { + description: 'Field description.', + type: ScalarType, + args: { + input: { + description: 'Argument description.', + type: ScalarType, + defaultValue: undefined, + default: { literal: dummyAny }, + deprecationReason: 'Argument deprecation reason.', + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + }, + }, + resolve: passThroughFunc, + subscribe: passThroughFunc, + deprecationReason: 'Field deprecation reason.', + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + }, + }, + resolveType: passThroughFunc, + extensions: {}, + astNode: {} as any, + extensionASTNodes: [], + }; + const someInterface = new GraphQLInterfaceType(someInterfaceConfig); + expect(someInterface.toConfig()).to.deep.equal(someInterfaceConfig); + }); + + it('accepts an Interface type defining a field', () => { expect( () => new GraphQLInterfaceType({ @@ -334,6 +526,26 @@ describe('Type System: Interfaces', () => { ).to.not.throw(); }); + it('accepts an Interface type with a field function', () => { + const interfaceType = new GraphQLInterfaceType({ + name: 'SomeInterface', + fields: () => ({ + f: { type: ScalarType }, + }), + }); + expect(interfaceType.getFields().f).to.deep.include({ + name: 'f', + description: undefined, + type: ScalarType, + args: [], + resolve: undefined, + subscribe: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + }); + it('accepts an Interface type with an array of interfaces', () => { const implementing = new GraphQLInterfaceType({ name: 'AnotherInterface', @@ -360,6 +572,36 @@ describe('Type System: Interfaces', () => { }); describe('Type System: Unions', () => { + it('can be converted from a minimal configuration object', () => { + const someUnion = new GraphQLUnionType({ + name: 'SomeUnion', + types: [], + }); + expect(someUnion.toConfig()).to.deep.equal({ + name: 'SomeUnion', + description: undefined, + types: [], + resolveType: undefined, + extensions: {}, + astNode: undefined, + extensionASTNodes: [], + }); + }); + + it('can be converted to a configuration object', () => { + const someUnionConfig: GraphQLUnionTypeConfig = { + name: 'SomeUnion', + description: 'SomeUnion description.', + types: [ObjectType], + resolveType: passThroughFunc, + extensions: {}, + astNode: {} as any, + extensionASTNodes: [], + }; + const someUnion = new GraphQLUnionType(someUnionConfig); + expect(someUnion.toConfig()).to.deep.equal(someUnionConfig); + }); + it('accepts a Union type defining resolveType', () => { expect( () => @@ -402,6 +644,63 @@ describe('Type System: Unions', () => { }); describe('Type System: Enums', () => { + it('can be converted from a minimal configuration object', () => { + const someEnum = new GraphQLEnumType({ name: 'SomeEnum', values: {} }); + expect(someEnum.toConfig()).to.deep.equal({ + name: 'SomeEnum', + description: undefined, + values: {}, + extensions: {}, + astNode: undefined, + extensionASTNodes: [], + }); + }); + + it('can be converted to a configuration object', () => { + const someEnumConfig: GraphQLEnumTypeConfig = { + name: 'SomeEnum', + description: 'SomeEnum description.', + values: { + FOO: { + description: 'FOO description.', + value: 'foo', + deprecationReason: 'Value deprecation reason.', + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + }, + }, + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + extensionASTNodes: [dummyAny], + }; + const someEnum = new GraphQLEnumType(someEnumConfig); + expect(someEnum.toConfig()).to.deep.equal(someEnumConfig); + }); + + it('can be coerced to an output value via serialize() method', () => { + const someEnum = new GraphQLEnumType({ + name: 'SomeEnum', + values: { + FOO: { + value: 'foo', + }, + }, + }); + expect(someEnum.serialize('foo')).to.equal('FOO'); + }); + + it('can be coerced to an input value via parseValue() method', () => { + const someEnum = new GraphQLEnumType({ + name: 'SomeEnum', + values: { + FOO: { + value: 'foo', + }, + }, + }); + expect(someEnum.parseValue('FOO')).to.equal('foo'); + }); + it('defines an enum type with deprecated value', () => { const EnumTypeWithDeprecatedValue = new GraphQLEnumType({ name: 'EnumWithDeprecatedValue', @@ -432,32 +731,36 @@ describe('Type System: Enums', () => { }, }); - expect(EnumTypeWithNullishValue.getValues()).to.deep.equal([ - { - name: 'NULL', - description: undefined, - value: null, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - { - name: 'NAN', - description: undefined, - value: NaN, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - { - name: 'NO_CUSTOM_VALUE', - description: undefined, - value: 'NO_CUSTOM_VALUE', - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - ]); + const values = EnumTypeWithNullishValue.getValues(); + + expect(values).to.have.lengthOf(3); + + expect(values[0]).to.deep.include({ + name: 'NULL', + description: undefined, + value: null, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + + expect(values[1]).to.deep.include({ + name: 'NAN', + description: undefined, + value: NaN, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + + expect(values[2]).to.deep.include({ + name: 'NO_CUSTOM_VALUE', + description: undefined, + value: 'NO_CUSTOM_VALUE', + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); }); it('accepts a well defined Enum type with empty value definition', () => { @@ -504,6 +807,46 @@ describe('Type System: Enums', () => { }); describe('Type System: Input Objects', () => { + it('can be converted from a minimal configuration object', () => { + const inputObject = new GraphQLInputObjectType({ + name: 'SomeInputObject', + fields: {}, + }); + expect(inputObject.toConfig()).to.deep.equal({ + name: 'SomeInputObject', + description: undefined, + fields: {}, + isOneOf: false, + extensions: {}, + astNode: undefined, + extensionASTNodes: [], + }); + }); + + it('can be converted to a configuration object', () => { + const someInputObjectConfig: GraphQLInputObjectTypeConfig = { + name: 'SomeInputObject', + description: 'SomeObject description.', + fields: { + input: { + description: 'Argument description.', + type: ScalarType, + defaultValue: undefined, + default: { value: 'DefaultValue' }, + deprecationReason: 'Argument deprecation reason.', + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + }, + }, + isOneOf: true, + extensions: { someExtension: 'extension' }, + astNode: dummyAny, + extensionASTNodes: [dummyAny], + }; + const someInputObject = new GraphQLInputObjectType(someInputObjectConfig); + expect(someInputObject.toConfig()).to.deep.equal(someInputObjectConfig); + }); + describe('Input Objects must have fields', () => { it('accepts an Input Object type with fields', () => { const inputObjType = new GraphQLInputObjectType({ @@ -512,16 +855,16 @@ describe('Type System: Input Objects', () => { f: { type: ScalarType }, }, }); - expect(inputObjType.getFields()).to.deep.equal({ - f: { - name: 'f', - description: undefined, - type: ScalarType, - defaultValue: undefined, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, + expect(inputObjType.getFields().f).to.deep.include({ + parentType: inputObjType, + name: 'f', + description: undefined, + type: ScalarType, + defaultValue: undefined, + default: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, }); }); @@ -532,16 +875,16 @@ describe('Type System: Input Objects', () => { f: { type: ScalarType }, }), }); - expect(inputObjType.getFields()).to.deep.equal({ - f: { - name: 'f', - description: undefined, - type: ScalarType, - defaultValue: undefined, - extensions: {}, - deprecationReason: undefined, - astNode: undefined, - }, + expect(inputObjType.getFields().f).to.deep.include({ + parentType: inputObjType, + name: 'f', + description: undefined, + type: ScalarType, + defaultValue: undefined, + default: undefined, + extensions: {}, + deprecationReason: undefined, + astNode: undefined, }); }); @@ -581,6 +924,49 @@ describe('Type System: Input Objects', () => { 'not used anymore', ); }); + + describe('Input Object fields may have default values', () => { + it('accepts an Input Object type with a default value', () => { + const inputObjType = new GraphQLInputObjectType({ + name: 'SomeInputObject', + fields: { + f: { type: ScalarType, default: { value: 3 } }, + }, + }); + expect(inputObjType.getFields().f).to.deep.include({ + name: 'f', + description: undefined, + type: ScalarType, + defaultValue: undefined, + default: { value: 3 }, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + }); + + it('accepts an Input Object type with a default value literal', () => { + const inputObjType = new GraphQLInputObjectType({ + name: 'SomeInputObject', + fields: { + f: { + type: ScalarType, + default: { literal: { kind: Kind.INT, value: '3' } }, + }, + }, + }); + expect(inputObjType.getFields().f).to.deep.include({ + name: 'f', + description: undefined, + type: ScalarType, + defaultValue: undefined, + default: { literal: { kind: 'IntValue', value: '3' } }, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + }); + }); }); describe('Type System: List', () => { @@ -618,13 +1004,22 @@ describe('Type System: Non-Null', () => { }); describe('Type System: test utility methods', () => { - it('stringifies types', () => { + const someField = ObjectType.getFields().someField; + const someArg = someField.args[0]; + const enumValue = EnumType.getValue('foo'); + const someInputField = InputObjectType.getFields().someInputField; + + it('stringifies schema elements', () => { expect(String(ScalarType)).to.equal('Scalar'); expect(String(ObjectType)).to.equal('Object'); + expect(String(someField)).to.equal('Object.someField'); + expect(String(someArg)).to.equal('Object.someField(someArg:)'); expect(String(InterfaceType)).to.equal('Interface'); expect(String(UnionType)).to.equal('Union'); expect(String(EnumType)).to.equal('Enum'); + expect(String(enumValue)).to.equal('Enum.foo'); expect(String(InputObjectType)).to.equal('InputObject'); + expect(String(someInputField)).to.equal('InputObject.someInputField'); expect(String(NonNullScalarType)).to.equal('Scalar!'); expect(String(ListOfScalarsType)).to.equal('[Scalar]'); @@ -636,10 +1031,15 @@ describe('Type System: test utility methods', () => { it('JSON.stringifies types', () => { expect(JSON.stringify(ScalarType)).to.equal('"Scalar"'); expect(JSON.stringify(ObjectType)).to.equal('"Object"'); - expect(JSON.stringify(InterfaceType)).to.equal('"Interface"'); + expect(JSON.stringify(someField)).to.equal('"Object.someField"'); + expect(JSON.stringify(someArg)).to.equal('"Object.someField(someArg:)"'); expect(JSON.stringify(UnionType)).to.equal('"Union"'); expect(JSON.stringify(EnumType)).to.equal('"Enum"'); + expect(JSON.stringify(enumValue)).to.equal('"Enum.foo"'); expect(JSON.stringify(InputObjectType)).to.equal('"InputObject"'); + expect(JSON.stringify(someInputField)).to.equal( + '"InputObject.someInputField"', + ); expect(JSON.stringify(NonNullScalarType)).to.equal('"Scalar!"'); expect(JSON.stringify(ListOfScalarsType)).to.equal('"[Scalar]"'); diff --git a/src/type/__tests__/directive-test.ts b/src/type/__tests__/directive-test.ts index 03af5e1fd9..90510bd0f9 100644 --- a/src/type/__tests__/directive-test.ts +++ b/src/type/__tests__/directive-test.ts @@ -33,29 +33,35 @@ describe('Type System: Directive', () => { expect(directive).to.deep.include({ name: 'Foo', - args: [ - { - name: 'foo', - description: undefined, - type: GraphQLString, - defaultValue: undefined, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - { - name: 'bar', - description: undefined, - type: GraphQLInt, - defaultValue: undefined, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - ], isRepeatable: false, locations: ['QUERY'], }); + + expect(directive.args).to.have.lengthOf(2); + + expect(directive.args[0]).to.deep.include({ + parent: directive, + name: 'foo', + description: undefined, + type: GraphQLString, + defaultValue: undefined, + default: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + + expect(directive.args[1]).to.deep.include({ + parent: directive, + name: 'bar', + description: undefined, + type: GraphQLInt, + defaultValue: undefined, + default: undefined, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); }); it('defines a repeatable directive', () => { diff --git a/src/type/__tests__/enumType-test.ts b/src/type/__tests__/enumType-test.ts index f2786947c6..007b00a78e 100644 --- a/src/type/__tests__/enumType-test.ts +++ b/src/type/__tests__/enumType-test.ts @@ -31,6 +31,14 @@ const ComplexEnum = new GraphQLEnumType({ }, }); +const ThunkValuesEnum = new GraphQLEnumType({ + name: 'ThunkValues', + values: () => ({ + A: { value: 'a' }, + B: { value: 'b' }, + }), +}); + const QueryType = new GraphQLObjectType({ name: 'Query', fields: { @@ -45,8 +53,8 @@ const QueryType = new GraphQLObjectType({ return fromInt !== undefined ? fromInt : fromString !== undefined - ? fromString - : fromEnum; + ? fromString + : fromEnum; }, }, colorInt: { @@ -63,9 +71,7 @@ const QueryType = new GraphQLObjectType({ args: { fromEnum: { type: ComplexEnum, - // Note: defaultValue is provided an *internal* representation for - // Enums, rather than the string name. - defaultValue: Complex1, + default: { value: 'ONE' }, }, provideGoodValue: { type: GraphQLBoolean }, provideBadValue: { type: GraphQLBoolean }, @@ -84,6 +90,27 @@ const QueryType = new GraphQLObjectType({ return fromEnum; }, }, + complexEnumWithLegacyDefault: { + type: ComplexEnum, + args: { + fromEnum: { + type: ComplexEnum, + defaultValue: Complex1, + }, + }, + resolve(_source, { fromEnum }) { + return fromEnum; + }, + }, + thunkValuesString: { + type: GraphQLString, + args: { + fromEnum: { type: ThunkValuesEnum }, + }, + resolve(_source, { fromEnum }) { + return fromEnum; + }, + }, }, }); @@ -118,8 +145,14 @@ const schema = new GraphQLSchema({ function executeQuery( source: string, variableValues?: { readonly [variable: string]: unknown }, + hideSuggestions = false, ) { - return graphqlSync({ schema, source, variableValues }); + return graphqlSync({ + schema, + source, + variableValues, + hideSuggestions, + }); } describe('Type System: Enum Values', () => { @@ -175,6 +208,23 @@ describe('Type System: Enum Values', () => { }); }); + it('does not accept values not in the enum (no suggestions)', () => { + const result = executeQuery( + '{ colorEnum(fromEnum: GREENISH) }', + undefined, + true, + ); + + expectJSON(result).toDeepEqual({ + errors: [ + { + message: 'Value "GREENISH" does not exist in "Color" enum.', + locations: [{ line: 1, column: 23 }], + }, + ], + }); + }); + it('does not accept values with incorrect casing', () => { const result = executeQuery('{ colorEnum(fromEnum: green) }'); @@ -266,7 +316,7 @@ describe('Type System: Enum Values', () => { errors: [ { message: - 'Variable "$color" got invalid value 2; Enum "Color" cannot represent non-string value: 2.', + 'Variable "$color" has invalid value: Enum "Color" cannot represent non-string value: 2.', locations: [{ line: 1, column: 8 }], }, ], @@ -343,24 +393,28 @@ describe('Type System: Enum Values', () => { it('presents a getValues() API for complex enums', () => { const values = ComplexEnum.getValues(); - expect(values).to.have.deep.ordered.members([ - { - name: 'ONE', - description: undefined, - value: Complex1, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - { - name: 'TWO', - description: undefined, - value: Complex2, - deprecationReason: undefined, - extensions: {}, - astNode: undefined, - }, - ]); + + expect(values).to.have.lengthOf(2); + + expect(values[0]).to.deep.include({ + parentEnum: ComplexEnum, + name: 'ONE', + description: undefined, + value: Complex1, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); + + expect(values[1]).to.deep.include({ + parentEnum: ComplexEnum, + name: 'TWO', + description: undefined, + value: Complex2, + deprecationReason: undefined, + extensions: {}, + astNode: undefined, + }); }); it('presents a getValue() API for complex enums', () => { @@ -400,6 +454,28 @@ describe('Type System: Enum Values', () => { }); }); + it('may be internally represented with complex values using legacy internal defaults', () => { + const result = executeQuery(` + { + complexEnumWithLegacyDefault + } + `); + + expectJSON(result).toDeepEqual({ + data: { + complexEnumWithLegacyDefault: 'ONE', + }, + }); + }); + + it('may have values specified via a callback', () => { + const result = executeQuery('{ thunkValuesString(fromEnum: B) }'); + + expect(result).to.deep.equal({ + data: { thunkValuesString: 'b' }, + }); + }); + it('can be introspected without error', () => { expect(() => introspectionFromSchema(schema)).to.not.throw(); }); diff --git a/src/type/__tests__/introspection-test.ts b/src/type/__tests__/introspection-test.ts index e6e5d0943e..9cdfe70697 100644 --- a/src/type/__tests__/introspection-test.ts +++ b/src/type/__tests__/introspection-test.ts @@ -32,7 +32,7 @@ describe('Introspection', () => { expect(result).to.deep.equal({ data: { __schema: { - queryType: { name: 'SomeObject' }, + queryType: { name: 'SomeObject', kind: 'OBJECT' }, mutationType: null, subscriptionType: null, types: [ @@ -859,6 +859,11 @@ describe('Introspection', () => { isDeprecated: false, deprecationReason: null, }, + { + name: 'FRAGMENT_VARIABLE_DEFINITION', + isDeprecated: false, + deprecationReason: null, + }, { name: 'SCHEMA', isDeprecated: false, @@ -973,9 +978,13 @@ describe('Introspection', () => { defaultValue: '"No longer supported"', name: 'reason', type: { - kind: 'SCALAR', - name: 'String', - ofType: null, + kind: 'NON_NULL', + name: null, + ofType: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, }, }, ], @@ -1644,7 +1653,7 @@ describe('Introspection', () => { errors: [ { message: - 'Field "__type" argument "name" of type "String!" is required, but it was not provided.', + 'Argument ".__type(name:)" of type "String!" is required, but it was not provided.', locations: [{ line: 3, column: 9 }], }, ], @@ -1738,11 +1747,11 @@ describe('Introspection', () => { _3: any, info: GraphQLResolveInfo, ): never { - expect.fail(`Called on ${info.parentType.name}::${info.fieldName}`); + expect.fail(`Called on ${info.parentType}::${info.fieldName}`); } function typeResolver(_1: any, _2: any, info: GraphQLResolveInfo): never { - expect.fail(`Called on ${info.parentType.name}::${info.fieldName}`); + expect.fail(`Called on ${info.parentType}::${info.fieldName}`); } /* c8 ignore stop */ diff --git a/src/type/__tests__/predicate-test.ts b/src/type/__tests__/predicate-test.ts index c1e1fb3059..f1089b6f8e 100644 --- a/src/type/__tests__/predicate-test.ts +++ b/src/type/__tests__/predicate-test.ts @@ -5,13 +5,18 @@ import { DirectiveLocation } from '../../language/directiveLocation.js'; import type { GraphQLArgument, + GraphQLDefaultInput, GraphQLInputField, GraphQLInputType, } from '../definition.js'; import { assertAbstractType, + assertArgument, assertCompositeType, assertEnumType, + assertEnumValue, + assertField, + assertInputField, assertInputObjectType, assertInputType, assertInterfaceType, @@ -37,8 +42,12 @@ import { GraphQLScalarType, GraphQLUnionType, isAbstractType, + isArgument, isCompositeType, isEnumType, + isEnumValue, + isField, + isInputField, isInputObjectType, isInputType, isInterfaceType, @@ -75,7 +84,10 @@ import { } from '../scalars.js'; import { assertSchema, GraphQLSchema, isSchema } from '../schema.js'; -const ObjectType = new GraphQLObjectType({ name: 'Object', fields: {} }); +const ObjectType = new GraphQLObjectType({ + name: 'Object', + fields: { f: { type: GraphQLString, args: { a: { type: GraphQLString } } } }, +}); const InterfaceType = new GraphQLInterfaceType({ name: 'Interface', fields: {}, @@ -84,7 +96,7 @@ const UnionType = new GraphQLUnionType({ name: 'Union', types: [ObjectType] }); const EnumType = new GraphQLEnumType({ name: 'Enum', values: { foo: {} } }); const InputObjectType = new GraphQLInputObjectType({ name: 'InputObject', - fields: {}, + fields: { f: { type: GraphQLString } }, }); const ScalarType = new GraphQLScalarType({ name: 'Scalar' }); const Directive = new GraphQLDirective({ @@ -184,6 +196,34 @@ describe('Type predicates', () => { }); }); + describe('isField', () => { + it('returns true for fields', () => { + const f = ObjectType.getFields().f; + expect(isField(f)).to.equal(true); + expect(() => assertField(f)).to.not.throw(); + }); + + it('returns false for non-field', () => { + const inputField = InputObjectType.getFields().f; + expect(isField(inputField)).to.equal(false); + expect(() => assertField(inputField)).to.throw(); + }); + }); + + describe('isArgument', () => { + it('returns true for arguments', () => { + const a = ObjectType.getFields().f.args[0]; + expect(isArgument(a)).to.equal(true); + expect(() => assertArgument(a)).to.not.throw(); + }); + + it('returns false for non-arguments', () => { + const f = ObjectType.getFields().f; + expect(isArgument(f)).to.equal(false); + expect(() => assertArgument(f)).to.throw(); + }); + }); + describe('isInterfaceType', () => { it('returns true for interface type', () => { expect(isInterfaceType(InterfaceType)).to.equal(true); @@ -237,6 +277,19 @@ describe('Type predicates', () => { }); }); + describe('isEnumValue', () => { + it('returns true for enum value', () => { + const value = EnumType.getValue('foo'); + expect(isEnumValue(value)).to.equal(true); + expect(() => assertEnumValue(value)).to.not.throw(); + }); + + it('returns false for non-enum type', () => { + expect(isEnumValue(EnumType)).to.equal(false); + expect(() => assertEnumValue(EnumType)).to.throw(); + }); + }); + describe('isInputObjectType', () => { it('returns true for input object type', () => { expect(isInputObjectType(InputObjectType)).to.equal(true); @@ -258,6 +311,20 @@ describe('Type predicates', () => { }); }); + describe('isInputField', () => { + it('returns true for input fields', () => { + const f = InputObjectType.getFields().f; + expect(isInputField(f)).to.equal(true); + expect(() => assertInputField(f)).to.not.throw(); + }); + + it('returns false for non-input fields', () => { + const f = ObjectType.getFields().f; + expect(isInputField(f)).to.equal(false); + expect(() => assertInputField(f)).to.throw(); + }); + }); + describe('isListType', () => { it('returns true for a list wrapped type', () => { expect(isListType(new GraphQLList(ObjectType))).to.equal(true); @@ -568,17 +635,15 @@ describe('Type predicates', () => { describe('isRequiredArgument', () => { function buildArg(config: { type: GraphQLInputType; - defaultValue?: unknown; + default?: GraphQLDefaultInput; }): GraphQLArgument { - return { - name: 'someArg', - type: config.type, - description: undefined, - defaultValue: config.defaultValue, - deprecationReason: null, - extensions: Object.create(null), - astNode: undefined, - }; + const objectType = new GraphQLObjectType({ + name: 'SomeType', + fields: { + someField: { type: GraphQLString, args: { someArg: config } }, + }, + }); + return objectType.getFields().someField.args[0]; } it('returns true for required arguments', () => { @@ -596,7 +661,7 @@ describe('Type predicates', () => { const optArg2 = buildArg({ type: GraphQLString, - defaultValue: null, + default: { value: null }, }); expect(isRequiredArgument(optArg2)).to.equal(false); @@ -607,7 +672,7 @@ describe('Type predicates', () => { const optArg4 = buildArg({ type: new GraphQLNonNull(GraphQLString), - defaultValue: 'default', + default: { value: 'default' }, }); expect(isRequiredArgument(optArg4)).to.equal(false); }); @@ -616,17 +681,15 @@ describe('Type predicates', () => { describe('isRequiredInputField', () => { function buildInputField(config: { type: GraphQLInputType; - defaultValue?: unknown; + default?: GraphQLDefaultInput; }): GraphQLInputField { - return { - name: 'someInputField', - type: config.type, - description: undefined, - defaultValue: config.defaultValue, - deprecationReason: null, - extensions: Object.create(null), - astNode: undefined, - }; + const inputObjectType = new GraphQLInputObjectType({ + name: 'SomeType', + fields: { + someInputField: config, + }, + }); + return inputObjectType.getFields().someInputField; } it('returns true for required input field', () => { @@ -644,7 +707,7 @@ describe('Type predicates', () => { const optField2 = buildInputField({ type: GraphQLString, - defaultValue: null, + default: { value: null }, }); expect(isRequiredInputField(optField2)).to.equal(false); @@ -655,7 +718,7 @@ describe('Type predicates', () => { const optField4 = buildInputField({ type: new GraphQLNonNull(GraphQLString), - defaultValue: 'default', + default: { value: 'default' }, }); expect(isRequiredInputField(optField4)).to.equal(false); }); diff --git a/src/type/__tests__/scalars-test.ts b/src/type/__tests__/scalars-test.ts index 45f77523dc..73d32b0efb 100644 --- a/src/type/__tests__/scalars-test.ts +++ b/src/type/__tests__/scalars-test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; -import { parseValue as parseValueToAST } from '../../language/parser.js'; +import { parseConstValue } from '../../language/parser.js'; import { GraphQLBoolean, @@ -13,114 +13,112 @@ import { describe('Type System: Specified scalar types', () => { describe('GraphQLInt', () => { - it('parseValue', () => { - function parseValue(value: unknown) { - return GraphQLInt.parseValue(value); + it('coerceInputValue', () => { + function coerceInputValue(value: unknown) { + return GraphQLInt.coerceInputValue(value); } - expect(parseValue(1)).to.equal(1); - expect(parseValue(0)).to.equal(0); - expect(parseValue(-1)).to.equal(-1); + expect(coerceInputValue(1)).to.equal(1); + expect(coerceInputValue(0)).to.equal(0); + expect(coerceInputValue(-1)).to.equal(-1); - expect(() => parseValue(9876504321)).to.throw( + expect(() => coerceInputValue(9876504321)).to.throw( 'Int cannot represent non 32-bit signed integer value: 9876504321', ); - expect(() => parseValue(-9876504321)).to.throw( + expect(() => coerceInputValue(-9876504321)).to.throw( 'Int cannot represent non 32-bit signed integer value: -9876504321', ); - expect(() => parseValue(0.1)).to.throw( + expect(() => coerceInputValue(0.1)).to.throw( 'Int cannot represent non-integer value: 0.1', ); - expect(() => parseValue(NaN)).to.throw( + expect(() => coerceInputValue(NaN)).to.throw( 'Int cannot represent non-integer value: NaN', ); - expect(() => parseValue(Infinity)).to.throw( + expect(() => coerceInputValue(Infinity)).to.throw( 'Int cannot represent non-integer value: Infinity', ); - expect(() => parseValue(undefined)).to.throw( + expect(() => coerceInputValue(undefined)).to.throw( 'Int cannot represent non-integer value: undefined', ); - expect(() => parseValue(null)).to.throw( + expect(() => coerceInputValue(null)).to.throw( 'Int cannot represent non-integer value: null', ); - expect(() => parseValue('')).to.throw( + expect(() => coerceInputValue('')).to.throw( 'Int cannot represent non-integer value: ""', ); - expect(() => parseValue('123')).to.throw( + expect(() => coerceInputValue('123')).to.throw( 'Int cannot represent non-integer value: "123"', ); - expect(() => parseValue(false)).to.throw( + expect(() => coerceInputValue(false)).to.throw( 'Int cannot represent non-integer value: false', ); - expect(() => parseValue(true)).to.throw( + expect(() => coerceInputValue(true)).to.throw( 'Int cannot represent non-integer value: true', ); - expect(() => parseValue([1])).to.throw( + expect(() => coerceInputValue([1])).to.throw( 'Int cannot represent non-integer value: [1]', ); - expect(() => parseValue({ value: 1 })).to.throw( + expect(() => coerceInputValue({ value: 1 })).to.throw( 'Int cannot represent non-integer value: { value: 1 }', ); }); - it('parseLiteral', () => { - function parseLiteral(str: string) { - return GraphQLInt.parseLiteral(parseValueToAST(str), undefined); + it('coerceInputLiteral', () => { + function coerceInputLiteral(str: string) { + /* @ts-expect-error to be removed in v18 when all custom scalars will have default method */ + return GraphQLInt.coerceInputLiteral(parseConstValue(str)); } - expect(parseLiteral('1')).to.equal(1); - expect(parseLiteral('0')).to.equal(0); - expect(parseLiteral('-1')).to.equal(-1); + expect(coerceInputLiteral('1')).to.equal(1); + expect(coerceInputLiteral('0')).to.equal(0); + expect(coerceInputLiteral('-1')).to.equal(-1); - expect(() => parseLiteral('9876504321')).to.throw( + expect(() => coerceInputLiteral('9876504321')).to.throw( 'Int cannot represent non 32-bit signed integer value: 9876504321', ); - expect(() => parseLiteral('-9876504321')).to.throw( + expect(() => coerceInputLiteral('-9876504321')).to.throw( 'Int cannot represent non 32-bit signed integer value: -9876504321', ); - expect(() => parseLiteral('1.0')).to.throw( + expect(() => coerceInputLiteral('1.0')).to.throw( 'Int cannot represent non-integer value: 1.0', ); - expect(() => parseLiteral('null')).to.throw( + expect(() => coerceInputLiteral('null')).to.throw( 'Int cannot represent non-integer value: null', ); - expect(() => parseLiteral('""')).to.throw( + expect(() => coerceInputLiteral('""')).to.throw( 'Int cannot represent non-integer value: ""', ); - expect(() => parseLiteral('"123"')).to.throw( + expect(() => coerceInputLiteral('"123"')).to.throw( 'Int cannot represent non-integer value: "123"', ); - expect(() => parseLiteral('false')).to.throw( + expect(() => coerceInputLiteral('false')).to.throw( 'Int cannot represent non-integer value: false', ); - expect(() => parseLiteral('[1]')).to.throw( + expect(() => coerceInputLiteral('[1]')).to.throw( 'Int cannot represent non-integer value: [1]', ); - expect(() => parseLiteral('{ value: 1 }')).to.throw( + expect(() => coerceInputLiteral('{ value: 1 }')).to.throw( 'Int cannot represent non-integer value: { value: 1 }', ); - expect(() => parseLiteral('ENUM_VALUE')).to.throw( + expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw( 'Int cannot represent non-integer value: ENUM_VALUE', ); - expect(() => parseLiteral('$var')).to.throw( - 'Int cannot represent non-integer value: $var', - ); }); - it('serialize', () => { - function serialize(value: unknown) { - return GraphQLInt.serialize(value); + it('coerceOutputValue', () => { + function coerceOutputValue(value: unknown) { + return GraphQLInt.coerceOutputValue(value); } - expect(serialize(1)).to.equal(1); - expect(serialize('123')).to.equal(123); - expect(serialize(0)).to.equal(0); - expect(serialize(-1)).to.equal(-1); - expect(serialize(1e5)).to.equal(100000); - expect(serialize(false)).to.equal(0); - expect(serialize(true)).to.equal(1); + expect(coerceOutputValue(1)).to.equal(1); + expect(coerceOutputValue('123')).to.equal(123); + expect(coerceOutputValue(0)).to.equal(0); + expect(coerceOutputValue(-1)).to.equal(-1); + expect(coerceOutputValue(1e5)).to.equal(100000); + expect(coerceOutputValue(false)).to.equal(0); + expect(coerceOutputValue(true)).to.equal(1); const customValueOfObj = { value: 5, @@ -128,162 +126,160 @@ describe('Type System: Specified scalar types', () => { return this.value; }, }; - expect(serialize(customValueOfObj)).to.equal(5); + expect(coerceOutputValue(customValueOfObj)).to.equal(5); // The GraphQL specification does not allow serializing non-integer values // as Int to avoid accidental data loss. - expect(() => serialize(0.1)).to.throw( + expect(() => coerceOutputValue(0.1)).to.throw( 'Int cannot represent non-integer value: 0.1', ); - expect(() => serialize(1.1)).to.throw( + expect(() => coerceOutputValue(1.1)).to.throw( 'Int cannot represent non-integer value: 1.1', ); - expect(() => serialize(-1.1)).to.throw( + expect(() => coerceOutputValue(-1.1)).to.throw( 'Int cannot represent non-integer value: -1.1', ); - expect(() => serialize('-1.1')).to.throw( + expect(() => coerceOutputValue('-1.1')).to.throw( 'Int cannot represent non-integer value: "-1.1"', ); // Maybe a safe JavaScript int, but bigger than 2^32, so not // representable as a GraphQL Int - expect(() => serialize(9876504321)).to.throw( + expect(() => coerceOutputValue(9876504321)).to.throw( 'Int cannot represent non 32-bit signed integer value: 9876504321', ); - expect(() => serialize(-9876504321)).to.throw( + expect(() => coerceOutputValue(-9876504321)).to.throw( 'Int cannot represent non 32-bit signed integer value: -9876504321', ); // Too big to represent as an Int in JavaScript or GraphQL - expect(() => serialize(1e100)).to.throw( + expect(() => coerceOutputValue(1e100)).to.throw( 'Int cannot represent non 32-bit signed integer value: 1e+100', ); - expect(() => serialize(-1e100)).to.throw( + expect(() => coerceOutputValue(-1e100)).to.throw( 'Int cannot represent non 32-bit signed integer value: -1e+100', ); - expect(() => serialize('one')).to.throw( + expect(() => coerceOutputValue('one')).to.throw( 'Int cannot represent non-integer value: "one"', ); // Doesn't represent number - expect(() => serialize('')).to.throw( + expect(() => coerceOutputValue('')).to.throw( 'Int cannot represent non-integer value: ""', ); - expect(() => serialize(NaN)).to.throw( + expect(() => coerceOutputValue(NaN)).to.throw( 'Int cannot represent non-integer value: NaN', ); - expect(() => serialize(Infinity)).to.throw( + expect(() => coerceOutputValue(Infinity)).to.throw( 'Int cannot represent non-integer value: Infinity', ); - expect(() => serialize([5])).to.throw( + expect(() => coerceOutputValue([5])).to.throw( 'Int cannot represent non-integer value: [5]', ); }); }); describe('GraphQLFloat', () => { - it('parseValue', () => { - function parseValue(value: unknown) { - return GraphQLFloat.parseValue(value); + it('coerceInputValue', () => { + function coerceInputValue(value: unknown) { + return GraphQLFloat.coerceInputValue(value); } - expect(parseValue(1)).to.equal(1); - expect(parseValue(0)).to.equal(0); - expect(parseValue(-1)).to.equal(-1); - expect(parseValue(0.1)).to.equal(0.1); - expect(parseValue(Math.PI)).to.equal(Math.PI); + expect(coerceInputValue(1)).to.equal(1); + expect(coerceInputValue(0)).to.equal(0); + expect(coerceInputValue(-1)).to.equal(-1); + expect(coerceInputValue(0.1)).to.equal(0.1); + expect(coerceInputValue(Math.PI)).to.equal(Math.PI); - expect(() => parseValue(NaN)).to.throw( + expect(() => coerceInputValue(NaN)).to.throw( 'Float cannot represent non numeric value: NaN', ); - expect(() => parseValue(Infinity)).to.throw( + expect(() => coerceInputValue(Infinity)).to.throw( 'Float cannot represent non numeric value: Infinity', ); - expect(() => parseValue(undefined)).to.throw( + expect(() => coerceInputValue(undefined)).to.throw( 'Float cannot represent non numeric value: undefined', ); - expect(() => parseValue(null)).to.throw( + expect(() => coerceInputValue(null)).to.throw( 'Float cannot represent non numeric value: null', ); - expect(() => parseValue('')).to.throw( + expect(() => coerceInputValue('')).to.throw( 'Float cannot represent non numeric value: ""', ); - expect(() => parseValue('123')).to.throw( + expect(() => coerceInputValue('123')).to.throw( 'Float cannot represent non numeric value: "123"', ); - expect(() => parseValue('123.5')).to.throw( + expect(() => coerceInputValue('123.5')).to.throw( 'Float cannot represent non numeric value: "123.5"', ); - expect(() => parseValue(false)).to.throw( + expect(() => coerceInputValue(false)).to.throw( 'Float cannot represent non numeric value: false', ); - expect(() => parseValue(true)).to.throw( + expect(() => coerceInputValue(true)).to.throw( 'Float cannot represent non numeric value: true', ); - expect(() => parseValue([0.1])).to.throw( + expect(() => coerceInputValue([0.1])).to.throw( 'Float cannot represent non numeric value: [0.1]', ); - expect(() => parseValue({ value: 0.1 })).to.throw( + expect(() => coerceInputValue({ value: 0.1 })).to.throw( 'Float cannot represent non numeric value: { value: 0.1 }', ); }); - it('parseLiteral', () => { - function parseLiteral(str: string) { - return GraphQLFloat.parseLiteral(parseValueToAST(str), undefined); + it('coerceInputLiteral', () => { + function coerceInputLiteral(str: string) { + /* @ts-expect-error to be removed in v18 when all custom scalars will have default method */ + return GraphQLFloat.coerceInputLiteral(parseConstValue(str)); } - expect(parseLiteral('1')).to.equal(1); - expect(parseLiteral('0')).to.equal(0); - expect(parseLiteral('-1')).to.equal(-1); - expect(parseLiteral('0.1')).to.equal(0.1); - expect(parseLiteral(Math.PI.toString())).to.equal(Math.PI); + expect(coerceInputLiteral('1')).to.equal(1); + expect(coerceInputLiteral('0')).to.equal(0); + expect(coerceInputLiteral('-1')).to.equal(-1); + expect(coerceInputLiteral('0.1')).to.equal(0.1); + expect(coerceInputLiteral(Math.PI.toString())).to.equal(Math.PI); - expect(() => parseLiteral('null')).to.throw( + expect(() => coerceInputLiteral('null')).to.throw( 'Float cannot represent non numeric value: null', ); - expect(() => parseLiteral('""')).to.throw( + expect(() => coerceInputLiteral('""')).to.throw( 'Float cannot represent non numeric value: ""', ); - expect(() => parseLiteral('"123"')).to.throw( + expect(() => coerceInputLiteral('"123"')).to.throw( 'Float cannot represent non numeric value: "123"', ); - expect(() => parseLiteral('"123.5"')).to.throw( + expect(() => coerceInputLiteral('"123.5"')).to.throw( 'Float cannot represent non numeric value: "123.5"', ); - expect(() => parseLiteral('false')).to.throw( + expect(() => coerceInputLiteral('false')).to.throw( 'Float cannot represent non numeric value: false', ); - expect(() => parseLiteral('[0.1]')).to.throw( + expect(() => coerceInputLiteral('[0.1]')).to.throw( 'Float cannot represent non numeric value: [0.1]', ); - expect(() => parseLiteral('{ value: 0.1 }')).to.throw( + expect(() => coerceInputLiteral('{ value: 0.1 }')).to.throw( 'Float cannot represent non numeric value: { value: 0.1 }', ); - expect(() => parseLiteral('ENUM_VALUE')).to.throw( + expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw( 'Float cannot represent non numeric value: ENUM_VALUE', ); - expect(() => parseLiteral('$var')).to.throw( - 'Float cannot represent non numeric value: $var', - ); }); - it('serialize', () => { - function serialize(value: unknown) { - return GraphQLFloat.serialize(value); + it('coerceOutputValue', () => { + function coerceOutputValue(value: unknown) { + return GraphQLFloat.coerceOutputValue(value); } - expect(serialize(1)).to.equal(1.0); - expect(serialize(0)).to.equal(0.0); - expect(serialize('123.5')).to.equal(123.5); - expect(serialize(-1)).to.equal(-1.0); - expect(serialize(0.1)).to.equal(0.1); - expect(serialize(1.1)).to.equal(1.1); - expect(serialize(-1.1)).to.equal(-1.1); - expect(serialize('-1.1')).to.equal(-1.1); - expect(serialize(false)).to.equal(0.0); - expect(serialize(true)).to.equal(1.0); + expect(coerceOutputValue(1)).to.equal(1.0); + expect(coerceOutputValue(0)).to.equal(0.0); + expect(coerceOutputValue('123.5')).to.equal(123.5); + expect(coerceOutputValue(-1)).to.equal(-1.0); + expect(coerceOutputValue(0.1)).to.equal(0.1); + expect(coerceOutputValue(1.1)).to.equal(1.1); + expect(coerceOutputValue(-1.1)).to.equal(-1.1); + expect(coerceOutputValue('-1.1')).to.equal(-1.1); + expect(coerceOutputValue(false)).to.equal(0.0); + expect(coerceOutputValue(true)).to.equal(1.0); const customValueOfObj = { value: 5.5, @@ -291,220 +287,218 @@ describe('Type System: Specified scalar types', () => { return this.value; }, }; - expect(serialize(customValueOfObj)).to.equal(5.5); + expect(coerceOutputValue(customValueOfObj)).to.equal(5.5); - expect(() => serialize(NaN)).to.throw( + expect(() => coerceOutputValue(NaN)).to.throw( 'Float cannot represent non numeric value: NaN', ); - expect(() => serialize(Infinity)).to.throw( + expect(() => coerceOutputValue(Infinity)).to.throw( 'Float cannot represent non numeric value: Infinity', ); - expect(() => serialize('one')).to.throw( + expect(() => coerceOutputValue('one')).to.throw( 'Float cannot represent non numeric value: "one"', ); - expect(() => serialize('')).to.throw( + expect(() => coerceOutputValue('')).to.throw( 'Float cannot represent non numeric value: ""', ); - expect(() => serialize([5])).to.throw( + expect(() => coerceOutputValue([5])).to.throw( 'Float cannot represent non numeric value: [5]', ); }); }); describe('GraphQLString', () => { - it('parseValue', () => { - function parseValue(value: unknown) { - return GraphQLString.parseValue(value); + it('coerceInputValue', () => { + function coerceInputValue(value: unknown) { + return GraphQLString.coerceInputValue(value); } - expect(parseValue('foo')).to.equal('foo'); + expect(coerceInputValue('foo')).to.equal('foo'); - expect(() => parseValue(undefined)).to.throw( + expect(() => coerceInputValue(undefined)).to.throw( 'String cannot represent a non string value: undefined', ); - expect(() => parseValue(null)).to.throw( + expect(() => coerceInputValue(null)).to.throw( 'String cannot represent a non string value: null', ); - expect(() => parseValue(1)).to.throw( + expect(() => coerceInputValue(1)).to.throw( 'String cannot represent a non string value: 1', ); - expect(() => parseValue(NaN)).to.throw( + expect(() => coerceInputValue(NaN)).to.throw( 'String cannot represent a non string value: NaN', ); - expect(() => parseValue(false)).to.throw( + expect(() => coerceInputValue(false)).to.throw( 'String cannot represent a non string value: false', ); - expect(() => parseValue(['foo'])).to.throw( + expect(() => coerceInputValue(['foo'])).to.throw( 'String cannot represent a non string value: ["foo"]', ); - expect(() => parseValue({ value: 'foo' })).to.throw( + expect(() => coerceInputValue({ value: 'foo' })).to.throw( 'String cannot represent a non string value: { value: "foo" }', ); }); - it('parseLiteral', () => { - function parseLiteral(str: string) { - return GraphQLString.parseLiteral(parseValueToAST(str), undefined); + it('coerceInputLiteral', () => { + function coerceInputLiteral(str: string) { + /* @ts-expect-error to be removed in v18 when all custom scalars will have default method */ + return GraphQLString.coerceInputLiteral(parseConstValue(str)); } - expect(parseLiteral('"foo"')).to.equal('foo'); - expect(parseLiteral('"""bar"""')).to.equal('bar'); + expect(coerceInputLiteral('"foo"')).to.equal('foo'); + expect(coerceInputLiteral('"""bar"""')).to.equal('bar'); - expect(() => parseLiteral('null')).to.throw( + expect(() => coerceInputLiteral('null')).to.throw( 'String cannot represent a non string value: null', ); - expect(() => parseLiteral('1')).to.throw( + expect(() => coerceInputLiteral('1')).to.throw( 'String cannot represent a non string value: 1', ); - expect(() => parseLiteral('0.1')).to.throw( + expect(() => coerceInputLiteral('0.1')).to.throw( 'String cannot represent a non string value: 0.1', ); - expect(() => parseLiteral('false')).to.throw( + expect(() => coerceInputLiteral('false')).to.throw( 'String cannot represent a non string value: false', ); - expect(() => parseLiteral('["foo"]')).to.throw( + expect(() => coerceInputLiteral('["foo"]')).to.throw( 'String cannot represent a non string value: ["foo"]', ); - expect(() => parseLiteral('{ value: "foo" }')).to.throw( + expect(() => coerceInputLiteral('{ value: "foo" }')).to.throw( 'String cannot represent a non string value: { value: "foo" }', ); - expect(() => parseLiteral('ENUM_VALUE')).to.throw( + expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw( 'String cannot represent a non string value: ENUM_VALUE', ); - expect(() => parseLiteral('$var')).to.throw( - 'String cannot represent a non string value: $var', - ); }); - it('serialize', () => { - function serialize(value: unknown) { - return GraphQLString.serialize(value); + it('coerceOutputValue', () => { + function coerceOutputValue(value: unknown) { + return GraphQLString.coerceOutputValue(value); } - expect(serialize('string')).to.equal('string'); - expect(serialize(1)).to.equal('1'); - expect(serialize(-1.1)).to.equal('-1.1'); - expect(serialize(true)).to.equal('true'); - expect(serialize(false)).to.equal('false'); + expect(coerceOutputValue('string')).to.equal('string'); + expect(coerceOutputValue(1)).to.equal('1'); + expect(coerceOutputValue(-1.1)).to.equal('-1.1'); + expect(coerceOutputValue(true)).to.equal('true'); + expect(coerceOutputValue(false)).to.equal('false'); const valueOf = () => 'valueOf string'; const toJSON = () => 'toJSON string'; const valueOfAndToJSONValue = { valueOf, toJSON }; - expect(serialize(valueOfAndToJSONValue)).to.equal('valueOf string'); + expect(coerceOutputValue(valueOfAndToJSONValue)).to.equal( + 'valueOf string', + ); const onlyToJSONValue = { toJSON }; - expect(serialize(onlyToJSONValue)).to.equal('toJSON string'); + expect(coerceOutputValue(onlyToJSONValue)).to.equal('toJSON string'); - expect(() => serialize(NaN)).to.throw( + expect(() => coerceOutputValue(NaN)).to.throw( 'String cannot represent value: NaN', ); - expect(() => serialize([1])).to.throw( + expect(() => coerceOutputValue([1])).to.throw( 'String cannot represent value: [1]', ); const badObjValue = {}; - expect(() => serialize(badObjValue)).to.throw( + expect(() => coerceOutputValue(badObjValue)).to.throw( 'String cannot represent value: {}', ); const badValueOfObjValue = { valueOf: 'valueOf string' }; - expect(() => serialize(badValueOfObjValue)).to.throw( + expect(() => coerceOutputValue(badValueOfObjValue)).to.throw( 'String cannot represent value: { valueOf: "valueOf string" }', ); }); }); describe('GraphQLBoolean', () => { - it('parseValue', () => { - function parseValue(value: unknown) { - return GraphQLBoolean.parseValue(value); + it('coerceInputValue', () => { + function coerceInputValue(value: unknown) { + return GraphQLBoolean.coerceInputValue(value); } - expect(parseValue(true)).to.equal(true); - expect(parseValue(false)).to.equal(false); + expect(coerceInputValue(true)).to.equal(true); + expect(coerceInputValue(false)).to.equal(false); - expect(() => parseValue(undefined)).to.throw( + expect(() => coerceInputValue(undefined)).to.throw( 'Boolean cannot represent a non boolean value: undefined', ); - expect(() => parseValue(null)).to.throw( + expect(() => coerceInputValue(null)).to.throw( 'Boolean cannot represent a non boolean value: null', ); - expect(() => parseValue(0)).to.throw( + expect(() => coerceInputValue(0)).to.throw( 'Boolean cannot represent a non boolean value: 0', ); - expect(() => parseValue(1)).to.throw( + expect(() => coerceInputValue(1)).to.throw( 'Boolean cannot represent a non boolean value: 1', ); - expect(() => parseValue(NaN)).to.throw( + expect(() => coerceInputValue(NaN)).to.throw( 'Boolean cannot represent a non boolean value: NaN', ); - expect(() => parseValue('')).to.throw( + expect(() => coerceInputValue('')).to.throw( 'Boolean cannot represent a non boolean value: ""', ); - expect(() => parseValue('false')).to.throw( + expect(() => coerceInputValue('false')).to.throw( 'Boolean cannot represent a non boolean value: "false"', ); - expect(() => parseValue([false])).to.throw( + expect(() => coerceInputValue([false])).to.throw( 'Boolean cannot represent a non boolean value: [false]', ); - expect(() => parseValue({ value: false })).to.throw( + expect(() => coerceInputValue({ value: false })).to.throw( 'Boolean cannot represent a non boolean value: { value: false }', ); }); - it('parseLiteral', () => { - function parseLiteral(str: string) { - return GraphQLBoolean.parseLiteral(parseValueToAST(str), undefined); + it('coerceInputLiteral', () => { + function coerceInputLiteral(str: string) { + /* @ts-expect-error to be removed in v18 when all custom scalars will have default method */ + return GraphQLBoolean.coerceInputLiteral(parseConstValue(str)); } - expect(parseLiteral('true')).to.equal(true); - expect(parseLiteral('false')).to.equal(false); + expect(coerceInputLiteral('true')).to.equal(true); + expect(coerceInputLiteral('false')).to.equal(false); - expect(() => parseLiteral('null')).to.throw( + expect(() => coerceInputLiteral('null')).to.throw( 'Boolean cannot represent a non boolean value: null', ); - expect(() => parseLiteral('0')).to.throw( + expect(() => coerceInputLiteral('0')).to.throw( 'Boolean cannot represent a non boolean value: 0', ); - expect(() => parseLiteral('1')).to.throw( + expect(() => coerceInputLiteral('1')).to.throw( 'Boolean cannot represent a non boolean value: 1', ); - expect(() => parseLiteral('0.1')).to.throw( + expect(() => coerceInputLiteral('0.1')).to.throw( 'Boolean cannot represent a non boolean value: 0.1', ); - expect(() => parseLiteral('""')).to.throw( + expect(() => coerceInputLiteral('""')).to.throw( 'Boolean cannot represent a non boolean value: ""', ); - expect(() => parseLiteral('"false"')).to.throw( + expect(() => coerceInputLiteral('"false"')).to.throw( 'Boolean cannot represent a non boolean value: "false"', ); - expect(() => parseLiteral('[false]')).to.throw( + expect(() => coerceInputLiteral('[false]')).to.throw( 'Boolean cannot represent a non boolean value: [false]', ); - expect(() => parseLiteral('{ value: false }')).to.throw( + expect(() => coerceInputLiteral('{ value: false }')).to.throw( 'Boolean cannot represent a non boolean value: { value: false }', ); - expect(() => parseLiteral('ENUM_VALUE')).to.throw( + expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw( 'Boolean cannot represent a non boolean value: ENUM_VALUE', ); - expect(() => parseLiteral('$var')).to.throw( - 'Boolean cannot represent a non boolean value: $var', - ); }); - it('serialize', () => { - function serialize(value: unknown) { - return GraphQLBoolean.serialize(value); + it('coerceOutputValue', () => { + function coerceOutputValue(value: unknown) { + return GraphQLBoolean.coerceOutputValue(value); } - expect(serialize(1)).to.equal(true); - expect(serialize(0)).to.equal(false); - expect(serialize(true)).to.equal(true); - expect(serialize(false)).to.equal(false); + expect(coerceOutputValue(1)).to.equal(true); + expect(coerceOutputValue(0)).to.equal(false); + expect(coerceOutputValue(true)).to.equal(true); + expect(coerceOutputValue(false)).to.equal(false); expect( - serialize({ + coerceOutputValue({ value: true, valueOf() { return (this as { value: boolean }).value; @@ -512,123 +506,129 @@ describe('Type System: Specified scalar types', () => { }), ).to.equal(true); - expect(() => serialize(NaN)).to.throw( + expect(() => coerceOutputValue(NaN)).to.throw( 'Boolean cannot represent a non boolean value: NaN', ); - expect(() => serialize('')).to.throw( + expect(() => coerceOutputValue('')).to.throw( 'Boolean cannot represent a non boolean value: ""', ); - expect(() => serialize('true')).to.throw( + expect(() => coerceOutputValue('true')).to.throw( 'Boolean cannot represent a non boolean value: "true"', ); - expect(() => serialize([false])).to.throw( + expect(() => coerceOutputValue([false])).to.throw( 'Boolean cannot represent a non boolean value: [false]', ); - expect(() => serialize({})).to.throw( + expect(() => coerceOutputValue({})).to.throw( 'Boolean cannot represent a non boolean value: {}', ); }); }); describe('GraphQLID', () => { - it('parseValue', () => { - function parseValue(value: unknown) { - return GraphQLID.parseValue(value); + it('coerceInputValue', () => { + function coerceInputValue(value: unknown) { + return GraphQLID.coerceInputValue(value); } - expect(parseValue('')).to.equal(''); - expect(parseValue('1')).to.equal('1'); - expect(parseValue('foo')).to.equal('foo'); - expect(parseValue(1)).to.equal('1'); - expect(parseValue(0)).to.equal('0'); - expect(parseValue(-1)).to.equal('-1'); + expect(coerceInputValue('')).to.equal(''); + expect(coerceInputValue('1')).to.equal('1'); + expect(coerceInputValue('foo')).to.equal('foo'); + expect(coerceInputValue(1)).to.equal('1'); + expect(coerceInputValue(0)).to.equal('0'); + expect(coerceInputValue(-1)).to.equal('-1'); // Maximum and minimum safe numbers in JS - expect(parseValue(9007199254740991)).to.equal('9007199254740991'); - expect(parseValue(-9007199254740991)).to.equal('-9007199254740991'); + expect(coerceInputValue(9007199254740991)).to.equal('9007199254740991'); + expect(coerceInputValue(-9007199254740991)).to.equal('-9007199254740991'); - expect(() => parseValue(undefined)).to.throw( + expect(() => coerceInputValue(undefined)).to.throw( 'ID cannot represent value: undefined', ); - expect(() => parseValue(null)).to.throw( + expect(() => coerceInputValue(null)).to.throw( 'ID cannot represent value: null', ); - expect(() => parseValue(0.1)).to.throw('ID cannot represent value: 0.1'); - expect(() => parseValue(NaN)).to.throw('ID cannot represent value: NaN'); - expect(() => parseValue(Infinity)).to.throw( + expect(() => coerceInputValue(0.1)).to.throw( + 'ID cannot represent value: 0.1', + ); + expect(() => coerceInputValue(NaN)).to.throw( + 'ID cannot represent value: NaN', + ); + expect(() => coerceInputValue(Infinity)).to.throw( 'ID cannot represent value: Inf', ); - expect(() => parseValue(false)).to.throw( + expect(() => coerceInputValue(false)).to.throw( 'ID cannot represent value: false', ); - expect(() => GraphQLID.parseValue(['1'])).to.throw( + expect(() => GraphQLID.coerceInputValue(['1'])).to.throw( 'ID cannot represent value: ["1"]', ); - expect(() => GraphQLID.parseValue({ value: '1' })).to.throw( + expect(() => GraphQLID.coerceInputValue({ value: '1' })).to.throw( 'ID cannot represent value: { value: "1" }', ); }); - it('parseLiteral', () => { - function parseLiteral(str: string) { - return GraphQLID.parseLiteral(parseValueToAST(str), undefined); + it('coerceInputLiteral', () => { + function coerceInputLiteral(str: string) { + /* @ts-expect-error to be removed in v18 when all custom scalars will have default method */ + return GraphQLID.coerceInputLiteral(parseConstValue(str)); } - expect(parseLiteral('""')).to.equal(''); - expect(parseLiteral('"1"')).to.equal('1'); - expect(parseLiteral('"foo"')).to.equal('foo'); - expect(parseLiteral('"""foo"""')).to.equal('foo'); - expect(parseLiteral('1')).to.equal('1'); - expect(parseLiteral('0')).to.equal('0'); - expect(parseLiteral('-1')).to.equal('-1'); + expect(coerceInputLiteral('""')).to.equal(''); + expect(coerceInputLiteral('"1"')).to.equal('1'); + expect(coerceInputLiteral('"foo"')).to.equal('foo'); + expect(coerceInputLiteral('"""foo"""')).to.equal('foo'); + expect(coerceInputLiteral('1')).to.equal('1'); + expect(coerceInputLiteral('0')).to.equal('0'); + expect(coerceInputLiteral('-1')).to.equal('-1'); // Support arbitrary long numbers even if they can't be represented in JS - expect(parseLiteral('90071992547409910')).to.equal('90071992547409910'); - expect(parseLiteral('-90071992547409910')).to.equal('-90071992547409910'); + expect(coerceInputLiteral('90071992547409910')).to.equal( + '90071992547409910', + ); + expect(coerceInputLiteral('-90071992547409910')).to.equal( + '-90071992547409910', + ); - expect(() => parseLiteral('null')).to.throw( + expect(() => coerceInputLiteral('null')).to.throw( 'ID cannot represent a non-string and non-integer value: null', ); - expect(() => parseLiteral('0.1')).to.throw( + expect(() => coerceInputLiteral('0.1')).to.throw( 'ID cannot represent a non-string and non-integer value: 0.1', ); - expect(() => parseLiteral('false')).to.throw( + expect(() => coerceInputLiteral('false')).to.throw( 'ID cannot represent a non-string and non-integer value: false', ); - expect(() => parseLiteral('["1"]')).to.throw( + expect(() => coerceInputLiteral('["1"]')).to.throw( 'ID cannot represent a non-string and non-integer value: ["1"]', ); - expect(() => parseLiteral('{ value: "1" }')).to.throw( + expect(() => coerceInputLiteral('{ value: "1" }')).to.throw( 'ID cannot represent a non-string and non-integer value: { value: "1" }', ); - expect(() => parseLiteral('ENUM_VALUE')).to.throw( + expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw( 'ID cannot represent a non-string and non-integer value: ENUM_VALUE', ); - expect(() => parseLiteral('$var')).to.throw( - 'ID cannot represent a non-string and non-integer value: $var', - ); }); - it('serialize', () => { - function serialize(value: unknown) { - return GraphQLID.serialize(value); + it('coerceOutputValue', () => { + function coerceOutputValue(value: unknown) { + return GraphQLID.coerceOutputValue(value); } - expect(serialize('string')).to.equal('string'); - expect(serialize('false')).to.equal('false'); - expect(serialize('')).to.equal(''); - expect(serialize(123)).to.equal('123'); - expect(serialize(0)).to.equal('0'); - expect(serialize(-1)).to.equal('-1'); + expect(coerceOutputValue('string')).to.equal('string'); + expect(coerceOutputValue('false')).to.equal('false'); + expect(coerceOutputValue('')).to.equal(''); + expect(coerceOutputValue(123)).to.equal('123'); + expect(coerceOutputValue(0)).to.equal('0'); + expect(coerceOutputValue(-1)).to.equal('-1'); const valueOf = () => 'valueOf ID'; const toJSON = () => 'toJSON ID'; const valueOfAndToJSONValue = { valueOf, toJSON }; - expect(serialize(valueOfAndToJSONValue)).to.equal('valueOf ID'); + expect(coerceOutputValue(valueOfAndToJSONValue)).to.equal('valueOf ID'); const onlyToJSONValue = { toJSON }; - expect(serialize(onlyToJSONValue)).to.equal('toJSON ID'); + expect(coerceOutputValue(onlyToJSONValue)).to.equal('toJSON ID'); const badObjValue = { _id: false, @@ -636,17 +636,23 @@ describe('Type System: Specified scalar types', () => { return this._id; }, }; - expect(() => serialize(badObjValue)).to.throw( + expect(() => coerceOutputValue(badObjValue)).to.throw( 'ID cannot represent value: { _id: false, valueOf: [function valueOf] }', ); - expect(() => serialize(true)).to.throw('ID cannot represent value: true'); + expect(() => coerceOutputValue(true)).to.throw( + 'ID cannot represent value: true', + ); - expect(() => serialize(3.14)).to.throw('ID cannot represent value: 3.14'); + expect(() => coerceOutputValue(3.14)).to.throw( + 'ID cannot represent value: 3.14', + ); - expect(() => serialize({})).to.throw('ID cannot represent value: {}'); + expect(() => coerceOutputValue({})).to.throw( + 'ID cannot represent value: {}', + ); - expect(() => serialize(['abc'])).to.throw( + expect(() => coerceOutputValue(['abc'])).to.throw( 'ID cannot represent value: ["abc"]', ); }); diff --git a/src/type/__tests__/schema-test.ts b/src/type/__tests__/schema-test.ts index 5bd86e030a..0dedb01cc9 100644 --- a/src/type/__tests__/schema-test.ts +++ b/src/type/__tests__/schema-test.ts @@ -24,6 +24,7 @@ import { } from '../introspection.js'; import { GraphQLBoolean, GraphQLInt, GraphQLString } from '../scalars.js'; import { GraphQLSchema } from '../schema.js'; +import { validateSchema } from '../validate.js'; describe('Type System: Schema', () => { it('Define sample schema', () => { @@ -432,11 +433,21 @@ describe('Type System: Schema', () => { describe('Validity', () => { describe('when not assumed valid', () => { it('configures the schema to still needing validation', () => { - expect( - new GraphQLSchema({ - assumeValid: false, - }).__validationErrors, - ).to.equal(undefined); + const schema = new GraphQLSchema({ + assumeValid: false, + }); + expect(schema.assumeValid).to.equal(false); + expect(schema.__validationErrors).to.equal(undefined); + }); + + it('configures the schema to have required validation even once validated', () => { + const schema = new GraphQLSchema({ + assumeValid: false, + }); + const validationErrors = validateSchema(schema); + expect(validationErrors.length).to.be.greaterThan(0); + expect(validationErrors).to.equal(schema.__validationErrors); + expect(schema.assumeValid).to.equal(false); }); }); @@ -486,11 +497,11 @@ describe('Type System: Schema', () => { describe('when assumed valid', () => { it('configures the schema to have no errors', () => { - expect( - new GraphQLSchema({ - assumeValid: true, - }).__validationErrors, - ).to.deep.equal([]); + const schema = new GraphQLSchema({ + assumeValid: true, + }); + expect(schema.assumeValid).to.equal(true); + expect(schema.__validationErrors).to.deep.equal([]); }); }); }); diff --git a/src/type/__tests__/validation-test.ts b/src/type/__tests__/validation-test.ts index 7d215361f9..9e003d874e 100644 --- a/src/type/__tests__/validation-test.ts +++ b/src/type/__tests__/validation-test.ts @@ -1,4 +1,4 @@ -import { expect } from 'chai'; +import { assert, expect } from 'chai'; import { describe, it } from 'mocha'; import { dedent } from '../../__testUtils__/dedent.js'; @@ -33,10 +33,11 @@ import { GraphQLList, GraphQLNonNull, GraphQLObjectType, + GraphQLScalarType, GraphQLUnionType, } from '../definition.js'; import { assertDirective, GraphQLDirective } from '../directives.js'; -import { GraphQLString } from '../scalars.js'; +import { GraphQLInt, GraphQLString } from '../scalars.js'; import { GraphQLSchema } from '../schema.js'; import { assertValidSchema, validateSchema } from '../validate.js'; @@ -431,6 +432,23 @@ describe('Type System: A Schema must have Object root types', () => { }, ]); }); + + it('rejects a Schema whose directives have empty locations', () => { + const badDirective = new GraphQLDirective({ + name: 'BadDirective', + args: {}, + locations: [], + }); + const schema = new GraphQLSchema({ + query: SomeObjectType, + directives: [badDirective], + }); + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: 'Directive @BadDirective must include 1 or more locations.', + }, + ]); + }); }); describe('Type System: Root types must all be different if provided', () => { @@ -790,6 +808,40 @@ describe('Type System: Union types must be valid', () => { ]); } }); + + it('rejects a Union type with non-Object members types with malformed AST', () => { + const schema = buildSchema(` + type Query { + test: BadUnion + } + + type TypeA { + field: String + } + + type TypeB { + field: String + } + + union BadUnion = + | TypeA + | String + | TypeB + `); + + const badUnionNode = (schema.getType('BadUnion') as GraphQLUnionType) + ?.astNode; + assert(badUnionNode); + /* @ts-expect-error */ + badUnionNode.types = undefined; + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + 'Union type BadUnion can only include Object types, it cannot include String.', + }, + ]); + }); }); describe('Type System: Input Objects must have fields', () => { @@ -872,7 +924,7 @@ describe('Type System: Input Objects must have fields', () => { expectJSON(validateSchema(schema)).toDeepEqual([ { message: - 'Cannot reference Input Object "SomeInputObject" within itself through a series of non-null fields: "nonNullSelf".', + 'Invalid circular reference. The Input Object SomeInputObject references itself in the non-null field SomeInputObject.nonNullSelf.', locations: [{ line: 7, column: 9 }], }, ]); @@ -900,7 +952,7 @@ describe('Type System: Input Objects must have fields', () => { expectJSON(validateSchema(schema)).toDeepEqual([ { message: - 'Cannot reference Input Object "SomeInputObject" within itself through a series of non-null fields: "startLoop.nextInLoop.closeLoop".', + 'Invalid circular reference. The Input Object SomeInputObject references itself via the non-null fields: SomeInputObject.startLoop, AnotherInputObject.nextInLoop, YetAnotherInputObject.closeLoop.', locations: [ { line: 7, column: 9 }, { line: 11, column: 9 }, @@ -934,7 +986,7 @@ describe('Type System: Input Objects must have fields', () => { expectJSON(validateSchema(schema)).toDeepEqual([ { message: - 'Cannot reference Input Object "SomeInputObject" within itself through a series of non-null fields: "startLoop.closeLoop".', + 'Invalid circular reference. The Input Object SomeInputObject references itself via the non-null fields: SomeInputObject.startLoop, AnotherInputObject.closeLoop.', locations: [ { line: 7, column: 9 }, { line: 11, column: 9 }, @@ -942,7 +994,7 @@ describe('Type System: Input Objects must have fields', () => { }, { message: - 'Cannot reference Input Object "AnotherInputObject" within itself through a series of non-null fields: "startSecondLoop.closeSecondLoop".', + 'Invalid circular reference. The Input Object AnotherInputObject references itself via the non-null fields: AnotherInputObject.startSecondLoop, YetAnotherInputObject.closeSecondLoop.', locations: [ { line: 12, column: 9 }, { line: 16, column: 9 }, @@ -950,12 +1002,294 @@ describe('Type System: Input Objects must have fields', () => { }, { message: - 'Cannot reference Input Object "YetAnotherInputObject" within itself through a series of non-null fields: "nonNullSelf".', + 'Invalid circular reference. The Input Object YetAnotherInputObject references itself in the non-null field YetAnotherInputObject.nonNullSelf.', locations: [{ line: 17, column: 9 }], }, ]); }); + it('accepts Input Objects with default values without circular references (SDL)', () => { + const validSchema = buildSchema(` + type Query { + field(arg1: A, arg2: B): String + } + + input A { + x: A = null + y: A = { x: null, y: null } + z: [A] = [] + } + + input B { + x: B2! = {} + y: String = "abc" + z: Custom = {} + } + + input B2 { + x: B3 = {} + } + + input B3 { + x: B = { x: { x: null } } + } + + scalar Custom + `); + + expect(validateSchema(validSchema)).to.deep.equal([]); + }); + + it('accepts Input Objects with default values without circular references (programmatic)', () => { + const AType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'A', + fields: () => ({ + x: { type: AType, default: { value: null } }, + y: { type: AType, default: { value: { x: null, y: null } } }, + z: { type: new GraphQLList(AType), default: { value: [] } }, + }), + }); + + const BType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'B', + fields: () => ({ + x: { type: new GraphQLNonNull(B2Type), default: { value: {} } }, + y: { type: GraphQLString, default: { value: 'abc' } }, + z: { type: CustomType, default: { value: {} } }, + }), + }); + + const B2Type: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'B2', + fields: () => ({ + x: { type: B3Type, default: { value: {} } }, + }), + }); + + const B3Type: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'B3', + fields: () => ({ + x: { type: BType, default: { value: { x: { x: null } } } }, + }), + }); + + const CustomType = new GraphQLScalarType({ name: 'Custom' }); + + const validSchema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + field: { + type: GraphQLString, + args: { + arg1: { type: AType }, + arg2: { type: BType }, + }, + }, + }, + }), + }); + + expect(validateSchema(validSchema)).to.deep.equal([]); + }); + + it('rejects Input Objects with default value circular reference (SDL)', () => { + const invalidSchema = buildSchema(` + type Query { + field(arg1: A, arg2: B, arg3: C, arg4: D, arg5: E): String + } + + input A { + x: A = {} + } + + input B { + x: B2 = {} + } + + input B2 { + x: B3 = {} + } + + input B3 { + x: B = {} + } + + input C { + x: [C] = [{}] + } + + input D { + x: D = { x: { x: {} } } + } + + input E { + x: E = { x: null } + y: E = { y: null } + } + + input F { + x: F2! = {} + } + + input F2 { + x: F = { x: {} } + } + `); + + expectJSON(validateSchema(invalidSchema)).toDeepEqual([ + { + message: + 'Invalid circular reference. The default value of Input Object field A.x references itself.', + locations: [{ line: 7, column: 16 }], + }, + { + message: + 'Invalid circular reference. The default value of Input Object field B.x references itself via the default values of: B2.x, B3.x.', + locations: [ + { line: 11, column: 17 }, + { line: 15, column: 17 }, + { line: 19, column: 16 }, + ], + }, + { + message: + 'Invalid circular reference. The default value of Input Object field C.x references itself.', + locations: [{ line: 23, column: 18 }], + }, + { + message: + 'Invalid circular reference. The default value of Input Object field D.x references itself.', + locations: [{ line: 27, column: 16 }], + }, + { + message: + 'Invalid circular reference. The default value of Input Object field E.x references itself via the default values of: E.y.', + locations: [ + { line: 31, column: 16 }, + { line: 32, column: 16 }, + ], + }, + { + message: + 'Invalid circular reference. The default value of Input Object field F2.x references itself.', + locations: [{ line: 40, column: 16 }], + }, + ]); + }); + + it('rejects Input Objects with default value circular reference (programmatic)', () => { + const AType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'A', + fields: () => ({ + x: { type: AType, default: { value: {} } }, + }), + }); + + const BType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'B', + fields: () => ({ + x: { type: B2Type, default: { value: {} } }, + }), + }); + + const B2Type: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'B2', + fields: () => ({ + x: { type: B3Type, default: { value: {} } }, + }), + }); + + const B3Type: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'B3', + fields: () => ({ + x: { type: BType, default: { value: {} } }, + }), + }); + + const CType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'C', + fields: () => ({ + x: { type: new GraphQLList(CType), default: { value: [{}] } }, + }), + }); + + const DType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'D', + fields: () => ({ + x: { type: DType, default: { value: { x: { x: {} } } } }, + }), + }); + + const EType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'E', + fields: () => ({ + x: { type: EType, default: { value: { x: null } } }, + y: { type: EType, default: { value: { y: null } } }, + }), + }); + + const FType: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'F', + fields: () => ({ + x: { type: new GraphQLNonNull(F2Type), default: { value: {} } }, + }), + }); + + const F2Type: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'F2', + fields: () => ({ + x: { type: FType, default: { value: { x: {} } } }, + }), + }); + + const invalidSchema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + field: { + type: GraphQLString, + args: { + arg1: { type: AType }, + arg2: { type: BType }, + arg3: { type: CType }, + arg4: { type: DType }, + arg5: { type: EType }, + arg6: { type: FType }, + }, + }, + }, + }), + }); + + expectJSON(validateSchema(invalidSchema)).toDeepEqual([ + { + message: + 'Invalid circular reference. The default value of Input Object field A.x references itself.', + }, + { + message: + 'Invalid circular reference. The default value of Input Object field B.x references itself via the default values of: B2.x, B3.x.', + }, + { + message: + 'Invalid circular reference. The default value of Input Object field C.x references itself.', + }, + { + message: + 'Invalid circular reference. The default value of Input Object field D.x references itself.', + }, + { + message: + 'Invalid circular reference. The default value of Input Object field E.x references itself via the default values of: E.y.', + }, + { + message: + 'Invalid circular reference. The default value of Input Object field F2.x references itself.', + }, + ]); + }); + it('rejects an Input Object type with incorrectly typed fields', () => { const schema = buildSchema(` type Query { @@ -988,7 +1322,7 @@ describe('Type System: Input Objects must have fields', () => { ]); }); - it('rejects an Input Object type with required argument that is deprecated', () => { + it('rejects an Input Object type with required field that is deprecated', () => { const schema = buildSchema(` type Query { field(arg: SomeInputObject): String @@ -1192,6 +1526,35 @@ describe('Type System: Objects can only implement unique interfaces', () => { ]); }); + it('rejects an Object implementing a non-Interface type with malformed AST', () => { + const schema = buildSchema(` + type Query { + test: BadObject + } + + input SomeInputObject { + field: String + } + + type BadObject implements SomeInputObject { + field: String + } + `); + + const badObjectNode = (schema.getType('BadObject') as GraphQLObjectType) + ?.astNode; + assert(badObjectNode); + /* @ts-expect-error */ + badObjectNode.interfaces = undefined; + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + 'Type BadObject must only implement Interface types, it cannot implement SomeInputObject.', + }, + ]); + }); + it('rejects an Object implementing the same interface twice', () => { const schema = buildSchema(` type Query { @@ -1653,6 +2016,207 @@ describe('Type System: Arguments must have input types', () => { }); }); +describe('Type System: Argument default values must be valid', () => { + it('rejects an argument with invalid default values (SDL)', () => { + const schema = buildSchema(` + type Query { + field(arg: Int = 3.14): Int + } + + directive @bad(arg: Int = 2.718) on FIELD + `); + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + '@bad(arg:) has invalid default value: Int cannot represent non-integer value: 2.718', + locations: [{ line: 6, column: 33 }], + }, + { + message: + 'Query.field(arg:) has invalid default value: Int cannot represent non-integer value: 3.14', + locations: [{ line: 3, column: 26 }], + }, + ]); + }); + + it('rejects an argument with invalid default values (programmatic)', () => { + const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + field: { + type: GraphQLInt, + args: { + arg: { type: GraphQLInt, default: { value: 3.14 } }, + }, + }, + }, + }), + directives: [ + new GraphQLDirective({ + name: 'bad', + args: { + arg: { type: GraphQLInt, default: { value: 2.718 } }, + }, + locations: [DirectiveLocation.FIELD], + }), + ], + }); + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + '@bad(arg:) has invalid default value: Int cannot represent non-integer value: 2.718', + }, + { + message: + 'Query.field(arg:) has invalid default value: Int cannot represent non-integer value: 3.14', + }, + ]); + }); + + it('Attempts to offer a suggested fix if possible (programmatic)', () => { + const Exotic = Symbol('Exotic'); + + const testEnum = new GraphQLEnumType({ + name: 'TestEnum', + values: { + ONE: { value: 1 }, + TWO: { value: Exotic }, + }, + }); + + const testInput: GraphQLInputObjectType = new GraphQLInputObjectType({ + name: 'TestInput', + fields: () => ({ + self: { type: testInput }, + string: { type: new GraphQLNonNull(new GraphQLList(GraphQLString)) }, + enum: { type: new GraphQLList(testEnum) }, + }), + }); + + const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + field: { + type: GraphQLInt, + args: { + argWithPossibleFix: { + type: testInput, + default: { value: { self: null, string: [1], enum: Exotic } }, + }, + argWithInvalidPossibleFix: { + type: testInput, + default: { value: { string: null } }, + }, + argWithoutPossibleFix: { + type: testInput, + default: { value: { enum: 'Exotic' } }, + }, + }, + }, + }, + }), + }); + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + 'Query.field(argWithPossibleFix:) has invalid default value: { self: null, string: [1], enum: Symbol(Exotic) }. Did you mean: { self: null, string: ["1"], enum: ["TWO"] }?', + }, + { + message: + 'Query.field(argWithInvalidPossibleFix:) has invalid default value at .string: Expected value of non-null type "[String]!" not to be null.', + }, + { + message: + 'Query.field(argWithoutPossibleFix:) has invalid default value: Expected value of type "TestInput" to include required field "string", found: { enum: "Exotic" }.', + }, + { + message: + 'Query.field(argWithoutPossibleFix:) has invalid default value at .enum: Value "Exotic" does not exist in "TestEnum" enum.', + }, + ]); + }); + + it('Attempts to offer a suggested fix if possible (SDL)', () => { + const originalSchema = buildSchema(` + enum TestEnum { + ONE + TWO + } + + input TestInput { + self: TestInput + string: [String]! + enum: [TestEnum] + } + + type Query { + field( + argWithPossibleFix: TestInput + argWithInvalidPossibleFix: TestInput + argWithoutPossibleFix: TestInput + ): Int + } + `); + + const Exotic = Symbol('Exotic'); + + // workaround as we cannot inject custom internal values into enums defined in SDL + const testEnum = new GraphQLEnumType({ + name: 'TestEnum', + values: { + ONE: { value: 1 }, + TWO: { value: Exotic }, + }, + }); + + const testInput = assertInputObjectType( + originalSchema.getType('TestInput'), + ); + testInput.getFields().enum.type = new GraphQLList(testEnum); + + // workaround as we cannot inject exotic default values into arguments defined in SDL + const QueryType = assertObjectType(originalSchema.getType('Query')); + for (const arg of QueryType.getFields().field.args) { + arg.type = testInput; + switch (arg.name) { + case 'argWithPossibleFix': + arg.default = { value: { self: null, string: [1], enum: Exotic } }; + break; + case 'argWithInvalidPossibleFix': + arg.default = { value: { string: null } }; + break; + case 'argWithoutPossibleFix': + arg.default = { value: { enum: 'Exotic' } }; + break; + } + } + + expectJSON(validateSchema(originalSchema)).toDeepEqual([ + { + message: + 'Query.field(argWithPossibleFix:) has invalid default value: { self: null, string: [1], enum: Symbol(Exotic) }. Did you mean: { self: null, string: ["1"], enum: ["TWO"] }?', + }, + { + message: + 'Query.field(argWithInvalidPossibleFix:) has invalid default value at .string: Expected value of non-null type "[String]!" not to be null.', + }, + { + message: + 'Query.field(argWithoutPossibleFix:) has invalid default value: Expected value of type "TestInput" to include required field "string", found: { enum: "Exotic" }.', + }, + { + message: + 'Query.field(argWithoutPossibleFix:) has invalid default value at .enum: Value "Exotic" does not exist in "TestEnum" enum.', + }, + ]); + }); +}); + describe('Type System: Input Object fields must have input types', () => { function schemaWithInputField( inputFieldConfig: GraphQLInputFieldConfig, @@ -1749,6 +2313,61 @@ describe('Type System: Input Object fields must have input types', () => { }); }); +describe('Type System: Input Object field default values must be valid', () => { + it('rejects an Input Object field with invalid default values (SDL)', () => { + const schema = buildSchema(` + type Query { + field(arg: SomeInputObject): Int + } + + input SomeInputObject { + field: Int = 3.14 + } + `); + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + 'SomeInputObject.field has invalid default value: Int cannot represent non-integer value: 3.14', + locations: [{ line: 7, column: 20 }], + }, + ]); + }); + + it('rejects an Input Object field with invalid default values (programmatic)', () => { + const someInputObject = new GraphQLInputObjectType({ + name: 'SomeInputObject', + fields: { + field: { + type: GraphQLInt, + default: { value: 3.14 }, + }, + }, + }); + + const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + field: { + type: GraphQLInt, + args: { + arg: { type: someInputObject }, + }, + }, + }, + }), + }); + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + 'SomeInputObject.field has invalid default value: Int cannot represent non-integer value: 3.14', + }, + ]); + }); +}); + describe('Type System: OneOf Input Object fields must be nullable', () => { it('rejects non-nullable fields', () => { const schema = buildSchema(` @@ -2072,7 +2691,7 @@ describe('Objects must adhere to Interface they implement', () => { expectJSON(validateSchema(schema)).toDeepEqual([ { message: - 'Object field AnotherObject.field includes required argument requiredArg that is missing from the Interface field AnotherInterface.field.', + 'Argument "AnotherObject.field(requiredArg:)" must not be required type "String!" if not provided by the Interface field "AnotherInterface.field".', locations: [ { line: 13, column: 11 }, { line: 7, column: 9 }, @@ -2529,7 +3148,7 @@ describe('Interfaces must adhere to Interface they implement', () => { expectJSON(validateSchema(schema)).toDeepEqual([ { message: - 'Object field ChildInterface.field includes required argument requiredArg that is missing from the Interface field ParentInterface.field.', + 'Argument "ChildInterface.field(requiredArg:)" must not be required type "String!" if not provided by the Interface field "ParentInterface.field".', locations: [ { line: 13, column: 11 }, { line: 7, column: 9 }, diff --git a/src/type/definition.ts b/src/type/definition.ts index 0ca4152bd2..ea96be5153 100644 --- a/src/type/definition.ts +++ b/src/type/definition.ts @@ -11,11 +11,12 @@ import type { ObjMap } from '../jsutils/ObjMap.js'; import type { Path } from '../jsutils/Path.js'; import type { PromiseOrValue } from '../jsutils/PromiseOrValue.js'; import { suggestionList } from '../jsutils/suggestionList.js'; -import { toObjMap } from '../jsutils/toObjMap.js'; +import { toObjMapWithSymbols } from '../jsutils/toObjMap.js'; import { GraphQLError } from '../error/GraphQLError.js'; import type { + ConstValueNode, EnumTypeDefinitionNode, EnumTypeExtensionNode, EnumValueDefinitionNode, @@ -39,9 +40,13 @@ import type { import { Kind } from '../language/kinds.js'; import { print } from '../language/printer.js'; +import type { GraphQLVariableSignature } from '../execution/getVariableSignature.js'; +import type { VariableValues } from '../execution/values.js'; + import { valueFromASTUntyped } from '../utilities/valueFromASTUntyped.js'; import { assertEnumValueName, assertName } from './assertName.js'; +import type { GraphQLDirective } from './directives.js'; import type { GraphQLSchema } from './schema.js'; // Predicates & Assertions @@ -72,7 +77,7 @@ export function assertType(type: unknown): GraphQLType { } /** - * There are predicates for each kind of GraphQL type. + * There are predicates for each GraphQL schema element. */ export function isScalarType(type: unknown): type is GraphQLScalarType { return instanceOf(type, GraphQLScalarType); @@ -96,6 +101,28 @@ export function assertObjectType(type: unknown): GraphQLObjectType { return type; } +export function isField(field: unknown): field is GraphQLField { + return instanceOf(field, GraphQLField); +} + +export function assertField(field: unknown): GraphQLField { + if (!isField(field)) { + throw new Error(`Expected ${inspect(field)} to be a GraphQL field.`); + } + return field; +} + +export function isArgument(arg: unknown): arg is GraphQLArgument { + return instanceOf(arg, GraphQLArgument); +} + +export function assertArgument(arg: unknown): GraphQLArgument { + if (!isArgument(arg)) { + throw new Error(`Expected ${inspect(arg)} to be a GraphQL argument.`); + } + return arg; +} + export function isInterfaceType(type: unknown): type is GraphQLInterfaceType { return instanceOf(type, GraphQLInterfaceType); } @@ -131,6 +158,17 @@ export function assertEnumType(type: unknown): GraphQLEnumType { return type; } +export function isEnumValue(value: unknown): value is GraphQLEnumValue { + return instanceOf(value, GraphQLEnumValue); +} + +export function assertEnumValue(value: unknown): GraphQLEnumValue { + if (!isEnumValue(value)) { + throw new Error(`Expected ${inspect(value)} to be a GraphQL Enum value.`); + } + return value; +} + export function isInputObjectType( type: unknown, ): type is GraphQLInputObjectType { @@ -146,6 +184,17 @@ export function assertInputObjectType(type: unknown): GraphQLInputObjectType { return type; } +export function isInputField(field: unknown): field is GraphQLInputField { + return instanceOf(field, GraphQLInputField); +} + +export function assertInputField(field: unknown): GraphQLInputField { + if (!isInputField(field)) { + throw new Error(`Expected ${inspect(field)} to be a GraphQL input field.`); + } + return field; +} + export function isListType( type: GraphQLInputType, ): type is GraphQLList; @@ -316,7 +365,9 @@ export function assertAbstractType(type: unknown): GraphQLAbstractType { * }) * ``` */ -export class GraphQLList { +export class GraphQLList + implements GraphQLSchemaElement +{ readonly ofType: T; constructor(ofType: T) { @@ -357,7 +408,9 @@ export class GraphQLList { * ``` * Note: the enforcement of non-nullability occurs within the executor. */ -export class GraphQLNonNull { +export class GraphQLNonNull + implements GraphQLSchemaElement +{ readonly ofType: T; constructor(ofType: T) { @@ -481,6 +534,15 @@ export function getNamedType( } } +/** + * An interface for all Schema Elements. + */ + +export interface GraphQLSchemaElement { + toString: () => string; + toJSON: () => string; +} + /** * Used while defining GraphQL types to allow for circular references in * otherwise immutable type definitions. @@ -508,7 +570,7 @@ export function resolveObjMapThunk(thunk: ThunkObjMap): ObjMap { * an object which can contain all the values you need. */ export interface GraphQLScalarTypeExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** @@ -518,56 +580,115 @@ export interface GraphQLScalarTypeExtensions { * Scalars (or Enums) and are defined with a name and a series of functions * used to parse input from ast or variables and to ensure validity. * - * If a type's serialize function returns `null` or does not return a value - * (i.e. it returns `undefined`) then an error will be raised and a `null` - * value will be returned in the response. It is always better to validate + * If a type's coerceOutputValue function returns `null` or does not return a + * value (i.e. it returns `undefined`) then an error will be raised and a + * `null` value will be returned in the response. It is always better to + * validate. * * Example: * * ```ts + * function ensureOdd(value) { + * if (!Number.isFinite(value)) { + * throw new Error( + * `Scalar "Odd" cannot represent "${value}" since it is not a finite number.`, + * ); + * } + * + * if (value % 2 === 0) { + * throw new Error(`Scalar "Odd" cannot represent "${value}" since it is even.`); + * } + * } + * * const OddType = new GraphQLScalarType({ * name: 'Odd', - * serialize(value) { - * if (!Number.isFinite(value)) { - * throw new Error( - * `Scalar "Odd" cannot represent "${value}" since it is not a finite number.`, - * ); - * } - * - * if (value % 2 === 0) { - * throw new Error(`Scalar "Odd" cannot represent "${value}" since it is even.`); - * } - * return value; + * coerceOutputValue(value) { + * return ensureOdd(value); + * }, + * coerceInputValue(value) { + * return ensureOdd(value); + * } + * valueToLiteral(value) { + * return parse(`${ensureOdd(value)`); * } * }); * ``` + * + * Custom scalars behavior is defined via the following functions: + * + * - coerceOutputValue(value): Implements "Result Coercion". Given an internal value, + * produces an external value valid for this type. Returns undefined or + * throws an error to indicate invalid values. + * + * - coerceInputValue(value): Implements "Input Coercion" for values. Given an + * external value (for example, variable values), produces an internal value + * valid for this type. Returns undefined or throws an error to indicate + * invalid values. + * + * - coerceInputLiteral(ast): Implements "Input Coercion" for constant literals. + * Given an GraphQL literal (AST) (for example, an argument value), produces + * an internal value valid for this type. Returns undefined or throws an + * error to indicate invalid values. + * + * - valueToLiteral(value): Converts an external value to a GraphQL + * literal (AST). Returns undefined or throws an error to indicate + * invalid values. + * + * Deprecated, to be removed in v18: + * + * - serialize(value): Implements "Result Coercion". Renamed to + * `coerceOutputValue()`. + * + * - parseValue(value): Implements "Input Coercion" for values. Renamed to + * `coerceInputValue()`. + * + * - parseLiteral(ast): Implements "Input Coercion" for literals including + * non-specified replacement of variables embedded within complex scalars. + * Replaced by the combination of the `replaceVariables()` utility and the + * `coerceInputLiteral()` method. + * */ -export class GraphQLScalarType { +export class GraphQLScalarType + implements GraphQLSchemaElement +{ name: string; description: Maybe; specifiedByURL: Maybe; + /** @deprecated use `coerceOutputValue()` instead, `serialize()` will be removed in v18 */ serialize: GraphQLScalarSerializer; + /** @deprecated use `coerceInputValue()` instead, `parseValue()` will be removed in v18 */ parseValue: GraphQLScalarValueParser; + /** @deprecated use `replaceVariables()` and `coerceInputLiteral()` instead, `parseLiteral()` will be removed in v18 */ parseLiteral: GraphQLScalarLiteralParser; + coerceOutputValue: GraphQLScalarOutputValueCoercer; + coerceInputValue: GraphQLScalarInputValueCoercer; + coerceInputLiteral: GraphQLScalarInputLiteralCoercer | undefined; + valueToLiteral: GraphQLScalarValueToLiteral | undefined; extensions: Readonly; astNode: Maybe; extensionASTNodes: ReadonlyArray; constructor(config: Readonly>) { - const parseValue = - config.parseValue ?? - (identityFunc as GraphQLScalarValueParser); - this.name = assertName(config.name); this.description = config.description; this.specifiedByURL = config.specifiedByURL; this.serialize = - config.serialize ?? (identityFunc as GraphQLScalarSerializer); - this.parseValue = parseValue; + config.serialize ?? + config.coerceOutputValue ?? + (identityFunc as GraphQLScalarSerializer); + this.parseValue = + config.parseValue ?? + config.coerceInputValue ?? + (identityFunc as GraphQLScalarValueParser); this.parseLiteral = config.parseLiteral ?? - ((node, variables) => parseValue(valueFromASTUntyped(node, variables))); - this.extensions = toObjMap(config.extensions); + ((node, variables) => + this.coerceInputValue(valueFromASTUntyped(node, variables))); + this.coerceOutputValue = config.coerceOutputValue ?? this.serialize; + this.coerceInputValue = config.coerceInputValue ?? this.parseValue; + this.coerceInputLiteral = config.coerceInputLiteral; + this.valueToLiteral = config.valueToLiteral; + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; @@ -578,6 +699,14 @@ export class GraphQLScalarType { `${this.name} must provide both "parseValue" and "parseLiteral" functions.`, ); } + + if (config.coerceInputLiteral) { + devAssert( + typeof config.coerceInputValue === 'function' && + typeof config.coerceInputLiteral === 'function', + `${this.name} must provide both "coerceInputValue" and "coerceInputLiteral" functions.`, + ); + } } get [Symbol.toStringTag]() { @@ -592,6 +721,10 @@ export class GraphQLScalarType { serialize: this.serialize, parseValue: this.parseValue, parseLiteral: this.parseLiteral, + coerceOutputValue: this.coerceOutputValue, + coerceInputValue: this.coerceInputValue, + coerceInputLiteral: this.coerceInputLiteral, + valueToLiteral: this.valueToLiteral, extensions: this.extensions, astNode: this.astNode, extensionASTNodes: this.extensionASTNodes, @@ -607,39 +740,72 @@ export class GraphQLScalarType { } } +/* @deprecated in favor of GraphQLScalarOutputValueCoercer, will be removed in v18 */ export type GraphQLScalarSerializer = ( outputValue: unknown, ) => TExternal; +export type GraphQLScalarOutputValueCoercer = ( + outputValue: unknown, +) => TExternal; + +/* @deprecated in favor of GraphQLScalarInputValueCoercer, will be removed in v18 */ export type GraphQLScalarValueParser = ( inputValue: unknown, ) => TInternal; +export type GraphQLScalarInputValueCoercer = ( + inputValue: unknown, +) => TInternal; + +/* @deprecated in favor of GraphQLScalarInputLiteralCoercer, will be removed in v18 */ export type GraphQLScalarLiteralParser = ( valueNode: ValueNode, - variables?: Maybe>, -) => TInternal; + variables: Maybe>, +) => Maybe; + +export type GraphQLScalarInputLiteralCoercer = ( + valueNode: ConstValueNode, +) => Maybe; + +export type GraphQLScalarValueToLiteral = ( + inputValue: unknown, +) => ConstValueNode | undefined; export interface GraphQLScalarTypeConfig { name: string; description?: Maybe; specifiedByURL?: Maybe; /** Serializes an internal value to include in a response. */ + /** @deprecated use `coerceOutputValue()` instead, `serialize()` will be removed in v18 */ serialize?: GraphQLScalarSerializer | undefined; /** Parses an externally provided value to use as an input. */ + /** @deprecated use `coerceInputValue()` instead, `parseValue()` will be removed in v18 */ parseValue?: GraphQLScalarValueParser | undefined; /** Parses an externally provided literal value to use as an input. */ + /** @deprecated use `replaceVariables()` and `coerceInputLiteral()` instead, `parseLiteral()` will be removed in v18 */ parseLiteral?: GraphQLScalarLiteralParser | undefined; + /** Coerces an internal value to include in a response. */ + coerceOutputValue?: GraphQLScalarOutputValueCoercer | undefined; + /** Coerces an externally provided value to use as an input. */ + coerceInputValue?: GraphQLScalarInputValueCoercer | undefined; + /** Coerces an externally provided const literal value to use as an input. */ + coerceInputLiteral?: GraphQLScalarInputLiteralCoercer | undefined; + /** Translates an externally provided value to a literal (AST). */ + valueToLiteral?: GraphQLScalarValueToLiteral | undefined; extensions?: Maybe>; astNode?: Maybe; extensionASTNodes?: Maybe>; } -interface GraphQLScalarTypeNormalizedConfig +export interface GraphQLScalarTypeNormalizedConfig extends GraphQLScalarTypeConfig { serialize: GraphQLScalarSerializer; parseValue: GraphQLScalarValueParser; parseLiteral: GraphQLScalarLiteralParser; + coerceOutputValue: GraphQLScalarOutputValueCoercer; + coerceInputValue: GraphQLScalarInputValueCoercer; + coerceInputLiteral: GraphQLScalarInputLiteralCoercer | undefined; extensions: Readonly; extensionASTNodes: ReadonlyArray; } @@ -657,7 +823,7 @@ interface GraphQLScalarTypeNormalizedConfig * you may find them useful. */ export interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** @@ -700,7 +866,9 @@ export interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { * }); * ``` */ -export class GraphQLObjectType { +export class GraphQLObjectType + implements GraphQLSchemaElement +{ name: string; description: Maybe; isTypeOf: Maybe>; @@ -715,13 +883,14 @@ export class GraphQLObjectType { this.name = assertName(config.name); this.description = config.description; this.isTypeOf = config.isTypeOf; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; - - // prettier-ignore - // FIXME: blocked by https://github.com/prettier/prettier/issues/14625 - this._fields = (defineFieldMap).bind(undefined, config.fields); + this._fields = (defineFieldMap).bind( + undefined, + this, + config.fields, + ); this._interfaces = defineInterfaces.bind(undefined, config.interfaces); } @@ -748,7 +917,7 @@ export class GraphQLObjectType { name: this.name, description: this.description, interfaces: this.getInterfaces(), - fields: fieldsToFieldsConfig(this.getFields()), + fields: mapValue(this.getFields(), (field) => field.toConfig()), isTypeOf: this.isTypeOf, extensions: this.extensions, astNode: this.astNode, @@ -772,72 +941,17 @@ function defineInterfaces( } function defineFieldMap( + parentType: + | GraphQLObjectType + | GraphQLInterfaceType, fields: ThunkObjMap>, ): GraphQLFieldMap { const fieldMap = resolveObjMapThunk(fields); - return mapValue(fieldMap, (fieldConfig, fieldName) => { - const argsConfig = fieldConfig.args ?? {}; - return { - name: assertName(fieldName), - description: fieldConfig.description, - type: fieldConfig.type, - args: defineArguments(argsConfig), - resolve: fieldConfig.resolve, - subscribe: fieldConfig.subscribe, - deprecationReason: fieldConfig.deprecationReason, - extensions: toObjMap(fieldConfig.extensions), - astNode: fieldConfig.astNode, - }; - }); -} - -export function defineArguments( - args: GraphQLFieldConfigArgumentMap, -): ReadonlyArray { - return Object.entries(args).map(([argName, argConfig]) => ({ - name: assertName(argName), - description: argConfig.description, - type: argConfig.type, - defaultValue: argConfig.defaultValue, - deprecationReason: argConfig.deprecationReason, - extensions: toObjMap(argConfig.extensions), - astNode: argConfig.astNode, - })); -} - -function fieldsToFieldsConfig( - fields: GraphQLFieldMap, -): GraphQLFieldConfigMap { - return mapValue(fields, (field) => ({ - description: field.description, - type: field.type, - args: argsToArgsConfig(field.args), - resolve: field.resolve, - subscribe: field.subscribe, - deprecationReason: field.deprecationReason, - extensions: field.extensions, - astNode: field.astNode, - })); -} - -/** - * @internal - */ -export function argsToArgsConfig( - args: ReadonlyArray, -): GraphQLFieldConfigArgumentMap { - return keyValMap( - args, - (arg) => arg.name, - (arg) => ({ - description: arg.description, - type: arg.type, - defaultValue: arg.defaultValue, - deprecationReason: arg.deprecationReason, - extensions: arg.extensions, - astNode: arg.astNode, - }), + return mapValue( + fieldMap, + (fieldConfig, fieldName) => + new GraphQLField(parentType, fieldName, fieldConfig), ); } @@ -852,10 +966,10 @@ export interface GraphQLObjectTypeConfig { extensionASTNodes?: Maybe>; } -interface GraphQLObjectTypeNormalizedConfig +export interface GraphQLObjectTypeNormalizedConfig extends GraphQLObjectTypeConfig { interfaces: ReadonlyArray; - fields: GraphQLFieldConfigMap; + fields: GraphQLFieldNormalizedConfigMap; extensions: Readonly>; extensionASTNodes: ReadonlyArray; } @@ -883,6 +997,7 @@ export type GraphQLFieldResolver< args: TArgs, context: TContext, info: GraphQLResolveInfo, + abortSignal: AbortSignal | undefined, ) => TResult; export interface GraphQLResolveInfo { @@ -895,7 +1010,7 @@ export interface GraphQLResolveInfo { readonly fragments: ObjMap; readonly rootValue: unknown; readonly operation: OperationDefinitionNode; - readonly variableValues: { [variable: string]: unknown }; + readonly variableValues: VariableValues; } /** @@ -911,7 +1026,7 @@ export interface GraphQLResolveInfo { * you may find them useful. */ export interface GraphQLFieldExtensions<_TSource, _TContext, _TArgs = any> { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } export interface GraphQLFieldConfig { @@ -927,8 +1042,17 @@ export interface GraphQLFieldConfig { astNode?: Maybe; } +export interface GraphQLFieldNormalizedConfig + extends GraphQLFieldConfig { + args: GraphQLFieldNormalizedConfigArgumentMap; + extensions: Readonly>; +} + export type GraphQLFieldConfigArgumentMap = ObjMap; +export type GraphQLFieldNormalizedConfigArgumentMap = + ObjMap; + /** * Custom extensions * @@ -939,23 +1063,40 @@ export type GraphQLFieldConfigArgumentMap = ObjMap; * an object which can contain all the values you need. */ export interface GraphQLArgumentExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } export interface GraphQLArgumentConfig { description?: Maybe; type: GraphQLInputType; + /** @deprecated use default instead, defaultValue will be removed in v18 **/ defaultValue?: unknown; + default?: GraphQLDefaultInput | undefined; deprecationReason?: Maybe; extensions?: Maybe>; astNode?: Maybe; } +export interface GraphQLArgumentNormalizedConfig extends GraphQLArgumentConfig { + default: GraphQLDefaultInput | undefined; + extensions: Readonly; +} + export type GraphQLFieldConfigMap = ObjMap< GraphQLFieldConfig >; -export interface GraphQLField { +export type GraphQLFieldNormalizedConfigMap = ObjMap< + GraphQLFieldNormalizedConfig +>; + +export class GraphQLField + implements GraphQLSchemaElement +{ + parentType: + | GraphQLObjectType + | GraphQLInterfaceType + | undefined; name: string; description: Maybe; type: GraphQLOutputType; @@ -965,26 +1106,135 @@ export interface GraphQLField { deprecationReason: Maybe; extensions: Readonly>; astNode: Maybe; + + constructor( + parentType: + | GraphQLObjectType + | GraphQLInterfaceType + | undefined, + name: string, + config: GraphQLFieldConfig, + ) { + this.parentType = parentType; + this.name = assertName(name); + this.description = config.description; + this.type = config.type; + + const argsConfig = config.args; + this.args = argsConfig + ? Object.entries(argsConfig).map( + ([argName, argConfig]) => + new GraphQLArgument(this, argName, argConfig), + ) + : []; + + this.resolve = config.resolve; + this.subscribe = config.subscribe; + this.deprecationReason = config.deprecationReason; + this.extensions = toObjMapWithSymbols(config.extensions); + this.astNode = config.astNode; + } + + get [Symbol.toStringTag]() { + return 'GraphQLField'; + } + + toConfig(): GraphQLFieldNormalizedConfig { + return { + description: this.description, + type: this.type, + args: keyValMap( + this.args, + (arg) => arg.name, + (arg) => arg.toConfig(), + ), + resolve: this.resolve, + subscribe: this.subscribe, + deprecationReason: this.deprecationReason, + extensions: this.extensions, + astNode: this.astNode, + }; + } + + toString(): string { + return `${this.parentType ?? ''}.${this.name}`; + } + + toJSON(): string { + return this.toString(); + } } -export interface GraphQLArgument { +export class GraphQLArgument implements GraphQLSchemaElement { + parent: GraphQLField | GraphQLDirective; name: string; description: Maybe; type: GraphQLInputType; defaultValue: unknown; + default: GraphQLDefaultInput | undefined; deprecationReason: Maybe; extensions: Readonly; astNode: Maybe; + + constructor( + parent: GraphQLField | GraphQLDirective, + name: string, + config: GraphQLArgumentConfig, + ) { + this.parent = parent; + this.name = assertName(name); + this.description = config.description; + this.type = config.type; + this.defaultValue = config.defaultValue; + this.default = config.default; + this.deprecationReason = config.deprecationReason; + this.extensions = toObjMapWithSymbols(config.extensions); + this.astNode = config.astNode; + } + + get [Symbol.toStringTag]() { + return 'GraphQLArgument'; + } + + toConfig(): GraphQLArgumentNormalizedConfig { + return { + description: this.description, + type: this.type, + defaultValue: this.defaultValue, + default: this.default, + deprecationReason: this.deprecationReason, + extensions: this.extensions, + astNode: this.astNode, + }; + } + + toString(): string { + return `${this.parent}(${this.name}:)`; + } + + toJSON(): string { + return this.toString(); + } } -export function isRequiredArgument(arg: GraphQLArgument): boolean { - return isNonNullType(arg.type) && arg.defaultValue === undefined; +export function isRequiredArgument( + arg: GraphQLArgument | GraphQLVariableSignature, +): boolean { + return ( + isNonNullType(arg.type) && + arg.default === undefined && + arg.defaultValue === undefined + ); } export type GraphQLFieldMap = ObjMap< GraphQLField >; +export type GraphQLDefaultInput = + | { value: unknown; literal?: never } + | { literal: ConstValueNode; value?: never }; + /** * Custom extensions * @@ -995,7 +1245,7 @@ export type GraphQLFieldMap = ObjMap< * an object which can contain all the values you need. */ export interface GraphQLInterfaceTypeExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** @@ -1017,7 +1267,9 @@ export interface GraphQLInterfaceTypeExtensions { * }); * ``` */ -export class GraphQLInterfaceType { +export class GraphQLInterfaceType + implements GraphQLSchemaElement +{ name: string; description: Maybe; resolveType: Maybe>; @@ -1032,13 +1284,14 @@ export class GraphQLInterfaceType { this.name = assertName(config.name); this.description = config.description; this.resolveType = config.resolveType; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; - - // prettier-ignore - // FIXME: blocked by https://github.com/prettier/prettier/issues/14625 - this._fields = (defineFieldMap).bind(undefined, config.fields); + this._fields = (defineFieldMap).bind( + undefined, + this, + config.fields, + ); this._interfaces = defineInterfaces.bind(undefined, config.interfaces); } @@ -1065,7 +1318,7 @@ export class GraphQLInterfaceType { name: this.name, description: this.description, interfaces: this.getInterfaces(), - fields: fieldsToFieldsConfig(this.getFields()), + fields: mapValue(this.getFields(), (field) => field.toConfig()), resolveType: this.resolveType, extensions: this.extensions, astNode: this.astNode, @@ -1101,7 +1354,7 @@ export interface GraphQLInterfaceTypeConfig { export interface GraphQLInterfaceTypeNormalizedConfig extends GraphQLInterfaceTypeConfig { interfaces: ReadonlyArray; - fields: GraphQLFieldConfigMap; + fields: GraphQLFieldNormalizedConfigMap; extensions: Readonly; extensionASTNodes: ReadonlyArray; } @@ -1116,7 +1369,7 @@ export interface GraphQLInterfaceTypeNormalizedConfig * an object which can contain all the values you need. */ export interface GraphQLUnionTypeExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** @@ -1143,7 +1396,7 @@ export interface GraphQLUnionTypeExtensions { * }); * ``` */ -export class GraphQLUnionType { +export class GraphQLUnionType implements GraphQLSchemaElement { name: string; description: Maybe; resolveType: Maybe>; @@ -1157,7 +1410,7 @@ export class GraphQLUnionType { this.name = assertName(config.name); this.description = config.description; this.resolveType = config.resolveType; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; @@ -1217,7 +1470,7 @@ export interface GraphQLUnionTypeConfig { extensionASTNodes?: Maybe>; } -interface GraphQLUnionTypeNormalizedConfig +export interface GraphQLUnionTypeNormalizedConfig extends GraphQLUnionTypeConfig { types: ReadonlyArray; extensions: Readonly; @@ -1234,13 +1487,13 @@ interface GraphQLUnionTypeNormalizedConfig * an object which can contain all the values you need. */ export interface GraphQLEnumTypeExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** * Enum Type Definition * - * Some leaf values of requests and input values are Enums. GraphQL serializes + * Some leaf values of requests and input values are Enums. GraphQL coerces * Enum values as strings, however internally Enums can be represented by any * kind of type, often integers. * @@ -1260,38 +1513,36 @@ export interface GraphQLEnumTypeExtensions { * Note: If a value is not provided in a definition, the name of the enum value * will be used as its internal value. */ -export class GraphQLEnumType /* */ { +export class GraphQLEnumType /* */ implements GraphQLSchemaElement { name: string; description: Maybe; extensions: Readonly; astNode: Maybe; extensionASTNodes: ReadonlyArray; - private _values: ReadonlyArray */>; - private _valueLookup: ReadonlyMap; - private _nameLookup: ObjMap; + private _values: + | ReadonlyArray */> + | (() => GraphQLEnumValueConfigMap); + + private _valueLookup: ReadonlyMap | null; + private _nameLookup: ObjMap | null; constructor(config: Readonly */>) { this.name = assertName(config.name); this.description = config.description; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; - this._values = Object.entries(config.values).map( - ([valueName, valueConfig]) => ({ - name: assertEnumValueName(valueName), - description: valueConfig.description, - value: valueConfig.value !== undefined ? valueConfig.value : valueName, - deprecationReason: valueConfig.deprecationReason, - extensions: toObjMap(valueConfig.extensions), - astNode: valueConfig.astNode, - }), - ); - this._valueLookup = new Map( - this._values.map((enumValue) => [enumValue.value, enumValue]), - ); - this._nameLookup = keyMap(this._values, (value) => value.name); + this._values = + typeof config.values === 'function' + ? config.values + : Object.entries(config.values).map( + ([valueName, valueConfig]) => + new GraphQLEnumValue(this, valueName, valueConfig), + ); + this._valueLookup = null; + this._nameLookup = null; } get [Symbol.toStringTag]() { @@ -1299,14 +1550,33 @@ export class GraphQLEnumType /* */ { } getValues(): ReadonlyArray */> { + if (typeof this._values === 'function') { + this._values = Object.entries(this._values()).map( + ([valueName, valueConfig]) => + new GraphQLEnumValue(this, valueName, valueConfig), + ); + } return this._values; } getValue(name: string): Maybe { + if (this._nameLookup === null) { + this._nameLookup = keyMap(this.getValues(), (value) => value.name); + } return this._nameLookup[name]; } + /** @deprecated use `coerceOutputValue()` instead, `serialize()` will be removed in v18 */ serialize(outputValue: unknown /* T */): Maybe { + return this.coerceOutputValue(outputValue); + } + + coerceOutputValue(outputValue: unknown /* T */): Maybe { + if (this._valueLookup === null) { + this._valueLookup = new Map( + this.getValues().map((enumValue) => [enumValue.value, enumValue]), + ); + } const enumValue = this._valueLookup.get(outputValue); if (enumValue === undefined) { throw new GraphQLError( @@ -1316,12 +1586,23 @@ export class GraphQLEnumType /* */ { return enumValue.name; } - parseValue(inputValue: unknown): Maybe /* T */ { + /** @deprecated use `coerceInputValue()` instead, `parseValue()` will be removed in v18 */ + parseValue( + inputValue: unknown, + hideSuggestions?: Maybe, + ): Maybe /* T */ { + return this.coerceInputValue(inputValue, hideSuggestions); + } + + coerceInputValue( + inputValue: unknown, + hideSuggestions?: Maybe, + ): Maybe /* T */ { if (typeof inputValue !== 'string') { const valueStr = inspect(inputValue); throw new GraphQLError( `Enum "${this.name}" cannot represent non-string value: ${valueStr}.` + - didYouMeanEnumValue(this, valueStr), + (hideSuggestions ? '' : didYouMeanEnumValue(this, valueStr)), ); } @@ -1329,22 +1610,34 @@ export class GraphQLEnumType /* */ { if (enumValue == null) { throw new GraphQLError( `Value "${inputValue}" does not exist in "${this.name}" enum.` + - didYouMeanEnumValue(this, inputValue), + (hideSuggestions ? '' : didYouMeanEnumValue(this, inputValue)), ); } return enumValue.value; } + /** @deprecated use `coerceInputLiteral()` instead, `parseLiteral()` will be removed in v18 */ parseLiteral( valueNode: ValueNode, _variables: Maybe>, + hideSuggestions?: Maybe, ): Maybe /* T */ { // Note: variables will be resolved to a value before calling this function. + return this.coerceInputLiteral( + valueNode as ConstValueNode, + hideSuggestions, + ); + } + + coerceInputLiteral( + valueNode: ConstValueNode, + hideSuggestions?: Maybe, + ): Maybe /* T */ { if (valueNode.kind !== Kind.ENUM) { const valueStr = print(valueNode); throw new GraphQLError( `Enum "${this.name}" cannot represent non-enum value: ${valueStr}.` + - didYouMeanEnumValue(this, valueStr), + (hideSuggestions ? '' : didYouMeanEnumValue(this, valueStr)), { nodes: valueNode }, ); } @@ -1354,30 +1647,28 @@ export class GraphQLEnumType /* */ { const valueStr = print(valueNode); throw new GraphQLError( `Value "${valueStr}" does not exist in "${this.name}" enum.` + - didYouMeanEnumValue(this, valueStr), + (hideSuggestions ? '' : didYouMeanEnumValue(this, valueStr)), { nodes: valueNode }, ); } return enumValue.value; } - toConfig(): GraphQLEnumTypeNormalizedConfig { - const values = keyValMap( - this.getValues(), - (value) => value.name, - (value) => ({ - description: value.description, - value: value.value, - deprecationReason: value.deprecationReason, - extensions: value.extensions, - astNode: value.astNode, - }), - ); + valueToLiteral(value: unknown): ConstValueNode | undefined { + if (typeof value === 'string' && this.getValue(value)) { + return { kind: Kind.ENUM, value }; + } + } + toConfig(): GraphQLEnumTypeNormalizedConfig { return { name: this.name, description: this.description, - values, + values: keyValMap( + this.getValues(), + (value) => value.name, + (value) => value.toConfig(), + ), extensions: this.extensions, astNode: this.astNode, extensionASTNodes: this.extensionASTNodes, @@ -1406,13 +1697,14 @@ function didYouMeanEnumValue( export interface GraphQLEnumTypeConfig { name: string; description?: Maybe; - values: GraphQLEnumValueConfigMap /* */; + values: ThunkObjMap */>; extensions?: Maybe>; astNode?: Maybe; extensionASTNodes?: Maybe>; } -interface GraphQLEnumTypeNormalizedConfig extends GraphQLEnumTypeConfig { +export interface GraphQLEnumTypeNormalizedConfig extends GraphQLEnumTypeConfig { + values: GraphQLEnumValueNormalizedConfigMap; extensions: Readonly; extensionASTNodes: ReadonlyArray; } @@ -1420,6 +1712,9 @@ interface GraphQLEnumTypeNormalizedConfig extends GraphQLEnumTypeConfig { export type GraphQLEnumValueConfigMap /* */ = ObjMap */>; +export type GraphQLEnumValueNormalizedConfigMap /* */ = + ObjMap */>; + /** * Custom extensions * @@ -1430,7 +1725,7 @@ export type GraphQLEnumValueConfigMap /* */ = * an object which can contain all the values you need. */ export interface GraphQLEnumValueExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } export interface GraphQLEnumValueConfig { @@ -1441,13 +1736,55 @@ export interface GraphQLEnumValueConfig { astNode?: Maybe; } -export interface GraphQLEnumValue { +export interface GraphQLEnumValueNormalizedConfig + extends GraphQLEnumValueConfig { + extensions: Readonly; +} + +export class GraphQLEnumValue implements GraphQLSchemaElement { + parentEnum: GraphQLEnumType; name: string; description: Maybe; value: any /* T */; deprecationReason: Maybe; extensions: Readonly; astNode: Maybe; + + constructor( + parentEnum: GraphQLEnumType, + name: string, + config: GraphQLEnumValueConfig, + ) { + this.parentEnum = parentEnum; + this.name = assertEnumValueName(name); + this.description = config.description; + this.value = config.value !== undefined ? config.value : name; + this.deprecationReason = config.deprecationReason; + this.extensions = toObjMapWithSymbols(config.extensions); + this.astNode = config.astNode; + } + + get [Symbol.toStringTag]() { + return 'GraphQLEnumValue'; + } + + toConfig(): GraphQLEnumValueNormalizedConfig { + return { + description: this.description, + value: this.value, + deprecationReason: this.deprecationReason, + extensions: this.extensions, + astNode: this.astNode, + }; + } + + toString(): string { + return `${this.parentEnum.name}.${this.name}`; + } + + toJSON(): string { + return this.toString(); + } } /** @@ -1460,7 +1797,7 @@ export interface GraphQLEnumValue { * an object which can contain all the values you need. */ export interface GraphQLInputObjectTypeExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** @@ -1484,7 +1821,7 @@ export interface GraphQLInputObjectTypeExtensions { * }); * ``` */ -export class GraphQLInputObjectType { +export class GraphQLInputObjectType implements GraphQLSchemaElement { name: string; description: Maybe; extensions: Readonly; @@ -1497,12 +1834,12 @@ export class GraphQLInputObjectType { constructor(config: Readonly) { this.name = assertName(config.name); this.description = config.description; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; this.isOneOf = config.isOneOf ?? false; - this._fields = defineInputFieldMap.bind(undefined, config.fields); + this._fields = defineInputFieldMap.bind(undefined, this, config.fields); } get [Symbol.toStringTag]() { @@ -1517,19 +1854,10 @@ export class GraphQLInputObjectType { } toConfig(): GraphQLInputObjectTypeNormalizedConfig { - const fields = mapValue(this.getFields(), (field) => ({ - description: field.description, - type: field.type, - defaultValue: field.defaultValue, - deprecationReason: field.deprecationReason, - extensions: field.extensions, - astNode: field.astNode, - })); - return { name: this.name, description: this.description, - fields, + fields: mapValue(this.getFields(), (field) => field.toConfig()), extensions: this.extensions, astNode: this.astNode, extensionASTNodes: this.extensionASTNodes, @@ -1547,18 +1875,15 @@ export class GraphQLInputObjectType { } function defineInputFieldMap( + parentType: GraphQLInputObjectType, fields: ThunkObjMap, ): GraphQLInputFieldMap { const fieldMap = resolveObjMapThunk(fields); - return mapValue(fieldMap, (fieldConfig, fieldName) => ({ - name: assertName(fieldName), - description: fieldConfig.description, - type: fieldConfig.type, - defaultValue: fieldConfig.defaultValue, - deprecationReason: fieldConfig.deprecationReason, - extensions: toObjMap(fieldConfig.extensions), - astNode: fieldConfig.astNode, - })); + return mapValue( + fieldMap, + (fieldConfig, fieldName) => + new GraphQLInputField(parentType, fieldName, fieldConfig), + ); } export interface GraphQLInputObjectTypeConfig { @@ -1571,9 +1896,9 @@ export interface GraphQLInputObjectTypeConfig { isOneOf?: boolean; } -interface GraphQLInputObjectTypeNormalizedConfig +export interface GraphQLInputObjectTypeNormalizedConfig extends GraphQLInputObjectTypeConfig { - fields: GraphQLInputFieldConfigMap; + fields: GraphQLInputFieldNormalizedConfigMap; extensions: Readonly; extensionASTNodes: ReadonlyArray; } @@ -1588,13 +1913,15 @@ interface GraphQLInputObjectTypeNormalizedConfig * an object which can contain all the values you need. */ export interface GraphQLInputFieldExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } export interface GraphQLInputFieldConfig { description?: Maybe; type: GraphQLInputType; + /** @deprecated use default instead, defaultValue will be removed in v18 **/ defaultValue?: unknown; + default?: GraphQLDefaultInput | undefined; deprecationReason?: Maybe; extensions?: Maybe>; astNode?: Maybe; @@ -1602,18 +1929,78 @@ export interface GraphQLInputFieldConfig { export type GraphQLInputFieldConfigMap = ObjMap; -export interface GraphQLInputField { +export interface GraphQLInputFieldNormalizedConfig + extends GraphQLInputFieldConfig { + default: GraphQLDefaultInput | undefined; + extensions: Readonly; +} + +export type GraphQLInputFieldNormalizedConfigMap = + ObjMap; + +export class GraphQLInputField implements GraphQLSchemaElement { + parentType: GraphQLInputObjectType; name: string; description: Maybe; type: GraphQLInputType; defaultValue: unknown; + default: GraphQLDefaultInput | undefined; deprecationReason: Maybe; extensions: Readonly; astNode: Maybe; + + constructor( + parentType: GraphQLInputObjectType, + name: string, + config: GraphQLInputFieldConfig, + ) { + devAssert( + !('resolve' in config), + `${parentType}.${name} field has a resolve property, but Input Types cannot define resolvers.`, + ); + + this.parentType = parentType; + this.name = assertName(name); + this.description = config.description; + this.type = config.type; + this.defaultValue = config.defaultValue; + this.default = config.default; + this.deprecationReason = config.deprecationReason; + this.extensions = toObjMapWithSymbols(config.extensions); + this.astNode = config.astNode; + } + + get [Symbol.toStringTag]() { + return 'GraphQLInputField'; + } + + toConfig(): GraphQLInputFieldNormalizedConfig { + return { + description: this.description, + type: this.type, + defaultValue: this.defaultValue, + default: this.default, + deprecationReason: this.deprecationReason, + extensions: this.extensions, + astNode: this.astNode, + }; + } + + toString(): string { + return `${this.parentType}.${this.name}`; + } + + toJSON(): string { + return this.toString(); + } } export function isRequiredInputField(field: GraphQLInputField): boolean { - return isNonNullType(field.type) && field.defaultValue === undefined; + return ( + isNonNullType(field.type) && + field.defaultValue === undefined && + field.default === undefined + ); } export type GraphQLInputFieldMap = ObjMap; diff --git a/src/type/directives.ts b/src/type/directives.ts index 48e90c5531..6b6f5d4fa2 100644 --- a/src/type/directives.ts +++ b/src/type/directives.ts @@ -1,21 +1,22 @@ +import { devAssert } from '../jsutils/devAssert.js'; import { inspect } from '../jsutils/inspect.js'; import { instanceOf } from '../jsutils/instanceOf.js'; +import { isObjectLike } from '../jsutils/isObjectLike.js'; +import { keyValMap } from '../jsutils/keyValMap.js'; import type { Maybe } from '../jsutils/Maybe.js'; -import { toObjMap } from '../jsutils/toObjMap.js'; +import type { ObjMap } from '../jsutils/ObjMap.js'; +import { toObjMapWithSymbols } from '../jsutils/toObjMap.js'; import type { DirectiveDefinitionNode } from '../language/ast.js'; import { DirectiveLocation } from '../language/directiveLocation.js'; import { assertName } from './assertName.js'; import type { - GraphQLArgument, - GraphQLFieldConfigArgumentMap, -} from './definition.js'; -import { - argsToArgsConfig, - defineArguments, - GraphQLNonNull, + GraphQLArgumentConfig, + GraphQLFieldNormalizedConfigArgumentMap, + GraphQLSchemaElement, } from './definition.js'; +import { GraphQLArgument, GraphQLNonNull } from './definition.js'; import { GraphQLBoolean, GraphQLInt, GraphQLString } from './scalars.js'; /** @@ -44,14 +45,14 @@ export function assertDirective(directive: unknown): GraphQLDirective { * an object which can contain all the values you need. */ export interface GraphQLDirectiveExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** * Directives are used by the GraphQL runtime as a way of modifying execution * behavior. Type system creators will usually not create these directly. */ -export class GraphQLDirective { +export class GraphQLDirective implements GraphQLSchemaElement { name: string; description: Maybe; locations: ReadonlyArray; @@ -65,11 +66,23 @@ export class GraphQLDirective { this.description = config.description; this.locations = config.locations; this.isRepeatable = config.isRepeatable ?? false; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; + devAssert( + Array.isArray(config.locations), + `@${this.name} locations must be an Array.`, + ); + const args = config.args ?? {}; - this.args = defineArguments(args); + devAssert( + isObjectLike(args) && !Array.isArray(args), + `@${this.name} args must be an object with argument names as keys.`, + ); + + this.args = Object.entries(args).map( + ([argName, argConfig]) => new GraphQLArgument(this, argName, argConfig), + ); } get [Symbol.toStringTag]() { @@ -81,7 +94,11 @@ export class GraphQLDirective { name: this.name, description: this.description, locations: this.locations, - args: argsToArgsConfig(this.args), + args: keyValMap( + this.args, + (arg) => arg.name, + (arg) => arg.toConfig(), + ), isRepeatable: this.isRepeatable, extensions: this.extensions, astNode: this.astNode, @@ -101,14 +118,15 @@ export interface GraphQLDirectiveConfig { name: string; description?: Maybe; locations: ReadonlyArray; - args?: Maybe; + args?: Maybe>; isRepeatable?: Maybe; extensions?: Maybe>; astNode?: Maybe; } -interface GraphQLDirectiveNormalizedConfig extends GraphQLDirectiveConfig { - args: GraphQLFieldConfigArgumentMap; +export interface GraphQLDirectiveNormalizedConfig + extends GraphQLDirectiveConfig { + args: GraphQLFieldNormalizedConfigArgumentMap; isRepeatable: boolean; extensions: Readonly; } @@ -168,7 +186,7 @@ export const GraphQLDeferDirective = new GraphQLDirective({ if: { type: new GraphQLNonNull(GraphQLBoolean), description: 'Deferred when true or undefined.', - defaultValue: true, + default: { value: true }, }, label: { type: GraphQLString, @@ -186,20 +204,20 @@ export const GraphQLStreamDirective = new GraphQLDirective({ 'Directs the executor to stream plural fields when the `if` argument is true or undefined.', locations: [DirectiveLocation.FIELD], args: { + initialCount: { + default: { value: 0 }, + type: new GraphQLNonNull(GraphQLInt), + description: 'Number of items to return immediately', + }, if: { type: new GraphQLNonNull(GraphQLBoolean), description: 'Stream when true or undefined.', - defaultValue: true, + default: { value: true }, }, label: { type: GraphQLString, description: 'Unique name', }, - initialCount: { - defaultValue: 0, - type: GraphQLInt, - description: 'Number of items to return immediately', - }, }, }); @@ -223,10 +241,10 @@ export const GraphQLDeprecatedDirective: GraphQLDirective = ], args: { reason: { - type: GraphQLString, + type: new GraphQLNonNull(GraphQLString), description: 'Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified by [CommonMark](https://commonmark.org/).', - defaultValue: DEFAULT_DEPRECATION_REASON, + default: { value: DEFAULT_DEPRECATION_REASON }, }, }, }); diff --git a/src/type/index.ts b/src/type/index.ts index 6617a7bfe1..dd9d103868 100644 --- a/src/type/index.ts +++ b/src/type/index.ts @@ -10,6 +10,12 @@ export { } from './schema.js'; export type { GraphQLSchemaConfig, GraphQLSchemaExtensions } from './schema.js'; +export type { + GraphQLField, + GraphQLArgument, + GraphQLEnumValue, + GraphQLInputField, +} from './definition.js'; export { resolveObjMapThunk, resolveReadonlyArrayThunk, @@ -17,13 +23,17 @@ export { isType, isScalarType, isObjectType, + isField, + isArgument, isInterfaceType, isUnionType, isEnumType, + isEnumValue, isInputObjectType, isListType, isNonNullType, isInputType, + isInputField, isOutputType, isLeafType, isCompositeType, @@ -37,10 +47,14 @@ export { assertType, assertScalarType, assertObjectType, + assertField, + assertArgument, assertInterfaceType, assertUnionType, assertEnumType, + assertEnumValue, assertInputObjectType, + assertInputField, assertListType, assertNonNullType, assertInputType, @@ -82,23 +96,19 @@ export type { GraphQLNamedOutputType, ThunkReadonlyArray, ThunkObjMap, - GraphQLArgument, GraphQLArgumentConfig, GraphQLArgumentExtensions, GraphQLEnumTypeConfig, GraphQLEnumTypeExtensions, - GraphQLEnumValue, GraphQLEnumValueConfig, GraphQLEnumValueConfigMap, GraphQLEnumValueExtensions, - GraphQLField, GraphQLFieldConfig, GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldExtensions, GraphQLFieldMap, GraphQLFieldResolver, - GraphQLInputField, GraphQLInputFieldConfig, GraphQLInputFieldConfigMap, GraphQLInputFieldExtensions, @@ -119,6 +129,10 @@ export type { GraphQLScalarSerializer, GraphQLScalarValueParser, GraphQLScalarLiteralParser, + GraphQLScalarOutputValueCoercer, + GraphQLScalarInputValueCoercer, + GraphQLScalarInputLiteralCoercer, + GraphQLDefaultInput, } from './definition.js'; export { diff --git a/src/type/introspection.ts b/src/type/introspection.ts index 5f3c9c1fa5..fc214bed3d 100644 --- a/src/type/introspection.ts +++ b/src/type/introspection.ts @@ -4,11 +4,10 @@ import { invariant } from '../jsutils/invariant.js'; import { DirectiveLocation } from '../language/directiveLocation.js'; import { print } from '../language/printer.js'; -import { astFromValue } from '../utilities/astFromValue.js'; +import { getDefaultValueAST } from '../utilities/getDefaultValueAST.js'; import type { GraphQLEnumValue, - GraphQLField, GraphQLFieldConfigMap, GraphQLInputField, GraphQLNamedType, @@ -16,6 +15,7 @@ import type { } from './definition.js'; import { GraphQLEnumType, + GraphQLField, GraphQLList, GraphQLNonNull, GraphQLObjectType, @@ -74,7 +74,7 @@ export const __Schema: GraphQLObjectType = new GraphQLObjectType({ ), resolve: (schema) => schema.getDirectives(), }, - } as GraphQLFieldConfigMap), + }) as GraphQLFieldConfigMap, }); export const __Directive: GraphQLObjectType = new GraphQLObjectType({ @@ -108,7 +108,7 @@ export const __Directive: GraphQLObjectType = new GraphQLObjectType({ args: { includeDeprecated: { type: GraphQLBoolean, - defaultValue: false, + default: { value: false }, }, }, resolve(field, { includeDeprecated }) { @@ -117,7 +117,7 @@ export const __Directive: GraphQLObjectType = new GraphQLObjectType({ : field.args.filter((arg) => arg.deprecationReason == null); }, }, - } as GraphQLFieldConfigMap), + }) as GraphQLFieldConfigMap, }); export const __DirectiveLocation: GraphQLEnumType = new GraphQLEnumType({ @@ -155,7 +155,11 @@ export const __DirectiveLocation: GraphQLEnumType = new GraphQLEnumType({ }, VARIABLE_DEFINITION: { value: DirectiveLocation.VARIABLE_DEFINITION, - description: 'Location adjacent to a variable definition.', + description: 'Location adjacent to an operation variable definition.', + }, + FRAGMENT_VARIABLE_DEFINITION: { + value: DirectiveLocation.FRAGMENT_VARIABLE_DEFINITION, + description: 'Location adjacent to a fragment variable definition.', }, SCHEMA: { value: DirectiveLocation.SCHEMA, @@ -261,7 +265,10 @@ export const __Type: GraphQLObjectType = new GraphQLObjectType({ fields: { type: new GraphQLList(new GraphQLNonNull(__Field)), args: { - includeDeprecated: { type: GraphQLBoolean, defaultValue: false }, + includeDeprecated: { + type: GraphQLBoolean, + default: { value: false }, + }, }, resolve(type, { includeDeprecated }) { if (isObjectType(type) || isInterfaceType(type)) { @@ -291,7 +298,10 @@ export const __Type: GraphQLObjectType = new GraphQLObjectType({ enumValues: { type: new GraphQLList(new GraphQLNonNull(__EnumValue)), args: { - includeDeprecated: { type: GraphQLBoolean, defaultValue: false }, + includeDeprecated: { + type: GraphQLBoolean, + default: { value: false }, + }, }, resolve(type, { includeDeprecated }) { if (isEnumType(type)) { @@ -307,7 +317,7 @@ export const __Type: GraphQLObjectType = new GraphQLObjectType({ args: { includeDeprecated: { type: GraphQLBoolean, - defaultValue: false, + default: { value: false }, }, }, resolve(type, { includeDeprecated }) { @@ -331,7 +341,7 @@ export const __Type: GraphQLObjectType = new GraphQLObjectType({ } }, }, - } as GraphQLFieldConfigMap), + }) as GraphQLFieldConfigMap, }); export const __Field: GraphQLObjectType = new GraphQLObjectType({ @@ -355,7 +365,7 @@ export const __Field: GraphQLObjectType = new GraphQLObjectType({ args: { includeDeprecated: { type: GraphQLBoolean, - defaultValue: false, + default: { value: false }, }, }, resolve(field, { includeDeprecated }) { @@ -376,7 +386,7 @@ export const __Field: GraphQLObjectType = new GraphQLObjectType({ type: GraphQLString, resolve: (field) => field.deprecationReason, }, - } as GraphQLFieldConfigMap, unknown>), + }) as GraphQLFieldConfigMap, unknown>, }); export const __InputValue: GraphQLObjectType = new GraphQLObjectType({ @@ -402,9 +412,11 @@ export const __InputValue: GraphQLObjectType = new GraphQLObjectType({ description: 'A GraphQL-formatted string representing the default value for this input value.', resolve(inputValue) { - const { type, defaultValue } = inputValue; - const valueAST = astFromValue(defaultValue, type); - return valueAST ? print(valueAST) : null; + const ast = getDefaultValueAST(inputValue); + if (ast) { + return print(ast); + } + return null; }, }, isDeprecated: { @@ -415,7 +427,7 @@ export const __InputValue: GraphQLObjectType = new GraphQLObjectType({ type: GraphQLString, resolve: (obj) => obj.deprecationReason, }, - } as GraphQLFieldConfigMap), + }) as GraphQLFieldConfigMap, }); export const __EnumValue: GraphQLObjectType = new GraphQLObjectType({ @@ -440,19 +452,22 @@ export const __EnumValue: GraphQLObjectType = new GraphQLObjectType({ type: GraphQLString, resolve: (enumValue) => enumValue.deprecationReason, }, - } as GraphQLFieldConfigMap), + }) as GraphQLFieldConfigMap, }); -export enum TypeKind { - SCALAR = 'SCALAR', - OBJECT = 'OBJECT', - INTERFACE = 'INTERFACE', - UNION = 'UNION', - ENUM = 'ENUM', - INPUT_OBJECT = 'INPUT_OBJECT', - LIST = 'LIST', - NON_NULL = 'NON_NULL', -} +export const TypeKind = { + SCALAR: 'SCALAR' as const, + OBJECT: 'OBJECT' as const, + INTERFACE: 'INTERFACE' as const, + UNION: 'UNION' as const, + ENUM: 'ENUM' as const, + INPUT_OBJECT: 'INPUT_OBJECT' as const, + LIST: 'LIST' as const, + NON_NULL: 'NON_NULL' as const, +} as const; + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type TypeKind = (typeof TypeKind)[keyof typeof TypeKind]; export const __TypeKind: GraphQLEnumType = new GraphQLEnumType({ name: '__TypeKind', @@ -499,53 +514,24 @@ export const __TypeKind: GraphQLEnumType = new GraphQLEnumType({ }, }); -/** - * Note that these are GraphQLField and not GraphQLFieldConfig, - * so the format for args is different. - */ - -export const SchemaMetaFieldDef: GraphQLField = { - name: '__schema', +export const SchemaMetaFieldDef = new GraphQLField(undefined, '__schema', { type: new GraphQLNonNull(__Schema), description: 'Access the current type schema of this server.', - args: [], resolve: (_source, _args, _context, { schema }) => schema, - deprecationReason: undefined, - extensions: Object.create(null), - astNode: undefined, -}; +}); -export const TypeMetaFieldDef: GraphQLField = { - name: '__type', +export const TypeMetaFieldDef = new GraphQLField(undefined, '__type', { type: __Type, description: 'Request the type information of a single type.', - args: [ - { - name: 'name', - description: undefined, - type: new GraphQLNonNull(GraphQLString), - defaultValue: undefined, - deprecationReason: undefined, - extensions: Object.create(null), - astNode: undefined, - }, - ], + args: { name: { type: new GraphQLNonNull(GraphQLString) } }, resolve: (_source, { name }, _context, { schema }) => schema.getType(name), - deprecationReason: undefined, - extensions: Object.create(null), - astNode: undefined, -}; +}); -export const TypeNameMetaFieldDef: GraphQLField = { - name: '__typename', +export const TypeNameMetaFieldDef = new GraphQLField(undefined, '__typename', { type: new GraphQLNonNull(GraphQLString), description: 'The name of the current Object type at runtime.', - args: [], resolve: (_source, _args, _context, { parentType }) => parentType.name, - deprecationReason: undefined, - extensions: Object.create(null), - astNode: undefined, -}; +}); export const introspectionTypes: ReadonlyArray = Object.freeze([ diff --git a/src/type/scalars.ts b/src/type/scalars.ts index d2c9c9bee2..37428e7146 100644 --- a/src/type/scalars.ts +++ b/src/type/scalars.ts @@ -6,6 +6,8 @@ import { GraphQLError } from '../error/GraphQLError.js'; import { Kind } from '../language/kinds.js'; import { print } from '../language/printer.js'; +import { defaultScalarValueToLiteral } from '../utilities/valueToLiteral.js'; + import type { GraphQLNamedType } from './definition.js'; import { GraphQLScalarType } from './definition.js'; @@ -26,8 +28,8 @@ export const GraphQLInt = new GraphQLScalarType({ description: 'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.', - serialize(outputValue) { - const coercedValue = serializeObject(outputValue); + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); if (typeof coercedValue === 'boolean') { return coercedValue ? 1 : 0; @@ -52,7 +54,7 @@ export const GraphQLInt = new GraphQLScalarType({ return num; }, - parseValue(inputValue) { + coerceInputValue(inputValue) { if (typeof inputValue !== 'number' || !Number.isInteger(inputValue)) { throw new GraphQLError( `Int cannot represent non-integer value: ${inspect(inputValue)}`, @@ -66,7 +68,7 @@ export const GraphQLInt = new GraphQLScalarType({ return inputValue; }, - parseLiteral(valueNode) { + coerceInputLiteral(valueNode) { if (valueNode.kind !== Kind.INT) { throw new GraphQLError( `Int cannot represent non-integer value: ${print(valueNode)}`, @@ -82,6 +84,16 @@ export const GraphQLInt = new GraphQLScalarType({ } return num; }, + valueToLiteral(value) { + if ( + typeof value === 'number' && + Number.isInteger(value) && + value <= GRAPHQL_MAX_INT && + value >= GRAPHQL_MIN_INT + ) { + return { kind: Kind.INT, value: String(value) }; + } + }, }); export const GraphQLFloat = new GraphQLScalarType({ @@ -89,8 +101,8 @@ export const GraphQLFloat = new GraphQLScalarType({ description: 'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).', - serialize(outputValue) { - const coercedValue = serializeObject(outputValue); + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); if (typeof coercedValue === 'boolean') { return coercedValue ? 1 : 0; @@ -109,7 +121,7 @@ export const GraphQLFloat = new GraphQLScalarType({ return num; }, - parseValue(inputValue) { + coerceInputValue(inputValue) { if (typeof inputValue !== 'number' || !Number.isFinite(inputValue)) { throw new GraphQLError( `Float cannot represent non numeric value: ${inspect(inputValue)}`, @@ -118,7 +130,7 @@ export const GraphQLFloat = new GraphQLScalarType({ return inputValue; }, - parseLiteral(valueNode) { + coerceInputLiteral(valueNode) { if (valueNode.kind !== Kind.FLOAT && valueNode.kind !== Kind.INT) { throw new GraphQLError( `Float cannot represent non numeric value: ${print(valueNode)}`, @@ -127,6 +139,12 @@ export const GraphQLFloat = new GraphQLScalarType({ } return parseFloat(valueNode.value); }, + valueToLiteral(value) { + const literal = defaultScalarValueToLiteral(value); + if (literal.kind === Kind.FLOAT || literal.kind === Kind.INT) { + return literal; + } + }, }); export const GraphQLString = new GraphQLScalarType({ @@ -134,10 +152,10 @@ export const GraphQLString = new GraphQLScalarType({ description: 'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.', - serialize(outputValue) { - const coercedValue = serializeObject(outputValue); + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); - // Serialize string, boolean and number values to a string, but do not + // Coerces string, boolean and number values to a string, but do not // attempt to coerce object, function, symbol, or other types as strings. if (typeof coercedValue === 'string') { return coercedValue; @@ -153,7 +171,7 @@ export const GraphQLString = new GraphQLScalarType({ ); }, - parseValue(inputValue) { + coerceInputValue(inputValue) { if (typeof inputValue !== 'string') { throw new GraphQLError( `String cannot represent a non string value: ${inspect(inputValue)}`, @@ -162,7 +180,7 @@ export const GraphQLString = new GraphQLScalarType({ return inputValue; }, - parseLiteral(valueNode) { + coerceInputLiteral(valueNode) { if (valueNode.kind !== Kind.STRING) { throw new GraphQLError( `String cannot represent a non string value: ${print(valueNode)}`, @@ -171,14 +189,20 @@ export const GraphQLString = new GraphQLScalarType({ } return valueNode.value; }, + valueToLiteral(value) { + const literal = defaultScalarValueToLiteral(value); + if (literal.kind === Kind.STRING) { + return literal; + } + }, }); export const GraphQLBoolean = new GraphQLScalarType({ name: 'Boolean', description: 'The `Boolean` scalar type represents `true` or `false`.', - serialize(outputValue) { - const coercedValue = serializeObject(outputValue); + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); if (typeof coercedValue === 'boolean') { return coercedValue; @@ -191,7 +215,7 @@ export const GraphQLBoolean = new GraphQLScalarType({ ); }, - parseValue(inputValue) { + coerceInputValue(inputValue) { if (typeof inputValue !== 'boolean') { throw new GraphQLError( `Boolean cannot represent a non boolean value: ${inspect(inputValue)}`, @@ -200,7 +224,7 @@ export const GraphQLBoolean = new GraphQLScalarType({ return inputValue; }, - parseLiteral(valueNode) { + coerceInputLiteral(valueNode) { if (valueNode.kind !== Kind.BOOLEAN) { throw new GraphQLError( `Boolean cannot represent a non boolean value: ${print(valueNode)}`, @@ -209,6 +233,12 @@ export const GraphQLBoolean = new GraphQLScalarType({ } return valueNode.value; }, + valueToLiteral(value) { + const literal = defaultScalarValueToLiteral(value); + if (literal.kind === Kind.BOOLEAN) { + return literal; + } + }, }); export const GraphQLID = new GraphQLScalarType({ @@ -216,8 +246,8 @@ export const GraphQLID = new GraphQLScalarType({ description: 'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.', - serialize(outputValue) { - const coercedValue = serializeObject(outputValue); + coerceOutputValue(outputValue) { + const coercedValue = coerceOutputValueObject(outputValue); if (typeof coercedValue === 'string') { return coercedValue; @@ -230,7 +260,7 @@ export const GraphQLID = new GraphQLScalarType({ ); }, - parseValue(inputValue) { + coerceInputValue(inputValue) { if (typeof inputValue === 'string') { return inputValue; } @@ -240,7 +270,7 @@ export const GraphQLID = new GraphQLScalarType({ throw new GraphQLError(`ID cannot represent value: ${inspect(inputValue)}`); }, - parseLiteral(valueNode) { + coerceInputLiteral(valueNode) { if (valueNode.kind !== Kind.STRING && valueNode.kind !== Kind.INT) { throw new GraphQLError( 'ID cannot represent a non-string and non-integer value: ' + @@ -250,6 +280,16 @@ export const GraphQLID = new GraphQLScalarType({ } return valueNode.value; }, + valueToLiteral(value) { + // ID types can use number values and Int literals. + const stringValue = Number.isInteger(value) ? String(value) : value; + if (typeof stringValue === 'string') { + // Will parse as an IntValue. + return /^-?(?:0|[1-9][0-9]*)$/.test(stringValue) + ? { kind: Kind.INT, value: stringValue } + : { kind: Kind.STRING, value: stringValue, block: false }; + } + }, }); export const specifiedScalarTypes: ReadonlyArray = @@ -265,10 +305,10 @@ export function isSpecifiedScalarType(type: GraphQLNamedType): boolean { return specifiedScalarTypes.some(({ name }) => type.name === name); } -// Support serializing objects with custom valueOf() or toJSON() functions - +// Support coercing objects with custom valueOf() or toJSON() functions - // a common way to represent a complex value which can be represented as // a string (ex: MongoDB id objects). -function serializeObject(outputValue: unknown): unknown { +function coerceOutputValueObject(outputValue: unknown): unknown { if (isObjectLike(outputValue)) { if (typeof outputValue.valueOf === 'function') { const valueOfResult = outputValue.valueOf(); diff --git a/src/type/schema.ts b/src/type/schema.ts index 694454fae5..03d7422085 100644 --- a/src/type/schema.ts +++ b/src/type/schema.ts @@ -2,7 +2,7 @@ import { inspect } from '../jsutils/inspect.js'; import { instanceOf } from '../jsutils/instanceOf.js'; import type { Maybe } from '../jsutils/Maybe.js'; import type { ObjMap } from '../jsutils/ObjMap.js'; -import { toObjMap } from '../jsutils/toObjMap.js'; +import { toObjMapWithSymbols } from '../jsutils/toObjMap.js'; import type { GraphQLError } from '../error/GraphQLError.js'; @@ -61,7 +61,7 @@ export function assertSchema(schema: unknown): GraphQLSchema { * an object which can contain all the values you need. */ export interface GraphQLSchemaExtensions { - [attributeName: string]: unknown; + [attributeName: string | symbol]: unknown; } /** @@ -138,7 +138,7 @@ export class GraphQLSchema { astNode: Maybe; extensionASTNodes: ReadonlyArray; - // Used as a cache for validateSchema(). + assumeValid: boolean; __validationErrors: Maybe>; private _queryType: Maybe; @@ -159,10 +159,12 @@ export class GraphQLSchema { constructor(config: Readonly) { // If this schema was built from a source known to be valid, then it may be // marked with assumeValid to avoid an additional type system validation. + this.assumeValid = config.assumeValid ?? false; + // Used as a cache for validateSchema(). this.__validationErrors = config.assumeValid === true ? [] : undefined; this.description = config.description; - this.extensions = toObjMap(config.extensions); + this.extensions = toObjMapWithSymbols(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; @@ -384,7 +386,7 @@ export class GraphQLSchema { extensions: this.extensions, astNode: this.astNode, extensionASTNodes: this.extensionASTNodes, - assumeValid: this.__validationErrors !== undefined, + assumeValid: this.assumeValid, }; } } diff --git a/src/type/validate.ts b/src/type/validate.ts index deee23a372..88e2dbb992 100644 --- a/src/type/validate.ts +++ b/src/type/validate.ts @@ -2,12 +2,20 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap.js'; import { capitalize } from '../jsutils/capitalize.js'; import { andList } from '../jsutils/formatList.js'; import { inspect } from '../jsutils/inspect.js'; +import { invariant } from '../jsutils/invariant.js'; +import { isIterableObject } from '../jsutils/isIterableObject.js'; +import { isObjectLike } from '../jsutils/isObjectLike.js'; +import { keyMap } from '../jsutils/keyMap.js'; +import { mapValue } from '../jsutils/mapValue.js'; import type { Maybe } from '../jsutils/Maybe.js'; +import type { ObjMap } from '../jsutils/ObjMap.js'; +import { printPathArray } from '../jsutils/printPathArray.js'; import { GraphQLError } from '../error/GraphQLError.js'; import type { ASTNode, + ConstValueNode, DirectiveNode, InterfaceTypeDefinitionNode, InterfaceTypeExtensionNode, @@ -18,22 +26,32 @@ import type { UnionTypeExtensionNode, } from '../language/ast.js'; import { OperationTypeNode } from '../language/ast.js'; +import { Kind } from '../language/kinds.js'; import { isEqualType, isTypeSubTypeOf } from '../utilities/typeComparators.js'; +import { + validateInputLiteral, + validateInputValue, +} from '../utilities/validateInputValue.js'; import type { + GraphQLArgument, GraphQLEnumType, GraphQLInputField, GraphQLInputObjectType, + GraphQLInputType, GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType, } from './definition.js'; import { + assertLeafType, + getNamedType, isEnumType, isInputObjectType, isInputType, isInterfaceType, + isListType, isNamedType, isNonNullType, isObjectType, @@ -148,7 +166,7 @@ function validateRootTypes(context: SchemaValidationContext): void { if (operationTypes.length > 1) { const operationList = andList(operationTypes); context.reportError( - `All root types must be different, "${rootType.name}" type is used as ${operationList} root types.`, + `All root types must be different, "${rootType}" type is used as ${operationList} root types.`, operationTypes.map((operationType) => getOperationTypeNode(schema, operationType), ), @@ -162,10 +180,7 @@ function getOperationTypeNode( operation: OperationTypeNode, ): Maybe { return [schema.astNode, ...schema.extensionASTNodes] - .flatMap( - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - (schemaNode) => /* c8 ignore next */ schemaNode?.operationTypes ?? [], - ) + .flatMap((schemaNode) => schemaNode?.operationTypes ?? []) .find((operationNode) => operationNode.operation === operation)?.type; } @@ -183,7 +198,12 @@ function validateDirectives(context: SchemaValidationContext): void { // Ensure they are named correctly. validateName(context, directive); - // TODO: Ensure proper locations. + if (directive.locations.length === 0) { + context.reportError( + `Directive ${directive} must include 1 or more locations.`, + directive.astNode, + ); + } // Ensure the arguments are valid. for (const arg of directive.args) { @@ -193,20 +213,137 @@ function validateDirectives(context: SchemaValidationContext): void { // Ensure the type is an input type. if (!isInputType(arg.type)) { context.reportError( - `The type of @${directive.name}(${arg.name}:) must be Input Type ` + + `The type of ${arg} must be Input Type ` + `but got: ${inspect(arg.type)}.`, arg.astNode, ); } if (isRequiredArgument(arg) && arg.deprecationReason != null) { + context.reportError(`Required argument ${arg} cannot be deprecated.`, [ + getDeprecatedDirectiveNode(arg.astNode), + arg.astNode?.type, + ]); + } + + validateDefaultValue(context, arg); + } + } +} + +function validateDefaultValue( + context: SchemaValidationContext, + inputValue: GraphQLArgument | GraphQLInputField, +): void { + const defaultInput = inputValue.default; + + if (!defaultInput) { + return; + } + + if (defaultInput.literal) { + validateInputLiteral( + defaultInput.literal, + inputValue.type, + (error, path) => { context.reportError( - `Required argument @${directive.name}(${arg.name}:) cannot be deprecated.`, - [getDeprecatedDirectiveNode(arg.astNode), arg.astNode?.type], + `${inputValue} has invalid default value${printPathArray(path)}: ${ + error.message + }`, + error.nodes, + ); + }, + ); + } else { + const errors: Array<[GraphQLError, ReadonlyArray]> = []; + validateInputValue(defaultInput.value, inputValue.type, (error, path) => { + errors.push([error, path]); + }); + + // If there were validation errors, check to see if it can be "uncoerced" + // and then correctly validated. If so, report a clear error with a path + // to resolution. + if (errors.length > 0) { + try { + const uncoercedValue = uncoerceDefaultValue( + defaultInput.value, + inputValue.type, ); + + const uncoercedErrors = []; + validateInputValue(uncoercedValue, inputValue.type, (error, path) => { + uncoercedErrors.push([error, path]); + }); + + if (uncoercedErrors.length === 0) { + context.reportError( + `${inputValue} has invalid default value: ${inspect( + defaultInput.value, + )}. Did you mean: ${inspect(uncoercedValue)}?`, + inputValue.astNode?.defaultValue, + ); + return; + } + } catch (_error) { + // ignore } } + + // Otherwise report the original set of errors. + for (const [error, path] of errors) { + context.reportError( + `${inputValue} has invalid default value${printPathArray(path)}: ${ + error.message + }`, + inputValue.astNode?.defaultValue, + ); + } + } +} + +/** + * Historically GraphQL.js allowed default values to be provided as + * assumed-coerced "internal" values, however default values should be provided + * as "external" pre-coerced values. `uncoerceDefaultValue()` will convert such + * "internal" values to "external" values to display as part of validation. + * + * This performs the "opposite" of `coerceInputValue()`. Given an "internal" + * coerced value, reverse the process to provide an "external" uncoerced value. + */ +function uncoerceDefaultValue(value: unknown, type: GraphQLInputType): unknown { + if (isNonNullType(type)) { + return uncoerceDefaultValue(value, type.ofType); + } + + if (value === null) { + return null; + } + + if (isListType(type)) { + if (isIterableObject(value)) { + return Array.from(value, (itemValue) => + uncoerceDefaultValue(itemValue, type.ofType), + ); + } + return [uncoerceDefaultValue(value, type.ofType)]; + } + + if (isInputObjectType(type)) { + invariant(isObjectLike(value)); + const fieldDefs = type.getFields(); + return mapValue(value, (fieldValue, fieldName) => { + invariant(fieldName in fieldDefs); + return uncoerceDefaultValue(fieldValue, fieldDefs[fieldName].type); + }); } + + assertLeafType(type); + + // For most leaf types (Scalars, Enums), output value coercion ("serialize") is + // the inverse of input coercion ("parseValue") and will produce an + // "external" value. Historically, this method was also used as part of the + // now-deprecated "astFromValue" to perform the same behavior. + return type.coerceOutputValue(value); } function validateName( @@ -223,8 +360,11 @@ function validateName( } function validateTypes(context: SchemaValidationContext): void { - const validateInputObjectCircularRefs = - createInputObjectCircularRefsValidator(context); + // Ensure Input Objects do not contain non-nullable circular references. + const validateInputObjectNonNullCircularRefs = + createInputObjectNonNullCircularRefsValidator(context); + const validateInputObjectDefaultValueCircularRefs = + createInputObjectDefaultValueCircularRefsValidator(context); const typeMap = context.schema.getTypeMap(); for (const type of Object.values(typeMap)) { // Ensure all provided types are in fact GraphQL type. @@ -263,8 +403,12 @@ function validateTypes(context: SchemaValidationContext): void { // Ensure Input Object fields are valid. validateInputFields(context, type); - // Ensure Input Objects do not contain non-nullable circular references - validateInputObjectCircularRefs(type); + // Ensure Input Objects do not contain invalid field circular references. + // Ensure Input Objects do not contain non-nullable circular references. + validateInputObjectNonNullCircularRefs(type); + + // Ensure Input Objects do not contain invalid default value circular references. + validateInputObjectDefaultValueCircularRefs(type); } } } @@ -277,7 +421,7 @@ function validateFields( // Objects and Interfaces both must define one or more fields. if (fields.length === 0) { - context.reportError(`Type ${type.name} must define one or more fields.`, [ + context.reportError(`Type ${type} must define one or more fields.`, [ type.astNode, ...type.extensionASTNodes, ]); @@ -290,7 +434,7 @@ function validateFields( // Ensure the type is an output type if (!isOutputType(field.type)) { context.reportError( - `The type of ${type.name}.${field.name} must be Output Type ` + + `The type of ${field} must be Output Type ` + `but got: ${inspect(field.type)}.`, field.astNode?.type, ); @@ -298,26 +442,25 @@ function validateFields( // Ensure the arguments are valid for (const arg of field.args) { - const argName = arg.name; - // Ensure they are named correctly. validateName(context, arg); // Ensure the type is an input type if (!isInputType(arg.type)) { context.reportError( - `The type of ${type.name}.${field.name}(${argName}:) must be Input ` + - `Type but got: ${inspect(arg.type)}.`, + `The type of ${arg} must be Input Type but got: ${inspect(arg.type)}.`, arg.astNode?.type, ); } if (isRequiredArgument(arg) && arg.deprecationReason != null) { - context.reportError( - `Required argument ${type.name}.${field.name}(${argName}:) cannot be deprecated.`, - [getDeprecatedDirectiveNode(arg.astNode), arg.astNode?.type], - ); + context.reportError(`Required argument ${arg} cannot be deprecated.`, [ + getDeprecatedDirectiveNode(arg.astNode), + arg.astNode?.type, + ]); } + + validateDefaultValue(context, arg); } } } @@ -330,7 +473,7 @@ function validateInterfaces( for (const iface of type.getInterfaces()) { if (!isInterfaceType(iface)) { context.reportError( - `Type ${inspect(type)} must only implement Interface types, ` + + `Type ${type} must only implement Interface types, ` + `it cannot implement ${inspect(iface)}.`, getAllImplementsInterfaceNodes(type, iface), ); @@ -339,7 +482,7 @@ function validateInterfaces( if (type === iface) { context.reportError( - `Type ${type.name} cannot implement itself because it would create a circular reference.`, + `Type ${type} cannot implement itself because it would create a circular reference.`, getAllImplementsInterfaceNodes(type, iface), ); continue; @@ -347,7 +490,7 @@ function validateInterfaces( if (ifaceTypeNames.has(iface.name)) { context.reportError( - `Type ${type.name} can only implement ${iface.name} once.`, + `Type ${type} can only implement ${iface} once.`, getAllImplementsInterfaceNodes(type, iface), ); continue; @@ -369,13 +512,12 @@ function validateTypeImplementsInterface( // Assert each interface field is implemented. for (const ifaceField of Object.values(iface.getFields())) { - const fieldName = ifaceField.name; - const typeField = typeFieldMap[fieldName]; + const typeField = typeFieldMap[ifaceField.name]; // Assert interface field exists on type. if (typeField == null) { context.reportError( - `Interface field ${iface.name}.${fieldName} expected but ${type.name} does not provide it.`, + `Interface field ${ifaceField} expected but ${type} does not provide it.`, [ifaceField.astNode, type.astNode, ...type.extensionASTNodes], ); continue; @@ -385,22 +527,20 @@ function validateTypeImplementsInterface( // a valid subtype. (covariant) if (!isTypeSubTypeOf(context.schema, typeField.type, ifaceField.type)) { context.reportError( - `Interface field ${iface.name}.${fieldName} expects type ` + - `${inspect(ifaceField.type)} but ${type.name}.${fieldName} ` + - `is type ${inspect(typeField.type)}.`, + `Interface field ${ifaceField} expects type ${ifaceField.type} ` + + `but ${typeField} is type ${typeField.type}.`, [ifaceField.astNode?.type, typeField.astNode?.type], ); } // Assert each interface field arg is implemented. for (const ifaceArg of ifaceField.args) { - const argName = ifaceArg.name; - const typeArg = typeField.args.find((arg) => arg.name === argName); + const typeArg = typeField.args.find((arg) => arg.name === ifaceArg.name); // Assert interface field arg exists on object field. if (!typeArg) { context.reportError( - `Interface field argument ${iface.name}.${fieldName}(${argName}:) expected but ${type.name}.${fieldName} does not provide it.`, + `Interface field argument ${ifaceArg} expected but ${typeField} does not provide it.`, [ifaceArg.astNode, typeField.astNode], ); continue; @@ -411,26 +551,26 @@ function validateTypeImplementsInterface( // TODO: change to contravariant? if (!isEqualType(ifaceArg.type, typeArg.type)) { context.reportError( - `Interface field argument ${iface.name}.${fieldName}(${argName}:) ` + - `expects type ${inspect(ifaceArg.type)} but ` + - `${type.name}.${fieldName}(${argName}:) is type ` + - `${inspect(typeArg.type)}.`, + `Interface field argument ${ifaceArg} expects type ${ifaceArg.type} ` + + `but ${typeArg} is type ${typeArg.type}.`, [ifaceArg.astNode?.type, typeArg.astNode?.type], ); } - - // TODO: validate default values? } // Assert additional arguments must not be required. for (const typeArg of typeField.args) { - const argName = typeArg.name; - const ifaceArg = ifaceField.args.find((arg) => arg.name === argName); - if (!ifaceArg && isRequiredArgument(typeArg)) { - context.reportError( - `Object field ${type.name}.${fieldName} includes required argument ${argName} that is missing from the Interface field ${iface.name}.${fieldName}.`, - [typeArg.astNode, ifaceField.astNode], + if (isRequiredArgument(typeArg)) { + const ifaceArg = ifaceField.args.find( + (arg) => arg.name === typeArg.name, ); + if (!ifaceArg) { + context.reportError( + `Argument "${typeArg}" must not be required type "${typeArg.type}" ` + + `if not provided by the Interface field "${ifaceField}".`, + [typeArg.astNode, ifaceField.astNode], + ); + } } } } @@ -446,8 +586,8 @@ function validateTypeImplementsAncestors( if (!ifaceInterfaces.includes(transitive)) { context.reportError( transitive === type - ? `Type ${type.name} cannot implement ${iface.name} because it would create a circular reference.` - : `Type ${type.name} must implement ${transitive.name} because it is implemented by ${iface.name}.`, + ? `Type ${type} cannot implement ${iface} because it would create a circular reference.` + : `Type ${type} must implement ${transitive} because it is implemented by ${iface}.`, [ ...getAllImplementsInterfaceNodes(iface, transitive), ...getAllImplementsInterfaceNodes(type, iface), @@ -465,7 +605,7 @@ function validateUnionMembers( if (memberTypes.length === 0) { context.reportError( - `Union type ${union.name} must define one or more member types.`, + `Union type ${union} must define one or more member types.`, [union.astNode, ...union.extensionASTNodes], ); } @@ -474,7 +614,7 @@ function validateUnionMembers( for (const memberType of memberTypes) { if (includedTypeNames.has(memberType.name)) { context.reportError( - `Union type ${union.name} can only include type ${memberType.name} once.`, + `Union type ${union} can only include type ${memberType} once.`, getUnionMemberTypeNodes(union, memberType.name), ); continue; @@ -482,7 +622,7 @@ function validateUnionMembers( includedTypeNames.add(memberType.name); if (!isObjectType(memberType)) { context.reportError( - `Union type ${union.name} can only include Object types, ` + + `Union type ${union} can only include Object types, ` + `it cannot include ${inspect(memberType)}.`, getUnionMemberTypeNodes(union, String(memberType)), ); @@ -498,7 +638,7 @@ function validateEnumValues( if (enumValues.length === 0) { context.reportError( - `Enum type ${enumType.name} must define one or more values.`, + `Enum type ${enumType} must define one or more values.`, [enumType.astNode, ...enumType.extensionASTNodes], ); } @@ -517,12 +657,12 @@ function validateInputFields( if (fields.length === 0) { context.reportError( - `Input Object type ${inputObj.name} must define one or more fields.`, + `Input Object type ${inputObj} must define one or more fields.`, [inputObj.astNode, ...inputObj.extensionASTNodes], ); } - // Ensure the arguments are valid + // Ensure the input fields are valid for (const field of fields) { // Ensure they are named correctly. validateName(context, field); @@ -530,7 +670,7 @@ function validateInputFields( // Ensure the type is an input type if (!isInputType(field.type)) { context.reportError( - `The type of ${inputObj.name}.${field.name} must be Input Type ` + + `The type of ${field} must be Input Type ` + `but got: ${inspect(field.type)}.`, field.astNode?.type, ); @@ -538,11 +678,13 @@ function validateInputFields( if (isRequiredInputField(field) && field.deprecationReason != null) { context.reportError( - `Required input field ${inputObj.name}.${field.name} cannot be deprecated.`, + `Required input field ${field} cannot be deprecated.`, [getDeprecatedDirectiveNode(field.astNode), field.astNode?.type], ); } + validateDefaultValue(context, field); + if (inputObj.isOneOf) { validateOneOfInputObjectField(inputObj, field, context); } @@ -556,20 +698,20 @@ function validateOneOfInputObjectField( ): void { if (isNonNullType(field.type)) { context.reportError( - `OneOf input field ${type.name}.${field.name} must be nullable.`, + `OneOf input field ${type}.${field.name} must be nullable.`, field.astNode?.type, ); } - if (field.defaultValue !== undefined) { + if (field.default !== undefined || field.defaultValue !== undefined) { context.reportError( - `OneOf input field ${type.name}.${field.name} cannot have a default value.`, + `OneOf input field ${type}.${field.name} cannot have a default value.`, field.astNode, ); } } -function createInputObjectCircularRefsValidator( +function createInputObjectNonNullCircularRefsValidator( context: SchemaValidationContext, ): (inputObj: GraphQLInputObjectType) => void { // Modified copy of algorithm from 'src/validation/rules/NoFragmentCycles.js'. @@ -578,10 +720,11 @@ function createInputObjectCircularRefsValidator( const visitedTypes = new Set(); // Array of types nodes used to produce meaningful errors - const fieldPath: Array = []; + const fieldPath: Array<{ fieldStr: string; astNode: Maybe }> = []; // Position in the type path - const fieldPathIndexByTypeName = Object.create(null); + const fieldPathIndexByTypeName: ObjMap = + Object.create(null); return detectCycleRecursive; @@ -602,14 +745,23 @@ function createInputObjectCircularRefsValidator( const fieldType = field.type.ofType; const cycleIndex = fieldPathIndexByTypeName[fieldType.name]; - fieldPath.push(field); + fieldPath.push({ + fieldStr: `${inputObj}.${field.name}`, + astNode: field.astNode, + }); if (cycleIndex === undefined) { detectCycleRecursive(fieldType); } else { const cyclePath = fieldPath.slice(cycleIndex); - const pathStr = cyclePath.map((fieldObj) => fieldObj.name).join('.'); + const pathStr = cyclePath + .map((fieldObj) => fieldObj.fieldStr) + .join(', '); context.reportError( - `Cannot reference Input Object "${fieldType.name}" within itself through a series of non-null fields: "${pathStr}".`, + `Invalid circular reference. The Input Object ${fieldType} references itself ${ + cyclePath.length > 1 + ? 'via the non-null fields:' + : 'in the non-null field' + } ${pathStr}.`, cyclePath.map((fieldObj) => fieldObj.astNode), ); } @@ -621,6 +773,161 @@ function createInputObjectCircularRefsValidator( } } +function createInputObjectDefaultValueCircularRefsValidator( + context: SchemaValidationContext, +): (inputObj: GraphQLInputObjectType) => void { + // Modified copy of algorithm from 'src/validation/rules/NoFragmentCycles.js'. + // Tracks already visited types to maintain O(N) and to ensure that cycles + // are not redundantly reported. + const visitedFields = Object.create(null); + + // Array of keys for fields and default values used to produce meaningful errors. + const fieldPath: Array< + [fieldStr: string, defaultValue: ConstValueNode | undefined] + > = []; + + // Position in the path + const fieldPathIndex: ObjMap = Object.create(null); + + // This does a straight-forward DFS to find cycles. + // It does not terminate when a cycle was found but continues to explore + // the graph to find all possible cycles. + return function validateInputObjectDefaultValueCircularRefs( + inputObj: GraphQLInputObjectType, + ): void { + // Start with an empty object as a way to visit every field in this input + // object type and apply every default value. + return detectValueDefaultValueCycle(inputObj, {}); + }; + + function detectValueDefaultValueCycle( + inputObj: GraphQLInputObjectType, + defaultValue: unknown, + ): void { + // If the value is a List, recursively check each entry for a cycle. + // Otherwise, only object values can contain a cycle. + if (isIterableObject(defaultValue)) { + for (const itemValue of defaultValue) { + detectValueDefaultValueCycle(inputObj, itemValue); + } + return; + } else if (!isObjectLike(defaultValue)) { + return; + } + + // Check each defined field for a cycle. + for (const field of Object.values(inputObj.getFields())) { + const namedFieldType = getNamedType(field.type); + + // Only input object type fields can result in a cycle. + if (!isInputObjectType(namedFieldType)) { + continue; + } + + if (Object.hasOwn(defaultValue, field.name)) { + // If the provided value has this field defined, recursively check it + // for cycles. + detectValueDefaultValueCycle(namedFieldType, defaultValue[field.name]); + } else { + // Otherwise check this field's default value for cycles. + detectFieldDefaultValueCycle( + field, + namedFieldType, + `${inputObj}.${field.name}`, + ); + } + } + } + + function detectLiteralDefaultValueCycle( + inputObj: GraphQLInputObjectType, + defaultValue: ConstValueNode, + ): void { + // If the value is a List, recursively check each entry for a cycle. + // Otherwise, only object values can contain a cycle. + if (defaultValue.kind === Kind.LIST) { + for (const itemLiteral of defaultValue.values) { + detectLiteralDefaultValueCycle(inputObj, itemLiteral); + } + return; + } else if (defaultValue.kind !== Kind.OBJECT) { + return; + } + + // Check each defined field for a cycle. + const fieldNodes = keyMap(defaultValue.fields, (field) => field.name.value); + for (const field of Object.values(inputObj.getFields())) { + const namedFieldType = getNamedType(field.type); + + // Only input object type fields can result in a cycle. + if (!isInputObjectType(namedFieldType)) { + continue; + } + + if (Object.hasOwn(fieldNodes, field.name)) { + // If the provided value has this field defined, recursively check it + // for cycles. + detectLiteralDefaultValueCycle( + namedFieldType, + fieldNodes[field.name].value, + ); + } else { + // Otherwise check this field's default value for cycles. + detectFieldDefaultValueCycle( + field, + namedFieldType, + `${inputObj}.${field.name}`, + ); + } + } + } + + function detectFieldDefaultValueCycle( + field: GraphQLInputField, + fieldType: GraphQLInputObjectType, + fieldStr: string, + ): void { + // Only a field with a default value can result in a cycle. + const defaultInput = field.default; + if (defaultInput === undefined) { + return; + } + + // Check to see if there is cycle. + const cycleIndex = fieldPathIndex[fieldStr]; + if (cycleIndex !== undefined && cycleIndex > 0) { + context.reportError( + `Invalid circular reference. The default value of Input Object field ${fieldStr} references itself${ + cycleIndex < fieldPath.length + ? ` via the default values of: ${fieldPath + .slice(cycleIndex) + .map(([stringForMessage]) => stringForMessage) + .join(', ')}` + : '' + }.`, + fieldPath.slice(cycleIndex - 1).map(([, node]) => node), + ); + return; + } + + // Recurse into this field's default value once, tracking the path. + if (visitedFields[fieldStr] === undefined) { + visitedFields[fieldStr] = true; + fieldPathIndex[fieldStr] = fieldPath.push([ + fieldStr, + field.astNode?.defaultValue, + ]); + if (defaultInput.literal) { + detectLiteralDefaultValueCycle(fieldType, defaultInput.literal); + } else { + detectValueDefaultValueCycle(fieldType, defaultInput.value); + } + fieldPath.pop(); + fieldPathIndex[fieldStr] = undefined; + } + } +} + function getAllImplementsInterfaceNodes( type: GraphQLObjectType | GraphQLInterfaceType, iface: GraphQLInterfaceType, @@ -633,9 +940,8 @@ function getAllImplementsInterfaceNodes( | InterfaceTypeExtensionNode > = astNode != null ? [astNode, ...extensionASTNodes] : extensionASTNodes; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 return nodes - .flatMap((typeNode) => /* c8 ignore next */ typeNode.interfaces ?? []) + .flatMap((typeNode) => typeNode.interfaces ?? []) .filter((ifaceNode) => ifaceNode.name.value === iface.name); } @@ -647,7 +953,6 @@ function getUnionMemberTypeNodes( const nodes: ReadonlyArray = astNode != null ? [astNode, ...extensionASTNodes] : extensionASTNodes; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 return nodes .flatMap((unionNode) => /* c8 ignore next */ unionNode.types ?? []) .filter((typeNode) => typeNode.name.value === typeName); diff --git a/src/utilities/TypeInfo.ts b/src/utilities/TypeInfo.ts index ffcc964b4a..22255faf64 100644 --- a/src/utilities/TypeInfo.ts +++ b/src/utilities/TypeInfo.ts @@ -1,6 +1,11 @@ import type { Maybe } from '../jsutils/Maybe.js'; -import type { ASTNode, FieldNode } from '../language/ast.js'; +import type { + ASTNode, + DocumentNode, + FragmentDefinitionNode, + VariableDefinitionNode, +} from '../language/ast.js'; import { isNode } from '../language/ast.js'; import { Kind } from '../language/kinds.js'; import type { ASTVisitor } from '../language/visitor.js'; @@ -32,6 +37,11 @@ import type { GraphQLSchema } from '../type/schema.js'; import { typeFromAST } from './typeFromAST.js'; +export interface FragmentSignature { + readonly definition: FragmentDefinitionNode; + readonly variableDefinitions: Map; +} + /** * TypeInfo is a utility class which, given a GraphQL schema, can keep track * of the current field and type definitions at any point in a GraphQL document @@ -43,11 +53,16 @@ export class TypeInfo { private _parentTypeStack: Array>; private _inputTypeStack: Array>; private _fieldDefStack: Array>>; - private _defaultValueStack: Array>; + private _defaultValueStack: Array; private _directive: Maybe; private _argument: Maybe; private _enumValue: Maybe; - private _getFieldDef: GetFieldDefFn; + private _fragmentSignaturesByName: ( + fragmentName: string, + ) => Maybe; + + private _fragmentSignature: Maybe; + private _fragmentArgument: Maybe; constructor( schema: GraphQLSchema, @@ -56,9 +71,9 @@ export class TypeInfo { * beginning somewhere other than documents. */ initialType?: Maybe, - - /** @deprecated will be removed in 17.0.0 */ - getFieldDefFn?: GetFieldDefFn, + fragmentSignatures?: Maybe< + (fragmentName: string) => Maybe + >, ) { this._schema = schema; this._typeStack = []; @@ -69,7 +84,9 @@ export class TypeInfo { this._directive = null; this._argument = null; this._enumValue = null; - this._getFieldDef = getFieldDefFn ?? getFieldDef; + this._fragmentSignaturesByName = fragmentSignatures ?? (() => null); + this._fragmentSignature = null; + this._fragmentArgument = null; if (initialType) { if (isInputType(initialType)) { this._inputTypeStack.push(initialType); @@ -107,7 +124,7 @@ export class TypeInfo { return this._fieldDefStack.at(-1); } - getDefaultValue(): Maybe { + getDefaultValue(): unknown { return this._defaultValueStack.at(-1); } @@ -119,6 +136,20 @@ export class TypeInfo { return this._argument; } + getFragmentSignature(): Maybe { + return this._fragmentSignature; + } + + getFragmentSignatureByName(): ( + fragmentName: string, + ) => Maybe { + return this._fragmentSignaturesByName; + } + + getFragmentArgument(): Maybe { + return this._fragmentArgument; + } + getEnumValue(): Maybe { return this._enumValue; } @@ -130,6 +161,12 @@ export class TypeInfo { // checked before continuing since TypeInfo is used as part of validation // which occurs before guarantees of schema and document validity. switch (node.kind) { + case Kind.DOCUMENT: { + const fragmentSignatures = getFragmentSignatures(node); + this._fragmentSignaturesByName = (fragmentName: string) => + fragmentSignatures.get(fragmentName); + break; + } case Kind.SELECTION_SET: { const namedType: unknown = getNamedType(this.getType()); this._parentTypeStack.push( @@ -142,7 +179,7 @@ export class TypeInfo { let fieldDef; let fieldType: unknown; if (parentType) { - fieldDef = this._getFieldDef(schema, parentType, node); + fieldDef = schema.getField(parentType, node.name.value); if (fieldDef) { fieldType = fieldDef.type; } @@ -159,6 +196,12 @@ export class TypeInfo { this._typeStack.push(isObjectType(rootType) ? rootType : undefined); break; } + case Kind.FRAGMENT_SPREAD: { + this._fragmentSignature = this.getFragmentSignatureByName()( + node.name.value, + ); + break; + } case Kind.INLINE_FRAGMENT: case Kind.FRAGMENT_DEFINITION: { const typeConditionAST = node.typeCondition; @@ -188,7 +231,22 @@ export class TypeInfo { } } this._argument = argDef; - this._defaultValueStack.push(argDef ? argDef.defaultValue : undefined); + this._defaultValueStack.push( + argDef?.default ?? argDef?.defaultValue ?? undefined, + ); + this._inputTypeStack.push(isInputType(argType) ? argType : undefined); + break; + } + case Kind.FRAGMENT_ARGUMENT: { + const fragmentSignature = this.getFragmentSignature(); + const argDef = fragmentSignature?.variableDefinitions.get( + node.name.value, + ); + this._fragmentArgument = argDef; + let argType: unknown; + if (argDef) { + argType = typeFromAST(this._schema, argDef.type); + } this._inputTypeStack.push(isInputType(argType) ? argType : undefined); break; } @@ -213,7 +271,7 @@ export class TypeInfo { } } this._defaultValueStack.push( - inputField ? inputField.defaultValue : undefined, + inputField?.default ?? inputField?.defaultValue ?? undefined, ); this._inputTypeStack.push( isInputType(inputFieldType) ? inputFieldType : undefined, @@ -236,6 +294,10 @@ export class TypeInfo { leave(node: ASTNode) { switch (node.kind) { + case Kind.DOCUMENT: + this._fragmentSignaturesByName = /* c8 ignore start */ () => + null /* c8 ignore end */; + break; case Kind.SELECTION_SET: this._parentTypeStack.pop(); break; @@ -246,6 +308,9 @@ export class TypeInfo { case Kind.DIRECTIVE: this._directive = null; break; + case Kind.FRAGMENT_SPREAD: + this._fragmentSignature = null; + break; case Kind.OPERATION_DEFINITION: case Kind.INLINE_FRAGMENT: case Kind.FRAGMENT_DEFINITION: @@ -259,6 +324,12 @@ export class TypeInfo { this._defaultValueStack.pop(); this._inputTypeStack.pop(); break; + case Kind.FRAGMENT_ARGUMENT: { + this._fragmentArgument = null; + this._defaultValueStack.pop(); + this._inputTypeStack.pop(); + break; + } case Kind.LIST: case Kind.OBJECT_FIELD: this._defaultValueStack.pop(); @@ -273,18 +344,23 @@ export class TypeInfo { } } -type GetFieldDefFn = ( - schema: GraphQLSchema, - parentType: GraphQLCompositeType, - fieldNode: FieldNode, -) => Maybe>; - -function getFieldDef( - schema: GraphQLSchema, - parentType: GraphQLCompositeType, - fieldNode: FieldNode, -) { - return schema.getField(parentType, fieldNode.name.value); +function getFragmentSignatures( + document: DocumentNode, +): Map { + const fragmentSignatures = new Map(); + for (const definition of document.definitions) { + if (definition.kind === Kind.FRAGMENT_DEFINITION) { + const variableDefinitions = new Map(); + if (definition.variableDefinitions) { + for (const varDef of definition.variableDefinitions) { + variableDefinitions.set(varDef.variable.name.value, varDef); + } + } + const signature = { definition, variableDefinitions }; + fragmentSignatures.set(definition.name.value, signature); + } + } + return fragmentSignatures; } /** diff --git a/src/utilities/__tests__/TypeInfo-test.ts b/src/utilities/__tests__/TypeInfo-test.ts index 971316f8b4..cc129287c3 100644 --- a/src/utilities/__tests__/TypeInfo-test.ts +++ b/src/utilities/__tests__/TypeInfo-test.ts @@ -68,6 +68,9 @@ describe('TypeInfo', () => { expect(typeInfo.getFieldDef()).to.equal(undefined); expect(typeInfo.getDefaultValue()).to.equal(undefined); expect(typeInfo.getDirective()).to.equal(null); + expect(typeInfo.getFragmentSignature()).to.equal(null); + expect(typeInfo.getFragmentSignatureByName()('')).to.equal(null); + expect(typeInfo.getFragmentArgument()).to.equal(null); expect(typeInfo.getArgument()).to.equal(null); expect(typeInfo.getEnumValue()).to.equal(null); }); @@ -515,4 +518,221 @@ describe('visitWithTypeInfo', () => { ['leave', 'SelectionSet', null, 'Human', 'Human'], ]); }); + + it('supports traversals of fragment arguments', () => { + const typeInfo = new TypeInfo(testSchema); + + const ast = parse( + ` + query { + ...Foo(x: 4) + ...Bar + } + fragment Foo( + $x: ID! + ) on QueryRoot { + human(id: $x) { name } + } + `, + { experimentalFragmentArguments: true }, + ); + + const visited: Array = []; + visit( + ast, + visitWithTypeInfo(typeInfo, { + enter(node) { + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + 'enter', + node.kind, + node.kind === 'Name' ? node.value : null, + String(type), + String(inputType), + ]); + }, + leave(node) { + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + 'leave', + node.kind, + node.kind === 'Name' ? node.value : null, + String(type), + String(inputType), + ]); + }, + }), + ); + + expect(visited).to.deep.equal([ + ['enter', 'Document', null, 'undefined', 'undefined'], + ['enter', 'OperationDefinition', null, 'QueryRoot', 'undefined'], + ['enter', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['enter', 'FragmentSpread', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['enter', 'FragmentArgument', null, 'QueryRoot', 'ID!'], + ['enter', 'Name', 'x', 'QueryRoot', 'ID!'], + ['leave', 'Name', 'x', 'QueryRoot', 'ID!'], + ['enter', 'IntValue', null, 'QueryRoot', 'ID!'], + ['leave', 'IntValue', null, 'QueryRoot', 'ID!'], + ['leave', 'FragmentArgument', null, 'QueryRoot', 'ID!'], + ['leave', 'FragmentSpread', null, 'QueryRoot', 'undefined'], + ['enter', 'FragmentSpread', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'Bar', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'Bar', 'QueryRoot', 'undefined'], + ['leave', 'FragmentSpread', null, 'QueryRoot', 'undefined'], + ['leave', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['leave', 'OperationDefinition', null, 'QueryRoot', 'undefined'], + ['enter', 'FragmentDefinition', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['enter', 'VariableDefinition', null, 'QueryRoot', 'ID!'], + ['enter', 'Variable', null, 'QueryRoot', 'ID!'], + ['enter', 'Name', 'x', 'QueryRoot', 'ID!'], + ['leave', 'Name', 'x', 'QueryRoot', 'ID!'], + ['leave', 'Variable', null, 'QueryRoot', 'ID!'], + ['enter', 'NonNullType', null, 'QueryRoot', 'ID!'], + ['enter', 'NamedType', null, 'QueryRoot', 'ID!'], + ['enter', 'Name', 'ID', 'QueryRoot', 'ID!'], + ['leave', 'Name', 'ID', 'QueryRoot', 'ID!'], + ['leave', 'NamedType', null, 'QueryRoot', 'ID!'], + ['leave', 'NonNullType', null, 'QueryRoot', 'ID!'], + ['leave', 'VariableDefinition', null, 'QueryRoot', 'ID!'], + ['enter', 'NamedType', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'QueryRoot', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'QueryRoot', 'QueryRoot', 'undefined'], + ['leave', 'NamedType', null, 'QueryRoot', 'undefined'], + ['enter', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['enter', 'Field', null, 'Human', 'undefined'], + ['enter', 'Name', 'human', 'Human', 'undefined'], + ['leave', 'Name', 'human', 'Human', 'undefined'], + ['enter', 'Argument', null, 'Human', 'ID'], + ['enter', 'Name', 'id', 'Human', 'ID'], + ['leave', 'Name', 'id', 'Human', 'ID'], + ['enter', 'Variable', null, 'Human', 'ID'], + ['enter', 'Name', 'x', 'Human', 'ID'], + ['leave', 'Name', 'x', 'Human', 'ID'], + ['leave', 'Variable', null, 'Human', 'ID'], + ['leave', 'Argument', null, 'Human', 'ID'], + ['enter', 'SelectionSet', null, 'Human', 'undefined'], + ['enter', 'Field', null, 'String', 'undefined'], + ['enter', 'Name', 'name', 'String', 'undefined'], + ['leave', 'Name', 'name', 'String', 'undefined'], + ['leave', 'Field', null, 'String', 'undefined'], + ['leave', 'SelectionSet', null, 'Human', 'undefined'], + ['leave', 'Field', null, 'Human', 'undefined'], + ['leave', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['leave', 'FragmentDefinition', null, 'QueryRoot', 'undefined'], + ['leave', 'Document', null, 'undefined', 'undefined'], + ]); + }); + + it('supports traversals of fragment arguments with default-value', () => { + const typeInfo = new TypeInfo(testSchema); + + const ast = parse( + ` + query { + ...Foo(x: null) + } + fragment Foo( + $x: ID = 4 + ) on QueryRoot { + human(id: $x) { name } + } + `, + { experimentalFragmentArguments: true }, + ); + + const visited: Array = []; + visit( + ast, + visitWithTypeInfo(typeInfo, { + enter(node) { + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + 'enter', + node.kind, + node.kind === 'Name' ? node.value : null, + String(type), + String(inputType), + ]); + }, + leave(node) { + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + 'leave', + node.kind, + node.kind === 'Name' ? node.value : null, + String(type), + String(inputType), + ]); + }, + }), + ); + + expect(visited).to.deep.equal([ + ['enter', 'Document', null, 'undefined', 'undefined'], + ['enter', 'OperationDefinition', null, 'QueryRoot', 'undefined'], + ['enter', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['enter', 'FragmentSpread', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['enter', 'FragmentArgument', null, 'QueryRoot', 'ID'], + ['enter', 'Name', 'x', 'QueryRoot', 'ID'], + ['leave', 'Name', 'x', 'QueryRoot', 'ID'], + ['enter', 'NullValue', null, 'QueryRoot', 'ID'], + ['leave', 'NullValue', null, 'QueryRoot', 'ID'], + ['leave', 'FragmentArgument', null, 'QueryRoot', 'ID'], + ['leave', 'FragmentSpread', null, 'QueryRoot', 'undefined'], + ['leave', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['leave', 'OperationDefinition', null, 'QueryRoot', 'undefined'], + ['enter', 'FragmentDefinition', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'Foo', 'QueryRoot', 'undefined'], + ['enter', 'VariableDefinition', null, 'QueryRoot', 'ID'], + ['enter', 'Variable', null, 'QueryRoot', 'ID'], + ['enter', 'Name', 'x', 'QueryRoot', 'ID'], + ['leave', 'Name', 'x', 'QueryRoot', 'ID'], + ['leave', 'Variable', null, 'QueryRoot', 'ID'], + ['enter', 'NamedType', null, 'QueryRoot', 'ID'], + ['enter', 'Name', 'ID', 'QueryRoot', 'ID'], + ['leave', 'Name', 'ID', 'QueryRoot', 'ID'], + ['leave', 'NamedType', null, 'QueryRoot', 'ID'], + ['enter', 'IntValue', null, 'QueryRoot', 'ID'], + ['leave', 'IntValue', null, 'QueryRoot', 'ID'], + ['leave', 'VariableDefinition', null, 'QueryRoot', 'ID'], + ['enter', 'NamedType', null, 'QueryRoot', 'undefined'], + ['enter', 'Name', 'QueryRoot', 'QueryRoot', 'undefined'], + ['leave', 'Name', 'QueryRoot', 'QueryRoot', 'undefined'], + ['leave', 'NamedType', null, 'QueryRoot', 'undefined'], + ['enter', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['enter', 'Field', null, 'Human', 'undefined'], + ['enter', 'Name', 'human', 'Human', 'undefined'], + ['leave', 'Name', 'human', 'Human', 'undefined'], + ['enter', 'Argument', null, 'Human', 'ID'], + ['enter', 'Name', 'id', 'Human', 'ID'], + ['leave', 'Name', 'id', 'Human', 'ID'], + ['enter', 'Variable', null, 'Human', 'ID'], + ['enter', 'Name', 'x', 'Human', 'ID'], + ['leave', 'Name', 'x', 'Human', 'ID'], + ['leave', 'Variable', null, 'Human', 'ID'], + ['leave', 'Argument', null, 'Human', 'ID'], + ['enter', 'SelectionSet', null, 'Human', 'undefined'], + ['enter', 'Field', null, 'String', 'undefined'], + ['enter', 'Name', 'name', 'String', 'undefined'], + ['leave', 'Name', 'name', 'String', 'undefined'], + ['leave', 'Field', null, 'String', 'undefined'], + ['leave', 'SelectionSet', null, 'Human', 'undefined'], + ['leave', 'Field', null, 'Human', 'undefined'], + ['leave', 'SelectionSet', null, 'QueryRoot', 'undefined'], + ['leave', 'FragmentDefinition', null, 'QueryRoot', 'undefined'], + ['leave', 'Document', null, 'undefined', 'undefined'], + ]); + }); }); diff --git a/src/utilities/__tests__/astFromValue-test.ts b/src/utilities/__tests__/astFromValue-test.ts index 0f9d474256..c5aba4a956 100644 --- a/src/utilities/__tests__/astFromValue-test.ts +++ b/src/utilities/__tests__/astFromValue-test.ts @@ -18,6 +18,7 @@ import { import { astFromValue } from '../astFromValue.js'; +/** @deprecated use `valueToLiteral()` instead with care to operate on external values - `astFromValue()` will be removed in v18 */ describe('astFromValue', () => { it('converts boolean values to ASTs', () => { expect(astFromValue(true, GraphQLBoolean)).to.deep.equal({ @@ -192,10 +193,10 @@ describe('astFromValue', () => { expect(astFromValue(undefined, GraphQLID)).to.deep.equal(null); }); - it('converts using serialize from a custom scalar type', () => { + it('converts using coerceOutputValue from a custom scalar type', () => { const passthroughScalar = new GraphQLScalarType({ name: 'PassthroughScalar', - serialize(value) { + coerceOutputValue(value) { return value; }, }); @@ -214,7 +215,7 @@ describe('astFromValue', () => { const returnNullScalar = new GraphQLScalarType({ name: 'ReturnNullScalar', - serialize() { + coerceOutputValue() { return null; }, }); @@ -225,7 +226,7 @@ describe('astFromValue', () => { const returnCustomClassScalar = new GraphQLScalarType({ name: 'ReturnCustomClassScalar', - serialize() { + coerceOutputValue() { return new SomeClass(); }, }); diff --git a/src/utilities/__tests__/buildASTSchema-test.ts b/src/utilities/__tests__/buildASTSchema-test.ts index e199abc2b3..5a794a1203 100644 --- a/src/utilities/__tests__/buildASTSchema-test.ts +++ b/src/utilities/__tests__/buildASTSchema-test.ts @@ -339,7 +339,7 @@ describe('Schema Builder', () => { const definition = parse(sdl).definitions[0]; expect( definition.kind === 'InterfaceTypeDefinition' && definition.interfaces, - ).to.deep.equal([], 'The interfaces property must be an empty array.'); + ).to.deep.equal(undefined, 'The interfaces property must not be defined.'); expect(cycleSDL(sdl)).to.equal(sdl); }); diff --git a/src/utilities/__tests__/buildClientSchema-test.ts b/src/utilities/__tests__/buildClientSchema-test.ts index 818198bf7b..00d99a0c8a 100644 --- a/src/utilities/__tests__/buildClientSchema-test.ts +++ b/src/utilities/__tests__/buildClientSchema-test.ts @@ -377,32 +377,35 @@ describe('Type System: build schema from introspection', () => { // Client types do not get server-only values, so `value` mirrors `name`, // rather than using the integers defined in the "server" schema. - expect(clientFoodEnum.getValues()).to.deep.equal([ - { - name: 'VEGETABLES', - description: 'Foods that are vegetables.', - value: 'VEGETABLES', - deprecationReason: null, - extensions: {}, - astNode: undefined, - }, - { - name: 'FRUITS', - description: null, - value: 'FRUITS', - deprecationReason: null, - extensions: {}, - astNode: undefined, - }, - { - name: 'OILS', - description: null, - value: 'OILS', - deprecationReason: 'Too fatty', - extensions: {}, - astNode: undefined, - }, - ]); + const values = clientFoodEnum.getValues(); + expect(values).to.have.lengthOf(3); + + expect(values[0]).to.deep.include({ + name: 'VEGETABLES', + description: 'Foods that are vegetables.', + value: 'VEGETABLES', + deprecationReason: null, + extensions: {}, + astNode: undefined, + }); + + expect(values[1]).to.deep.include({ + name: 'FRUITS', + description: null, + value: 'FRUITS', + deprecationReason: null, + extensions: {}, + astNode: undefined, + }); + + expect(values[2]).to.deep.include({ + name: 'OILS', + description: null, + value: 'OILS', + deprecationReason: 'Too fatty', + extensions: {}, + astNode: undefined, + }); }); it('builds a schema with an input object', () => { @@ -439,6 +442,7 @@ describe('Type System: build schema from introspection', () => { } type Query { + defaultID(intArg: ID = "123"): String defaultInt(intArg: Int = 30): String defaultList(listArg: [Int] = [1, 2, 3]): String defaultObject(objArg: Geo = { lat: 37.485, lon: -122.148 }): String @@ -571,6 +575,21 @@ describe('Type System: build schema from introspection', () => { expect(cycleIntrospection(sdl)).to.equal(sdl); }); + it('builds a schema with @oneOf directive', () => { + const sdl = dedent` + type Query { + someField(someArg: SomeInputObject): String + } + + input SomeInputObject @oneOf { + someInputField1: String + someInputField2: String + } + `; + + expect(cycleIntrospection(sdl)).to.equal(sdl); + }); + it('can use client schema for limited execution', () => { const schema = buildSchema(` scalar CustomScalar @@ -594,6 +613,28 @@ describe('Type System: build schema from introspection', () => { expect(result.data).to.deep.equal({ foo: 'bar' }); }); + it('can use client schema for execution if resolvers are added', () => { + const schema = buildSchema(` + type Query { + foo(bar: String = "abc"): String + } + `); + + const introspection = introspectionFromSchema(schema); + const clientSchema = buildClientSchema(introspection); + + const QueryType: GraphQLObjectType = clientSchema.getType('Query') as any; + QueryType.getFields().foo.resolve = (_value, args) => args.bar; + + const result = graphqlSync({ + schema: clientSchema, + source: '{ foo }', + }); + + expect(result.data).to.deep.equal({ foo: 'abc' }); + expect(result.data).to.deep.equal({ foo: 'abc' }); + }); + it('can build invalid schema', () => { const schema = buildSchema('type Query', { assumeValid: true }); @@ -678,7 +719,7 @@ describe('Type System: build schema from introspection', () => { delete introspection.__schema.queryType.name; expect(() => buildClientSchema(introspection)).to.throw( - 'Unknown type reference: {}.', + 'Unknown type reference: { kind: "OBJECT" }.', ); }); diff --git a/src/utilities/__tests__/coerceInputValue-test.ts b/src/utilities/__tests__/coerceInputValue-test.ts index 7712c91a39..963474ed7e 100644 --- a/src/utilities/__tests__/coerceInputValue-test.ts +++ b/src/utilities/__tests__/coerceInputValue-test.ts @@ -1,6 +1,15 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; +import { identityFunc } from '../../jsutils/identityFunc.js'; +import { invariant } from '../../jsutils/invariant.js'; +import type { ReadOnlyObjMap } from '../../jsutils/ObjMap.js'; + +import { Kind } from '../../language/kinds.js'; +import { Parser, parseValue } from '../../language/parser.js'; +import { print } from '../../language/printer.js'; +import { TokenKind } from '../../language/tokenKind.js'; + import type { GraphQLInputType } from '../../type/definition.js'; import { GraphQLEnumType, @@ -9,82 +18,53 @@ import { GraphQLNonNull, GraphQLScalarType, } from '../../type/definition.js'; -import { GraphQLInt } from '../../type/scalars.js'; - -import { coerceInputValue } from '../coerceInputValue.js'; - -interface CoerceResult { - value: unknown; - errors: ReadonlyArray; -} - -interface CoerceError { - path: ReadonlyArray; - value: unknown; - error: string; -} - -function coerceValue( - inputValue: unknown, - type: GraphQLInputType, -): CoerceResult { - const errors: Array = []; - const value = coerceInputValue( - inputValue, - type, - (path, invalidValue, error) => { - errors.push({ path, value: invalidValue, error: error.message }); - }, - ); - - return { errors, value }; -} +import { + GraphQLBoolean, + GraphQLFloat, + GraphQLID, + GraphQLInt, + GraphQLString, +} from '../../type/scalars.js'; +import { GraphQLSchema } from '../../type/schema.js'; -function expectValue(result: CoerceResult) { - expect(result.errors).to.deep.equal([]); - return expect(result.value); -} +import type { VariableValues } from '../../execution/values.js'; +import { getVariableValues } from '../../execution/values.js'; -function expectErrors(result: CoerceResult) { - return expect(result.errors); -} +import { + coerceDefaultValue, + coerceInputLiteral, + coerceInputValue, +} from '../coerceInputValue.js'; describe('coerceInputValue', () => { + function test( + inputValue: unknown, + type: GraphQLInputType, + expected: unknown, + ) { + expect(coerceInputValue(inputValue, type)).to.deep.equal(expected); + } + describe('for GraphQLNonNull', () => { const TestNonNull = new GraphQLNonNull(GraphQLInt); - it('returns no error for non-null value', () => { - const result = coerceValue(1, TestNonNull); - expectValue(result).to.equal(1); + it('returns for a non-null value', () => { + test(1, TestNonNull, 1); }); - it('returns an error for undefined value', () => { - const result = coerceValue(undefined, TestNonNull); - expectErrors(result).to.deep.equal([ - { - error: 'Expected non-nullable type "Int!" not to be null.', - path: [], - value: undefined, - }, - ]); + it('invalid for undefined value', () => { + test(undefined, TestNonNull, undefined); }); - it('returns an error for null value', () => { - const result = coerceValue(null, TestNonNull); - expectErrors(result).to.deep.equal([ - { - error: 'Expected non-nullable type "Int!" not to be null.', - path: [], - value: null, - }, - ]); + it('invalid for null value', () => { + test(null, TestNonNull, undefined); }); }); describe('for GraphQLScalar', () => { const TestScalar = new GraphQLScalarType({ name: 'TestScalar', - parseValue(input: any) { + coerceInputValue(input: any) { if (input.error != null) { throw new Error(input.error); } @@ -92,42 +72,27 @@ describe('coerceInputValue', () => { }, }); - it('returns no error for valid input', () => { - const result = coerceValue({ value: 1 }, TestScalar); - expectValue(result).to.equal(1); + it('returns for valid input', () => { + test({ value: 1 }, TestScalar, 1); }); - it('returns no error for null result', () => { - const result = coerceValue({ value: null }, TestScalar); - expectValue(result).to.equal(null); + it('returns for null result', () => { + test({ value: null }, TestScalar, null); }); - it('returns no error for NaN result', () => { - const result = coerceValue({ value: NaN }, TestScalar); - expectValue(result).to.satisfy(Number.isNaN); + it('returns for NaN result', () => { + expect(coerceInputValue({ value: NaN }, TestScalar)).to.satisfy( + Number.isNaN, + ); }); - it('returns an error for undefined result', () => { - const result = coerceValue({ value: undefined }, TestScalar); - expectErrors(result).to.deep.equal([ - { - error: 'Expected type "TestScalar".', - path: [], - value: { value: undefined }, - }, - ]); + it('invalid for undefined result', () => { + test({ value: undefined }, TestScalar, undefined); }); - it('returns a thrown error', () => { + it('invalid for undefined result', () => { const inputValue = { error: 'Some error message' }; - const result = coerceValue(inputValue, TestScalar); - expectErrors(result).to.deep.equal([ - { - error: 'Expected type "TestScalar". Some error message', - path: [], - value: { error: 'Some error message' }, - }, - ]); + test(inputValue, TestScalar, undefined); }); }); @@ -141,44 +106,18 @@ describe('coerceInputValue', () => { }); it('returns no error for a known enum name', () => { - const fooResult = coerceValue('FOO', TestEnum); - expectValue(fooResult).to.equal('InternalFoo'); + test('FOO', TestEnum, 'InternalFoo'); - const barResult = coerceValue('BAR', TestEnum); - expectValue(barResult).to.equal(123456789); + test('BAR', TestEnum, 123456789); }); - it('returns an error for misspelled enum value', () => { - const result = coerceValue('foo', TestEnum); - expectErrors(result).to.deep.equal([ - { - error: - 'Value "foo" does not exist in "TestEnum" enum. Did you mean the enum value "FOO"?', - path: [], - value: 'foo', - }, - ]); + it('invalid for misspelled enum value', () => { + test('foo', TestEnum, undefined); }); - it('returns an error for incorrect value type', () => { - const result1 = coerceValue(123, TestEnum); - expectErrors(result1).to.deep.equal([ - { - error: 'Enum "TestEnum" cannot represent non-string value: 123.', - path: [], - value: 123, - }, - ]); - - const result2 = coerceValue({ field: 'value' }, TestEnum); - expectErrors(result2).to.deep.equal([ - { - error: - 'Enum "TestEnum" cannot represent non-string value: { field: "value" }.', - path: [], - value: { field: 'value' }, - }, - ]); + it('invalid for incorrect value type', () => { + test(123, TestEnum, undefined); + test({ field: 'value' }, TestEnum, undefined); }); }); @@ -192,84 +131,27 @@ describe('coerceInputValue', () => { }); it('returns no error for a valid input', () => { - const result = coerceValue({ foo: 123 }, TestInputObject); - expectValue(result).to.deep.equal({ foo: 123 }); + test({ foo: 123 }, TestInputObject, { foo: 123 }); }); - it('returns an error for a non-object type', () => { - const result = coerceValue(123, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Expected type "TestInputObject" to be an object.', - path: [], - value: 123, - }, - ]); + it('invalid for a non-object type', () => { + test(123, TestInputObject, undefined); }); - it('returns an error for an invalid field', () => { - const result = coerceValue({ foo: NaN }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Int cannot represent non-integer value: NaN', - path: ['foo'], - value: NaN, - }, - ]); + it('invalid for an invalid field', () => { + test({ foo: NaN }, TestInputObject, undefined); }); - it('returns multiple errors for multiple invalid fields', () => { - const result = coerceValue({ foo: 'abc', bar: 'def' }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Int cannot represent non-integer value: "abc"', - path: ['foo'], - value: 'abc', - }, - { - error: 'Int cannot represent non-integer value: "def"', - path: ['bar'], - value: 'def', - }, - ]); + it('invalid for multiple invalid fields', () => { + test({ foo: 'abc', bar: 'def' }, TestInputObject, undefined); }); - it('returns error for a missing required field', () => { - const result = coerceValue({ bar: 123 }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Field "foo" of required type "Int!" was not provided.', - path: [], - value: { bar: 123 }, - }, - ]); + it('invalid for a missing required field', () => { + test({ bar: 123 }, TestInputObject, undefined); }); - it('returns error for an unknown field', () => { - const result = coerceValue( - { foo: 123, unknownField: 123 }, - TestInputObject, - ); - expectErrors(result).to.deep.equal([ - { - error: - 'Field "unknownField" is not defined by type "TestInputObject".', - path: [], - value: { foo: 123, unknownField: 123 }, - }, - ]); - }); - - it('returns error for a misspelled field', () => { - const result = coerceValue({ foo: 123, bart: 123 }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: - 'Field "bart" is not defined by type "TestInputObject". Did you mean "bar"?', - path: [], - value: { foo: 123, bart: 123 }, - }, - ]); + it('invalid for an unknown field', () => { + test({ foo: 123, unknownField: 123 }, TestInputObject, undefined); }); }); @@ -283,131 +165,55 @@ describe('coerceInputValue', () => { isOneOf: true, }); - it('returns no error for a valid input', () => { - const result = coerceValue({ foo: 123 }, TestInputObject); - expectValue(result).to.deep.equal({ foo: 123 }); - }); - - it('returns an error if more than one field is specified', () => { - const result = coerceValue({ foo: 123, bar: null }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: - 'Exactly one key must be specified for OneOf type "TestInputObject".', - path: [], - value: { foo: 123, bar: null }, - }, - ]); - }); - - it('returns an error the one field is null', () => { - const result = coerceValue({ bar: null }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Field "bar" must be non-null.', - path: ['bar'], - value: null, - }, - ]); + it('returns for valid input', () => { + test({ foo: 123 }, TestInputObject, { foo: 123 }); }); - it('returns an error for an invalid field', () => { - const result = coerceValue({ foo: NaN }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Int cannot represent non-integer value: NaN', - path: ['foo'], - value: NaN, - }, - ]); + it('invalid if more than one field is specified', () => { + test({ foo: 123, bar: null }, TestInputObject, undefined); }); - it('returns multiple errors for multiple invalid fields', () => { - const result = coerceValue({ foo: 'abc', bar: 'def' }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: 'Int cannot represent non-integer value: "abc"', - path: ['foo'], - value: 'abc', - }, - { - error: 'Int cannot represent non-integer value: "def"', - path: ['bar'], - value: 'def', - }, - { - error: - 'Exactly one key must be specified for OneOf type "TestInputObject".', - path: [], - value: { foo: 'abc', bar: 'def' }, - }, - ]); + it('invalid if the one field is null', () => { + test({ bar: null }, TestInputObject, undefined); }); - it('returns error for an unknown field', () => { - const result = coerceValue( - { foo: 123, unknownField: 123 }, - TestInputObject, - ); - expectErrors(result).to.deep.equal([ - { - error: - 'Field "unknownField" is not defined by type "TestInputObject".', - path: [], - value: { foo: 123, unknownField: 123 }, - }, - ]); + it('invalid for an invalid field', () => { + test({ foo: NaN }, TestInputObject, undefined); }); - it('returns error for a misspelled field', () => { - const result = coerceValue({ bart: 123 }, TestInputObject); - expectErrors(result).to.deep.equal([ - { - error: - 'Field "bart" is not defined by type "TestInputObject". Did you mean "bar"?', - path: [], - value: { bart: 123 }, - }, - { - error: - 'Exactly one key must be specified for OneOf type "TestInputObject".', - path: [], - value: { bart: 123 }, - }, - ]); + it('invalid for an unknown field', () => { + test({ foo: 123, unknownField: 123 }, TestInputObject, undefined); }); }); describe('for GraphQLInputObject with default value', () => { - const makeTestInputObject = (defaultValue: any) => + const makeTestInputObject = (defaultValue: unknown) => new GraphQLInputObjectType({ name: 'TestInputObject', fields: { foo: { type: new GraphQLScalarType({ name: 'TestScalar' }), - defaultValue, + default: { value: defaultValue }, }, }, }); it('returns no errors for valid input value', () => { - const result = coerceValue({ foo: 5 }, makeTestInputObject(7)); - expectValue(result).to.deep.equal({ foo: 5 }); + test({ foo: 5 }, makeTestInputObject(7), { foo: 5 }); }); it('returns object with default value', () => { - const result = coerceValue({}, makeTestInputObject(7)); - expectValue(result).to.deep.equal({ foo: 7 }); + test({}, makeTestInputObject(7), { foo: 7 }); }); it('returns null as value', () => { - const result = coerceValue({}, makeTestInputObject(null)); - expectValue(result).to.deep.equal({ foo: null }); + test({}, makeTestInputObject(null), { foo: null }); }); it('returns NaN as value', () => { - const result = coerceValue({}, makeTestInputObject(NaN)); - expectValue(result).to.have.property('foo').that.satisfy(Number.isNaN); + expect(coerceInputValue({}, makeTestInputObject(NaN))) + .to.have.property('foo') + .that.satisfy(Number.isNaN); }); }); @@ -415,8 +221,7 @@ describe('coerceInputValue', () => { const TestList = new GraphQLList(GraphQLInt); it('returns no error for a valid input', () => { - const result = coerceValue([1, 2, 3], TestList); - expectValue(result).to.deep.equal([1, 2, 3]); + test([1, 2, 3], TestList, [1, 2, 3]); }); it('returns no error for a valid iterable input', () => { @@ -426,29 +231,15 @@ describe('coerceInputValue', () => { yield 3; } - const result = coerceValue(listGenerator(), TestList); - expectValue(result).to.deep.equal([1, 2, 3]); + test(listGenerator(), TestList, [1, 2, 3]); }); - it('returns an error for an invalid input', () => { - const result = coerceValue([1, 'b', true, 4], TestList); - expectErrors(result).to.deep.equal([ - { - error: 'Int cannot represent non-integer value: "b"', - path: [1], - value: 'b', - }, - { - error: 'Int cannot represent non-integer value: true', - path: [2], - value: true, - }, - ]); + it('invalid for an invalid input', () => { + test([1, 'b', true, 4], TestList, undefined); }); it('returns a list for a non-list value', () => { - const result = coerceValue(42, TestList); - expectValue(result).to.deep.equal([42]); + test(42, TestList, [42]); }); it('returns a list for a non-list object value', () => { @@ -461,24 +252,15 @@ describe('coerceInputValue', () => { }), ); - const result = coerceValue({ length: 100500 }, TestListOfObjects); - expectValue(result).to.deep.equal([{ length: 100500 }]); + test({ length: 100500 }, TestListOfObjects, [{ length: 100500 }]); }); - it('returns an error for a non-list invalid value', () => { - const result = coerceValue('INVALID', TestList); - expectErrors(result).to.deep.equal([ - { - error: 'Int cannot represent non-integer value: "INVALID"', - path: [], - value: 'INVALID', - }, - ]); + it('invalid for a non-list invalid value', () => { + test('INVALID', TestList, undefined); }); it('returns null for a null value', () => { - const result = coerceValue(null, TestList); - expectValue(result).to.deep.equal(null); + test(null, TestList, null); }); }); @@ -486,49 +268,379 @@ describe('coerceInputValue', () => { const TestNestedList = new GraphQLList(new GraphQLList(GraphQLInt)); it('returns no error for a valid input', () => { - const result = coerceValue([[1], [2, 3]], TestNestedList); - expectValue(result).to.deep.equal([[1], [2, 3]]); + test([[1], [2, 3]], TestNestedList, [[1], [2, 3]]); }); it('returns a list for a non-list value', () => { - const result = coerceValue(42, TestNestedList); - expectValue(result).to.deep.equal([[42]]); + test(42, TestNestedList, [[42]]); }); it('returns null for a null value', () => { - const result = coerceValue(null, TestNestedList); - expectValue(result).to.deep.equal(null); + test(null, TestNestedList, null); }); it('returns nested lists for nested non-list values', () => { - const result = coerceValue([1, 2, 3], TestNestedList); - expectValue(result).to.deep.equal([[1], [2], [3]]); + test([1, 2, 3], TestNestedList, [[1], [2], [3]]); }); it('returns nested null for nested null values', () => { - const result = coerceValue([42, [null], null], TestNestedList); - expectValue(result).to.deep.equal([[42], [null], null]); + test([42, [null], null], TestNestedList, [[42], [null], null]); }); }); +}); - describe('with default onError', () => { - it('throw error without path', () => { - expect(() => - coerceInputValue(null, new GraphQLNonNull(GraphQLInt)), - ).to.throw( - 'Invalid value null: Expected non-nullable type "Int!" not to be null.', - ); +describe('coerceInputLiteral', () => { + function test( + valueText: string, + type: GraphQLInputType, + expected: unknown, + variableValues?: VariableValues, + ) { + const ast = parseValue(valueText); + const value = coerceInputLiteral(ast, type, variableValues); + expect(value).to.deep.equal(expected); + } + + function testWithVariables( + variableDefs: string, + inputs: ReadOnlyObjMap, + valueText: string, + type: GraphQLInputType, + expected: unknown, + ) { + const parser = new Parser(variableDefs); + parser.expectToken(TokenKind.SOF); + const variableValuesOrErrors = getVariableValues( + new GraphQLSchema({}), + parser.parseVariableDefinitions() ?? [], + inputs, + ); + invariant(variableValuesOrErrors.variableValues !== undefined); + test(valueText, type, expected, variableValuesOrErrors.variableValues); + } + + it('converts according to input coercion rules', () => { + test('true', GraphQLBoolean, true); + test('false', GraphQLBoolean, false); + test('123', GraphQLInt, 123); + test('123', GraphQLFloat, 123); + test('123.456', GraphQLFloat, 123.456); + test('"abc123"', GraphQLString, 'abc123'); + test('123456', GraphQLID, '123456'); + test('"123456"', GraphQLID, '123456'); + }); + + it('does not convert when input coercion rules reject a value', () => { + test('123', GraphQLBoolean, undefined); + test('123.456', GraphQLInt, undefined); + test('true', GraphQLInt, undefined); + test('"123"', GraphQLInt, undefined); + test('"123"', GraphQLFloat, undefined); + test('123', GraphQLString, undefined); + test('true', GraphQLString, undefined); + test('123.456', GraphQLString, undefined); + test('123.456', GraphQLID, undefined); + }); + + it('convert using coerceInputLiteral from a custom scalar type', () => { + const passthroughScalar = new GraphQLScalarType({ + name: 'PassthroughScalar', + coerceInputLiteral(node) { + invariant(node.kind === 'StringValue'); + return node.value; + }, + coerceInputValue: identityFunc, }); - it('throw error with path', () => { - expect(() => - coerceInputValue( - [null], - new GraphQLList(new GraphQLNonNull(GraphQLInt)), - ), - ).to.throw( - 'Invalid value null at "value[0]": Expected non-nullable type "Int!" not to be null.', - ); + test('"value"', passthroughScalar, 'value'); + + const printScalar = new GraphQLScalarType({ + name: 'PrintScalar', + coerceInputLiteral(node) { + return `~~~${print(node)}~~~`; + }, + coerceInputValue: identityFunc, + }); + + test('"value"', printScalar, '~~~"value"~~~'); + testWithVariables( + '($var: String)', + { var: 'value' }, + '{ field: $var }', + printScalar, + '~~~{ field: "value" }~~~', + ); + + const throwScalar = new GraphQLScalarType({ + name: 'ThrowScalar', + coerceInputLiteral() { + throw new Error('Test'); + }, + coerceInputValue: identityFunc, }); + + test('value', throwScalar, undefined); + + const returnUndefinedScalar = new GraphQLScalarType({ + name: 'ReturnUndefinedScalar', + coerceInputLiteral() { + return undefined; + }, + coerceInputValue: identityFunc, + }); + + test('value', returnUndefinedScalar, undefined); + }); + + it('converts enum values according to input coercion rules', () => { + const testEnum = new GraphQLEnumType({ + name: 'TestColor', + values: { + RED: { value: 1 }, + GREEN: { value: 2 }, + BLUE: { value: 3 }, + NULL: { value: null }, + NAN: { value: NaN }, + NO_CUSTOM_VALUE: { value: undefined }, + }, + }); + + test('RED', testEnum, 1); + test('BLUE', testEnum, 3); + test('3', testEnum, undefined); + test('"BLUE"', testEnum, undefined); + test('null', testEnum, null); + test('NULL', testEnum, null); + test('NULL', new GraphQLNonNull(testEnum), null); + test('NAN', testEnum, NaN); + test('NO_CUSTOM_VALUE', testEnum, 'NO_CUSTOM_VALUE'); + }); + + // Boolean! + const nonNullBool = new GraphQLNonNull(GraphQLBoolean); + // [Boolean] + const listOfBool = new GraphQLList(GraphQLBoolean); + // [Boolean!] + const listOfNonNullBool = new GraphQLList(nonNullBool); + // [Boolean]! + const nonNullListOfBool = new GraphQLNonNull(listOfBool); + // [Boolean!]! + const nonNullListOfNonNullBool = new GraphQLNonNull(listOfNonNullBool); + + it('coerces to null unless non-null', () => { + test('null', GraphQLBoolean, null); + test('null', nonNullBool, undefined); + }); + + it('coerces lists of values', () => { + test('true', listOfBool, [true]); + test('123', listOfBool, undefined); + test('null', listOfBool, null); + test('[true, false]', listOfBool, [true, false]); + test('[true, 123]', listOfBool, undefined); + test('[true, null]', listOfBool, [true, null]); + test('{ true: true }', listOfBool, undefined); + }); + + it('coerces non-null lists of values', () => { + test('true', nonNullListOfBool, [true]); + test('123', nonNullListOfBool, undefined); + test('null', nonNullListOfBool, undefined); + test('[true, false]', nonNullListOfBool, [true, false]); + test('[true, 123]', nonNullListOfBool, undefined); + test('[true, null]', nonNullListOfBool, [true, null]); + }); + + it('coerces lists of non-null values', () => { + test('true', listOfNonNullBool, [true]); + test('123', listOfNonNullBool, undefined); + test('null', listOfNonNullBool, null); + test('[true, false]', listOfNonNullBool, [true, false]); + test('[true, 123]', listOfNonNullBool, undefined); + test('[true, null]', listOfNonNullBool, undefined); + }); + + it('coerces non-null lists of non-null values', () => { + test('true', nonNullListOfNonNullBool, [true]); + test('123', nonNullListOfNonNullBool, undefined); + test('null', nonNullListOfNonNullBool, undefined); + test('[true, false]', nonNullListOfNonNullBool, [true, false]); + test('[true, 123]', nonNullListOfNonNullBool, undefined); + test('[true, null]', nonNullListOfNonNullBool, undefined); + }); + + it('uses default values for unprovided fields', () => { + const type = new GraphQLInputObjectType({ + name: 'TestInput', + fields: { + int: { type: GraphQLInt, default: { value: 42 } }, + float: { + type: GraphQLFloat, + default: { literal: { kind: Kind.FLOAT, value: '3.14' } }, + }, + }, + }); + + test('{}', type, { int: 42, float: 3.14 }); + }); + + const testInputObj = new GraphQLInputObjectType({ + name: 'TestInput', + fields: { + int: { type: GraphQLInt, default: { value: 42 } }, + bool: { type: GraphQLBoolean }, + requiredBool: { type: nonNullBool }, + }, + }); + const testOneOfInputObj = new GraphQLInputObjectType({ + name: 'TestOneOfInput', + fields: { + a: { type: GraphQLString }, + b: { type: GraphQLString }, + }, + isOneOf: true, + }); + + it('coerces input objects according to input coercion rules', () => { + test('null', testInputObj, null); + test('123', testInputObj, undefined); + test('[]', testInputObj, undefined); + test('{ requiredBool: true }', testInputObj, { + int: 42, + requiredBool: true, + }); + test('{ int: null, requiredBool: true }', testInputObj, { + int: null, + requiredBool: true, + }); + test('{ int: 123, requiredBool: false }', testInputObj, { + int: 123, + requiredBool: false, + }); + test('{ bool: true, requiredBool: false }', testInputObj, { + int: 42, + bool: true, + requiredBool: false, + }); + test('{ int: true, requiredBool: true }', testInputObj, undefined); + test('{ requiredBool: null }', testInputObj, undefined); + test('{ bool: true }', testInputObj, undefined); + test('{ requiredBool: true, unknown: 123 }', testInputObj, undefined); + test('{ a: "abc" }', testOneOfInputObj, { + a: 'abc', + }); + test('{ b: "def" }', testOneOfInputObj, { + b: 'def', + }); + test('{ a: "abc", b: null }', testOneOfInputObj, undefined); + test('{ a: null }', testOneOfInputObj, undefined); + test('{ a: 1 }', testOneOfInputObj, undefined); + test('{ a: "abc", b: "def" }', testOneOfInputObj, undefined); + test('{}', testOneOfInputObj, undefined); + test('{ c: "abc" }', testOneOfInputObj, undefined); + }); + + it('accepts variable values assuming already coerced', () => { + test('$var', GraphQLBoolean, undefined); + testWithVariables( + '($var: Boolean)', + { var: true }, + '$var', + GraphQLBoolean, + true, + ); + testWithVariables( + '($var: Boolean)', + { var: null }, + '$var', + GraphQLBoolean, + null, + ); + testWithVariables( + '($var: Boolean)', + { var: null }, + '$var', + nonNullBool, + undefined, + ); + }); + + it('asserts variables are provided as items in lists', () => { + test('[ $foo ]', listOfBool, [null]); + test('[ $foo ]', listOfNonNullBool, undefined); + testWithVariables( + '($foo: Boolean)', + { foo: true }, + '[ $foo ]', + listOfNonNullBool, + [true], + ); + // Note: variables are expected to have already been coerced, so we + // do not expect the singleton wrapping behavior for variables. + testWithVariables( + '($foo: Boolean)', + { foo: true }, + '$foo', + listOfNonNullBool, + true, + ); + testWithVariables( + '($foo: [Boolean])', + { foo: [true] }, + '$foo', + listOfNonNullBool, + [true], + ); + }); + + it('omits input object fields for unprovided variables', () => { + test('{ int: $foo, bool: $foo, requiredBool: true }', testInputObj, { + int: 42, + requiredBool: true, + }); + test('{ requiredBool: $foo }', testInputObj, undefined); + testWithVariables( + '', + {}, + '{ requiredBool: $foo }', + testInputObj, + undefined, + ); + testWithVariables( + '($foo: Boolean)', + { foo: true }, + '{ requiredBool: $foo }', + testInputObj, + { int: 42, requiredBool: true }, + ); + }); +}); + +describe('coerceDefaultValue', () => { + it('memoizes coercion', () => { + const coerceInputValueCalls: any = []; + + const spyScalar = new GraphQLScalarType({ + name: 'SpyScalar', + coerceInputValue(value) { + coerceInputValueCalls.push(value); + return value; + }, + }); + + const inputDefault = { + literal: { kind: Kind.STRING, value: 'hello' }, + } as const; + + const inputValue = { + default: inputDefault, + type: spyScalar, + }; + + expect(coerceDefaultValue(inputValue)).to.equal('hello'); + + // Call a second time + expect(coerceDefaultValue(inputValue)).to.equal('hello'); + expect(coerceInputValueCalls).to.deep.equal(['hello']); }); }); diff --git a/src/utilities/__tests__/findBreakingChanges-test.ts b/src/utilities/__tests__/findBreakingChanges-test.ts index 5d92522fe3..dd2e1dc7fb 100644 --- a/src/utilities/__tests__/findBreakingChanges-test.ts +++ b/src/utilities/__tests__/findBreakingChanges-test.ts @@ -16,7 +16,7 @@ import { DangerousChangeType, findBreakingChanges, findDangerousChanges, -} from '../findBreakingChanges.js'; +} from '../findSchemaChanges.js'; describe('findBreakingChanges', () => { it('should detect if a type was removed or not', () => { @@ -57,7 +57,7 @@ describe('findBreakingChanges', () => { }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Query.foo changed type from Float to String.', + description: 'Field Query.foo changed type from Float to String.', }, ]); expect(findBreakingChanges(oldSchema, oldSchema)).to.deep.equal([]); @@ -149,55 +149,56 @@ describe('findBreakingChanges', () => { expect(changes).to.deep.equal([ { type: BreakingChangeType.FIELD_REMOVED, - description: 'Type1.field2 was removed.', + description: 'Field Type1.field2 was removed.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field3 changed type from String to Boolean.', + description: 'Field Type1.field3 changed type from String to Boolean.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field4 changed type from TypeA to TypeB.', + description: 'Field Type1.field4 changed type from TypeA to TypeB.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field6 changed type from String to [String].', + description: 'Field Type1.field6 changed type from String to [String].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field7 changed type from [String] to String.', + description: 'Field Type1.field7 changed type from [String] to String.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field9 changed type from Int! to Int.', + description: 'Field Type1.field9 changed type from Int! to Int.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field10 changed type from [Int]! to [Int].', + description: 'Field Type1.field10 changed type from [Int]! to [Int].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field11 changed type from Int to [Int]!.', + description: 'Field Type1.field11 changed type from Int to [Int]!.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field13 changed type from [Int!] to [Int].', + description: 'Field Type1.field13 changed type from [Int!] to [Int].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field14 changed type from [Int] to [[Int]].', + description: 'Field Type1.field14 changed type from [Int] to [[Int]].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field15 changed type from [[Int]] to [Int].', + description: 'Field Type1.field15 changed type from [[Int]] to [Int].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field16 changed type from Int! to [Int]!.', + description: 'Field Type1.field16 changed type from Int! to [Int]!.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'Type1.field18 changed type from [[Int!]!] to [[Int!]].', + description: + 'Field Type1.field18 changed type from [[Int!]!] to [[Int!]].', }, ]); }); @@ -245,48 +246,55 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.FIELD_REMOVED, - description: 'InputType1.field2 was removed.', + description: 'Field InputType1.field2 was removed.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field1 changed type from String to Int.', + description: 'Field InputType1.field1 changed type from String to Int.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field3 changed type from [String] to String.', + description: + 'Field InputType1.field3 changed type from [String] to String.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field5 changed type from String to String!.', + description: + 'Field InputType1.field5 changed type from String to String!.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field6 changed type from [Int] to [Int]!.', + description: + 'Field InputType1.field6 changed type from [Int] to [Int]!.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field8 changed type from Int to [Int]!.', + description: 'Field InputType1.field8 changed type from Int to [Int]!.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field9 changed type from [Int] to [Int!].', + description: + 'Field InputType1.field9 changed type from [Int] to [Int!].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field11 changed type from [Int] to [[Int]].', + description: + 'Field InputType1.field11 changed type from [Int] to [[Int]].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field12 changed type from [[Int]] to [Int].', + description: + 'Field InputType1.field12 changed type from [[Int]] to [Int].', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, - description: 'InputType1.field13 changed type from Int! to [Int]!.', + description: + 'Field InputType1.field13 changed type from Int! to [Int]!.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, description: - 'InputType1.field15 changed type from [[Int]!] to [[Int!]!].', + 'Field InputType1.field15 changed type from [[Int]!] to [[Int!]!].', }, ]); }); @@ -310,8 +318,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.REQUIRED_INPUT_FIELD_ADDED, - description: - 'A required field requiredField on input type InputType1 was added.', + description: 'A required field InputType1.requiredField was added.', }, ]); }); @@ -360,7 +367,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.VALUE_REMOVED_FROM_ENUM, - description: 'VALUE1 was removed from enum type EnumType1.', + description: 'Enum value EnumType1.VALUE1 was removed.', }, ]); }); @@ -389,15 +396,15 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.ARG_REMOVED, - description: 'Interface1.field1 arg arg1 was removed.', + description: 'Argument Interface1.field1(arg1:) was removed.', }, { type: BreakingChangeType.ARG_REMOVED, - description: 'Interface1.field1 arg objectArg was removed.', + description: 'Argument Interface1.field1(objectArg:) was removed.', }, { type: BreakingChangeType.ARG_REMOVED, - description: 'Type1.field1 arg name was removed.', + description: 'Argument Type1.field1(name:) was removed.', }, ]); }); @@ -451,62 +458,62 @@ describe('findBreakingChanges', () => { { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg1 has changed type from String to Int.', + 'Argument Type1.field1(arg1:) has changed type from String to Int.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg2 has changed type from String to [String].', + 'Argument Type1.field1(arg2:) has changed type from String to [String].', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg3 has changed type from [String] to String.', + 'Argument Type1.field1(arg3:) has changed type from [String] to String.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg4 has changed type from String to String!.', + 'Argument Type1.field1(arg4:) has changed type from String to String!.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg5 has changed type from String! to Int.', + 'Argument Type1.field1(arg5:) has changed type from String! to Int.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg6 has changed type from String! to Int!.', + 'Argument Type1.field1(arg6:) has changed type from String! to Int!.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg8 has changed type from Int to [Int]!.', + 'Argument Type1.field1(arg8:) has changed type from Int to [Int]!.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg9 has changed type from [Int] to [Int!].', + 'Argument Type1.field1(arg9:) has changed type from [Int] to [Int!].', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg11 has changed type from [Int] to [[Int]].', + 'Argument Type1.field1(arg11:) has changed type from [Int] to [[Int]].', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg12 has changed type from [[Int]] to [Int].', + 'Argument Type1.field1(arg12:) has changed type from [[Int]] to [Int].', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg13 has changed type from Int! to [Int]!.', + 'Argument Type1.field1(arg13:) has changed type from Int! to [Int]!.', }, { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'Type1.field1 arg arg15 has changed type from [[Int]!] to [[Int!]!].', + 'Argument Type1.field1(arg15:) has changed type from [[Int]!] to [[Int!]!].', }, ]); }); @@ -532,7 +539,8 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.REQUIRED_ARG_ADDED, - description: 'A required arg newRequiredArg on Type1.field1 was added.', + description: + 'A required argument Type1.field1(newRequiredArg:) was added.', }, ]); }); @@ -721,12 +729,11 @@ describe('findBreakingChanges', () => { { type: BreakingChangeType.ARG_CHANGED_KIND, description: - 'ArgThatChanges.field1 arg id has changed type from Float to String.', + 'Argument ArgThatChanges.field1(id:) has changed type from Float to String.', }, { type: BreakingChangeType.VALUE_REMOVED_FROM_ENUM, - description: - 'VALUE0 was removed from enum type EnumTypeThatLosesAValue.', + description: 'Enum value EnumTypeThatLosesAValue.VALUE0 was removed.', }, { type: BreakingChangeType.IMPLEMENTED_INTERFACE_REMOVED, @@ -745,34 +752,35 @@ describe('findBreakingChanges', () => { }, { type: BreakingChangeType.FIELD_REMOVED, - description: 'TypeThatHasBreakingFieldChanges.field1 was removed.', + description: + 'Field TypeThatHasBreakingFieldChanges.field1 was removed.', }, { type: BreakingChangeType.FIELD_CHANGED_KIND, description: - 'TypeThatHasBreakingFieldChanges.field2 changed type from String to Boolean.', + 'Field TypeThatHasBreakingFieldChanges.field2 changed type from String to Boolean.', }, { type: BreakingChangeType.DIRECTIVE_REMOVED, - description: 'DirectiveThatIsRemoved was removed.', + description: 'Directive @DirectiveThatIsRemoved was removed.', }, { type: BreakingChangeType.DIRECTIVE_ARG_REMOVED, - description: 'arg1 was removed from DirectiveThatRemovesArg.', + description: 'Argument @DirectiveThatRemovesArg(arg1:) was removed.', }, { type: BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED, description: - 'A required arg arg1 on directive NonNullDirectiveAdded was added.', + 'A required argument @NonNullDirectiveAdded(arg1:) was added.', }, { type: BreakingChangeType.DIRECTIVE_REPEATABLE_REMOVED, description: - 'Repeatable flag was removed from DirectiveThatWasRepeatable.', + 'Repeatable flag was removed from @DirectiveThatWasRepeatable.', }, { type: BreakingChangeType.DIRECTIVE_LOCATION_REMOVED, - description: 'QUERY was removed from DirectiveName.', + description: 'QUERY was removed from @DirectiveName.', }, ]); }); @@ -790,7 +798,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.DIRECTIVE_REMOVED, - description: 'DirectiveThatIsRemoved was removed.', + description: 'Directive @DirectiveThatIsRemoved was removed.', }, ]); }); @@ -810,7 +818,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.DIRECTIVE_REMOVED, - description: `${GraphQLDeprecatedDirective.name} was removed.`, + description: `Directive ${GraphQLDeprecatedDirective} was removed.`, }, ]); }); @@ -827,7 +835,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.DIRECTIVE_ARG_REMOVED, - description: 'arg1 was removed from DirectiveWithArg.', + description: 'Argument @DirectiveWithArg(arg1:) was removed.', }, ]); }); @@ -849,7 +857,7 @@ describe('findBreakingChanges', () => { { type: BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED, description: - 'A required arg newRequiredArg on directive DirectiveName was added.', + 'A required argument @DirectiveName(newRequiredArg:) was added.', }, ]); }); @@ -866,7 +874,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.DIRECTIVE_REPEATABLE_REMOVED, - description: 'Repeatable flag was removed from DirectiveName.', + description: 'Repeatable flag was removed from @DirectiveName.', }, ]); }); @@ -883,7 +891,7 @@ describe('findBreakingChanges', () => { expect(findBreakingChanges(oldSchema, newSchema)).to.deep.equal([ { type: BreakingChangeType.DIRECTIVE_LOCATION_REMOVED, - description: 'QUERY was removed from DirectiveName.', + description: 'QUERY was removed from @DirectiveName.', }, ]); }); @@ -943,27 +951,27 @@ describe('findDangerousChanges', () => { { type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: - 'Type1.field1 arg withDefaultValue defaultValue was removed.', + 'Type1.field1(withDefaultValue:) defaultValue was removed.', }, { type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: - 'Type1.field1 arg stringArg has changed defaultValue from "test" to "Test".', + 'Type1.field1(stringArg:) has changed defaultValue from "test" to "Test".', }, { type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: - 'Type1.field1 arg emptyArray has changed defaultValue from [] to [7].', + 'Type1.field1(emptyArray:) has changed defaultValue from [] to [7].', }, { type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: - 'Type1.field1 arg valueArray has changed defaultValue from [["a", "b"], ["c"]] to [["b", "a"], ["d"]].', + 'Type1.field1(valueArray:) has changed defaultValue from [["a", "b"], ["c"]] to [["b", "a"], ["d"]].', }, { type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: - 'Type1.field1 arg complexObject has changed defaultValue from { innerInputArray: [{ arrayField: [1, 2, 3] }] } to { innerInputArray: [{ arrayField: [3, 2, 1] }] }.', + 'Type1.field1(complexObject:) has changed defaultValue from { innerInputArray: [{ arrayField: [1, 2, 3] }] } to { innerInputArray: [{ arrayField: [3, 2, 1] }] }.', }, ]); }); @@ -1051,7 +1059,7 @@ describe('findDangerousChanges', () => { expect(findDangerousChanges(oldSchema, newSchema)).to.deep.equal([ { type: DangerousChangeType.VALUE_ADDED_TO_ENUM, - description: 'VALUE2 was added to enum type EnumType1.', + description: 'Enum value EnumType1.VALUE2 was added.', }, ]); }); @@ -1143,8 +1151,7 @@ describe('findDangerousChanges', () => { expect(findDangerousChanges(oldSchema, newSchema)).to.deep.equal([ { type: DangerousChangeType.OPTIONAL_INPUT_FIELD_ADDED, - description: - 'An optional field field2 on input type InputType1 was added.', + description: 'An optional field InputType1.field2 was added.', }, ]); }); @@ -1189,12 +1196,12 @@ describe('findDangerousChanges', () => { expect(findDangerousChanges(oldSchema, newSchema)).to.deep.equal([ { type: DangerousChangeType.VALUE_ADDED_TO_ENUM, - description: 'VALUE2 was added to enum type EnumType1.', + description: 'Enum value EnumType1.VALUE2 was added.', }, { type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: - 'Type1.field1 arg argThatChangesDefaultValue has changed defaultValue from "test" to "Test".', + 'Type1.field1(argThatChangesDefaultValue:) has changed defaultValue from "test" to "Test".', }, { type: DangerousChangeType.IMPLEMENTED_INTERFACE_ADDED, @@ -1225,7 +1232,7 @@ describe('findDangerousChanges', () => { expect(findDangerousChanges(oldSchema, newSchema)).to.deep.equal([ { type: DangerousChangeType.OPTIONAL_ARG_ADDED, - description: 'An optional arg arg2 on Type1.field1 was added.', + description: 'An optional argument Type1.field1(arg2:) was added.', }, ]); }); diff --git a/src/utilities/__tests__/findSchemaChanges-test.ts b/src/utilities/__tests__/findSchemaChanges-test.ts new file mode 100644 index 0000000000..7bcdf32264 --- /dev/null +++ b/src/utilities/__tests__/findSchemaChanges-test.ts @@ -0,0 +1,506 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { buildSchema } from '../buildASTSchema.js'; +import { + BreakingChangeType, + DangerousChangeType, + findSchemaChanges, + SafeChangeType, +} from '../findSchemaChanges.js'; + +describe('findSchemaChanges', () => { + it('should detect if a type was added', () => { + const newSchema = buildSchema(` + type Type1 + type Type2 + `); + + const oldSchema = buildSchema(` + type Type1 + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.TYPE_ADDED, + description: 'Type2 was added.', + }, + ]); + }); + + it('should detect a type changing description', () => { + const newSchema = buildSchema(` + "New Description" + type Type1 + `); + + const oldSchema = buildSchema(` + type Type1 + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.DESCRIPTION_CHANGED, + description: 'Description of Type1 has changed to "New Description".', + }, + ]); + }); + + it('should detect if a field was added', () => { + const oldSchema = buildSchema(` + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + type Query { + foo: String + bar: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.FIELD_ADDED, + description: 'Field Query.bar was added.', + }, + ]); + }); + + it('should detect a field changing description', () => { + const oldSchema = buildSchema(` + type Query { + foo: String + bar: String + } + `); + + const newSchema = buildSchema(` + type Query { + foo: String + "New Description" + bar: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.DESCRIPTION_CHANGED, + description: + 'Description of field Query.bar has changed to "New Description".', + }, + ]); + }); + + it('should detect if a default value was added', () => { + const oldSchema = buildSchema(` + type Query { + foo(x: String): String + } + `); + + const newSchema = buildSchema(` + type Query { + foo(x: String = "bar"): String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.ARG_DEFAULT_VALUE_ADDED, + description: 'Query.foo(x:) added a defaultValue "bar".', + }, + ]); + }); + + it('should detect if an arg value changes safely', () => { + const oldSchema = buildSchema(` + type Query { + foo(x: String!): String + } + `); + + const newSchema = buildSchema(` + type Query { + foo(x: String): String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.ARG_CHANGED_KIND_SAFE, + description: + 'Argument Query.foo(x:) has changed type from String! to String.', + }, + ]); + }); + + it('should detect if an arg value changes description', () => { + const oldSchema = buildSchema(` + type Query { + foo(x: String!): String + } + `); + + const newSchema = buildSchema(` + type Query { + foo( + "New Description" + x: String! + ): String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + type: SafeChangeType.DESCRIPTION_CHANGED, + description: + 'Description of argument Query.foo(x:) has changed to "New Description".', + }, + ]); + }); + + it('should detect if a directive was added', () => { + const oldSchema = buildSchema(` + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: 'Directive @Foo was added.', + type: SafeChangeType.DIRECTIVE_ADDED, + }, + ]); + }); + + it('should detect if a changes argument safely', () => { + const oldSchema = buildSchema(` + directive @Foo(foo: String!) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo(foo: String) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: + 'Argument @Foo(foo:) has changed type from String! to String.', + type: SafeChangeType.ARG_CHANGED_KIND_SAFE, + }, + ]); + }); + + it('should detect if a default value is added to an argument', () => { + const oldSchema = buildSchema(` + directive @Foo(foo: String) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo(foo: String = "Foo") on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: '@Foo(foo:) added a defaultValue "Foo".', + type: SafeChangeType.ARG_DEFAULT_VALUE_ADDED, + }, + ]); + }); + + it('should detect if a default value is removed from an argument', () => { + const newSchema = buildSchema(` + directive @Foo(foo: String) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const oldSchema = buildSchema(` + directive @Foo(foo: String = "Foo") on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: '@Foo(foo:) defaultValue was removed.', + type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, + }, + ]); + }); + + it('should detect if a default value is changed in an argument', () => { + const oldSchema = buildSchema(` + directive @Foo(foo: String = "Bar") on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo(foo: String = "Foo") on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: '@Foo(foo:) has changed defaultValue from "Bar" to "Foo".', + type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, + }, + ]); + }); + + it('should detect if a directive argument does a breaking change', () => { + const oldSchema = buildSchema(` + directive @Foo(foo: String) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo(foo: String!) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: + 'Argument @Foo(foo:) has changed type from String to String!.', + type: BreakingChangeType.ARG_CHANGED_KIND, + }, + ]); + }); + + it('should not detect if a directive argument default value does not change', () => { + const oldSchema = buildSchema(` + directive @Foo(foo: String = "FOO") on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo(foo: String = "FOO") on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([]); + }); + + it('should detect if a directive changes description', () => { + const oldSchema = buildSchema(` + directive @Foo on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + "New Description" + directive @Foo on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: 'Description of @Foo has changed to "New Description".', + type: SafeChangeType.DESCRIPTION_CHANGED, + }, + ]); + }); + + it('should detect if a directive becomes repeatable', () => { + const oldSchema = buildSchema(` + directive @Foo on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo repeatable on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: 'Repeatable flag was added to @Foo.', + type: SafeChangeType.DIRECTIVE_REPEATABLE_ADDED, + }, + ]); + }); + + it('should detect if a directive adds locations', () => { + const oldSchema = buildSchema(` + directive @Foo on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo on FIELD_DEFINITION | QUERY + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: 'QUERY was added to @Foo.', + type: SafeChangeType.DIRECTIVE_LOCATION_ADDED, + }, + ]); + }); + + it('should detect if a directive arg gets added', () => { + const oldSchema = buildSchema(` + directive @Foo on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo(arg1: String) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: 'An optional argument @Foo(arg1:) was added.', + type: SafeChangeType.OPTIONAL_DIRECTIVE_ARG_ADDED, + }, + ]); + }); + + it('should detect if a directive arg changes description', () => { + const oldSchema = buildSchema(` + directive @Foo( + arg1: String + ) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + directive @Foo( + "New Description" + arg1: String + ) on FIELD_DEFINITION + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: + 'Description of @Foo(Foo) has changed to "New Description".', + type: SafeChangeType.DESCRIPTION_CHANGED, + }, + ]); + }); + + it('should detect if an enum member changes description', () => { + const oldSchema = buildSchema(` + enum Foo { + TEST + } + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + enum Foo { + "New Description" + TEST + } + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: + 'Description of enum value Foo.TEST has changed to "New Description".', + type: SafeChangeType.DESCRIPTION_CHANGED, + }, + ]); + }); + + it('should detect if an input field changes description', () => { + const oldSchema = buildSchema(` + input Foo { + x: String + } + + type Query { + foo: String + } + `); + + const newSchema = buildSchema(` + input Foo { + "New Description" + x: String + } + + type Query { + foo: String + } + `); + expect(findSchemaChanges(oldSchema, newSchema)).to.deep.equal([ + { + description: + 'Description of input-field Foo.x has changed to "New Description".', + type: SafeChangeType.DESCRIPTION_CHANGED, + }, + ]); + }); +}); diff --git a/src/utilities/__tests__/getIntrospectionQuery-test.ts b/src/utilities/__tests__/getIntrospectionQuery-test.ts index 62f64c968e..b57950841b 100644 --- a/src/utilities/__tests__/getIntrospectionQuery-test.ts +++ b/src/utilities/__tests__/getIntrospectionQuery-test.ts @@ -117,6 +117,14 @@ describe('getIntrospectionQuery', () => { ); }); + it('include "isOneOf" field on input objects', () => { + expectIntrospectionQuery().toNotMatch('isOneOf'); + + expectIntrospectionQuery({ oneOf: true }).toMatch('isOneOf', 1); + + expectIntrospectionQuery({ oneOf: false }).toNotMatch('isOneOf'); + }); + it('include deprecated input field and args', () => { expectIntrospectionQuery().toMatch('includeDeprecated: true', 2); diff --git a/src/utilities/__tests__/mapSchemaConfig-test.ts b/src/utilities/__tests__/mapSchemaConfig-test.ts new file mode 100644 index 0000000000..e443dadfa4 --- /dev/null +++ b/src/utilities/__tests__/mapSchemaConfig-test.ts @@ -0,0 +1,919 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { dedentString } from '../../__testUtils__/dedent.js'; + +import { GraphQLObjectType } from '../../type/definition.js'; +import type { GraphQLSchemaNormalizedConfig } from '../../type/schema.js'; +import { GraphQLSchema } from '../../type/schema.js'; + +import { buildSchema } from '../buildASTSchema.js'; +import type { + ConfigMapperMap, + MappedSchemaContext, +} from '../mapSchemaConfig.js'; +import { mapSchemaConfig, SchemaElementKind } from '../mapSchemaConfig.js'; +import { printSchema } from '../printSchema.js'; + +function expectSchemaMapping( + schemaConfig: GraphQLSchemaNormalizedConfig, + configMapperMapFn: (context: MappedSchemaContext) => ConfigMapperMap, + expected: string, +) { + const newSchemaConfig = mapSchemaConfig(schemaConfig, configMapperMapFn); + expect(printSchema(new GraphQLSchema(newSchemaConfig))).to.equal( + dedentString(expected), + ); +} + +describe('mapSchemaConfig', () => { + it('returns the original config when no mappers are included', () => { + const sdl = 'type Query'; + const schemaConfig = buildSchema(sdl).toConfig(); + expectSchemaMapping(schemaConfig, () => ({}), sdl); + }); + + describe('scalar mapping', () => { + it('can map scalar types', () => { + const sdl = 'scalar SomeScalar'; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.SCALAR]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + scalar SomeScalar + `, + ); + }); + }); + + describe('argument mapping', () => { + it('can map arguments', () => { + const sdl = ` + type SomeType { + field(arg: String): String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.ARGUMENT]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + type SomeType { + field( + """Some description""" + arg: String + ): String + } + `, + ); + }); + }); + + describe('field mapping', () => { + it('can map fields', () => { + const sdl = ` + type SomeType { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.FIELD]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + type SomeType { + """Some description""" + field: String + } + `, + ); + }); + + it('maps fields after mapping arguments', () => { + const sdl = ` + type SomeType { + field(arg: String): String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.ARGUMENT]: (config) => ({ + ...config, + description: 'Some argument description', + }), + [SchemaElementKind.FIELD]: (config) => { + expect(config.args.arg.description).to.equal( + 'Some argument description', + ); + return { + ...config, + description: 'Some field description', + }; + }, + }), + ` + type SomeType { + """Some field description""" + field( + """Some argument description""" + arg: String + ): String + } + `, + ); + }); + }); + + describe('object type mapping', () => { + it('can map object types', () => { + const sdl = 'type SomeType'; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.OBJECT]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + type SomeType + `, + ); + }); + + it('maps object types after mapping fields', () => { + const sdl = ` + type SomeType { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.FIELD]: (config) => ({ + ...config, + description: 'Some field description', + }), + [SchemaElementKind.OBJECT]: (config) => { + expect(config.fields().field.description).to.equal( + 'Some field description', + ); + return { + ...config, + description: 'Some object description', + }; + }, + }), + ` + """Some object description""" + type SomeType { + """Some field description""" + field: String + } + `, + ); + }); + + it('maps object types after mapping interfaces', () => { + const sdl = ` + interface SomeInterface + type SomeType implements SomeInterface + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.INTERFACE]: (config) => ({ + ...config, + description: 'Some interface description', + }), + [SchemaElementKind.OBJECT]: (config) => { + expect(config.interfaces()[0].description).to.equal( + 'Some interface description', + ); + return { + ...config, + description: 'Some object description', + }; + }, + }), + ` + """Some interface description""" + interface SomeInterface + + """Some object description""" + type SomeType implements SomeInterface + `, + ); + }); + }); + + describe('interface type mapping', () => { + it('can map interface types', () => { + const sdl = 'interface SomeInterface'; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.INTERFACE]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + interface SomeInterface + `, + ); + }); + + it('maps interface types after mapping fields', () => { + const sdl = ` + interface SomeInterface { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.FIELD]: (config) => ({ + ...config, + description: 'Some field description', + }), + [SchemaElementKind.INTERFACE]: (config) => { + expect(config.fields().field.description).to.equal( + 'Some field description', + ); + return { + ...config, + description: 'Some interface description', + }; + }, + }), + ` + """Some interface description""" + interface SomeInterface { + """Some field description""" + field: String + } + `, + ); + }); + + it('maps interface types after mapping parent interfaces', () => { + const sdl = ` + interface SomeParentInterface + interface SomeInterface implements SomeParentInterface + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.INTERFACE]: (config) => { + if (config.name === 'SomeInterface') { + expect(config.interfaces()[0].description).to.equal( + 'Some interface description', + ); + } + return { + ...config, + description: 'Some interface description', + }; + }, + }), + ` + """Some interface description""" + interface SomeParentInterface + + """Some interface description""" + interface SomeInterface implements SomeParentInterface + `, + ); + }); + }); + + describe('union type mapping', () => { + it('can map union types', () => { + const sdl = 'union SomeUnion'; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.UNION]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + union SomeUnion + `, + ); + }); + + it('maps union types after mapping types', () => { + const sdl = ` + type SomeType + union SomeUnion = SomeType + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.OBJECT]: (config) => ({ + ...config, + description: 'Some type description', + }), + [SchemaElementKind.UNION]: (config) => { + expect(config.types()[0].description).to.equal( + 'Some type description', + ); + return { + ...config, + description: 'Some union description', + }; + }, + }), + ` + """Some type description""" + type SomeType + + """Some union description""" + union SomeUnion = SomeType + `, + ); + }); + }); + + describe('enum value mapping', () => { + it('can map enum values', () => { + const sdl = ` + enum SomeEnum { + SOME_VALUE + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.ENUM_VALUE]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + enum SomeEnum { + """Some description""" + SOME_VALUE + } + `, + ); + }); + }); + + describe('enum type mapping', () => { + it('can map enum types', () => { + const sdl = 'enum SomeEnum'; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.ENUM]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + enum SomeEnum + `, + ); + }); + + it('maps enum types after mapping values', () => { + const sdl = ` + enum SomeEnum { + SOME_VALUE + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.ENUM_VALUE]: (config) => ({ + ...config, + description: 'Some value description', + }), + [SchemaElementKind.ENUM]: (config) => { + expect(config.values().SOME_VALUE.description).to.equal( + 'Some value description', + ); + return { + ...config, + description: 'Some enum description', + }; + }, + }), + ` + """Some enum description""" + enum SomeEnum { + """Some value description""" + SOME_VALUE + } + `, + ); + }); + }); + + describe('input field mapping', () => { + it('can map input fields', () => { + const sdl = ` + input SomeInput { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.INPUT_FIELD]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + input SomeInput { + """Some description""" + field: String + } + `, + ); + }); + }); + + describe('input object type mapping', () => { + it('can map input object types', () => { + const sdl = 'input SomeInput'; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.INPUT_OBJECT]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + input SomeInput + `, + ); + }); + + it('maps input object types after mapping input fields', () => { + const sdl = ` + input SomeInput { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.INPUT_FIELD]: (config) => ({ + ...config, + description: 'Some input field description', + }), + [SchemaElementKind.INPUT_OBJECT]: (config) => { + expect(config.fields().field.description).to.equal( + 'Some input field description', + ); + return { + ...config, + description: 'Some input object description', + }; + }, + }), + ` + """Some input object description""" + input SomeInput { + """Some input field description""" + field: String + } + `, + ); + }); + }); + + describe('directive mapping', () => { + it('can map directives', () => { + const sdl = ` + directive @SomeDirective on FIELD + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.DIRECTIVE]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + directive @SomeDirective on FIELD + `, + ); + }); + + it('maps directives after mapping arguments', () => { + const sdl = ` + directive @SomeDirective(arg: String) on FIELD + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.ARGUMENT]: (config) => ({ + ...config, + description: 'Some argument description', + }), + [SchemaElementKind.DIRECTIVE]: (config) => { + expect(config.args.arg.description).to.equal( + 'Some argument description', + ); + return { + ...config, + description: 'Some directive description', + }; + }, + }), + ` + """Some directive description""" + directive @SomeDirective( + """Some argument description""" + arg: String + ) on FIELD + `, + ); + }); + }); + + describe('schema mapping', () => { + it('can map the schema', () => { + const sdl = ` + type Query + + type Mutation + + type Subscription + + directive @SomeDirective on FIELD + + scalar SomeScalar + + type SomeType { + field: String + } + + interface SomeInterface + + union SomeUnion + + enum SomeEnum { + SOME_VALUE + } + + input SomeInput { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.SCHEMA]: (config) => ({ + ...config, + description: 'Some description', + }), + }), + ` + """Some description""" + schema { + query: Query + mutation: Mutation + subscription: Subscription + } + + directive @SomeDirective on FIELD + + type Query + + type Mutation + + type Subscription + + scalar SomeScalar + + type SomeType { + field: String + } + + interface SomeInterface + + union SomeUnion + + enum SomeEnum { + SOME_VALUE + } + + input SomeInput { + field: String + } + `, + ); + }); + + it('maps the schema after mapping types and directives', () => { + const sdl = ` + type Query + + type Mutation + + type Subscription + + directive @SomeDirective on FIELD + + scalar SomeScalar + + type SomeType { + field: String + } + + interface SomeInterface + + union SomeUnion + + enum SomeEnum { + SOME_VALUE + } + + input SomeInput { + field: String + } + `; + + const schemaConfig = buildSchema(sdl).toConfig(); + + expectSchemaMapping( + schemaConfig, + () => ({ + [SchemaElementKind.DIRECTIVE]: (config) => ({ + ...config, + description: 'Some directive description', + }), + [SchemaElementKind.SCALAR]: (config) => ({ + ...config, + description: 'Some scalar description', + }), + [SchemaElementKind.OBJECT]: (config) => ({ + ...config, + description: 'Some object description', + }), + [SchemaElementKind.INTERFACE]: (config) => ({ + ...config, + description: 'Some interface description', + }), + [SchemaElementKind.UNION]: (config) => ({ + ...config, + description: 'Some union description', + }), + [SchemaElementKind.ENUM]: (config) => ({ + ...config, + description: 'Some enum description', + }), + [SchemaElementKind.INPUT_OBJECT]: (config) => ({ + ...config, + description: 'Some input object description', + }), + [SchemaElementKind.SCHEMA]: (config) => { + for (const directive of config.directives) { + if (directive.name === 'SomeDirective') { + expect(directive.description).to.equal( + 'Some directive description', + ); + } + } + + for (const type of config.types) { + switch (type.name) { + case 'SomeScalar': + expect(type.description).to.equal('Some scalar description'); + break; + case 'SomeType': + expect(type.description).to.equal('Some object description'); + break; + case 'SomeInterface': + expect(type.description).to.equal( + 'Some interface description', + ); + break; + case 'SomeUnion': + expect(type.description).to.equal('Some union description'); + break; + case 'SomeEnum': + expect(type.description).to.equal('Some enum description'); + break; + case 'SomeInput': + expect(type.description).to.equal( + 'Some input object description', + ); + break; + } + } + + return { + ...config, + description: 'Some schema description', + }; + }, + }), + ` + """Some schema description""" + schema { + query: Query + mutation: Mutation + subscription: Subscription + } + + """Some directive description""" + directive @SomeDirective on FIELD + + """Some object description""" + type Query + + """Some object description""" + type Mutation + + """Some object description""" + type Subscription + + """Some scalar description""" + scalar SomeScalar + + """Some object description""" + type SomeType { + field: String + } + + """Some interface description""" + interface SomeInterface + + """Some union description""" + union SomeUnion + + """Some enum description""" + enum SomeEnum { + SOME_VALUE + } + + """Some input object description""" + input SomeInput { + field: String + } + `, + ); + }); + }); + + describe('schema context', () => { + it('allows access to the final mapped named type via getNamedType()', () => { + const sdl = ` + """Some description""" + type SomeType + `; + + const schema = buildSchema(sdl); + const schemaConfig = schema.toConfig(); + const someType = schema.getType('SomeType') as GraphQLObjectType; + + expectSchemaMapping( + schemaConfig, + ({ getNamedType }) => { + return { + [SchemaElementKind.OBJECT]: (config) => ({ + ...config, + fields: () => { + expectMappedSomeType(); + return config.fields(); + }, + }), + [SchemaElementKind.SCHEMA]: (config) => { + expectMappedSomeType(); + return config; + }, + }; + + function expectMappedSomeType() { + const mappedType = getNamedType(someType.name); + expect(mappedType).not.to.equal(someType); + expect(mappedType.description).to.equal(someType.description); + } + }, + sdl, + ); + }); + + it('allows adding a named type via setNamedType() and retrieving the new list via getNamedTypes', () => { + const sdl = 'type SomeType'; + + const schema = buildSchema(sdl); + const schemaConfig = schema.toConfig(); + + expectSchemaMapping( + schemaConfig, + ({ setNamedType, getNamedTypes }) => ({ + [SchemaElementKind.SCHEMA]: (config) => { + setNamedType( + new GraphQLObjectType({ name: 'AnotherType', fields: {} }), + ); + return { + ...config, + types: getNamedTypes(), + }; + }, + }), + ` + type SomeType + + type AnotherType + `, + ); + }); + }); +}); diff --git a/src/utilities/__tests__/printSchema-test.ts b/src/utilities/__tests__/printSchema-test.ts index 78f793b183..3c28907f40 100644 --- a/src/utilities/__tests__/printSchema-test.ts +++ b/src/utilities/__tests__/printSchema-test.ts @@ -148,7 +148,7 @@ describe('Type System Printer', () => { it('Prints String Field With Int Arg With Default', () => { const schema = buildSingleFieldSchema({ type: GraphQLString, - args: { argOne: { type: GraphQLInt, defaultValue: 2 } }, + args: { argOne: { type: GraphQLInt, default: { value: 2 } } }, }); expectPrintedSchema(schema).to.equal(dedent` @@ -161,7 +161,9 @@ describe('Type System Printer', () => { it('Prints String Field With String Arg With Default', () => { const schema = buildSingleFieldSchema({ type: GraphQLString, - args: { argOne: { type: GraphQLString, defaultValue: 'tes\t de\fault' } }, + args: { + argOne: { type: GraphQLString, default: { value: 'tes\t de\fault' } }, + }, }); expectPrintedSchema(schema).to.equal( @@ -176,7 +178,7 @@ describe('Type System Printer', () => { it('Prints String Field With Int Arg With Default Null', () => { const schema = buildSingleFieldSchema({ type: GraphQLString, - args: { argOne: { type: GraphQLInt, defaultValue: null } }, + args: { argOne: { type: GraphQLInt, default: { value: null } } }, }); expectPrintedSchema(schema).to.equal(dedent` @@ -219,7 +221,7 @@ describe('Type System Printer', () => { const schema = buildSingleFieldSchema({ type: GraphQLString, args: { - argOne: { type: GraphQLInt, defaultValue: 1 }, + argOne: { type: GraphQLInt, default: { value: 1 } }, argTwo: { type: GraphQLString }, argThree: { type: GraphQLBoolean }, }, @@ -237,7 +239,7 @@ describe('Type System Printer', () => { type: GraphQLString, args: { argOne: { type: GraphQLInt }, - argTwo: { type: GraphQLString, defaultValue: 'foo' }, + argTwo: { type: GraphQLString, default: { value: 'foo' } }, argThree: { type: GraphQLBoolean }, }, }); @@ -255,7 +257,7 @@ describe('Type System Printer', () => { args: { argOne: { type: GraphQLInt }, argTwo: { type: GraphQLString }, - argThree: { type: GraphQLBoolean, defaultValue: false }, + argThree: { type: GraphQLBoolean, default: { value: false } }, }, }); @@ -601,7 +603,7 @@ describe('Type System Printer', () => { description: 'Complex Directive', args: { stringArg: { type: GraphQLString }, - intArg: { type: GraphQLInt, defaultValue: -1 }, + intArg: { type: GraphQLInt, default: { value: -1 } }, }, isRepeatable: true, locations: [DirectiveLocation.FIELD, DirectiveLocation.QUERY], @@ -803,7 +805,7 @@ describe('Type System Printer', () => { """ Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified by [CommonMark](https://commonmark.org/). """ - reason: String = "No longer supported" + reason: String! = "No longer supported" ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE """Exposes a URL that specifies the behavior of this scalar.""" @@ -971,9 +973,12 @@ describe('Type System Printer', () => { """Location adjacent to an inline fragment.""" INLINE_FRAGMENT - """Location adjacent to a variable definition.""" + """Location adjacent to an operation variable definition.""" VARIABLE_DEFINITION + """Location adjacent to a fragment variable definition.""" + FRAGMENT_VARIABLE_DEFINITION + """Location adjacent to a schema definition.""" SCHEMA diff --git a/src/utilities/__tests__/replaceVariables-test.ts b/src/utilities/__tests__/replaceVariables-test.ts new file mode 100644 index 0000000000..61b0780d6a --- /dev/null +++ b/src/utilities/__tests__/replaceVariables-test.ts @@ -0,0 +1,196 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { invariant } from '../../jsutils/invariant.js'; +import type { ReadOnlyObjMap } from '../../jsutils/ObjMap.js'; + +import type { ValueNode } from '../../language/ast.js'; +import { Parser, parseValue as _parseValue } from '../../language/parser.js'; +import { TokenKind } from '../../language/tokenKind.js'; + +import { GraphQLInt } from '../../type/scalars.js'; +import { GraphQLSchema } from '../../type/schema.js'; + +import { getVariableValues } from '../../execution/values.js'; + +import { replaceVariables } from '../replaceVariables.js'; + +function parseValue(ast: string): ValueNode { + return _parseValue(ast, { noLocation: true }); +} + +function testVariables(variableDefs: string, inputs: ReadOnlyObjMap) { + const parser = new Parser(variableDefs, { noLocation: true }); + parser.expectToken(TokenKind.SOF); + const variableValuesOrErrors = getVariableValues( + new GraphQLSchema({ types: [GraphQLInt] }), + parser.parseVariableDefinitions() ?? [], + inputs, + ); + invariant(variableValuesOrErrors.variableValues !== undefined); + return variableValuesOrErrors.variableValues; +} + +describe('replaceVariables', () => { + describe('Operation Variables', () => { + it('does not change simple AST', () => { + const ast = parseValue('null'); + expect(replaceVariables(ast, undefined)).to.equal(ast); + }); + + it('replaces simple Variables', () => { + const ast = parseValue('$var'); + const vars = testVariables('($var: Int)', { var: 123 }); + expect(replaceVariables(ast, vars)).to.deep.equal(parseValue('123')); + }); + + it('replaces Variables with default values', () => { + const ast = parseValue('$var'); + const vars = testVariables('($var: Int = 123)', {}); + expect(replaceVariables(ast, vars)).to.deep.equal(parseValue('123')); + }); + + it('replaces nested Variables', () => { + const ast = parseValue('{ foo: [ $var ], bar: $var }'); + const vars = testVariables('($var: Int)', { var: 123 }); + expect(replaceVariables(ast, vars)).to.deep.equal( + parseValue('{ foo: [ 123 ], bar: 123 }'), + ); + }); + + it('replaces missing Variables with null', () => { + const ast = parseValue('$var'); + expect(replaceVariables(ast, undefined)).to.deep.equal( + parseValue('null'), + ); + }); + + it('replaces missing variable declaration with null', () => { + const ast = parseValue('$var'); + const vars = testVariables('', {}); + expect(replaceVariables(ast, vars)).to.deep.equal(parseValue('null')); + }); + + it('replaces misspelled variable declaration with null', () => { + const ast = parseValue('$var1'); + const vars = testVariables('($var2: Int)', { var2: 123 }); + expect(replaceVariables(ast, vars)).to.deep.equal(parseValue('null')); + }); + + it('replaces missing Variables in lists with null', () => { + const ast = parseValue('[1, $var]'); + expect(replaceVariables(ast, undefined)).to.deep.equal( + parseValue('[1, null]'), + ); + }); + + it('omits missing Variables from objects', () => { + const ast = parseValue('{ foo: 1, bar: $var }'); + const vars = testVariables('($wrongVar: Int)', { var: 123 }); + expect(replaceVariables(ast, vars)).to.deep.equal( + parseValue('{ foo: 1 }'), + ); + }); + }); + + describe('Fragment Variables', () => { + it('replaces simple Fragment Variables', () => { + const ast = parseValue('$var'); + const fragmentVars = testVariables('($var: Int)', { var: 123 }); + expect(replaceVariables(ast, undefined, fragmentVars)).to.deep.equal( + parseValue('123'), + ); + }); + + it('replaces simple Fragment Variables even when overlapping with Operation Variables', () => { + const ast = parseValue('$var'); + const operationVars = testVariables('($var: Int)', { var: 123 }); + const fragmentVars = testVariables('($var: Int)', { var: 456 }); + expect(replaceVariables(ast, operationVars, fragmentVars)).to.deep.equal( + parseValue('456'), + ); + }); + + it('replaces Fragment Variables with default values', () => { + const ast = parseValue('$var'); + const fragmentVars = testVariables('($var: Int = 123)', {}); + expect(replaceVariables(ast, undefined, fragmentVars)).to.deep.equal( + parseValue('123'), + ); + }); + + it('replaces Fragment Variables with default values even when overlapping with Operation Variables', () => { + const ast = parseValue('$var'); + const operationVars = testVariables('($var: Int = 123)', {}); + const fragmentVars = testVariables('($var: Int = 456)', {}); + expect(replaceVariables(ast, operationVars, fragmentVars)).to.deep.equal( + parseValue('456'), + ); + }); + + it('replaces nested Fragment Variables', () => { + const ast = parseValue('{ foo: [ $var ], bar: $var }'); + const fragmentVars = testVariables('($var: Int)', { var: 123 }); + expect(replaceVariables(ast, undefined, fragmentVars)).to.deep.equal( + parseValue('{ foo: [ 123 ], bar: 123 }'), + ); + }); + + it('replaces nested Fragment Variables even when overlapping with Operation Variables', () => { + const ast = parseValue('{ foo: [ $var ], bar: $var }'); + const operationVars = testVariables('($var: Int)', { var: 123 }); + const fragmentVars = testVariables('($var: Int)', { var: 456 }); + expect(replaceVariables(ast, operationVars, fragmentVars)).to.deep.equal( + parseValue('{ foo: [ 456 ], bar: 456 }'), + ); + }); + + it('replaces missing Fragment Variables with null', () => { + const ast = parseValue('$var'); + expect(replaceVariables(ast, undefined, undefined)).to.deep.equal( + parseValue('null'), + ); + }); + + it('replaces missing Fragment Variables with null even when overlapping with Operation Variables', () => { + const ast = parseValue('$var'); + const operationVars = testVariables('($var: Int)', { var: 123 }); + const fragmentVars = testVariables('($var: Int)', {}); + expect(replaceVariables(ast, operationVars, fragmentVars)).to.deep.equal( + parseValue('null'), + ); + }); + + it('replaces missing Fragment Variables in lists with null', () => { + const ast = parseValue('[1, $var]'); + expect(replaceVariables(ast, undefined, undefined)).to.deep.equal( + parseValue('[1, null]'), + ); + }); + + it('replaces missing Fragment Variables in lists with null even when overlapping with Operation Variables', () => { + const ast = parseValue('[1, $var]'); + const operationVars = testVariables('($var: Int)', { var: 123 }); + const fragmentVars = testVariables('($var: Int)', {}); + expect(replaceVariables(ast, operationVars, fragmentVars)).to.deep.equal( + parseValue('[1, null]'), + ); + }); + + it('omits missing Fragment Variables from objects', () => { + const ast = parseValue('{ foo: 1, bar: $var }'); + expect(replaceVariables(ast, undefined, undefined)).to.deep.equal( + parseValue('{ foo: 1 }'), + ); + }); + + it('omits missing Fragment Variables from objects even when overlapping with Operation Variables', () => { + const ast = parseValue('{ foo: 1, bar: $var }'); + const operationVars = testVariables('($var: Int)', { var: 123 }); + const fragmentVars = testVariables('($var: Int)', {}); + expect(replaceVariables(ast, operationVars, fragmentVars)).to.deep.equal( + parseValue('{ foo: 1 }'), + ); + }); + }); +}); diff --git a/src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts b/src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts index bc4f2a9f3d..e6248f39a3 100644 --- a/src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts +++ b/src/utilities/__tests__/stripIgnoredCharacters-fuzz.ts @@ -276,7 +276,7 @@ describe('stripIgnoredCharacters', () => { let testValue; try { testValue = lexValue(testStr); - } catch (e) { + } catch (_e) { continue; // skip invalid values } diff --git a/src/utilities/__tests__/stripIgnoredCharacters-test.ts b/src/utilities/__tests__/stripIgnoredCharacters-test.ts index 509f76ee3c..f334810582 100644 --- a/src/utilities/__tests__/stripIgnoredCharacters-test.ts +++ b/src/utilities/__tests__/stripIgnoredCharacters-test.ts @@ -208,14 +208,8 @@ describe('stripIgnoredCharacters', () => { const strippedQuery = stripIgnoredCharacters(kitchenSinkQuery); expect(stripIgnoredCharacters(strippedQuery)).to.equal(strippedQuery); - const queryAST = parse(kitchenSinkQuery, { - noLocation: true, - experimentalClientControlledNullability: true, - }); - const strippedAST = parse(strippedQuery, { - noLocation: true, - experimentalClientControlledNullability: true, - }); + const queryAST = parse(kitchenSinkQuery, { noLocation: true }); + const strippedAST = parse(strippedQuery, { noLocation: true }); expect(strippedAST).to.deep.equal(queryAST); }); diff --git a/src/utilities/__tests__/validateInputValue-test.ts b/src/utilities/__tests__/validateInputValue-test.ts new file mode 100644 index 0000000000..7b1667c912 --- /dev/null +++ b/src/utilities/__tests__/validateInputValue-test.ts @@ -0,0 +1,924 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { invariant } from '../../jsutils/invariant.js'; +import type { ReadOnlyObjMap } from '../../jsutils/ObjMap.js'; + +import { Parser, parseValue } from '../../language/parser.js'; +import { TokenKind } from '../../language/tokenKind.js'; + +import type { GraphQLInputType } from '../../type/definition.js'; +import { + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLScalarType, +} from '../../type/definition.js'; +import { GraphQLInt } from '../../type/scalars.js'; +import { GraphQLSchema } from '../../type/schema.js'; + +import type { VariableValues } from '../../execution/values.js'; +import { getVariableValues } from '../../execution/values.js'; + +import { + validateInputLiteral, + validateInputValue, +} from '../validateInputValue.js'; + +describe('validateInputValue', () => { + function test( + inputValue: unknown, + type: GraphQLInputType, + expected: unknown, + hideSuggestions = false, + ) { + const errors: any = []; + validateInputValue( + inputValue, + type, + (error, path) => { + errors.push({ error: error.message, path }); + }, + hideSuggestions, + ); + expect(errors).to.deep.equal(expected); + } + + describe('for GraphQLNonNull', () => { + const TestNonNull = new GraphQLNonNull(GraphQLInt); + + it('returns no error for non-null value', () => { + test(1, TestNonNull, []); + }); + + it('returns an error for undefined value', () => { + test(undefined, TestNonNull, [ + { + error: 'Expected a value of non-null type "Int!" to be provided.', + path: [], + }, + ]); + }); + + it('returns an error for null value', () => { + test(null, TestNonNull, [ + { + error: 'Expected value of non-null type "Int!" not to be null.', + path: [], + }, + ]); + }); + }); + + describe('for GraphQLScalar', () => { + const TestScalar = new GraphQLScalarType({ + name: 'TestScalar', + parseValue(input: any) { + invariant(typeof input === 'object' && input !== null); + if (input.error != null) { + throw new Error(input.error); + } + return input.value; + }, + }); + + it('returns no error for valid input', () => { + test({ value: 1 }, TestScalar, []); + }); + + it('returns no error for null result', () => { + test({ value: null }, TestScalar, []); + }); + + it('returns no error for NaN result', () => { + test({ value: NaN }, TestScalar, []); + }); + + it('returns an error for undefined result', () => { + test({ value: undefined }, TestScalar, [ + { + error: + 'Expected value of type "TestScalar", found: { value: undefined }.', + path: [], + }, + ]); + }); + + it('returns an error for undefined result', () => { + const inputValue = { error: 'Some error message.' }; + test(inputValue, TestScalar, [ + { + error: + 'Expected value of type "TestScalar", but encountered error "Some error message."; found: { error: "Some error message." }.', + path: [], + }, + ]); + }); + }); + + describe('for GraphQLEnum', () => { + const TestEnum = new GraphQLEnumType({ + name: 'TestEnum', + values: { + FOO: { value: 'InternalFoo' }, + BAR: { value: 123456789 }, + }, + }); + + it('returns no error for a known enum name', () => { + test('FOO', TestEnum, []); + + test('BAR', TestEnum, []); + }); + + it('returns an error for unknown enum value', () => { + test('UNKNOWN', TestEnum, [ + { + error: 'Value "UNKNOWN" does not exist in "TestEnum" enum.', + path: [], + }, + ]); + }); + + it('returns an error for misspelled enum value', () => { + test('foo', TestEnum, [ + { + error: + 'Value "foo" does not exist in "TestEnum" enum. Did you mean the enum value "FOO"?', + path: [], + }, + ]); + }); + + it('returns an error for misspelled enum value (no suggestions)', () => { + test( + 'foo', + TestEnum, + [ + { + error: 'Value "foo" does not exist in "TestEnum" enum.', + path: [], + }, + ], + true, + ); + }); + + it('returns an error for incorrect value type', () => { + class Foo { + toJSON() { + return 'FOO'; + } + } + + test(new Foo(), TestEnum, [ + { + error: + 'Enum "TestEnum" cannot represent non-string value: FOO. Did you mean the enum value "FOO"?', + path: [], + }, + ]); + + test( + new Foo(), + TestEnum, + [ + { + error: 'Enum "TestEnum" cannot represent non-string value: FOO.', + path: [], + }, + ], + true, + ); + + test(123, TestEnum, [ + { + error: 'Enum "TestEnum" cannot represent non-string value: 123.', + path: [], + }, + ]); + + test({ field: 'value' }, TestEnum, [ + { + error: + 'Enum "TestEnum" cannot represent non-string value: { field: "value" }.', + path: [], + }, + ]); + }); + + it('reports thrown non-error', () => { + const TestThrowScalar = new GraphQLScalarType({ + name: 'TestScalar', + parseValue() { + // eslint-disable-next-line no-throw-literal, @typescript-eslint/only-throw-error + throw 'Not an error object.'; + }, + }); + + test({}, TestThrowScalar, [ + { + error: + 'Expected value of type "TestScalar", but encountered error "Not an error object."; found: {}.', + path: [], + }, + ]); + }); + }); + + describe('for GraphQLInputObject', () => { + const TestInputObject = new GraphQLInputObjectType({ + name: 'TestInputObject', + fields: { + foo: { type: new GraphQLNonNull(GraphQLInt) }, + bar: { type: GraphQLInt }, + }, + }); + + it('returns no error for a valid input', () => { + test({ foo: 123 }, TestInputObject, []); + }); + + it('returns an error for a non-object type', () => { + test(123, TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" to be an object, found: 123.', + path: [], + }, + ]); + }); + + it('returns an error for an invalid field', () => { + test({ foo: NaN }, TestInputObject, [ + { + error: 'Int cannot represent non-integer value: NaN', + path: ['foo'], + }, + ]); + }); + + it('returns multiple errors for multiple invalid fields', () => { + test({ foo: 'abc', bar: 'def' }, TestInputObject, [ + { + error: 'Int cannot represent non-integer value: "abc"', + path: ['foo'], + }, + { + error: 'Int cannot represent non-integer value: "def"', + path: ['bar'], + }, + ]); + }); + + it('returns error for a missing required field', () => { + test({ bar: 123 }, TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" to include required field "foo", found: { bar: 123 }.', + path: [], + }, + ]); + }); + + it('returns error for an unknown field', () => { + test({ foo: 123, unknownField: 123 }, TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.', + path: [], + }, + ]); + }); + + it('returns error for a misspelled field', () => { + test({ foo: 123, bart: 123 }, TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { foo: 123, bart: 123 }.', + path: [], + }, + ]); + }); + + it('returns error for a misspelled field (no suggestions)', () => { + test( + { foo: 123, bart: 123 }, + TestInputObject, + [ + { + error: + 'Expected value of type "TestInputObject" not to include unknown field "bart", found: { foo: 123, bart: 123 }.', + path: [], + }, + ], + true, + ); + }); + }); + + describe('for GraphQLInputObject with default value', () => { + function makeTestInputObject(defaultValue: unknown) { + return new GraphQLInputObjectType({ + name: 'TestInputObject', + fields: { + foo: { + type: new GraphQLScalarType({ name: 'TestScalar' }), + default: { value: defaultValue }, + }, + }, + }); + } + + it('no error for no errors for valid input value', () => { + test({ foo: 5 }, makeTestInputObject(7), []); + }); + + it('no error for object with default value', () => { + test({}, makeTestInputObject(7), []); + }); + + it('no error for null as value', () => { + test({}, makeTestInputObject(null), []); + }); + + it('no error for NaN as value', () => { + test({}, makeTestInputObject(NaN), []); + }); + }); + + describe('for GraphQLList', () => { + const TestList = new GraphQLList(GraphQLInt); + + it('returns no error for a valid input', () => { + test([1, 2, 3], TestList, []); + }); + + it('returns no error for a valid iterable input', () => { + // TODO: put an error in this list and show it appears + function* listGenerator() { + yield 1; + yield 2; + yield 3; + } + + test(listGenerator(), TestList, []); + }); + + it('returns an error for an invalid input', () => { + test([1, 'b', true, 4], TestList, [ + { + error: 'Int cannot represent non-integer value: "b"', + path: [1], + }, + { + error: 'Int cannot represent non-integer value: true', + path: [2], + }, + ]); + }); + + it('no error for a list for a non-list value', () => { + test(42, TestList, []); + }); + + it('returns an error for a non-list invalid value', () => { + test('INVALID', TestList, [ + { + error: 'Int cannot represent non-integer value: "INVALID"', + path: [], + }, + ]); + }); + + it('no error for null for a null value', () => { + test(null, TestList, []); + }); + }); + + describe('for nested GraphQLList', () => { + const TestNestedList = new GraphQLList(new GraphQLList(GraphQLInt)); + + it('no error for a valid input', () => { + test([[1], [2, 3]], TestNestedList, []); + }); + + it('no error for a list for a non-list value', () => { + test(42, TestNestedList, []); + }); + + it('no error for null for a null value', () => { + test(null, TestNestedList, []); + }); + + it('no error for nested lists for nested non-list values', () => { + test([1, 2, 3], TestNestedList, []); + }); + + it('no error for nested null for nested null values', () => { + test([42, [null], null], TestNestedList, []); + }); + }); +}); + +describe('validateInputLiteral', () => { + function test( + inputValue: string, + type: GraphQLInputType, + expected: unknown, + variableValues?: VariableValues, + hideSuggestions = false, + ) { + const errors: any = []; + validateInputLiteral( + parseValue(inputValue), + type, + (error, path) => { + errors.push({ error: error.message, path }); + }, + variableValues, + undefined, + hideSuggestions, + ); + expect(errors).to.deep.equal(expected); + } + + function testWithVariables( + variableDefs: string, + values: ReadOnlyObjMap, + inputValue: string, + type: GraphQLInputType, + expected: unknown, + ) { + const parser = new Parser(variableDefs); + parser.expectToken(TokenKind.SOF); + const variableValuesOrErrors = getVariableValues( + new GraphQLSchema({ types: [GraphQLInt] }), + parser.parseVariableDefinitions() ?? [], + values, + ); + invariant(variableValuesOrErrors.variableValues != null); + test(inputValue, type, expected, variableValuesOrErrors.variableValues); + } + + it('ignores variables statically', () => { + const TestNonNull = new GraphQLNonNull(GraphQLInt); + test('$var', TestNonNull, []); + }); + + it('returns an error for null variables for non-nullable types', () => { + const TestNonNull = new GraphQLNonNull(GraphQLInt); + testWithVariables('($var: Int)', { var: null }, '$var', TestNonNull, [ + { + error: + 'Expected variable "$var" provided to non-null type "Int!" not to be null.', + path: [], + }, + ]); + }); + + describe('for GraphQLNonNull', () => { + const TestNonNull = new GraphQLNonNull(GraphQLInt); + + it('returns no error for non-null value', () => { + test('1', TestNonNull, []); + }); + + it('returns an error for null value', () => { + test('null', TestNonNull, [ + { + error: 'Expected value of non-null type "Int!" not to be null.', + path: [], + }, + ]); + }); + }); + + describe('for GraphQLScalar', () => { + const TestScalar = new GraphQLScalarType({ + name: 'TestScalar', + parseValue(input: any) { + invariant(typeof input === 'object' && input !== null); + if (input.error != null) { + throw new Error(input.error); + } + return input.value; + }, + }); + + it('returns no error for valid input', () => { + test('{ value: 1 }', TestScalar, []); + }); + + it('returns no error for null result', () => { + test('{ value: null }', TestScalar, []); + }); + + it('returns no error for NaN result', () => { + test('{ value: NaN }', TestScalar, []); + }); + + it('returns an error for undefined result', () => { + test('{}', TestScalar, [ + { + error: 'Expected value of type "TestScalar", found: { }.', + path: [], + }, + ]); + }); + + it('returns an error for undefined result', () => { + const inputValue = '{ error: "Some error message." }'; + test(inputValue, TestScalar, [ + { + error: + 'Expected value of type "TestScalar", but encountered error "Some error message."; found: { error: "Some error message." }.', + path: [], + }, + ]); + }); + + it('reports thrown non-error', () => { + const TestThrowScalar = new GraphQLScalarType({ + name: 'TestScalar', + parseValue() { + // eslint-disable-next-line no-throw-literal, @typescript-eslint/only-throw-error + throw 'Not an error object.'; + }, + }); + + test('{}', TestThrowScalar, [ + { + error: + 'Expected value of type "TestScalar", but encountered error "Not an error object."; found: { }.', + path: [], + }, + ]); + }); + }); + + describe('for GraphQLEnum', () => { + const TestEnum = new GraphQLEnumType({ + name: 'TestEnum', + values: { + FOO: { value: 'InternalFoo' }, + BAR: { value: 123456789 }, + }, + }); + + it('returns no error for a known enum name', () => { + test('FOO', TestEnum, []); + + test('BAR', TestEnum, []); + }); + + it('returns an error for unknown enum value', () => { + test('UNKNOWN', TestEnum, [ + { + error: 'Value "UNKNOWN" does not exist in "TestEnum" enum.', + path: [], + }, + ]); + }); + + it('returns an error for misspelled enum value', () => { + test('foo', TestEnum, [ + { + error: + 'Value "foo" does not exist in "TestEnum" enum. Did you mean the enum value "FOO"?', + path: [], + }, + ]); + }); + + it('returns an error for misspelled enum value (no suggestions)', () => { + test( + 'foo', + TestEnum, + [ + { + error: 'Value "foo" does not exist in "TestEnum" enum.', + path: [], + }, + ], + undefined, + true, + ); + }); + + it('returns an error for incorrect value type', () => { + test('"FOO"', TestEnum, [ + { + error: + 'Enum "TestEnum" cannot represent non-enum value: "FOO". Did you mean the enum value "FOO"?', + path: [], + }, + ]); + + test( + '"FOO"', + TestEnum, + [ + { + error: 'Enum "TestEnum" cannot represent non-enum value: "FOO".', + path: [], + }, + ], + undefined, + true, + ); + + test('"UNKNOWN"', TestEnum, [ + { + error: 'Enum "TestEnum" cannot represent non-enum value: "UNKNOWN".', + path: [], + }, + ]); + + test('123', TestEnum, [ + { + error: 'Enum "TestEnum" cannot represent non-enum value: 123.', + path: [], + }, + ]); + + test('{ field: "value" }', TestEnum, [ + { + error: + 'Enum "TestEnum" cannot represent non-enum value: { field: "value" }.', + path: [], + }, + ]); + }); + }); + + describe('for GraphQLInputObject', () => { + const TestInputObject = new GraphQLInputObjectType({ + name: 'TestInputObject', + fields: { + foo: { type: new GraphQLNonNull(GraphQLInt) }, + bar: { type: GraphQLInt }, + optional: { + type: new GraphQLNonNull(GraphQLInt), + default: { value: 42 }, + }, + }, + }); + + it('returns no error for a valid input', () => { + test('{ foo: 123 }', TestInputObject, []); + }); + + it('returns an error for a non-object type', () => { + test('123', TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" to be an object, found: 123.', + path: [], + }, + ]); + }); + + it('returns an error for an invalid field', () => { + test('{ foo: 1.5 }', TestInputObject, [ + { + error: 'Int cannot represent non-integer value: 1.5', + path: ['foo'], + }, + ]); + }); + + it('returns multiple errors for multiple invalid fields', () => { + test('{ foo: "abc", bar: "def" }', TestInputObject, [ + { + error: 'Int cannot represent non-integer value: "abc"', + path: ['foo'], + }, + { + error: 'Int cannot represent non-integer value: "def"', + path: ['bar'], + }, + ]); + }); + + it('returns error for a missing required field', () => { + test('{ bar: 123 }', TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" to include required field "foo", found: { bar: 123 }.', + path: [], + }, + ]); + }); + + it('returns error for an unknown field', () => { + test('{ foo: 123, unknownField: 123 }', TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.', + path: [], + }, + ]); + }); + + it('returns error for a misspelled field', () => { + test('{ foo: 123, bart: 123 }', TestInputObject, [ + { + error: + 'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { foo: 123, bart: 123 }.', + path: [], + }, + ]); + }); + + it('allows variables in an object, statically', () => { + test('{ foo: $var }', TestInputObject, []); + }); + + it('allows correct use of variables', () => { + testWithVariables( + '($var: Int)', + { var: 123 }, + '{ foo: $var }', + TestInputObject, + [], + ); + }); + + it('allows missing variables in an nullable field', () => { + testWithVariables('', {}, '{ foo: 123, bar: $var }', TestInputObject, []); + testWithVariables( + '($var: Int)', + {}, + '{ foo: 123, bar: $var }', + TestInputObject, + [], + ); + }); + + it('allows missing variables in an optional field', () => { + testWithVariables( + '($var: Int)', + {}, + '{ foo: 123, optional: $var }', + TestInputObject, + [], + ); + }); + + it('errors on missing variable in an required field', () => { + testWithVariables('($var: Int)', {}, '{ foo: $var }', TestInputObject, [ + { + error: + 'Expected variable "$var" provided to type "Int!" to provide a runtime value.', + path: ['foo'], + }, + ]); + }); + + it('errors on null variable in an non-null field', () => { + testWithVariables( + '($var: Int)', + { var: null }, + '{ foo: 123, optional: $var }', + TestInputObject, + [ + { + error: + 'Expected variable "$var" provided to non-null type "Int!" not to be null.', + path: ['optional'], + }, + ], + ); + }); + }); + + describe('for GraphQLInputObject with default value', () => { + function makeTestInputObject(defaultValue: unknown) { + return new GraphQLInputObjectType({ + name: 'TestInputObject', + fields: { + foo: { + type: new GraphQLScalarType({ name: 'TestScalar' }), + default: { value: defaultValue }, + }, + }, + }); + } + + it('no error for no errors for valid input value', () => { + test('{ foo: 5 }', makeTestInputObject(7), []); + }); + + it('no error for object with default value', () => { + test('{}', makeTestInputObject(7), []); + }); + + it('no error for null as value', () => { + test('{}', makeTestInputObject(null), []); + }); + + it('no error for NaN as value', () => { + test('{}', makeTestInputObject(NaN), []); + }); + }); + + describe('for GraphQLList', () => { + const TestList = new GraphQLList(GraphQLInt); + + it('returns no error for a valid input', () => { + test('[1, 2, 3]', TestList, []); + }); + + it('returns an error for an invalid input', () => { + test('[1, "b", true, 4]', TestList, [ + { + error: 'Int cannot represent non-integer value: "b"', + path: [1], + }, + { + error: 'Int cannot represent non-integer value: true', + path: [2], + }, + ]); + }); + + it('no error for a list for a non-list value', () => { + test('42', TestList, []); + }); + + it('returns an error for a non-list invalid value', () => { + test('"INVALID"', TestList, [ + { + error: 'Int cannot represent non-integer value: "INVALID"', + path: [], + }, + ]); + }); + + it('no error for null for a null value', () => { + test('null', TestList, []); + }); + + it('allows variables in a list, statically', () => { + test('[1, $var, 3]', TestList, []); + }); + + it('allows missing variables in a list (which coerce to null)', () => { + testWithVariables('($var: Int)', {}, '[1, $var, 3]', TestList, []); + }); + + it('errors on missing variables in a list of non-null', () => { + const TestListNonNull = new GraphQLList(new GraphQLNonNull(GraphQLInt)); + testWithVariables('($var: Int)', {}, '[1, $var, 3]', TestListNonNull, [ + { + error: + 'Expected variable "$var" provided to type "Int!" to provide a runtime value.', + path: [1], + }, + ]); + }); + + it('errors on null variables in a list of non-null', () => { + const TestListNonNull = new GraphQLList(new GraphQLNonNull(GraphQLInt)); + testWithVariables( + '($var: Int)', + { var: null }, + '[1, $var, 3]', + TestListNonNull, + [ + { + error: + 'Expected variable "$var" provided to non-null type "Int!" not to be null.', + path: [1], + }, + ], + ); + }); + }); + + describe('for nested GraphQLList', () => { + const TestNestedList = new GraphQLList(new GraphQLList(GraphQLInt)); + + it('no error for a valid input', () => { + test('[[1], [2, 3]]', TestNestedList, []); + }); + + it('no error for a list for a non-list value', () => { + test('42', TestNestedList, []); + }); + + it('no error for null for a null value', () => { + test('null', TestNestedList, []); + }); + + it('no error for nested lists for nested non-list values', () => { + test('[1, 2, 3]', TestNestedList, []); + }); + + it('no error for nested null for nested null values', () => { + test('[42, [null], null]', TestNestedList, []); + }); + }); +}); diff --git a/src/utilities/__tests__/valueFromAST-test.ts b/src/utilities/__tests__/valueFromAST-test.ts index e287d91691..2bed756925 100644 --- a/src/utilities/__tests__/valueFromAST-test.ts +++ b/src/utilities/__tests__/valueFromAST-test.ts @@ -24,6 +24,7 @@ import { import { valueFromAST } from '../valueFromAST.js'; +/** @deprecated use `coerceInputLiteral()` instead - will be removed in v18 */ describe('valueFromAST', () => { function expectValueFrom( valueText: string, diff --git a/src/utilities/__tests__/valueToLiteral-test.ts b/src/utilities/__tests__/valueToLiteral-test.ts new file mode 100644 index 0000000000..8db4f869f8 --- /dev/null +++ b/src/utilities/__tests__/valueToLiteral-test.ts @@ -0,0 +1,222 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { Kind } from '../../language/kinds.js'; +import { parseConstValue } from '../../language/parser.js'; + +import type { GraphQLInputType } from '../../type/definition.js'; +import { + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, + GraphQLNonNull, + GraphQLScalarType, +} from '../../type/definition.js'; +import { + GraphQLBoolean, + GraphQLFloat, + GraphQLID, + GraphQLInt, + GraphQLString, +} from '../../type/scalars.js'; + +import { + defaultScalarValueToLiteral, + valueToLiteral, +} from '../valueToLiteral.js'; + +describe('valueToLiteral', () => { + function test( + value: unknown, + type: GraphQLInputType, + expected: string | undefined, + ) { + return expect(valueToLiteral(value, type)).to.deep.equal( + expected == null + ? undefined + : parseConstValue(expected, { noLocation: true }), + ); + } + + it('converts null values to Null AST', () => { + test(null, GraphQLString, 'null'); + test(undefined, GraphQLString, 'null'); + test(null, new GraphQLNonNull(GraphQLString), undefined); + }); + + it('converts boolean values to Boolean ASTs', () => { + test(true, GraphQLBoolean, 'true'); + test(false, GraphQLBoolean, 'false'); + test('false', GraphQLBoolean, undefined); + }); + + it('converts int number values to Int ASTs', () => { + test(0, GraphQLInt, '0'); + test(-1, GraphQLInt, '-1'); + test(2147483647, GraphQLInt, '2147483647'); + test(2147483648, GraphQLInt, undefined); + test(0.5, GraphQLInt, undefined); + }); + + it('converts float number values to Float ASTs', () => { + test(123.5, GraphQLFloat, '123.5'); + test(2e40, GraphQLFloat, '2e+40'); + test(1099511627776, GraphQLFloat, '1099511627776'); + test('0.5', GraphQLFloat, undefined); + // Non-finite + test(NaN, GraphQLFloat, undefined); + test(Infinity, GraphQLFloat, undefined); + }); + + it('converts String ASTs to String values', () => { + test('hello world', GraphQLString, '"hello world"'); + test(123, GraphQLString, undefined); + }); + + it('converts ID values to Int/String ASTs', () => { + test('hello world', GraphQLID, '"hello world"'); + test('123', GraphQLID, '123'); + test(123, GraphQLID, '123'); + test( + '123456789123456789123456789123456789', + GraphQLID, + '123456789123456789123456789123456789', + ); + test(123.5, GraphQLID, undefined); + }); + + const myEnum = new GraphQLEnumType({ + name: 'MyEnum', + values: { + HELLO: {}, + COMPLEX: { value: { someArbitrary: 'complexValue' } }, + }, + }); + + it('converts Enum names to Enum ASTs', () => { + test('HELLO', myEnum, 'HELLO'); + test('COMPLEX', myEnum, 'COMPLEX'); + // Undefined Enum + test('GOODBYE', myEnum, undefined); + test(123, myEnum, undefined); + }); + + it('converts List ASTs to array values', () => { + test(['FOO', 'BAR'], new GraphQLList(GraphQLString), '["FOO", "BAR"]'); + test(['123', 123], new GraphQLList(GraphQLID), '[123, 123]'); + // Invalid items create an invalid result + test(['FOO', 123], new GraphQLList(GraphQLString), undefined); + // Does not coerce items to list singletons + test('FOO', new GraphQLList(GraphQLString), '"FOO"'); + }); + + const inputObj = new GraphQLInputObjectType({ + name: 'MyInputObj', + fields: { + foo: { type: new GraphQLNonNull(GraphQLFloat) }, + bar: { type: GraphQLID }, + }, + }); + + it('converts input objects', () => { + test({ foo: 3, bar: '3' }, inputObj, '{ foo: 3, bar: 3 }'); + test({ foo: 3 }, inputObj, '{ foo: 3 }'); + + // Non-object is invalid + test('123', inputObj, undefined); + + // Invalid fields create an invalid result + test({ foo: '3' }, inputObj, undefined); + + // Missing required fields create an invalid result + test({ bar: 3 }, inputObj, undefined); + + // Additional fields create an invalid result + test({ foo: 3, unknown: 3 }, inputObj, undefined); + }); + + it('custom scalar types may define valueToLiteral', () => { + const customScalar = new GraphQLScalarType({ + name: 'CustomScalar', + valueToLiteral(value) { + if (typeof value === 'string' && value.startsWith('#')) { + return { kind: Kind.ENUM, value: value.slice(1) }; + } + }, + }); + + test('#FOO', customScalar, 'FOO'); + test('FOO', customScalar, undefined); + }); + + it('custom scalar types may throw errors from valueToLiteral', () => { + const customScalar = new GraphQLScalarType({ + name: 'CustomScalar', + valueToLiteral() { + throw new Error(); + }, + }); + + test('FOO', customScalar, undefined); + }); + + it('custom scalar types may fall back on default valueToLiteral', () => { + const customScalar = new GraphQLScalarType({ + name: 'CustomScalar', + }); + + test({ foo: 'bar' }, customScalar, '{ foo: "bar" }'); + }); + + describe('defaultScalarValueToLiteral', () => { + function testDefault(value: unknown, expected: string) { + return expect(defaultScalarValueToLiteral(value)).to.deep.equal( + parseConstValue(expected, { noLocation: true }), + ); + } + + it('converts null values to Null ASTs', () => { + testDefault(null, 'null'); + testDefault(undefined, 'null'); + }); + + it('converts boolean values to Boolean ASTs', () => { + testDefault(true, 'true'); + testDefault(false, 'false'); + }); + + it('converts number values to Int/Float ASTs', () => { + testDefault(0, '0'); + testDefault(-1, '-1'); + testDefault(1099511627776, '1099511627776'); + testDefault(123.5, '123.5'); + testDefault(2e40, '2e+40'); + }); + + it('converts non-finite number values to Null ASTs', () => { + testDefault(NaN, 'null'); + testDefault(Infinity, 'null'); + }); + + it('converts String values to String ASTs', () => { + testDefault('hello world', '"hello world"'); + }); + + it('converts array values to List ASTs', () => { + testDefault(['abc', 123], '["abc", 123]'); + }); + + it('converts object values to Object ASTs', () => { + testDefault( + { foo: 'abc', bar: null, baz: undefined }, + '{ foo: "abc", bar: null }', + ); + }); + + it('throws on values it cannot convert', () => { + expect(() => defaultScalarValueToLiteral(Symbol())).to.throw( + 'Cannot convert value to AST: Symbol().', + ); + }); + }); +}); diff --git a/src/utilities/astFromValue.ts b/src/utilities/astFromValue.ts index bb03baf232..3ace598d91 100644 --- a/src/utilities/astFromValue.ts +++ b/src/utilities/astFromValue.ts @@ -37,6 +37,7 @@ import { GraphQLID } from '../type/scalars.js'; * | Unknown | Enum Value | * | null | NullValue | * + * @deprecated use `valueToLiteral()` instead with care to operate on external values - `astFromValue()` will be removed in v18 */ export function astFromValue( value: unknown, @@ -98,44 +99,44 @@ export function astFromValue( } if (isLeafType(type)) { - // Since value is an internally represented value, it must be serialized + // Since value is an internally represented value, it must be coerced // to an externally represented value before converting into an AST. - const serialized = type.serialize(value); - if (serialized == null) { + const coerced = type.coerceOutputValue(value); + if (coerced == null) { return null; } - // Others serialize based on their corresponding JavaScript scalar types. - if (typeof serialized === 'boolean') { - return { kind: Kind.BOOLEAN, value: serialized }; + // Others coerce based on their corresponding JavaScript scalar types. + if (typeof coerced === 'boolean') { + return { kind: Kind.BOOLEAN, value: coerced }; } // JavaScript numbers can be Int or Float values. - if (typeof serialized === 'number' && Number.isFinite(serialized)) { - const stringNum = String(serialized); + if (typeof coerced === 'number' && Number.isFinite(coerced)) { + const stringNum = String(coerced); return integerStringRegExp.test(stringNum) ? { kind: Kind.INT, value: stringNum } : { kind: Kind.FLOAT, value: stringNum }; } - if (typeof serialized === 'string') { + if (typeof coerced === 'string') { // Enum types use Enum literals. if (isEnumType(type)) { - return { kind: Kind.ENUM, value: serialized }; + return { kind: Kind.ENUM, value: coerced }; } // ID types can use Int literals. - if (type === GraphQLID && integerStringRegExp.test(serialized)) { - return { kind: Kind.INT, value: serialized }; + if (type === GraphQLID && integerStringRegExp.test(coerced)) { + return { kind: Kind.INT, value: coerced }; } return { kind: Kind.STRING, - value: serialized, + value: coerced, }; } - throw new TypeError(`Cannot convert value to AST: ${inspect(serialized)}.`); + throw new TypeError(`Cannot convert value to AST: ${inspect(coerced)}.`); } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. diff --git a/src/utilities/buildASTSchema.ts b/src/utilities/buildASTSchema.ts index 09fd7cd7dd..5be0b6e421 100644 --- a/src/utilities/buildASTSchema.ts +++ b/src/utilities/buildASTSchema.ts @@ -93,7 +93,7 @@ export function buildSchema( ): GraphQLSchema { const document = parse(source, { noLocation: options?.noLocation, - allowLegacyFragmentVariables: options?.allowLegacyFragmentVariables, + experimentalFragmentArguments: options?.experimentalFragmentArguments, }); return buildASTSchema(document, { diff --git a/src/utilities/buildClientSchema.ts b/src/utilities/buildClientSchema.ts index ab50728554..c760e1ec95 100644 --- a/src/utilities/buildClientSchema.ts +++ b/src/utilities/buildClientSchema.ts @@ -3,7 +3,7 @@ import { inspect } from '../jsutils/inspect.js'; import { isObjectLike } from '../jsutils/isObjectLike.js'; import { keyValMap } from '../jsutils/keyValMap.js'; -import { parseValue } from '../language/parser.js'; +import { parseConstValue } from '../language/parser.js'; import type { GraphQLFieldConfig, @@ -47,7 +47,6 @@ import type { IntrospectionTypeRef, IntrospectionUnionType, } from './getIntrospectionQuery.js'; -import { valueFromAST } from './valueFromAST.js'; /** * Build a GraphQLSchema for use by client tools. @@ -55,8 +54,8 @@ import { valueFromAST } from './valueFromAST.js'; * Given the result of a client running the introspection query, creates and * returns a GraphQLSchema instance which can be then used with all graphql-js * tools, but cannot be used to execute a query, as introspection does not - * represent the "resolver", "parse" or "serialize" functions or any other - * server-internal mechanisms. + * represent the "resolver", "coerceInputValue" or "coerceOutputValue" + * functions or any other server-internal mechanisms. * * This function expects a complete introspection result. Don't forget to check * the "errors" field of a server response before calling this function. @@ -178,28 +177,26 @@ export function buildClientSchema( // Given a type's introspection result, construct the correct // GraphQLType instance. function buildType(type: IntrospectionType): GraphQLNamedType { - // eslint-disable-next-line @typescript-eslint/prefer-optional-chain - if (type != null && type.name != null && type.kind != null) { - // FIXME: Properly type IntrospectionType, it's a breaking change so fix in v17 - // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check - switch (type.kind) { - case TypeKind.SCALAR: - return buildScalarDef(type); - case TypeKind.OBJECT: - return buildObjectDef(type); - case TypeKind.INTERFACE: - return buildInterfaceDef(type); - case TypeKind.UNION: - return buildUnionDef(type); - case TypeKind.ENUM: - return buildEnumDef(type); - case TypeKind.INPUT_OBJECT: - return buildInputObjectDef(type); - } + switch (type.kind) { + case TypeKind.SCALAR: + return buildScalarDef(type); + case TypeKind.OBJECT: + return buildObjectDef(type); + case TypeKind.INTERFACE: + return buildInterfaceDef(type); + case TypeKind.UNION: + return buildUnionDef(type); + case TypeKind.ENUM: + return buildEnumDef(type); + case TypeKind.INPUT_OBJECT: + return buildInputObjectDef(type); } - const typeStr = inspect(type); + // Unreachable. + // @ts-expect-error throw new Error( - `Invalid or incomplete introspection result. Ensure that a full introspection query is used in order to build a client schema: ${typeStr}.`, + `Invalid or incomplete introspection result. Ensure that a full introspection query is used in order to build a client schema: ${inspect( + type, + )}.`, ); } @@ -311,6 +308,7 @@ export function buildClientSchema( name: inputObjectIntrospection.name, description: inputObjectIntrospection.description, fields: () => buildInputValueDefMap(inputObjectIntrospection.inputFields), + isOneOf: inputObjectIntrospection.isOneOf, }); } @@ -375,14 +373,13 @@ export function buildClientSchema( ); } - const defaultValue = - inputValueIntrospection.defaultValue != null - ? valueFromAST(parseValue(inputValueIntrospection.defaultValue), type) - : undefined; return { description: inputValueIntrospection.description, type, - defaultValue, + default: + inputValueIntrospection.defaultValue != null + ? { literal: parseConstValue(inputValueIntrospection.defaultValue) } + : undefined, deprecationReason: inputValueIntrospection.deprecationReason, }; } diff --git a/src/utilities/coerceInputValue.ts b/src/utilities/coerceInputValue.ts index 9aa49abed5..d33b4273c6 100644 --- a/src/utilities/coerceInputValue.ts +++ b/src/utilities/coerceInputValue.ts @@ -1,206 +1,327 @@ -import { didYouMean } from '../jsutils/didYouMean.js'; -import { inspect } from '../jsutils/inspect.js'; import { invariant } from '../jsutils/invariant.js'; import { isIterableObject } from '../jsutils/isIterableObject.js'; import { isObjectLike } from '../jsutils/isObjectLike.js'; -import type { Path } from '../jsutils/Path.js'; -import { addPath, pathToArray } from '../jsutils/Path.js'; -import { printPathArray } from '../jsutils/printPathArray.js'; -import { suggestionList } from '../jsutils/suggestionList.js'; +import type { Maybe } from '../jsutils/Maybe.js'; -import { GraphQLError } from '../error/GraphQLError.js'; +import type { ValueNode, VariableNode } from '../language/ast.js'; +import { Kind } from '../language/kinds.js'; -import type { GraphQLInputType } from '../type/definition.js'; +import type { + GraphQLDefaultInput, + GraphQLInputType, +} from '../type/definition.js'; import { + assertLeafType, isInputObjectType, - isLeafType, isListType, isNonNullType, + isRequiredInputField, } from '../type/definition.js'; -type OnErrorCB = ( - path: ReadonlyArray, - invalidValue: unknown, - error: GraphQLError, -) => void; +import type { VariableValues } from '../execution/values.js'; + +import { replaceVariables } from './replaceVariables.js'; /** * Coerces a JavaScript value given a GraphQL Input Type. + * + * Returns `undefined` when the value could not be validly coerced according to + * the provided type. */ export function coerceInputValue( inputValue: unknown, type: GraphQLInputType, - onError: OnErrorCB = defaultOnError, -): unknown { - return coerceInputValueImpl(inputValue, type, onError, undefined); -} - -function defaultOnError( - path: ReadonlyArray, - invalidValue: unknown, - error: GraphQLError, -): void { - let errorPrefix = 'Invalid value ' + inspect(invalidValue); - if (path.length > 0) { - errorPrefix += ` at "value${printPathArray(path)}"`; - } - error.message = errorPrefix + ': ' + error.message; - throw error; -} - -function coerceInputValueImpl( - inputValue: unknown, - type: GraphQLInputType, - onError: OnErrorCB, - path: Path | undefined, ): unknown { if (isNonNullType(type)) { - if (inputValue != null) { - return coerceInputValueImpl(inputValue, type.ofType, onError, path); + if (inputValue == null) { + return; // Invalid: intentionally return no value. } - onError( - pathToArray(path), - inputValue, - new GraphQLError( - `Expected non-nullable type "${inspect(type)}" not to be null.`, - ), - ); - return; + return coerceInputValue(inputValue, type.ofType); } if (inputValue == null) { - // Explicitly return the value null. - return null; + return null; // Explicitly return the value null. } if (isListType(type)) { - const itemType = type.ofType; - if (isIterableObject(inputValue)) { - return Array.from(inputValue, (itemValue, index) => { - const itemPath = addPath(path, index, undefined); - return coerceInputValueImpl(itemValue, itemType, onError, itemPath); - }); + if (!isIterableObject(inputValue)) { + // Lists accept a non-list value as a list of one. + const coercedItem = coerceInputValue(inputValue, type.ofType); + if (coercedItem === undefined) { + return; // Invalid: intentionally return no value. + } + return [coercedItem]; + } + const coercedValue = []; + for (const itemValue of inputValue) { + const coercedItem = coerceInputValue(itemValue, type.ofType); + if (coercedItem === undefined) { + return; // Invalid: intentionally return no value. + } + coercedValue.push(coercedItem); } - // Lists accept a non-list value as a list of one. - return [coerceInputValueImpl(inputValue, itemType, onError, path)]; + return coercedValue; } if (isInputObjectType(type)) { if (!isObjectLike(inputValue)) { - onError( - pathToArray(path), - inputValue, - new GraphQLError(`Expected type "${type.name}" to be an object.`), - ); - return; + return; // Invalid: intentionally return no value. } const coercedValue: any = {}; const fieldDefs = type.getFields(); - + const hasUndefinedField = Object.keys(inputValue).some( + (name) => !Object.hasOwn(fieldDefs, name), + ); + if (hasUndefinedField) { + return; // Invalid: intentionally return no value. + } for (const field of Object.values(fieldDefs)) { const fieldValue = inputValue[field.name]; - if (fieldValue === undefined) { - if (field.defaultValue !== undefined) { - coercedValue[field.name] = field.defaultValue; - } else if (isNonNullType(field.type)) { - const typeStr = inspect(field.type); - onError( - pathToArray(path), - inputValue, - new GraphQLError( - `Field "${field.name}" of required type "${typeStr}" was not provided.`, - ), - ); + if (isRequiredInputField(field)) { + return; // Invalid: intentionally return no value. } - continue; - } - - coercedValue[field.name] = coerceInputValueImpl( - fieldValue, - field.type, - onError, - addPath(path, field.name, type.name), - ); - } - - // Ensure every provided field is defined. - for (const fieldName of Object.keys(inputValue)) { - if (fieldDefs[fieldName] == null) { - const suggestions = suggestionList( - fieldName, - Object.keys(type.getFields()), - ); - onError( - pathToArray(path), - inputValue, - new GraphQLError( - `Field "${fieldName}" is not defined by type "${type.name}".` + - didYouMean(suggestions), - ), - ); + const coercedDefaultValue = coerceDefaultValue(field); + if (coercedDefaultValue !== undefined) { + coercedValue[field.name] = coercedDefaultValue; + } + } else { + const coercedField = coerceInputValue(fieldValue, field.type); + if (coercedField === undefined) { + return; // Invalid: intentionally return no value. + } + coercedValue[field.name] = coercedField; } } if (type.isOneOf) { const keys = Object.keys(coercedValue); if (keys.length !== 1) { - onError( - pathToArray(path), - inputValue, - new GraphQLError( - `Exactly one key must be specified for OneOf type "${type.name}".`, - ), - ); + return; // Invalid: intentionally return no value. } const key = keys[0]; const value = coercedValue[key]; if (value === null) { - onError( - pathToArray(path).concat(key), - value, - new GraphQLError(`Field "${key}" must be non-null.`), - ); + return; // Invalid: intentionally return no value. } } return coercedValue; } - if (isLeafType(type)) { - let parseResult; - - // Scalars and Enums determine if an input value is valid via parseValue(), - // which can throw to indicate failure. If it throws, maintain a reference - // to the original error. - try { - parseResult = type.parseValue(inputValue); - } catch (error) { - if (error instanceof GraphQLError) { - onError(pathToArray(path), inputValue, error); + const leafType = assertLeafType(type); + + try { + return leafType.coerceInputValue(inputValue); + } catch (_error) { + // Invalid: ignore error and intentionally return no value. + } +} + +/** + * Produces a coerced "internal" JavaScript value given a GraphQL Value AST. + * + * Returns `undefined` when the value could not be validly coerced according to + * the provided type. + */ +export function coerceInputLiteral( + valueNode: ValueNode, + type: GraphQLInputType, + variableValues?: Maybe, + fragmentVariableValues?: Maybe, +): unknown { + if (valueNode.kind === Kind.VARIABLE) { + const coercedVariableValue = getCoercedVariableValue( + valueNode, + variableValues, + fragmentVariableValues, + ); + if (coercedVariableValue == null && isNonNullType(type)) { + return; // Invalid: intentionally return no value. + } + // Note: This does no further checking that this variable is correct. + // This assumes validated has checked this variable is of the correct type. + return coercedVariableValue; + } + + if (isNonNullType(type)) { + if (valueNode.kind === Kind.NULL) { + return; // Invalid: intentionally return no value. + } + return coerceInputLiteral( + valueNode, + type.ofType, + variableValues, + fragmentVariableValues, + ); + } + + if (valueNode.kind === Kind.NULL) { + return null; // Explicitly return the value null. + } + + if (isListType(type)) { + if (valueNode.kind !== Kind.LIST) { + // Lists accept a non-list value as a list of one. + const itemValue = coerceInputLiteral( + valueNode, + type.ofType, + variableValues, + fragmentVariableValues, + ); + if (itemValue === undefined) { + return; // Invalid: intentionally return no value. + } + return [itemValue]; + } + const coercedValue: Array = []; + for (const itemNode of valueNode.values) { + let itemValue = coerceInputLiteral( + itemNode, + type.ofType, + variableValues, + fragmentVariableValues, + ); + if (itemValue === undefined) { + if ( + itemNode.kind === Kind.VARIABLE && + getCoercedVariableValue( + itemNode, + variableValues, + fragmentVariableValues, + ) == null && + !isNonNullType(type.ofType) + ) { + // A missing variable within a list is coerced to null. + itemValue = null; + } else { + return; // Invalid: intentionally return no value. + } + } + coercedValue.push(itemValue); + } + return coercedValue; + } + + if (isInputObjectType(type)) { + if (valueNode.kind !== Kind.OBJECT) { + return; // Invalid: intentionally return no value. + } + + const coercedValue: { [field: string]: unknown } = {}; + const fieldDefs = type.getFields(); + const hasUndefinedField = valueNode.fields.some( + (field) => !Object.hasOwn(fieldDefs, field.name.value), + ); + if (hasUndefinedField) { + return; // Invalid: intentionally return no value. + } + const fieldNodes = new Map( + valueNode.fields.map((field) => [field.name.value, field]), + ); + for (const field of Object.values(fieldDefs)) { + const fieldNode = fieldNodes.get(field.name); + if ( + !fieldNode || + (fieldNode.value.kind === Kind.VARIABLE && + getCoercedVariableValue( + fieldNode.value, + variableValues, + fragmentVariableValues, + ) == null) + ) { + if (isRequiredInputField(field)) { + return; // Invalid: intentionally return no value. + } + const coercedDefaultValue = coerceDefaultValue(field); + if (coercedDefaultValue !== undefined) { + coercedValue[field.name] = coercedDefaultValue; + } } else { - onError( - pathToArray(path), - inputValue, - new GraphQLError(`Expected type "${type.name}". ` + error.message, { - originalError: error, - }), + const fieldValue = coerceInputLiteral( + fieldNode.value, + field.type, + variableValues, + fragmentVariableValues, ); + if (fieldValue === undefined) { + return; // Invalid: intentionally return no value. + } + coercedValue[field.name] = fieldValue; } - return; } - if (parseResult === undefined) { - onError( - pathToArray(path), - inputValue, - new GraphQLError(`Expected type "${type.name}".`), - ); + + if (type.isOneOf) { + const keys = Object.keys(coercedValue); + if (keys.length !== 1) { + return; // Invalid: not exactly one key, intentionally return no value. + } + + if (coercedValue[keys[0]] === null) { + return; // Invalid: value not non-null, intentionally return no value. + } } - return parseResult; + + return coercedValue; + } + + const leafType = assertLeafType(type); + try { + return leafType.coerceInputLiteral + ? leafType.coerceInputLiteral( + replaceVariables(valueNode, variableValues, fragmentVariableValues), + ) + : leafType.parseLiteral(valueNode, variableValues?.coerced); + } catch (_error) { + // Invalid: ignore error and intentionally return no value. + } +} + +// Retrieves the variable value for the given variable node. +function getCoercedVariableValue( + variableNode: VariableNode, + variableValues: Maybe, + fragmentVariableValues: Maybe, +): unknown { + const varName = variableNode.name.value; + if (fragmentVariableValues?.sources[varName] !== undefined) { + return fragmentVariableValues.coerced[varName]; + } + + return variableValues?.coerced[varName]; +} + +interface InputValue { + type: GraphQLInputType; + default?: GraphQLDefaultInput | undefined; + defaultValue?: unknown; +} + +/** + * @internal + */ +export function coerceDefaultValue(inputValue: InputValue): unknown { + // Memoize the result of coercing the default value in a hidden field. + let coercedDefaultValue = (inputValue as any)._memoizedCoercedDefaultValue; + if (coercedDefaultValue !== undefined) { + return coercedDefaultValue; + } + + const defaultInput = inputValue.default; + if (defaultInput !== undefined) { + coercedDefaultValue = defaultInput.literal + ? coerceInputLiteral(defaultInput.literal, inputValue.type) + : coerceInputValue(defaultInput.value, inputValue.type); + invariant(coercedDefaultValue !== undefined); + (inputValue as any)._memoizedCoercedDefaultValue = coercedDefaultValue; + return coercedDefaultValue; + } + + const defaultValue = inputValue.defaultValue; + if (defaultValue !== undefined) { + (inputValue as any)._memoizedCoercedDefaultValue = defaultValue; } - /* c8 ignore next 3 */ - // Not reachable, all possible types have been considered. - invariant(false, 'Unexpected input type: ' + inspect(type)); + return defaultValue; } diff --git a/src/utilities/extendSchema.ts b/src/utilities/extendSchema.ts index 0733aad14e..93b3776533 100644 --- a/src/utilities/extendSchema.ts +++ b/src/utilities/extendSchema.ts @@ -1,7 +1,5 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap.js'; -import { inspect } from '../jsutils/inspect.js'; import { invariant } from '../jsutils/invariant.js'; -import { mapValue } from '../jsutils/mapValue.js'; import type { Maybe } from '../jsutils/Maybe.js'; import type { @@ -31,12 +29,10 @@ import type { import { Kind } from '../language/kinds.js'; import type { - GraphQLArgumentConfig, - GraphQLEnumValueConfigMap, - GraphQLFieldConfig, + GraphQLEnumValueNormalizedConfigMap, GraphQLFieldConfigArgumentMap, - GraphQLFieldConfigMap, - GraphQLInputFieldConfigMap, + GraphQLFieldNormalizedConfigMap, + GraphQLInputFieldNormalizedConfigMap, GraphQLNamedType, GraphQLType, } from '../type/definition.js'; @@ -49,30 +45,15 @@ import { GraphQLObjectType, GraphQLScalarType, GraphQLUnionType, - isEnumType, - isInputObjectType, - isInterfaceType, - isListType, - isNonNullType, - isObjectType, - isScalarType, - isUnionType, } from '../type/definition.js'; import { GraphQLDeprecatedDirective, GraphQLDirective, GraphQLOneOfDirective, GraphQLSpecifiedByDirective, - isSpecifiedDirective, } from '../type/directives.js'; -import { - introspectionTypes, - isIntrospectionType, -} from '../type/introspection.js'; -import { - isSpecifiedScalarType, - specifiedScalarTypes, -} from '../type/scalars.js'; +import { introspectionTypes } from '../type/introspection.js'; +import { specifiedScalarTypes } from '../type/scalars.js'; import type { GraphQLSchemaNormalizedConfig, GraphQLSchemaValidationOptions, @@ -83,7 +64,7 @@ import { assertValidSDLExtension } from '../validation/validate.js'; import { getDirectiveValues } from '../execution/values.js'; -import { valueFromAST } from './valueFromAST.js'; +import { mapSchemaConfig, SchemaElementKind } from './mapSchemaConfig.js'; interface Options extends GraphQLSchemaValidationOptions { /** @@ -216,490 +197,378 @@ export function extendSchemaImpl( return schemaConfig; } - const typeMap = new Map( - schemaConfig.types.map((type) => [type.name, extendNamedType(type)]), - ); - - for (const typeNode of typeDefs) { - const name = typeNode.name.value; - typeMap.set(name, stdTypeMap.get(name) ?? buildType(typeNode)); - } + return mapSchemaConfig(schemaConfig, (context) => { + const { getNamedType, setNamedType, getNamedTypes } = context; + return { + [SchemaElementKind.SCHEMA]: (config) => { + for (const typeNode of typeDefs) { + const type = + stdTypeMap.get(typeNode.name.value) ?? buildNamedType(typeNode); + setNamedType(type); + } + + const operationTypes = { + // Get the extended root operation types. + query: + config.query && + (getNamedType(config.query.name) as GraphQLObjectType), + mutation: + config.mutation && + (getNamedType(config.mutation.name) as GraphQLObjectType), + subscription: + config.subscription && + (getNamedType(config.subscription.name) as GraphQLObjectType), + // Then, incorporate schema definition and all schema extensions. + ...(schemaDef && getOperationTypes([schemaDef])), + ...getOperationTypes(schemaExtensions), + }; - const operationTypes = { - // Get the extended root operation types. - query: schemaConfig.query && replaceNamedType(schemaConfig.query), - mutation: schemaConfig.mutation && replaceNamedType(schemaConfig.mutation), - subscription: - schemaConfig.subscription && replaceNamedType(schemaConfig.subscription), - // Then, incorporate schema definition and all schema extensions. - ...(schemaDef && getOperationTypes([schemaDef])), - ...getOperationTypes(schemaExtensions), - }; - - // Then produce and return a Schema config with these types. - return { - description: schemaDef?.description?.value ?? schemaConfig.description, - ...operationTypes, - types: Array.from(typeMap.values()), - directives: [ - ...schemaConfig.directives.map(replaceDirective), - ...directiveDefs.map(buildDirective), - ], - extensions: schemaConfig.extensions, - astNode: schemaDef ?? schemaConfig.astNode, - extensionASTNodes: schemaConfig.extensionASTNodes.concat(schemaExtensions), - assumeValid: options?.assumeValid ?? false, - }; - - // Below are functions used for producing this schema that have closed over - // this scope and have access to the schema, cache, and newly defined types. - - function replaceType(type: T): T { - if (isListType(type)) { - // @ts-expect-error - return new GraphQLList(replaceType(type.ofType)); - } - if (isNonNullType(type)) { - // @ts-expect-error - return new GraphQLNonNull(replaceType(type.ofType)); - } - // @ts-expect-error FIXME - return replaceNamedType(type); - } + // Then produce and return a Schema config with these types. + return { + description: schemaDef?.description?.value ?? config.description, + ...operationTypes, + types: getNamedTypes(), + directives: [ + ...config.directives, + ...directiveDefs.map(buildDirective), + ], + extensions: config.extensions, + astNode: schemaDef ?? config.astNode, + extensionASTNodes: config.extensionASTNodes.concat(schemaExtensions), + assumeValid: options?.assumeValid ?? false, + }; + }, + [SchemaElementKind.INPUT_OBJECT]: (config) => { + const extensions = inputObjectExtensions.get(config.name) ?? []; + return { + ...config, + fields: () => ({ + ...config.fields(), + ...buildInputFieldMap(extensions), + }), + extensionASTNodes: config.extensionASTNodes.concat(extensions), + }; + }, + [SchemaElementKind.ENUM]: (config) => { + const extensions = enumExtensions.get(config.name) ?? []; + return { + ...config, + values: () => ({ + ...config.values(), + ...buildEnumValueMap(extensions), + }), + extensionASTNodes: config.extensionASTNodes.concat(extensions), + }; + }, + [SchemaElementKind.SCALAR]: (config) => { + const extensions = scalarExtensions.get(config.name) ?? []; + let specifiedByURL = config.specifiedByURL; + for (const extensionNode of extensions) { + specifiedByURL = getSpecifiedByURL(extensionNode) ?? specifiedByURL; + } + return { + ...config, + specifiedByURL, + extensionASTNodes: config.extensionASTNodes.concat(extensions), + }; + }, + [SchemaElementKind.OBJECT]: (config) => { + const extensions = objectExtensions.get(config.name) ?? []; + return { + ...config, + interfaces: () => [ + ...config.interfaces(), + ...buildInterfaces(extensions), + ], + fields: () => ({ + ...config.fields(), + ...buildFieldMap(extensions), + }), + extensionASTNodes: config.extensionASTNodes.concat(extensions), + }; + }, + [SchemaElementKind.INTERFACE]: (config) => { + const extensions = interfaceExtensions.get(config.name) ?? []; + return { + ...config, + interfaces: () => [ + ...config.interfaces(), + ...buildInterfaces(extensions), + ], + fields: () => ({ + ...config.fields(), + ...buildFieldMap(extensions), + }), + extensionASTNodes: config.extensionASTNodes.concat(extensions), + }; + }, + [SchemaElementKind.UNION]: (config) => { + const extensions = unionExtensions.get(config.name) ?? []; + return { + ...config, + types: () => [...config.types(), ...buildUnionTypes(extensions)], + extensionASTNodes: config.extensionASTNodes.concat(extensions), + }; + }, + }; - function replaceNamedType(type: T): T { - // Note: While this could make early assertions to get the correctly - // typed values, that would throw immediately while type system - // validation with validateSchema() will produce more actionable results. - return typeMap.get(type.name) as T; - } + function getOperationTypes( + nodes: ReadonlyArray, + ): { + query?: Maybe; + mutation?: Maybe; + subscription?: Maybe; + } { + const opTypes = {}; + for (const node of nodes) { + const operationTypesNodes = node.operationTypes ?? []; + + for (const operationType of operationTypesNodes) { + // Note: While this could make early assertions to get the correctly + // typed values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + // @ts-expect-error + opTypes[operationType.operation] = namedTypeFromAST( + operationType.type, + ); + } + } - function replaceDirective(directive: GraphQLDirective): GraphQLDirective { - if (isSpecifiedDirective(directive)) { - // Builtin directives are not extended. - return directive; + return opTypes; } - const config = directive.toConfig(); - return new GraphQLDirective({ - ...config, - args: mapValue(config.args, extendArg), - }); - } - - function extendNamedType(type: GraphQLNamedType): GraphQLNamedType { - if (isIntrospectionType(type) || isSpecifiedScalarType(type)) { - // Builtin types are not extended. + function namedTypeFromAST(node: NamedTypeNode): GraphQLNamedType { + const name = node.name.value; + const type = getNamedType(name); + invariant(type !== undefined, `Unknown type: "${name}".`); return type; } - if (isScalarType(type)) { - return extendScalarType(type); - } - if (isObjectType(type)) { - return extendObjectType(type); - } - if (isInterfaceType(type)) { - return extendInterfaceType(type); - } - if (isUnionType(type)) { - return extendUnionType(type); - } - if (isEnumType(type)) { - return extendEnumType(type); - } - if (isInputObjectType(type)) { - return extendInputObjectType(type); - } - /* c8 ignore next 3 */ - // Not reachable, all possible type definition nodes have been considered. - invariant(false, 'Unexpected type: ' + inspect(type)); - } - - function extendInputObjectType( - type: GraphQLInputObjectType, - ): GraphQLInputObjectType { - const config = type.toConfig(); - const extensions = inputObjectExtensions.get(config.name) ?? []; - - return new GraphQLInputObjectType({ - ...config, - fields: () => ({ - ...mapValue(config.fields, (field) => ({ - ...field, - type: replaceType(field.type), - })), - ...buildInputFieldMap(extensions), - }), - extensionASTNodes: config.extensionASTNodes.concat(extensions), - }); - } - function extendEnumType(type: GraphQLEnumType): GraphQLEnumType { - const config = type.toConfig(); - const extensions = enumExtensions.get(type.name) ?? []; - - return new GraphQLEnumType({ - ...config, - values: { - ...config.values, - ...buildEnumValueMap(extensions), - }, - extensionASTNodes: config.extensionASTNodes.concat(extensions), - }); - } - - function extendScalarType(type: GraphQLScalarType): GraphQLScalarType { - const config = type.toConfig(); - const extensions = scalarExtensions.get(config.name) ?? []; - - let specifiedByURL = config.specifiedByURL; - for (const extensionNode of extensions) { - specifiedByURL = getSpecifiedByURL(extensionNode) ?? specifiedByURL; - } - - return new GraphQLScalarType({ - ...config, - specifiedByURL, - extensionASTNodes: config.extensionASTNodes.concat(extensions), - }); - } - - function extendObjectType(type: GraphQLObjectType): GraphQLObjectType { - const config = type.toConfig(); - const extensions = objectExtensions.get(config.name) ?? []; - - return new GraphQLObjectType({ - ...config, - interfaces: () => [ - ...type.getInterfaces().map(replaceNamedType), - ...buildInterfaces(extensions), - ], - fields: () => ({ - ...mapValue(config.fields, extendField), - ...buildFieldMap(extensions), - }), - extensionASTNodes: config.extensionASTNodes.concat(extensions), - }); - } - - function extendInterfaceType( - type: GraphQLInterfaceType, - ): GraphQLInterfaceType { - const config = type.toConfig(); - const extensions = interfaceExtensions.get(config.name) ?? []; - - return new GraphQLInterfaceType({ - ...config, - interfaces: () => [ - ...type.getInterfaces().map(replaceNamedType), - ...buildInterfaces(extensions), - ], - fields: () => ({ - ...mapValue(config.fields, extendField), - ...buildFieldMap(extensions), - }), - extensionASTNodes: config.extensionASTNodes.concat(extensions), - }); - } - - function extendUnionType(type: GraphQLUnionType): GraphQLUnionType { - const config = type.toConfig(); - const extensions = unionExtensions.get(config.name) ?? []; - - return new GraphQLUnionType({ - ...config, - types: () => [ - ...type.getTypes().map(replaceNamedType), - ...buildUnionTypes(extensions), - ], - extensionASTNodes: config.extensionASTNodes.concat(extensions), - }); - } - - function extendField( - field: GraphQLFieldConfig, - ): GraphQLFieldConfig { - return { - ...field, - type: replaceType(field.type), - args: field.args && mapValue(field.args, extendArg), - }; - } - - function extendArg(arg: GraphQLArgumentConfig) { - return { - ...arg, - type: replaceType(arg.type), - }; - } - - function getOperationTypes( - nodes: ReadonlyArray, - ): { - query?: Maybe; - mutation?: Maybe; - subscription?: Maybe; - } { - const opTypes = {}; - for (const node of nodes) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const operationTypesNodes = - /* c8 ignore next */ node.operationTypes ?? []; - - for (const operationType of operationTypesNodes) { - // Note: While this could make early assertions to get the correctly - // typed values below, that would throw immediately while type system - // validation with validateSchema() will produce more actionable results. - // @ts-expect-error - opTypes[operationType.operation] = getNamedType(operationType.type); + function typeFromAST(node: TypeNode): GraphQLType { + if (node.kind === Kind.LIST_TYPE) { + return new GraphQLList(typeFromAST(node.type)); + } + if (node.kind === Kind.NON_NULL_TYPE) { + return new GraphQLNonNull(typeFromAST(node.type)); } + return namedTypeFromAST(node); } - return opTypes; - } - - function getNamedType(node: NamedTypeNode): GraphQLNamedType { - const name = node.name.value; - const type = stdTypeMap.get(name) ?? typeMap.get(name); - - if (type === undefined) { - throw new Error(`Unknown type: "${name}".`); - } - return type; - } - - function getWrappedType(node: TypeNode): GraphQLType { - if (node.kind === Kind.LIST_TYPE) { - return new GraphQLList(getWrappedType(node.type)); - } - if (node.kind === Kind.NON_NULL_TYPE) { - return new GraphQLNonNull(getWrappedType(node.type)); + function buildDirective(node: DirectiveDefinitionNode): GraphQLDirective { + return new GraphQLDirective({ + name: node.name.value, + description: node.description?.value, + // @ts-expect-error + locations: node.locations.map(({ value }) => value), + isRepeatable: node.repeatable, + args: buildArgumentMap(node.arguments), + astNode: node, + }); } - return getNamedType(node); - } - - function buildDirective(node: DirectiveDefinitionNode): GraphQLDirective { - return new GraphQLDirective({ - name: node.name.value, - description: node.description?.value, - // @ts-expect-error - locations: node.locations.map(({ value }) => value), - isRepeatable: node.repeatable, - args: buildArgumentMap(node.arguments), - astNode: node, - }); - } - function buildFieldMap( - nodes: ReadonlyArray< - | InterfaceTypeDefinitionNode - | InterfaceTypeExtensionNode - | ObjectTypeDefinitionNode - | ObjectTypeExtensionNode - >, - ): GraphQLFieldConfigMap { - const fieldConfigMap = Object.create(null); - for (const node of nodes) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const nodeFields = /* c8 ignore next */ node.fields ?? []; - - for (const field of nodeFields) { - fieldConfigMap[field.name.value] = { - // Note: While this could make assertions to get the correctly typed - // value, that would throw immediately while type system validation - // with validateSchema() will produce more actionable results. - type: getWrappedType(field.type), - description: field.description?.value, - args: buildArgumentMap(field.arguments), - deprecationReason: getDeprecationReason(field), - astNode: field, - }; + function buildFieldMap( + nodes: ReadonlyArray< + | InterfaceTypeDefinitionNode + | InterfaceTypeExtensionNode + | ObjectTypeDefinitionNode + | ObjectTypeExtensionNode + >, + ): GraphQLFieldNormalizedConfigMap { + const fieldConfigMap = Object.create(null); + for (const node of nodes) { + const nodeFields = node.fields ?? []; + + for (const field of nodeFields) { + fieldConfigMap[field.name.value] = { + // Note: While this could make assertions to get the correctly typed + // value, that would throw immediately while type system validation + // with validateSchema() will produce more actionable results. + type: typeFromAST(field.type), + description: field.description?.value, + args: buildArgumentMap(field.arguments), + deprecationReason: getDeprecationReason(field), + astNode: field, + }; + } } + return fieldConfigMap; } - return fieldConfigMap; - } - - function buildArgumentMap( - args: Maybe>, - ): GraphQLFieldConfigArgumentMap { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const argsNodes = /* c8 ignore next */ args ?? []; - const argConfigMap = Object.create(null); - for (const arg of argsNodes) { - // Note: While this could make assertions to get the correctly typed - // value, that would throw immediately while type system validation - // with validateSchema() will produce more actionable results. - const type: any = getWrappedType(arg.type); - - argConfigMap[arg.name.value] = { - type, - description: arg.description?.value, - defaultValue: valueFromAST(arg.defaultValue, type), - deprecationReason: getDeprecationReason(arg), - astNode: arg, - }; - } - return argConfigMap; - } + function buildArgumentMap( + args: Maybe>, + ): GraphQLFieldConfigArgumentMap { + const argsNodes = args ?? []; - function buildInputFieldMap( - nodes: ReadonlyArray< - InputObjectTypeDefinitionNode | InputObjectTypeExtensionNode - >, - ): GraphQLInputFieldConfigMap { - const inputFieldMap = Object.create(null); - for (const node of nodes) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const fieldsNodes = /* c8 ignore next */ node.fields ?? []; - - for (const field of fieldsNodes) { + const argConfigMap = Object.create(null); + for (const arg of argsNodes) { // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. - const type: any = getWrappedType(field.type); + const type: any = typeFromAST(arg.type); - inputFieldMap[field.name.value] = { + argConfigMap[arg.name.value] = { type, - description: field.description?.value, - defaultValue: valueFromAST(field.defaultValue, type), - deprecationReason: getDeprecationReason(field), - astNode: field, + description: arg.description?.value, + default: arg.defaultValue && { literal: arg.defaultValue }, + deprecationReason: getDeprecationReason(arg), + astNode: arg, }; } + return argConfigMap; } - return inputFieldMap; - } - function buildEnumValueMap( - nodes: ReadonlyArray, - ): GraphQLEnumValueConfigMap { - const enumValueMap = Object.create(null); - for (const node of nodes) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const valuesNodes = /* c8 ignore next */ node.values ?? []; - - for (const value of valuesNodes) { - enumValueMap[value.name.value] = { - description: value.description?.value, - deprecationReason: getDeprecationReason(value), - astNode: value, - }; + function buildInputFieldMap( + nodes: ReadonlyArray< + InputObjectTypeDefinitionNode | InputObjectTypeExtensionNode + >, + ): GraphQLInputFieldNormalizedConfigMap { + const inputFieldMap = Object.create(null); + for (const node of nodes) { + const fieldsNodes = node.fields ?? []; + + for (const field of fieldsNodes) { + // Note: While this could make assertions to get the correctly typed + // value, that would throw immediately while type system validation + // with validateSchema() will produce more actionable results. + const type: any = typeFromAST(field.type); + + inputFieldMap[field.name.value] = { + type, + description: field.description?.value, + default: field.defaultValue && { literal: field.defaultValue }, + deprecationReason: getDeprecationReason(field), + astNode: field, + }; + } } + return inputFieldMap; } - return enumValueMap; - } - function buildInterfaces( - nodes: ReadonlyArray< - | InterfaceTypeDefinitionNode - | InterfaceTypeExtensionNode - | ObjectTypeDefinitionNode - | ObjectTypeExtensionNode - >, - ): Array { - // Note: While this could make assertions to get the correctly typed - // values below, that would throw immediately while type system - // validation with validateSchema() will produce more actionable results. - // @ts-expect-error - return nodes.flatMap( - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - (node) => /* c8 ignore next */ node.interfaces?.map(getNamedType) ?? [], - ); - } + function buildEnumValueMap( + nodes: ReadonlyArray, + ): GraphQLEnumValueNormalizedConfigMap { + const enumValueMap = Object.create(null); + for (const node of nodes) { + const valuesNodes = node.values ?? []; + + for (const value of valuesNodes) { + enumValueMap[value.name.value] = { + description: value.description?.value, + deprecationReason: getDeprecationReason(value), + astNode: value, + }; + } + } + return enumValueMap; + } - function buildUnionTypes( - nodes: ReadonlyArray, - ): Array { - // Note: While this could make assertions to get the correctly typed - // values below, that would throw immediately while type system - // validation with validateSchema() will produce more actionable results. - // @ts-expect-error - return nodes.flatMap( - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - (node) => /* c8 ignore next */ node.types?.map(getNamedType) ?? [], - ); - } + function buildInterfaces( + nodes: ReadonlyArray< + | InterfaceTypeDefinitionNode + | InterfaceTypeExtensionNode + | ObjectTypeDefinitionNode + | ObjectTypeExtensionNode + >, + ): Array { + // Note: While this could make assertions to get the correctly typed + // values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + // @ts-expect-error + return nodes.flatMap( + (node) => node.interfaces?.map(namedTypeFromAST) ?? [], + ); + } - function buildType(astNode: TypeDefinitionNode): GraphQLNamedType { - const name = astNode.name.value; - - switch (astNode.kind) { - case Kind.OBJECT_TYPE_DEFINITION: { - const extensionASTNodes = objectExtensions.get(name) ?? []; - const allNodes = [astNode, ...extensionASTNodes]; - - return new GraphQLObjectType({ - name, - description: astNode.description?.value, - interfaces: () => buildInterfaces(allNodes), - fields: () => buildFieldMap(allNodes), - astNode, - extensionASTNodes, - }); - } - case Kind.INTERFACE_TYPE_DEFINITION: { - const extensionASTNodes = interfaceExtensions.get(name) ?? []; - const allNodes = [astNode, ...extensionASTNodes]; - - return new GraphQLInterfaceType({ - name, - description: astNode.description?.value, - interfaces: () => buildInterfaces(allNodes), - fields: () => buildFieldMap(allNodes), - astNode, - extensionASTNodes, - }); - } - case Kind.ENUM_TYPE_DEFINITION: { - const extensionASTNodes = enumExtensions.get(name) ?? []; - const allNodes = [astNode, ...extensionASTNodes]; - - return new GraphQLEnumType({ - name, - description: astNode.description?.value, - values: buildEnumValueMap(allNodes), - astNode, - extensionASTNodes, - }); - } - case Kind.UNION_TYPE_DEFINITION: { - const extensionASTNodes = unionExtensions.get(name) ?? []; - const allNodes = [astNode, ...extensionASTNodes]; - - return new GraphQLUnionType({ - name, - description: astNode.description?.value, - types: () => buildUnionTypes(allNodes), - astNode, - extensionASTNodes, - }); - } - case Kind.SCALAR_TYPE_DEFINITION: { - const extensionASTNodes = scalarExtensions.get(name) ?? []; - return new GraphQLScalarType({ - name, - description: astNode.description?.value, - specifiedByURL: getSpecifiedByURL(astNode), - astNode, - extensionASTNodes, - }); - } - case Kind.INPUT_OBJECT_TYPE_DEFINITION: { - const extensionASTNodes = inputObjectExtensions.get(name) ?? []; - const allNodes = [astNode, ...extensionASTNodes]; - - return new GraphQLInputObjectType({ - name, - description: astNode.description?.value, - fields: () => buildInputFieldMap(allNodes), - astNode, - extensionASTNodes, - isOneOf: isOneOf(astNode), - }); + function buildUnionTypes( + nodes: ReadonlyArray, + ): Array { + // Note: While this could make assertions to get the correctly typed + // values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + // @ts-expect-error + return nodes.flatMap((node) => node.types?.map(namedTypeFromAST) ?? []); + } + + function buildNamedType(astNode: TypeDefinitionNode): GraphQLNamedType { + const name = astNode.name.value; + + switch (astNode.kind) { + case Kind.OBJECT_TYPE_DEFINITION: { + const extensionASTNodes = objectExtensions.get(name) ?? []; + const allNodes = [astNode, ...extensionASTNodes]; + + return new GraphQLObjectType({ + name, + description: astNode.description?.value, + interfaces: () => buildInterfaces(allNodes), + fields: () => buildFieldMap(allNodes), + astNode, + extensionASTNodes, + }); + } + case Kind.INTERFACE_TYPE_DEFINITION: { + const extensionASTNodes = interfaceExtensions.get(name) ?? []; + const allNodes = [astNode, ...extensionASTNodes]; + + return new GraphQLInterfaceType({ + name, + description: astNode.description?.value, + interfaces: () => buildInterfaces(allNodes), + fields: () => buildFieldMap(allNodes), + astNode, + extensionASTNodes, + }); + } + case Kind.ENUM_TYPE_DEFINITION: { + const extensionASTNodes = enumExtensions.get(name) ?? []; + const allNodes = [astNode, ...extensionASTNodes]; + + return new GraphQLEnumType({ + name, + description: astNode.description?.value, + values: () => buildEnumValueMap(allNodes), + astNode, + extensionASTNodes, + }); + } + case Kind.UNION_TYPE_DEFINITION: { + const extensionASTNodes = unionExtensions.get(name) ?? []; + const allNodes = [astNode, ...extensionASTNodes]; + + return new GraphQLUnionType({ + name, + description: astNode.description?.value, + types: () => buildUnionTypes(allNodes), + astNode, + extensionASTNodes, + }); + } + case Kind.SCALAR_TYPE_DEFINITION: { + const extensionASTNodes = scalarExtensions.get(name) ?? []; + return new GraphQLScalarType({ + name, + description: astNode.description?.value, + specifiedByURL: getSpecifiedByURL(astNode), + astNode, + extensionASTNodes, + }); + } + case Kind.INPUT_OBJECT_TYPE_DEFINITION: { + const extensionASTNodes = inputObjectExtensions.get(name) ?? []; + const allNodes = [astNode, ...extensionASTNodes]; + + return new GraphQLInputObjectType({ + name, + description: astNode.description?.value, + fields: () => buildInputFieldMap(allNodes), + astNode, + extensionASTNodes, + isOneOf: isOneOf(astNode), + }); + } } } - } + }); } const stdTypeMap = new Map( diff --git a/src/utilities/findBreakingChanges.ts b/src/utilities/findSchemaChanges.ts similarity index 53% rename from src/utilities/findBreakingChanges.ts rename to src/utilities/findSchemaChanges.ts index 793d29bc83..4599ae489b 100644 --- a/src/utilities/findBreakingChanges.ts +++ b/src/utilities/findSchemaChanges.ts @@ -5,10 +5,11 @@ import { keyMap } from '../jsutils/keyMap.js'; import { print } from '../language/printer.js'; import type { + GraphQLArgument, GraphQLEnumType, GraphQLField, + GraphQLInputField, GraphQLInputObjectType, - GraphQLInputType, GraphQLInterfaceType, GraphQLNamedType, GraphQLObjectType, @@ -31,36 +32,60 @@ import { import { isSpecifiedScalarType } from '../type/scalars.js'; import type { GraphQLSchema } from '../type/schema.js'; -import { astFromValue } from './astFromValue.js'; +import { getDefaultValueAST } from './getDefaultValueAST.js'; import { sortValueNode } from './sortValueNode.js'; -export enum BreakingChangeType { - TYPE_REMOVED = 'TYPE_REMOVED', - TYPE_CHANGED_KIND = 'TYPE_CHANGED_KIND', - TYPE_REMOVED_FROM_UNION = 'TYPE_REMOVED_FROM_UNION', - VALUE_REMOVED_FROM_ENUM = 'VALUE_REMOVED_FROM_ENUM', - REQUIRED_INPUT_FIELD_ADDED = 'REQUIRED_INPUT_FIELD_ADDED', - IMPLEMENTED_INTERFACE_REMOVED = 'IMPLEMENTED_INTERFACE_REMOVED', - FIELD_REMOVED = 'FIELD_REMOVED', - FIELD_CHANGED_KIND = 'FIELD_CHANGED_KIND', - REQUIRED_ARG_ADDED = 'REQUIRED_ARG_ADDED', - ARG_REMOVED = 'ARG_REMOVED', - ARG_CHANGED_KIND = 'ARG_CHANGED_KIND', - DIRECTIVE_REMOVED = 'DIRECTIVE_REMOVED', - DIRECTIVE_ARG_REMOVED = 'DIRECTIVE_ARG_REMOVED', - REQUIRED_DIRECTIVE_ARG_ADDED = 'REQUIRED_DIRECTIVE_ARG_ADDED', - DIRECTIVE_REPEATABLE_REMOVED = 'DIRECTIVE_REPEATABLE_REMOVED', - DIRECTIVE_LOCATION_REMOVED = 'DIRECTIVE_LOCATION_REMOVED', -} - -export enum DangerousChangeType { - VALUE_ADDED_TO_ENUM = 'VALUE_ADDED_TO_ENUM', - TYPE_ADDED_TO_UNION = 'TYPE_ADDED_TO_UNION', - OPTIONAL_INPUT_FIELD_ADDED = 'OPTIONAL_INPUT_FIELD_ADDED', - OPTIONAL_ARG_ADDED = 'OPTIONAL_ARG_ADDED', - IMPLEMENTED_INTERFACE_ADDED = 'IMPLEMENTED_INTERFACE_ADDED', - ARG_DEFAULT_VALUE_CHANGE = 'ARG_DEFAULT_VALUE_CHANGE', -} +export const BreakingChangeType = { + TYPE_REMOVED: 'TYPE_REMOVED' as const, + TYPE_CHANGED_KIND: 'TYPE_CHANGED_KIND' as const, + TYPE_REMOVED_FROM_UNION: 'TYPE_REMOVED_FROM_UNION' as const, + VALUE_REMOVED_FROM_ENUM: 'VALUE_REMOVED_FROM_ENUM' as const, + REQUIRED_INPUT_FIELD_ADDED: 'REQUIRED_INPUT_FIELD_ADDED' as const, + IMPLEMENTED_INTERFACE_REMOVED: 'IMPLEMENTED_INTERFACE_REMOVED' as const, + FIELD_REMOVED: 'FIELD_REMOVED' as const, + FIELD_CHANGED_KIND: 'FIELD_CHANGED_KIND' as const, + REQUIRED_ARG_ADDED: 'REQUIRED_ARG_ADDED' as const, + ARG_REMOVED: 'ARG_REMOVED' as const, + ARG_CHANGED_KIND: 'ARG_CHANGED_KIND' as const, + DIRECTIVE_REMOVED: 'DIRECTIVE_REMOVED' as const, + DIRECTIVE_ARG_REMOVED: 'DIRECTIVE_ARG_REMOVED' as const, + REQUIRED_DIRECTIVE_ARG_ADDED: 'REQUIRED_DIRECTIVE_ARG_ADDED' as const, + DIRECTIVE_REPEATABLE_REMOVED: 'DIRECTIVE_REPEATABLE_REMOVED' as const, + DIRECTIVE_LOCATION_REMOVED: 'DIRECTIVE_LOCATION_REMOVED' as const, +} as const; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type BreakingChangeType = + (typeof BreakingChangeType)[keyof typeof BreakingChangeType]; + +export const DangerousChangeType = { + VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM' as const, + TYPE_ADDED_TO_UNION: 'TYPE_ADDED_TO_UNION' as const, + OPTIONAL_INPUT_FIELD_ADDED: 'OPTIONAL_INPUT_FIELD_ADDED' as const, + OPTIONAL_ARG_ADDED: 'OPTIONAL_ARG_ADDED' as const, + IMPLEMENTED_INTERFACE_ADDED: 'IMPLEMENTED_INTERFACE_ADDED' as const, + ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE' as const, +}; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type DangerousChangeType = + (typeof DangerousChangeType)[keyof typeof DangerousChangeType]; + +export const SafeChangeType = { + DESCRIPTION_CHANGED: 'DESCRIPTION_CHANGED' as const, + TYPE_ADDED: 'TYPE_ADDED' as const, + OPTIONAL_INPUT_FIELD_ADDED: 'OPTIONAL_INPUT_FIELD_ADDED' as const, + OPTIONAL_ARG_ADDED: 'OPTIONAL_ARG_ADDED' as const, + DIRECTIVE_ADDED: 'DIRECTIVE_ADDED' as const, + FIELD_ADDED: 'FIELD_ADDED' as const, + DIRECTIVE_REPEATABLE_ADDED: 'DIRECTIVE_REPEATABLE_ADDED' as const, + DIRECTIVE_LOCATION_ADDED: 'DIRECTIVE_LOCATION_ADDED' as const, + OPTIONAL_DIRECTIVE_ARG_ADDED: 'OPTIONAL_DIRECTIVE_ARG_ADDED' as const, + FIELD_CHANGED_KIND_SAFE: 'FIELD_CHANGED_KIND_SAFE' as const, + ARG_CHANGED_KIND_SAFE: 'ARG_CHANGED_KIND_SAFE' as const, + ARG_DEFAULT_VALUE_ADDED: 'ARG_DEFAULT_VALUE_ADDED' as const, +}; +// eslint-disable-next-line @typescript-eslint/no-redeclare +export type SafeChangeType = + (typeof SafeChangeType)[keyof typeof SafeChangeType]; export interface BreakingChange { type: BreakingChangeType; @@ -72,9 +97,18 @@ export interface DangerousChange { description: string; } +export interface SafeChange { + type: SafeChangeType; + description: string; +} + +export type SchemaChange = SafeChange | DangerousChange | BreakingChange; + /** * Given two schemas, returns an Array containing descriptions of all the types * of breaking changes covered by the other functions down below. + * + * @deprecated Please use `findSchemaChanges` instead. Will be removed in v18. */ export function findBreakingChanges( oldSchema: GraphQLSchema, @@ -89,6 +123,8 @@ export function findBreakingChanges( /** * Given two schemas, returns an Array containing descriptions of all the types * of potentially dangerous changes covered by the other functions down below. + * + * @deprecated Please use `findSchemaChanges` instead. Will be removed in v18. */ export function findDangerousChanges( oldSchema: GraphQLSchema, @@ -100,10 +136,10 @@ export function findDangerousChanges( ); } -function findSchemaChanges( +export function findSchemaChanges( oldSchema: GraphQLSchema, newSchema: GraphQLSchema, -): Array { +): Array { return [ ...findTypeChanges(oldSchema, newSchema), ...findDirectiveChanges(oldSchema, newSchema), @@ -113,7 +149,7 @@ function findSchemaChanges( function findDirectiveChanges( oldSchema: GraphQLSchema, newSchema: GraphQLSchema, -): Array { +): Array { const schemaChanges = []; const directivesDiff = diff( @@ -124,7 +160,14 @@ function findDirectiveChanges( for (const oldDirective of directivesDiff.removed) { schemaChanges.push({ type: BreakingChangeType.DIRECTIVE_REMOVED, - description: `${oldDirective.name} was removed.`, + description: `Directive ${oldDirective} was removed.`, + }); + } + + for (const newDirective of directivesDiff.added) { + schemaChanges.push({ + type: SafeChangeType.DIRECTIVE_ADDED, + description: `Directive @${newDirective.name} was added.`, }); } @@ -135,7 +178,12 @@ function findDirectiveChanges( if (isRequiredArgument(newArg)) { schemaChanges.push({ type: BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED, - description: `A required arg ${newArg.name} on directive ${oldDirective.name} was added.`, + description: `A required argument ${newArg} was added.`, + }); + } else { + schemaChanges.push({ + type: SafeChangeType.OPTIONAL_DIRECTIVE_ARG_ADDED, + description: `An optional argument @${oldDirective.name}(${newArg.name}:) was added.`, }); } } @@ -143,14 +191,78 @@ function findDirectiveChanges( for (const oldArg of argsDiff.removed) { schemaChanges.push({ type: BreakingChangeType.DIRECTIVE_ARG_REMOVED, - description: `${oldArg.name} was removed from ${oldDirective.name}.`, + description: `Argument ${oldArg} was removed.`, }); } + for (const [oldArg, newArg] of argsDiff.persisted) { + const isSafe = isChangeSafeForInputObjectFieldOrFieldArg( + oldArg.type, + newArg.type, + ); + + const oldDefaultValueStr = getDefaultValue(oldArg); + const newDefaultValueStr = getDefaultValue(newArg); + if (!isSafe) { + schemaChanges.push({ + type: BreakingChangeType.ARG_CHANGED_KIND, + description: + `Argument @${oldDirective.name}(${oldArg.name}:) has changed type from ` + + `${String(oldArg.type)} to ${String(newArg.type)}.`, + }); + } else if (oldDefaultValueStr !== undefined) { + if (newDefaultValueStr === undefined) { + schemaChanges.push({ + type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, + description: `@${oldDirective.name}(${oldArg.name}:) defaultValue was removed.`, + }); + } else if (oldDefaultValueStr !== newDefaultValueStr) { + schemaChanges.push({ + type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, + description: `@${oldDirective.name}(${oldArg.name}:) has changed defaultValue from ${oldDefaultValueStr} to ${newDefaultValueStr}.`, + }); + } + } else if ( + newDefaultValueStr !== undefined && + oldDefaultValueStr === undefined + ) { + schemaChanges.push({ + type: SafeChangeType.ARG_DEFAULT_VALUE_ADDED, + description: `@${oldDirective.name}(${oldArg.name}:) added a defaultValue ${newDefaultValueStr}.`, + }); + } else if (oldArg.type.toString() !== newArg.type.toString()) { + schemaChanges.push({ + type: SafeChangeType.ARG_CHANGED_KIND_SAFE, + description: + `Argument @${oldDirective.name}(${oldArg.name}:) has changed type from ` + + `${String(oldArg.type)} to ${String(newArg.type)}.`, + }); + } + + if (oldArg.description !== newArg.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of @${oldDirective.name}(${oldDirective.name}) has changed to "${newArg.description}".`, + }); + } + } + if (oldDirective.isRepeatable && !newDirective.isRepeatable) { schemaChanges.push({ type: BreakingChangeType.DIRECTIVE_REPEATABLE_REMOVED, - description: `Repeatable flag was removed from ${oldDirective.name}.`, + description: `Repeatable flag was removed from ${oldDirective}.`, + }); + } else if (newDirective.isRepeatable && !oldDirective.isRepeatable) { + schemaChanges.push({ + type: SafeChangeType.DIRECTIVE_REPEATABLE_ADDED, + description: `Repeatable flag was added to @${oldDirective.name}.`, + }); + } + + if (oldDirective.description !== newDirective.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of @${oldDirective.name} has changed to "${newDirective.description}".`, }); } @@ -158,7 +270,16 @@ function findDirectiveChanges( if (!newDirective.locations.includes(location)) { schemaChanges.push({ type: BreakingChangeType.DIRECTIVE_LOCATION_REMOVED, - description: `${location} was removed from ${oldDirective.name}.`, + description: `${location} was removed from ${oldDirective}.`, + }); + } + } + + for (const location of newDirective.locations) { + if (!oldDirective.locations.includes(location)) { + schemaChanges.push({ + type: SafeChangeType.DIRECTIVE_LOCATION_ADDED, + description: `${location} was added to @${oldDirective.name}.`, }); } } @@ -170,7 +291,7 @@ function findDirectiveChanges( function findTypeChanges( oldSchema: GraphQLSchema, newSchema: GraphQLSchema, -): Array { +): Array { const schemaChanges = []; const typesDiff = diff( @@ -182,12 +303,26 @@ function findTypeChanges( schemaChanges.push({ type: BreakingChangeType.TYPE_REMOVED, description: isSpecifiedScalarType(oldType) - ? `Standard scalar ${oldType.name} was removed because it is not referenced anymore.` - : `${oldType.name} was removed.`, + ? `Standard scalar ${oldType} was removed because it is not referenced anymore.` + : `${oldType} was removed.`, + }); + } + + for (const newType of typesDiff.added) { + schemaChanges.push({ + type: SafeChangeType.TYPE_ADDED, + description: `${newType} was added.`, }); } for (const [oldType, newType] of typesDiff.persisted) { + if (oldType.description !== newType.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of ${oldType.name} has changed to "${newType.description}".`, + }); + } + if (isEnumType(oldType) && isEnumType(newType)) { schemaChanges.push(...findEnumTypeChanges(oldType, newType)); } else if (isUnionType(oldType) && isUnionType(newType)) { @@ -207,9 +342,9 @@ function findTypeChanges( } else if (oldType.constructor !== newType.constructor) { schemaChanges.push({ type: BreakingChangeType.TYPE_CHANGED_KIND, - description: - `${oldType.name} changed from ` + - `${typeKindName(oldType)} to ${typeKindName(newType)}.`, + description: `${oldType} changed from ${typeKindName( + oldType, + )} to ${typeKindName(newType)}.`, }); } } @@ -220,7 +355,7 @@ function findTypeChanges( function findInputObjectTypeChanges( oldType: GraphQLInputObjectType, newType: GraphQLInputObjectType, -): Array { +): Array { const schemaChanges = []; const fieldsDiff = diff( Object.values(oldType.getFields()), @@ -231,12 +366,12 @@ function findInputObjectTypeChanges( if (isRequiredInputField(newField)) { schemaChanges.push({ type: BreakingChangeType.REQUIRED_INPUT_FIELD_ADDED, - description: `A required field ${newField.name} on input type ${oldType.name} was added.`, + description: `A required field ${newField} was added.`, }); } else { schemaChanges.push({ type: DangerousChangeType.OPTIONAL_INPUT_FIELD_ADDED, - description: `An optional field ${newField.name} on input type ${oldType.name} was added.`, + description: `An optional field ${newField} was added.`, }); } } @@ -244,7 +379,7 @@ function findInputObjectTypeChanges( for (const oldField of fieldsDiff.removed) { schemaChanges.push({ type: BreakingChangeType.FIELD_REMOVED, - description: `${oldType.name}.${oldField.name} was removed.`, + description: `Field ${oldField} was removed.`, }); } @@ -256,11 +391,23 @@ function findInputObjectTypeChanges( if (!isSafe) { schemaChanges.push({ type: BreakingChangeType.FIELD_CHANGED_KIND, + description: `Field ${newField} changed type from ${oldField.type} to ${newField.type}.`, + }); + } else if (oldField.type.toString() !== newField.type.toString()) { + schemaChanges.push({ + type: SafeChangeType.FIELD_CHANGED_KIND_SAFE, description: - `${oldType.name}.${oldField.name} changed type from ` + + `Field ${oldType}.${oldField.name} changed type from ` + `${String(oldField.type)} to ${String(newField.type)}.`, }); } + + if (oldField.description !== newField.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of input-field ${newType}.${newField.name} has changed to "${newField.description}".`, + }); + } } return schemaChanges; @@ -276,14 +423,14 @@ function findUnionTypeChanges( for (const newPossibleType of possibleTypesDiff.added) { schemaChanges.push({ type: DangerousChangeType.TYPE_ADDED_TO_UNION, - description: `${newPossibleType.name} was added to union type ${oldType.name}.`, + description: `${newPossibleType} was added to union type ${oldType}.`, }); } for (const oldPossibleType of possibleTypesDiff.removed) { schemaChanges.push({ type: BreakingChangeType.TYPE_REMOVED_FROM_UNION, - description: `${oldPossibleType.name} was removed from union type ${oldType.name}.`, + description: `${oldPossibleType} was removed from union type ${oldType}.`, }); } @@ -293,24 +440,33 @@ function findUnionTypeChanges( function findEnumTypeChanges( oldType: GraphQLEnumType, newType: GraphQLEnumType, -): Array { +): Array { const schemaChanges = []; const valuesDiff = diff(oldType.getValues(), newType.getValues()); for (const newValue of valuesDiff.added) { schemaChanges.push({ type: DangerousChangeType.VALUE_ADDED_TO_ENUM, - description: `${newValue.name} was added to enum type ${oldType.name}.`, + description: `Enum value ${newValue} was added.`, }); } for (const oldValue of valuesDiff.removed) { schemaChanges.push({ type: BreakingChangeType.VALUE_REMOVED_FROM_ENUM, - description: `${oldValue.name} was removed from enum type ${oldType.name}.`, + description: `Enum value ${oldValue} was removed.`, }); } + for (const [oldValue, newValue] of valuesDiff.persisted) { + if (oldValue.description !== newValue.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of enum value ${oldType}.${oldValue.name} has changed to "${newValue.description}".`, + }); + } + } + return schemaChanges; } @@ -324,14 +480,14 @@ function findImplementedInterfacesChanges( for (const newInterface of interfacesDiff.added) { schemaChanges.push({ type: DangerousChangeType.IMPLEMENTED_INTERFACE_ADDED, - description: `${newInterface.name} added to interfaces implemented by ${oldType.name}.`, + description: `${newInterface} added to interfaces implemented by ${oldType}.`, }); } for (const oldInterface of interfacesDiff.removed) { schemaChanges.push({ type: BreakingChangeType.IMPLEMENTED_INTERFACE_REMOVED, - description: `${oldType.name} no longer implements interface ${oldInterface.name}.`, + description: `${oldType} no longer implements interface ${oldInterface}.`, }); } @@ -341,7 +497,7 @@ function findImplementedInterfacesChanges( function findFieldChanges( oldType: GraphQLObjectType | GraphQLInterfaceType, newType: GraphQLObjectType | GraphQLInterfaceType, -): Array { +): Array { const schemaChanges = []; const fieldsDiff = diff( Object.values(oldType.getFields()), @@ -351,12 +507,19 @@ function findFieldChanges( for (const oldField of fieldsDiff.removed) { schemaChanges.push({ type: BreakingChangeType.FIELD_REMOVED, - description: `${oldType.name}.${oldField.name} was removed.`, + description: `Field ${oldField} was removed.`, + }); + } + + for (const newField of fieldsDiff.added) { + schemaChanges.push({ + type: SafeChangeType.FIELD_ADDED, + description: `Field ${oldType}.${newField.name} was added.`, }); } for (const [oldField, newField] of fieldsDiff.persisted) { - schemaChanges.push(...findArgChanges(oldType, oldField, newField)); + schemaChanges.push(...findArgChanges(oldField, newField)); const isSafe = isChangeSafeForObjectOrInterfaceField( oldField.type, @@ -365,28 +528,39 @@ function findFieldChanges( if (!isSafe) { schemaChanges.push({ type: BreakingChangeType.FIELD_CHANGED_KIND, + description: `Field ${newField} changed type from ${oldField.type} to ${newField.type}.`, + }); + } else if (oldField.type.toString() !== newField.type.toString()) { + schemaChanges.push({ + type: SafeChangeType.FIELD_CHANGED_KIND_SAFE, description: - `${oldType.name}.${oldField.name} changed type from ` + + `Field ${oldType}.${oldField.name} changed type from ` + `${String(oldField.type)} to ${String(newField.type)}.`, }); } + + if (oldField.description !== newField.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of field ${oldType}.${oldField.name} has changed to "${newField.description}".`, + }); + } } return schemaChanges; } function findArgChanges( - oldType: GraphQLObjectType | GraphQLInterfaceType, oldField: GraphQLField, newField: GraphQLField, -): Array { +): Array { const schemaChanges = []; const argsDiff = diff(oldField.args, newField.args); for (const oldArg of argsDiff.removed) { schemaChanges.push({ type: BreakingChangeType.ARG_REMOVED, - description: `${oldType.name}.${oldField.name} arg ${oldArg.name} was removed.`, + description: `Argument ${oldArg} was removed.`, }); } @@ -395,33 +569,48 @@ function findArgChanges( oldArg.type, newArg.type, ); + + const oldDefaultValueStr = getDefaultValue(oldArg); + const newDefaultValueStr = getDefaultValue(newArg); if (!isSafe) { schemaChanges.push({ type: BreakingChangeType.ARG_CHANGED_KIND, - description: - `${oldType.name}.${oldField.name} arg ${oldArg.name} has changed type from ` + - `${String(oldArg.type)} to ${String(newArg.type)}.`, + description: `Argument ${newArg} has changed type from ${oldArg.type} to ${newArg.type}.`, }); - } else if (oldArg.defaultValue !== undefined) { - if (newArg.defaultValue === undefined) { + } else if (oldDefaultValueStr !== undefined) { + if (newDefaultValueStr === undefined) { schemaChanges.push({ type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, - description: `${oldType.name}.${oldField.name} arg ${oldArg.name} defaultValue was removed.`, + description: `${oldArg} defaultValue was removed.`, + }); + } else if (oldDefaultValueStr !== newDefaultValueStr) { + schemaChanges.push({ + type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, + description: `${oldArg} has changed defaultValue from ${oldDefaultValueStr} to ${newDefaultValueStr}.`, }); - } else { - // Since we looking only for client's observable changes we should - // compare default values in the same representation as they are - // represented inside introspection. - const oldValueStr = stringifyValue(oldArg.defaultValue, oldArg.type); - const newValueStr = stringifyValue(newArg.defaultValue, newArg.type); - - if (oldValueStr !== newValueStr) { - schemaChanges.push({ - type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, - description: `${oldType.name}.${oldField.name} arg ${oldArg.name} has changed defaultValue from ${oldValueStr} to ${newValueStr}.`, - }); - } } + } else if ( + newDefaultValueStr !== undefined && + oldDefaultValueStr === undefined + ) { + schemaChanges.push({ + type: SafeChangeType.ARG_DEFAULT_VALUE_ADDED, + description: `${oldArg} added a defaultValue ${newDefaultValueStr}.`, + }); + } else if (oldArg.type.toString() !== newArg.type.toString()) { + schemaChanges.push({ + type: SafeChangeType.ARG_CHANGED_KIND_SAFE, + description: + `Argument ${oldArg} has changed type from ` + + `${String(oldArg.type)} to ${String(newArg.type)}.`, + }); + } + + if (oldArg.description !== newArg.description) { + schemaChanges.push({ + type: SafeChangeType.DESCRIPTION_CHANGED, + description: `Description of argument ${oldArg} has changed to "${newArg.description}".`, + }); } } @@ -429,12 +618,12 @@ function findArgChanges( if (isRequiredArgument(newArg)) { schemaChanges.push({ type: BreakingChangeType.REQUIRED_ARG_ADDED, - description: `A required arg ${newArg.name} on ${oldType.name}.${oldField.name} was added.`, + description: `A required argument ${newArg} was added.`, }); } else { schemaChanges.push({ type: DangerousChangeType.OPTIONAL_ARG_ADDED, - description: `An optional arg ${newArg.name} on ${oldType.name}.${oldField.name} was added.`, + description: `An optional argument ${newArg} was added.`, }); } } @@ -532,10 +721,16 @@ function typeKindName(type: GraphQLNamedType): string { invariant(false, 'Unexpected type: ' + inspect(type)); } -function stringifyValue(value: unknown, type: GraphQLInputType): string { - const ast = astFromValue(value, type); - invariant(ast != null); - return print(sortValueNode(ast)); +// Since we looking only for client's observable changes we should +// compare default values in the same representation as they are +// represented inside introspection. +function getDefaultValue( + argOrInputField: GraphQLArgument | GraphQLInputField, +): string | undefined { + const ast = getDefaultValueAST(argOrInputField); + if (ast) { + return print(sortValueNode(ast)); + } } function diff( diff --git a/src/utilities/getDefaultValueAST.ts b/src/utilities/getDefaultValueAST.ts new file mode 100644 index 0000000000..3b2b9342e7 --- /dev/null +++ b/src/utilities/getDefaultValueAST.ts @@ -0,0 +1,29 @@ +import { invariant } from '../jsutils/invariant.js'; + +import type { ConstValueNode } from '../language/ast.js'; + +import type { GraphQLArgument, GraphQLInputField } from '../type/definition.js'; + +import { astFromValue } from './astFromValue.js'; +import { valueToLiteral } from './valueToLiteral.js'; + +export function getDefaultValueAST( + argOrInputField: GraphQLArgument | GraphQLInputField, +): ConstValueNode | undefined { + const type = argOrInputField.type; + const defaultInput = argOrInputField.default; + if (defaultInput) { + const literal = + defaultInput.literal ?? valueToLiteral(defaultInput.value, type); + invariant(literal != null, 'Invalid default value'); + return literal; + } + + const defaultValue = argOrInputField.defaultValue; + if (defaultValue !== undefined) { + const valueAST = astFromValue(defaultValue, type); + invariant(valueAST != null, 'Invalid default value'); + return valueAST; + } + return undefined; +} diff --git a/src/utilities/getIntrospectionQuery.ts b/src/utilities/getIntrospectionQuery.ts index 5eb182bc36..94fdfe59d7 100644 --- a/src/utilities/getIntrospectionQuery.ts +++ b/src/utilities/getIntrospectionQuery.ts @@ -2,6 +2,8 @@ import type { Maybe } from '../jsutils/Maybe.js'; import type { DirectiveLocation } from '../language/directiveLocation.js'; +import type { TypeKind } from '../type/introspection.js'; + export interface IntrospectionOptions { /** * Whether to include descriptions in the introspection result. @@ -32,6 +34,12 @@ export interface IntrospectionOptions { * Default: false */ inputValueDeprecation?: boolean; + + /** + * Whether target GraphQL server supports `@oneOf` input objects. + * Default: false + */ + oneOf?: boolean; } /** @@ -45,6 +53,7 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { directiveIsRepeatable: false, schemaDescription: false, inputValueDeprecation: false, + oneOf: false, ...options, }; @@ -62,14 +71,15 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { function inputDeprecation(str: string) { return optionsWithDefault.inputValueDeprecation ? str : ''; } + const oneOf = optionsWithDefault.oneOf ? 'isOneOf' : ''; return ` query IntrospectionQuery { __schema { ${schemaDescription} - queryType { name } - mutationType { name } - subscriptionType { name } + queryType { name kind } + mutationType { name kind } + subscriptionType { name kind } types { ...FullType } @@ -90,6 +100,7 @@ export function getIntrospectionQuery(options?: IntrospectionOptions): string { name ${descriptions} ${specifiedByUrl} + ${oneOf} fields(includeDeprecated: true) { name ${descriptions} @@ -209,14 +220,14 @@ export type IntrospectionInputType = | IntrospectionInputObjectType; export interface IntrospectionScalarType { - readonly kind: 'SCALAR'; + readonly kind: typeof TypeKind.SCALAR; readonly name: string; readonly description?: Maybe; readonly specifiedByURL?: Maybe; } export interface IntrospectionObjectType { - readonly kind: 'OBJECT'; + readonly kind: typeof TypeKind.OBJECT; readonly name: string; readonly description?: Maybe; readonly fields: ReadonlyArray; @@ -226,7 +237,7 @@ export interface IntrospectionObjectType { } export interface IntrospectionInterfaceType { - readonly kind: 'INTERFACE'; + readonly kind: typeof TypeKind.INTERFACE; readonly name: string; readonly description?: Maybe; readonly fields: ReadonlyArray; @@ -239,7 +250,7 @@ export interface IntrospectionInterfaceType { } export interface IntrospectionUnionType { - readonly kind: 'UNION'; + readonly kind: typeof TypeKind.UNION; readonly name: string; readonly description?: Maybe; readonly possibleTypes: ReadonlyArray< @@ -248,30 +259,31 @@ export interface IntrospectionUnionType { } export interface IntrospectionEnumType { - readonly kind: 'ENUM'; + readonly kind: typeof TypeKind.ENUM; readonly name: string; readonly description?: Maybe; readonly enumValues: ReadonlyArray; } export interface IntrospectionInputObjectType { - readonly kind: 'INPUT_OBJECT'; + readonly kind: typeof TypeKind.INPUT_OBJECT; readonly name: string; readonly description?: Maybe; readonly inputFields: ReadonlyArray; + readonly isOneOf: boolean; } export interface IntrospectionListTypeRef< T extends IntrospectionTypeRef = IntrospectionTypeRef, > { - readonly kind: 'LIST'; + readonly kind: typeof TypeKind.LIST; readonly ofType: T; } export interface IntrospectionNonNullTypeRef< T extends IntrospectionTypeRef = IntrospectionTypeRef, > { - readonly kind: 'NON_NULL'; + readonly kind: typeof TypeKind.NON_NULL; readonly ofType: T; } diff --git a/src/utilities/index.ts b/src/utilities/index.ts index 6968dca4d3..5b891cded1 100644 --- a/src/utilities/index.ts +++ b/src/utilities/index.ts @@ -57,19 +57,42 @@ export { export { typeFromAST } from './typeFromAST.js'; // Create a JavaScript value from a GraphQL language AST with a type. -export { valueFromAST } from './valueFromAST.js'; +export { + /** @deprecated use `coerceInputLiteral()` instead - will be removed in v18 */ + valueFromAST, +} from './valueFromAST.js'; // Create a JavaScript value from a GraphQL language AST without a type. export { valueFromASTUntyped } from './valueFromASTUntyped.js'; // Create a GraphQL language AST from a JavaScript value. -export { astFromValue } from './astFromValue.js'; +export { + /** @deprecated use `valueToLiteral()` instead with care to operate on external values - `astFromValue()` will be removed in v18 */ + astFromValue, +} from './astFromValue.js'; // A helper to use within recursive-descent visitors which need to be aware of the GraphQL type system. export { TypeInfo, visitWithTypeInfo } from './TypeInfo.js'; -// Coerces a JavaScript value to a GraphQL type, or produces errors. -export { coerceInputValue } from './coerceInputValue.js'; +// Converts a value to a const value by replacing variables. +export { replaceVariables } from './replaceVariables.js'; + +// Create a GraphQL literal (AST) from a JavaScript input value. +export { valueToLiteral } from './valueToLiteral.js'; + +export { + // Coerces a JavaScript value to a GraphQL type, or returns undefined. + coerceInputValue, + // Coerces a GraphQL literal (AST) to a GraphQL type, or returns undefined. + coerceInputLiteral, +} from './coerceInputValue.js'; + +export { + // Validate a JavaScript value with a GraphQL type, collecting all errors. + validateInputValue, + // Validate a GraphQL literal (AST) with a GraphQL type, collecting all errors. + validateInputLiteral, +} from './validateInputValue.js'; // Concatenates multiple AST together. export { concatAST } from './concatAST.js'; @@ -91,10 +114,16 @@ export { export { BreakingChangeType, DangerousChangeType, + SafeChangeType, findBreakingChanges, findDangerousChanges, -} from './findBreakingChanges.js'; -export type { BreakingChange, DangerousChange } from './findBreakingChanges.js'; + findSchemaChanges, +} from './findSchemaChanges.js'; +export type { + BreakingChange, + DangerousChange, + SafeChange, +} from './findSchemaChanges.js'; // Wrapper type that contains DocumentNode and types that can be deduced from it. export type { TypedQueryDocumentNode } from './typedQueryDocumentNode.js'; diff --git a/src/utilities/introspectionFromSchema.ts b/src/utilities/introspectionFromSchema.ts index 041a0ce489..375d53f119 100644 --- a/src/utilities/introspectionFromSchema.ts +++ b/src/utilities/introspectionFromSchema.ts @@ -30,6 +30,7 @@ export function introspectionFromSchema( directiveIsRepeatable: true, schemaDescription: true, inputValueDeprecation: true, + oneOf: true, ...options, }; diff --git a/src/utilities/lexicographicSortSchema.ts b/src/utilities/lexicographicSortSchema.ts index e3f25e1c4a..639aa6e01e 100644 --- a/src/utilities/lexicographicSortSchema.ts +++ b/src/utilities/lexicographicSortSchema.ts @@ -1,173 +1,62 @@ -import { inspect } from '../jsutils/inspect.js'; -import { invariant } from '../jsutils/invariant.js'; -import type { Maybe } from '../jsutils/Maybe.js'; import { naturalCompare } from '../jsutils/naturalCompare.js'; import type { ObjMap } from '../jsutils/ObjMap.js'; -import type { - GraphQLFieldConfigArgumentMap, - GraphQLFieldConfigMap, - GraphQLInputFieldConfigMap, - GraphQLNamedType, - GraphQLType, -} from '../type/definition.js'; -import { - GraphQLEnumType, - GraphQLInputObjectType, - GraphQLInterfaceType, - GraphQLList, - GraphQLNonNull, - GraphQLObjectType, - GraphQLUnionType, - isEnumType, - isInputObjectType, - isInterfaceType, - isListType, - isNonNullType, - isObjectType, - isScalarType, - isUnionType, -} from '../type/definition.js'; -import { GraphQLDirective } from '../type/directives.js'; -import { isIntrospectionType } from '../type/introspection.js'; import { GraphQLSchema } from '../type/schema.js'; +import { mapSchemaConfig, SchemaElementKind } from './mapSchemaConfig.js'; + /** * Sort GraphQLSchema. * * This function returns a sorted copy of the given GraphQLSchema. */ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { - const schemaConfig = schema.toConfig(); - const typeMap = new Map( - sortByName(schemaConfig.types).map((type) => [ - type.name, - sortNamedType(type), - ]), - ); - - return new GraphQLSchema({ - ...schemaConfig, - types: Array.from(typeMap.values()), - directives: sortByName(schemaConfig.directives).map(sortDirective), - query: replaceMaybeType(schemaConfig.query), - mutation: replaceMaybeType(schemaConfig.mutation), - subscription: replaceMaybeType(schemaConfig.subscription), - }); - - function replaceType(type: T): T { - if (isListType(type)) { - // @ts-expect-error - return new GraphQLList(replaceType(type.ofType)); - } else if (isNonNullType(type)) { - // @ts-expect-error - return new GraphQLNonNull(replaceType(type.ofType)); - } - // @ts-expect-error FIXME: TS Conversion - return replaceNamedType(type); - } - - function replaceNamedType(type: T): T { - return typeMap.get(type.name) as T; - } - - function replaceMaybeType( - maybeType: Maybe, - ): Maybe { - return maybeType && replaceNamedType(maybeType); - } - - function sortDirective(directive: GraphQLDirective) { - const config = directive.toConfig(); - return new GraphQLDirective({ - ...config, - locations: sortBy(config.locations, (x) => x), - args: sortArgs(config.args), - }); - } - - function sortArgs(args: GraphQLFieldConfigArgumentMap) { - return sortObjMap(args, (arg) => ({ - ...arg, - type: replaceType(arg.type), - })); - } - - function sortFields(fieldsMap: GraphQLFieldConfigMap) { - return sortObjMap(fieldsMap, (field) => ({ - ...field, - type: replaceType(field.type), - args: field.args && sortArgs(field.args), - })); - } - - function sortInputFields(fieldsMap: GraphQLInputFieldConfigMap) { - return sortObjMap(fieldsMap, (field) => ({ - ...field, - type: replaceType(field.type), - })); - } - - function sortTypes( - array: ReadonlyArray, - ): Array { - return sortByName(array).map(replaceNamedType); - } - - function sortNamedType(type: GraphQLNamedType): GraphQLNamedType { - if (isScalarType(type) || isIntrospectionType(type)) { - return type; - } - if (isObjectType(type)) { - const config = type.toConfig(); - return new GraphQLObjectType({ + return new GraphQLSchema( + mapSchemaConfig(schema.toConfig(), () => ({ + [SchemaElementKind.OBJECT]: (config) => ({ ...config, - interfaces: () => sortTypes(config.interfaces), - fields: () => sortFields(config.fields), - }); - } - if (isInterfaceType(type)) { - const config = type.toConfig(); - return new GraphQLInterfaceType({ + interfaces: () => sortByName(config.interfaces()), + fields: () => sortObjMap(config.fields()), + }), + [SchemaElementKind.FIELD]: (config) => ({ ...config, - interfaces: () => sortTypes(config.interfaces), - fields: () => sortFields(config.fields), - }); - } - if (isUnionType(type)) { - const config = type.toConfig(); - return new GraphQLUnionType({ + args: sortObjMap(config.args), + }), + [SchemaElementKind.INTERFACE]: (config) => ({ ...config, - types: () => sortTypes(config.types), - }); - } - if (isEnumType(type)) { - const config = type.toConfig(); - return new GraphQLEnumType({ + interfaces: () => sortByName(config.interfaces()), + fields: () => sortObjMap(config.fields()), + }), + [SchemaElementKind.UNION]: (config) => ({ ...config, - values: sortObjMap(config.values, (value) => value), - }); - } - if (isInputObjectType(type)) { - const config = type.toConfig(); - return new GraphQLInputObjectType({ + types: () => sortByName(config.types()), + }), + [SchemaElementKind.ENUM]: (config) => ({ ...config, - fields: () => sortInputFields(config.fields), - }); - } - /* c8 ignore next 3 */ - // Not reachable, all possible types have been considered. - invariant(false, 'Unexpected type: ' + inspect(type)); - } + values: () => sortObjMap(config.values()), + }), + [SchemaElementKind.INPUT_OBJECT]: (config) => ({ + ...config, + fields: () => sortObjMap(config.fields()), + }), + [SchemaElementKind.DIRECTIVE]: (config) => ({ + ...config, + locations: sortBy(config.locations, (x) => x), + args: sortObjMap(config.args), + }), + [SchemaElementKind.SCHEMA]: (config) => ({ + ...config, + types: sortByName(config.types), + directives: sortByName(config.directives), + }), + })), + ); } -function sortObjMap( - map: ObjMap, - sortValueFn: (value: T) => R, -): ObjMap { +function sortObjMap(map: ObjMap): ObjMap { const sortedMap = Object.create(null); for (const key of Object.keys(map).sort(naturalCompare)) { - sortedMap[key] = sortValueFn(map[key]); + sortedMap[key] = map[key]; } return sortedMap; } diff --git a/src/utilities/mapSchemaConfig.ts b/src/utilities/mapSchemaConfig.ts new file mode 100644 index 0000000000..dbcce21746 --- /dev/null +++ b/src/utilities/mapSchemaConfig.ts @@ -0,0 +1,464 @@ +import { inspect } from '../jsutils/inspect.js'; +import { invariant } from '../jsutils/invariant.js'; +import type { Maybe } from '../jsutils/Maybe.js'; + +import type { + GraphQLArgumentNormalizedConfig, + GraphQLEnumTypeNormalizedConfig, + GraphQLEnumValueConfig, + GraphQLFieldNormalizedConfig, + GraphQLFieldNormalizedConfigArgumentMap, + GraphQLFieldNormalizedConfigMap, + GraphQLInputFieldConfig, + GraphQLInputObjectTypeNormalizedConfig, + GraphQLInterfaceTypeNormalizedConfig, + GraphQLNamedType, + GraphQLObjectTypeNormalizedConfig, + GraphQLScalarTypeNormalizedConfig, + GraphQLType, + GraphQLUnionTypeNormalizedConfig, +} from '../type/definition.js'; +import { + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLInterfaceType, + GraphQLList, + GraphQLNonNull, + GraphQLObjectType, + GraphQLScalarType, + GraphQLUnionType, + isEnumType, + isInputObjectType, + isInterfaceType, + isListType, + isNonNullType, + isObjectType, + isScalarType, + isUnionType, +} from '../type/definition.js'; +import type { GraphQLDirectiveNormalizedConfig } from '../type/directives.js'; +import { GraphQLDirective, isSpecifiedDirective } from '../type/directives.js'; +import { + introspectionTypes, + isIntrospectionType, +} from '../type/introspection.js'; +import { + isSpecifiedScalarType, + specifiedScalarTypes, +} from '../type/scalars.js'; +import type { GraphQLSchemaNormalizedConfig } from '../type/schema.js'; + +/** + * The set of GraphQL Schema Elements. + */ +export const SchemaElementKind = { + SCHEMA: 'SCHEMA' as const, + SCALAR: 'SCALAR' as const, + OBJECT: 'OBJECT' as const, + FIELD: 'FIELD' as const, + ARGUMENT: 'ARGUMENT' as const, + INTERFACE: 'INTERFACE' as const, + UNION: 'UNION' as const, + ENUM: 'ENUM' as const, + ENUM_VALUE: 'ENUM_VALUE' as const, + INPUT_OBJECT: 'INPUT_OBJECT' as const, + INPUT_FIELD: 'INPUT_FIELD' as const, + DIRECTIVE: 'DIRECTIVE' as const, +} as const; +// eslint-disable-next-line @typescript-eslint/no-redeclare +type SchemaElementKind = + (typeof SchemaElementKind)[keyof typeof SchemaElementKind]; + +export interface MappedSchemaContext { + getNamedType: (typeName: string) => GraphQLNamedType; + setNamedType: (type: GraphQLNamedType) => void; + getNamedTypes: () => ReadonlyArray; +} + +type GraphQLScalarTypeMappedConfig = GraphQLScalarTypeNormalizedConfig< + any, + any +>; + +type EnsureThunks = { + [K in keyof T]: K extends ThunkFields ? () => T[K] : T[K]; +}; + +type GraphQLObjectTypeMappedConfig = EnsureThunks< + GraphQLObjectTypeNormalizedConfig, + 'interfaces' | 'fields' +>; +type GraphQLInterfaceTypeMappedConfig = EnsureThunks< + GraphQLInterfaceTypeNormalizedConfig, + 'interfaces' | 'fields' +>; +type GraphQLUnionTypeMappedConfig = EnsureThunks< + GraphQLUnionTypeNormalizedConfig, + 'types' +>; +type GraphQLEnumTypeMappedConfig = EnsureThunks< + GraphQLEnumTypeNormalizedConfig, + 'values' +>; +type GraphQLInputObjectTypeMappedConfig = EnsureThunks< + GraphQLInputObjectTypeNormalizedConfig, + 'fields' +>; + +type ScalarTypeConfigMapper = ( + scalarConfig: GraphQLScalarTypeMappedConfig, +) => GraphQLScalarTypeMappedConfig; + +type ObjectTypeConfigMapper = ( + objectConfig: GraphQLObjectTypeMappedConfig, +) => GraphQLObjectTypeMappedConfig; + +type FieldConfigMapper = ( + fieldConfig: GraphQLFieldNormalizedConfig, + parentTypeName: string, +) => GraphQLFieldNormalizedConfig; + +type ArgumentConfigMapper = ( + argConfig: GraphQLArgumentNormalizedConfig, + fieldOrDirectiveName: string, + parentTypeName?: string, +) => GraphQLArgumentNormalizedConfig; + +type InterfaceTypeConfigMapper = ( + interfaceConfig: GraphQLInterfaceTypeMappedConfig, +) => GraphQLInterfaceTypeMappedConfig; + +type UnionTypeConfigMapper = ( + unionConfig: GraphQLUnionTypeMappedConfig, +) => GraphQLUnionTypeMappedConfig; + +type EnumTypeConfigMapper = ( + enumConfig: GraphQLEnumTypeMappedConfig, +) => GraphQLEnumTypeMappedConfig; + +type EnumValueConfigMapper = ( + enumValueConfig: GraphQLEnumValueConfig, + valueName: string, + enumName: string, +) => GraphQLEnumValueConfig; + +type InputObjectTypeConfigMapper = ( + inputObjectConfig: GraphQLInputObjectTypeMappedConfig, +) => GraphQLInputObjectTypeMappedConfig; + +type InputFieldConfigMapper = ( + inputFieldConfig: GraphQLInputFieldConfig, + inputFieldName: string, + inputObjectTypeName: string, +) => GraphQLInputFieldConfig; + +type DirectiveConfigMapper = ( + directiveConfig: GraphQLDirectiveNormalizedConfig, +) => GraphQLDirectiveNormalizedConfig; + +type SchemaConfigMapper = ( + originalSchemaConfig: GraphQLSchemaNormalizedConfig, +) => GraphQLSchemaNormalizedConfig; + +export interface ConfigMapperMap { + [SchemaElementKind.SCALAR]?: ScalarTypeConfigMapper; + [SchemaElementKind.OBJECT]?: ObjectTypeConfigMapper; + [SchemaElementKind.FIELD]?: FieldConfigMapper; + [SchemaElementKind.ARGUMENT]?: ArgumentConfigMapper; + [SchemaElementKind.INTERFACE]?: InterfaceTypeConfigMapper; + [SchemaElementKind.UNION]?: UnionTypeConfigMapper; + [SchemaElementKind.ENUM]?: EnumTypeConfigMapper; + [SchemaElementKind.ENUM_VALUE]?: EnumValueConfigMapper; + [SchemaElementKind.INPUT_OBJECT]?: InputObjectTypeConfigMapper; + [SchemaElementKind.INPUT_FIELD]?: InputFieldConfigMapper; + [SchemaElementKind.DIRECTIVE]?: DirectiveConfigMapper; + [SchemaElementKind.SCHEMA]?: SchemaConfigMapper; +} + +/** + * @internal + */ +export function mapSchemaConfig( + schemaConfig: GraphQLSchemaNormalizedConfig, + configMapperMapFn: (context: MappedSchemaContext) => ConfigMapperMap, +): GraphQLSchemaNormalizedConfig { + const configMapperMap = configMapperMapFn({ + getNamedType, + setNamedType, + getNamedTypes, + }); + + const mappedTypeMap = new Map(); + for (const type of schemaConfig.types) { + const typeName = type.name; + const mappedNamedType = mapNamedType(type); + if (mappedNamedType) { + mappedTypeMap.set(typeName, mappedNamedType); + } + } + + const mappedDirectives: Array = []; + for (const directive of schemaConfig.directives) { + if (isSpecifiedDirective(directive)) { + // Builtin directives cannot be mapped. + mappedDirectives.push(directive); + continue; + } + + const mappedDirectiveConfig = mapDirective(directive.toConfig()); + if (mappedDirectiveConfig) { + mappedDirectives.push(new GraphQLDirective(mappedDirectiveConfig)); + } + } + + const mappedSchemaConfig = { + ...schemaConfig, + query: + schemaConfig.query && + (getNamedType(schemaConfig.query.name) as GraphQLObjectType), + mutation: + schemaConfig.mutation && + (getNamedType(schemaConfig.mutation.name) as GraphQLObjectType), + subscription: + schemaConfig.subscription && + (getNamedType(schemaConfig.subscription.name) as GraphQLObjectType), + types: Array.from(mappedTypeMap.values()), + directives: mappedDirectives, + }; + + const schemaMapper = configMapperMap[SchemaElementKind.SCHEMA]; + + return schemaMapper == null + ? mappedSchemaConfig + : schemaMapper(mappedSchemaConfig); + + function getType(type: T): T { + if (isListType(type)) { + return new GraphQLList(getType(type.ofType)) as T; + } + if (isNonNullType(type)) { + return new GraphQLNonNull(getType(type.ofType)) as T; + } + + return getNamedType(type.name) as T; + } + + function getNamedType(typeName: string): GraphQLNamedType { + const type = stdTypeMap.get(typeName) ?? mappedTypeMap.get(typeName); + invariant(type !== undefined, `Unknown type: "${typeName}".`); + return type; + } + + function setNamedType(type: GraphQLNamedType): void { + mappedTypeMap.set(type.name, type); + } + + function getNamedTypes(): ReadonlyArray { + return Array.from(mappedTypeMap.values()); + } + + function mapNamedType(type: GraphQLNamedType): Maybe { + if (isIntrospectionType(type) || isSpecifiedScalarType(type)) { + // Builtin types cannot be mapped. + return type; + } + + if (isScalarType(type)) { + return mapScalarType(type); + } + if (isObjectType(type)) { + return mapObjectType(type); + } + if (isInterfaceType(type)) { + return mapInterfaceType(type); + } + if (isUnionType(type)) { + return mapUnionType(type); + } + if (isEnumType(type)) { + return mapEnumType(type); + } + if (isInputObjectType(type)) { + return mapInputObjectType(type); + } + /* c8 ignore next 3 */ + // Not reachable, all possible type definition nodes have been considered. + invariant(false, 'Unexpected type: ' + inspect(type)); + } + + function mapScalarType(type: GraphQLScalarType): GraphQLScalarType { + let mappedConfig: Maybe = type.toConfig(); + const mapper = configMapperMap[SchemaElementKind.SCALAR]; + mappedConfig = mapper == null ? mappedConfig : mapper(mappedConfig); + return new GraphQLScalarType(mappedConfig); + } + + function mapObjectType(type: GraphQLObjectType): GraphQLObjectType { + const config = type.toConfig(); + let mappedConfig: Maybe = { + ...config, + interfaces: () => + config.interfaces.map( + (iface) => getNamedType(iface.name) as GraphQLInterfaceType, + ), + fields: () => mapFields(config.fields, type.name), + }; + const mapper = configMapperMap[SchemaElementKind.OBJECT]; + mappedConfig = mapper == null ? mappedConfig : mapper(mappedConfig); + return new GraphQLObjectType(mappedConfig); + } + + function mapFields( + fieldMap: GraphQLFieldNormalizedConfigMap, + parentTypeName: string, + ): GraphQLFieldNormalizedConfigMap { + const newFieldMap = Object.create(null); + for (const [fieldName, field] of Object.entries(fieldMap)) { + let mappedField = { + ...field, + type: getType(field.type), + args: mapArgs(field.args, parentTypeName, fieldName), + }; + const mapper = configMapperMap[SchemaElementKind.FIELD]; + if (mapper) { + mappedField = mapper(mappedField, parentTypeName); + } + newFieldMap[fieldName] = mappedField; + } + return newFieldMap; + } + + function mapArgs( + argumentMap: GraphQLFieldNormalizedConfigArgumentMap, + fieldOrDirectiveName: string, + parentTypeName?: string, + ): GraphQLFieldNormalizedConfigArgumentMap { + const newArgumentMap = Object.create(null); + + for (const [argName, arg] of Object.entries(argumentMap)) { + let mappedArg = { + ...arg, + type: getType(arg.type), + }; + const mapper = configMapperMap[SchemaElementKind.ARGUMENT]; + if (mapper) { + mappedArg = mapper(mappedArg, fieldOrDirectiveName, parentTypeName); + } + newArgumentMap[argName] = mappedArg; + } + + return newArgumentMap; + } + + function mapInterfaceType(type: GraphQLInterfaceType): GraphQLInterfaceType { + const config = type.toConfig(); + let mappedConfig: Maybe = { + ...config, + interfaces: () => + config.interfaces.map( + (iface) => getNamedType(iface.name) as GraphQLInterfaceType, + ), + fields: () => mapFields(config.fields, type.name), + }; + const mapper = configMapperMap[SchemaElementKind.INTERFACE]; + mappedConfig = mapper == null ? mappedConfig : mapper(mappedConfig); + return new GraphQLInterfaceType(mappedConfig); + } + + function mapUnionType(type: GraphQLUnionType): GraphQLUnionType { + const config = type.toConfig(); + let mappedConfig: Maybe = { + ...config, + types: () => + config.types.map( + (memberType) => getNamedType(memberType.name) as GraphQLObjectType, + ), + }; + const mapper = configMapperMap[SchemaElementKind.UNION]; + mappedConfig = mapper == null ? mappedConfig : mapper(mappedConfig); + return new GraphQLUnionType(mappedConfig); + } + + function mapEnumType(type: GraphQLEnumType): GraphQLEnumType { + const config = type.toConfig(); + let mappedConfig: Maybe = { + ...config, + values: () => { + const newEnumValues = Object.create(null); + for (const [valueName, value] of Object.entries(config.values)) { + const mappedValue = mapEnumValue(value, valueName, type.name); + newEnumValues[valueName] = mappedValue; + } + return newEnumValues; + }, + }; + const mapper = configMapperMap[SchemaElementKind.ENUM]; + mappedConfig = mapper == null ? mappedConfig : mapper(mappedConfig); + return new GraphQLEnumType(mappedConfig); + } + + function mapEnumValue( + valueConfig: GraphQLEnumValueConfig, + valueName: string, + enumName: string, + ): GraphQLEnumValueConfig { + const mappedConfig = { ...valueConfig }; + const mapper = configMapperMap[SchemaElementKind.ENUM_VALUE]; + return mapper == null + ? mappedConfig + : mapper(mappedConfig, valueName, enumName); + } + + function mapInputObjectType( + type: GraphQLInputObjectType, + ): GraphQLInputObjectType { + const config = type.toConfig(); + let mappedConfig: Maybe = { + ...config, + fields: () => { + const newInputFieldMap = Object.create(null); + for (const [fieldName, field] of Object.entries(config.fields)) { + const mappedField = mapInputField(field, fieldName, type.name); + newInputFieldMap[fieldName] = mappedField; + } + return newInputFieldMap; + }, + }; + const mapper = configMapperMap[SchemaElementKind.INPUT_OBJECT]; + mappedConfig = mapper == null ? mappedConfig : mapper(mappedConfig); + return new GraphQLInputObjectType(mappedConfig); + } + + function mapInputField( + inputFieldConfig: GraphQLInputFieldConfig, + inputFieldName: string, + inputObjectTypeName: string, + ): GraphQLInputFieldConfig { + const mappedConfig = { + ...inputFieldConfig, + type: getType(inputFieldConfig.type), + }; + const mapper = configMapperMap[SchemaElementKind.INPUT_FIELD]; + return mapper == null + ? mappedConfig + : mapper(mappedConfig, inputFieldName, inputObjectTypeName); + } + + function mapDirective( + config: GraphQLDirectiveNormalizedConfig, + ): Maybe { + const mappedConfig = { + ...config, + args: mapArgs(config.args, config.name, undefined), + }; + const mapper = configMapperMap[SchemaElementKind.DIRECTIVE]; + return mapper == null ? mappedConfig : mapper(mappedConfig); + } +} + +const stdTypeMap = new Map( + [...specifiedScalarTypes, ...introspectionTypes].map((type) => [ + type.name, + type, + ]), +); diff --git a/src/utilities/printSchema.ts b/src/utilities/printSchema.ts index c4caffc616..be5238ae3a 100644 --- a/src/utilities/printSchema.ts +++ b/src/utilities/printSchema.ts @@ -34,7 +34,7 @@ import { isIntrospectionType } from '../type/introspection.js'; import { isSpecifiedScalarType } from '../type/scalars.js'; import type { GraphQLSchema } from '../type/schema.js'; -import { astFromValue } from './astFromValue.js'; +import { getDefaultValueAST } from './getDefaultValueAST.js'; export function printSchema(schema: GraphQLSchema): string { return printFilteredSchema( @@ -86,9 +86,9 @@ function printSchemaDefinition(schema: GraphQLSchema): Maybe { return ( printDescription(schema) + 'schema {\n' + - (queryType ? ` query: ${queryType.name}\n` : '') + - (mutationType ? ` mutation: ${mutationType.name}\n` : '') + - (subscriptionType ? ` subscription: ${subscriptionType.name}\n` : '') + + (queryType ? ` query: ${queryType}\n` : '') + + (mutationType ? ` mutation: ${mutationType}\n` : '') + + (subscriptionType ? ` subscription: ${subscriptionType}\n` : '') + '}' ); } @@ -148,9 +148,7 @@ export function printType(type: GraphQLNamedType): string { } function printScalar(type: GraphQLScalarType): string { - return ( - printDescription(type) + `scalar ${type.name}` + printSpecifiedByURL(type) - ); + return printDescription(type) + `scalar ${type}` + printSpecifiedByURL(type); } function printImplementedInterfaces( @@ -165,7 +163,7 @@ function printImplementedInterfaces( function printObject(type: GraphQLObjectType): string { return ( printDescription(type) + - `type ${type.name}` + + `type ${type}` + printImplementedInterfaces(type) + printFields(type) ); @@ -174,7 +172,7 @@ function printObject(type: GraphQLObjectType): string { function printInterface(type: GraphQLInterfaceType): string { return ( printDescription(type) + - `interface ${type.name}` + + `interface ${type}` + printImplementedInterfaces(type) + printFields(type) ); @@ -183,7 +181,7 @@ function printInterface(type: GraphQLInterfaceType): string { function printUnion(type: GraphQLUnionType): string { const types = type.getTypes(); const possibleTypes = types.length ? ' = ' + types.join(' | ') : ''; - return printDescription(type) + 'union ' + type.name + possibleTypes; + return printDescription(type) + `union ${type.name}` + possibleTypes; } function printEnum(type: GraphQLEnumType): string { @@ -197,7 +195,7 @@ function printEnum(type: GraphQLEnumType): string { printDeprecated(value.deprecationReason), ); - return printDescription(type) + `enum ${type.name}` + printBlock(values); + return printDescription(type) + `enum ${type}` + printBlock(values); } function printInputObject(type: GraphQLInputObjectType): string { @@ -206,7 +204,7 @@ function printInputObject(type: GraphQLInputObjectType): string { ); return ( printDescription(type) + - `input ${type.name}` + + `input ${type}` + (type.isOneOf ? ' @oneOf' : '') + printBlock(fields) ); @@ -260,20 +258,21 @@ function printArgs( ); } -function printInputValue(arg: GraphQLInputField): string { - const defaultAST = astFromValue(arg.defaultValue, arg.type); - let argDecl = arg.name + ': ' + String(arg.type); - if (defaultAST) { - argDecl += ` = ${print(defaultAST)}`; +function printInputValue( + argOrInputField: GraphQLArgument | GraphQLInputField, +): string { + let argDecl = argOrInputField.name + ': ' + String(argOrInputField.type); + const defaultValueAST = getDefaultValueAST(argOrInputField); + if (defaultValueAST) { + argDecl += ` = ${print(defaultValueAST)}`; } - return argDecl + printDeprecated(arg.deprecationReason); + return argDecl + printDeprecated(argOrInputField.deprecationReason); } export function printDirective(directive: GraphQLDirective): string { return ( printDescription(directive) + - 'directive @' + - directive.name + + `directive ${directive}` + printArgs(directive.args) + (directive.isRepeatable ? ' repeatable' : '') + ' on ' + diff --git a/src/utilities/replaceVariables.ts b/src/utilities/replaceVariables.ts new file mode 100644 index 0000000000..fc09a290e3 --- /dev/null +++ b/src/utilities/replaceVariables.ts @@ -0,0 +1,100 @@ +import type { Maybe } from '../jsutils/Maybe.js'; + +import type { + ConstValueNode, + ObjectFieldNode, + ValueNode, +} from '../language/ast.js'; +import { Kind } from '../language/kinds.js'; + +import type { VariableValues } from '../execution/values.js'; + +import { valueToLiteral } from './valueToLiteral.js'; + +/** + * Replaces any Variables found within an AST Value literal with literals + * supplied from a map of variable values, or removed if no variable replacement + * exists, returning a constant value. + * + * Used primarily to ensure only complete constant values are used during input + * coercion of custom scalars which accept complex literals. + */ +export function replaceVariables( + valueNode: ValueNode, + variableValues?: Maybe, + fragmentVariableValues?: Maybe, +): ConstValueNode { + switch (valueNode.kind) { + case Kind.VARIABLE: { + const varName = valueNode.name.value; + const scopedVariableValues = fragmentVariableValues?.sources[varName] + ? fragmentVariableValues + : variableValues; + + const scopedVariableSource = scopedVariableValues?.sources[varName]; + if (scopedVariableSource == null) { + return { kind: Kind.NULL }; + } + + if (scopedVariableSource.value === undefined) { + const defaultValue = scopedVariableSource.signature.default; + if (defaultValue !== undefined) { + return defaultValue.literal; + } + } + + return valueToLiteral( + scopedVariableSource.value, + scopedVariableSource.signature.type, + ) as ConstValueNode; + } + case Kind.OBJECT: { + const newFields: Array = []; + for (const field of valueNode.fields) { + if (field.value.kind === Kind.VARIABLE) { + const scopedVariableSource = + fragmentVariableValues?.sources[field.value.name.value] ?? + variableValues?.sources[field.value.name.value]; + + if ( + scopedVariableSource?.value === undefined && + scopedVariableSource?.signature.default === undefined + ) { + continue; + } + } + const newFieldNodeValue = replaceVariables( + field.value, + variableValues, + fragmentVariableValues, + ); + newFields.push({ + ...field, + value: newFieldNodeValue, + }); + } + return { + ...valueNode, + fields: newFields, + } as ConstValueNode; + } + case Kind.LIST: { + const newValues: Array = []; + for (const value of valueNode.values) { + const newItemNodeValue = replaceVariables( + value, + variableValues, + fragmentVariableValues, + ); + newValues.push(newItemNodeValue); + } + return { + ...valueNode, + values: newValues, + } as ConstValueNode; + } + default: { + return valueNode; + } + } +} diff --git a/src/utilities/validateInputValue.ts b/src/utilities/validateInputValue.ts new file mode 100644 index 0000000000..4b6295320a --- /dev/null +++ b/src/utilities/validateInputValue.ts @@ -0,0 +1,507 @@ +import { didYouMean } from '../jsutils/didYouMean.js'; +import { inspect } from '../jsutils/inspect.js'; +import { isIterableObject } from '../jsutils/isIterableObject.js'; +import { isObjectLike } from '../jsutils/isObjectLike.js'; +import { keyMap } from '../jsutils/keyMap.js'; +import type { Maybe } from '../jsutils/Maybe.js'; +import type { Path } from '../jsutils/Path.js'; +import { addPath, pathToArray } from '../jsutils/Path.js'; +import { suggestionList } from '../jsutils/suggestionList.js'; + +import { GraphQLError } from '../error/GraphQLError.js'; + +import type { ASTNode, ValueNode, VariableNode } from '../language/ast.js'; +import { Kind } from '../language/kinds.js'; +import { print } from '../language/printer.js'; + +import type { GraphQLInputType } from '../type/definition.js'; +import { + assertLeafType, + isInputObjectType, + isListType, + isNonNullType, + isRequiredInputField, +} from '../type/definition.js'; + +import type { VariableValues } from '../execution/values.js'; + +import { replaceVariables } from './replaceVariables.js'; + +/** + * Validate that the provided input value is allowed for this type, collecting + * all errors via a callback function. + */ +export function validateInputValue( + inputValue: unknown, + type: GraphQLInputType, + onError: (error: GraphQLError, path: ReadonlyArray) => void, + hideSuggestions?: Maybe, +): void { + return validateInputValueImpl( + inputValue, + type, + onError, + hideSuggestions, + undefined, + ); +} + +function validateInputValueImpl( + inputValue: unknown, + type: GraphQLInputType, + onError: (error: GraphQLError, path: ReadonlyArray) => void, + hideSuggestions: Maybe, + path: Path | undefined, +): void { + if (isNonNullType(type)) { + if (inputValue === undefined) { + reportInvalidValue( + onError, + `Expected a value of non-null type "${type}" to be provided.`, + path, + ); + return; + } + if (inputValue === null) { + reportInvalidValue( + onError, + `Expected value of non-null type "${type}" not to be null.`, + path, + ); + return; + } + return validateInputValueImpl( + inputValue, + type.ofType, + onError, + hideSuggestions, + path, + ); + } + + if (inputValue == null) { + return; + } + + if (isListType(type)) { + if (!isIterableObject(inputValue)) { + // Lists accept a non-list value as a list of one. + validateInputValueImpl( + inputValue, + type.ofType, + onError, + hideSuggestions, + path, + ); + } else { + let index = 0; + for (const itemValue of inputValue) { + validateInputValueImpl( + itemValue, + type.ofType, + onError, + hideSuggestions, + addPath(path, index++, undefined), + ); + } + } + } else if (isInputObjectType(type)) { + if (!isObjectLike(inputValue)) { + reportInvalidValue( + onError, + `Expected value of type "${type}" to be an object, found: ${inspect( + inputValue, + )}.`, + path, + ); + return; + } + + const fieldDefs = type.getFields(); + + for (const field of Object.values(fieldDefs)) { + const fieldValue = inputValue[field.name]; + if (fieldValue === undefined) { + if (isRequiredInputField(field)) { + reportInvalidValue( + onError, + `Expected value of type "${type}" to include required field "${ + field.name + }", found: ${inspect(inputValue)}.`, + path, + ); + } + } else { + validateInputValueImpl( + fieldValue, + field.type, + onError, + hideSuggestions, + addPath(path, field.name, type.name), + ); + } + } + + const fields = Object.keys(inputValue); + // Ensure every provided field is defined. + for (const fieldName of fields) { + if (!Object.hasOwn(fieldDefs, fieldName)) { + const suggestion = hideSuggestions + ? '' + : didYouMean(suggestionList(fieldName, Object.keys(fieldDefs))); + reportInvalidValue( + onError, + `Expected value of type "${type}" not to include unknown field "${fieldName}"${ + suggestion ? `.${suggestion} Found` : ', found' + }: ${inspect(inputValue)}.`, + path, + ); + } + } + + if (type.isOneOf) { + if (fields.length !== 1) { + reportInvalidValue( + onError, + `Exactly one key must be specified for OneOf type "${type}".`, + path, + ); + } + + const field = fields[0]; + const value = inputValue[field]; + if (value === null) { + reportInvalidValue( + onError, + `Field "${field}" for OneOf type "${type}" must be non-null.`, + path, + ); + } + } + } else { + assertLeafType(type); + + let result; + let caughtError; + + try { + result = type.coerceInputValue(inputValue, hideSuggestions); + } catch (error) { + if (error instanceof GraphQLError) { + onError(error, pathToArray(path)); + return; + } + caughtError = error; + } + + if (result === undefined) { + reportInvalidValue( + onError, + `Expected value of type "${type}"${ + caughtError != null + ? `, but encountered error "${caughtError.message != null && caughtError.message !== '' ? caughtError.message : caughtError}"; found` + : ', found' + }: ${inspect(inputValue)}.`, + path, + caughtError, + ); + } + } +} + +function reportInvalidValue( + onError: (error: GraphQLError, path: ReadonlyArray) => void, + message: string, + path: Path | undefined, + originalError?: GraphQLError, +): void { + onError(new GraphQLError(message, { originalError }), pathToArray(path)); +} + +/** + * Validate that the provided input literal is allowed for this type, collecting + * all errors via a callback function. + * + * If variable values are not provided, the literal is validated statically + * (not assuming that those variables are missing runtime values). + */ +// eslint-disable-next-line @typescript-eslint/max-params +export function validateInputLiteral( + valueNode: ValueNode, + type: GraphQLInputType, + onError: (error: GraphQLError, path: ReadonlyArray) => void, + variables?: Maybe, + fragmentVariableValues?: Maybe, + hideSuggestions?: Maybe, +): void { + const context: ValidationContext = { + static: !variables && !fragmentVariableValues, + onError, + variables, + fragmentVariableValues, + }; + return validateInputLiteralImpl( + context, + valueNode, + type, + hideSuggestions, + undefined, + ); +} + +interface ValidationContext { + static: boolean; + onError: (error: GraphQLError, path: ReadonlyArray) => void; + variables?: Maybe; + fragmentVariableValues?: Maybe; +} + +function validateInputLiteralImpl( + context: ValidationContext, + valueNode: ValueNode, + type: GraphQLInputType, + hideSuggestions: Maybe, + path: Path | undefined, +): void { + if (valueNode.kind === Kind.VARIABLE) { + if (context.static) { + // If no variable values are provided, this is being validated statically, + // and cannot yet produce any validation errors for variables. + return; + } + const scopedVariableValues = getScopedVariableValues(context, valueNode); + const value = scopedVariableValues?.coerced[valueNode.name.value]; + if (isNonNullType(type)) { + if (value === undefined) { + reportInvalidLiteral( + context.onError, + `Expected variable "$${valueNode.name.value}" provided to type "${type}" to provide a runtime value.`, + valueNode, + path, + ); + } else if (value === null) { + reportInvalidLiteral( + context.onError, + `Expected variable "$${valueNode.name.value}" provided to non-null type "${type}" not to be null.`, + valueNode, + path, + ); + } + } + // Note: This does no further checking that this variable is correct. + // This assumes this variable usage has already been validated. + return; + } + + if (isNonNullType(type)) { + if (valueNode.kind === Kind.NULL) { + reportInvalidLiteral( + context.onError, + `Expected value of non-null type "${type}" not to be null.`, + valueNode, + path, + ); + return; + } + return validateInputLiteralImpl( + context, + valueNode, + type.ofType, + hideSuggestions, + path, + ); + } + + if (valueNode.kind === Kind.NULL) { + return; + } + + if (isListType(type)) { + if (valueNode.kind !== Kind.LIST) { + // Lists accept a non-list value as a list of one. + validateInputLiteralImpl( + context, + valueNode, + type.ofType, + hideSuggestions, + path, + ); + } else { + let index = 0; + for (const itemNode of valueNode.values) { + validateInputLiteralImpl( + context, + itemNode, + type.ofType, + hideSuggestions, + addPath(path, index++, undefined), + ); + } + } + } else if (isInputObjectType(type)) { + if (valueNode.kind !== Kind.OBJECT) { + reportInvalidLiteral( + context.onError, + `Expected value of type "${type}" to be an object, found: ${print( + valueNode, + )}.`, + valueNode, + path, + ); + return; + } + + const fieldDefs = type.getFields(); + const fieldNodes = keyMap(valueNode.fields, (field) => field.name.value); + + for (const field of Object.values(fieldDefs)) { + const fieldNode = fieldNodes[field.name]; + if (fieldNode === undefined) { + if (isRequiredInputField(field)) { + reportInvalidLiteral( + context.onError, + `Expected value of type "${type}" to include required field "${ + field.name + }", found: ${print(valueNode)}.`, + valueNode, + path, + ); + } + } else { + const fieldValueNode = fieldNode.value; + if (fieldValueNode.kind === Kind.VARIABLE && !context.static) { + const scopedVariableValues = getScopedVariableValues( + context, + fieldValueNode, + ); + const variableName = fieldValueNode.name.value; + const value = scopedVariableValues?.coerced[variableName]; + if (type.isOneOf) { + if (value === undefined) { + reportInvalidLiteral( + context.onError, + `Expected variable "$${variableName}" provided to field "${field.name}" for OneOf Input Object type "${type}" to provide a runtime value.`, + valueNode, + path, + ); + } else if (value === null) { + reportInvalidLiteral( + context.onError, + `Expected variable "$${variableName}" provided to field "${field.name}" for OneOf Input Object type "${type}" not to be null.`, + valueNode, + path, + ); + } + } else if (value === undefined && !isRequiredInputField(field)) { + continue; + } + } + + validateInputLiteralImpl( + context, + fieldValueNode, + field.type, + hideSuggestions, + addPath(path, field.name, type.name), + ); + } + } + + const fields = valueNode.fields; + // Ensure every provided field is defined. + for (const fieldNode of fields) { + const fieldName = fieldNode.name.value; + if (!Object.hasOwn(fieldDefs, fieldName)) { + const suggestion = hideSuggestions + ? '' + : didYouMean(suggestionList(fieldName, Object.keys(fieldDefs))); + reportInvalidLiteral( + context.onError, + `Expected value of type "${type}" not to include unknown field "${fieldName}"${ + suggestion ? `.${suggestion} Found` : ', found' + }: ${print(valueNode)}.`, + fieldNode, + path, + ); + } + } + + if (type.isOneOf) { + const isNotExactlyOneField = fields.length !== 1; + if (isNotExactlyOneField) { + reportInvalidLiteral( + context.onError, + `OneOf Input Object "${type}" must specify exactly one key.`, + valueNode, + path, + ); + return; + } + + const fieldValueNode = fields[0].value; + if (fieldValueNode.kind === Kind.NULL) { + const fieldName = fields[0].name.value; + reportInvalidLiteral( + context.onError, + `Field "${type}.${fieldName}" used for OneOf Input Object must be non-null.`, + valueNode, + addPath(path, fieldName, undefined), + ); + } + } + } else { + assertLeafType(type); + + let result; + let caughtError; + try { + result = type.coerceInputLiteral + ? type.coerceInputLiteral(replaceVariables(valueNode), hideSuggestions) + : type.parseLiteral(valueNode, undefined, hideSuggestions); + } catch (error) { + if (error instanceof GraphQLError) { + context.onError(error, pathToArray(path)); + return; + } + caughtError = error; + } + + if (result === undefined) { + reportInvalidLiteral( + context.onError, + `Expected value of type "${type}"${ + caughtError != null + ? `, but encountered error "${caughtError.message != null && caughtError.message !== '' ? caughtError.message : caughtError}"; found` + : ', found' + }: ${print(valueNode)}.`, + valueNode, + path, + caughtError, + ); + } + } +} + +function getScopedVariableValues( + context: ValidationContext, + valueNode: VariableNode, +): Maybe { + const variableName = valueNode.name.value; + const { fragmentVariableValues, variables } = context; + return fragmentVariableValues?.sources[variableName] + ? fragmentVariableValues + : variables; +} + +function reportInvalidLiteral( + onError: (error: GraphQLError, path: ReadonlyArray) => void, + message: string, + valueNode: ASTNode, + path: Path | undefined, + originalError?: GraphQLError, +): void { + onError( + new GraphQLError(message, { nodes: valueNode, originalError }), + pathToArray(path), + ); +} diff --git a/src/utilities/valueFromAST.ts b/src/utilities/valueFromAST.ts index 5e0d3c517e..add9153680 100644 --- a/src/utilities/valueFromAST.ts +++ b/src/utilities/valueFromAST.ts @@ -33,6 +33,7 @@ import { * | Enum Value | Unknown | * | NullValue | null | * + * @deprecated use `coerceInputLiteral()` instead - will be removed in v18 */ export function valueFromAST( valueNode: Maybe, @@ -47,11 +48,11 @@ export function valueFromAST( if (valueNode.kind === Kind.VARIABLE) { const variableName = valueNode.name.value; - if (variables == null || variables[variableName] === undefined) { + const variableValue = variables?.[variableName]; + if (variableValue === undefined) { // No valid return value. return; } - const variableValue = variables[variableName]; if (variableValue === null && isNonNullType(type)) { return; // Invalid: intentionally return no value. } diff --git a/src/utilities/valueFromASTUntyped.ts b/src/utilities/valueFromASTUntyped.ts index 87af11a9a3..4c8e197821 100644 --- a/src/utilities/valueFromASTUntyped.ts +++ b/src/utilities/valueFromASTUntyped.ts @@ -8,8 +8,8 @@ import { Kind } from '../language/kinds.js'; /** * Produces a JavaScript value given a GraphQL Value AST. * - * Unlike `valueFromAST()`, no type is provided. The resulting JavaScript value - * will reflect the provided GraphQL value AST. + * No type is provided. The resulting JavaScript value will reflect the + * provided GraphQL value AST. * * | GraphQL Value | JavaScript Value | * | -------------------- | ---------------- | diff --git a/src/utilities/valueToLiteral.ts b/src/utilities/valueToLiteral.ts new file mode 100644 index 0000000000..bb61b41ca5 --- /dev/null +++ b/src/utilities/valueToLiteral.ts @@ -0,0 +1,168 @@ +import { inspect } from '../jsutils/inspect.js'; +import { isIterableObject } from '../jsutils/isIterableObject.js'; +import { isObjectLike } from '../jsutils/isObjectLike.js'; + +import type { ConstObjectFieldNode, ConstValueNode } from '../language/ast.js'; +import { Kind } from '../language/kinds.js'; + +import type { GraphQLInputType } from '../type/definition.js'; +import { + assertLeafType, + isInputObjectType, + isListType, + isNonNullType, + isRequiredInputField, +} from '../type/definition.js'; + +/** + * Produces a GraphQL Value AST given a JavaScript value and a GraphQL type. + * + * Scalar types are converted by calling the `valueToLiteral` method on that + * type, otherwise the default scalar `valueToLiteral` method is used, defined + * below. + * + * The provided value is an non-coerced "input" value. This function does not + * perform any coercion, however it does perform validation. Provided values + * which are invalid for the given type will result in an `undefined` return + * value. + */ +export function valueToLiteral( + value: unknown, + type: GraphQLInputType, +): ConstValueNode | undefined { + if (isNonNullType(type)) { + if (value == null) { + return; // Invalid: intentionally return no value. + } + return valueToLiteral(value, type.ofType); + } + + // Like JSON, a null literal is produced for both null and undefined. + if (value == null) { + return { kind: Kind.NULL }; + } + + if (isListType(type)) { + if (!isIterableObject(value)) { + return valueToLiteral(value, type.ofType); + } + const values: Array = []; + for (const itemValue of value) { + const itemNode = valueToLiteral(itemValue, type.ofType); + if (!itemNode) { + return; // Invalid: intentionally return no value. + } + values.push(itemNode); + } + return { kind: Kind.LIST, values }; + } + + if (isInputObjectType(type)) { + if (!isObjectLike(value)) { + return; // Invalid: intentionally return no value. + } + const fields: Array = []; + const fieldDefs = type.getFields(); + const hasUndefinedField = Object.keys(value).some( + (name) => !Object.hasOwn(fieldDefs, name), + ); + if (hasUndefinedField) { + return; // Invalid: intentionally return no value. + } + for (const field of Object.values(type.getFields())) { + const fieldValue = value[field.name]; + if (fieldValue === undefined) { + if (isRequiredInputField(field)) { + return; // Invalid: intentionally return no value. + } + } else { + const fieldNode = valueToLiteral(value[field.name], field.type); + if (!fieldNode) { + return; // Invalid: intentionally return no value. + } + fields.push({ + kind: Kind.OBJECT_FIELD, + name: { kind: Kind.NAME, value: field.name }, + value: fieldNode, + }); + } + } + return { kind: Kind.OBJECT, fields }; + } + + const leafType = assertLeafType(type); + + if (leafType.valueToLiteral) { + try { + return leafType.valueToLiteral(value); + } catch (_error) { + return; // Invalid: intentionally ignore error and return no value. + } + } + + return defaultScalarValueToLiteral(value); +} + +/** + * The default implementation to convert scalar values to literals. + * + * | JavaScript Value | GraphQL Value | + * | ----------------- | -------------------- | + * | Object | Input Object | + * | Array | List | + * | Boolean | Boolean | + * | String | String | + * | Number | Int / Float | + * | null / undefined | Null | + * + * @internal + */ +export function defaultScalarValueToLiteral(value: unknown): ConstValueNode { + // Like JSON, a null literal is produced for both null and undefined. + if (value == null) { + return { kind: Kind.NULL }; + } + + // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check + switch (typeof value) { + case 'boolean': + return { kind: Kind.BOOLEAN, value }; + case 'string': + return { kind: Kind.STRING, value, block: false }; + case 'number': { + if (!Number.isFinite(value)) { + // Like JSON, a null literal is produced for non-finite values. + return { kind: Kind.NULL }; + } + const stringValue = String(value); + // Will parse as an IntValue. + return /^-?(?:0|[1-9][0-9]*)$/.test(stringValue) + ? { kind: Kind.INT, value: stringValue } + : { kind: Kind.FLOAT, value: stringValue }; + } + case 'object': { + if (isIterableObject(value)) { + return { + kind: Kind.LIST, + values: Array.from(value, defaultScalarValueToLiteral), + }; + } + const objValue = value as { [prop: string]: unknown }; + const fields: Array = []; + for (const fieldName of Object.keys(objValue)) { + const fieldValue = objValue[fieldName]; + // Like JSON, undefined fields are not included in the literal result. + if (fieldValue !== undefined) { + fields.push({ + kind: Kind.OBJECT_FIELD, + name: { kind: Kind.NAME, value: fieldName }, + value: defaultScalarValueToLiteral(fieldValue), + }); + } + } + return { kind: Kind.OBJECT, fields }; + } + } + + throw new TypeError(`Cannot convert value to AST: ${inspect(value)}.`); +} diff --git a/src/validation/ValidationContext.ts b/src/validation/ValidationContext.ts index b0c5524fa7..a37220a33f 100644 --- a/src/validation/ValidationContext.ts +++ b/src/validation/ValidationContext.ts @@ -9,6 +9,7 @@ import type { FragmentSpreadNode, OperationDefinitionNode, SelectionSetNode, + VariableDefinitionNode, VariableNode, } from '../language/ast.js'; import { Kind } from '../language/kinds.js'; @@ -26,13 +27,16 @@ import type { import type { GraphQLDirective } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; +import type { FragmentSignature } from '../utilities/TypeInfo.js'; import { TypeInfo, visitWithTypeInfo } from '../utilities/TypeInfo.js'; type NodeWithSelectionSet = OperationDefinitionNode | FragmentDefinitionNode; interface VariableUsage { readonly node: VariableNode; readonly type: Maybe; - readonly defaultValue: Maybe; + readonly parentType: Maybe; + readonly defaultValue: unknown; + readonly fragmentVariableDefinition: Maybe; } /** @@ -150,7 +154,11 @@ export class SDLValidationContext extends ASTValidationContext { this._schema = schema; } - get [Symbol.toStringTag]() { + get hideSuggestions() { + return false; + } + + override get [Symbol.toStringTag]() { return 'SDLValidationContext'; } @@ -173,24 +181,31 @@ export class ValidationContext extends ASTValidationContext { OperationDefinitionNode, ReadonlyArray >; + private _hideSuggestions: boolean; constructor( schema: GraphQLSchema, ast: DocumentNode, typeInfo: TypeInfo, onError: (error: GraphQLError) => void, + hideSuggestions?: Maybe, ) { super(ast, onError); this._schema = schema; this._typeInfo = typeInfo; this._variableUsages = new Map(); this._recursiveVariableUsages = new Map(); + this._hideSuggestions = hideSuggestions ?? false; } - get [Symbol.toStringTag]() { + override get [Symbol.toStringTag]() { return 'ValidationContext'; } + get hideSuggestions() { + return this._hideSuggestions; + } + getSchema(): GraphQLSchema { return this._schema; } @@ -199,17 +214,42 @@ export class ValidationContext extends ASTValidationContext { let usages = this._variableUsages.get(node); if (!usages) { const newUsages: Array = []; - const typeInfo = new TypeInfo(this._schema); + const typeInfo = new TypeInfo( + this._schema, + undefined, + this._typeInfo.getFragmentSignatureByName(), + ); + const fragmentDefinition = + node.kind === Kind.FRAGMENT_DEFINITION ? node : undefined; visit( node, visitWithTypeInfo(typeInfo, { VariableDefinition: () => false, Variable(variable) { - newUsages.push({ - node: variable, - type: typeInfo.getInputType(), - defaultValue: typeInfo.getDefaultValue(), - }); + let fragmentVariableDefinition; + if (fragmentDefinition) { + const fragmentSignature = typeInfo.getFragmentSignatureByName()( + fragmentDefinition.name.value, + ); + + fragmentVariableDefinition = + fragmentSignature?.variableDefinitions.get(variable.name.value); + newUsages.push({ + node: variable, + type: typeInfo.getInputType(), + parentType: typeInfo.getParentInputType(), + defaultValue: undefined, // fragment variables have a variable default but no location default, which is what this default value represents + fragmentVariableDefinition, + }); + } else { + newUsages.push({ + node: variable, + type: typeInfo.getInputType(), + parentType: typeInfo.getParentInputType(), + defaultValue: typeInfo.getDefaultValue(), + fragmentVariableDefinition: undefined, + }); + } }, }), ); @@ -261,6 +301,16 @@ export class ValidationContext extends ASTValidationContext { return this._typeInfo.getArgument(); } + getFragmentSignature(): Maybe { + return this._typeInfo.getFragmentSignature(); + } + + getFragmentSignatureByName(): ( + fragmentName: string, + ) => Maybe { + return this._typeInfo.getFragmentSignatureByName(); + } + getEnumValue(): Maybe { return this._typeInfo.getEnumValue(); } diff --git a/src/validation/__tests__/DeferStreamDirectiveLabelRule-test.ts b/src/validation/__tests__/DeferStreamDirectiveLabelRule-test.ts index 44709e00c5..4126c6e578 100644 --- a/src/validation/__tests__/DeferStreamDirectiveLabelRule-test.ts +++ b/src/validation/__tests__/DeferStreamDirectiveLabelRule-test.ts @@ -63,7 +63,7 @@ describe('Validate: Defer/Stream directive labels', () => { } `).toDeepEqual([ { - message: 'Directive "defer"\'s label argument must be a static string.', + message: 'Argument "@defer(label:)" must be a static string.', locations: [{ line: 4, column: 25 }], }, ]); @@ -101,7 +101,8 @@ describe('Validate: Defer/Stream directive labels', () => { } `).toDeepEqual([ { - message: 'Defer/Stream directive label argument must be unique.', + message: + 'Value for arguments "defer(label:)" and "stream(label:)" must be unique across all Defer/Stream directive usages.', locations: [ { line: 4, column: 25 }, { line: 5, column: 25 }, @@ -139,8 +140,7 @@ describe('Validate: Defer/Stream directive labels', () => { } `).toDeepEqual([ { - message: - 'Directive "stream"\'s label argument must be a static string.', + message: 'Argument "@stream(label:)" must be a static string.', locations: [{ line: 6, column: 39 }], }, ]); @@ -160,7 +160,8 @@ describe('Validate: Defer/Stream directive labels', () => { } `).toDeepEqual([ { - message: 'Defer/Stream directive label argument must be unique.', + message: + 'Value for arguments "defer(label:)" and "stream(label:)" must be unique across all Defer/Stream directive usages.', locations: [ { line: 4, column: 26 }, { line: 6, column: 39 }, diff --git a/src/validation/__tests__/DeferStreamDirectiveOnValidOperationsRule-test.ts b/src/validation/__tests__/DeferStreamDirectiveOnValidOperationsRule-test.ts index 3dee7fe5a1..ab2488ff28 100644 --- a/src/validation/__tests__/DeferStreamDirectiveOnValidOperationsRule-test.ts +++ b/src/validation/__tests__/DeferStreamDirectiveOnValidOperationsRule-test.ts @@ -241,7 +241,7 @@ describe('Validate: Defer/Stream directive on valid operations', () => { `).toDeepEqual([ { message: - 'Stream directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', + 'Stream directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.', locations: [{ line: 4, column: 20 }], }, ]); @@ -259,7 +259,7 @@ describe('Validate: Defer/Stream directive on valid operations', () => { `).toDeepEqual([ { message: - 'Stream directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', + 'Stream directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.', locations: [{ line: 8, column: 18 }], }, ]); @@ -301,7 +301,7 @@ describe('Validate: Defer/Stream directive on valid operations', () => { `).toDeepEqual([ { message: - 'Stream directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', + 'Stream directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.', locations: [{ line: 15, column: 18 }], }, ]); diff --git a/src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts b/src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts index 1c7fbc0351..6e77055b3c 100644 --- a/src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts +++ b/src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts @@ -12,11 +12,12 @@ import { validate } from '../validate.js'; import { expectValidationErrorsWithSchema } from './harness.js'; -function expectErrors(queryStr: string) { +function expectErrors(queryStr: string, hideSuggestions = false) { return expectValidationErrorsWithSchema( testSchema, FieldsOnCorrectTypeRule, queryStr, + hideSuggestions, ); } @@ -140,6 +141,22 @@ describe('Validate: Fields on correct type', () => { ]); }); + it('Field not defined on fragment (no suggestions)', () => { + expectErrors( + ` + fragment fieldNotDefined on Dog { + meowVolume + } + `, + true, + ).toDeepEqual([ + { + message: 'Cannot query field "meowVolume" on type "Dog".', + locations: [{ line: 3, column: 9 }], + }, + ]); + }); + it('Ignores deeply unknown field', () => { expectErrors(` fragment deepFieldNotDefined on Dog { diff --git a/src/validation/__tests__/KnownArgumentNamesRule-test.ts b/src/validation/__tests__/KnownArgumentNamesRule-test.ts index 0fcffeca2c..073f9eded3 100644 --- a/src/validation/__tests__/KnownArgumentNamesRule-test.ts +++ b/src/validation/__tests__/KnownArgumentNamesRule-test.ts @@ -14,8 +14,12 @@ import { expectValidationErrors, } from './harness.js'; -function expectErrors(queryStr: string) { - return expectValidationErrors(KnownArgumentNamesRule, queryStr); +function expectErrors(queryStr: string, hideSuggestions = false) { + return expectValidationErrors( + KnownArgumentNamesRule, + queryStr, + hideSuggestions, + ); } function expectValid(queryStr: string) { @@ -100,6 +104,19 @@ describe('Validate: Known argument names', () => { `); }); + it('fragment args are known', () => { + expectValid(` + { + dog { + ...withArg(dogCommand: SIT) + } + } + fragment withArg($dogCommand: DogCommand) on Dog { + doesKnowCommand(dogCommand: $dogCommand) + } + `); + }); + it('field args are invalid', () => { expectErrors(` { @@ -148,6 +165,80 @@ describe('Validate: Known argument names', () => { ]); }); + it('misspelled directive args are reported (no suggestions)', () => { + expectErrors( + ` + { + dog @skip(iff: true) + } + `, + true, + ).toDeepEqual([ + { + message: 'Unknown argument "iff" on directive "@skip".', + locations: [{ line: 3, column: 19 }], + }, + ]); + }); + + it('arg passed to fragment without arg is reported', () => { + expectErrors(` + { + dog { + ...withoutArg(unknown: true) + } + } + fragment withoutArg on Dog { + doesKnowCommand + } + `).toDeepEqual([ + { + message: 'Unknown argument "unknown" on fragment "withoutArg".', + locations: [{ line: 4, column: 25 }], + }, + ]); + }); + + it('misspelled fragment args are reported', () => { + expectErrors(` + { + dog { + ...withArg(command: SIT) + } + } + fragment withArg($dogCommand: DogCommand) on Dog { + doesKnowCommand(dogCommand: $dogCommand) + } + `).toDeepEqual([ + { + message: + 'Unknown argument "command" on fragment "withArg". Did you mean "dogCommand"?', + locations: [{ line: 4, column: 22 }], + }, + ]); + }); + + it('misspelled fragment args are reported (no suggestions)', () => { + expectErrors( + ` + { + dog { + ...withArg(command: SIT) + } + } + fragment withArg($dogCommand: DogCommand) on Dog { + doesKnowCommand(dogCommand: $dogCommand) + } + `, + true, + ).toDeepEqual([ + { + message: 'Unknown argument "command" on fragment "withArg".', + locations: [{ line: 4, column: 22 }], + }, + ]); + }); + it('invalid arg name', () => { expectErrors(` fragment invalidArgName on Dog { @@ -175,6 +266,23 @@ describe('Validate: Known argument names', () => { ]); }); + it('misspelled arg name is reported (no suggestions)', () => { + expectErrors( + ` + fragment invalidArgName on Dog { + doesKnowCommand(DogCommand: true) + } + `, + true, + ).toDeepEqual([ + { + message: + 'Unknown argument "DogCommand" on field "Dog.doesKnowCommand".', + locations: [{ line: 3, column: 25 }], + }, + ]); + }); + it('unknown args amongst known args', () => { expectErrors(` fragment oneGoodArgOneInvalidArg on Dog { diff --git a/src/validation/__tests__/KnownDirectivesRule-test.ts b/src/validation/__tests__/KnownDirectivesRule-test.ts index a3bbc198da..7c91de4870 100644 --- a/src/validation/__tests__/KnownDirectivesRule-test.ts +++ b/src/validation/__tests__/KnownDirectivesRule-test.ts @@ -44,6 +44,7 @@ const schemaWithDirectives = buildSchema(` directive @onFragmentSpread on FRAGMENT_SPREAD directive @onInlineFragment on INLINE_FRAGMENT directive @onVariableDefinition on VARIABLE_DEFINITION + directive @onFragmentVariableDefinition on FRAGMENT_VARIABLE_DEFINITION `); const schemaWithSDLDirectives = buildSchema(` @@ -150,7 +151,9 @@ describe('Validate: Known directives', () => { someField @onField } - fragment Frag on Human @onFragmentDefinition { + fragment Frag( + $arg: Int @onFragmentVariableDefinition + ) on Human @onFragmentDefinition { name @onField } `); @@ -175,7 +178,7 @@ describe('Validate: Known directives', () => { someField @onQuery } - fragment Frag on Human @onQuery { + fragment Frag($arg: Int @onVariableDefinition) on Human @onQuery { name @onQuery } `).toDeepEqual([ @@ -219,9 +222,14 @@ describe('Validate: Known directives', () => { message: 'Directive "@onQuery" may not be used on FIELD.', locations: [{ column: 19, line: 16 }], }, + { + message: + 'Directive "@onVariableDefinition" may not be used on FRAGMENT_VARIABLE_DEFINITION.', + locations: [{ column: 31, line: 19 }], + }, { message: 'Directive "@onQuery" may not be used on FRAGMENT_DEFINITION.', - locations: [{ column: 30, line: 19 }], + locations: [{ column: 63, line: 19 }], }, { message: 'Directive "@onQuery" may not be used on FIELD.', @@ -348,6 +356,9 @@ describe('Validate: Known directives', () => { query: MyQuery } + directive @myDirective(arg:String) on ARGUMENT_DEFINITION + directive @myDirective2(arg:String @myDirective) on FIELD + extend schema @onSchema `, schemaWithSDLDirectives, diff --git a/src/validation/__tests__/KnownOperationTypesRules-test.ts b/src/validation/__tests__/KnownOperationTypesRules-test.ts new file mode 100644 index 0000000000..93ab581725 --- /dev/null +++ b/src/validation/__tests__/KnownOperationTypesRules-test.ts @@ -0,0 +1,60 @@ +import { describe, it } from 'mocha'; + +import { KnownOperationTypesRule } from '../rules/KnownOperationTypesRule.js'; + +import { expectValidationErrors } from './harness.js'; + +function expectErrors(queryStr: string) { + return expectValidationErrors(KnownOperationTypesRule, queryStr); +} + +function expectValid(queryStr: string) { + expectErrors(queryStr).toDeepEqual([]); +} + +describe('Validate: Known operation types', () => { + it('one known operation', () => { + expectValid(` + { field } + `); + }); + + it('unknown mutation operation', () => { + expectErrors(` + mutation { field } + `).toDeepEqual([ + { + message: 'The mutation operation is not supported by the schema.', + locations: [{ line: 2, column: 7 }], + }, + ]); + }); + + it('unknown subscription operation', () => { + expectErrors(` + subscription { field } + `).toDeepEqual([ + { + message: 'The subscription operation is not supported by the schema.', + locations: [{ line: 2, column: 7 }], + }, + ]); + }); + + it('mixture of known and unknown operations', () => { + expectErrors(` + query { field } + mutation { field } + subscription { field } + `).toDeepEqual([ + { + message: 'The mutation operation is not supported by the schema.', + locations: [{ line: 3, column: 7 }], + }, + { + message: 'The subscription operation is not supported by the schema.', + locations: [{ line: 4, column: 7 }], + }, + ]); + }); +}); diff --git a/src/validation/__tests__/KnownTypeNamesRule-test.ts b/src/validation/__tests__/KnownTypeNamesRule-test.ts index 0440c094d0..c01b93638b 100644 --- a/src/validation/__tests__/KnownTypeNamesRule-test.ts +++ b/src/validation/__tests__/KnownTypeNamesRule-test.ts @@ -12,8 +12,8 @@ import { expectValidationErrorsWithSchema, } from './harness.js'; -function expectErrors(queryStr: string) { - return expectValidationErrors(KnownTypeNamesRule, queryStr); +function expectErrors(queryStr: string, hideSuggestions = false) { + return expectValidationErrors(KnownTypeNamesRule, queryStr, hideSuggestions); } function expectErrorsWithSchema(schema: GraphQLSchema, queryStr: string) { @@ -78,6 +78,36 @@ describe('Validate: Known type names', () => { ]); }); + it('unknown type names are invalid (no suggestions)', () => { + expectErrors( + ` + query Foo($var: [JumbledUpLetters!]!) { + user(id: 4) { + name + pets { ... on Badger { name }, ...PetFields } + } + } + fragment PetFields on Peat { + name + } + `, + true, + ).toDeepEqual([ + { + message: 'Unknown type "JumbledUpLetters".', + locations: [{ line: 2, column: 24 }], + }, + { + message: 'Unknown type "Badger".', + locations: [{ line: 5, column: 25 }], + }, + { + message: 'Unknown type "Peat".', + locations: [{ line: 8, column: 29 }], + }, + ]); + }); + it('references to standard scalars that are missing in schema', () => { const schema = buildSchema('type Query { foo: String }'); const query = ` diff --git a/src/validation/__tests__/MaxIntrospectionDepthRule-test.ts b/src/validation/__tests__/MaxIntrospectionDepthRule-test.ts new file mode 100644 index 0000000000..ff6826c873 --- /dev/null +++ b/src/validation/__tests__/MaxIntrospectionDepthRule-test.ts @@ -0,0 +1,554 @@ +import { describe, it } from 'mocha'; + +import { getIntrospectionQuery } from '../../utilities/getIntrospectionQuery.js'; + +import { MaxIntrospectionDepthRule } from '../rules/MaxIntrospectionDepthRule.js'; + +import { expectValidationErrors } from './harness.js'; + +function expectErrors(queryStr: string) { + return expectValidationErrors(MaxIntrospectionDepthRule, queryStr); +} + +function expectValid(queryStr: string) { + expectErrors(queryStr).toDeepEqual([]); +} + +describe('Validate: Max introspection nodes rule', () => { + it('default introspection query', () => { + expectValid(getIntrospectionQuery()); + }); + + it('all options introspection query', () => { + expectValid( + getIntrospectionQuery({ + descriptions: true, + specifiedByUrl: true, + directiveIsRepeatable: true, + schemaDescription: true, + inputValueDeprecation: true, + }), + ); + }); + + it('3 flat fields introspection query', () => { + expectValid(` + { + __type(name: "Query") { + trueFields: fields(includeDeprecated: true) { + name + } + falseFields: fields(includeDeprecated: false) { + name + } + omittedFields: fields { + name + } + } + } + `); + }); + + it('3 fields deep introspection query from __schema', () => { + expectErrors(` + { + __schema { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 interfaces deep introspection query from __schema', () => { + expectErrors(` + { + __schema { + types { + interfaces { + interfaces { + interfaces { + name + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 possibleTypes deep introspection query from __schema', () => { + expectErrors(` + { + __schema { + types { + possibleTypes { + possibleTypes { + possibleTypes { + name + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 inputFields deep introspection query from __schema', () => { + expectErrors(` + { + __schema { + types { + inputFields { + type { + inputFields { + type { + inputFields { + type { + name + } + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 fields deep introspection query from multiple __schema', () => { + expectErrors(` + { + one: __schema { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + two: __schema { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + three: __schema { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + { + locations: [ + { + column: 7, + line: 18, + }, + ], + message: 'Maximum introspection depth exceeded', + }, + { + locations: [ + { + column: 7, + line: 33, + }, + ], + message: 'Maximum introspection depth exceeded', + }, + ]); + }); + + it('3 fields deep introspection query from __type', () => { + expectErrors(` + { + __type(name: "Query") { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 fields deep introspection query from multiple __type', () => { + expectErrors(` + { + one: __type(name: "Query") { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + two: __type(name: "Query") { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + three: __type(name: "Query") { + types { + fields { + type { + fields { + type { + fields { + name + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + { + locations: [ + { + column: 7, + line: 18, + }, + ], + message: 'Maximum introspection depth exceeded', + }, + { + locations: [ + { + column: 7, + line: 33, + }, + ], + message: 'Maximum introspection depth exceeded', + }, + ]); + }); + + it('1 fields deep with 3 fields introspection query', () => { + expectValid(` + { + __schema { + types { + fields { + type { + oneFields: fields { + name + } + twoFields: fields { + name + } + threeFields: fields { + name + } + } + } + } + } + } + `); + }); + + it('3 fields deep from varying parents introspection query', () => { + expectErrors(` + { + __schema { + types { + fields { + type { + fields { + type { + ofType { + fields { + name + } + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 fields deep introspection query with inline fragments', () => { + expectErrors(` + query test { + __schema { + types { + ... on __Type { + fields { + type { + ... on __Type { + ofType { + fields { + type { + ... on __Type { + fields { + name + } + } + } + } + } + } + } + } + } + } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 fields deep introspection query with fragments', () => { + expectErrors(` + query test { + __schema { + types { + ...One + } + } + } + + fragment One on __Type { + fields { + type { + ...Two + } + } + } + + fragment Two on __Type { + fields { + type { + ...Three + } + } + } + + fragment Three on __Type { + fields { + name + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 7, + line: 3, + }, + ], + }, + ]); + }); + + it('3 fields deep inside inline fragment on query', () => { + expectErrors(` + { + ... { + __schema { types { fields { type { fields { type { fields { name } } } } } } } + } + } + `).toDeepEqual([ + { + message: 'Maximum introspection depth exceeded', + locations: [ + { + column: 9, + line: 4, + }, + ], + }, + ]); + }); + + it('opts out if fragment is missing', () => { + expectValid(` + query test { + __schema { + types { + ...Missing + } + } + } + `); + }); + + it("doesn't infinitely recurse on fragment cycle", () => { + expectValid(` + query test { + __schema { + types { + ...Cycle + } + } + } + fragment Cycle on __Type { + ...Cycle + } + `); + }); +}); diff --git a/src/validation/__tests__/NoDeprecatedCustomRule-test.ts b/src/validation/__tests__/NoDeprecatedCustomRule-test.ts index 96823684fc..90dfb0dbdc 100644 --- a/src/validation/__tests__/NoDeprecatedCustomRule-test.ts +++ b/src/validation/__tests__/NoDeprecatedCustomRule-test.ts @@ -106,7 +106,7 @@ describe('Validate: no deprecated', () => { `).toDeepEqual([ { message: - 'Field "Query.someField" argument "deprecatedArg" is deprecated. Some arg reason.', + 'The argument "Query.someField(deprecatedArg:)" is deprecated. Some arg reason.', locations: [{ line: 3, column: 21 }], }, ]); @@ -150,7 +150,7 @@ describe('Validate: no deprecated', () => { `).toDeepEqual([ { message: - 'Directive "@someDirective" argument "deprecatedArg" is deprecated. Some arg reason.', + 'The argument "@someDirective(deprecatedArg:)" is deprecated. Some arg reason.', locations: [{ line: 3, column: 36 }], }, ]); diff --git a/src/validation/__tests__/NoUndefinedVariablesRule-test.ts b/src/validation/__tests__/NoUndefinedVariablesRule-test.ts index c6ed758cad..9d53ea8c2e 100644 --- a/src/validation/__tests__/NoUndefinedVariablesRule-test.ts +++ b/src/validation/__tests__/NoUndefinedVariablesRule-test.ts @@ -404,4 +404,67 @@ describe('Validate: No undefined variables', () => { }, ]); }); + + it('fragment defined arguments are not undefined variables', () => { + expectValid(` + query Foo { + ...FragA + } + fragment FragA($a: String) on Type { + field1(a: $a) + } + `); + }); + + it('defined variables used as fragment arguments are not undefined variables', () => { + expectValid(` + query Foo($b: String) { + ...FragA(a: $b) + } + fragment FragA($a: String) on Type { + field1 + } + `); + }); + + it('variables used as fragment arguments may be undefined variables', () => { + expectErrors(` + query Foo { + ...FragA(a: $a) + } + fragment FragA($a: String) on Type { + field1 + } + `).toDeepEqual([ + { + message: 'Variable "$a" is not defined by operation "Foo".', + locations: [ + { line: 3, column: 21 }, + { line: 2, column: 7 }, + ], + }, + ]); + }); + + it('variables shadowed by parent fragment arguments are still undefined variables', () => { + expectErrors(` + query Foo { + ...FragA + } + fragment FragA($a: String) on Type { + ...FragB + } + fragment FragB on Type { + field1(a: $a) + } + `).toDeepEqual([ + { + message: 'Variable "$a" is not defined by operation "Foo".', + locations: [ + { line: 9, column: 19 }, + { line: 2, column: 7 }, + ], + }, + ]); + }); }); diff --git a/src/validation/__tests__/NoUnusedVariablesRule-test.ts b/src/validation/__tests__/NoUnusedVariablesRule-test.ts index 47dac39c99..49076361be 100644 --- a/src/validation/__tests__/NoUnusedVariablesRule-test.ts +++ b/src/validation/__tests__/NoUnusedVariablesRule-test.ts @@ -230,4 +230,42 @@ describe('Validate: No unused variables', () => { }, ]); }); + + it('fragment defined arguments are not unused variables', () => { + expectValid(` + query Foo { + ...FragA + } + fragment FragA($a: String) on Type { + field1(a: $a) + } + `); + }); + + it('defined variables used as fragment arguments are not unused variables', () => { + expectValid(` + query Foo($b: String) { + ...FragA(a: $b) + } + fragment FragA($a: String) on Type { + field1(a: $a) + } + `); + }); + + it('unused fragment variables are reported', () => { + expectErrors(` + query Foo { + ...FragA(a: "value") + } + fragment FragA($a: String) on Type { + field1 + } + `).toDeepEqual([ + { + message: 'Variable "$a" is never used in fragment "FragA".', + locations: [{ line: 5, column: 22 }], + }, + ]); + }); }); diff --git a/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts b/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts index ecb56a15cf..582e4602af 100644 --- a/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts +++ b/src/validation/__tests__/OverlappingFieldsCanBeMergedRule-test.ts @@ -638,10 +638,10 @@ describe('Validate: Overlapping fields can be merged', () => { expectErrors(` { field { - ...F + ...I } field { - ...I + ...F } } fragment F on T { @@ -661,14 +661,41 @@ describe('Validate: Overlapping fields can be merged', () => { `).toDeepEqual([ { message: - 'Fields "field" conflict because subfields "x" conflict because "a" and "b" are different fields and subfields "y" conflict because "c" and "d" are different fields. Use different aliases on the fields to fetch both if this was intentional.', + 'Fields "field" conflict because subfields "y" conflict because "d" and "c" are different fields and subfields "x" conflict because "b" and "a" are different fields. Use different aliases on the fields to fetch both if this was intentional.', locations: [ { line: 3, column: 9 }, - { line: 11, column: 9 }, - { line: 15, column: 9 }, - { line: 6, column: 9 }, - { line: 22, column: 9 }, { line: 18, column: 9 }, + { line: 22, column: 9 }, + { line: 6, column: 9 }, + { line: 15, column: 9 }, + { line: 11, column: 9 }, + ], + }, + ]); + }); + + it('reports deep conflict after nested fragments', () => { + expectErrors(` + fragment F on T { + ...G + } + fragment G on T { + ...H + } + fragment H on T { + x: a + } + { + x: b + ...F + } + `).toDeepEqual([ + { + message: + 'Fields "x" conflict because "b" and "a" are different fields. Use different aliases on the fields to fetch both if this was intentional.', + locations: [ + { line: 12, column: 9 }, + { line: 9, column: 9 }, ], }, ]); @@ -1264,4 +1291,266 @@ describe('Validate: Overlapping fields can be merged', () => { }, ]); }); + + it('does not infinite loop on recursive fragments separated by fields', () => { + expectValid(` + { + ...fragA + ...fragB + } + + fragment fragA on T { + x { + ...fragA + x { + ...fragA + } + } + } + + fragment fragB on T { + x { + ...fragB + x { + ...fragB + } + } + } + `); + }); + + describe('fragment arguments must produce fields that can be merged', () => { + it('allows conflicting spreads at different depths', () => { + expectValid(` + query ValidDifferingFragmentArgs($command1: DogCommand, $command2: DogCommand) { + dog { + ...DoesKnowCommand(command: $command1) + mother { + ...DoesKnowCommand(command: $command2) + } + } + } + fragment DoesKnowCommand($command: DogCommand) on Dog { + doesKnowCommand(dogCommand: $command) + } + `); + }); + + it('encounters conflict in fragments', () => { + expectErrors(` + { + ...WithArgs(x: 3) + ...WithArgs(x: 4) + } + fragment WithArgs($x: Int) on Type { + a(x: $x) + } + `).toDeepEqual([ + { + message: + 'Spreads "WithArgs" conflict because WithArgs(x: 3) and WithArgs(x: 4) have different fragment arguments.', + locations: [ + { line: 3, column: 11 }, + { line: 4, column: 11 }, + ], + }, + ]); + }); + + it('allows operations with overlapping fields with arguments using identical operation variables', () => { + expectValid(` + query ($y: Int = 1) { + a(x: $y) + ...WithArgs(x: 1) + } + fragment WithArgs($x: Int = 1) on Type { + a(x: $y) + } + `); + }); + + it('allows operations with overlapping fields with identical variable arguments passed via fragment arguments', () => { + expectValid(` + query ($y: Int = 1) { + a(x: $y) + ...WithArgs(x: $y) + } + fragment WithArgs($x: Int) on Type { + a(x: $x) + } + `); + }); + + it('allows operations with overlapping fields with identical variable arguments passed via nested fragment arguments', () => { + expectValid(` + query ($z: Int = 1) { + a(x: $z) + ...WithArgs(y: $z) + } + fragment WithArgs($y: Int) on Type { + ...NestedWithArgs(x: $y) + } + fragment NestedWithArgs($x: Int) on Type { + a(x: $x) + } + `); + }); + + it('allows operations with overlapping fields with identical arguments via fragment variable defaults', () => { + expectValid(` + query { + a(x: 1) + ...WithArgs + } + fragment WithArgs($x: Int = 1) on Type { + a(x: $x) + } + `); + }); + + it('raises errors with overlapping fields with arguments that conflict via operation variables even with defaults and fragment variable defaults', () => { + expectErrors(` + query ($y: Int = 1) { + a(x: $y) + ...WithArgs + } + fragment WithArgs($x: Int = 1) on Type { + a(x: $x) + } + `).toDeepEqual([ + { + message: + 'Fields "a" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.', + locations: [ + { line: 3, column: 11 }, + { line: 7, column: 11 }, + ], + }, + ]); + }); + + it('allows operations with overlapping list fields with identical variable arguments passed via fragment arguments', () => { + expectValid(` + query Query($stringListVarY: [String]) { + complicatedArgs { + stringListArgField(stringListArg: $stringListVarY) + ...WithArgs(stringListVarX: $stringListVarY) + } + } + fragment WithArgs($stringListVarX: [String]) on Type { + stringListArgField(stringListArg: $stringListVarX) + } + `); + }); + + it('allows operations with overlapping list fields with identical variable arguments in item position passed via fragment arguments', () => { + expectValid(` + query Query($stringListVarY: [String]) { + complicatedArgs { + stringListArgField(stringListArg: [$stringListVarY]) + ...WithArgs(stringListVarX: $stringListVarY) + } + } + fragment WithArgs($stringListVarX: [String]) on Type { + stringListArgField(stringListArg: [$stringListVarX]) + } + `); + }); + + it('allows operations with overlapping input object fields with identical variable arguments passed via fragment arguments', () => { + expectValid(` + query Query($complexVarY: ComplexInput) { + complicatedArgs { + complexArgField(complexArg: $complexVarY) + ...WithArgs(complexVarX: $complexVarY) + } + } + fragment WithArgs($complexVarX: ComplexInput) on Type { + complexArgField(complexArg: $complexVarX) + } + `); + }); + + it('allows operations with overlapping input object fields with identical variable arguments in field position passed via fragment arguments', () => { + expectValid(` + query Query($boolVarY: Boolean) { + complicatedArgs { + complexArgField(complexArg: {requiredArg: $boolVarY}) + ...WithArgs(boolVarX: $boolVarY) + } + } + fragment WithArgs($boolVarX: Boolean) on Type { + complexArgField(complexArg: {requiredArg: $boolVarX}) + } + `); + }); + + it('encounters nested field conflict in fragments that could otherwise merge', () => { + expectErrors(` + query ValidDifferingFragmentArgs($command1: DogCommand, $command2: DogCommand) { + dog { + ...DoesKnowCommandNested(command: $command1) + mother { + ...DoesKnowCommandNested(command: $command2) + } + } + } + fragment DoesKnowCommandNested($command: DogCommand) on Dog { + doesKnowCommand(dogCommand: $command) + mother { + doesKnowCommand(dogCommand: $command) + } + } + `).toDeepEqual([ + { + message: + 'Fields "mother" conflict because subfields "doesKnowCommand" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.', + locations: [ + { line: 5, column: 13 }, + { line: 13, column: 13 }, + { line: 12, column: 11 }, + { line: 11, column: 11 }, + ], + }, + ]); + }); + + it('encounters nested conflict in fragments', () => { + expectErrors(` + { + connection { + edges { + ...WithArgs(x: 3) + } + } + ...Connection + } + fragment Connection on Type { + connection { + edges { + ...WithArgs(x: 4) + } + } + } + fragment WithArgs($x: Int) on Type { + a(x: $x) + } + `).toDeepEqual([ + { + message: + 'Spreads "WithArgs" conflict because WithArgs(x: 3) and WithArgs(x: 4) have different fragment arguments.', + locations: [ + { + column: 15, + line: 5, + }, + { + column: 15, + line: 13, + }, + ], + }, + ]); + }); + }); }); diff --git a/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts b/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts index 6f0d223c15..95953fc37f 100644 --- a/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts +++ b/src/validation/__tests__/ProvidedRequiredArgumentsRule-test.ts @@ -168,7 +168,7 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Field "multipleReqs" argument "req1" of type "Int!" is required, but it was not provided.', + 'Argument "ComplicatedArgs.multipleReqs(req1:)" of type "Int!" is required, but it was not provided.', locations: [{ line: 4, column: 13 }], }, ]); @@ -184,12 +184,12 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Field "multipleReqs" argument "req1" of type "Int!" is required, but it was not provided.', + 'Argument "ComplicatedArgs.multipleReqs(req1:)" of type "Int!" is required, but it was not provided.', locations: [{ line: 4, column: 13 }], }, { message: - 'Field "multipleReqs" argument "req2" of type "Int!" is required, but it was not provided.', + 'Argument "ComplicatedArgs.multipleReqs(req2:)" of type "Int!" is required, but it was not provided.', locations: [{ line: 4, column: 13 }], }, ]); @@ -205,7 +205,7 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Field "multipleReqs" argument "req2" of type "Int!" is required, but it was not provided.', + 'Argument "ComplicatedArgs.multipleReqs(req2:)" of type "Int!" is required, but it was not provided.', locations: [{ line: 4, column: 13 }], }, ]); @@ -244,12 +244,12 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Directive "@include" argument "if" of type "Boolean!" is required, but it was not provided.', + 'Argument "@include(if:)" of type "Boolean!" is required, but it was not provided.', locations: [{ line: 3, column: 15 }], }, { message: - 'Directive "@skip" argument "if" of type "Boolean!" is required, but it was not provided.', + 'Argument "@skip(if:)" of type "Boolean!" is required, but it was not provided.', locations: [{ line: 4, column: 18 }], }, ]); @@ -277,7 +277,7 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Directive "@test" argument "arg" of type "String!" is required, but it was not provided.', + 'Argument "@test(arg:)" of type "String!" is required, but it was not provided.', locations: [{ line: 3, column: 23 }], }, ]); @@ -291,7 +291,7 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Directive "@include" argument "if" of type "Boolean!" is required, but it was not provided.', + 'Argument "@include(if:)" of type "Boolean!" is required, but it was not provided.', locations: [{ line: 3, column: 23 }], }, ]); @@ -306,7 +306,7 @@ describe('Validate: Provided required arguments', () => { `).toDeepEqual([ { message: - 'Directive "@deprecated" argument "reason" of type "String!" is required, but it was not provided.', + 'Argument "@deprecated(reason:)" of type "String!" is required, but it was not provided.', locations: [{ line: 3, column: 23 }], }, ]); @@ -328,7 +328,7 @@ describe('Validate: Provided required arguments', () => { ).toDeepEqual([ { message: - 'Directive "@test" argument "arg" of type "String!" is required, but it was not provided.', + 'Argument "@test(arg:)" of type "String!" is required, but it was not provided.', locations: [{ line: 4, column: 30 }], }, ]); @@ -350,10 +350,89 @@ describe('Validate: Provided required arguments', () => { ).toDeepEqual([ { message: - 'Directive "@test" argument "arg" of type "String!" is required, but it was not provided.', + 'Argument "@test(arg:)" of type "String!" is required, but it was not provided.', locations: [{ line: 2, column: 29 }], }, ]); }); }); + + describe('Fragment required arguments', () => { + it('ignores unknown arguments', () => { + expectValid(` + { + ...Foo(unknownArgument: true) + } + fragment Foo on Query { + dog + } + `); + }); + + it('Missing nullable argument with default is allowed', () => { + expectValid(` + { + ...F + } + fragment F($x: Int = 3) on Query { + foo + } + `); + }); + it('Missing nullable argument is allowed', () => { + expectValid(` + { + ...F + } + fragment F($x: Int) on Query { + foo + } + `); + }); + it('Missing non-nullable argument with default is allowed', () => { + expectValid(` + { + ...F + } + fragment F($x: Int! = 3) on Query { + foo + } + `); + }); + it('Missing non-nullable argument is not allowed', () => { + expectErrors(` + { + ...F + } + fragment F($x: Int!) on Query { + foo + } + `).toDeepEqual([ + { + message: + 'Fragment "F" argument "x" of type "Int!" is required, but it was not provided.', + locations: [{ line: 3, column: 13 }], + }, + ]); + }); + + it('Supplies required variables', () => { + expectValid(` + { + ...F(x: 3) + } + fragment F($x: Int!) on Query { + foo + } + `); + }); + + it('Skips missing fragments', () => { + expectValid(` + { + ...Missing(x: 3) + } + `); + }); + }); }); diff --git a/src/validation/__tests__/ScalarLeafsRule-test.ts b/src/validation/__tests__/ScalarLeafsRule-test.ts index fd000b92c9..33f091e65c 100644 --- a/src/validation/__tests__/ScalarLeafsRule-test.ts +++ b/src/validation/__tests__/ScalarLeafsRule-test.ts @@ -1,8 +1,15 @@ import { describe, it } from 'mocha'; +import { expectJSON } from '../../__testUtils__/expectJSON.js'; + +import type { DocumentNode } from '../../language/ast.js'; +import { OperationTypeNode } from '../../language/ast.js'; +import { Kind } from '../../language/kinds.js'; + import { ScalarLeafsRule } from '../rules/ScalarLeafsRule.js'; +import { validate } from '../validate.js'; -import { expectValidationErrors } from './harness.js'; +import { expectValidationErrors, testSchema } from './harness.js'; function expectErrors(queryStr: string) { return expectValidationErrors(ScalarLeafsRule, queryStr); @@ -35,6 +42,39 @@ describe('Validate: Scalar leafs', () => { ]); }); + it('object type having only one selection', () => { + const doc: DocumentNode = { + kind: Kind.DOCUMENT, + definitions: [ + { + kind: Kind.OPERATION_DEFINITION, + operation: OperationTypeNode.QUERY, + selectionSet: { + kind: Kind.SELECTION_SET, + selections: [ + { + kind: Kind.FIELD, + name: { kind: Kind.NAME, value: 'human' }, + selectionSet: { kind: Kind.SELECTION_SET, selections: [] }, + }, + ], + }, + }, + ], + }; + + // We can't leverage expectErrors since it doesn't support passing in the + // documentNode directly. We have to do this because this is technically + // an invalid document. + const errors = validate(testSchema, doc, [ScalarLeafsRule]); + expectJSON(errors).toDeepEqual([ + { + message: + 'Field "human" of type "Human" must have at least one field selected.', + }, + ]); + }); + it('interface type missing selection', () => { expectErrors(` { diff --git a/src/validation/__tests__/StreamDirectiveOnListFieldRule-test.ts b/src/validation/__tests__/StreamDirectiveOnListFieldRule-test.ts index a35c31232d..ec49d42c29 100644 --- a/src/validation/__tests__/StreamDirectiveOnListFieldRule-test.ts +++ b/src/validation/__tests__/StreamDirectiveOnListFieldRule-test.ts @@ -71,7 +71,7 @@ describe('Validate: Stream directive on list field', () => { `).toDeepEqual([ { message: - 'Stream directive cannot be used on non-list field "name" on type "Human".', + 'Directive "@stream" cannot be used on non-list field "Human.name".', locations: [{ line: 3, column: 14 }], }, ]); diff --git a/src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts b/src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts index c36ebb6992..9631c1ae05 100644 --- a/src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts +++ b/src/validation/__tests__/ValuesOfCorrectTypeRule-test.ts @@ -3,8 +3,6 @@ import { describe, it } from 'mocha'; import { expectJSON } from '../../__testUtils__/expectJSON.js'; -import { inspect } from '../../jsutils/inspect.js'; - import { parse } from '../../language/parser.js'; import { GraphQLObjectType, GraphQLScalarType } from '../../type/definition.js'; @@ -19,8 +17,12 @@ import { expectValidationErrorsWithSchema, } from './harness.js'; -function expectErrors(queryStr: string) { - return expectValidationErrors(ValuesOfCorrectTypeRule, queryStr); +function expectErrors(queryStr: string, hideSuggestions = false) { + return expectValidationErrors( + ValuesOfCorrectTypeRule, + queryStr, + hideSuggestions, + ); } function expectErrorsWithSchema(schema: GraphQLSchema, queryStr: string) { @@ -526,6 +528,24 @@ describe('Validate: Values of correct type', () => { ]); }); + it('String into Enum (no suggestion)', () => { + expectErrors( + ` + { + dog { + doesKnowCommand(dogCommand: "SIT") + } + } + `, + true, + ).toDeepEqual([ + { + message: 'Enum "DogCommand" cannot represent non-enum value: "SIT".', + locations: [{ line: 4, column: 41 }], + }, + ]); + }); + it('Boolean into Enum', () => { expectErrors(` { @@ -571,6 +591,24 @@ describe('Validate: Values of correct type', () => { }, ]); }); + + it('Different case Enum Value into Enum (no suggestion)', () => { + expectErrors( + ` + { + dog { + doesKnowCommand(dogCommand: sit) + } + } + `, + true, + ).toDeepEqual([ + { + message: 'Value "sit" does not exist in "DogCommand" enum.', + locations: [{ line: 4, column: 41 }], + }, + ]); + }); }); describe('Valid List value', () => { @@ -793,7 +831,7 @@ describe('Validate: Values of correct type', () => { } `).toDeepEqual([ { - message: 'Expected value of type "Int!", found null.', + message: 'Expected value of non-null type "Int!" not to be null.', locations: [{ line: 4, column: 32 }], }, ]); @@ -907,7 +945,7 @@ describe('Validate: Values of correct type', () => { `).toDeepEqual([ { message: - 'Field "ComplexInput.requiredField" of required type "Boolean!" was not provided.', + 'Expected value of type "ComplexInput" to include required field "requiredField", found: { intField: 4 }.', locations: [{ line: 4, column: 41 }], }, ]); @@ -943,7 +981,7 @@ describe('Validate: Values of correct type', () => { } `).toDeepEqual([ { - message: 'Expected value of type "Boolean!", found null.', + message: 'Expected value of non-null type "Boolean!" not to be null.', locations: [{ line: 6, column: 29 }], }, ]); @@ -962,7 +1000,29 @@ describe('Validate: Values of correct type', () => { `).toDeepEqual([ { message: - 'Field "invalidField" is not defined by type "ComplexInput". Did you mean "intField"?', + 'Expected value of type "ComplexInput" not to include unknown field "invalidField". Did you mean "intField"? Found: { requiredField: true, invalidField: "value" }.', + locations: [{ line: 6, column: 15 }], + }, + ]); + }); + + it('Partial object, unknown field arg (no suggestions)', () => { + expectErrors( + ` + { + complicatedArgs { + complexArgField(complexArg: { + requiredField: true, + invalidField: "value" + }) + } + } + `, + true, + ).toDeepEqual([ + { + message: + 'Expected value of type "ComplexInput" not to include unknown field "invalidField", found: { requiredField: true, invalidField: "value" }.', locations: [{ line: 6, column: 15 }], }, ]); @@ -971,10 +1031,8 @@ describe('Validate: Values of correct type', () => { it('reports original error for custom scalar which throws', () => { const customScalar = new GraphQLScalarType({ name: 'Invalid', - parseValue(value) { - throw new Error( - `Invalid scalar is always invalid: ${inspect(value)}`, - ); + coerceInputValue() { + throw new Error('Invalid scalar is always invalid.'); }, }); @@ -996,21 +1054,21 @@ describe('Validate: Values of correct type', () => { expectJSON(errors).toDeepEqual([ { message: - 'Expected value of type "Invalid", found 123; Invalid scalar is always invalid: 123', + 'Expected value of type "Invalid", but encountered error "Invalid scalar is always invalid."; found: 123.', locations: [{ line: 1, column: 19 }], }, ]); expect(errors[0]).to.have.nested.property( 'originalError.message', - 'Invalid scalar is always invalid: 123', + 'Invalid scalar is always invalid.', ); }); it('reports error for custom scalar that returns undefined', () => { const customScalar = new GraphQLScalarType({ name: 'CustomScalar', - parseValue() { + coerceInputValue() { return undefined; }, }); @@ -1029,7 +1087,7 @@ describe('Validate: Values of correct type', () => { expectErrorsWithSchema(schema, '{ invalidArg(arg: 123) }').toDeepEqual([ { - message: 'Expected value of type "CustomScalar", found 123.', + message: 'Expected value of type "CustomScalar", found: 123.', locations: [{ line: 1, column: 19 }], }, ]); @@ -1086,25 +1144,10 @@ describe('Validate: Values of correct type', () => { oneOfArgField(oneOfArg: { stringField: null }) } } - `).toDeepEqual([ - { - message: 'Field "OneOfInput.stringField" must be non-null.', - locations: [{ line: 4, column: 37 }], - }, - ]); - }); - - it('Exactly one nullable variable', () => { - expectErrors(` - query ($string: String) { - complicatedArgs { - oneOfArgField(oneOfArg: { stringField: $string }) - } - } `).toDeepEqual([ { message: - 'Variable "string" must be non-nullable to be used for OneOf Input Object "OneOfInput".', + 'Field "OneOfInput.stringField" used for OneOf Input Object must be non-null.', locations: [{ line: 4, column: 37 }], }, ]); @@ -1198,15 +1241,15 @@ describe('Validate: Values of correct type', () => { } `).toDeepEqual([ { - message: 'Expected value of type "Int!", found null.', + message: 'Expected value of non-null type "Int!" not to be null.', locations: [{ line: 3, column: 22 }], }, { - message: 'Expected value of type "String!", found null.', + message: 'Expected value of non-null type "String!" not to be null.', locations: [{ line: 4, column: 25 }], }, { - message: 'Expected value of type "Boolean!", found null.', + message: 'Expected value of non-null type "Boolean!" not to be null.', locations: [{ line: 5, column: 47 }], }, ]); @@ -1232,7 +1275,7 @@ describe('Validate: Values of correct type', () => { }, { message: - 'Expected value of type "ComplexInput", found "NotVeryComplex".', + 'Expected value of type "ComplexInput" to be an object, found: "NotVeryComplex".', locations: [{ line: 5, column: 30 }], }, ]); @@ -1265,7 +1308,7 @@ describe('Validate: Values of correct type', () => { `).toDeepEqual([ { message: - 'Field "ComplexInput.requiredField" of required type "Boolean!" was not provided.', + 'Expected value of type "ComplexInput" to include required field "requiredField", found: { intField: 3 }.', locations: [{ line: 2, column: 55 }], }, ]); @@ -1284,4 +1327,35 @@ describe('Validate: Values of correct type', () => { ]); }); }); + + describe('Fragment argument values', () => { + it('list variables with invalid item', () => { + expectErrors(` + fragment InvalidItem($a: [String] = ["one", 2]) on Query { + dog { name } + } + `).toDeepEqual([ + { + message: 'String cannot represent a non string value: 2', + locations: [{ line: 2, column: 53 }], + }, + ]); + }); + + it('fragment spread with invalid argument value', () => { + expectErrors(` + fragment GivesString on Query { + ...ExpectsInt(a: "three") + } + fragment ExpectsInt($a: Int) on Query { + dog { name } + } + `).toDeepEqual([ + { + message: 'Int cannot represent non-integer value: "three"', + locations: [{ line: 3, column: 28 }], + }, + ]); + }); + }); }); diff --git a/src/validation/__tests__/VariablesAreInputTypesRule-test.ts b/src/validation/__tests__/VariablesAreInputTypesRule-test.ts index 8027a35826..eddd202df8 100644 --- a/src/validation/__tests__/VariablesAreInputTypesRule-test.ts +++ b/src/validation/__tests__/VariablesAreInputTypesRule-test.ts @@ -18,6 +18,9 @@ describe('Validate: Variables are input types', () => { query Foo($a: Unknown, $b: [[Unknown!]]!) { field(a: $a, b: $b) } + fragment Bar($a: Unknown, $b: [[Unknown!]]!) on Query { + field(a: $a, b: $b) + } `); }); @@ -26,6 +29,9 @@ describe('Validate: Variables are input types', () => { query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) { field(a: $a, b: $b, c: $c) } + fragment Bar($a: String, $b: [Boolean!]!, $c: ComplexInput) on Query { + field(a: $a, b: $b, c: $c) + } `); }); @@ -49,4 +55,25 @@ describe('Validate: Variables are input types', () => { }, ]); }); + + it('output types on fragment arguments are invalid', () => { + expectErrors(` + fragment Bar($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) on Query { + field(a: $a, b: $b, c: $c) + } + `).toDeepEqual([ + { + locations: [{ line: 2, column: 24 }], + message: 'Variable "$a" cannot be non-input type "Dog".', + }, + { + locations: [{ line: 2, column: 33 }], + message: 'Variable "$b" cannot be non-input type "[[CatOrDog!]]!".', + }, + { + locations: [{ line: 2, column: 53 }], + message: 'Variable "$c" cannot be non-input type "Pet".', + }, + ]); + }); }); diff --git a/src/validation/__tests__/VariablesInAllowedPositionRule-test.ts b/src/validation/__tests__/VariablesInAllowedPositionRule-test.ts index 16467741bb..127f146230 100644 --- a/src/validation/__tests__/VariablesInAllowedPositionRule-test.ts +++ b/src/validation/__tests__/VariablesInAllowedPositionRule-test.ts @@ -356,5 +356,140 @@ describe('Validate: Variables are in allowed positions', () => { dog @include(if: $boolVar) }`); }); + + it('undefined in directive with default value with option', () => { + expectValid(` + { + dog @include(if: $x) + }`); + }); + }); + + describe('Validates OneOf Input Objects', () => { + it('Allows exactly one non-nullable variable', () => { + expectValid(` + query ($string: String!) { + complicatedArgs { + oneOfArgField(oneOfArg: { stringField: $string }) + } + } + `); + }); + + it('Forbids one nullable variable', () => { + expectErrors(` + query ($string: String) { + complicatedArgs { + oneOfArgField(oneOfArg: { stringField: $string }) + } + } + `).toDeepEqual([ + { + message: + 'Variable "$string" is of type "String" but must be non-nullable to be used for OneOf Input Object "OneOfInput".', + locations: [ + { line: 2, column: 16 }, + { line: 4, column: 52 }, + ], + }, + ]); + }); + }); + + describe('Fragment arguments are validated', () => { + it('Boolean => Boolean', () => { + expectValid(` + query Query($booleanArg: Boolean) + { + complicatedArgs { + ...A(b: $booleanArg) + } + } + fragment A($b: Boolean) on ComplicatedArgs { + booleanArgField(booleanArg: $b) + } + `); + }); + + it('Boolean => Boolean with default value', () => { + expectValid(` + query Query($booleanArg: Boolean) + { + complicatedArgs { + ...A(b: $booleanArg) + } + } + fragment A($b: Boolean = true) on ComplicatedArgs { + booleanArgField(booleanArg: $b) + } + `); + }); + + it('Boolean => Boolean!', () => { + expectErrors(` + query Query($ab: Boolean) + { + complicatedArgs { + ...A(b: $ab) + } + } + fragment A($b: Boolean!) on ComplicatedArgs { + booleanArgField(booleanArg: $b) + } + `).toDeepEqual([ + { + message: + 'Variable "$ab" of type "Boolean" used in position expecting type "Boolean!".', + locations: [ + { line: 2, column: 21 }, + { line: 5, column: 21 }, + ], + }, + ]); + }); + + it('Int => Int! fails when variable provides null default value', () => { + expectErrors(` + query Query($intVar: Int = null) { + complicatedArgs { + ...A(i: $intVar) + } + } + fragment A($i: Int!) on ComplicatedArgs { + nonNullIntArgField(nonNullIntArg: $i) + } + `).toDeepEqual([ + { + message: + 'Variable "$intVar" of type "Int" used in position expecting type "Int!".', + locations: [ + { line: 2, column: 21 }, + { line: 4, column: 21 }, + ], + }, + ]); + }); + + it('Int fragment arg => Int! field arg fails even when shadowed by Int! variable', () => { + expectErrors(` + query Query($intVar: Int!) { + complicatedArgs { + ...A(i: $intVar) + } + } + fragment A($intVar: Int) on ComplicatedArgs { + nonNullIntArgField(nonNullIntArg: $intVar) + } + `).toDeepEqual([ + { + message: + 'Variable "$intVar" of type "Int" used in position expecting type "Int!".', + locations: [ + { line: 7, column: 20 }, + { line: 8, column: 45 }, + ], + }, + ]); + }); }); }); diff --git a/src/validation/__tests__/harness.ts b/src/validation/__tests__/harness.ts index b7710ff9d9..cb0c424a0e 100644 --- a/src/validation/__tests__/harness.ts +++ b/src/validation/__tests__/harness.ts @@ -128,17 +128,24 @@ export function expectValidationErrorsWithSchema( schema: GraphQLSchema, rule: ValidationRule, queryStr: string, + hideSuggestions = false, ): any { - const doc = parse(queryStr); - const errors = validate(schema, doc, [rule]); + const doc = parse(queryStr, { experimentalFragmentArguments: true }); + const errors = validate(schema, doc, [rule], { hideSuggestions }); return expectJSON(errors); } export function expectValidationErrors( rule: ValidationRule, queryStr: string, + hideSuggestions = false, ): any { - return expectValidationErrorsWithSchema(testSchema, rule, queryStr); + return expectValidationErrorsWithSchema( + testSchema, + rule, + queryStr, + hideSuggestions, + ); } export function expectSDLValidationErrors( diff --git a/src/validation/__tests__/validation-test.ts b/src/validation/__tests__/validation-test.ts index 19cb3b178a..13de153c39 100644 --- a/src/validation/__tests__/validation-test.ts +++ b/src/validation/__tests__/validation-test.ts @@ -9,7 +9,6 @@ import type { DirectiveNode } from '../../language/ast.js'; import { parse } from '../../language/parser.js'; import { buildSchema } from '../../utilities/buildASTSchema.js'; -import { TypeInfo } from '../../utilities/TypeInfo.js'; import { validate } from '../validate.js'; import type { ValidationContext } from '../ValidationContext.js'; @@ -53,35 +52,6 @@ describe('Validate: Supports full validation', () => { ]); }); - it('Deprecated: validates using a custom TypeInfo', () => { - // This TypeInfo will never return a valid field. - const typeInfo = new TypeInfo(testSchema, null, () => null); - - const doc = parse(` - query { - human { - pets { - ... on Cat { - meowsVolume - } - ... on Dog { - barkVolume - } - } - } - } - `); - - const errors = validate(testSchema, doc, undefined, undefined, typeInfo); - const errorMessages = errors.map((error) => error.message); - - expect(errorMessages).to.deep.equal([ - 'Cannot query field "human" on type "QueryRoot". Did you mean "human"?', - 'Cannot query field "meowsVolume" on type "Cat". Did you mean "meowsVolume"?', - 'Cannot query field "barkVolume" on type "Dog". Did you mean "barkVolume"?', - ]); - }); - it('validates using a custom rule', () => { const schema = buildSchema(` directive @custom(arg: String) on FIELD diff --git a/src/validation/index.ts b/src/validation/index.ts index b0cc754490..b1998b5300 100644 --- a/src/validation/index.ts +++ b/src/validation/index.ts @@ -4,7 +4,7 @@ export { ValidationContext } from './ValidationContext.js'; export type { ValidationRule } from './ValidationContext.js'; // All validation rules in the GraphQL Specification. -export { specifiedRules } from './specifiedRules.js'; +export { specifiedRules, recommendedRules } from './specifiedRules.js'; // Spec Section: "Defer And Stream Directive Labels Are Unique" export { DeferStreamDirectiveLabelRule } from './rules/DeferStreamDirectiveLabelRule.js'; @@ -33,6 +33,9 @@ export { KnownDirectivesRule } from './rules/KnownDirectivesRule.js'; // Spec Section: "Fragment spread target defined" export { KnownFragmentNamesRule } from './rules/KnownFragmentNamesRule.js'; +// Spec Section: "Operation Type Existence" +export { KnownOperationTypesRule } from './rules/KnownOperationTypesRule.js'; + // Spec Section: "Fragment Spread Type Existence" export { KnownTypeNamesRule } from './rules/KnownTypeNamesRule.js'; @@ -96,6 +99,8 @@ export { VariablesAreInputTypesRule } from './rules/VariablesAreInputTypesRule.j // Spec Section: "All Variable Usages Are Allowed" export { VariablesInAllowedPositionRule } from './rules/VariablesInAllowedPositionRule.js'; +export { MaxIntrospectionDepthRule } from './rules/MaxIntrospectionDepthRule.js'; + // SDL-specific validation rules export { LoneSchemaDefinitionRule } from './rules/LoneSchemaDefinitionRule.js'; export { UniqueOperationTypesRule } from './rules/UniqueOperationTypesRule.js'; diff --git a/src/validation/rules/DeferStreamDirectiveLabelRule.ts b/src/validation/rules/DeferStreamDirectiveLabelRule.ts index 45537af436..2b6d35a816 100644 --- a/src/validation/rules/DeferStreamDirectiveLabelRule.ts +++ b/src/validation/rules/DeferStreamDirectiveLabelRule.ts @@ -36,7 +36,7 @@ export function DeferStreamDirectiveLabelRule( if (labelValue.kind !== Kind.STRING) { context.reportError( new GraphQLError( - `Directive "${node.name.value}"'s label argument must be a static string.`, + `Argument "@${node.name.value}(label:)" must be a static string.`, { nodes: node }, ), ); @@ -47,7 +47,7 @@ export function DeferStreamDirectiveLabelRule( if (knownLabel != null) { context.reportError( new GraphQLError( - 'Defer/Stream directive label argument must be unique.', + 'Value for arguments "defer(label:)" and "stream(label:)" must be unique across all Defer/Stream directive usages.', { nodes: [knownLabel, node] }, ), ); diff --git a/src/validation/rules/DeferStreamDirectiveOnRootFieldRule.ts b/src/validation/rules/DeferStreamDirectiveOnRootFieldRule.ts index b0d2dda18f..ce7c20664c 100644 --- a/src/validation/rules/DeferStreamDirectiveOnRootFieldRule.ts +++ b/src/validation/rules/DeferStreamDirectiveOnRootFieldRule.ts @@ -26,7 +26,7 @@ export function DeferStreamDirectiveOnRootFieldRule( if (mutationType && parentType === mutationType) { context.reportError( new GraphQLError( - `Defer directive cannot be used on root mutation type "${parentType.name}".`, + `Defer directive cannot be used on root mutation type "${parentType}".`, { nodes: node }, ), ); @@ -34,7 +34,7 @@ export function DeferStreamDirectiveOnRootFieldRule( if (subscriptionType && parentType === subscriptionType) { context.reportError( new GraphQLError( - `Defer directive cannot be used on root subscription type "${parentType.name}".`, + `Defer directive cannot be used on root subscription type "${parentType}".`, { nodes: node }, ), ); @@ -44,7 +44,7 @@ export function DeferStreamDirectiveOnRootFieldRule( if (mutationType && parentType === mutationType) { context.reportError( new GraphQLError( - `Stream directive cannot be used on root mutation type "${parentType.name}".`, + `Stream directive cannot be used on root mutation type "${parentType}".`, { nodes: node }, ), ); @@ -52,7 +52,7 @@ export function DeferStreamDirectiveOnRootFieldRule( if (subscriptionType && parentType === subscriptionType) { context.reportError( new GraphQLError( - `Stream directive cannot be used on root subscription type "${parentType.name}".`, + `Stream directive cannot be used on root subscription type "${parentType}".`, { nodes: node }, ), ); diff --git a/src/validation/rules/DeferStreamDirectiveOnValidOperationsRule.ts b/src/validation/rules/DeferStreamDirectiveOnValidOperationsRule.ts index e8e6a292b6..44a15009b2 100644 --- a/src/validation/rules/DeferStreamDirectiveOnValidOperationsRule.ts +++ b/src/validation/rules/DeferStreamDirectiveOnValidOperationsRule.ts @@ -70,7 +70,7 @@ export function DeferStreamDirectiveOnValidOperationsRule( if (!ifArgumentCanBeFalse(node)) { context.reportError( new GraphQLError( - 'Stream directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', + 'Stream directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.', { nodes: node }, ), ); diff --git a/src/validation/rules/FieldsOnCorrectTypeRule.ts b/src/validation/rules/FieldsOnCorrectTypeRule.ts index 5d61e08b03..c8afc1a402 100644 --- a/src/validation/rules/FieldsOnCorrectTypeRule.ts +++ b/src/validation/rules/FieldsOnCorrectTypeRule.ts @@ -45,18 +45,24 @@ export function FieldsOnCorrectTypeRule( // First determine if there are any suggested types to condition on. let suggestion = didYouMean( 'to use an inline fragment on', - getSuggestedTypeNames(schema, type, fieldName), + context.hideSuggestions + ? [] + : getSuggestedTypeNames(schema, type, fieldName), ); // If there are no suggested types, then perhaps this was a typo? if (suggestion === '') { - suggestion = didYouMean(getSuggestedFieldNames(type, fieldName)); + suggestion = didYouMean( + context.hideSuggestions + ? [] + : getSuggestedFieldNames(type, fieldName), + ); } // Report an error, including helpful suggestions. context.reportError( new GraphQLError( - `Cannot query field "${fieldName}" on type "${type.name}".` + + `Cannot query field "${fieldName}" on type "${type}".` + suggestion, { nodes: node }, ), diff --git a/src/validation/rules/KnownArgumentNamesRule.ts b/src/validation/rules/KnownArgumentNamesRule.ts index 2f09348778..40b925aab1 100644 --- a/src/validation/rules/KnownArgumentNamesRule.ts +++ b/src/validation/rules/KnownArgumentNamesRule.ts @@ -26,18 +26,47 @@ export function KnownArgumentNamesRule(context: ValidationContext): ASTVisitor { return { // eslint-disable-next-line new-cap ...KnownArgumentNamesOnDirectivesRule(context), + FragmentArgument(argNode) { + const fragmentSignature = context.getFragmentSignature(); + if (fragmentSignature) { + const varDef = fragmentSignature.variableDefinitions.get( + argNode.name.value, + ); + if (!varDef) { + const argName = argNode.name.value; + const suggestions = context.hideSuggestions + ? [] + : suggestionList( + argName, + Array.from(fragmentSignature.variableDefinitions.values()).map( + (varSignature) => varSignature.variable.name.value, + ), + ); + context.reportError( + new GraphQLError( + `Unknown argument "${argName}" on fragment "${fragmentSignature.definition.name.value}".` + + didYouMean(suggestions), + { nodes: argNode }, + ), + ); + } + } + }, Argument(argNode) { const argDef = context.getArgument(); const fieldDef = context.getFieldDef(); - const parentType = context.getParentType(); - if (!argDef && fieldDef && parentType) { + if (!argDef && fieldDef) { const argName = argNode.name.value; - const knownArgsNames = fieldDef.args.map((arg) => arg.name); - const suggestions = suggestionList(argName, knownArgsNames); + const suggestions = context.hideSuggestions + ? [] + : suggestionList( + argName, + fieldDef.args.map((arg) => arg.name), + ); context.reportError( new GraphQLError( - `Unknown argument "${argName}" on field "${parentType.name}.${fieldDef.name}".` + + `Unknown argument "${argName}" on field "${fieldDef}".` + didYouMean(suggestions), { nodes: argNode }, ), @@ -69,8 +98,6 @@ export function KnownArgumentNamesOnDirectivesRule( const astDefinitions = context.getDocument().definitions; for (const def of astDefinitions) { if (def.kind === Kind.DIRECTIVE_DEFINITION) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argsNodes = def.arguments ?? []; directiveArgs.set( @@ -93,7 +120,7 @@ export function KnownArgumentNamesOnDirectivesRule( context.reportError( new GraphQLError( `Unknown argument "${argName}" on directive "@${directiveName}".` + - didYouMean(suggestions), + (context.hideSuggestions ? '' : didYouMean(suggestions)), { nodes: argNode }, ), ); diff --git a/src/validation/rules/KnownDirectivesRule.ts b/src/validation/rules/KnownDirectivesRule.ts index a2c7ec81eb..9a1e87d029 100644 --- a/src/validation/rules/KnownDirectivesRule.ts +++ b/src/validation/rules/KnownDirectivesRule.ts @@ -89,8 +89,13 @@ function getDirectiveLocationForASTPath( return DirectiveLocation.INLINE_FRAGMENT; case Kind.FRAGMENT_DEFINITION: return DirectiveLocation.FRAGMENT_DEFINITION; - case Kind.VARIABLE_DEFINITION: - return DirectiveLocation.VARIABLE_DEFINITION; + case Kind.VARIABLE_DEFINITION: { + const parentNode = ancestors[ancestors.length - 3]; + invariant('kind' in parentNode); + return parentNode.kind === Kind.OPERATION_DEFINITION + ? DirectiveLocation.VARIABLE_DEFINITION + : DirectiveLocation.FRAGMENT_VARIABLE_DEFINITION; + } case Kind.SCHEMA_DEFINITION: case Kind.SCHEMA_EXTENSION: return DirectiveLocation.SCHEMA; diff --git a/src/validation/rules/KnownOperationTypesRule.ts b/src/validation/rules/KnownOperationTypesRule.ts new file mode 100644 index 0000000000..4b17df05fb --- /dev/null +++ b/src/validation/rules/KnownOperationTypesRule.ts @@ -0,0 +1,32 @@ +import { GraphQLError } from '../../error/GraphQLError.js'; + +import type { ASTVisitor } from '../../language/visitor.js'; + +import type { ValidationContext } from '../ValidationContext.js'; + +/** + * Known Operation Types + * + * A GraphQL document is only valid if when it contains an operation, + * the root type for the operation exists within the schema. + * + * See https://spec.graphql.org/draft/#sec-Operation-Type-Existence + */ +export function KnownOperationTypesRule( + context: ValidationContext, +): ASTVisitor { + const schema = context.getSchema(); + return { + OperationDefinition(node) { + const operation = node.operation; + if (!schema.getRootType(operation)) { + context.reportError( + new GraphQLError( + `The ${operation} operation is not supported by the schema.`, + { nodes: node }, + ), + ); + } + }, + }; +} diff --git a/src/validation/rules/KnownTypeNamesRule.ts b/src/validation/rules/KnownTypeNamesRule.ts index 789e93eac1..d36a57da14 100644 --- a/src/validation/rules/KnownTypeNamesRule.ts +++ b/src/validation/rules/KnownTypeNamesRule.ts @@ -48,10 +48,12 @@ export function KnownTypeNamesRule( return; } - const suggestedTypes = suggestionList( - typeName, - isSDL ? [...standardTypeNames, ...typeNames] : [...typeNames], - ); + const suggestedTypes = context.hideSuggestions + ? [] + : suggestionList( + typeName, + isSDL ? [...standardTypeNames, ...typeNames] : [...typeNames], + ); context.reportError( new GraphQLError( `Unknown type "${typeName}".` + didYouMean(suggestedTypes), diff --git a/src/validation/rules/MaxIntrospectionDepthRule.ts b/src/validation/rules/MaxIntrospectionDepthRule.ts new file mode 100644 index 0000000000..5cde22f130 --- /dev/null +++ b/src/validation/rules/MaxIntrospectionDepthRule.ts @@ -0,0 +1,92 @@ +import { GraphQLError } from '../../error/GraphQLError.js'; + +import type { ASTNode } from '../../language/ast.js'; +import { Kind } from '../../language/kinds.js'; +import type { ASTVisitor } from '../../language/visitor.js'; + +import type { ValidationContext } from '../ValidationContext.js'; + +const MAX_LISTS_DEPTH = 3; + +export function MaxIntrospectionDepthRule( + context: ValidationContext, +): ASTVisitor { + /** + * Counts the depth of list fields in "__Type" recursively and + * returns `true` if the limit has been reached. + */ + function checkDepth( + node: ASTNode, + visitedFragments: { + [fragmentName: string]: true | undefined; + } = Object.create(null), + depth: number = 0, + ): boolean { + if (node.kind === Kind.FRAGMENT_SPREAD) { + const fragmentName = node.name.value; + if (visitedFragments[fragmentName] === true) { + // Fragment cycles are handled by `NoFragmentCyclesRule`. + return false; + } + const fragment = context.getFragment(fragmentName); + if (!fragment) { + // Missing fragments checks are handled by the `KnownFragmentNamesRule`. + return false; + } + + // Rather than following an immutable programming pattern which has + // significant memory and garbage collection overhead, we've opted to + // take a mutable approach for efficiency's sake. Importantly visiting a + // fragment twice is fine, so long as you don't do one visit inside the + // other. + try { + visitedFragments[fragmentName] = true; + return checkDepth(fragment, visitedFragments, depth); + } finally { + visitedFragments[fragmentName] = undefined; + } + } + + if ( + node.kind === Kind.FIELD && + // check all introspection lists + // TODO: instead of relying on field names, check whether the type is a list + (node.name.value === 'fields' || + node.name.value === 'interfaces' || + node.name.value === 'possibleTypes' || + node.name.value === 'inputFields') + ) { + // eslint-disable-next-line no-param-reassign + depth++; + if (depth >= MAX_LISTS_DEPTH) { + return true; + } + } + + // handles fields and inline fragments + if ('selectionSet' in node && node.selectionSet) { + for (const child of node.selectionSet.selections) { + if (checkDepth(child, visitedFragments, depth)) { + return true; + } + } + } + + return false; + } + + return { + Field(node) { + if (node.name.value === '__schema' || node.name.value === '__type') { + if (checkDepth(node)) { + context.reportError( + new GraphQLError('Maximum introspection depth exceeded', { + nodes: [node], + }), + ); + return false; + } + } + }, + }; +} diff --git a/src/validation/rules/NoUndefinedVariablesRule.ts b/src/validation/rules/NoUndefinedVariablesRule.ts index d1672ecd0b..ae010cab8e 100644 --- a/src/validation/rules/NoUndefinedVariablesRule.ts +++ b/src/validation/rules/NoUndefinedVariablesRule.ts @@ -22,7 +22,10 @@ export function NoUndefinedVariablesRule( ); const usages = context.getRecursiveVariableUsages(operation); - for (const { node } of usages) { + for (const { node, fragmentVariableDefinition } of usages) { + if (fragmentVariableDefinition) { + continue; + } const varName = node.name.value; if (!variableNameDefined.has(varName)) { context.reportError( diff --git a/src/validation/rules/NoUnusedVariablesRule.ts b/src/validation/rules/NoUnusedVariablesRule.ts index 7a0660cce0..6d0bd0871a 100644 --- a/src/validation/rules/NoUnusedVariablesRule.ts +++ b/src/validation/rules/NoUnusedVariablesRule.ts @@ -14,18 +14,38 @@ import type { ValidationContext } from '../ValidationContext.js'; */ export function NoUnusedVariablesRule(context: ValidationContext): ASTVisitor { return { - OperationDefinition(operation) { - const usages = context.getRecursiveVariableUsages(operation); - const variableNameUsed = new Set( + FragmentDefinition(fragment) { + const usages = context.getVariableUsages(fragment); + const argumentNameUsed = new Set( usages.map(({ node }) => node.name.value), ); + const variableDefinitions = fragment.variableDefinitions ?? []; + for (const varDef of variableDefinitions) { + const argName = varDef.variable.name.value; + if (!argumentNameUsed.has(argName)) { + context.reportError( + new GraphQLError( + `Variable "$${argName}" is never used in fragment "${fragment.name.value}".`, + { nodes: varDef }, + ), + ); + } + } + }, + OperationDefinition(operation) { + const usages = context.getRecursiveVariableUsages(operation); + const operationVariableNameUsed = new Set(); + for (const { node, fragmentVariableDefinition } of usages) { + const varName = node.name.value; + if (!fragmentVariableDefinition) { + operationVariableNameUsed.add(varName); + } + } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const variableDefinitions = operation.variableDefinitions ?? []; for (const variableDef of variableDefinitions) { const variableName = variableDef.variable.name.value; - if (!variableNameUsed.has(variableName)) { + if (!operationVariableNameUsed.has(variableName)) { context.reportError( new GraphQLError( operation.name diff --git a/src/validation/rules/OverlappingFieldsCanBeMergedRule.ts b/src/validation/rules/OverlappingFieldsCanBeMergedRule.ts index 851f7ea625..c74ecc7fe5 100644 --- a/src/validation/rules/OverlappingFieldsCanBeMergedRule.ts +++ b/src/validation/rules/OverlappingFieldsCanBeMergedRule.ts @@ -4,9 +4,12 @@ import type { Maybe } from '../../jsutils/Maybe.js'; import { GraphQLError } from '../../error/GraphQLError.js'; import type { + ArgumentNode, DirectiveNode, FieldNode, + FragmentArgumentNode, FragmentDefinitionNode, + FragmentSpreadNode, SelectionSetNode, ValueNode, } from '../../language/ast.js'; @@ -33,7 +36,7 @@ import { typeFromAST } from '../../utilities/typeFromAST.js'; import type { ValidationContext } from '../ValidationContext.js'; -/* eslint-disable max-params */ +/* eslint-disable @typescript-eslint/max-params */ // This file contains a lot of such errors but we plan to refactor it anyway // so just disable it for entire file. @@ -62,21 +65,26 @@ function reasonMessage(reason: ConflictReasonMessage): string { export function OverlappingFieldsCanBeMergedRule( context: ValidationContext, ): ASTVisitor { - // A memoization for when two fragments are compared "between" each other for - // conflicts. Two fragments may be compared many times, so memoizing this can - // dramatically improve the performance of this validator. - const comparedFragmentPairs = new PairSet(); - - // A cache for the "field map" and list of fragment names found in any given + // A memoization for when fields and a fragment or two fragments are compared + // "between" each other for conflicts. Comparisons made be made many times, + // so memoizing this can dramatically improve the performance of this validator. + const comparedFieldsAndFragmentPairs = new OrderedPairSet< + NodeAndDefCollection, + string + >(); + const comparedFragmentPairs = new PairSet(); + + // A cache for the "field map" and list of fragment spreads found in any given // selection set. Selection sets may be asked for this information multiple // times, so this improves the performance of this validator. - const cachedFieldsAndFragmentNames = new Map(); + const cachedFieldsAndFragmentSpreads = new Map(); return { SelectionSet(selectionSet) { const conflicts = findConflictsWithinSelectionSet( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, context.getParentType(), selectionSet, @@ -107,8 +115,16 @@ type NodeAndDef = [ ]; // Map of array of those. type NodeAndDefCollection = Map>; -type FragmentNames = ReadonlyArray; -type FieldsAndFragmentNames = readonly [NodeAndDefCollection, FragmentNames]; +interface FragmentSpread { + key: string; + node: FragmentSpreadNode; + varMap: Map | undefined; +} +type FragmentSpreads = ReadonlyArray; +type FieldsAndFragmentSpreads = readonly [ + NodeAndDefCollection, + FragmentSpreads, +]; /** * Algorithm: @@ -170,56 +186,64 @@ type FieldsAndFragmentNames = readonly [NodeAndDefCollection, FragmentNames]; // GraphQL Document. function findConflictsWithinSelectionSet( context: ValidationContext, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, parentType: Maybe, selectionSet: SelectionSetNode, ): Array { const conflicts: Array = []; - const [fieldMap, fragmentNames] = getFieldsAndFragmentNames( + const [fieldMap, fragmentSpreads] = getFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, parentType, selectionSet, + undefined, ); - // (A) Find find all conflicts "within" the fields of this selection set. + // (A) Find find all conflicts "within" the fields and f of this selection set. // Note: this is the *only place* `collectConflictsWithin` is called. collectConflictsWithin( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, fieldMap, ); - if (fragmentNames.length !== 0) { + if (fragmentSpreads.length !== 0) { // (B) Then collect conflicts between these fields and those represented by - // each spread fragment name found. - for (let i = 0; i < fragmentNames.length; i++) { + // each spread found. + for (let i = 0; i < fragmentSpreads.length; i++) { collectConflictsBetweenFieldsAndFragment( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, false, fieldMap, - fragmentNames[i], + fragmentSpreads[i], ); // (C) Then compare this fragment with all other fragments found in this // selection set to collect conflicts between fragments spread together. - // This compares each item in the list of fragment names to every other + // This compares each item in the list of fragment spreads to every other // item in that same list (except for itself). - for (let j = i + 1; j < fragmentNames.length; j++) { + for (let j = i + 1; j < fragmentSpreads.length; j++) { collectConflictsBetweenFragments( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, false, - fragmentNames[i], - fragmentNames[j], + fragmentSpreads[i], + fragmentSpreads[j], ); } } @@ -232,22 +256,44 @@ function findConflictsWithinSelectionSet( function collectConflictsBetweenFieldsAndFragment( context: ValidationContext, conflicts: Array, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, areMutuallyExclusive: boolean, fieldMap: NodeAndDefCollection, - fragmentName: string, + fragmentSpread: FragmentSpread, ): void { - const fragment = context.getFragment(fragmentName); + // Memoize so the fields and fragments are not compared for conflicts more + // than once. + if ( + comparedFieldsAndFragmentPairs.has( + fieldMap, + fragmentSpread.key, + areMutuallyExclusive, + ) + ) { + return; + } + comparedFieldsAndFragmentPairs.add( + fieldMap, + fragmentSpread.key, + areMutuallyExclusive, + ); + + const fragment = context.getFragment(fragmentSpread.node.name.value); if (!fragment) { return; } - const [fieldMap2, referencedFragmentNames] = - getReferencedFieldsAndFragmentNames( + const [fieldMap2, referencedFragmentSpreads] = + getReferencedFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, fragment, + fragmentSpread.varMap, ); // Do not compare a fragment's fieldMap to itself. @@ -260,40 +306,28 @@ function collectConflictsBetweenFieldsAndFragment( collectConflictsBetween( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, fieldMap, + undefined, fieldMap2, + fragmentSpread.varMap, ); // (E) Then collect any conflicts between the provided collection of fields // and any fragment names found in the given fragment. - for (const referencedFragmentName of referencedFragmentNames) { - // Memoize so two fragments are not compared for conflicts more than once. - if ( - comparedFragmentPairs.has( - referencedFragmentName, - fragmentName, - areMutuallyExclusive, - ) - ) { - continue; - } - comparedFragmentPairs.add( - referencedFragmentName, - fragmentName, - areMutuallyExclusive, - ); - + for (const referencedFragmentSpread of referencedFragmentSpreads) { collectConflictsBetweenFieldsAndFragment( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, fieldMap, - referencedFragmentName, + referencedFragmentSpread, ); } } @@ -303,46 +337,75 @@ function collectConflictsBetweenFieldsAndFragment( function collectConflictsBetweenFragments( context: ValidationContext, conflicts: Array, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, areMutuallyExclusive: boolean, - fragmentName1: string, - fragmentName2: string, + fragmentSpread1: FragmentSpread, + fragmentSpread2: FragmentSpread, ): void { // No need to compare a fragment to itself. - if (fragmentName1 === fragmentName2) { + if (fragmentSpread1.key === fragmentSpread2.key) { return; } + if (fragmentSpread1.node.name.value === fragmentSpread2.node.name.value) { + if ( + !sameArguments( + fragmentSpread1.node.arguments, + fragmentSpread1.varMap, + fragmentSpread2.node.arguments, + fragmentSpread2.varMap, + ) + ) { + context.reportError( + new GraphQLError( + `Spreads "${fragmentSpread1.node.name.value}" conflict because ${fragmentSpread1.key} and ${fragmentSpread2.key} have different fragment arguments.`, + { nodes: [fragmentSpread1.node, fragmentSpread2.node] }, + ), + ); + return; + } + } + // Memoize so two fragments are not compared for conflicts more than once. if ( comparedFragmentPairs.has( - fragmentName1, - fragmentName2, + fragmentSpread1.key, + fragmentSpread2.key, areMutuallyExclusive, ) ) { return; } - comparedFragmentPairs.add(fragmentName1, fragmentName2, areMutuallyExclusive); + comparedFragmentPairs.add( + fragmentSpread1.key, + fragmentSpread2.key, + areMutuallyExclusive, + ); - const fragment1 = context.getFragment(fragmentName1); - const fragment2 = context.getFragment(fragmentName2); + const fragment1 = context.getFragment(fragmentSpread1.node.name.value); + const fragment2 = context.getFragment(fragmentSpread2.node.name.value); if (!fragment1 || !fragment2) { return; } - const [fieldMap1, referencedFragmentNames1] = - getReferencedFieldsAndFragmentNames( + const [fieldMap1, referencedFragmentSpreads1] = + getReferencedFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, fragment1, + fragmentSpread1.varMap, ); - const [fieldMap2, referencedFragmentNames2] = - getReferencedFieldsAndFragmentNames( + const [fieldMap2, referencedFragmentSpreads2] = + getReferencedFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, fragment2, + fragmentSpread2.varMap, ); // (F) First, collect all conflicts between these two collections of fields @@ -350,38 +413,43 @@ function collectConflictsBetweenFragments( collectConflictsBetween( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, + fragmentSpread1.varMap, fieldMap2, + fragmentSpread2.varMap, ); // (G) Then collect conflicts between the first fragment and any nested // fragments spread in the second fragment. - for (const referencedFragmentName2 of referencedFragmentNames2) { + for (const referencedFragmentSpread2 of referencedFragmentSpreads2) { collectConflictsBetweenFragments( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, - fragmentName1, - referencedFragmentName2, + fragmentSpread1, + referencedFragmentSpread2, ); } // (G) Then collect conflicts between the second fragment and any nested // fragments spread in the first fragment. - for (const referencedFragmentName1 of referencedFragmentNames1) { + for (const referencedFragmentSpread1 of referencedFragmentSpreads1) { collectConflictsBetweenFragments( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, - referencedFragmentName1, - fragmentName2, + referencedFragmentSpread1, + fragmentSpread2, ); } } @@ -391,81 +459,95 @@ function collectConflictsBetweenFragments( // between the sub-fields of two overlapping fields. function findConflictsBetweenSubSelectionSets( context: ValidationContext, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, areMutuallyExclusive: boolean, parentType1: Maybe, selectionSet1: SelectionSetNode, + varMap1: Map | undefined, parentType2: Maybe, selectionSet2: SelectionSetNode, + varMap2: Map | undefined, ): Array { const conflicts: Array = []; - const [fieldMap1, fragmentNames1] = getFieldsAndFragmentNames( + const [fieldMap1, fragmentSpreads1] = getFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, parentType1, selectionSet1, + varMap1, ); - const [fieldMap2, fragmentNames2] = getFieldsAndFragmentNames( + const [fieldMap2, fragmentSpreads2] = getFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, parentType2, selectionSet2, + varMap2, ); // (H) First, collect all conflicts between these two collections of field. collectConflictsBetween( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, + varMap1, fieldMap2, + varMap2, ); // (I) Then collect conflicts between the first collection of fields and // those referenced by each fragment name associated with the second. - for (const fragmentName2 of fragmentNames2) { + for (const fragmentSpread2 of fragmentSpreads2) { collectConflictsBetweenFieldsAndFragment( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, - fragmentName2, + fragmentSpread2, ); } // (I) Then collect conflicts between the second collection of fields and // those referenced by each fragment name associated with the first. - for (const fragmentName1 of fragmentNames1) { + for (const fragmentSpread1 of fragmentSpreads1) { collectConflictsBetweenFieldsAndFragment( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, fieldMap2, - fragmentName1, + fragmentSpread1, ); } - // (J) Also collect conflicts between any fragment names by the first and - // fragment names by the second. This compares each item in the first set of - // names to each item in the second set of names. - for (const fragmentName1 of fragmentNames1) { - for (const fragmentName2 of fragmentNames2) { + // (J) Also collect conflicts between any fragment spreads by the first and + // fragment spreads by the second. This compares each item in the first set of + // spreads to each item in the second set of spreads. + for (const fragmentSpread1 of fragmentSpreads1) { + for (const fragmentSpread2 of fragmentSpreads2) { collectConflictsBetweenFragments( context, conflicts, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, - fragmentName1, - fragmentName2, + fragmentSpread1, + fragmentSpread2, ); } } @@ -476,8 +558,12 @@ function findConflictsBetweenSubSelectionSets( function collectConflictsWithin( context: ValidationContext, conflicts: Array, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, fieldMap: NodeAndDefCollection, ): void { // A field map is a keyed collection, where each key represents a response @@ -493,12 +579,15 @@ function collectConflictsWithin( for (let j = i + 1; j < fields.length; j++) { const conflict = findConflict( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, false, // within one collection is never mutually exclusive responseName, fields[i], + undefined, fields[j], + undefined, ); if (conflict) { conflicts.push(conflict); @@ -517,11 +606,17 @@ function collectConflictsWithin( function collectConflictsBetween( context: ValidationContext, conflicts: Array, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, parentFieldsAreMutuallyExclusive: boolean, fieldMap1: NodeAndDefCollection, + varMap1: Map | undefined, fieldMap2: NodeAndDefCollection, + varMap2: Map | undefined, ): void { // A field map is a keyed collection, where each key represents a response // name and the value at that key is a list of all fields which provide that @@ -535,12 +630,15 @@ function collectConflictsBetween( for (const field2 of fields2) { const conflict = findConflict( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, responseName, field1, + varMap1, field2, + varMap2, ); if (conflict) { conflicts.push(conflict); @@ -555,12 +653,18 @@ function collectConflictsBetween( // comparing their sub-fields. function findConflict( context: ValidationContext, - cachedFieldsAndFragmentNames: Map, - comparedFragmentPairs: PairSet, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, + comparedFieldsAndFragmentPairs: OrderedPairSet, + comparedFragmentPairs: PairSet, parentFieldsAreMutuallyExclusive: boolean, responseName: string, field1: NodeAndDef, + varMap1: Map | undefined, field2: NodeAndDef, + varMap2: Map | undefined, ): Maybe { const [parentType1, node1, def1] = field1; const [parentType2, node2, def2] = field2; @@ -592,7 +696,7 @@ function findConflict( } // Two field calls must have the same arguments. - if (!sameArguments(node1, node2)) { + if (!sameArguments(node1.arguments, varMap1, node2.arguments, varMap2)) { return [ [responseName, 'they have differing arguments'], [node1], @@ -601,10 +705,9 @@ function findConflict( } } - // FIXME https://github.com/graphql/graphql-js/issues/2203 - const directives1 = /* c8 ignore next */ node1.directives ?? []; - const directives2 = /* c8 ignore next */ node2.directives ?? []; - if (!sameStreams(directives1, directives2)) { + const directives1 = node1.directives ?? []; + const directives2 = node2.directives ?? []; + if (!sameStreams(directives1, varMap1, directives2, varMap2)) { return [ [responseName, 'they have differing stream directives'], [node1], @@ -629,7 +732,7 @@ function findConflict( ]; } - // Collect and compare sub-fields. Use the same "visited fragment names" list + // Collect and compare sub-fields. Use the same "visited fragment spreads" list // for both collections so fields in a fragment reference are never // compared to themselves. const selectionSet1 = node1.selectionSet; @@ -637,25 +740,27 @@ function findConflict( if (selectionSet1 && selectionSet2) { const conflicts = findConflictsBetweenSubSelectionSets( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, + comparedFieldsAndFragmentPairs, comparedFragmentPairs, areMutuallyExclusive, getNamedType(type1), selectionSet1, + varMap1, getNamedType(type2), selectionSet2, + varMap2, ); return subfieldConflicts(conflicts, responseName, node1, node2); } } -function sameArguments( - node1: FieldNode | DirectiveNode, - node2: FieldNode | DirectiveNode, +function sameArguments( + args1: ReadonlyArray | undefined, + varMap1: Map | undefined, + args2: ReadonlyArray | undefined, + varMap2: Map | undefined, ): boolean { - const args1 = node1.arguments; - const args2 = node2.arguments; - if (args1 === undefined || args1.length === 0) { return args2 === undefined || args2.length === 0; } @@ -667,9 +772,17 @@ function sameArguments( return false; } - const values2 = new Map(args2.map(({ name, value }) => [name.value, value])); + const values2 = new Map( + args2.map(({ name, value }) => [ + name.value, + varMap2 === undefined ? value : replaceFragmentVariables(value, varMap2), + ]), + ); return args1.every((arg1) => { - const value1 = arg1.value; + let value1 = arg1.value; + if (varMap1) { + value1 = replaceFragmentVariables(value1, varMap1); + } const value2 = values2.get(arg1.name.value); if (value2 === undefined) { return false; @@ -679,6 +792,34 @@ function sameArguments( }); } +function replaceFragmentVariables( + valueNode: ValueNode, + varMap: ReadonlyMap, +): ValueNode { + switch (valueNode.kind) { + case Kind.VARIABLE: + return varMap.get(valueNode.name.value) ?? valueNode; + case Kind.LIST: + return { + ...valueNode, + values: valueNode.values.map((node) => + replaceFragmentVariables(node, varMap), + ), + }; + case Kind.OBJECT: + return { + ...valueNode, + fields: valueNode.fields.map((field) => ({ + ...field, + value: replaceFragmentVariables(field.value, varMap), + })), + }; + default: { + return valueNode; + } + } +} + function stringifyValue(value: ValueNode): string | null { return print(sortValueNode(value)); } @@ -691,7 +832,9 @@ function getStreamDirective( function sameStreams( directives1: ReadonlyArray, + varMap1: Map | undefined, directives2: ReadonlyArray, + varMap2: Map | undefined, ): boolean { const stream1 = getStreamDirective(directives1); const stream2 = getStreamDirective(directives2); @@ -700,7 +843,12 @@ function sameStreams( return true; } else if (stream1 && stream2) { // check if both fields have equivalent streams - return sameArguments(stream1, stream2); + return sameArguments( + stream1.arguments, + varMap1, + stream2.arguments, + varMap2, + ); } // fields have a mix of stream and no stream return false; @@ -736,60 +884,74 @@ function doTypesConflict( } // Given a selection set, return the collection of fields (a mapping of response -// name to field nodes and definitions) as well as a list of fragment names +// name to field nodes and definitions) as well as a list of fragment spreads // referenced via fragment spreads. -function getFieldsAndFragmentNames( +function getFieldsAndFragmentSpreads( context: ValidationContext, - cachedFieldsAndFragmentNames: Map, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, parentType: Maybe, selectionSet: SelectionSetNode, -): FieldsAndFragmentNames { - const cached = cachedFieldsAndFragmentNames.get(selectionSet); + varMap: Map | undefined, +): FieldsAndFragmentSpreads { + const cached = cachedFieldsAndFragmentSpreads.get(selectionSet); if (cached) { return cached; } const nodeAndDefs: NodeAndDefCollection = new Map(); - const fragmentNames = new Set(); - _collectFieldsAndFragmentNames( + const fragmentSpreads = new Map(); + _collectFieldsAndFragmentSpreads( context, parentType, selectionSet, nodeAndDefs, - fragmentNames, + fragmentSpreads, + varMap, ); - const result = [nodeAndDefs, [...fragmentNames]] as const; - cachedFieldsAndFragmentNames.set(selectionSet, result); + const result: FieldsAndFragmentSpreads = [ + nodeAndDefs, + Array.from(fragmentSpreads.values()), + ]; + cachedFieldsAndFragmentSpreads.set(selectionSet, result); return result; } // Given a reference to a fragment, return the represented collection of fields -// as well as a list of nested fragment names referenced via fragment spreads. -function getReferencedFieldsAndFragmentNames( +// as well as a list of nested fragment spreads referenced via fragment spreads. +function getReferencedFieldsAndFragmentSpreads( context: ValidationContext, - cachedFieldsAndFragmentNames: Map, + cachedFieldsAndFragmentSpreads: Map< + SelectionSetNode, + FieldsAndFragmentSpreads + >, fragment: FragmentDefinitionNode, + varMap: Map | undefined, ) { // Short-circuit building a type from the node if possible. - const cached = cachedFieldsAndFragmentNames.get(fragment.selectionSet); + const cached = cachedFieldsAndFragmentSpreads.get(fragment.selectionSet); if (cached) { return cached; } const fragmentType = typeFromAST(context.getSchema(), fragment.typeCondition); - return getFieldsAndFragmentNames( + return getFieldsAndFragmentSpreads( context, - cachedFieldsAndFragmentNames, + cachedFieldsAndFragmentSpreads, fragmentType, fragment.selectionSet, + varMap, ); } -function _collectFieldsAndFragmentNames( +function _collectFieldsAndFragmentSpreads( context: ValidationContext, parentType: Maybe, selectionSet: SelectionSetNode, nodeAndDefs: NodeAndDefCollection, - fragmentNames: Set, + fragmentSpreads: Map, + varMap: Map | undefined, ): void { for (const selection of selectionSet.selections) { switch (selection.kind) { @@ -811,20 +973,23 @@ function _collectFieldsAndFragmentNames( nodeAndDefsList.push([parentType, selection, fieldDef]); break; } - case Kind.FRAGMENT_SPREAD: - fragmentNames.add(selection.name.value); + case Kind.FRAGMENT_SPREAD: { + const fragmentSpread = getFragmentSpread(context, selection, varMap); + fragmentSpreads.set(fragmentSpread.key, fragmentSpread); break; + } case Kind.INLINE_FRAGMENT: { const typeCondition = selection.typeCondition; const inlineFragmentType = typeCondition ? typeFromAST(context.getSchema(), typeCondition) : parentType; - _collectFieldsAndFragmentNames( + _collectFieldsAndFragmentSpreads( context, inlineFragmentType, selection.selectionSet, nodeAndDefs, - fragmentNames, + fragmentSpreads, + varMap, ); break; } @@ -832,6 +997,48 @@ function _collectFieldsAndFragmentNames( } } +function getFragmentSpread( + context: ValidationContext, + fragmentSpreadNode: FragmentSpreadNode, + varMap: Map | undefined, +): FragmentSpread { + let key = ''; + const newVarMap = new Map(); + const fragmentSignature = context.getFragmentSignatureByName()( + fragmentSpreadNode.name.value, + ); + const argMap = new Map(); + if (fragmentSpreadNode.arguments) { + for (const arg of fragmentSpreadNode.arguments) { + argMap.set(arg.name.value, arg.value); + } + } + if (fragmentSignature?.variableDefinitions) { + key += fragmentSpreadNode.name.value + '('; + for (const [varName, variable] of fragmentSignature.variableDefinitions) { + const value = argMap.get(varName); + if (value) { + key += varName + ': ' + print(sortValueNode(value)); + } + const arg = argMap.get(varName); + if (arg !== undefined) { + newVarMap.set( + varName, + varMap !== undefined ? replaceFragmentVariables(arg, varMap) : arg, + ); + } else if (variable.defaultValue) { + newVarMap.set(varName, variable.defaultValue); + } + } + key += ')'; + } + return { + key, + node: fragmentSpreadNode, + varMap: newVarMap.size > 0 ? newVarMap : undefined, + }; +} + // Given a series of Conflicts which occurred between two sub-fields, generate // a single Conflict. function subfieldConflicts( @@ -850,37 +1057,60 @@ function subfieldConflicts( } /** - * A way to keep track of pairs of things when the ordering of the pair does not matter. + * A way to keep track of pairs of things where the ordering of the pair + * matters. + * + * Provides a third argument for has/set to allow flagging the pair as + * weakly or strongly present within the collection. */ -class PairSet { - _data: Map>; +class OrderedPairSet { + _data: Map>; constructor() { this._data = new Map(); } - has(a: string, b: string, areMutuallyExclusive: boolean): boolean { - const [key1, key2] = a < b ? [a, b] : [b, a]; - - const result = this._data.get(key1)?.get(key2); + has(a: T, b: U, weaklyPresent: boolean): boolean { + const result = this._data.get(a)?.get(b); if (result === undefined) { return false; } - // areMutuallyExclusive being false is a superset of being true, hence if - // we want to know if this PairSet "has" these two with no exclusivity, - // we have to ensure it was added as such. - return areMutuallyExclusive ? true : areMutuallyExclusive === result; + return weaklyPresent ? true : weaklyPresent === result; } - add(a: string, b: string, areMutuallyExclusive: boolean): void { - const [key1, key2] = a < b ? [a, b] : [b, a]; - - const map = this._data.get(key1); + add(a: T, b: U, weaklyPresent: boolean): void { + const map = this._data.get(a); if (map === undefined) { - this._data.set(key1, new Map([[key2, areMutuallyExclusive]])); + this._data.set(a, new Map([[b, weaklyPresent]])); + } else { + map.set(b, weaklyPresent); + } + } +} + +/** + * A way to keep track of pairs of similar things when the ordering of the pair + * does not matter. + */ +class PairSet { + _orderedPairSet: OrderedPairSet; + + constructor() { + this._orderedPairSet = new OrderedPairSet(); + } + + has(a: T, b: T, weaklyPresent: boolean): boolean { + return a < b + ? this._orderedPairSet.has(a, b, weaklyPresent) + : this._orderedPairSet.has(b, a, weaklyPresent); + } + + add(a: T, b: T, weaklyPresent: boolean): void { + if (a < b) { + this._orderedPairSet.add(a, b, weaklyPresent); } else { - map.set(key2, areMutuallyExclusive); + this._orderedPairSet.add(b, a, weaklyPresent); } } } diff --git a/src/validation/rules/PossibleTypeExtensionsRule.ts b/src/validation/rules/PossibleTypeExtensionsRule.ts index d9ccb73cfa..57f2b5541b 100644 --- a/src/validation/rules/PossibleTypeExtensionsRule.ts +++ b/src/validation/rules/PossibleTypeExtensionsRule.ts @@ -78,11 +78,10 @@ export function PossibleTypeExtensionsRule( ...Object.keys(schema?.getTypeMap() ?? {}), ]; - const suggestedTypes = suggestionList(typeName, allTypeNames); context.reportError( new GraphQLError( `Cannot extend type "${typeName}" because it is not defined.` + - didYouMean(suggestedTypes), + didYouMean(suggestionList(typeName, allTypeNames)), { nodes: node.name }, ), ); diff --git a/src/validation/rules/ProvidedRequiredArgumentsRule.ts b/src/validation/rules/ProvidedRequiredArgumentsRule.ts index 72d104b852..32ecafdabb 100644 --- a/src/validation/rules/ProvidedRequiredArgumentsRule.ts +++ b/src/validation/rules/ProvidedRequiredArgumentsRule.ts @@ -2,7 +2,10 @@ import { inspect } from '../../jsutils/inspect.js'; import { GraphQLError } from '../../error/GraphQLError.js'; -import type { InputValueDefinitionNode } from '../../language/ast.js'; +import type { + InputValueDefinitionNode, + VariableDefinitionNode, +} from '../../language/ast.js'; import { Kind } from '../../language/kinds.js'; import { print } from '../../language/printer.js'; import type { ASTVisitor } from '../../language/visitor.js'; @@ -11,6 +14,8 @@ import type { GraphQLArgument } from '../../type/definition.js'; import { isRequiredArgument, isType } from '../../type/definition.js'; import { specifiedDirectives } from '../../type/directives.js'; +import { typeFromAST } from '../../utilities/typeFromAST.js'; + import type { SDLValidationContext, ValidationContext, @@ -37,16 +42,13 @@ export function ProvidedRequiredArgumentsRule( } const providedArgs = new Set( - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ fieldNode.arguments?.map((arg) => arg.name.value), ); for (const argDef of fieldDef.args) { if (!providedArgs.has(argDef.name) && isRequiredArgument(argDef)) { - const argTypeStr = inspect(argDef.type); context.reportError( new GraphQLError( - `Field "${fieldDef.name}" argument "${argDef.name}" of type "${argTypeStr}" is required, but it was not provided.`, + `Argument "${argDef}" of type "${argDef.type}" is required, but it was not provided.`, { nodes: fieldNode }, ), ); @@ -54,6 +56,40 @@ export function ProvidedRequiredArgumentsRule( } }, }, + FragmentSpread: { + // Validate on leave to allow for deeper errors to appear first. + leave(spreadNode) { + const fragmentSignature = context.getFragmentSignature(); + if (!fragmentSignature) { + return false; + } + + const providedArgs = new Set( + spreadNode.arguments?.map((arg) => arg.name.value), + ); + for (const [ + varName, + variableDefinition, + ] of fragmentSignature.variableDefinitions) { + if ( + !providedArgs.has(varName) && + isRequiredArgumentNode(variableDefinition) + ) { + const type = typeFromAST( + context.getSchema(), + variableDefinition.type, + ); + const argTypeStr = inspect(type); + context.reportError( + new GraphQLError( + `Fragment "${spreadNode.name.value}" argument "${varName}" of type "${argTypeStr}" is required, but it was not provided.`, + { nodes: spreadNode }, + ), + ); + } + } + }, + }, }; } @@ -82,8 +118,6 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( const astDefinitions = context.getDocument().definitions; for (const def of astDefinitions) { if (def.kind === Kind.DIRECTIVE_DEFINITION) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argNodes = def.arguments ?? []; requiredArgsMap.set( @@ -104,8 +138,6 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( const directiveName = directiveNode.name.value; const requiredArgs = requiredArgsMap.get(directiveName); if (requiredArgs != null) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argNodes = directiveNode.arguments ?? []; const argNodeMap = new Set(argNodes.map((arg) => arg.name.value)); for (const [argName, argDef] of requiredArgs.entries()) { @@ -115,7 +147,7 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( : print(argDef.type); context.reportError( new GraphQLError( - `Directive "@${directiveName}" argument "${argName}" of type "${argType}" is required, but it was not provided.`, + `Argument "@${directiveName}(${argName}:)" of type "${argType}" is required, but it was not provided.`, { nodes: directiveNode }, ), ); @@ -127,6 +159,8 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( }; } -function isRequiredArgumentNode(arg: InputValueDefinitionNode): boolean { +function isRequiredArgumentNode( + arg: InputValueDefinitionNode | VariableDefinitionNode, +): boolean { return arg.type.kind === Kind.NON_NULL_TYPE && arg.defaultValue == null; } diff --git a/src/validation/rules/ScalarLeafsRule.ts b/src/validation/rules/ScalarLeafsRule.ts index 7e9014932c..f1c365b33e 100644 --- a/src/validation/rules/ScalarLeafsRule.ts +++ b/src/validation/rules/ScalarLeafsRule.ts @@ -41,6 +41,15 @@ export function ScalarLeafsRule(context: ValidationContext): ASTVisitor { { nodes: node }, ), ); + } else if (selectionSet.selections.length === 0) { + const fieldName = node.name.value; + const typeStr = inspect(type); + context.reportError( + new GraphQLError( + `Field "${fieldName}" of type "${typeStr}" must have at least one field selected.`, + { nodes: node }, + ), + ); } } }, diff --git a/src/validation/rules/SingleFieldSubscriptionsRule.ts b/src/validation/rules/SingleFieldSubscriptionsRule.ts index 15aee1ece4..02948fc895 100644 --- a/src/validation/rules/SingleFieldSubscriptionsRule.ts +++ b/src/validation/rules/SingleFieldSubscriptionsRule.ts @@ -2,22 +2,20 @@ import type { ObjMap } from '../../jsutils/ObjMap.js'; import { GraphQLError } from '../../error/GraphQLError.js'; -import type { - FieldNode, - FragmentDefinitionNode, - OperationDefinitionNode, -} from '../../language/ast.js'; +import type { FieldNode, OperationDefinitionNode } from '../../language/ast.js'; import { Kind } from '../../language/kinds.js'; import type { ASTVisitor } from '../../language/visitor.js'; -import type { FieldDetails } from '../../execution/collectFields.js'; +import type { + FieldDetailsList, + FragmentDetails, +} from '../../execution/collectFields.js'; import { collectFields } from '../../execution/collectFields.js'; +import type { VariableValues } from '../../execution/values.js'; import type { ValidationContext } from '../ValidationContext.js'; -function toNodes( - fieldDetailsList: ReadonlyArray, -): ReadonlyArray { +function toNodes(fieldDetailsList: FieldDetailsList): ReadonlyArray { return fieldDetailsList.map((fieldDetails) => fieldDetails.node); } @@ -39,28 +37,27 @@ export function SingleFieldSubscriptionsRule( const subscriptionType = schema.getSubscriptionType(); if (subscriptionType) { const operationName = node.name ? node.name.value : null; - const variableValues: { - [variable: string]: any; - } = Object.create(null); + const variableValues: VariableValues = Object.create(null); const document = context.getDocument(); - const fragments: ObjMap = Object.create(null); + const fragments: ObjMap = Object.create(null); for (const definition of document.definitions) { if (definition.kind === Kind.FRAGMENT_DEFINITION) { - fragments[definition.name.value] = definition; + fragments[definition.name.value] = { definition }; } } - const fields = collectFields( + const { groupedFieldSet } = collectFields( schema, fragments, variableValues, subscriptionType, - node, + node.selectionSet, + context.hideSuggestions, ); - if (fields.size > 1) { - const fieldGroups = [...fields.values()]; - const extraFieldGroups = fieldGroups.slice(1); - const extraFieldSelections = extraFieldGroups.flatMap( - (fieldGroup) => toNodes(fieldGroup), + if (groupedFieldSet.size > 1) { + const fieldDetailsLists = [...groupedFieldSet.values()]; + const extraFieldDetailsLists = fieldDetailsLists.slice(1); + const extraFieldSelections = extraFieldDetailsLists.flatMap( + (fieldDetailsList) => toNodes(fieldDetailsList), ); context.reportError( new GraphQLError( @@ -71,15 +68,15 @@ export function SingleFieldSubscriptionsRule( ), ); } - for (const fieldGroup of fields.values()) { - const fieldName = toNodes(fieldGroup)[0].name.value; + for (const fieldDetailsList of groupedFieldSet.values()) { + const fieldName = toNodes(fieldDetailsList)[0].name.value; if (fieldName.startsWith('__')) { context.reportError( new GraphQLError( operationName != null ? `Subscription "${operationName}" must not select an introspection top level field.` : 'Anonymous Subscription must not select an introspection top level field.', - { nodes: toNodes(fieldGroup) }, + { nodes: toNodes(fieldDetailsList) }, ), ); } diff --git a/src/validation/rules/StreamDirectiveOnListFieldRule.ts b/src/validation/rules/StreamDirectiveOnListFieldRule.ts index 34346e249a..223a5e66d3 100644 --- a/src/validation/rules/StreamDirectiveOnListFieldRule.ts +++ b/src/validation/rules/StreamDirectiveOnListFieldRule.ts @@ -31,7 +31,7 @@ export function StreamDirectiveOnListFieldRule( ) { context.reportError( new GraphQLError( - `Stream directive cannot be used on non-list field "${fieldDef.name}" on type "${parentType.name}".`, + `Directive "@stream" cannot be used on non-list field "${parentType}.${fieldDef.name}".`, { nodes: node }, ), ); diff --git a/src/validation/rules/UniqueArgumentDefinitionNamesRule.ts b/src/validation/rules/UniqueArgumentDefinitionNamesRule.ts index 9904477bc6..ada4fe94b2 100644 --- a/src/validation/rules/UniqueArgumentDefinitionNamesRule.ts +++ b/src/validation/rules/UniqueArgumentDefinitionNamesRule.ts @@ -22,8 +22,6 @@ export function UniqueArgumentDefinitionNamesRule( ): ASTVisitor { return { DirectiveDefinition(directiveNode) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argumentNodes = directiveNode.arguments ?? []; return checkArgUniqueness(`@${directiveNode.name.value}`, argumentNodes); @@ -40,15 +38,11 @@ export function UniqueArgumentDefinitionNamesRule( }) { const typeName = typeNode.name.value; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const fieldNodes = typeNode.fields ?? []; for (const fieldDef of fieldNodes) { const fieldName = fieldDef.name.value; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argumentNodes = fieldDef.arguments ?? []; checkArgUniqueness(`${typeName}.${fieldName}`, argumentNodes); diff --git a/src/validation/rules/UniqueArgumentNamesRule.ts b/src/validation/rules/UniqueArgumentNamesRule.ts index 2baba71c21..c4305e6e4b 100644 --- a/src/validation/rules/UniqueArgumentNamesRule.ts +++ b/src/validation/rules/UniqueArgumentNamesRule.ts @@ -26,8 +26,6 @@ export function UniqueArgumentNamesRule( function checkArgUniqueness(parentNode: { arguments?: ReadonlyArray | undefined; }) { - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const argumentNodes = parentNode.arguments ?? []; const seenArgs = groupBy(argumentNodes, (arg) => arg.name.value); diff --git a/src/validation/rules/UniqueEnumValueNamesRule.ts b/src/validation/rules/UniqueEnumValueNamesRule.ts index 8342880f82..74d8b6518a 100644 --- a/src/validation/rules/UniqueEnumValueNamesRule.ts +++ b/src/validation/rules/UniqueEnumValueNamesRule.ts @@ -39,8 +39,6 @@ export function UniqueEnumValueNamesRule( knownValueNames.set(typeName, valueNames); } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const valueNodes = node.values ?? []; for (const valueDef of valueNodes) { diff --git a/src/validation/rules/UniqueFieldDefinitionNamesRule.ts b/src/validation/rules/UniqueFieldDefinitionNamesRule.ts index e776bb4d06..cf8e618605 100644 --- a/src/validation/rules/UniqueFieldDefinitionNamesRule.ts +++ b/src/validation/rules/UniqueFieldDefinitionNamesRule.ts @@ -51,8 +51,6 @@ export function UniqueFieldDefinitionNamesRule( knownFieldNames.set(typeName, fieldNames); } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const fieldNodes = node.fields ?? []; for (const fieldDef of fieldNodes) { diff --git a/src/validation/rules/UniqueOperationTypesRule.ts b/src/validation/rules/UniqueOperationTypesRule.ts index 51e4cfe6b1..cf4c191ee9 100644 --- a/src/validation/rules/UniqueOperationTypesRule.ts +++ b/src/validation/rules/UniqueOperationTypesRule.ts @@ -35,8 +35,6 @@ export function UniqueOperationTypesRule( function checkOperationTypes( node: SchemaDefinitionNode | SchemaExtensionNode, ) { - // See: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const operationTypesNodes = node.operationTypes ?? []; for (const operationType of operationTypesNodes) { diff --git a/src/validation/rules/UniqueVariableNamesRule.ts b/src/validation/rules/UniqueVariableNamesRule.ts index 8c067263fd..509fefbeff 100644 --- a/src/validation/rules/UniqueVariableNamesRule.ts +++ b/src/validation/rules/UniqueVariableNamesRule.ts @@ -16,8 +16,6 @@ export function UniqueVariableNamesRule( ): ASTVisitor { return { OperationDefinition(operationNode) { - // See: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ const variableDefinitions = operationNode.variableDefinitions ?? []; const seenVariableDefinitions = groupBy( diff --git a/src/validation/rules/ValuesOfCorrectTypeRule.ts b/src/validation/rules/ValuesOfCorrectTypeRule.ts index 3b9a1ee645..a437edc821 100644 --- a/src/validation/rules/ValuesOfCorrectTypeRule.ts +++ b/src/validation/rules/ValuesOfCorrectTypeRule.ts @@ -1,29 +1,11 @@ -import { didYouMean } from '../../jsutils/didYouMean.js'; -import { inspect } from '../../jsutils/inspect.js'; -import { suggestionList } from '../../jsutils/suggestionList.js'; +import type { Maybe } from '../../jsutils/Maybe.js'; -import { GraphQLError } from '../../error/GraphQLError.js'; - -import type { - ObjectFieldNode, - ObjectValueNode, - ValueNode, - VariableDefinitionNode, -} from '../../language/ast.js'; -import { Kind } from '../../language/kinds.js'; -import { print } from '../../language/printer.js'; +import type { ValueNode } from '../../language/ast.js'; import type { ASTVisitor } from '../../language/visitor.js'; -import type { GraphQLInputObjectType } from '../../type/definition.js'; -import { - getNamedType, - getNullableType, - isInputObjectType, - isLeafType, - isListType, - isNonNullType, - isRequiredInputField, -} from '../../type/definition.js'; +import type { GraphQLInputType } from '../../type/index.js'; + +import { validateInputLiteral } from '../../utilities/validateInputValue.js'; import type { ValidationContext } from '../ValidationContext.js'; @@ -38,92 +20,24 @@ import type { ValidationContext } from '../ValidationContext.js'; export function ValuesOfCorrectTypeRule( context: ValidationContext, ): ASTVisitor { - let variableDefinitions: { [key: string]: VariableDefinitionNode } = {}; - return { - OperationDefinition: { - enter() { - variableDefinitions = {}; - }, - }, - VariableDefinition(definition) { - variableDefinitions[definition.variable.name.value] = definition; - }, - ListValue(node) { + NullValue: (node) => + isValidValueNode(context, node, context.getInputType()), + ListValue: (node) => // Note: TypeInfo will traverse into a list's item type, so look to the // parent input type to check if it is a list. - const type = getNullableType(context.getParentInputType()); - if (!isListType(type)) { - isValidValueNode(context, node); - return false; // Don't traverse further. - } - }, - ObjectValue(node) { - const type = getNamedType(context.getInputType()); - if (!isInputObjectType(type)) { - isValidValueNode(context, node); - return false; // Don't traverse further. - } - // Ensure every required field exists. - const fieldNodeMap = new Map( - node.fields.map((field) => [field.name.value, field]), - ); - for (const fieldDef of Object.values(type.getFields())) { - const fieldNode = fieldNodeMap.get(fieldDef.name); - if (!fieldNode && isRequiredInputField(fieldDef)) { - const typeStr = inspect(fieldDef.type); - context.reportError( - new GraphQLError( - `Field "${type.name}.${fieldDef.name}" of required type "${typeStr}" was not provided.`, - { nodes: node }, - ), - ); - } - } - - if (type.isOneOf) { - validateOneOfInputObject( - context, - node, - type, - fieldNodeMap, - variableDefinitions, - ); - } - }, - ObjectField(node) { - const parentType = getNamedType(context.getParentInputType()); - const fieldType = context.getInputType(); - if (!fieldType && isInputObjectType(parentType)) { - const suggestions = suggestionList( - node.name.value, - Object.keys(parentType.getFields()), - ); - context.reportError( - new GraphQLError( - `Field "${node.name.value}" is not defined by type "${parentType.name}".` + - didYouMean(suggestions), - { nodes: node }, - ), - ); - } - }, - NullValue(node) { - const type = context.getInputType(); - if (isNonNullType(type)) { - context.reportError( - new GraphQLError( - `Expected value of type "${inspect(type)}", found ${print(node)}.`, - { nodes: node }, - ), - ); - } - }, - EnumValue: (node) => isValidValueNode(context, node), - IntValue: (node) => isValidValueNode(context, node), - FloatValue: (node) => isValidValueNode(context, node), - StringValue: (node) => isValidValueNode(context, node), - BooleanValue: (node) => isValidValueNode(context, node), + isValidValueNode(context, node, context.getParentInputType()), + ObjectValue: (node) => + isValidValueNode(context, node, context.getInputType()), + EnumValue: (node) => + isValidValueNode(context, node, context.getInputType()), + IntValue: (node) => isValidValueNode(context, node, context.getInputType()), + FloatValue: (node) => + isValidValueNode(context, node, context.getInputType()), + StringValue: (node) => + isValidValueNode(context, node, context.getInputType()), + BooleanValue: (node) => + isValidValueNode(context, node, context.getInputType()), }; } @@ -131,100 +45,22 @@ export function ValuesOfCorrectTypeRule( * Any value literal may be a valid representation of a Scalar, depending on * that scalar type. */ -function isValidValueNode(context: ValidationContext, node: ValueNode): void { - // Report any error at the full type expected by the location. - const locationType = context.getInputType(); - if (!locationType) { - return; - } - - const type = getNamedType(locationType); - - if (!isLeafType(type)) { - const typeStr = inspect(locationType); - context.reportError( - new GraphQLError( - `Expected value of type "${typeStr}", found ${print(node)}.`, - { nodes: node }, - ), - ); - return; - } - - // Scalars and Enums determine if a literal value is valid via parseLiteral(), - // which may throw or return an invalid value to indicate failure. - try { - const parseResult = type.parseLiteral(node, undefined /* variables */); - if (parseResult === undefined) { - const typeStr = inspect(locationType); - context.reportError( - new GraphQLError( - `Expected value of type "${typeStr}", found ${print(node)}.`, - { nodes: node }, - ), - ); - } - } catch (error) { - const typeStr = inspect(locationType); - if (error instanceof GraphQLError) { - context.reportError(error); - } else { - context.reportError( - new GraphQLError( - `Expected value of type "${typeStr}", found ${print(node)}; ` + - error.message, - { nodes: node, originalError: error }, - ), - ); - } - } -} - -function validateOneOfInputObject( +function isValidValueNode( context: ValidationContext, - node: ObjectValueNode, - type: GraphQLInputObjectType, - fieldNodeMap: Map, - variableDefinitions: { [key: string]: VariableDefinitionNode }, -): void { - const keys = Array.from(fieldNodeMap.keys()); - const isNotExactlyOneField = keys.length !== 1; - - if (isNotExactlyOneField) { - context.reportError( - new GraphQLError( - `OneOf Input Object "${type.name}" must specify exactly one key.`, - { nodes: [node] }, - ), - ); - return; - } - - const value = fieldNodeMap.get(keys[0])?.value; - const isNullLiteral = !value || value.kind === Kind.NULL; - const isVariable = value?.kind === Kind.VARIABLE; - - if (isNullLiteral) { - context.reportError( - new GraphQLError(`Field "${type.name}.${keys[0]}" must be non-null.`, { - nodes: [node], - }), + node: ValueNode, + inputType: Maybe, +): false { + if (inputType) { + validateInputLiteral( + node, + inputType, + (error) => { + context.reportError(error); + }, + undefined, + undefined, + context.hideSuggestions, ); - return; - } - - if (isVariable) { - const variableName = value.name.value; - const definition = variableDefinitions[variableName]; - const isNullableVariable = definition.type.kind !== Kind.NON_NULL_TYPE; - - if (isNullableVariable) { - context.reportError( - new GraphQLError( - `Variable "${variableName}" must be non-nullable to be used for OneOf Input Object "${type.name}".`, - { nodes: [node] }, - ), - ); - } } + return false; } diff --git a/src/validation/rules/VariablesInAllowedPositionRule.ts b/src/validation/rules/VariablesInAllowedPositionRule.ts index e662ba443c..00f50efce0 100644 --- a/src/validation/rules/VariablesInAllowedPositionRule.ts +++ b/src/validation/rules/VariablesInAllowedPositionRule.ts @@ -1,4 +1,3 @@ -import { inspect } from '../../jsutils/inspect.js'; import type { Maybe } from '../../jsutils/Maybe.js'; import { GraphQLError } from '../../error/GraphQLError.js'; @@ -8,7 +7,11 @@ import { Kind } from '../../language/kinds.js'; import type { ASTVisitor } from '../../language/visitor.js'; import type { GraphQLType } from '../../type/definition.js'; -import { isNonNullType } from '../../type/definition.js'; +import { + isInputObjectType, + isNonNullType, + isNullableType, +} from '../../type/definition.js'; import type { GraphQLSchema } from '../../type/schema.js'; import { isTypeSubTypeOf } from '../../utilities/typeComparators.js'; @@ -36,9 +39,19 @@ export function VariablesInAllowedPositionRule( leave(operation) { const usages = context.getRecursiveVariableUsages(operation); - for (const { node, type, defaultValue } of usages) { + for (const { + node, + type, + parentType, + defaultValue, + fragmentVariableDefinition, + } of usages) { const varName = node.name.value; - const varDef = varDefMap.get(varName); + + let varDef = fragmentVariableDefinition; + if (!varDef) { + varDef = varDefMap.get(varName); + } if (varDef && type) { // A var type is allowed if it is the same or more strict (e.g. is // a subtype of) than the expected type. It can be more strict if @@ -57,11 +70,22 @@ export function VariablesInAllowedPositionRule( defaultValue, ) ) { - const varTypeStr = inspect(varType); - const typeStr = inspect(type); context.reportError( new GraphQLError( - `Variable "$${varName}" of type "${varTypeStr}" used in position expecting type "${typeStr}".`, + `Variable "$${varName}" of type "${varType}" used in position expecting type "${type}".`, + { nodes: [varDef, node] }, + ), + ); + } + + if ( + isInputObjectType(parentType) && + parentType.isOneOf && + isNullableType(varType) + ) { + context.reportError( + new GraphQLError( + `Variable "$${varName}" is of type "${varType}" but must be non-nullable to be used for OneOf Input Object "${parentType}".`, { nodes: [varDef, node] }, ), ); @@ -78,15 +102,18 @@ export function VariablesInAllowedPositionRule( /** * Returns true if the variable is allowed in the location it was found, - * which includes considering if default values exist for either the variable + * including considering if default values exist for either the variable * or the location at which it is located. + * + * OneOf Input Object Type fields are considered separately above to + * provide a more descriptive error message. */ function allowedVariableUsage( schema: GraphQLSchema, varType: GraphQLType, varDefaultValue: Maybe, locationType: GraphQLType, - locationDefaultValue: Maybe, + locationDefaultValue: unknown, ): boolean { if (isNonNullType(locationType) && !isNonNullType(varType)) { const hasNonNullVariableDefaultValue = diff --git a/src/validation/rules/custom/NoDeprecatedCustomRule.ts b/src/validation/rules/custom/NoDeprecatedCustomRule.ts index 375373eb1d..6fcf5651a7 100644 --- a/src/validation/rules/custom/NoDeprecatedCustomRule.ts +++ b/src/validation/rules/custom/NoDeprecatedCustomRule.ts @@ -1,5 +1,3 @@ -import { invariant } from '../../../jsutils/invariant.js'; - import { GraphQLError } from '../../../error/GraphQLError.js'; import type { ASTVisitor } from '../../../language/visitor.js'; @@ -24,11 +22,9 @@ export function NoDeprecatedCustomRule(context: ValidationContext): ASTVisitor { const fieldDef = context.getFieldDef(); const deprecationReason = fieldDef?.deprecationReason; if (fieldDef && deprecationReason != null) { - const parentType = context.getParentType(); - invariant(parentType != null); context.reportError( new GraphQLError( - `The field ${parentType.name}.${fieldDef.name} is deprecated. ${deprecationReason}`, + `The field ${fieldDef} is deprecated. ${deprecationReason}`, { nodes: node }, ), ); @@ -38,25 +34,12 @@ export function NoDeprecatedCustomRule(context: ValidationContext): ASTVisitor { const argDef = context.getArgument(); const deprecationReason = argDef?.deprecationReason; if (argDef && deprecationReason != null) { - const directiveDef = context.getDirective(); - if (directiveDef != null) { - context.reportError( - new GraphQLError( - `Directive "@${directiveDef.name}" argument "${argDef.name}" is deprecated. ${deprecationReason}`, - { nodes: node }, - ), - ); - } else { - const parentType = context.getParentType(); - const fieldDef = context.getFieldDef(); - invariant(parentType != null && fieldDef != null); - context.reportError( - new GraphQLError( - `Field "${parentType.name}.${fieldDef.name}" argument "${argDef.name}" is deprecated. ${deprecationReason}`, - { nodes: node }, - ), - ); - } + context.reportError( + new GraphQLError( + `The argument "${argDef}" is deprecated. ${deprecationReason}`, + { nodes: node }, + ), + ); } }, ObjectField(node) { @@ -67,7 +50,7 @@ export function NoDeprecatedCustomRule(context: ValidationContext): ASTVisitor { if (deprecationReason != null) { context.reportError( new GraphQLError( - `The input field ${inputObjectDef.name}.${inputFieldDef.name} is deprecated. ${deprecationReason}`, + `The input field ${inputFieldDef} is deprecated. ${deprecationReason}`, { nodes: node }, ), ); @@ -78,11 +61,9 @@ export function NoDeprecatedCustomRule(context: ValidationContext): ASTVisitor { const enumValueDef = context.getEnumValue(); const deprecationReason = enumValueDef?.deprecationReason; if (enumValueDef && deprecationReason != null) { - const enumTypeDef = getNamedType(context.getInputType()); - invariant(enumTypeDef != null); context.reportError( new GraphQLError( - `The enum value "${enumTypeDef.name}.${enumValueDef.name}" is deprecated. ${deprecationReason}`, + `The enum value "${enumValueDef}" is deprecated. ${deprecationReason}`, { nodes: node }, ), ); diff --git a/src/validation/specifiedRules.ts b/src/validation/specifiedRules.ts index 60c967f8f0..fa2d746de4 100644 --- a/src/validation/specifiedRules.ts +++ b/src/validation/specifiedRules.ts @@ -19,12 +19,16 @@ import { import { KnownDirectivesRule } from './rules/KnownDirectivesRule.js'; // Spec Section: "Fragment spread target defined" import { KnownFragmentNamesRule } from './rules/KnownFragmentNamesRule.js'; +// Spec Section: "Operation Type Existence" +import { KnownOperationTypesRule } from './rules/KnownOperationTypesRule.js'; // Spec Section: "Fragment Spread Type Existence" import { KnownTypeNamesRule } from './rules/KnownTypeNamesRule.js'; // Spec Section: "Lone Anonymous Operation" import { LoneAnonymousOperationRule } from './rules/LoneAnonymousOperationRule.js'; // SDL-specific validation rules import { LoneSchemaDefinitionRule } from './rules/LoneSchemaDefinitionRule.js'; +// TODO: Spec Section +import { MaxIntrospectionDepthRule } from './rules/MaxIntrospectionDepthRule.js'; // Spec Section: "Fragments must not form cycles" import { NoFragmentCyclesRule } from './rules/NoFragmentCyclesRule.js'; // Spec Section: "All Variable Used Defined" @@ -75,6 +79,12 @@ import { VariablesAreInputTypesRule } from './rules/VariablesAreInputTypesRule.j import { VariablesInAllowedPositionRule } from './rules/VariablesInAllowedPositionRule.js'; import type { SDLValidationRule, ValidationRule } from './ValidationContext.js'; +/** + * Technically these aren't part of the spec but they are strongly encouraged + * validation rules. + */ +export const recommendedRules = Object.freeze([MaxIntrospectionDepthRule]); + /** * This set includes all validation rules defined by the GraphQL spec. * @@ -83,6 +93,7 @@ import type { SDLValidationRule, ValidationRule } from './ValidationContext.js'; */ export const specifiedRules: ReadonlyArray = Object.freeze([ ExecutableDefinitionsRule, + KnownOperationTypesRule, UniqueOperationNamesRule, LoneAnonymousOperationRule, SingleFieldSubscriptionsRule, @@ -112,6 +123,7 @@ export const specifiedRules: ReadonlyArray = Object.freeze([ VariablesInAllowedPositionRule, OverlappingFieldsCanBeMergedRule, UniqueInputFieldNamesRule, + ...recommendedRules, ]); /** diff --git a/src/validation/validate.ts b/src/validation/validate.ts index 93da49be78..05eeb39dbb 100644 --- a/src/validation/validate.ts +++ b/src/validation/validate.ts @@ -41,12 +41,10 @@ export function validate( schema: GraphQLSchema, documentAST: DocumentNode, rules: ReadonlyArray = specifiedRules, - options?: { maxErrors?: number }, - - /** @deprecated will be removed in 17.0.0 */ - typeInfo: TypeInfo = new TypeInfo(schema), + options?: { maxErrors?: number; hideSuggestions?: Maybe }, ): ReadonlyArray { const maxErrors = options?.maxErrors ?? 100; + const hideSuggestions = options?.hideSuggestions ?? false; // If the schema used for validation is invalid, throw an error. assertValidSchema(schema); @@ -55,6 +53,7 @@ export function validate( 'Too many validation errors, error limit reached. Validation aborted.', ); const errors: Array = []; + const typeInfo = new TypeInfo(schema); const context = new ValidationContext( schema, documentAST, @@ -65,6 +64,7 @@ export function validate( } errors.push(error); }, + hideSuggestions, ); // This uses a specialized visitor which runs multiple visitors in parallel, diff --git a/src/version.ts b/src/version.ts index a12213bc7e..91e3f0113f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -4,7 +4,7 @@ /** * A string containing the version of the GraphQL.js library */ -export const version = '17.0.0-alpha.3' as string; +export const version = '17.0.0-alpha.7' as string; /** * An object containing the components of the GraphQL.js version string @@ -13,5 +13,5 @@ export const versionInfo = Object.freeze({ major: 17 as number, minor: 0 as number, patch: 0 as number, - preReleaseTag: 'alpha.3' as string | null, + preReleaseTag: 'alpha.7' as string | null, }); diff --git a/stryker.conf.json b/stryker.conf.json deleted file mode 100644 index 3ded7b25a0..0000000000 --- a/stryker.conf.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "warnings": { "slow": false }, - "packageManager": "npm", - "coverageAnalysis": "perTest", - "mutate": ["src/**/*.ts", "!src/**/__tests__/**/*.ts"], - "buildCommand": "tsc --outDir dist --noEmit false", - "checkers": ["typescript"], - "tsconfigFile": "tsconfig.json", - "testRunner": "mocha", - "mochaOptions": { - "spec": ["dist/src/**/*-test.js"] - }, - "reporters": ["html", "progress", "dashboard"] -} diff --git a/tsconfig.json b/tsconfig.json index 7a2b32b927..1bd54781c0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,8 @@ "dom" // Workaround for missing web-compatible globals in `@types/node` ], "target": "es2021", + "sourceMap": true, + "inlineSources": true, "module": "es2022", "moduleResolution": "node", "noEmit": true, diff --git a/website/.babelrc.json b/website/.babelrc.json deleted file mode 100644 index ea45a66e30..0000000000 --- a/website/.babelrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "presets": ["@docusaurus/core/lib/babel/preset"], - "browserslist": { - "production": ["last 2 versions"], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/website/css/globals.css b/website/css/globals.css new file mode 100644 index 0000000000..b5a84e2189 --- /dev/null +++ b/website/css/globals.css @@ -0,0 +1,482 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } +} + +.conf-hero { + background: linear-gradient( + 360deg, + #0e031c 10.63%, + #0e031c 10.65%, + rgba(14, 3, 28, 0) 166.98% + ), + url('/img/conf/graphql-conf-bg.png'); + @apply text-white max-md:text-base; +} + +.with-arrow:after { + @apply content-['_→'] font-sans text-xl; + @apply transition-all duration-75 hover:ml-1; +} + +footer { + @apply !bg-transparent; +} + +.nextra-logo { + mask-image: linear-gradient( + 60deg, + black 25%, + rgba(0, 0, 0, 0.2) 50%, + black 75% + ); + mask-size: 400%; + mask-position: 0; + + &:hover { + mask-position: 100%; + transition: + mask-position 1s ease, + -webkit-mask-position 1s ease; + } +} + +div[role='menu'][data-headlessui-state] { + @apply left-0 right-auto; +} + +div[id^='headlessui-menu-items'] { + @apply rounded-none; + + > a { + @apply py-3.5; + } +} + +/* should be fixed in Nextra 4 */ +._max-w-\[90rem\] { + @apply container; +} + +.nextra-nav-container + ._max-w-\[90rem\] { + @apply px-0; +} + +.nextra-nav-container > nav { + @apply gap-6; +} + +/* Move nav links to the left */ +.nextra-nav-container nav { + @apply justify-start; + + > a { + @apply hover:!text-primary; + } + + button[id^='headlessui-menu-button'] { + @apply hover:text-primary; + + + div > a { + @apply hover:text-primary; + } + } + + .nextra-search { + @apply ml-auto; + + + * { + @apply max-md:ml-auto; + } + } +} + +/*._max-w-\[90rem\] {*/ +/* !* TODO: maybe add to nextra as option to configure width? *!*/ +/* @apply container;*/ +/*}*/ + +.miniGraphiQL { + @apply !shadow-none border-2 dark:border-neutral-900 dark:!bg-neutral-900/10 !rounded-md dark:brightness-200; +} + +.result-window { + @apply !shadow-none border-l-2 dark:border-neutral-900 !rounded-none; +} + +.variable-editor { + @apply before:!bg-transparent border-t-2 dark:border-neutral-900; +} + +.CodeMirror-selected { + @apply !bg-primary/50 dark:bg-primary/40; +} + +.CodeMirror-cursor { + @apply dark:border-white; +} + +.CodeMirror { + @apply p-2; +} + +::selection { + @apply bg-primary/50 dark:bg-primary; +} + +@media (prefers-color-scheme: dark) { + body { + /*background: linear-gradient(*/ + /* 125deg,*/ + /* rgba(234, 117, 195, 0.3) -10%,*/ + /* rgba(234, 117, 195, 0) 8%*/ + /* ),*/ + /* linear-gradient(*/ + /* -125deg,*/ + /* rgba(234, 117, 195, 0.3) -10%,*/ + /* rgba(234, 117, 195, 0) 8%*/ + /* ),*/ + /* linear-gradient(0deg, #05031c, #05031c);*/ + /*@apply bg-gradient-to-b from-primary/10 to-[#05031c]*/ + + /*background:*/ + /* !*linear-gradient(0deg, #05031c, #05031c),*!*/ + /* linear-gradient(*/ + /* 125.93deg,*/ + /* rgba(234, 117, 195, 0.7) -10.45%,*/ + /* rgba(234, 117, 195, 0) 28.49%*/ + /* ),*/ + /* linear-gradient(*/ + /* -125.93deg,*/ + /* rgba(234, 117, 195, 0.7) -33.25%,*/ + /* rgba(234, 117, 195, 0) 26.45%*/ + /* );*/ + } +} + +.donts-images ul { + gap: 0 3em; + @apply flex flex-wrap; + + li { + @apply flex gap-3 grow md:basis-1/3; + + div { + @apply grow; + } + + img { + @apply bg-gray-200 p-4 h-20; + } + } +} + +.dos > ul:first-child li:before { + background: url('/img/brand/do.svg'); +} + +.donts > ul:first-child li:before { + background: url('/img/brand/dont.svg'); +} + +.dos, +.donts { + @apply mt-6; + + > ul ul { + @apply mt-0; + + li:before { + @apply grayscale; + } + } + + & > ul:first-child li { + @apply list-none relative; + + &:before { + @apply size-4 absolute content-[''] top-1 -left-6; + } + } +} + +.code-page { + background: linear-gradient( + 303.75deg, + rgba(124, 124, 124, 0.2) 0.8%, + rgba(124, 124, 124, 0) 74.17% + ), + linear-gradient(0deg, #f8f8f8, #f8f8f8); +} + +.dark .code-page { + background: linear-gradient( + 303.75deg, + rgba(124, 124, 124, 0.2) 0.8%, + rgba(124, 124, 124, 0) 74.17% + ), + linear-gradient(0deg, #1b1b1b, #1b1b1b); +} + +.dark .blog-page { + background: linear-gradient( + 250.93deg, + rgba(115, 119, 125, 0.1), + rgba(115, 119, 125, 0) + ), + #18181b; +} + +.blog-page { + background: linear-gradient( + 231.79deg, + rgba(225, 0, 152, 0.4) -23.67%, + rgba(225, 0, 152, 0) 25.9% + ), + linear-gradient( + 113.65deg, + rgba(229, 53, 171, 0.4) -49.55%, + rgba(225, 0, 152, 0) 33.97% + ), + linear-gradient(180deg, #f3f4f6 0%, #fff 100%); +} + +.conf-heading { + @apply text-3xl lg:text-[50px]/[4rem] font-bold text-balance; +} + +.conf-block { + @apply py-14 lg:py-24; +} + +.tag { + @apply hover:text-white hover:border-transparent hover:bg-primary; + @apply text-sm border border-current rounded px-2.5 py-1 font-bold transition-colors; +} + +.index { + p { + @apply text-lg lg:text-xl/9 mb-5 max-w-2xl; + } + + h2 { + @apply text-3xl lg:text-5xl font-bold mb-10 text-balance; + } + + pre { + @apply bg-white; + } +} + +.add, +.remove { + @apply shadow-[2px_0_currentColor_inset]; +} + +.add { + @apply !bg-green-200 dark:!bg-green-200/50 text-green-300; + + &::before { + @apply absolute start-1.5 content-['+']; + } +} + +.remove { + @apply !bg-red-200 dark:!bg-red-200/50 text-red-300; + + &::before { + @apply absolute start-1.5 content-['-']; + } +} + +.step0, +.step6 { + .v2 { + @apply opacity-0; + } +} + +.step1 .v2 code > span:nth-child(5) { + @apply add; +} + +.step2 .v3 code > span:nth-child(6) { + @apply add; +} + +.step3 .v4 code > { + span:nth-child(7), + span:nth-last-child(-n + 5) { + @apply add; + } +} + +.step4 { + .v4 code > span:nth-child(6) { + @apply remove; + } + + .v5 code > span:nth-child(6) { + @apply add; + } +} + +.index-button { + @apply border border-current rounded-md transition-colors py-2.5 px-6; + + &:hover, + &:focus { + @apply bg-primary border-transparent text-white; + } +} + +.nextra-codeblocks { + div.nextra-code { + pre { + @apply h-full; + } + + &:not(:first-child) { + @apply mt-0; + + > div { + @apply first:rounded-l-none; + } + + pre { + @apply rounded-l-none; + } + } + + &:not(:last-child) { + > div { + @apply first:rounded-r-none; + } + + pre { + @apply rounded-r-none; + } + } + } +} + +.index-bg { + background: linear-gradient( + 303.75deg, + rgba(124, 124, 124, 0.2) 0.8%, + rgba(124, 124, 124, 0) 74.17% + ), + linear-gradient(0deg, #f8f8f8, #f8f8f8); + + .dark & { + background: linear-gradient(0deg, #111, #111), + linear-gradient( + 303.75deg, + rgba(124, 124, 124, 0.2) 0.8%, + rgba(124, 124, 124, 0) 74.17% + ); + } +} + +.index-gradient { + @apply bg-gradient-to-b from-transparent to-primary/5 dark:to-primary/10; +} + +.type-evolution { + @apply w-full overflow-hidden; + + #typeEvolveView { + @apply select-none h-full relative left-0 flex; + + .v1, + .v2, + .v3, + .v4 { + @apply border-r dark:border-neutral-800 w-1/2 shrink-0; + } + + .v5 { + @apply w-full shrink-0; + } + + &.step1 { + .v2 { + opacity: 1; + transition: opacity 0.5s ease-in-out; + } + } + + &.step2 { + left: calc(-1 * 50%); + transition: left 0.5s ease-in-out; + } + + &.step3 { + left: calc(-2 * 50%); + transition: left 0.5s ease-in-out; + } + + &.step4 { + left: calc(-3 * 50%); + transition: left 0.5s ease-in-out; + } + + &.step5 { + left: calc(-4 * 50%); + transition: left 0.5s ease-in-out; + } + + &.step6 { + .v5 { + left: calc(-4 * 50%); + opacity: 0; + transition: opacity 0.5s ease-in-out; + } + } + } +} + +.apiIndex { + @apply mt-6; +} + +.apiIndex li { + margin: 0 0 5px 0; +} + +.apiIndex li a { + color: inherit; + display: block; + position: relative; + text-decoration: none; +} + +.apiIndex li a:hover::before { + @apply text-primary; + content: '#'; + font-size: 16px; + left: -2em; + line-height: 20px; + position: absolute; +} + +.apiIndex li { + @apply bg-white dark:bg-black; + @apply [box-shadow:inset_0_0_0_1px_#ddd,inset_4px_0_0_#ddd]; + @apply dark:[box-shadow:inset_0_0_0_1px_#444,inset_4px_0_0_#444]; + font-size: 13px; + padding: 7px 14px; +} diff --git a/website/docs/tutorials/basic-types.md b/website/docs/tutorials/basic-types.md deleted file mode 100644 index 56b34a883d..0000000000 --- a/website/docs/tutorials/basic-types.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Basic Types ---- - -In most situations, all you need to do is to specify the types for your API using the GraphQL schema language, taken as an argument to the `buildSchema` function. - -The GraphQL schema language supports the scalar types of `String`, `Int`, `Float`, `Boolean`, and `ID`, so you can use these directly in the schema you pass to `buildSchema`. - -By default, every type is nullable - it's legitimate to return `null` as any of the scalar types. Use an exclamation point to indicate a type cannot be nullable, so `String!` is a non-nullable string. - -To use a list type, surround the type in square brackets, so `[Int]` is a list of integers. - -Each of these types maps straightforwardly to JavaScript, so you can just return plain old JavaScript objects in APIs that return these types. Here's an example that shows how to use some of these basic types: - -```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -var schema = buildSchema(` - type Query { - quoteOfTheDay: String - random: Float! - rollThreeDice: [Int] - } -`); - -// The root provides a resolver function for each API endpoint -var root = { - quoteOfTheDay: () => { - return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within'; - }, - random: () => { - return Math.random(); - }, - rollThreeDice: () => { - return [1, 2, 3].map((_) => 1 + Math.floor(Math.random() * 6)); - }, -}; - -var app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs. - -These examples show you how to call APIs that return different types. To send different types of data into an API, you will also need to learn about [passing arguments to a GraphQL API](./passing-arguments.md). diff --git a/website/docs/tutorials/constructing-types.md b/website/docs/tutorials/constructing-types.md deleted file mode 100644 index e125bdd28d..0000000000 --- a/website/docs/tutorials/constructing-types.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Constructing Types -category: Advanced Guides ---- - -For many apps, you can define a fixed schema when the application starts, and define it using GraphQL schema language. In some cases, it's useful to construct a schema programmatically. You can do this using the `GraphQLSchema` constructor. - -When you are using the `GraphQLSchema` constructor to create a schema, instead of defining `Query` and `Mutation` types solely using schema language, you create them as separate object types. - -For example, let's say we are building a simple API that lets you fetch user data for a few hardcoded users based on an id. Using `buildSchema` we could write a server with: - -```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); - -var schema = buildSchema(` - type User { - id: String - name: String - } - - type Query { - user(id: String): User - } -`); - -// Maps id to User object -var fakeDatabase = { - a: { - id: 'a', - name: 'alice', - }, - b: { - id: 'b', - name: 'bob', - }, -}; - -var root = { - user: function ({ id }) { - return fakeDatabase[id]; - }, -}; - -var app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -We can implement this same API without using GraphQL schema language: - -```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var graphql = require('graphql'); - -// Maps id to User object -var fakeDatabase = { - a: { - id: 'a', - name: 'alice', - }, - b: { - id: 'b', - name: 'bob', - }, -}; - -// Define the User type -var userType = new graphql.GraphQLObjectType({ - name: 'User', - fields: { - id: { type: graphql.GraphQLString }, - name: { type: graphql.GraphQLString }, - }, -}); - -// Define the Query type -var queryType = new graphql.GraphQLObjectType({ - name: 'Query', - fields: { - user: { - type: userType, - // `args` describes the arguments that the `user` query accepts - args: { - id: { type: graphql.GraphQLString }, - }, - resolve: function (_, { id }) { - return fakeDatabase[id]; - }, - }, - }, -}); - -var schema = new graphql.GraphQLSchema({ query: queryType }); - -var app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -When we use this method of creating the API, the root level resolvers are implemented on the `Query` and `Mutation` types rather than on a `root` object. - -This is particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema. You might have a common format for something like creating and updating database records. This is also useful for implementing features like union types which don't map cleanly to ES6 classes and schema language. diff --git a/website/docs/tutorials/express-graphql.md b/website/docs/tutorials/express-graphql.md deleted file mode 100644 index 80ec4cb086..0000000000 --- a/website/docs/tutorials/express-graphql.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: express-graphql ---- - -The `express-graphql` module provides a simple way to create an [Express](https://expressjs.com/) server that runs a GraphQL API. - -```js -import { graphqlHTTP } from 'express-graphql'; // ES6 -var { graphqlHTTP } = require('express-graphql'); // CommonJS -``` - -### graphqlHTTP - -```js -graphqlHTTP({ - schema: GraphQLSchema, - graphiql?: ?boolean, - rootValue?: ?any, - context?: ?any, - pretty?: ?boolean, - formatError?: ?Function, - validationRules?: ?Array, -}): Middleware -``` - -Constructs an Express application based on a GraphQL schema. - -See the [express-graphql tutorial](./running-an-express-graphql-server.md) for sample usage. - -See the [GitHub README](https://github.com/graphql/express-graphql) for more extensive documentation of the details of this method. diff --git a/website/docs/tutorials/hello.png b/website/docs/tutorials/hello.png deleted file mode 100644 index e1d56100da..0000000000 Binary files a/website/docs/tutorials/hello.png and /dev/null differ diff --git a/website/docs/tutorials/index.md b/website/docs/tutorials/index.md deleted file mode 100644 index 50b67f86c7..0000000000 --- a/website/docs/tutorials/index.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Getting Started With GraphQL.js ---- - -## Prerequisites - -Before getting started, you should have Node v6 installed, although the examples should mostly work in previous versions of Node as well. For this guide, we won't use any language features that require transpilation, but we will use some ES6 features like [Promises](http://www.html5rocks.com/en/tutorials/es6/promises/), [classes](http://javascriptplayground.com/blog/2014/07/introduction-to-es6-classes-tutorial/), and [fat arrow functions](https://strongloop.com/strongblog/an-introduction-to-javascript-es6-arrow-functions/), so if you aren't familiar with them you might want to read up on them first. - -To create a new project and install GraphQL.js in your current directory: - -```bash -npm init -npm install graphql --save -``` - -## Writing Code - -To handle GraphQL queries, we need a schema that defines the `Query` type, and we need an API root with a function called a “resolver” for each API endpoint. For an API that just returns “Hello world!”, we can put this code in a file named `server.js`: - -```js -let { graphql, buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -let schema = buildSchema(` - type Query { - hello: String - } -`); - -// The root provides a resolver function for each API endpoint -let root = { - hello: () => { - return 'Hello world!'; - }, -}; - -// Run the GraphQL query '{ hello }' and print out the response -graphql({ schema, source: '{ hello }', rootValue: root }).then((response) => { - console.log(JSON.stringify(response, null, 2)); -}); -``` - -If you run this with: - -```bash -node server.js -``` - -You should see the GraphQL response printed out: - -```js -{ - "data": { - "hello": "Hello world!" - } -} -``` - -Congratulations - you just executed a GraphQL query! - -For practical applications, you'll probably want to run GraphQL queries from an API server, rather than executing GraphQL with a command line tool. To use GraphQL for an API server over HTTP, check out [Running an Express GraphQL Server](./running-an-express-graphql-server.md). diff --git a/website/docs/tutorials/mutations-and-input-types.md b/website/docs/tutorials/mutations-and-input-types.md deleted file mode 100644 index 474671aa70..0000000000 --- a/website/docs/tutorials/mutations-and-input-types.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Mutations and Input Types ---- - -If you have an API endpoint that alters data, like inserting data into a database or altering data already in a database, you should make this endpoint a `Mutation` rather than a `Query`. This is as simple as making the API endpoint part of the top-level `Mutation` type instead of the top-level `Query` type. - -Let's say we have a “message of the day” server, where anyone can update the message of the day, and anyone can read the current one. The GraphQL schema for this is simply: - -```graphql -type Mutation { - setMessage(message: String): String -} - -type Query { - getMessage: String -} -``` - -It's often convenient to have a mutation that maps to a database create or update operation, like `setMessage`, return the same thing that the server stored. That way, if you modify the data on the server, the client can learn about those modifications. - -Both mutations and queries can be handled by root resolvers, so the root that implements this schema can simply be: - -```js -var fakeDatabase = {}; -var root = { - setMessage: function ({ message }) { - fakeDatabase.message = message; - return message; - }, - getMessage: function () { - return fakeDatabase.message; - }, -}; -``` - -You don't need anything more than this to implement mutations. But in many cases, you will find a number of different mutations that all accept the same input parameters. A common example is that creating an object in a database and updating an object in a database often take the same parameters. To make your schema simpler, you can use “input types” for this, by using the `input` keyword instead of the `type` keyword. - -For example, instead of a single message of the day, let's say we have many messages, indexed in a database by the `id` field, and each message has both a `content` string and an `author` string. We want a mutation API both for creating a new message and for updating an old message. We could use the schema: - -```graphql -input MessageInput { - content: String - author: String -} - -type Message { - id: ID! - content: String - author: String -} - -type Query { - getMessage(id: ID!): Message -} - -type Mutation { - createMessage(input: MessageInput): Message - updateMessage(id: ID!, input: MessageInput): Message -} -``` - -Here, the mutations return a `Message` type, so that the client can get more information about the newly-modified `Message` in the same request as the request that mutates it. - -Input types can't have fields that are other objects, only basic scalar types, list types, and other input types. - -Naming input types with `Input` on the end is a useful convention, because you will often want both an input type and an output type that are slightly different for a single conceptual object. - -Here's some runnable code that implements this schema, keeping the data in memory: - -```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -var schema = buildSchema(` - input MessageInput { - content: String - author: String - } - - type Message { - id: ID! - content: String - author: String - } - - type Query { - getMessage(id: ID!): Message - } - - type Mutation { - createMessage(input: MessageInput): Message - updateMessage(id: ID!, input: MessageInput): Message - } -`); - -// If Message had any complex fields, we'd put them on this object. -class Message { - constructor(id, { content, author }) { - this.id = id; - this.content = content; - this.author = author; - } -} - -// Maps username to content -var fakeDatabase = {}; - -var root = { - getMessage: function ({ id }) { - if (!fakeDatabase[id]) { - throw new Error('no message exists with id ' + id); - } - return new Message(id, fakeDatabase[id]); - }, - createMessage: function ({ input }) { - // Create a random id for our "database". - var id = require('crypto').randomBytes(10).toString('hex'); - - fakeDatabase[id] = input; - return new Message(id, input); - }, - updateMessage: function ({ id, input }) { - if (!fakeDatabase[id]) { - throw new Error('no message exists with id ' + id); - } - // This replaces all old data, but some apps might want partial update. - fakeDatabase[id] = input; - return new Message(id, input); - }, -}; - -var app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -To call a mutation, you must use the keyword `mutation` before your GraphQL query. To pass an input type, provide the data written as if it's a JSON object. For example, with the server defined above, you can create a new message and return the `id` of the new message with this operation: - -```graphql -mutation { - createMessage(input: { author: "andy", content: "hope is a good thing" }) { - id - } -} -``` - -You can use variables to simplify mutation client logic just like you can with queries. For example, some JavaScript code that calls the server to execute this mutation is: - -```js -var author = 'andy'; -var content = 'hope is a good thing'; -var query = `mutation CreateMessage($input: MessageInput) { - createMessage(input: $input) { - id - } -}`; - -fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ - query, - variables: { - input: { - author, - content, - }, - }, - }), -}) - .then((r) => r.json()) - .then((data) => console.log('data returned:', data)); -``` - -One particular type of mutation is operations that change users, like signing up a new user. While you can implement this using GraphQL mutations, you can reuse many existing libraries if you learn about [GraphQL with authentication and Express middleware](./authentication-and-express-middleware.md). diff --git a/website/docs/tutorials/object-types.md b/website/docs/tutorials/object-types.md deleted file mode 100644 index 37cfe69131..0000000000 --- a/website/docs/tutorials/object-types.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: Object Types -category: GraphQL.js Tutorial ---- - -In many cases, you don't want to return a number or a string from an API. You want to return an object that has its own complex behavior. GraphQL is a perfect fit for this. - -In GraphQL schema language, the way you define a new object type is the same way we have been defining the `Query` type in our examples. Each object can have fields that return a particular type, and methods that take arguments. For example, in the [Passing Arguments](./passing-arguments.md) documentation, we had a method to roll some random dice: - -```graphql -type Query { - rollDice(numDice: Int!, numSides: Int): [Int] -} -``` - -If we wanted to have more and more methods based on a random die over time, we could implement this with a `RandomDie` object type instead. - -```graphql -type RandomDie { - roll(numRolls: Int!): [Int] -} - -type Query { - getDie(numSides: Int): RandomDie -} -``` - -Instead of a root-level resolver for the `RandomDie` type, we can instead use an ES6 class, where the resolvers are instance methods. This code shows how the `RandomDie` schema above can be implemented: - -```js -class RandomDie { - constructor(numSides) { - this.numSides = numSides; - } - - rollOnce() { - return 1 + Math.floor(Math.random() * this.numSides); - } - - roll({ numRolls }) { - var output = []; - for (var i = 0; i < numRolls; i++) { - output.push(this.rollOnce()); - } - return output; - } -} - -var root = { - getDie: function ({ numSides }) { - return new RandomDie(numSides || 6); - }, -}; -``` - -For fields that don't use any arguments, you can use either properties on the object or instance methods. So for the example code above, both `numSides` and `rollOnce` can actually be used to implement GraphQL fields, so that code also implements the schema of: - -```graphql -type RandomDie { - numSides: Int! - rollOnce: Int! - roll(numRolls: Int!): [Int] -} - -type Query { - getDie(numSides: Int): RandomDie -} -``` - -Putting this all together, here is some sample code that runs a server with this GraphQL API: - -```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -var schema = buildSchema(` - type RandomDie { - numSides: Int! - rollOnce: Int! - roll(numRolls: Int!): [Int] - } - - type Query { - getDie(numSides: Int): RandomDie - } -`); - -// This class implements the RandomDie GraphQL type -class RandomDie { - constructor(numSides) { - this.numSides = numSides; - } - - rollOnce() { - return 1 + Math.floor(Math.random() * this.numSides); - } - - roll({ numRolls }) { - var output = []; - for (var i = 0; i < numRolls; i++) { - output.push(this.rollOnce()); - } - return output; - } -} - -// The root provides the top-level API endpoints -var root = { - getDie: function ({ numSides }) { - return new RandomDie(numSides || 6); - }, -}; - -var app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -When you issue a GraphQL query against an API that returns object types, you can call multiple methods on the object at once by nesting the GraphQL field names. For example, if you wanted to call both `rollOnce` to roll a die once, and `roll` to roll a die three times, you could do it with this query: - -```graphql -{ - getDie(numSides: 6) { - rollOnce - roll(numRolls: 3) - } -} -``` - -If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs with GraphiQL. - -This way of defining object types often provides advantages over a traditional REST API. Instead of doing one API request to get basic information about an object, and then multiple subsequent API requests to find out more information about that object, you can get all of that information in one API request. That saves bandwidth, makes your app run faster, and simplifies your client-side logic. - -So far, every API we've looked at is designed for returning data. In order to modify stored data or handle complex input, it helps to [learn about mutations and input types](./mutations-and-input-types.md). diff --git a/website/docs/tutorials/running-an-express-graphql-server.md b/website/docs/tutorials/running-an-express-graphql-server.md deleted file mode 100644 index 2acd733f8c..0000000000 --- a/website/docs/tutorials/running-an-express-graphql-server.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Running an Express GraphQL Server -sidebar_label: Running Express + GraphQL ---- - -The simplest way to run a GraphQL API server is to use [Express](https://expressjs.com), a popular web application framework for Node.js. You will need to install two additional dependencies: - -```bash -npm install express express-graphql graphql --save -``` - -Let's modify our “hello world” example so that it's an API server rather than a script that runs a single query. We can use the 'express' module to run a web server, and instead of executing a query directly with the `graphql` function, we can use the `express-graphql` library to mount a GraphQL API server on the “/graphql” HTTP endpoint: - -```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -var schema = buildSchema(` - type Query { - hello: String - } -`); - -// The root provides a resolver function for each API endpoint -var root = { - hello: () => { - return 'Hello world!'; - }, -}; - -var app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -You can run this GraphQL server with: - -```bash -node server.js -``` - -Since we configured `graphqlHTTP` with `graphiql: true`, you can use the GraphiQL tool to manually issue GraphQL queries. If you navigate in a web browser to `http://localhost:4000/graphql`, you should see an interface that lets you enter queries. It should look like: - -![hello world graphql example](./hello.png) - -This screen shot shows the GraphQL query `{ hello }` being issued and giving a result of `{ data: { hello: 'Hello world!' } }`. GraphiQL is a great tool for debugging and inspecting a server, so we recommend running it whenever your application is in development mode. - -At this point you have learned how to run a GraphQL server and how to use GraphiQL interface to issue queries. The next step is to learn how to [issue GraphQL queries from client code](./graphql-clients.md). diff --git a/website/docusaurus.config.cjs b/website/docusaurus.config.cjs deleted file mode 100644 index dce7dacae4..0000000000 --- a/website/docusaurus.config.cjs +++ /dev/null @@ -1,134 +0,0 @@ -'use strict'; - -const path = require('path'); - -const lightCodeTheme = require('prism-react-renderer/themes/github'); -const darkCodeTheme = require('prism-react-renderer/themes/dracula'); - -/** @type {import('@docusaurus/types').Config} */ -module.exports = { - title: 'graphql-js', - tagline: 'A reference implementation of GraphQL for JavaScript', - url: 'https://graphql-js.graphql.org', - baseUrl: '/', - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'throw', - onDuplicateRoutes: 'throw', - favicon: 'img/favicon.ico', - organizationName: 'graphql', - projectName: 'graphql-js', - presets: [ - [ - '@docusaurus/preset-classic', - /** @type {import('@docusaurus/preset-classic').Options} */ - ({ - docs: { - sidebarPath: require.resolve('./sidebars.cjs'), - editUrl: 'https://github.com/graphql/graphql-js/edit/main/website/', - }, - theme: { - customCss: require.resolve('./src/css/custom.css'), - }, - }), - ], - ], - plugins: [ - [ - 'docusaurus-plugin-typedoc-api', - { - projectRoot: path.join(__dirname, '..'), - packages: [{ path: '.' }], - }, - ], - ], - themeConfig: - /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ - ({ - navbar: { - title: 'graphql-js', - logo: { - alt: 'GraphQL Logo', - src: 'img/logo.svg', - }, - items: [ - { - type: 'doc', - docId: 'tutorials/index', - position: 'left', - label: 'Tutorial', - }, - { - href: 'https://github.com/graphql/graphql-js', - label: 'GitHub', - position: 'right', - }, - { - to: 'api', - label: 'API', - position: 'left', - }, - ], - }, - footer: { - style: 'dark', - links: [ - { - title: 'Docs', - items: [ - { - label: 'Tutorial', - to: 'docs/tutorials/', - }, - ], - }, - { - title: 'Community', - items: [ - { - label: 'Code of Conduct', - href: 'https://graphql.org/codeofconduct/', - }, - { - label: 'Stack Overflow', - href: 'https://stackoverflow.com/questions/tagged/graphql-js', - }, - { - label: 'Discord', - href: 'https://discord.graphql.org/', - }, - { - label: 'Twitter', - href: 'https://twitter.com/graphql', - }, - { - label: 'Upcoming Events', - href: 'https://graphql.org/community/upcoming-events/', - }, - ], - }, - { - title: 'More', - items: [ - { - label: 'GraphQL JS Working Group', - href: 'https://github.com/graphql/graphql-js-wg', - }, - { - label: 'GraphQL Foundation', - href: 'https://graphql.org/foundation', - }, - { - label: 'GraphQL Spec', - href: 'https://spec.graphql.org', - }, - ], - }, - ], - copyright: `Copyright © ${new Date().getFullYear()} The GraphQL Foundation. All rights reserved.
For web site terms of use, trademark policy and general project policies please see  https://lfprojects.org.`, - }, - prism: { - theme: lightCodeTheme, - darkTheme: darkCodeTheme, - }, - }), -}; diff --git a/website/icons/discord.svg b/website/icons/discord.svg new file mode 100644 index 0000000000..57ea755cc5 --- /dev/null +++ b/website/icons/discord.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/website/icons/github.svg b/website/icons/github.svg new file mode 100644 index 0000000000..66cb3d3791 --- /dev/null +++ b/website/icons/github.svg @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/website/icons/graphql-wordmark.svg b/website/icons/graphql-wordmark.svg new file mode 100644 index 0000000000..c407187504 --- /dev/null +++ b/website/icons/graphql-wordmark.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/icons/graphql.svg b/website/icons/graphql.svg new file mode 100644 index 0000000000..857fa8d9df --- /dev/null +++ b/website/icons/graphql.svg @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/website/icons/index.ts b/website/icons/index.ts new file mode 100644 index 0000000000..3935beb8e7 --- /dev/null +++ b/website/icons/index.ts @@ -0,0 +1,6 @@ +export { default as DiscordIcon } from './discord.svg'; +export { default as GitHubIcon } from './github.svg'; +export { default as GraphQLLogo } from './graphql.svg'; +export { default as GraphQLWordmarkLogo } from './graphql-wordmark.svg'; +export { default as StackOverflowIcon } from './stackoverflow.svg'; +export { default as TwitterIcon } from './twitter.svg'; diff --git a/website/icons/stackoverflow.svg b/website/icons/stackoverflow.svg new file mode 100644 index 0000000000..d210d7768a --- /dev/null +++ b/website/icons/stackoverflow.svg @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/website/icons/twitter.svg b/website/icons/twitter.svg new file mode 100644 index 0000000000..377365e1cf --- /dev/null +++ b/website/icons/twitter.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/website/next-env.d.ts b/website/next-env.d.ts new file mode 100644 index 0000000000..a4a7b3f5cf --- /dev/null +++ b/website/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/website/next.config.js b/website/next.config.js new file mode 100644 index 0000000000..3da28a4473 --- /dev/null +++ b/website/next.config.js @@ -0,0 +1,54 @@ +/* eslint-disable camelcase */ +import path from 'node:path'; + +import nextra from 'nextra'; + +const withNextra = nextra({ + theme: 'nextra-theme-docs', + themeConfig: './theme.config.tsx', +}); + +const sep = path.sep === '/' ? '/' : '\\\\'; + +const ALLOWED_SVG_REGEX = new RegExp(`${sep}icons${sep}.+\\.svg$`); + +/** + * @type {import('next').NextConfig} + */ +export default withNextra({ + webpack(config) { + const fileLoaderRule = config.module.rules.find((rule) => + rule.test?.test?.('.svg'), + ); + + fileLoaderRule.exclude = ALLOWED_SVG_REGEX; + + config.module.rules.push({ + test: ALLOWED_SVG_REGEX, + use: ['@svgr/webpack'], + }); + return config; + }, + output: 'export', + images: { + loader: 'custom', + imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], + deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], + }, + transpilePackages: ['next-image-export-optimizer'], + env: { + nextImageExportOptimizer_imageFolderPath: 'public/images', + nextImageExportOptimizer_exportFolderPath: 'out', + nextImageExportOptimizer_quality: '75', + nextImageExportOptimizer_storePicturesInWEBP: 'true', + nextImageExportOptimizer_exportFolderName: 'nextImageExportOptimizer', + // If you do not want to use blurry placeholder images, then you can set + // nextImageExportOptimizer_generateAndUseBlurImages to false and pass + // `placeholder="empty"` to all components. + nextImageExportOptimizer_generateAndUseBlurImages: 'true', + // If you want to cache the remote images, you can set the time to live of the cache in seconds. + // The default value is 0 seconds. + nextImageExportOptimizer_remoteImageCacheTTL: '0', + }, + trailingSlash: true, +}); diff --git a/website/package-lock.json b/website/package-lock.json new file mode 100644 index 0000000000..4bdfc8cfe7 --- /dev/null +++ b/website/package-lock.json @@ -0,0 +1,9536 @@ +{ + "name": "website", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "website", + "version": "0.0.0", + "devDependencies": { + "@svgr/webpack": "^8.1.0", + "@tailwindcss/typography": "^0.5.10", + "@types/node": "^22.7.5", + "autoprefixer": "^10.4.20", + "next": "^14.2.15", + "nextra": "^3.0.13", + "nextra-theme-docs": "^3.0.13", + "postcss": "^8.4.47", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.4.1.tgz", + "integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==", + "dev": true, + "dependencies": { + "package-manager-detector": "^0.2.0", + "tinyexec": "^0.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", + "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", + "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.8", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.8", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", + "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "regexpu-core": "^6.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", + "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-wrap-function": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", + "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", + "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", + "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz", + "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.8.tgz", + "integrity": "sha512-9ypqkozyzpG+HxlH4o4gdctalFGIjjdufzo7I2XPda0iBnZ6a+FO0rIEQcdSPXp02CkvGsII1exJhmROPQd5oA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.7.tgz", + "integrity": "sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-remap-async-to-generator": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.8.tgz", + "integrity": "sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.8.tgz", + "integrity": "sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.8.tgz", + "integrity": "sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.8.tgz", + "integrity": "sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.8.tgz", + "integrity": "sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.8.tgz", + "integrity": "sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.8.tgz", + "integrity": "sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.8.tgz", + "integrity": "sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-transform-parameters": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.8.tgz", + "integrity": "sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.8.tgz", + "integrity": "sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.8.tgz", + "integrity": "sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.7.tgz", + "integrity": "sha512-/qXt69Em8HgsjCLu7G3zdIQn7A2QwmYND7Wa0LTp09Na+Zn8L5d0A7wSXrKi18TJRc/Q5S1i1De/SU1LzVkSvA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.7.tgz", + "integrity": "sha512-r0QY7NVU8OnrwE+w2IWiRom0wwsTbjx4+xH2RTd7AVdof3uurXOF+/mXHQDRk+2jIvWgSaCHKMgggfvM4dyUGA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.7.tgz", + "integrity": "sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.7.tgz", + "integrity": "sha512-5yd3lH1PWxzW6IZj+p+Y4OLQzz0/LzlOG8vGqonHfVR3euf1vyzyMUJk9Ac+m97BH46mFc/98t9PmYLyvgL3qg==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.7.tgz", + "integrity": "sha512-6YTHJ7yjjgYqGc8S+CbEXhLICODk0Tn92j+vNJo07HFk9t3bjFgAKxPLFhHwF2NjmQVSI1zBRfBWUeVBa2osfA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", + "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-typescript": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.8.tgz", + "integrity": "sha512-58T2yulDHMN8YMUxiLq5YmWUnlDCyY1FsHM+v12VMx+1/FlrUj5tY50iDCpofFQEM8fMYOaY9YRvym2jcjn1Dg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.8", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.25.7", + "@babel/plugin-syntax-import-attributes": "^7.25.7", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.8", + "@babel/plugin-transform-async-to-generator": "^7.25.7", + "@babel/plugin-transform-block-scoped-functions": "^7.25.7", + "@babel/plugin-transform-block-scoping": "^7.25.7", + "@babel/plugin-transform-class-properties": "^7.25.7", + "@babel/plugin-transform-class-static-block": "^7.25.8", + "@babel/plugin-transform-classes": "^7.25.7", + "@babel/plugin-transform-computed-properties": "^7.25.7", + "@babel/plugin-transform-destructuring": "^7.25.7", + "@babel/plugin-transform-dotall-regex": "^7.25.7", + "@babel/plugin-transform-duplicate-keys": "^7.25.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-dynamic-import": "^7.25.8", + "@babel/plugin-transform-exponentiation-operator": "^7.25.7", + "@babel/plugin-transform-export-namespace-from": "^7.25.8", + "@babel/plugin-transform-for-of": "^7.25.7", + "@babel/plugin-transform-function-name": "^7.25.7", + "@babel/plugin-transform-json-strings": "^7.25.8", + "@babel/plugin-transform-literals": "^7.25.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.8", + "@babel/plugin-transform-member-expression-literals": "^7.25.7", + "@babel/plugin-transform-modules-amd": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.7", + "@babel/plugin-transform-modules-umd": "^7.25.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.7", + "@babel/plugin-transform-new-target": "^7.25.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.8", + "@babel/plugin-transform-numeric-separator": "^7.25.8", + "@babel/plugin-transform-object-rest-spread": "^7.25.8", + "@babel/plugin-transform-object-super": "^7.25.7", + "@babel/plugin-transform-optional-catch-binding": "^7.25.8", + "@babel/plugin-transform-optional-chaining": "^7.25.8", + "@babel/plugin-transform-parameters": "^7.25.7", + "@babel/plugin-transform-private-methods": "^7.25.7", + "@babel/plugin-transform-private-property-in-object": "^7.25.8", + "@babel/plugin-transform-property-literals": "^7.25.7", + "@babel/plugin-transform-regenerator": "^7.25.7", + "@babel/plugin-transform-reserved-words": "^7.25.7", + "@babel/plugin-transform-shorthand-properties": "^7.25.7", + "@babel/plugin-transform-spread": "^7.25.7", + "@babel/plugin-transform-sticky-regex": "^7.25.7", + "@babel/plugin-transform-template-literals": "^7.25.7", + "@babel/plugin-transform-typeof-symbol": "^7.25.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.7", + "@babel/plugin-transform-unicode-property-regex": "^7.25.7", + "@babel/plugin-transform-unicode-regex": "^7.25.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.7.tgz", + "integrity": "sha512-GjV0/mUEEXpi1U5ZgDprMRRgajGMRW3G5FjMr5KLKD8nT2fTG8+h/klV3+6Dm5739QE+K5+2e91qFKAYI3pmRg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-transform-react-display-name": "^7.25.7", + "@babel/plugin-transform-react-jsx": "^7.25.7", + "@babel/plugin-transform-react-jsx-development": "^7.25.7", + "@babel/plugin-transform-react-pure-annotations": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.25.7.tgz", + "integrity": "sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "@babel/plugin-syntax-jsx": "^7.25.7", + "@babel/plugin-transform-modules-commonjs": "^7.25.7", + "@babel/plugin-transform-typescript": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.0.tgz", + "integrity": "sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==", + "dev": true + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dev": true, + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dev": true, + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "dev": true + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "dev": true + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "dev": true + }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "dev": true, + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.25", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.25.tgz", + "integrity": "sha512-hZOmgN0NTOzOuZxI1oIrDu3Gcl8WViIkvPMpB4xdd4QD6xAMtwgwr3VPoiyH/bLtRcS1cDnhxLSD1NsMJmwh/A==", + "dev": true, + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dev": true, + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", + "dev": true + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.5.tgz", + "integrity": "sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==", + "dev": true, + "dependencies": { + "tslib": "^2.7.0" + } + }, + "node_modules/@headlessui/react": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.1.10.tgz", + "integrity": "sha512-6mLa2fjMDAFQi+/R10B+zU3edsUk/MDtENB2zHho0lqKU1uzhAfJLUduWds4nCo8wbl3vULtC5rJfZAQ1yqIng==", + "dev": true, + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@tanstack/react-virtual": "^3.8.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18", + "react-dom": "^18" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true + }, + "node_modules/@iconify/utils": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz", + "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==", + "dev": true, + "dependencies": { + "@antfu/install-pkg": "^0.4.0", + "@antfu/utils": "^0.7.10", + "@iconify/types": "^2.0.0", + "debug": "^4.3.6", + "kolorist": "^1.8.0", + "local-pkg": "^0.5.0", + "mlly": "^1.7.1" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@mermaid-js/parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz", + "integrity": "sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==", + "dev": true, + "dependencies": { + "langium": "3.0.0" + } + }, + "node_modules/@napi-rs/simple-git": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git/-/simple-git-0.1.19.tgz", + "integrity": "sha512-jMxvwzkKzd3cXo2EB9GM2ic0eYo2rP/BS6gJt6HnWbsDO1O8GSD4k7o2Cpr2YERtMpGF/MGcDfsfj2EbQPtrXw==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/simple-git-android-arm-eabi": "0.1.19", + "@napi-rs/simple-git-android-arm64": "0.1.19", + "@napi-rs/simple-git-darwin-arm64": "0.1.19", + "@napi-rs/simple-git-darwin-x64": "0.1.19", + "@napi-rs/simple-git-freebsd-x64": "0.1.19", + "@napi-rs/simple-git-linux-arm-gnueabihf": "0.1.19", + "@napi-rs/simple-git-linux-arm64-gnu": "0.1.19", + "@napi-rs/simple-git-linux-arm64-musl": "0.1.19", + "@napi-rs/simple-git-linux-powerpc64le-gnu": "0.1.19", + "@napi-rs/simple-git-linux-s390x-gnu": "0.1.19", + "@napi-rs/simple-git-linux-x64-gnu": "0.1.19", + "@napi-rs/simple-git-linux-x64-musl": "0.1.19", + "@napi-rs/simple-git-win32-arm64-msvc": "0.1.19", + "@napi-rs/simple-git-win32-x64-msvc": "0.1.19" + } + }, + "node_modules/@napi-rs/simple-git-android-arm-eabi": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.19.tgz", + "integrity": "sha512-XryEH/hadZ4Duk/HS/HC/cA1j0RHmqUGey3MsCf65ZS0VrWMqChXM/xlTPWuY5jfCc/rPubHaqI7DZlbexnX/g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-android-arm64": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.19.tgz", + "integrity": "sha512-ZQ0cPvY6nV9p7zrR9ZPo7hQBkDAcY/CHj3BjYNhykeUCiSNCrhvwX+WEeg5on8M1j4d5jcI/cwVG2FslfiByUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-darwin-arm64": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.19.tgz", + "integrity": "sha512-viZB5TYgjA1vH+QluhxZo0WKro3xBA+1xSzYx8mcxUMO5gnAoUMwXn0ZO/6Zy6pai+aGae+cj6XihGnrBRu3Pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-darwin-x64": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.19.tgz", + "integrity": "sha512-6dNkzSNUV5X9rsVYQbpZLyJu4Gtkl2vNJ3abBXHX/Etk0ILG5ZasO3ncznIANZQpqcbn/QPHr49J2QYAXGoKJA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-freebsd-x64": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-freebsd-x64/-/simple-git-freebsd-x64-0.1.19.tgz", + "integrity": "sha512-sB9krVIchzd20FjI2ZZ8FDsTSsXLBdnwJ6CpeVyrhXHnoszfcqxt49ocZHujAS9lMpXq7i2Nv1EXJmCy4KdhwA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-arm-gnueabihf": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.19.tgz", + "integrity": "sha512-6HPn09lr9N1n5/XKfP8Np53g4fEXVxOFqNkS6rTH3Rm1lZHdazTRH62RggXLTguZwjcE+MvOLvoTIoR5kAS8+g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-arm64-gnu": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.19.tgz", + "integrity": "sha512-G0gISckt4cVDp3oh5Z6PV3GHJrJO6Z8bIS+9xA7vTtKdqB1i5y0n3cSFLlzQciLzhr+CajFD27doW4lEyErQ/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-arm64-musl": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.19.tgz", + "integrity": "sha512-OwTRF+H4IZYxmDFRi1IrLMfqbdIpvHeYbJl2X94NVsLVOY+3NUHvEzL3fYaVx5urBaMnIK0DD3wZLbcueWvxbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-powerpc64le-gnu": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-powerpc64le-gnu/-/simple-git-linux-powerpc64le-gnu-0.1.19.tgz", + "integrity": "sha512-p7zuNNVyzpRvkCt2RIGv9FX/WPcPbZ6/FRUgUTZkA2WU33mrbvNqSi4AOqCCl6mBvEd+EOw5NU4lS9ORRJvAEg==", + "cpu": [ + "powerpc64le" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-s390x-gnu": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-s390x-gnu/-/simple-git-linux-s390x-gnu-0.1.19.tgz", + "integrity": "sha512-6N2vwJUPLiak8GLrS0a3is0gSb0UwI2CHOOqtvQxPmv+JVI8kn3vKiUscsktdDb0wGEPeZ8PvZs0y8UWix7K4g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-x64-gnu": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.19.tgz", + "integrity": "sha512-61YfeO1J13WK7MalLgP3QlV6of2rWnVw1aqxWkAgy/lGxoOFSJ4Wid6ANVCEZk4tJpPX/XNeneqkUz5xpeb2Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-x64-musl": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.19.tgz", + "integrity": "sha512-cCTWNpMJnN3PrUBItWcs3dQKCydsIasbrS3laMzq8k7OzF93Zrp2LWDTPlLCO9brbBVpBzy2Qk5Xg9uAfe/Ukw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-win32-arm64-msvc": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.19.tgz", + "integrity": "sha512-sWavb1BjeLKKBA+PbTsRSSzVNfb7V/dOpaJvkgR5d2kWFn/AHmCZHSSj/3nyZdYf0BdDC+DIvqk3daAEZ6QMVw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-win32-x64-msvc": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.19.tgz", + "integrity": "sha512-FmNuPoK4+qwaSCkp8lm3sJlrxk374enW+zCE5ZksXlZzj/9BDJAULJb5QUJ7o9Y8A/G+d8LkdQLPBE2Jaxe5XA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/env": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", + "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==", + "dev": true + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz", + "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz", + "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz", + "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz", + "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz", + "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz", + "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz", + "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz", + "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz", + "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.18.4.tgz", + "integrity": "sha512-91J35077w9UNaMK1cpMUEFRkNNz0uZjnSwiyBCFuRdaVuivO53wNC9XtWSDNDdcO5cGy87vfJRVAiyoCn/mjqA==", + "dev": true, + "dependencies": { + "@react-aria/interactions": "^3.22.4", + "@react-aria/utils": "^3.25.3", + "@react-types/shared": "^3.25.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.22.4.tgz", + "integrity": "sha512-E0vsgtpItmknq/MJELqYJwib+YN18Qag8nroqwjk1qOnBa9ROIkUhWJerLi1qs5diXq9LHKehZDXRlwPvdEFww==", + "dev": true, + "dependencies": { + "@react-aria/ssr": "^3.9.6", + "@react-aria/utils": "^3.25.3", + "@react-types/shared": "^3.25.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.6.tgz", + "integrity": "sha512-iLo82l82ilMiVGy342SELjshuWottlb5+VefO3jOQqQRNYnJBFpUSadswDPbRimSgJUZuFwIEYs6AabkP038fA==", + "dev": true, + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.25.3.tgz", + "integrity": "sha512-PR5H/2vaD8fSq0H/UB9inNbc8KDcVmW6fYAfSWkkn+OAdhTTMVKqXXrZuZBWyFfSD5Ze7VN6acr4hrOQm2bmrA==", + "dev": true, + "dependencies": { + "@react-aria/ssr": "^3.9.6", + "@react-stately/utils": "^3.10.4", + "@react-types/shared": "^3.25.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.4.tgz", + "integrity": "sha512-gBEQEIMRh5f60KCm7QKQ2WfvhB2gLUr9b72sqUdIZ2EG+xuPgaIlCBeSicvjmjBvYZwOjoOEnmIkcx2GHp/HWw==", + "dev": true, + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.25.0.tgz", + "integrity": "sha512-OZSyhzU6vTdW3eV/mz5i6hQwQUhkRs7xwY2d1aqPvTdMe0+2cY7Fwp45PAiwYLEj73i9ro2FxF9qC4DvHGSCgQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@shikijs/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", + "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "dev": true, + "dependencies": { + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", + "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "dev": true, + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", + "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "dev": true, + "dependencies": { + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0" + } + }, + "node_modules/@shikijs/twoslash": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-1.22.0.tgz", + "integrity": "sha512-r5F/x4GTh18XzhAREehgT9lCDFZlISBSIsOFZQQaqjiOLG81PIqJN1I1D6XY58UN9OJt+3mffuKq19K4FOJKJA==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.22.0", + "@shikijs/types": "1.22.0", + "twoslash": "^0.2.12" + } + }, + "node_modules/@shikijs/types": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", + "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "dev": true, + "dependencies": { + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==", + "dev": true + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz", + "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==", + "dev": true, + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.10.8", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.10.8.tgz", + "integrity": "sha512-VbzbVGSsZlQktyLrP5nxE+vE1ZR+U0NFAWPbJLoG2+DKPwd2D7dVICTVIIaYlJqX1ZCEnYDbaOpmMwbsyhBoIA==", + "dev": true, + "dependencies": { + "@tanstack/virtual-core": "3.10.8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.10.8", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.10.8.tgz", + "integrity": "sha512-PBu00mtt95jbKFi6Llk9aik8bnR3tR/oQP1o3TSi+iG//+Q2RTIzCEgKkHG8BB86kxMNW6O8wku+Lmi+QFR6jA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@theguild/remark-mermaid": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.1.3.tgz", + "integrity": "sha512-2FjVlaaKXK7Zj7UJAgOVTyaahn/3/EAfqYhyXg0BfDBVUl+lXcoIWRaxzqfnDr2rv8ax6GsC5mNh6hAaT86PDw==", + "dev": true, + "dependencies": { + "mermaid": "^11.0.0", + "unist-util-visit": "^5.0.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@theguild/remark-npm2yarn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@theguild/remark-npm2yarn/-/remark-npm2yarn-0.3.2.tgz", + "integrity": "sha512-H9T/GOuS/+4H7AY1cfD5DJIIIcGIIw1zMCB8OeTgXk7azJULsnuOurZ/CR54rvuTD+Krx0MVQccaUCvCWfP+vw==", + "dev": true, + "dependencies": { + "npm-to-yarn": "^3.0.0", + "unist-util-visit": "^5.0.0" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "dev": true + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "dev": true, + "peer": true + }, + "node_modules/@types/react": { + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true + }, + "node_modules/@typescript/vfs": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.0.tgz", + "integrity": "sha512-hvJUjNVeBMp77qPINuUvYXj4FyWeeMMKZkxEATEU3hqBAQ7qdTBCUFT7Sp0Zu0faeEtFf+ldXxMEDr/bk73ISg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-1.0.0.tgz", + "integrity": "sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "dev": true, + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/better-react-mathjax": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/better-react-mathjax/-/better-react-mathjax-2.0.3.tgz", + "integrity": "sha512-wfifT8GFOKb1TWm2+E50I6DJpLZ5kLbch283Lu043EJtwSv0XvZDjr4YfR4d2MjAhqP6SH4VjjrKgbX8R00oCQ==", + "dev": true, + "dependencies": { + "mathjax-full": "^3.2.2" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dev": true, + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dev": true, + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "dev": true + }, + "node_modules/clipboardy": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", + "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", + "dev": true, + "dependencies": { + "arch": "^2.1.0", + "execa": "^0.8.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", + "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dev": true, + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "peer": true + }, + "node_modules/cytoscape": { + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.2.tgz", + "integrity": "sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dev": true, + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dev": true, + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dev": true, + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "dev": true + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dev": true, + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dev": true, + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dev": true, + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dev": true, + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dev": true, + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dev": true, + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dev": true, + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dev": true, + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dev": true, + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dev": true, + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "dev": true + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dev": true, + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dev": true, + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dev": true, + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dev": true, + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", + "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "dev": true, + "dependencies": { + "d3": "^7.8.2", + "lodash-es": "^4.17.21" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dev": true, + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dev": true, + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==", + "dev": true + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.39", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.39.tgz", + "integrity": "sha512-4xkpSR6CjuiaNyvwiWDI85N9AxsvbPawB8xc7yzLPonYTuP19BVgYweKyUMFtHEZgIcHWMt1ks5Cqx2m+6/Grg==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.2.tgz", + "integrity": "sha512-S0gW2+XZkmsx00tU2uJ4L9hUT7IFabbml9pHh2WQqFmAbxit++YGZne0sKJbNwkj9Wvg9E4uqWl4nCIFQMmfag==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", + "dev": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dev": true, + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flexsearch": { + "version": "0.7.43", + "resolved": "https://registry.npmjs.org/flexsearch/-/flexsearch-0.7.43.tgz", + "integrity": "sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/foreground-child/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "dev": true + }, + "node_modules/has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-dom": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz", + "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^8.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", + "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.2.tgz", + "integrity": "sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "dev": true + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "dev": true, + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "dev": true + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-reference": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", + "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/katex": { + "version": "0.16.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", + "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true + }, + "node_modules/langium": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.0.0.tgz", + "integrity": "sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==", + "dev": true, + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "dev": true + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/marked": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mathjax-full": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", + "integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==", + "dev": true, + "dependencies": { + "esm": "^3.2.25", + "mhchemparser": "^4.1.0", + "mj-context-menu": "^0.6.1", + "speech-rule-engine": "^4.0.6" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dev": true, + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dev": true, + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.3.0.tgz", + "integrity": "sha512-fFmf2gRXLtlGzug4wpIGN+rQdZ30M8IZEB1D3eZkXNqC7puhqeURBcD/9tbwXsqBO+A6Nzzo3MSSepmnw5xSeg==", + "dev": true, + "dependencies": { + "@braintree/sanitize-url": "^7.0.1", + "@iconify/utils": "^2.1.32", + "@mermaid-js/parser": "^0.3.0", + "cytoscape": "^3.29.2", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.10", + "dayjs": "^1.11.10", + "dompurify": "^3.0.11 <3.1.7", + "katex": "^0.16.9", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^13.0.2", + "roughjs": "^4.6.6", + "stylis": "^4.3.1", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.1" + } + }, + "node_modules/mhchemparser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz", + "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==", + "dev": true + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "dev": true, + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dev": true, + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dev": true, + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "dev": true, + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", + "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.1.tgz", + "integrity": "sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==", + "dev": true, + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "dev": true, + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "dev": true, + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.2.tgz", + "integrity": "sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", + "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mj-context-menu": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", + "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==", + "dev": true + }, + "node_modules/mlly": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.2.tgz", + "integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz", + "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==", + "dev": true, + "dependencies": { + "@next/env": "14.2.15", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.15", + "@next/swc-darwin-x64": "14.2.15", + "@next/swc-linux-arm64-gnu": "14.2.15", + "@next/swc-linux-arm64-musl": "14.2.15", + "@next/swc-linux-x64-gnu": "14.2.15", + "@next/swc-linux-x64-musl": "14.2.15", + "@next/swc-win32-arm64-msvc": "14.2.15", + "@next/swc-win32-ia32-msvc": "14.2.15", + "@next/swc-win32-x64-msvc": "14.2.15" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-themes": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", + "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", + "dev": true, + "peerDependencies": { + "react": "^16.8 || ^17 || ^18", + "react-dom": "^16.8 || ^17 || ^18" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/nextra": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/nextra/-/nextra-3.0.13.tgz", + "integrity": "sha512-aK5ZEnKGE2lWhJvFfpj7T35JeA4ytvo2zUiXJ5JApIpFrwkzy8IYTa+irGHB0l9sxGiRlss4p+nAM8Kunvmlug==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "^0.5.4", + "@headlessui/react": "^2.1.2", + "@mdx-js/mdx": "^3.0.0", + "@mdx-js/react": "^3.0.0", + "@napi-rs/simple-git": "^0.1.9", + "@shikijs/twoslash": "^1.0.0", + "@theguild/remark-mermaid": "^0.1.2", + "@theguild/remark-npm2yarn": "^0.3.2", + "better-react-mathjax": "^2.0.3", + "clsx": "^2.0.0", + "estree-util-to-js": "^2.0.0", + "estree-util-value-to-estree": "^3.0.1", + "github-slugger": "^2.0.0", + "graceful-fs": "^4.2.11", + "gray-matter": "^4.0.3", + "hast-util-to-estree": "^3.1.0", + "katex": "^0.16.9", + "negotiator": "^0.6.3", + "p-limit": "^6.0.0", + "rehype-katex": "^7.0.0", + "rehype-pretty-code": "0.14.0", + "rehype-raw": "^7.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "remark-math": "^6.0.0", + "remark-reading-time": "^2.0.1", + "remark-smartypants": "^3.0.0", + "shiki": "^1.0.0", + "slash": "^5.1.0", + "title": "^3.5.3", + "unist-util-remove": "^4.0.0", + "unist-util-visit": "^5.0.0", + "yaml": "^2.3.2", + "zod": "^3.22.3", + "zod-validation-error": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "next": ">=13", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/nextra-theme-docs": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/nextra-theme-docs/-/nextra-theme-docs-3.0.13.tgz", + "integrity": "sha512-1NEo4NJxXRsNPE2PXlYdVlW7N8ZWe5XssePFKUq0comQaxDNc6SaxfBNw0VoQlwB3T5ifTp9f5wb9xfIjPa6OA==", + "dev": true, + "dependencies": { + "@headlessui/react": "^2.1.2", + "clsx": "^2.0.0", + "escape-string-regexp": "^5.0.0", + "flexsearch": "^0.7.43", + "next-themes": "^0.3.0", + "scroll-into-view-if-needed": "^3.1.0", + "zod": "^3.22.3" + }, + "peerDependencies": { + "next": ">=13", + "nextra": "3.0.13", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "dev": true, + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-to-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.0.0.tgz", + "integrity": "sha512-76YnmsbfrYp0tMsWxM0RNX0Vs+x8JxpJGu6B/jDn4lW8+laiTcKmKi9MeMh4UikO4RkJ1oqURoDy9bXJmMXS6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/nebrelbug/npm-to-yarn?sponsor=1" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "dev": true, + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", + "integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/package-manager-detector": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.2.tgz", + "integrity": "sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "dev": true, + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "dev": true + }, + "node_modules/parse5": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "dev": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", + "dev": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "dev": true + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "dev": true, + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", + "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "dev": true + }, + "node_modules/regexpu-core": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz", + "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==", + "dev": true, + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/rehype-katex": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", + "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-pretty-code": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.14.0.tgz", + "integrity": "sha512-hBeKF/Wkkf3zyUS8lal9RCUuhypDWLQc+h9UrP9Pav25FUm/AQAVh4m5gdvJxh4Oz+U+xKvdsV01p1LdvsZTiQ==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.4", + "hast-util-to-string": "^3.0.0", + "parse-numeric-range": "^1.3.0", + "rehype-parse": "^9.0.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "shiki": "^1.3.0" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "dev": true, + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-reading-time": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-reading-time/-/remark-reading-time-2.0.1.tgz", + "integrity": "sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==", + "dev": true, + "dependencies": { + "estree-util-is-identifier-name": "^2.0.0", + "estree-util-value-to-estree": "^1.3.0", + "reading-time": "^1.3.0", + "unist-util-visit": "^3.1.0" + } + }, + "node_modules/remark-reading-time/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true + }, + "node_modules/remark-reading-time/node_modules/estree-util-is-identifier-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz", + "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-reading-time/node_modules/estree-util-value-to-estree": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz", + "integrity": "sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==", + "dev": true, + "dependencies": { + "is-plain-obj": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/remark-reading-time/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/remark-reading-time/node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-reading-time/node_modules/unist-util-visit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz", + "integrity": "sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-reading-time/node_modules/unist-util-visit-parents": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz", + "integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "dev": true, + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "dev": true, + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "dev": true, + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "dev": true, + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "dev": true, + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "dev": true + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "dev": true, + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "dev": true, + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shiki": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", + "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.22.0", + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", + "@types/hast": "^3.0.4" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speech-rule-engine": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz", + "integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==", + "dev": true, + "dependencies": { + "commander": "9.2.0", + "wicked-good-xpath": "1.3.0", + "xmldom-sre": "0.1.31" + }, + "bin": { + "sre": "bin/sre" + } + }, + "node_modules/speech-rule-engine/node_modules/commander": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", + "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "dev": true, + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dev": true, + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", + "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==", + "dev": true + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==", + "dev": true, + "dependencies": { + "has-flag": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/tailwindcss/node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "dev": true + }, + "node_modules/title": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/title/-/title-3.5.3.tgz", + "integrity": "sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==", + "dev": true, + "dependencies": { + "arg": "1.0.0", + "chalk": "2.3.0", + "clipboardy": "1.2.2", + "titleize": "1.0.0" + }, + "bin": { + "title": "bin/title.js" + } + }, + "node_modules/titleize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.0.tgz", + "integrity": "sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "dev": true + }, + "node_modules/twoslash": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/twoslash/-/twoslash-0.2.12.tgz", + "integrity": "sha512-tEHPASMqi7kqwfJbkk7hc/4EhlrKCSLcur+TcvYki3vhIfaRMXnXjaYFgXpoZRbT6GdprD4tGuVBEmTpUgLBsw==", + "dev": true, + "dependencies": { + "@typescript/vfs": "^1.6.0", + "twoslash-protocol": "0.2.12" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/twoslash-protocol": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/twoslash-protocol/-/twoslash-protocol-0.2.12.tgz", + "integrity": "sha512-5qZLXVYfZ9ABdjqbvPc4RWMr7PrpPaaDSeaYY55vl/w1j6H6kzsWK/urAEIXlzYlyrFmyz1UbwIt+AA0ck+wbg==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", + "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/wicked-good-xpath": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz", + "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/xmldom-sre": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz", + "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==", + "dev": true, + "engines": { + "node": ">=0.1" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "dev": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/website/package.json b/website/package.json new file mode 100644 index 0000000000..8e47515861 --- /dev/null +++ b/website/package.json @@ -0,0 +1,28 @@ +{ + "name": "website", + "version": "0.0.0", + "description": "The GraphQL.JS documentation website", + "type": "module", + "private": true, + "directories": { + "doc": "docs" + }, + "scripts": { + "build": "next build", + "dev": "next" + }, + "devDependencies": { + "@svgr/webpack": "^8.1.0", + "@tailwindcss/typography": "^0.5.10", + "@types/node": "^22.7.5", + "autoprefixer": "^10.4.20", + "next": "^14.2.15", + "nextra": "^3.0.13", + "nextra-theme-docs": "^3.0.13", + "postcss": "^8.4.47", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + } +} diff --git a/website/pages/_app.tsx b/website/pages/_app.tsx new file mode 100644 index 0000000000..c50ff45c1e --- /dev/null +++ b/website/pages/_app.tsx @@ -0,0 +1,31 @@ +import type { AppProps } from 'next/app'; +import { Roboto_Flex, Roboto_Mono } from 'next/font/google'; + +import '../css/globals.css'; + +const robotoFlex = Roboto_Flex({ + subsets: ['latin'], +}); + +const robotoMono = Roboto_Mono({ + subsets: ['latin'], +}); + +// TODO: do we need google analytics? + +export default function App({ Component, pageProps }: AppProps) { + return ( + <> + + + + ); +} diff --git a/website/pages/_document.tsx b/website/pages/_document.tsx new file mode 100644 index 0000000000..e1e9cbbb75 --- /dev/null +++ b/website/pages/_document.tsx @@ -0,0 +1,13 @@ +import { Html, Head, Main, NextScript } from 'next/document'; + +export default function Document() { + return ( + + + +
+ + + + ); +} diff --git a/website/pages/_meta.ts b/website/pages/_meta.ts new file mode 100644 index 0000000000..b56f19ce54 --- /dev/null +++ b/website/pages/_meta.ts @@ -0,0 +1,39 @@ +const meta = { + index: '', + '-- 1': { + type: 'separator', + title: 'GraphQL.JS Tutorial', + }, + 'getting-started': '', + 'running-an-express-graphql-server': '', + 'graphql-clients': '', + 'basic-types': '', + 'passing-arguments': '', + 'object-types': '', + 'mutations-and-input-types': '', + 'authentication-and-express-middleware': '', + '-- 2': { + type: 'separator', + title: 'Advanced Guides', + }, + 'constructing-types': '', + 'oneof-input-objects': 'OneOf input objects', + 'defer-stream': '', + '-- 3': { + type: 'separator', + title: 'FAQ', + }, + 'going-to-production': '', + 'api-v16': { + type: 'menu', + title: 'API', + items: { + 2: { + title: 'V16', + href: '/api-v16/graphql', + }, + }, + }, +}; + +export default meta; diff --git a/website/pages/api-v16/_meta.ts b/website/pages/api-v16/_meta.ts new file mode 100644 index 0000000000..075de90bca --- /dev/null +++ b/website/pages/api-v16/_meta.ts @@ -0,0 +1,12 @@ +const meta = { + graphql: '', + error: '', + execution: '', + language: '', + type: '', + utilities: '', + validation: '', + 'graphql-http': '', +}; + +export default meta; diff --git a/docs-old/APIReference-Errors.md b/website/pages/api-v16/error.mdx similarity index 55% rename from docs-old/APIReference-Errors.md rename to website/pages/api-v16/error.mdx index eccd0934ce..1338d321de 100644 --- a/docs-old/APIReference-Errors.md +++ b/website/pages/api-v16/error.mdx @@ -1,64 +1,63 @@ --- title: graphql/error -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/error/ -sublinks: formatError,GraphQLError,locatedError,syntaxError -next: /graphql-js/execution/ --- +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql/error` + The `graphql/error` module is responsible for creating and formatting GraphQL errors. You can import either from the `graphql/error` module, or from the root `graphql` module. For example: ```js import { GraphQLError } from 'graphql'; // ES6 -var { GraphQLError } = require('graphql'); // CommonJS +const { GraphQLError } = require('graphql'); // CommonJS ``` ## Overview -
    + ## Errors -### GraphQLError +### `GraphQLError` -```js +```ts class GraphQLError extends Error { - constructor( - message: string, - nodes?: Array, - stack?: ?string, - source?: Source, - positions?: Array, - originalError?: ?Error, - extensions?: ?{ [key: string]: mixed } - ) + constructor( + message: string, + nodes?: any[], + stack?: string, + source?: Source, + positions?: number[], + originalError?: Error, + extensions?: { [key: string]: mixed }, + ); } ``` @@ -66,42 +65,42 @@ A representation of an error that occurred within GraphQL. Contains information about where in the query the error occurred for debugging. Most commonly constructed with `locatedError` below. -### syntaxError +### `syntaxError` -```js +```ts function syntaxError( source: Source, position: number, - description: string + description: string, ): GraphQLError; ``` Produces a GraphQLError representing a syntax error, containing useful descriptive information about the syntax error's position in the source. -### locatedError +### `locatedError` -```js -function locatedError(error: ?Error, nodes: Array): GraphQLError { +```ts +function locatedError(error: Error, nodes: any[]): GraphQLError; ``` Given an arbitrary Error, presumably thrown while attempting to execute a GraphQL operation, produce a new GraphQLError aware of the location in the document responsible for the original Error. -### formatError +### `formatError` -```js -function formatError(error: GraphQLError): GraphQLFormattedError +```ts +function formatError(error: GraphQLError): GraphQLFormattedError; type GraphQLFormattedError = { - message: string, - locations: ?Array + message: string; + locations: GraphQLErrorLocation[]; }; type GraphQLErrorLocation = { - line: number, - column: number + line: number; + column: number; }; ``` diff --git a/docs-old/APIReference-Execution.md b/website/pages/api-v16/execution.mdx similarity index 50% rename from docs-old/APIReference-Execution.md rename to website/pages/api-v16/execution.mdx index 750c2889f8..2810ed183a 100644 --- a/docs-old/APIReference-Execution.md +++ b/website/pages/api-v16/execution.mdx @@ -1,27 +1,25 @@ --- title: graphql/execution -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/execution/ -sublinks: execute -next: /graphql-js/language/ --- +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql/execution` + The `graphql/execution` module is responsible for the execution phase of fulfilling a GraphQL request. You can import either from the `graphql/execution` module, or from the root `graphql` module. For example: ```js import { execute } from 'graphql'; // ES6 -var { execute } = require('graphql'); // CommonJS +const { execute } = require('graphql'); // CommonJS ``` ## Overview -
      + @@ -30,21 +28,25 @@ var { execute } = require('graphql'); // CommonJS ### execute -```js +```ts export function execute( schema: GraphQLSchema, documentAST: Document, rootValue?: mixed, contextValue?: mixed, - variableValues?: ?{[key: string]: mixed}, - operationName?: ?string -): MaybePromise + variableValues?: { [key: string]: mixed }, + operationName?: string, +): MaybePromise; type MaybePromise = Promise | T; -type ExecutionResult = { - data: ?Object; - errors?: Array; +interface ExecutionResult< + TData = ObjMap, + TExtensions = ObjMap, +> { + errors?: ReadonlyArray; + data?: TData | null; + extensions?: TExtensions; } ``` @@ -58,3 +60,25 @@ a GraphQLError will be thrown immediately explaining the invalid input. `ExecutionResult` represents the result of execution. `data` is the result of executing the query, `errors` is null if no errors occurred, and is a non-empty array if an error occurred. + +### executeSync + +```ts +export function executeSync( + schema: GraphQLSchema, + documentAST: Document, + rootValue?: mixed, + contextValue?: mixed, + variableValues?: { [key: string]: mixed }, + operationName?: string, +): ExecutionResult; + +type ExecutionResult = { + data: Object; + errors?: GraphQLError[]; +}; +``` + +This is a short-hand method that will call `execute` and when the response can +be returned synchronously it will be returned, when a `Promise` is returned this +method will throw an error. diff --git a/website/pages/api-v16/graphql-http.mdx b/website/pages/api-v16/graphql-http.mdx new file mode 100644 index 0000000000..73c36fd310 --- /dev/null +++ b/website/pages/api-v16/graphql-http.mdx @@ -0,0 +1,39 @@ +--- +title: graphql-http +--- + +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql-http` + +The [official `graphql-http` package](https://github.com/graphql/graphql-http) provides a simple way to create a fully compliant GraphQL server. It has a handler for Node.js native [`http`](https://nodejs.org/api/http.html), together with handlers for well-known frameworks like [Express](https://expressjs.com/), [Fastify](https://www.fastify.io/) and [Koa](https://koajs.com/); as well as handlers for different runtimes like [Deno](https://deno.land/) and [Bun](https://bun.sh/). + +## Express + +```js +import { createHandler } from 'graphql-http/lib/use/express'; // ES6 +const { createHandler } = require('graphql-http/lib/use/express'); // CommonJS +``` + +### createHandler + +```ts +function createHandler({ + schema, + rootValue, + context, + formatError, + validationRules, +}: { + rootValue?: any; + context?: any; + formatError?: Function; + validationRules?: any[]; +}): Handler; +``` + +Constructs an Express handler based on a GraphQL schema. + +See the [tutorial](/running-an-express-graphql-server/) for sample usage. + +See the [GitHub README](https://github.com/graphql/graphql-http) for more extensive documentation, including how to use `graphql-http` with other server frameworks and runtimes. diff --git a/website/pages/api-v16/graphql.mdx b/website/pages/api-v16/graphql.mdx new file mode 100644 index 0000000000..e6936f279c --- /dev/null +++ b/website/pages/api-v16/graphql.mdx @@ -0,0 +1,181 @@ +--- +title: graphql +--- + +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql` + +The `graphql` module exports a core subset of GraphQL functionality for creation +of GraphQL type systems and servers. + +```js +import { graphql } from 'graphql'; // ES6 +const { graphql } = require('graphql'); // CommonJS +``` + +## Overview + +### Entry Point + + + +### Schema + + + +### Type Definitions + + + +### Scalars + + + +### Errors + + + +## Entry Point + +### `graphql` + +```ts +function graphql( + schema: GraphQLSchema, + requestString: string, + rootValue?: any, + contextValue?: any, + variableValues?: { [key: string]: any }, + operationName?: string, +): Promise; + +interface ExecutionResult< + TData = ObjMap, + TExtensions = ObjMap, +> { + errors?: ReadonlyArray; + data?: TData | null; + extensions?: TExtensions; +} +``` + +The `graphql` function lexes, parses, validates and executes a GraphQL request. +It requires a `schema` and a `requestString`. Optional arguments include a +`rootValue`, which will get passed as the root value to the executor, a `contextValue`, +which will get passed to all resolve functions, +`variableValues`, which will get passed to the executor to provide values for +any variables in `requestString`, and `operationName`, which allows the caller +to specify which operation in `requestString` will be run, in cases where +`requestString` contains multiple top-level operations. + +## Schema + +See the [Type System API Reference](/type#schema). + +## Type Definitions + +See the [Type System API Reference](/type#definitions). + +## Scalars + +See the [Type System API Reference](/type#scalars). + +## Errors + +See the [Errors API Reference](/error) diff --git a/docs-old/APIReference-Language.md b/website/pages/api-v16/language.mdx similarity index 65% rename from docs-old/APIReference-Language.md rename to website/pages/api-v16/language.mdx index 4d430c3787..897bb00927 100644 --- a/docs-old/APIReference-Language.md +++ b/website/pages/api-v16/language.mdx @@ -1,97 +1,87 @@ --- title: graphql/language -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/language/ -sublinks: BREAK,getLocation,Kind,lex,parse,parseValue,printSource,visit -next: /graphql-js/type/ --- +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql/language` + The `graphql/language` module is responsible for parsing and operating on the GraphQL language. You can import either from the `graphql/language` module, or from the root `graphql` module. For example: ```js import { Source } from 'graphql'; // ES6 -var { Source } = require('graphql'); // CommonJS +const { Source } = require('graphql'); // CommonJS ``` ## Overview -_Source_ +### Source -
        + -_Lexer_ +### Lexer -
          + -_Parser_ +### Parser -
            + -_Visitor_ +### Visitor -
              + -_Printer_ +### Printer -
                + @@ -99,32 +89,26 @@ _Printer_ ### Source -```js +```ts export class Source { - constructor(body: string, name?: string, locationOffset?: Location) -} - -type Location = { - line: number; - column: number; + constructor(body: string, name?: string); } ``` -A representation of source input to GraphQL. The `name` and `locationOffset` parameters are -optional, but they are useful for clients who store GraphQL documents in source files. -For example, if the GraphQL input starts at line 40 in a file named `Foo.graphql`, it might -be useful for `name` to be `"Foo.graphql"` and location to be `{ line: 40, column: 1 }`. -The `line` and `column` properties in `locationOffset` are 1-indexed. +A representation of source input to GraphQL. The name is optional, +but is mostly useful for clients who store GraphQL documents in +source files; for example, if the GraphQL input is in a file Foo.graphql, +it might be useful for name to be "Foo.graphql". ### getLocation -```js -function getLocation(source: Source, position: number): SourceLocation +```ts +function getLocation(source: Source, position: number): SourceLocation; type SourceLocation = { line: number; column: number; -} +}; ``` Takes a Source and a UTF-8 character offset, and returns the corresponding @@ -132,9 +116,9 @@ line and column as a SourceLocation. ## Lexer -### lex +### `lex` -```js +```ts function lex(source: Source): Lexer; type Lexer = (resetPosition?: number) => Token; @@ -143,42 +127,42 @@ export type Token = { kind: number; start: number; end: number; - value: ?string; + value: string; }; ``` Given a Source object, this returns a Lexer for that source. -A Lexer is a function that acts as a generator in that every time +A Lexer is a function that acts like a generator in that every time it is called, it returns the next token in the Source. Assuming the source lexes, the final Token emitted by the lexer will be of kind EOF, after which the lexer will repeatedly return EOF tokens whenever called. -The argument to the lexer function is optional and can be used to +The argument to the lexer function is optional, and can be used to rewind or fast forward the lexer to a new position in the source. ## Parser -### parse +### `parse` -```js +```ts export function parse( source: Source | string, - options?: ParseOptions -): Document + options?: ParseOptions, +): Document; ``` Given a GraphQL source, parses it into a Document. Throws GraphQLError if a syntax error is encountered. -### parseValue +### `parseValue` -```js +```ts export function parseValue( source: Source | string, - options?: ParseOptions -): Value + options?: ParseOptions, +): Value; ``` Given a string containing a GraphQL value, parse the AST for that value. @@ -188,19 +172,19 @@ Throws GraphQLError if a syntax error is encountered. This is useful within tools that operate upon GraphQL Values directly and in isolation of complete GraphQL documents. -### Kind +### `Kind` An enum that describes the different kinds of AST nodes. ## Visitor -### visit +### `visit` -```js -function visit(root, visitor, keyMap) +```ts +function visit(root, visitor, keyMap); ``` -visit() will walk through an AST using a depth-first traversal, calling +visit() will walk through an AST using a depth first traversal, calling the visitor's enter function at each node in the traversal, and calling the leave function after visiting that node and all of its child nodes. @@ -214,7 +198,7 @@ a new version of the AST with the changes applied will be returned from the visit function. ```js -var editedAST = visit(ast, { +const editedAST = visit(ast, { enter(node, key, parent, path, ancestors) { // @return // undefined: no action @@ -236,10 +220,10 @@ var editedAST = visit(ast, { Alternatively to providing enter() and leave() functions, a visitor can instead provide functions named the same as the kinds of AST nodes, or -enter/leave visitors at a named key, leading to four permutations of the +enter/leave visitors at a named key, leading to four permutations of visitor API: -1. Named visitors triggered when entering a node of a specific kind. +1. Named visitors triggered when entering a node a specific kind. ```js visit(ast, { @@ -257,11 +241,11 @@ visit(ast, { Kind: { enter(node) { // enter the "Kind" node - } + }, leave(node) { // leave the "Kind" node - } - } + }, + }, }); ``` @@ -295,16 +279,16 @@ visit(ast, { }); ``` -### BREAK +### `BREAK` The sentinel `BREAK` value described in the documentation of `visitor`. ## Printer -### print +### `print` -```js -function print(ast): string +```ts +function print(ast): string; ``` Converts an AST into a string, using one set of reasonable diff --git a/docs-old/APIReference-TypeSystem.md b/website/pages/api-v16/type.mdx similarity index 57% rename from docs-old/APIReference-TypeSystem.md rename to website/pages/api-v16/type.mdx index 5b5047c349..4ab3d7d1a2 100644 --- a/docs-old/APIReference-TypeSystem.md +++ b/website/pages/api-v16/type.mdx @@ -1,168 +1,157 @@ --- title: graphql/type -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/type/ -sublinks: getNamedType,getNullableType,GraphQLBoolean,GraphQLEnumType,GraphQLFloat,GraphQLID,GraphQLInputObjectType,GraphQLInt,GraphQLInterfaceType,GraphQLList,GraphQLNonNull,GraphQLObjectType,GraphQLScalarType,GraphQLSchema,GraphQLString,GraphQLUnionType,isAbstractType,isCompositeType,isInputType,isLeafType,isOutputType -next: /graphql-js/utilities/ --- +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql/type` + The `graphql/type` module is responsible for defining GraphQL types and schema. You can import either from the `graphql/type` module, or from the root `graphql` module. For example: ```js import { GraphQLSchema } from 'graphql'; // ES6 -var { GraphQLSchema } = require('graphql'); // CommonJS +const { GraphQLSchema } = require('graphql'); // CommonJS ``` ## Overview -_Schema_ +### Schema -
                  + -_Definitions_ +### Definitions -
                    + -_Predicates_ +### Predicates -
                      + -_Un-modifiers_ +### Un-modifiers -
                        + -_Scalars_ +### Scalars -
                          + @@ -170,15 +159,15 @@ _Scalars_ ### GraphQLSchema -```js +```ts class GraphQLSchema { - constructor(config: GraphQLSchemaConfig) + constructor(config: GraphQLSchemaConfig); } type GraphQLSchemaConfig = { query: GraphQLObjectType; - mutation?: ?GraphQLObjectType; -} + mutation?: GraphQLObjectType; +}; ``` A Schema is created by supplying the root types of each type of operation, @@ -188,9 +177,9 @@ validator and executor. #### Example ```js -var MyAppSchema = new GraphQLSchema({ - query: MyAppQueryRootType - mutation: MyAppMutationRootType +const MyAppSchema = new GraphQLSchema({ + query: MyAppQueryRootType, + mutation: MyAppMutationRootType, }); ``` @@ -198,19 +187,22 @@ var MyAppSchema = new GraphQLSchema({ ### GraphQLScalarType -```js -class GraphQLScalarType { - constructor(config: GraphQLScalarTypeConfig) +```ts +class GraphQLScalarType { + constructor(config: GraphQLScalarTypeConfig); } -type GraphQLScalarTypeConfig = { +type GraphQLScalarTypeConfig = { name: string; - description?: ?string; - specifiedByURL?: string; - serialize: (value: mixed) => ?InternalType; - parseValue?: (value: mixed) => ?InternalType; - parseLiteral?: (valueAST: Value) => ?InternalType; -} + description?: string; + specifiedByURL?: Maybe; + serialize: (outputValue: unknown) => ExternalType; + parseValue?: (inputValue: unknown) => InternalType; + parseLiteral?: ( + valueAST: Value, + variables?: Maybe>, + ) => InternalType; +}; ``` The leaf values of any request and input values to arguments are @@ -220,37 +212,48 @@ functions used to ensure validity. #### Example ```js -var OddType = new GraphQLScalarType({ +const OddType = new GraphQLScalarType({ name: 'Odd', - serialize: oddValue, - parseValue: oddValue, + // Can be used to link to a specification + // for this scalar, for instance the JSON + // specification. + specifiedByURL: '', + description: + 'This custom scalar will only return a value if the passed in value is an odd integer, when it's not it will return null.' + serialize: (outputValue) => { + // This function gets called for response-data, the application returns data + // for a property and in the schema we see that this value has the "Odd" type. + return typeof outputValue === 'number' && outputValue % 2 === 1 ? value : null; + }, + parseValue: (inputValue) => { + // This function gets called for input-data, i.e. variables being passed in + return typeof inputValue === 'number' && outputValue % 2 === 1 ? value : null; + }, parseLiteral(ast) { + // This function gets called when the value is passed in as a literal on the + // Executable GraphQL Document if (ast.kind === Kind.INT) { return oddValue(parseInt(ast.value, 10)); } return null; }, }); - -function oddValue(value) { - return value % 2 === 1 ? value : null; -} ``` ### GraphQLObjectType -```js +```ts class GraphQLObjectType { - constructor(config: GraphQLObjectTypeConfig) + constructor(config: GraphQLObjectTypeConfig); } type GraphQLObjectTypeConfig = { name: string; - interfaces?: GraphQLInterfacesThunk | Array; + interfaces?: GraphQLInterfacesThunk | GraphQLInterfaceType[]; fields: GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap; isTypeOf?: (value: any, info?: GraphQLResolveInfo) => boolean; - description?: ?string -} + description?: string; +}; type GraphQLInterfacesThunk = () => Array; @@ -259,30 +262,30 @@ type GraphQLFieldConfigMapThunk = () => GraphQLFieldConfigMap; // See below about resolver functions. type GraphQLFieldResolveFn = ( source?: any, - args?: {[argName: string]: any}, + args?: { [argName: string]: any }, context?: any, - info?: GraphQLResolveInfo -) => any + info?: GraphQLResolveInfo, +) => any; type GraphQLResolveInfo = { - fieldName: string, - fieldNodes: Array, - returnType: GraphQLOutputType, - parentType: GraphQLCompositeType, - schema: GraphQLSchema, - fragments: { [fragmentName: string]: FragmentDefinition }, - rootValue: any, - operation: OperationDefinition, - variableValues: { [variableName: string]: any }, -} + fieldName: string; + fieldNodes: Array; + returnType: GraphQLOutputType; + parentType: GraphQLCompositeType; + schema: GraphQLSchema; + fragments: { [fragmentName: string]: FragmentDefinition }; + rootValue: any; + operation: OperationDefinition; + variableValues: { [variableName: string]: any }; +}; type GraphQLFieldConfig = { type: GraphQLOutputType; args?: GraphQLFieldConfigArgumentMap; resolve?: GraphQLFieldResolveFn; deprecationReason?: string; - description?: ?string; -} + description?: string; +}; type GraphQLFieldConfigArgumentMap = { [argName: string]: GraphQLArgumentConfig; @@ -291,8 +294,8 @@ type GraphQLFieldConfigArgumentMap = { type GraphQLArgumentConfig = { type: GraphQLInputType; defaultValue?: any; - description?: ?string; -} + description?: string; +}; type GraphQLFieldConfigMap = { [fieldName: string]: GraphQLFieldConfig; @@ -315,7 +318,7 @@ that value can always be referenced with `this`. #### Examples ```js -var AddressType = new GraphQLObjectType({ +const AddressType = new GraphQLObjectType({ name: 'Address', fields: { street: { type: GraphQLString }, @@ -329,7 +332,7 @@ var AddressType = new GraphQLObjectType({ }, }); -var PersonType = new GraphQLObjectType({ +const PersonType = new GraphQLObjectType({ name: 'Person', fields: () => ({ name: { type: GraphQLString }, @@ -340,16 +343,16 @@ var PersonType = new GraphQLObjectType({ ### GraphQLInterfaceType -```js +```ts class GraphQLInterfaceType { - constructor(config: GraphQLInterfaceTypeConfig) + constructor(config: GraphQLInterfaceTypeConfig); } type GraphQLInterfaceTypeConfig = { - name: string, - fields: GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap, - resolveType?: (value: any, info?: GraphQLResolveInfo) => ?GraphQLObjectType, - description?: ?string + name: string; + fields: GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap; + resolveType?: (value: any, info?: GraphQLResolveInfo) => GraphQLObjectType; + description?: string; }; ``` @@ -361,7 +364,7 @@ when the field is resolved. #### Example ```js -var EntityType = new GraphQLInterfaceType({ +const EntityType = new GraphQLInterfaceType({ name: 'Entity', fields: { name: { type: GraphQLString }, @@ -371,19 +374,19 @@ var EntityType = new GraphQLInterfaceType({ ### GraphQLUnionType -```js +```ts class GraphQLUnionType { - constructor(config: GraphQLUnionTypeConfig) + constructor(config: GraphQLUnionTypeConfig); } type GraphQLUnionTypeConfig = { - name: string, - types: GraphQLObjectsThunk | Array, - resolveType?: (value: any, info?: GraphQLResolveInfo) => ?GraphQLObjectType; - description?: ?string; + name: string; + types: GraphQLObjectsThunk | GraphQLObjectType[]; + resolveType?: (value: any, info?: GraphQLResolveInfo) => GraphQLObjectType; + description?: string; }; -type GraphQLObjectsThunk = () => Array; +type GraphQLObjectsThunk = () => GraphQLObjectType[]; ``` When a field can return one of a heterogeneous set of types, a Union type @@ -393,7 +396,7 @@ to determine which type is actually used when the field is resolved. ### Example ```js -var PetType = new GraphQLUnionType({ +const PetType = new GraphQLUnionType({ name: 'Pet', types: [DogType, CatType], resolveType(value) { @@ -409,16 +412,16 @@ var PetType = new GraphQLUnionType({ ### GraphQLEnumType -```js +```ts class GraphQLEnumType { - constructor(config: GraphQLEnumTypeConfig) + constructor(config: GraphQLEnumTypeConfig); } type GraphQLEnumTypeConfig = { name: string; values: GraphQLEnumValueConfigMap; - description?: ?string; -} + description?: string; +}; type GraphQLEnumValueConfigMap = { [valueName: string]: GraphQLEnumValueConfig; @@ -427,15 +430,15 @@ type GraphQLEnumValueConfigMap = { type GraphQLEnumValueConfig = { value?: any; deprecationReason?: string; - description?: ?string; -} + description?: string; +}; type GraphQLEnumValueDefinition = { name: string; value?: any; deprecationReason?: string; - description?: ?string; -} + description?: string; +}; ``` Some leaf values of requests and input values are Enums. GraphQL serializes @@ -448,7 +451,7 @@ will be used as its internal value. #### Example ```js -var RGBType = new GraphQLEnumType({ +const RGBType = new GraphQLEnumType({ name: 'RGB', values: { RED: { value: 0 }, @@ -460,24 +463,27 @@ var RGBType = new GraphQLEnumType({ ### GraphQLInputObjectType -```js +```ts class GraphQLInputObjectType { - constructor(config: GraphQLInputObjectConfig) + constructor(config: GraphQLInputObjectConfig); } type GraphQLInputObjectConfig = { name: string; - fields: GraphQLInputObjectConfigFieldMapThunk | GraphQLInputObjectConfigFieldMap; - description?: ?string; -} + fields: + | GraphQLInputObjectConfigFieldMapThunk + | GraphQLInputObjectConfigFieldMap; + description?: string; +}; -type GraphQLInputObjectConfigFieldMapThunk = () => GraphQLInputObjectConfigFieldMap; +type GraphQLInputObjectConfigFieldMapThunk = + () => GraphQLInputObjectConfigFieldMap; type GraphQLInputObjectFieldConfig = { type: GraphQLInputType; defaultValue?: any; - description?: ?string; -} + description?: string; +}; type GraphQLInputObjectConfigFieldMap = { [fieldName: string]: GraphQLInputObjectFieldConfig; @@ -487,8 +493,8 @@ type GraphQLInputObjectField = { name: string; type: GraphQLInputType; defaultValue?: any; - description?: ?string; -} + description?: string; +}; type GraphQLInputObjectFieldMap = { [fieldName: string]: GraphQLInputObjectField; @@ -503,7 +509,7 @@ Using `NonNull` will ensure that a value must be provided by the query #### Example ```js -var GeoPoint = new GraphQLInputObjectType({ +const GeoPoint = new GraphQLInputObjectType({ name: 'GeoPoint', fields: { lat: { type: new GraphQLNonNull(GraphQLFloat) }, @@ -515,9 +521,9 @@ var GeoPoint = new GraphQLInputObjectType({ ### GraphQLList -```js +```ts class GraphQLList { - constructor(type: GraphQLType) + constructor(type: GraphQLType); } ``` @@ -528,20 +534,20 @@ an object type. #### Example ```js -var PersonType = new GraphQLObjectType({ +const PersonType = new GraphQLObjectType({ name: 'Person', fields: () => ({ - parents: { type: new GraphQLList(Person) }, - children: { type: new GraphQLList(Person) }, + parents: { type: new GraphQLList(PersonType) }, + children: { type: new GraphQLList(PersonType) }, }), }); ``` ### GraphQLNonNull -```js +```ts class GraphQLNonNull { - constructor(type: GraphQLType) + constructor(type: GraphQLType); } ``` @@ -554,7 +560,7 @@ usually the id field of a database row will never be null. #### Example ```js -var RowType = new GraphQLObjectType({ +const RowType = new GraphQLObjectType({ name: 'Row', fields: () => ({ id: { type: new GraphQLNonNull(String) }, @@ -567,39 +573,39 @@ var RowType = new GraphQLObjectType({ ### isInputType ```js -function isInputType(type: ?GraphQLType): boolean +function isInputType(type: GraphQLType): boolean ``` These types may be used as input types for arguments and directives. ### isOutputType -```js -function isOutputType(type: ?GraphQLType): boolean +```ts +function isOutputType(type: GraphQLType): boolean; ``` These types may be used as output types as the result of fields ### isLeafType -```js -function isLeafType(type: ?GraphQLType): boolean +```ts +function isLeafType(type: GraphQLType): boolean; ``` These types may describe types which may be leaf values ### isCompositeType -```js -function isCompositeType(type: ?GraphQLType): boolean +```ts +function isCompositeType(type: GraphQLType): boolean; ``` These types may describe the parent context of a selection set ### isAbstractType -```js -function isAbstractType(type: ?GraphQLType): boolean +```ts +function isAbstractType(type: GraphQLType): boolean; ``` These types may describe a combination of object types @@ -608,8 +614,8 @@ These types may describe a combination of object types ### getNullableType -```js -function getNullableType(type: ?GraphQLType): ?GraphQLNullableType +```ts +function getNullableType(type: GraphQLType): GraphQLNullableType; ``` If a given type is non-nullable, this strips the non-nullability and @@ -617,8 +623,8 @@ returns the underlying type. ### getNamedType -```js -function getNamedType(type: ?GraphQLType): ?GraphQLNamedType +```ts +function getNamedType(type: GraphQLType): GraphQLNamedType; ``` If a given type is non-nullable or a list, this repeated strips the @@ -628,40 +634,40 @@ non-nullability and list wrappers and returns the underlying type. ### GraphQLInt -```js -var GraphQLInt: GraphQLScalarType; +```ts +let GraphQLInt: GraphQLScalarType; ``` A `GraphQLScalarType` that represents an int. ### GraphQLFloat -```js -var GraphQLFloat: GraphQLScalarType; +```ts +let GraphQLFloat: GraphQLScalarType; ``` A `GraphQLScalarType` that represents a float. ### GraphQLString -```js -var GraphQLString: GraphQLScalarType; +```ts +let GraphQLString: GraphQLScalarType; ``` A `GraphQLScalarType` that represents a string. ### GraphQLBoolean -```js -var GraphQLBoolean: GraphQLScalarType; +```ts +let GraphQLBoolean: GraphQLScalarType; ``` A `GraphQLScalarType` that represents a boolean. ### GraphQLID -```js -var GraphQLID: GraphQLScalarType; +```ts +let GraphQLID: GraphQLScalarType; ``` A `GraphQLScalarType` that represents an ID. diff --git a/website/pages/api-v16/utilities.mdx b/website/pages/api-v16/utilities.mdx new file mode 100644 index 0000000000..ba8533c220 --- /dev/null +++ b/website/pages/api-v16/utilities.mdx @@ -0,0 +1,232 @@ +--- +title: graphql/utilities +--- + +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql/utilities` + +The `graphql/utilities` module contains common useful computations to use with +the GraphQL language and type objects. You can import either from the `graphql/utilities` module, or from the root `graphql` module. For example: + +```js +import { introspectionQuery } from 'graphql'; // ES6 +const { introspectionQuery } = require('graphql'); // CommonJS +``` + +## Overview + +### Introspection + + + +### Schema Language + + + +### Visitors + + + +### Value Validation + + + +## Introspection + +### introspectionQuery + +```js +const introspectionQuery: string; +``` + +A GraphQL query that queries a server's introspection system for enough +information to reproduce that server's type system. + +### `buildClientSchema` + +```ts +function buildClientSchema(introspection: IntrospectionQuery): GraphQLSchema; +``` + +Build a GraphQLSchema for use by client tools. + +Given the result of a client running the introspection query, creates and +returns a GraphQLSchema instance which can be then used with all GraphQL.js +tools, but cannot be used to execute a query, as introspection does not +represent the "resolver", "parse" or "serialize" functions or any other +server-internal mechanisms. + +## Schema Representation + +### `buildSchema` + +```ts +function buildSchema(source: string | Source): GraphQLSchema; +``` + +Creates a GraphQLSchema object from GraphQL schema language. The schema will use default resolvers. For more detail on the GraphQL schema language, see the [schema language docs](/learn/schema/) or this [schema language cheat sheet](https://wehavefaces.net/graphql-shorthand-notation-cheatsheet-17cd715861b6#.9oztv0a7n). + +### `printSchema` + +```ts +function printSchema(schema: GraphQLSchema): string; +``` + +Prints the provided schema in the Schema Language format. + +### `printIntrospectionSchema` + +```ts +function printIntrospectionSchema(schema: GraphQLSchema): string; +``` + +Prints the built-in introspection schema in the Schema Language format. + +### `buildASTSchema` + +```ts +function buildASTSchema( + ast: SchemaDocument, + queryTypeName: string, + mutationTypeName: string, +): GraphQLSchema; +``` + +This takes the ast of a schema document produced by `parseSchemaIntoAST` in +`graphql/language/schema` and constructs a GraphQLSchema instance which can be +then used with all GraphQL.js tools, but cannot be used to execute a query, as +introspection does not represent the "resolver", "parse" or "serialize" +functions or any other server-internal mechanisms. + +### `typeFromAST` + +```ts +function typeFromAST(schema: GraphQLSchema, inputTypeAST: Type): GraphQLType; +``` + +Given the name of a Type as it appears in a GraphQL AST and a Schema, return the +corresponding GraphQLType from that schema. + +### `astFromValue` + +```ts +function astFromValue(value: any, type: GraphQLInputType): Value; +``` + +Produces a GraphQL Input Value AST given a JavaScript value. + +Optionally, a GraphQL type may be provided, which will be used to +disambiguate between value primitives. + +## Visitors + +### `TypeInfo` + +```ts +class TypeInfo { + constructor(schema: GraphQLSchema); + getType(): GraphQLOutputType; + getParentType(): GraphQLCompositeType; + getInputType(): GraphQLInputType; + getFieldDef(): GraphQLFieldDefinition; + getDirective(): GraphQLDirective; + getArgument(): GraphQLArgument; +} +``` + +TypeInfo is a utility class which, given a GraphQL schema, can keep track +of the current field and type definitions at any point in a GraphQL document +AST during a recursive descent by calling `enter(node)` and `leave(node)`. + +## Value Validation + +### `isValidJSValue` + +```ts +function isValidJSValue(value: any, type: GraphQLInputType): string[]; +``` + +Given a JavaScript value and a GraphQL type, determine if the value will be +accepted for that type. This is primarily useful for validating the +runtime values of query variables. + +### `isValidLiteralValue` + +```ts +function isValidLiteralValue(type: GraphQLInputType, valueAST: Value): string[]; +``` + +Utility for validators which determines if a value literal AST is valid given +an input type. + +Note that this only validates literal values, variables are assumed to +provide values of the correct type. diff --git a/docs-old/APIReference-Validation.md b/website/pages/api-v16/validation.mdx similarity index 70% rename from docs-old/APIReference-Validation.md rename to website/pages/api-v16/validation.mdx index e9c28ebbe0..6b45caec6a 100644 --- a/docs-old/APIReference-Validation.md +++ b/website/pages/api-v16/validation.mdx @@ -1,46 +1,45 @@ --- title: graphql/validation -layout: ../_core/GraphQLJSLayout -category: API Reference -permalink: /graphql-js/validation/ -sublinks: specifiedRules,validate --- +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# `graphql/validation` + The `graphql/validation` module fulfills the Validation phase of fulfilling a GraphQL result. You can import either from the `graphql/validation` module, or from the root `graphql` module. For example: ```js import { validate } from 'graphql/validation'; // ES6 -var { validate } = require('graphql/validation'); // CommonJS +const { validate } = require('graphql/validation'); // CommonJS ``` ## Overview -
                            + ## Validation -### validate +### `validate` -```js +```ts function validate( schema: GraphQLSchema, ast: Document, - rules?: Array -): Array + rules?: any[], +): GraphQLError[]; ``` Implements the "Validation" section of the spec. @@ -59,10 +58,10 @@ Visitors can also supply `visitSpreadFragments: true` which will alter the behavior of the visitor to skip over top level defined fragments, and instead visit those fragments at every point a spread is encountered. -### specifiedRules +### `specifiedRules` -```js -var specifiedRules: Array<(context: ValidationContext): any> +```ts +let specifiedRules: Array<(context: ValidationContext) => any>; ``` This set includes all validation rules defined by the GraphQL spec diff --git a/website/docs/tutorials/authentication-and-express-middleware.md b/website/pages/authentication-and-express-middleware.mdx similarity index 50% rename from website/docs/tutorials/authentication-and-express-middleware.md rename to website/pages/authentication-and-express-middleware.mdx index 15a413de50..c03f444496 100644 --- a/website/docs/tutorials/authentication-and-express-middleware.md +++ b/website/pages/authentication-and-express-middleware.mdx @@ -1,52 +1,101 @@ --- title: Authentication and Express Middleware -sidebar_label: Authentication & Middleware +sidebarTitle: Authentication & Middleware --- -It's simple to use any Express middleware in conjunction with `express-graphql`. In particular, this is a great pattern for handling authentication. +import { Tabs } from 'nextra/components'; + +It's simple to use any Express middleware in conjunction with `graphql-http`. In particular, this is a great pattern for handling authentication. To use middleware with a GraphQL resolver, just use the middleware like you would with a normal Express app. The `request` object is then available as the second argument in any resolver. For example, let's say we wanted our server to log the IP address of every request, and we also want to write an API that returns the IP address of the caller. We can do the former with middleware, and the latter by accessing the `request` object in a resolver. Here's server code that implements this: + + ```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { buildSchema } = require('graphql'); -var schema = buildSchema(` - type Query { - ip: String - } -`); +const schema = buildSchema(`type Query { ip: String }`); function loggingMiddleware(req, res, next) { console.log('ip:', req.ip); next(); } -var root = { - ip: function (args, request) { - return request.ip; +const root = { + ip(args, context) { + return context.ip; }, }; -var app = express(); +const app = express(); app.use(loggingMiddleware); -app.use( +app.all( '/graphql', - graphqlHTTP({ + createHandler({ schema: schema, rootValue: root, - graphiql: true, + context: (req) => ({ + ip: req.raw.ip, + }), }), ); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); + +```` + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { + GraphQLObjectType, + GraphQLSchema, + GraphQLString, +} = require('graphql'); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { ip: { type: GraphQLString } }, + }), }); -``` -In a REST API, authentication is often handled with a header, that contains an auth token which proves what user is making this request. Express middleware processes these headers and puts authentication data on the Express `request` object. Some middleware modules that handle authentication like this are [Passport](http://passportjs.org/), [express-jwt](https://github.com/auth0/express-jwt), and [express-session](https://github.com/expressjs/session). Each of these modules works with `express-graphql`. +function loggingMiddleware(req, res, next) { + console.log('ip:', req.ip); + next(); +} + +const root = { + ip(args, context) { + return context.ip; + }, +}; + +const app = express(); +app.use(loggingMiddleware); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + context: (req) => ({ + ip: req.raw.ip, + }), + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); +```` + + + + +In a REST API, authentication is often handled with a header, that contains an auth token which proves what user is making this request. Express middleware processes these headers and puts authentication data on the Express `request` object. Some middleware modules that handle authentication like this are [Passport](http://passportjs.org/), [express-jwt](https://github.com/auth0/express-jwt), and [express-session](https://github.com/expressjs/session). Each of these modules works with `graphql-http`. If you aren't familiar with any of these authentication mechanisms, we recommend using `express-jwt` because it's simple without sacrificing any future flexibility. diff --git a/website/pages/basic-types.mdx b/website/pages/basic-types.mdx new file mode 100644 index 0000000000..b6480a979d --- /dev/null +++ b/website/pages/basic-types.mdx @@ -0,0 +1,115 @@ +--- +title: Basic Types +--- + +import { Tabs } from 'nextra/components'; + +In most situations, all you need to do is to specify the types for your API using the GraphQL schema language, taken as an argument to the `buildSchema` function. + +The GraphQL schema language supports the scalar types of `String`, `Int`, `Float`, `Boolean`, and `ID`, so you can use these directly in the schema you pass to `buildSchema`. + +By default, every type is nullable - it's legitimate to return `null` as any of the scalar types. Use an exclamation point to indicate a type cannot be nullable, so `String!` is a non-nullable string. + +To use a list type, surround the type in square brackets, so `[Int]` is a list of integers. + +Each of these types maps straightforwardly to JavaScript, so you can just return plain old JavaScript objects in APIs that return these types. Here's an example that shows how to use some of these basic types: + + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { buildSchema } = require('graphql'); + +// Construct a schema, using GraphQL schema language +const schema = buildSchema(` + type Query { + quoteOfTheDay: String + random: Float! + rollThreeDice: [Int] + } +`); + +// The root provides a resolver function for each API endpoint +const root = { + quoteOfTheDay() { + return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within'; + }, + random() { + return Math.random(); + }, + rollThreeDice() { + return [1, 2, 3].map((\_) => 1 + Math.floor(Math.random() \* 6)); + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); + +```` + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { + GraphQLObjectType, + GraphQLSchema, + GraphQLString, + GraphQLFloat, + GraphQLList, +} = require('graphql'); + +// Construct a schema +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + quoteOfTheDay: { type: GraphQLString }, + random: { type: GraphQLFloat }, + rollThreeDice: { type: new GraphQLList(GraphQLFloat) }, + }, + }), +}); + +// The root provides a resolver function for each API endpoint +const root = { + quoteOfTheDay() { + return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within'; + }, + random() { + return Math.random(); + }, + rollThreeDice() { + return [1, 2, 3].map((_) => 1 + Math.floor(Math.random() * 6)); + }, +}; + +const app = express(); + +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); + +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); +```` + + + + +If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs. + +These examples show you how to call APIs that return different types. To send different types of data into an API, you will also need to learn about [passing arguments to a GraphQL API](/passing-arguments/). diff --git a/website/pages/constructing-types.mdx b/website/pages/constructing-types.mdx new file mode 100644 index 0000000000..2ae7b93872 --- /dev/null +++ b/website/pages/constructing-types.mdx @@ -0,0 +1,124 @@ +--- +title: Constructing Types +--- + +import { Tabs } from 'nextra/components'; + +For many apps, you can define a fixed schema when the application starts, and define it using GraphQL schema language. In some cases, it's useful to construct a schema programmatically. You can do this using the `GraphQLSchema` constructor. + +When you are using the `GraphQLSchema` constructor to create a schema, instead of defining `Query` and `Mutation` types solely using schema language, you create them as separate object types. + +For example, let's say we are building a simple API that lets you fetch user data for a few hardcoded users based on an id. Using `buildSchema` we could write a server with: + + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { buildSchema } = require('graphql'); + +const schema = buildSchema(` +type User { + id: String + name: String +} + +type Query { + user(id: String): User +} +`); + +// Maps id to User object +const fakeDatabase = { + a: { + id: 'a', + name: 'alice', + }, + b: { + id: 'b', + name: 'bob', + }, +}; + +const root = { + user({ id }) { + return fakeDatabase[id]; + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); + +```` + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const graphql = require('graphql'); + +// Maps id to User object +const fakeDatabase = { + a: { + id: 'a', + name: 'alice', + }, + b: { + id: 'b', + name: 'bob', + }, +}; + +// Define the User type +const userType = new graphql.GraphQLObjectType({ + name: 'User', + fields: { + id: { type: graphql.GraphQLString }, + name: { type: graphql.GraphQLString }, + }, +}); + +// Define the Query type +const queryType = new graphql.GraphQLObjectType({ + name: 'Query', + fields: { + user: { + type: userType, + // `args` describes the arguments that the `user` query accepts + args: { + id: { type: graphql.GraphQLString }, + }, + resolve: (_, { id }) => { + return fakeDatabase[id]; + }, + }, + }, +}); + +const schema = new graphql.GraphQLSchema({ query: queryType }); + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); +```` + + + + +When we use the `GraphQLSchema` constructor method of creating the API, the root level resolvers are implemented on the `Query` and `Mutation` types rather than on a `root` object. + +This can be particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema. You might have a common format for something like creating and updating database records. This is also useful for implementing features like union types which don't map cleanly to ES6 classes and schema language. diff --git a/website/pages/defer-stream.mdx b/website/pages/defer-stream.mdx new file mode 100644 index 0000000000..166bcb3eb3 --- /dev/null +++ b/website/pages/defer-stream.mdx @@ -0,0 +1,38 @@ +--- +title: Enabling Defer & Stream +--- + +import { Callout } from 'nextra/components' + + + These exports are only available in v17 and beyond. + + +The `@defer` and `@stream` directives are not enabled by default. +In order to use these directives, you must add them to your GraphQL Schema and +use the `experimentalExecuteIncrementally` function instead of `execute`. + +```js +import { + GraphQLSchema, + GraphQLDeferDirective, + GraphQLStreamDirective, + specifiedDirectives, +} from 'graphql'; + +const schema = new GraphQLSchema({ + query, + directives: [ + ...specifiedDirectives, + GraphQLDeferDirective, + GraphQLStreamDirective, + ], +}); + +const result = experimentalExecuteIncrementally({ + schema, + document, +}); +``` + +If the `directives` option is passed to `GraphQLSchema`, the default directives will not be included. `specifiedDirectives` must be passed to ensure all standard directives are added in addition to `defer` & `stream`. diff --git a/website/pages/getting-started.mdx b/website/pages/getting-started.mdx new file mode 100644 index 0000000000..c84d1509ac --- /dev/null +++ b/website/pages/getting-started.mdx @@ -0,0 +1,112 @@ +--- +title: Getting Started With GraphQL.js +sidebarTitle: Getting Started +--- + +import { Tabs } from 'nextra/components'; + +{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */} + +# Getting Started With GraphQL.js + +## Prerequisites + +Before getting started, you should have Node v6 installed, although the examples should mostly work in previous versions of Node as well. +For this guide, we won't use any language features that require transpilation, but we will use some ES6 features like +[Promises](http://www.html5rocks.com/en/tutorials/es6/promises/), classes, +and arrow functions, so if you aren't familiar with them you might want to read up on them first. + +> Alternatively you can start from [this StackBlitz](https://stackblitz.com/edit/stackblitz-starters-znvgwr) - if you choose +> this route you can skip to [Basic Types](./basic-types.mdx). + +To create a new project and install GraphQL.js in your current directory: + +```sh npm2yarn +npm init +npm install graphql --save +``` + +## Writing Code + +To handle GraphQL queries, we need a schema that defines the `Query` type, and we need an API root with a function called a “resolver” for each API endpoint. For an API that just returns “Hello world!”, we can put this code in a file named `server.js`: + + + +```javascript +const { graphql, buildSchema } = require('graphql'); + +// Construct a schema, using GraphQL schema language +const schema = buildSchema(`type Query { hello: String } `); + +// The rootValue provides a resolver function for each API endpoint +const rootValue = { + hello() { + return 'Hello world!'; + }, +}; + +// Run the GraphQL query '{ hello }' and print out the response +graphql({ + schema, + source: '{ hello }', + rootValue, + }).then((response) => { + console.log(response); + }); +}); + +```` + + +```javascript +const { graphql, GraphQLSchema, GraphQLObjectType } = require('graphql'); + +// Construct a schema +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + hello: { type: GraphQLString }, + }, + }), +}); + +// The rootValue provides a resolver function for each API endpoint +const rootValue = { + hello() { + return 'Hello world!'; + }, +}; + +// Run the GraphQL query '{ hello }' and print out the response +graphql({ + schema, + source: '{ hello }', + rootValue, +}).then((response) => { + console.log(JSON.stringify(response, null, 2)); +}); +```` + + + + +If you run this with: + +```sh +node server.js +``` + +You should see the GraphQL response printed out: + +```json +{ + "data": { + "hello": "Hello world!" + } +} +``` + +Congratulations - you just executed a GraphQL query! + +For practical applications, you'll probably want to run GraphQL queries from an API server, rather than executing GraphQL with a command line tool. To use GraphQL for an API server over HTTP, check out [Running an Express GraphQL Server](/running-an-express-graphql-server/). diff --git a/website/pages/going-to-production.mdx b/website/pages/going-to-production.mdx new file mode 100644 index 0000000000..862932fb10 --- /dev/null +++ b/website/pages/going-to-production.mdx @@ -0,0 +1,126 @@ +--- +title: Going to Production +--- + +GraphQL.JS contains a few development checks which in production will cause slower performance and +an increase in bundle-size. Every bundler goes about these changes different, in here we'll list +out the most popular ones. + +## Bundler-specific configuration + +Here are some bundler-specific suggestions for configuring your bundler to remove `globalThis.process` and `process.env.NODE_ENV` on build time. + +### Vite + +```js +export default defineConfig({ + // ... + define: { + 'globalThis.process': JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('production'), + }, +}); +``` + +### Next.js + +```js +// ... +/** @type {import('next').NextConfig} */ +const nextConfig = { + webpack(config, { webpack }) { + config.plugins.push( + new webpack.DefinePlugin({ + 'globalThis.process': JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('production'), + }), + ); + return config; + }, +}; + +module.exports = nextConfig; +``` + +### create-react-app + +With `create-react-app`, you need to use a third-party package like [`craco`](https://craco.js.org/) to modify the bundler configuration. + +```js +const webpack = require('webpack'); +module.exports = { + webpack: { + plugins: [ + new webpack.DefinePlugin({ + 'globalThis.process': JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('production'), + }), + ], + }, +}; +``` + +### esbuild + +```json +{ + "define": { + "globalThis.process": true, + "process.env.NODE_ENV": "production" + } +} +``` + +### Webpack + +```js +config.plugins.push( + new webpack.DefinePlugin({ + 'globalThis.process': JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('production'), + }), +); +``` + +### Rollup + +```js +export default [ + { + // ... input, output, etc. + plugins: [ + minify({ + mangle: { + toplevel: true, + }, + compress: { + toplevel: true, + global_defs: { + '@globalThis.process': JSON.stringify(true), + '@process.env.NODE_ENV': JSON.stringify('production'), + }, + }, + }), + ], + }, +]; +``` + +### SWC + +```json filename=".swcrc" +{ + "jsc": { + "transform": { + "optimizer": { + "globals": { + "vars": { + "globalThis.process": true, + "process.env.NODE_ENV": "production" + } + } + } + } + } +} +``` diff --git a/website/docs/tutorials/graphql-clients.md b/website/pages/graphql-clients.mdx similarity index 66% rename from website/docs/tutorials/graphql-clients.md rename to website/pages/graphql-clients.mdx index 30e9686131..342193450f 100644 --- a/website/docs/tutorials/graphql-clients.md +++ b/website/pages/graphql-clients.mdx @@ -1,11 +1,10 @@ --- title: GraphQL Clients -category: GraphQL.js Tutorial --- -Since a GraphQL API has more underlying structure than a REST API, there are more powerful clients like [Relay](https://facebook.github.io/relay/) which can automatically handle batching, caching, and other features. But you don't need a complex client to call a GraphQL server. With `express-graphql`, you can just send an HTTP POST request to the endpoint you mounted your GraphQL server on, passing the GraphQL query as the `query` field in a JSON payload. +Since a GraphQL API has more underlying structure than a REST API, there are more powerful clients like [Relay](https://facebook.github.io/relay/) which can automatically handle batching, caching, and other features. But you don't need a complex client to call a GraphQL server. With `graphql-http`, you can just send an HTTP POST request to the endpoint you mounted your GraphQL server on, passing the GraphQL query as the `query` field in a JSON payload. -For example, let's say we mounted a GraphQL server on http://localhost:4000/graphql as in the example code for [running an Express GraphQL server](./running-an-express-graphql-server.md), and we want to send the GraphQL query `{ hello }`. We can do this from the command line with `curl`. If you paste this into a terminal: +For example, let's say we mounted a GraphQL server on http://localhost:4000/graphql as in the example code for [running an Express GraphQL server](/running-an-express-graphql-server/), and we want to send the GraphQL query `{ hello }`. We can do this from the command line with `curl`. If you paste this into a terminal: ```bash curl -X POST \ @@ -16,13 +15,13 @@ http://localhost:4000/graphql You should see the output returned as JSON: -``` -{"data":{"hello":"Hello world!"}} +```json +{ "data": { "hello": "Hello world!" } } ``` -If you prefer to use a graphical user interface to send a test query, you can use clients such as [GraphiQL](https://github.com/graphql/graphiql) and [Insomnia](https://github.com/getinsomnia/insomnia). +If you prefer to use a graphical user interface to send a test query, you can use clients such as [GraphiQL](https://github.com/graphql/graphiql), [Insomnia](https://github.com/getinsomnia/insomnia), and [Postman](https://www.postman.com/product/graphql-client/). -It's also simple to send GraphQL from the browser. Open up http://localhost:4000, open a developer console, and paste in: +It's also simple to send GraphQL from the browser. Open up http://localhost:4000/graphql, open a developer console, and paste in: ```js fetch('/graphql', { @@ -39,13 +38,13 @@ fetch('/graphql', { You should see the data returned, logged in the console: -``` +```text data returned: Object { hello: "Hello world!" } ``` -In this example, the query was just a hardcoded string. As your application becomes more complex, and you add GraphQL endpoints that take arguments as described in [Passing Arguments](./passing-arguments.md), you will want to construct GraphQL queries using variables in client code. You can do this by including a keyword prefixed with a dollar sign in the query, and passing an extra `variables` field on the payload. +In this example, the query was just a hardcoded string. As your application becomes more complex, and you add GraphQL endpoints that take arguments as described in [Passing Arguments](/passing-arguments/), you will want to construct GraphQL queries using variables in client code. You can do this by including a keyword prefixed with a dollar sign in the query, and passing an extra `variables` field on the payload. -For example, let's say you're running the example server from [Passing Arguments](./passing-arguments.md) that has a schema of +For example, let's say you're running the example server from [Passing Arguments](/passing-arguments/) that has a schema of ```graphql type Query { @@ -56,11 +55,13 @@ type Query { You could access this from JavaScript with the code: ```js -var dice = 3; -var sides = 6; -var query = `query RollDice($dice: Int!, $sides: Int) { - rollDice(numDice: $dice, numSides: $sides) -}`; +let dice = 3; +let sides = 6; +let query = /* GraphQL */ ` + query RollDice($dice: Int!, $sides: Int) { + rollDice(numDice: $dice, numSides: $sides) + } +`; fetch('/graphql', { method: 'POST', @@ -81,4 +82,4 @@ Using this syntax for variables is a good idea because it automatically prevents In general, it will take a bit more time to set up a GraphQL client like Relay, but it's worth it to get more features as your application grows. You might want to start out just using HTTP requests as the underlying transport layer, and switching to a more complex client as your application gets more complex. -At this point you can write a client and server in GraphQL for an API that receives a single string. To do more, you will want to [learn how to use the other basic data types](./basic-types.md). +At this point you can write a client and server in GraphQL for an API that receives a single string. To do more, you will want to [learn how to use the other basic data types](/basic-types/). diff --git a/website/pages/index.mdx b/website/pages/index.mdx new file mode 100644 index 0000000000..4c8fb78b56 --- /dev/null +++ b/website/pages/index.mdx @@ -0,0 +1,18 @@ +--- +title: Overview +sidebarTitle: Overview +--- + +GraphQL.JS is the reference implementation to the [GraphQL Specification](https://spec.graphql.org/draft/), it's designed to be simple to use and easy to understand +while closely following the Specification. + +You can build GraphQL servers, clients, and tools with this library, it's designed so you can choose which parts you use, for example, you can build your own parser +and use the execution/validation from the library. There also a lot of useful utilities for schema-diffing, working with arguments and [many more](./utilities.mdx). + +In the following chapters you'll find out more about the three critical pieces of this library + +- The GraphQL language +- Document validation +- GraphQL Execution + +You can also code along on [a tutorial](./getting-started.mdx). diff --git a/website/pages/mutations-and-input-types.mdx b/website/pages/mutations-and-input-types.mdx new file mode 100644 index 0000000000..7b4bfa4859 --- /dev/null +++ b/website/pages/mutations-and-input-types.mdx @@ -0,0 +1,405 @@ +--- +title: Mutations and Input Types +--- + +import { Tabs } from 'nextra/components'; + +If you have an API endpoint that alters data, like inserting data into a database or altering data already in a database, you should make this endpoint a `Mutation` rather than a `Query`. This is as simple as making the API endpoint part of the top-level `Mutation` type instead of the top-level `Query` type. + +Let's say we have a “message of the day” server, where anyone can update the message of the day, and anyone can read the current one. The GraphQL schema for this is simply: + + + +```graphql +type Mutation { + setMessage(message: String): String +} + +type Query { + getMessage: String +} +```` + + +```js +const { + GraphQLObjectType, + GraphQLString, + GraphQLSchema, +} = require('graphql'); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + getMessage: { type: GraphQLString }, + }, + }), + mutation: new GraphQLObjectType({ + name: 'Mutation', + fields: { + setMessage: { type: GraphQLString }, + }, + }), +}); +```` + + + + +It's often convenient to have a mutation that maps to a database create or update operation, like `setMessage`, return the same thing that the server stored. That way, if you modify the data on the server, the client can learn about those modifications. + +Both mutations and queries can be handled by root resolvers, so the root that implements this schema can simply be: + +```js +const fakeDatabase = {}; +const root = { + setMessage({ message }) { + fakeDatabase.message = message; + return message; + }, + getMessage() { + return fakeDatabase.message; + }, +}; +``` + +You don't need anything more than this to implement mutations. But in many cases, you will find a number of different mutations that all accept the same input parameters. A common example is that creating an object in a database and updating an object in a database often take the same parameters. To make your schema simpler, you can use “input types” for this, by using the `input` keyword instead of the `type` keyword. + +For example, instead of a single message of the day, let's say we have many messages, indexed in a database by the `id` field, and each message has both a `content` string and an `author` string. We want a mutation API both for creating a new message and for updating an old message. We could use the schema: + + + +```graphql +input MessageInput { + content: String + author: String +} + +type Message { + id: ID! + content: String + author: String +} + +type Query { + getMessage(id: ID!): Message +} + +type Mutation { + createMessage(input: MessageInput): Message + updateMessage(id: ID!, input: MessageInput): Message +} + +```` + + +```js +const { + GraphQLObjectType, + GraphQLString, + GraphQLSchema, + GraphQLID, + GraphQLInputObjectType, + GraphQLNonNull, +} = require('graphql'); + +const MessageInput = new GraphQLInputObjectType({ + name: 'MessageInput', + fields: { + content: { type: GraphQLString }, + author: { type: GraphQLString }, + }, +}); + +const Message = new GraphQLObjectType({ + name: 'Message', + fields: { + id: { type: GraphQLID }, + content: { type: GraphQLString }, + author: { type: GraphQLString }, + }, +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + getMessage: { + type: Message, + args: { + id: { type: new GraphQLNonNull(GraphQLID) }, + }, + }, + }, + }), + mutation: new GraphQLObjectType({ + name: 'Mutation', + fields: { + createMessage: { + type: Message, + args: { + input: { type: new GraphQLNonNull(MessageInput) }, + }, + }, + updateMessage: { + type: Message, + args: { + id: { type: new GraphQLNonNull(GraphQLID) }, + input: { type: new GraphQLNonNull(MessageInput) }, + }, + }, + }, + }), +}); +```` + + + + +Here, the mutations return a `Message` type, so that the client can get more information about the newly-modified `Message` in the same request as the request that mutates it. + +Input types can't have fields that are other objects, only basic scalar types, list types, and other input types. + +Naming input types with `Input` on the end is a useful convention, because you will often want both an input type and an output type that are slightly different for a single conceptual object. + +Here's some runnable code that implements this schema, keeping the data in memory: + + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { buildSchema } = require('graphql'); + +// Construct a schema, using GraphQL schema language +const schema = buildSchema(` +input MessageInput { + content: String + author: String +} + +type Message { + id: ID! + content: String + author: String +} + +type Query { + getMessage(id: ID!): Message +} + +type Mutation { + createMessage(input: MessageInput): Message + updateMessage(id: ID!, input: MessageInput): Message +} +`); + +// If Message had any complex fields, we'd put them on this object. +class Message { + constructor(id, { content, author }) { + this.id = id; + this.content = content; + this.author = author; + } +} + +// Maps username to content +const fakeDatabase = {}; + +const root = { + getMessage({ id }) { + if (!fakeDatabase[id]) { + throw new Error('no message exists with id ' + id); + } + return new Message(id, fakeDatabase[id]); + }, + createMessage({ input }) { + // Create a random id for our "database". + const id = require('crypto').randomBytes(10).toString('hex'); + + fakeDatabase[id] = input; + return new Message(id, input); + }, + updateMessage({ id, input }) { + if (!fakeDatabase[id]) { + throw new Error('no message exists with id ' + id); + } + // This replaces all old data, but some apps might want partial update. + fakeDatabase[id] = input; + return new Message(id, input); + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000, () => { +console.log('Running a GraphQL API server at localhost:4000/graphql'); +}); + +```` + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { + GraphQLObjectType, + GraphQLString, + GraphQLSchema, + GraphQLID, + GraphQLInputObjectType, + GraphQLNonNull, +} = require('graphql'); + +const MessageInput = new GraphQLInputObjectType({ + name: 'MessageInput', + fields: { + content: { type: GraphQLString }, + author: { type: GraphQLString }, + }, +}); + +const Message = new GraphQLObjectType({ + name: 'Message', + fields: { + id: { type: GraphQLID }, + content: { type: GraphQLString }, + author: { type: GraphQLString }, + }, +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + getMessage: { + type: Message, + args: { + id: { type: new GraphQLNonNull(GraphQLID) }, + }, + }, + }, + }), + mutation: new GraphQLObjectType({ + name: 'Mutation', + fields: { + createMessage: { + type: Message, + args: { + input: { type: new GraphQLNonNull(MessageInput) }, + }, + }, + updateMessage: { + type: Message, + args: { + id: { type: new GraphQLNonNull(GraphQLID) }, + input: { type: new GraphQLNonNull(MessageInput) }, + }, + }, + }, + }), +}); + +// If Message had any complex fields, we'd put them on this object. +class Message { + constructor(id, { content, author }) { + this.id = id; + this.content = content; + this.author = author; + } +} + +// Maps username to content +const fakeDatabase = {}; + +const root = { + getMessage({ id }) { + if (!fakeDatabase[id]) { + throw new Error('no message exists with id ' + id); + } + return new Message(id, fakeDatabase[id]); + }, + createMessage({ input }) { + // Create a random id for our "database". + const id = require('crypto').randomBytes(10).toString('hex'); + + fakeDatabase[id] = input; + return new Message(id, input); + }, + updateMessage({ id, input }) { + if (!fakeDatabase[id]) { + throw new Error('no message exists with id ' + id); + } + // This replaces all old data, but some apps might want partial update. + fakeDatabase[id] = input; + return new Message(id, input); + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000, () => { + console.log('Running a GraphQL API server at localhost:4000/graphql'); +}); +```` + + + + +To call a mutation, you must use the keyword `mutation` before your GraphQL query. To pass an input type, provide the data written as if it's a JSON object. For example, with the server defined above, you can create a new message and return the `id` of the new message with this operation: + +```graphql +mutation { + createMessage(input: { author: "andy", content: "hope is a good thing" }) { + id + } +} +``` + +You can use variables to simplify mutation client logic just like you can with queries. For example, some JavaScript code that calls the server to execute this mutation is: + +```js +const author = 'andy'; +const content = 'hope is a good thing'; +const query = /* GraphQL */ ` + mutation CreateMessage($input: MessageInput) { + createMessage(input: $input) { + id + } + } +`; + +fetch('/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify({ + query, + variables: { + input: { + author, + content, + }, + }, + }), +}) + .then((r) => r.json()) + .then((data) => console.log('data returned:', data)); +``` + +One particular type of mutation is operations that change users, like signing up a new user. While you can implement this using GraphQL mutations, you can reuse many existing libraries if you learn about [GraphQL with authentication and Express middleware](/authentication-and-express-middleware/). diff --git a/website/pages/object-types.mdx b/website/pages/object-types.mdx new file mode 100644 index 0000000000..366620c970 --- /dev/null +++ b/website/pages/object-types.mdx @@ -0,0 +1,372 @@ +--- +title: Object Types +--- + +import { Tabs } from 'nextra/components'; + +In many cases, you don't want to return a number or a string from an API. You want to return an object that has its own complex behavior. GraphQL is a perfect fit for this. + +In GraphQL schema language, the way you define a new object type is the same way we have been defining the `Query` type in our examples. Each object can have fields that return a particular type, and methods that take arguments. For example, in the [Passing Arguments](/passing-arguments/) documentation, we had a method to roll some random dice: + + + +```graphql +type Query { + rollDice(numDice: Int!, numSides: Int): [Int] +} +``` + + +```js +const { + GraphQLObjectType, + GraphQLNonNull, + GraphQLInt, + GraphQLString, + GraphQLList, + GraphQLFloat, +} = require('graphql'); + +new GraphQLObjectType({ + name: 'Query', + fields: { + rollDice: { + type: new GraphQLList(GraphQLFloat), + args: { + numDice: { + type: new GraphQLNonNull(GraphQLInt) + }, + numSides: { + type: new GraphQLNonNull(GraphQLInt) + }, + }, + }, + }, +}) + +```` + + + +If we wanted to have more and more methods based on a random die over time, we could implement this with a `RandomDie` object type instead. + + + +```graphql +type RandomDie { + roll(numRolls: Int!): [Int] +} + +type Query { + getDie(numSides: Int): RandomDie +} +```` + + + +```js +const { + GraphQLObjectType, + GraphQLNonNull, + GraphQLInt, + GraphQLString, + GraphQLList, + GraphQLFloat, +} = require('graphql'); + +const RandomDie = new GraphQLObjectType({ + name: 'RandomDie', + fields: { + roll: { + type: new GraphQLList(GraphQLInt), + args: { + numRolls: { + type: new GraphQLNonNull(GraphQLInt) + } + } + } + } +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + getDie: { + type: RandomDie, + args: { + numSides: { + type: GraphQLInt + } + } + } + } + }) +}); + +```` + + + +Instead of a root-level resolver for the `RandomDie` type, we can instead use an ES6 class, where the resolvers are instance methods. This code shows how the `RandomDie` schema above can be implemented: + +```js +class RandomDie { + constructor(numSides) { + this.numSides = numSides; + } + + rollOnce() { + return 1 + Math.floor(Math.random() * this.numSides); + } + + roll({ numRolls }) { + const output = []; + for (const i = 0; i < numRolls; i++) { + output.push(this.rollOnce()); + } + return output; + } +} + +const root = { + getDie({ numSides }) { + return new RandomDie(numSides || 6); + }, +}; +```` + +For fields that don't use any arguments, you can use either properties on the object or instance methods. So for the example code above, both `numSides` and `rollOnce` can actually be used to implement GraphQL fields, so that code also implements the schema of: + + + +```graphql +type RandomDie { + numSides: Int! + rollOnce: Int! + roll(numRolls: Int!): [Int] +} + +type Query { +getDie(numSides: Int): RandomDie +} + +```` + + +```js +const { + GraphQLObjectType, + GraphQLNonNull, + GraphQLInt, + GraphQLString, + GraphQLList, + GraphQLFloat, +} = require('graphql'); + +const RandomDie = new GraphQLObjectType({ + name: 'RandomDie', + fields: { + numSides: { + type: new GraphQLNonNull(GraphQLInt), + }, + rollOnce: { + type: new GraphQLNonNull(GraphQLInt), + }, + roll: { + type: new GraphQLList(GraphQLInt), + args: { + numRolls: { + type: new GraphQLNonNull(GraphQLInt) + }, + } + } + } +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + getDie: { + type: RandomDie, + args: { + numSides: { + type: GraphQLInt + } + } + } + } + }) +}); +```` + + + + +Putting this all together, here is some sample code that runs a server with this GraphQL API: + + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { buildSchema } = require('graphql'); + +// Construct a schema, using GraphQL schema language +const schema = buildSchema(` +type RandomDie { + numSides: Int! + rollOnce: Int! + roll(numRolls: Int!): [Int] +} + +type Query { + getDie(numSides: Int): RandomDie +} +`); + +// This class implements the RandomDie GraphQL type +class RandomDie { + constructor(numSides) { + this.numSides = numSides; + } + + rollOnce() { + return 1 + Math.floor(Math.random() \* this.numSides); + } + + roll({ numRolls }) { + const output = []; + for (const i = 0; i < numRolls; i++) { + output.push(this.rollOnce()); + } + return output; + } +} + +// The root provides the top-level API endpoints +const root = { + getDie({ numSides }) { + return new RandomDie(numSides || 6); + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); +```` + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { + GraphQLObjectType, + GraphQLNonNull, + GraphQLInt, + GraphQLString, + GraphQLList, + GraphQLFloat, +} = require('graphql'); + +const RandomDie = new GraphQLObjectType({ + name: 'RandomDie', + fields: { + numSides: { + type: new GraphQLNonNull(GraphQLInt), + }, + rollOnce: { + type: new GraphQLNonNull(GraphQLInt), + }, + roll: { + type: new GraphQLList(GraphQLInt), + args: { + numRolls: { + type: new GraphQLNonNull(GraphQLInt) + }, + } + } + } +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + getDie: { + type: RandomDie, + args: { + numSides: { + type: GraphQLInt + } + } + } + } + }) +}); + +// This class implements the RandomDie GraphQL type +class RandomDie { + constructor(numSides) { + this.numSides = numSides; + } + + rollOnce() { + return 1 + Math.floor(Math.random() * this.numSides); + } + + roll({ numRolls }) { + const output = []; + for (const i = 0; i < numRolls; i++) { + output.push(this.rollOnce()); + } + return output; + } +} + +// The root provides the top-level API endpoints +const root = { + getDie({ numSides }) { + return new RandomDie(numSides || 6); + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); +```` + + + + +When you issue a GraphQL query against an API that returns object types, you can call multiple methods on the object at once by nesting the GraphQL field names. For example, if you wanted to call both `rollOnce` to roll a die once, and `roll` to roll a die three times, you could do it with this query: + +```graphql +{ + getDie(numSides: 6) { + rollOnce + roll(numRolls: 3) + } +} +``` + +If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs with [GraphiQL](https://github.com/graphql/graphiql). + +This way of defining object types often provides advantages over a traditional REST API. Instead of doing one API request to get basic information about an object, and then multiple subsequent API requests to find out more information about that object, you can get all of that information in one API request. That saves bandwidth, makes your app run faster, and simplifies your client-side logic. + +So far, every API we've looked at is designed for returning data. In order to modify stored data or handle complex input, it helps to [learn about mutations and input types](/mutations-and-input-types/). diff --git a/website/pages/oneof-input-objects.mdx b/website/pages/oneof-input-objects.mdx new file mode 100644 index 0000000000..95be65d2c2 --- /dev/null +++ b/website/pages/oneof-input-objects.mdx @@ -0,0 +1,91 @@ +--- +title: OneOf input objects +--- + +import { Tabs } from 'nextra/components'; + +Some inputs will behave differently depending on what input we choose. Let's look at the case for +a field named `product`, we can fetch a `Product` by either its `id` or its `name`. Currently we'd +make a tradeoff for this by introducing two arguments that are both nullable, now if both are passed +as null (or both non-null) we'd have to handle that in code - the type system wouldn't indicate that exactly one was required. To fix this, the `@oneOf` directive was introduced so we +can create this "exactly one option" constraint without sacrificing the strictly typed nature of our GraphQL Schema. + + + +```js +const schema = buildSchema(` + type Product { + id: ID! + name: String! + } + + input ProductLocation { + aisleNumber: Int! + shelfNumber: Int! + positionOnShelf: Int! + } + + input ProductSpecifier @oneOf { + id: ID + name: String + location: ProductLocation + } + + type Query { + product(by: ProductSpecifier!): Product + } +`); +``` + + +```js +const Product = new GraphQLObjectType({ + name: 'Product', + fields: { + id: { + type: new GraphQLNonNull(GraphQLID), + }, + name: { + type: new GraphQLNonNull(GraphQLString), + }, + }, +}); + +const ProductLocation = new GraphQLInputObjectType({ + name: 'ProductLocation', + isOneOf: true, + fields: { + aisleNumber: { type: GraphQLInt }, + shelfNumber: { type: GraphQLInt }, + positionOnShelf: { type: GraphQLInt }, + }, +}); + +const ProductSpecifier = new GraphQLInputObjectType({ + name: 'ProductSpecifier', + isOneOf: true, + fields: { + id: { type: GraphQLID }, + name: { type: GraphQLString }, + location: { type: ProductLocation }, + }, +}); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + product: { + type: Product, + args: { by: { type: ProductSpecifier } }, + }, + }, + }), +}); +``` + + + +It doesn't matter whether you have 2 or more inputs here, all that matters is +that your user will have to specify one, and only one, for this input to be valid. +The values are not limited to scalars, lists and other input object types are also allowed. \ No newline at end of file diff --git a/website/docs/tutorials/passing-arguments.md b/website/pages/passing-arguments.mdx similarity index 51% rename from website/docs/tutorials/passing-arguments.md rename to website/pages/passing-arguments.mdx index 699fdad791..0017a69638 100644 --- a/website/docs/tutorials/passing-arguments.md +++ b/website/pages/passing-arguments.mdx @@ -2,7 +2,9 @@ title: Passing Arguments --- -Just like a REST API, it's common to pass arguments to an endpoint in a GraphQL API. By defining the arguments in the schema language, type checking happens automatically. Each argument must be named and have a type. For example, in the [Basic Types documentation](./basic-types.md) we had an endpoint called `rollThreeDice`: +import { Tabs } from 'nextra/components'; + +Just like a REST API, it's common to pass arguments to an endpoint in a GraphQL API. By defining the arguments in the schema language, typechecking happens automatically. Each argument must be named and have a type. For example, in the [Basic Types documentation](/basic-types/) we had an endpoint called `rollThreeDice`: ```graphql type Query { @@ -10,37 +12,71 @@ type Query { } ``` -Instead of hard-coding “three”, we might want a more general function that rolls `numDice` dice, each of which have `numSides` sides. We can add arguments to the GraphQL schema language like this: +Instead of hard coding “three”, we might want a more general function that rolls `numDice` dice, each of which have `numSides` sides. We can add arguments to the GraphQL schema language like this: + + ```graphql type Query { rollDice(numDice: Int!, numSides: Int): [Int] } ``` + + +```js +const { + GraphQLObjectType, + GraphQLNonNull, + GraphQLInt, + GraphQLString, + GraphQLList, + GraphQLFloat, +} = require('graphql'); + +new GraphQLObjectType({ + name: 'Query', + fields: { + rollDice: { + type: new GraphQLList(GraphQLFloat), + args: { + numDice: { + type: new GraphQLNonNull(GraphQLInt) + }, + numSides: { + type: new GraphQLNonNull(GraphQLInt) + }, + }, + }, + }, +}) + +```` + + The exclamation point in `Int!` indicates that `numDice` can't be null, which means we can skip a bit of validation logic to make our server code simpler. We can let `numSides` be null and assume that by default a die has 6 sides. So far, our resolver functions took no arguments. When a resolver takes arguments, they are passed as one “args” object, as the first argument to the function. So rollDice could be implemented as: ```js -var root = { - rollDice: function (args) { - var output = []; - for (var i = 0; i < args.numDice; i++) { +const root = { + rollDice(args) { + const output = []; + for (const i = 0; i < args.numDice; i++) { output.push(1 + Math.floor(Math.random() * (args.numSides || 6))); } return output; }, }; -``` +```` It's convenient to use [ES6 destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) for these parameters, since you know what format they will be. So we can also write `rollDice` as ```js -var root = { - rollDice: function ({ numDice, numSides }) { - var output = []; - for (var i = 0; i < numDice; i++) { +const root = { + rollDice({ numDice, numSides }) { + const output = []; + for (const i = 0; i < numDice; i++) { output.push(1 + Math.floor(Math.random() * (numSides || 6))); } return output; @@ -52,42 +88,98 @@ If you're familiar with destructuring, this is a bit nicer because the line of c The entire code for a server that hosts this `rollDice` API is: + + ```js -var express = require('express'); -var { graphqlHTTP } = require('express-graphql'); -var { buildSchema } = require('graphql'); +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { buildSchema } = require('graphql'); // Construct a schema, using GraphQL schema language -var schema = buildSchema(` - type Query { - rollDice(numDice: Int!, numSides: Int): [Int] - } -`); +const schema = buildSchema(/_ GraphQL _/ ` type Query { rollDice(numDice: Int!, numSides: Int): [Int] }`); // The root provides a resolver function for each API endpoint -var root = { - rollDice: function ({ numDice, numSides }) { - var output = []; - for (var i = 0; i < numDice; i++) { +const root = { + rollDice({ numDice, numSides }) { + const output = []; + for (const i = 0; i < numDice; i++) { + output.push(1 + Math.floor(Math.random() \* (numSides || 6))); + } + return output; + }, +}; + +const app = express(); +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); + +```` + + +```js +const express = require('express'); +const { createHandler } = require('graphql-http/lib/use/express'); +const { + GraphQLObjectType, + GraphQLNonNull, + GraphQLInt, + GraphQLString, + GraphQLList, + GraphQLFloat, +} = require('graphql'); + +// Construct a schema, using GraphQL schema language +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + rollDice: { + type: new GraphQLList(GraphQLFloat), + args: { + numDice: { + type: new GraphQLNonNull(GraphQLInt) + }, + numSides: { + type: new GraphQLNonNull(GraphQLInt) + }, + }, + }, + }, + }) +}) + +// The root provides a resolver function for each API endpoint +const root = { + rollDice({ numDice, numSides }) { + const output = []; + for (const i = 0; i < numDice; i++) { output.push(1 + Math.floor(Math.random() * (numSides || 6))); } return output; }, }; -var app = express(); -app.use( +const app = express(); +app.all( '/graphql', - graphqlHTTP({ + createHandler({ schema: schema, rootValue: root, - graphiql: true, }), ); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` +app.listen(4000); +console.log('Running a GraphQL API server at localhost:4000/graphql'); +```` + + + When you call this API, you have to pass each argument by name. So for the server above, you could issue this GraphQL query to roll three six-sided dice: @@ -104,11 +196,13 @@ When you're passing arguments in code, it's generally better to avoid constructi For example, some JavaScript code that calls our server above is: ```js -var dice = 3; -var sides = 6; -var query = `query RollDice($dice: Int!, $sides: Int) { - rollDice(numDice: $dice, numSides: $sides) -}`; +const dice = 3; +const sides = 6; +const query = /* GraphQL */ ` + query RollDice($dice: Int!, $sides: Int) { + rollDice(numDice: $dice, numSides: $sides) + } +`; fetch('/graphql', { method: 'POST', @@ -127,4 +221,4 @@ fetch('/graphql', { Using `$dice` and `$sides` as variables in GraphQL means we don't have to worry about escaping on the client side. -With basic types and argument passing, you can implement anything you can implement in a REST API. But GraphQL supports even more powerful queries. You can replace multiple API calls with a single API call if you learn how to [define your own object types](./object-types.md). +With basic types and argument passing, you can implement anything you can implement in a REST API. But GraphQL supports even more powerful queries. You can replace multiple API calls with a single API call if you learn how to [define your own object types](/object-types/). diff --git a/website/pages/running-an-express-graphql-server.mdx b/website/pages/running-an-express-graphql-server.mdx new file mode 100644 index 0000000000..5b8e201ec1 --- /dev/null +++ b/website/pages/running-an-express-graphql-server.mdx @@ -0,0 +1,117 @@ +--- +title: Running an Express GraphQL Server +sidebarTitle: Running Express + GraphQL +--- + +import { Tabs } from 'nextra/components'; + +The simplest way to run a GraphQL API server is to use [Express](https://expressjs.com), a popular web application framework for Node.js. You will need to install two additional dependencies: + +```sh npm2yarn +npm install express graphql-http graphql --save +``` + +Let's modify our “hello world” example so that it's an API server rather than a script that runs a single query. We can use the 'express' module to run a web server, and instead of executing a query directly with the `graphql` function, we can use the `graphql-http` library to mount a GraphQL API server on the “/graphql” HTTP endpoint: + + + +```javascript +const { buildSchema } = require('graphql'); +const { createHandler } = require('graphql-http/lib/use/express'); +const express = require('express'); + +// Construct a schema, using GraphQL schema language +const schema = buildSchema(`type Query { hello: String } `); + +// The rootValue provides a resolver function for each API endpoint +const rootValue = { + hello() { + return 'Hello world!'; + }, +}; + +const app = express(); + +// Create and use the GraphQL handler. +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); + +// Start the server at port +app.listen(4000); +console.log('Running a GraphQL API server at http://localhost:4000/graphql'); + +```` + + +```javascript +const { GraphQLObjectType, GraphQLSchema } = require('graphql'); +const { createHandler } = require('graphql-http/lib/use/express'); +const express = require('express'); + +// Construct a schema +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + hello: { type: GraphQLString }, + }, + }), +}); + +// The rootValue provides a resolver function for each API endpoint +const rootValue = { + hello() { + return 'Hello world!'; + }, +}; + +const app = express(); + +// Create and use the GraphQL handler. +app.all( + '/graphql', + createHandler({ + schema: schema, + rootValue: root, + }), +); + +// Start the server at port +app.listen(4000); +console.log('Running a GraphQL API server at http://localhost:4000/graphql'); +```` + + + + +You can run this GraphQL server with: + +```sh +node server.js +``` + +## Using GraphiQL + +[GraphiQL](https://github.com/graphql/graphiql) is GraphQL's IDE; a great way of querying and exploring your GraphQL API. +One easy way to add it to your server is via the MIT-licensed [ruru](https://github.com/graphile/crystal/blob/main/grafast/ruru/README.md) package which bundles a prebuilt GraphiQL with some popular enhancements. +To do so, install the `ruru` module with `npm install --save ruru` and then add the following to your `server.js` file, then restart the `node server.js` command: + +```js +const { ruruHTML } = require('ruru/server'); + +// Serve the GraphiQL IDE. +app.get('/', (_req, res) => { + res.type('html'); + res.end(ruruHTML({ endpoint: '/graphql' })); +}); +``` + +If you navigate to [http://localhost:4000](http://localhost:4000), you should see an interface that lets you enter queries; +now you can use the GraphiQL IDE tool to issue GraphQL queries directly in the browser. + +At this point you have learned how to run a GraphQL server. The next step is to learn how to [issue GraphQL queries from client code](/graphql-clients/). diff --git a/website/postcss.config.js b/website/postcss.config.js new file mode 100644 index 0000000000..444d84db0d --- /dev/null +++ b/website/postcss.config.js @@ -0,0 +1,9 @@ +const config = { + plugins: { + 'tailwindcss/nesting': {}, + tailwindcss: {}, + autoprefixer: {}, + }, +}; + +export default config; diff --git a/website/sidebars.cjs b/website/sidebars.cjs deleted file mode 100644 index 5201b4fd95..0000000000 --- a/website/sidebars.cjs +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -module.exports = { - tutorialSidebar: [ - 'tutorials/index', - 'tutorials/running-an-express-graphql-server', - 'tutorials/graphql-clients', - 'tutorials/basic-types', - 'tutorials/passing-arguments', - 'tutorials/object-types', - 'tutorials/mutations-and-input-types', - 'tutorials/authentication-and-express-middleware', - { - type: 'category', - label: 'Advanced', - items: ['tutorials/constructing-types'], - }, - 'tutorials/express-graphql', - 'tutorials/defer-stream', - ], -}; diff --git a/website/src/css/custom.css b/website/src/css/custom.css deleted file mode 100644 index 3f17ca4f0b..0000000000 --- a/website/src/css/custom.css +++ /dev/null @@ -1,31 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); -/* stylelint-disable docusaurus/copyright-header */ -/** - * Any CSS included here will be global. The classic template - * bundles Infima by default. Infima is a CSS framework designed to - * work well for content-centric websites. - */ - -/* You can override the default Infima variables here. */ -:root { - --ifm-color-primary: #e434aa; - --ifm-color-primary-dark: #de1e9f; - --ifm-color-primary-darker: #d21c96; - --ifm-color-primary-darkest: #ad177c; - --ifm-color-primary-light: #e74db4; - --ifm-color-primary-lighter: #e959ba; - --ifm-color-primary-lightest: #ee7ec9; - --ifm-code-font-size: 95%; - --ifm-font-family-base: 'Rubik', sans-serif; -} - -.docusaurus-highlight-code-line { - background-color: rgba(0, 0, 0, 0.1); - display: block; - margin: 0 calc(-1 * var(--ifm-pre-padding)); - padding: 0 var(--ifm-pre-padding); -} - -html[data-theme='dark'] .docusaurus-highlight-code-line { - background-color: rgba(0, 0, 0, 0.3); -} diff --git a/website/src/pages/index.jsx b/website/src/pages/index.jsx deleted file mode 100644 index 5344893b79..0000000000 --- a/website/src/pages/index.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import clsx from 'clsx'; -import React from 'react'; - -import styles from './index.module.css'; - -function HomepageHeader() { - const { siteConfig } = useDocusaurusContext(); - return ( -
                            -
                            -

                            {siteConfig.title}

                            -

                            {siteConfig.tagline}

                            -
                            - - Get Started - -
                            -
                            -
                            - ); -} - -const Home = () => ( - - - -); - -export default Home; diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css deleted file mode 100644 index 5c0d4f6e20..0000000000 --- a/website/src/pages/index.module.css +++ /dev/null @@ -1,25 +0,0 @@ -/* stylelint-disable docusaurus/copyright-header */ - -/** - * CSS files with the .module.css suffix will be treated as CSS modules - * and scoped locally. - */ - -.heroBanner { - padding: 4rem 0; - text-align: center; - position: relative; - overflow: hidden; -} - -@media screen and (max-width: 966px) { - .heroBanner { - padding: 2rem; - } -} - -.buttons { - display: flex; - align-items: center; - justify-content: center; -} diff --git a/website/static/.nojekyll b/website/static/.nojekyll deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/website/static/favicon.ico b/website/static/favicon.ico deleted file mode 100644 index dc43ea2ed2..0000000000 Binary files a/website/static/favicon.ico and /dev/null differ diff --git a/website/static/img/logo.svg b/website/static/img/logo.svg deleted file mode 100644 index 3fd0b6ed3d..0000000000 --- a/website/static/img/logo.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/website/tailwind.config.js b/website/tailwind.config.js new file mode 100644 index 0000000000..384ecc396e --- /dev/null +++ b/website/tailwind.config.js @@ -0,0 +1,43 @@ +import typography from '@tailwindcss/typography'; + +const config = { + content: [ + './pages/**/*.{ts,tsx,mdx}', + './icons/**/*.{ts,tsx,mdx}', + './css/**/*.css', + './theme.config.tsx', + ], + theme: { + container: { + center: true, + padding: '1rem', + }, + extend: { + colors: { + primary: '#e10098', + 'conf-black': '#0e031c', + black: '#1b1b1b', + }, + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': + 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + animation: { + scroll: + 'scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite', + }, + keyframes: { + scroll: { + to: { + transform: 'translate(calc(-50% - .5rem))', + }, + }, + }, + }, + }, + plugins: [typography], + darkMode: ['class', 'html[class~="dark"]'], +}; + +export default config; diff --git a/website/theme.config.tsx b/website/theme.config.tsx new file mode 100644 index 0000000000..5d8d5ff3a7 --- /dev/null +++ b/website/theme.config.tsx @@ -0,0 +1,249 @@ +import React from 'react'; +import { DocsThemeConfig, ThemeSwitch, useConfig } from 'nextra-theme-docs'; +import NextLink from 'next/link'; +import { + GraphQLWordmarkLogo, + StackOverflowIcon, + GitHubIcon, + DiscordIcon, + TwitterIcon, +} from './icons/index'; +import { useRouter } from 'next/router'; + +const graphQLLogo = ( + +); + +const classes = { + link: 'hover:underline decoration-from-font [text-underline-position:from-font]', +}; + +function List({ + title, + items, +}: { + title: string; + items: { title: string; url: string }[]; +}) { + return ( +
                              +

                              {title}

                              + {items.map((item) => ( +
                            • + + {item.title} + +
                            • + ))} +
                            + ); +} + +function Footer() { + return ( +
                            +
                            + + {graphQLLogo} + + + + + +
                            +
                            +

                            + Copyright © {new Date().getFullYear()} The GraphQL Foundation. All + rights reserved. +
                            + For web site terms of use, trademark policy and general project + policies please see{' '} + + https://lfprojects.org + +

                            +
                            +
                              + {[ + { url: 'https://github.com/graphql', icon: GitHubIcon }, + { url: 'https://discord.graphql.org', icon: DiscordIcon }, + { url: 'https://x.com/graphql', icon: TwitterIcon }, + { + url: 'http://stackoverflow.com/questions/tagged/graphql', + icon: StackOverflowIcon, + }, + ].map(({ url, icon: Icon }) => ( +
                            • + + + +
                            • + ))} +
                            + + Powered by{' '} + + + + + +
                            +
                            +
                            + ); +} + +const cfg: DocsThemeConfig = { + backgroundColor: { + dark: '27,27,27', + }, + head: function useHead() { + const { frontMatter, title: pageTitle } = useConfig(); + const { asPath } = useRouter(); + + const title = `${pageTitle}${asPath === '/' ? '' : ' | GraphQL'}`; + const { description, canonical, image } = frontMatter; + return ( + <> + {title} + + {description && ( + <> + + + + )} + {canonical && } + {image && } + + + + ); + }, + banner: { + content: ( + <> + 🎬 That's a Wrap for GraphQLConf 2024! • Watch the Videos •{' '} + + Check out the recorded talks and workshops + + + ), + key: 'graphqlconf-2024', + }, + logo: graphQLLogo, + docsRepositoryBase: + 'https://github.com/graphql/graphql-js/tree/16.x.x/website', + color: { + hue: 319, + }, + sidebar: { + defaultMenuCollapseLevel: 1, + }, + footer: { + content: Footer, + }, + navbar: { + extraContent: , + }, + toc: { + backToTop: true, + }, + search: { + placeholder: 'Search…', + }, +}; + +export default cfg; diff --git a/website/tsconfig.json b/website/tsconfig.json new file mode 100644 index 0000000000..27bb74a6f8 --- /dev/null +++ b/website/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "plugins": [ + { + "name": "next" + } + ], + "strictNullChecks": true, + "module": "esnext" + }, + "include": ["next-env.d.mts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +}