diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index d76ab129f..2e6986722 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -2,8 +2,58 @@ name: ocelot.social end-to-end test CI on: push jobs: + docker_preparation: + name: Fullstack test preparation + runs-on: ubuntu-latest + outputs: + pr-number: ${{ steps.pr.outputs.number }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Copy env files + run: | + cp webapp/.env.template webapp/.env + cp backend/.env.template backend/.env + + - name: Build docker images + run: | + mkdir /tmp/images + docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/ + docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/images/neo4j.tar + docker build --target test -t "ocelotsocialnetwork/backend:test" backend/ + docker save "ocelotsocialnetwork/backend:test" > /tmp/images/backend.tar + docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/ + docker save "ocelotsocialnetwork/webapp:test" > /tmp/images/webapp.tar + + - name: Install cypress requirements + run: | + wget --no-verbose -O /opt/cucumber-json-formatter "https://github.com/cucumber/json-formatter/releases/download/v19.0.0/cucumber-json-formatter-linux-386" + cd backend + yarn install + yarn build + cd .. + yarn install + + - name: Get pr number + id: pr + uses: 8BitJonny/gh-get-current-pr@2.2.0 + + - name: Cache docker images + id: cache + uses: actions/cache/save@v3.3.1 + with: + path: | + /opt/cucumber-json-formatter + /home/runner/.cache/Cypress + /home/runner/work/Ocelot-Social/Ocelot-Social + /tmp/images/ + key: e2e-preparation-cache-pr${{ steps.pr.outputs.number }} + fullstack_tests: name: Fullstack tests + if: success() + needs: docker_preparation runs-on: ubuntu-latest env: jobs: 8 @@ -12,30 +62,56 @@ jobs: # run copies of the current job in parallel job: [1, 2, 3, 4, 5, 6, 7, 8] steps: - - name: Checkout code - uses: actions/checkout@v3 + - name: Restore cache + uses: actions/cache/restore@v3.3.1 + id: cache + with: + path: | + /opt/cucumber-json-formatter + /home/runner/.cache/Cypress + /home/runner/work/Ocelot-Social/Ocelot-Social + /tmp/images/ + key: e2e-preparation-cache-pr${{ needs.docker_preparation.outputs.pr-number }} + fail-on-cache-miss: true - - name: webapp | copy env file - run: cp webapp/.env.template webapp/.env - - - name: backend | copy env file - run: cp backend/.env.template backend/.env - - - name: boot up test system | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend - - - name: cypress | Fullstack tests - id: e2e-tests + - name: Boot up test system | docker-compose run: | - yarn install - yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) + chmod +x /opt/cucumber-json-formatter + sudo ln -fs /opt/cucumber-json-formatter /usr/bin/cucumber-json-formatter + docker load < /tmp/images/neo4j.tar + docker load < /tmp/images/backend.tar + docker load < /tmp/images/webapp.tar + docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend + sleep 90s - ########################################################################## - # UPLOAD SCREENSHOTS - IF TESTS FAIL ##################################### - ########################################################################## - - name: Full stack tests | if any test failed, upload screenshots + - name: Full stack tests | run tests + id: e2e-tests + run: yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) + + - name: Full stack tests | if tests failed, compile html report + if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} + run: | + cd cypress/ + node create-cucumber-html-report.js + + - name: Full stack tests | if tests failed, upload report + id: e2e-report if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} uses: actions/upload-artifact@v3 with: - name: cypress-screenshots - path: cypress/screenshots/ + name: ocelot-e2e-test-report-pr${{ needs.docker_preparation.outputs.pr-number }} + path: /home/runner/work/Ocelot-Social/Ocelot-Social/cypress/reports/cucumber_html_report + + cleanup: + name: Cleanup + if: always() + needs: [docker_preparation, fullstack_tests] + runs-on: ubuntu-latest + steps: + - name: Delete cache + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh extension install actions/gh-actions-cache + KEY="e2e-preparation-cache-pr${{ needs.docker_preparation.outputs.pr-number }}" + gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm \ No newline at end of file diff --git a/.github/workflows/test-webapp.yml b/.github/workflows/test-webapp.yml index 9ca3023cc..c1aee47cf 100644 --- a/.github/workflows/test-webapp.yml +++ b/.github/workflows/test-webapp.yml @@ -23,7 +23,7 @@ jobs: prepare: name: Prepare - if: needs.files-changed.outputs.webapp + if: needs.files-changed.outputs.webapp == 'true' needs: files-changed runs-on: ubuntu-latest steps: @@ -37,7 +37,7 @@ jobs: build_test_webapp: name: Docker Build Test - Webapp - if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp + if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp == 'true' needs: [files-changed, prepare] runs-on: ubuntu-latest steps: @@ -57,7 +57,7 @@ jobs: lint_webapp: name: Lint Webapp - if: needs.files-changed.outputs.webapp + if: needs.files-changed.outputs.webapp == 'true' needs: files-changed runs-on: ubuntu-latest steps: @@ -69,7 +69,7 @@ jobs: unit_test_webapp: name: Unit Tests - Webapp - if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp + if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp == 'true' needs: [files-changed, build_test_webapp] runs-on: ubuntu-latest permissions: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7030227c9..cc09544ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,68 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [2.7.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.6.0...2.7.0) + +- fix(webapp): fix event teaser date from start to end by new components [`#6385`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6385) +- refactor(webapp): optimize create and update event form [`#6381`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6381) +- feat(backend): show events not ended yet [`#6405`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6405) +- feat(backend): migration to add postType property to existing posts [`#6396`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6396) +- feat(backend): seed events [`#6391`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6391) +- feat(backend): seed posts as article [`#6227`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6227) +- refactor(webapp): fix coverage [`#6361`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6361) +- test(other): migrate cypress to v12 [`#6008`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6008) +- refactor(backend): copy files in external script [`#6364`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6364) +- feat(webapp): alternative solution for filter and order posts [`#6367`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6367) +- refactor(webapp): changed color for event-ribbon. [`#6362`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6362) +- fix(webapp): warnings in unit tests [`#6359`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6359) +- Bump metascraper-title from 5.33.5 to 5.34.7 in /backend [`#6372`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6372) +- Bump @babel/preset-env from 7.21.5 to 7.22.4 [`#6369`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6369) +- fix(other): typescript fix regarding dist/build folder 2 [`#6366`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6366) +- fix(backend): corrected path in branded images for backend build folder(former dist) [`#6365`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6365) +- chore(other): upgrade node version in '.nvmrc' files to v20.2.0 [`#6331`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6331) +- feat(backend): typescript [`#6321`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6321) +- fix(webapp): fix group list number to six [`#6319`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6319) +- fix(webapp): fix notification menu comment hash [`#6335`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6335) +- feat(other): 🍰 epic events – master [`#6199`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6199) +- fix(other): fix avatar seeding [`#6260`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6260) +- chore(other): set 'DEBUG=true' in backend '.env.template' to use GraphQL Playground [`#6333`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6333) +- refactor(other): unused packages ocelot [`#6326`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6326) +- refactor(backend): unused packages backend [`#6325`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6325) +- docs(other): add description for script usage in deployment readme [`#6329`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6329) +- fix(webapp): fix newsfeed layout [`#6154`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6154) +- fix(webapp): adds white space after user handle in comment editor [`#6308`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6308) +- Bump validator from 13.0.0 to 13.9.0 in /backend [`#6076`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6076) +- Bump metascraper-soundcloud from 5.34.2 to 5.34.4 in /backend [`#6312`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6312) +- Bump metascraper-audio from 5.33.5 to 5.34.4 in /backend [`#6287`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6287) +- Bump node from 19.9.0-alpine3.17 to 20.2.0-alpine3.17 in /backend [`#6310`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6310) +- docs(other): add missing todo in deployment readme 'TODO-next-update.md' [`#6324`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6324) +- Bump node from 20.1.0-alpine3.17 to 20.2.0-alpine3.17 in /webapp [`#6309`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6309) +- fix(backend): helmet fix [`#6318`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6318) +- fix(backend): helmet + graphiql [`#6303`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6303) +- Bump @babel/preset-env from 7.21.4 to 7.21.5 [`#6273`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6273) +- Bump date-fns from 2.25.0 to 2.30.0 [`#6283`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6283) +- Bump node from 19.9.0-alpine3.17 to 20.1.0-alpine3.17 in /webapp [`#6280`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6280) +- Bump @babel/core from 7.21.4 to 7.21.8 [`#6284`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6284) +- Bump helmet from 3.22.0 to 7.0.0 in /backend [`#6296`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6296) +- fix(webapp): fix z layer of header elements [`#6279`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6279) +- fix(webapp): properly render avatars in group settings [`#6289`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6289) +- fix(backend): post type on notifications [`#6257`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6257) +- fix(backend): recover missing commit [`#6262`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6262) +- feat(backend): filter posts by post type [`#6255`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6255) +- feat(backend): save location address [`#6240`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6240) +- feat(backend): add further event params [`#6231`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6231) +- feat(backend): event parameters [`#6198`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6198) +- feat(backend): create and update posts with labels [`#6197`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6197) +- feat(backend): add article label to posts [`#6196`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6196) +- Cypress: update packaage info [`b38769b`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/b38769b048e9cb9ca07862a61ea810f21b4ce82a) +- update cypress related packageges in package.json [`692ec2a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/692ec2a11555600647ec8d95b8296c9869948b02) +- fixed coverage reporting [`540cd40`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/540cd40e10ec0461ef17379cb93d914839f3a84f) + #### [2.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.1...2.6.0) +> 27 April 2023 + +- chore(release): v2.6.0 [`#6271`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6271) - fix(other): docker-compose for rebranding deployment [`#6265`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6265) - feat(webapp): default categories of group for posts in group [`#6259`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6259) - refactor(webapp): make action radius select in group form a reusable component [`#6244`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6244) diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js index 0000bb066..cc5440d82 100644 --- a/backend/.eslintrc.js +++ b/backend/.eslintrc.js @@ -1,25 +1,219 @@ module.exports = { + root: true, env: { - es6: true, + // es6: true, node: true, - jest: true }, - parserOptions: { + /* parserOptions: { parser: 'babel-eslint' - }, + },*/ + parser: '@typescript-eslint/parser', + plugins: ['prettier', '@typescript-eslint' /*, 'import', 'n', 'promise'*/], extends: [ 'standard', - 'plugin:prettier/recommended' + // 'eslint:recommended', + 'plugin:prettier/recommended', + // 'plugin:import/recommended', + // 'plugin:import/typescript', + // 'plugin:security/recommended', + // 'plugin:@eslint-community/eslint-comments/recommended', ], - plugins: [ - 'jest' - ], - rules: { + settings: { + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + 'import/resolver': { + typescript: { + project: ['./tsconfig.json'], + }, + node: true, + }, + }, + /* rules: { //'indent': [ 'error', 2 ], //'quotes': [ "error", "single"], // 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', - 'no-console': ['error'], - 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', - 'prettier/prettier': ['error'], + > 'no-console': ['error'], + > 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', + > 'prettier/prettier': ['error'], + }, */ + rules: { + 'no-console': 'error', + camelcase: 'error', + 'no-debugger': 'error', + 'prettier/prettier': [ + 'error', + { + htmlWhitespaceSensitivity: 'ignore', + }, + ], + // import + // 'import/export': 'error', + // 'import/no-deprecated': 'error', + // 'import/no-empty-named-blocks': 'error', + // 'import/no-extraneous-dependencies': 'error', + // 'import/no-mutable-exports': 'error', + // 'import/no-unused-modules': 'error', + // 'import/no-named-as-default': 'error', + // 'import/no-named-as-default-member': 'error', + // 'import/no-amd': 'error', + // 'import/no-commonjs': 'error', + // 'import/no-import-module-exports': 'error', + // 'import/no-nodejs-modules': 'off', + // 'import/unambiguous': 'error', + // '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': 'error', + // 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }], + // 'import/no-self-import': 'error', + // 'import/no-unresolved': 'error', + // 'import/no-useless-path-segments': 'error', + // 'import/no-webpack-loader-syntax': 'error', + // 'import/consistent-type-specifier-style': 'error', + // 'import/exports-last': 'off', + // 'import/extensions': 'error', + // 'import/first': 'error', + // 'import/group-exports': '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-namespace': 'error', + // 'import/no-unassigned-import': 'error', + // 'import/order': [ + // 'error', + // { + // groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], + // 'newlines-between': 'always', + // pathGroups: [ + // { + // pattern: '@?*/**', + // group: 'external', + // position: 'after', + // }, + // { + // pattern: '@/**', + // group: 'external', + // position: 'after', + // }, + // ], + // alphabetize: { + // order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, + // caseInsensitive: true /* ignore case. Options: [true, false] */, + // }, + // distinctGroup: true, + // }, + // ], + // 'import/prefer-default-export': 'off', + // n + // 'n/handle-callback-err': 'error', + // 'n/no-callback-literal': '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': 'off', // not compatible with typescript + // 'n/no-missing-require': 'error', + // 'n/no-new-require': 'error', + // 'n/no-path-concat': 'error', + // 'n/no-process-exit': 'error', + // 'n/no-unpublished-bin': 'error', + // 'n/no-unpublished-import': 'off', // TODO need to exclude seeds + // 'n/no-unpublished-require': 'error', + // 'n/no-unsupported-features': ['error', { ignores: ['modules'] }], + // 'n/no-unsupported-features/es-builtins': 'error', + // 'n/no-unsupported-features/es-syntax': 'error', + // 'n/no-unsupported-features/node-builtins': 'error', + // 'n/process-exit-as-throw': 'error', + // 'n/shebang': 'error', + // 'n/callback-return': 'error', + // 'n/exports-style': 'error', + // 'n/file-extension-in-import': 'off', + // 'n/global-require': 'error', + // 'n/no-mixed-requires': 'error', + // 'n/no-process-env': 'error', + // 'n/no-restricted-import': 'error', + // 'n/no-restricted-require': 'error', + // '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': 'error', + // 'n/prefer-global/url-search-params': 'error', + // 'n/prefer-promises/dns': 'error', + // 'n/prefer-promises/fs': 'error', + // promise + // 'promise/catch-or-return': 'error', + // 'promise/no-return-wrap': 'error', + // 'promise/param-names': 'error', + // 'promise/always-return': 'error', + // 'promise/no-native': 'off', + // 'promise/no-nesting': 'warn', + // 'promise/no-promise-in-callback': 'warn', + // 'promise/no-callback-in-promise': 'warn', + // 'promise/avoid-new': 'warn', + // 'promise/no-new-statics': 'error', + // 'promise/no-return-in-finally': 'warn', + // 'promise/valid-params': 'warn', + // 'promise/prefer-await-to-callbacks': 'error', + // 'promise/no-multiple-resolved': 'error', + // eslint comments + // '@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }], + // '@eslint-community/eslint-comments/no-restricted-disable': 'error', + // '@eslint-community/eslint-comments/no-use': 'off', + // '@eslint-community/eslint-comments/require-description': 'off', }, + overrides: [ + // only for ts files + { + files: ['*.ts', '*.tsx'], + extends: [ + // 'plugin:@typescript-eslint/recommended', + // 'plugin:@typescript-eslint/recommended-requiring-type-checking', + // 'plugin:@typescript-eslint/strict', + ], + rules: { + // allow explicitly defined dangling promises + // '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }], + 'no-void': ['error', { allowAsStatement: true }], + // ignore prefer-regexp-exec rule to allow string.match(regex) + '@typescript-eslint/prefer-regexp-exec': 'off', + // this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486 + 'import/unambiguous': 'off', + // this is not compatible with typeorm, due to joined tables can be null, but are not defined as nullable + '@typescript-eslint/no-unnecessary-condition': 'off', + }, + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], + // this is to properly reference the referenced project database without requirement of compiling it + // eslint-disable-next-line camelcase + EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true, + }, + }, + { + files: ['*.spec.ts'], + plugins: ['jest'], + env: { + jest: true, + }, + rules: { + 'jest/no-disabled-tests': 'error', + 'jest/no-focused-tests': 'error', + 'jest/no-identical-title': 'error', + 'jest/prefer-to-have-length': 'error', + 'jest/valid-expect': 'error', + '@typescript-eslint/unbound-method': 'off', + // 'jest/unbound-method': 'error', + }, + }, + ], }; diff --git a/backend/jest.config.js b/backend/jest.config.js index 38c59916d..d1cc7bd3f 100644 --- a/backend/jest.config.js +++ b/backend/jest.config.js @@ -1,18 +1,19 @@ module.exports = { verbose: true, + preset: 'ts-jest', collectCoverage: true, collectCoverageFrom: [ - '**/*.js', + '**/*.ts', '!**/node_modules/**', '!**/test/**', '!**/build/**', - '!**/src/**/?(*.)+(spec|test).js?(x)' + '!**/src/**/?(*.)+(spec|test).ts?(x)' ], coverageThreshold: { global: { - lines: 57, + lines: 67, }, }, - testMatch: ['**/src/**/?(*.)+(spec|test).js?(x)'], - setupFilesAfterEnv: ['/test/setup.js'] + testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'], + setupFilesAfterEnv: ['/test/setup.ts'] } diff --git a/backend/package.json b/backend/package.json index eb8119a8f..48703b649 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,26 +1,26 @@ { "name": "ocelot-social-backend", - "version": "2.6.0", + "version": "2.7.0", "description": "GraphQL Backend for ocelot.social", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "author": "ocelot.social Community", "license": "MIT", "private": false, - "main": "src/index.js", + "main": "src/index.ts", "scripts": { - "__migrate": "migrate --compiler 'js:@babel/register' --migrations-dir ./src/db/migrations", - "prod:migrate": "migrate --migrations-dir ./build/db/migrations --store ./build/db/migrate/store.js", - "start": "node build/", + "__migrate": "migrate --compiler 'ts:./src/db/compiler.ts' --migrations-dir ./src/db/migrations", + "prod:migrate": "migrate --migrations-dir ./build/src/db/migrations --store ./build/src/db/migrate/store.js", + "start": "node build/src/", "build": "tsc && ./scripts/build.copy.files.sh", "dev": "nodemon --exec ts-node src/ -e js,ts,gql", - "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql", - "lint": "eslint src --config .eslintrc.js", + "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,ts,gql", + "lint": "eslint --max-warnings=0 --ext .js,.ts ./src", "test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --runInBand --coverage --forceExit --detectOpenHandles", - "db:clean": "babel-node src/db/clean.js", + "db:clean": "ts-node src/db/clean.ts", "db:reset": "yarn run db:clean", - "db:seed": "babel-node src/db/seed.js", - "db:migrate": "yarn run __migrate --store ./src/db/migrate/store.js", - "db:migrate:create": "yarn run __migrate --template-file ./src/db/migrate/template.js --date-format 'yyyymmddHHmmss' create" + "db:seed": "ts-node src/db/seed.ts", + "db:migrate": "yarn run __migrate --store ./src/db/migrate/store.ts", + "db:migrate:create": "yarn run __migrate --template-file ./src/db/migrate/template.ts --date-format 'yyyymmddHHmmss' create" }, "dependencies": { "@babel/cli": "~7.8.4", @@ -45,7 +45,6 @@ "cheerio": "~1.0.0-rc.3", "cors": "~2.8.5", "cross-env": "~7.0.3", - "debug": "~4.1.1", "dotenv": "~8.2.0", "express": "^4.17.1", "graphql": "^14.6.0", @@ -76,7 +75,7 @@ "metascraper-url": "^5.34.2", "metascraper-video": "^5.33.5", "metascraper-youtube": "^5.33.5", - "migrate": "^1.7.0", + "migrate": "^2.0.0", "mime-types": "^2.1.26", "minimatch": "^3.0.4", "mustache": "^4.2.0", @@ -97,24 +96,30 @@ }, "devDependencies": { "@faker-js/faker": "7.6.0", + "@types/jest": "^27.0.2", + "@types/node": "^20.2.5", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", "apollo-server-testing": "~2.11.0", "chai": "~4.2.0", "cucumber": "~6.0.5", - "eslint": "~6.8.0", - "eslint-config-prettier": "~6.15.0", - "eslint-config-standard": "~14.1.1", - "eslint-plugin-import": "~2.20.2", - "eslint-plugin-jest": "~23.8.2", - "eslint-plugin-node": "~11.1.0", - "eslint-plugin-prettier": "~3.4.1", - "eslint-plugin-promise": "~4.3.1", - "eslint-plugin-standard": "~4.0.1", - "jest": "29.4", + "eslint": "^8.37.0", + "eslint-config-prettier": "^8.8.0", + "eslint-config-standard": "^17.0.0", + "eslint-import-resolver-typescript": "^3.5.4", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^27.2.1", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-security": "^1.7.1", + "prettier": "^2.8.7", + "jest": "^27.2.4", "nodemon": "~2.0.2", - "prettier": "~2.3.2", "rosie": "^2.0.1", + "ts-jest": "^27.0.5", "ts-node": "^10.9.1", - "typescript": "^5.0.4" + "typescript": "^4.9.4" }, "resolutions": { "**/**/fs-capacitor": "^6.2.0", diff --git a/backend/scripts/build.copy.files.sh b/backend/scripts/build.copy.files.sh index 85022ba9b..9d17f46ae 100755 --- a/backend/scripts/build.copy.files.sh +++ b/backend/scripts/build.copy.files.sh @@ -1,24 +1,24 @@ #!/bin/sh # html files -mkdir -p build/middleware/helpers/email/templates/ -cp -r src/middleware/helpers/email/templates/*.html build/middleware/helpers/email/templates/ +mkdir -p build/src/middleware/helpers/email/templates/ +cp -r src/middleware/helpers/email/templates/*.html build/src/middleware/helpers/email/templates/ -mkdir -p build/middleware/helpers/email/templates/en/ -cp -r src/middleware/helpers/email/templates/en/*.html build/middleware/helpers/email/templates/en/ +mkdir -p build/src/middleware/helpers/email/templates/en/ +cp -r src/middleware/helpers/email/templates/en/*.html build/src/middleware/helpers/email/templates/en/ -mkdir -p build/middleware/helpers/email/templates/de/ -cp -r src/middleware/helpers/email/templates/de/*.html build/middleware/helpers/email/templates/de/ +mkdir -p build/src/middleware/helpers/email/templates/de/ +cp -r src/middleware/helpers/email/templates/de/*.html build/src/middleware/helpers/email/templates/de/ # gql files -mkdir -p build/schema/types/ -cp -r src/schema/types/*.gql build/schema/types/ +mkdir -p build/src/schema/types/ +cp -r src/schema/types/*.gql build/src/schema/types/ -mkdir -p build/schema/types/enum/ -cp -r src/schema/types/enum/*.gql build/schema/types/enum/ +mkdir -p build/src/schema/types/enum/ +cp -r src/schema/types/enum/*.gql build/src/schema/types/enum/ -mkdir -p build/schema/types/scalar/ -cp -r src/schema/types/scalar/*.gql build/schema/types/scalar/ +mkdir -p build/src/schema/types/scalar/ +cp -r src/schema/types/scalar/*.gql build/src/schema/types/scalar/ -mkdir -p build/schema/types/type/ -cp -r src/schema/types/type/*.gql build/schema/types/type/ \ No newline at end of file +mkdir -p build/src/schema/types/type/ +cp -r src/schema/types/type/*.gql build/src/schema/types/type/ \ No newline at end of file diff --git a/backend/src/activitypub/ActivityPub.js b/backend/src/activitypub/ActivityPub.js deleted file mode 100644 index 7ecc9d3fe..000000000 --- a/backend/src/activitypub/ActivityPub.js +++ /dev/null @@ -1,240 +0,0 @@ -// import { extractDomainFromUrl, signAndSend } from './utils' -import { extractNameFromId, signAndSend } from './utils' -import { isPublicAddressed } from './utils/activity' -// import { isPublicAddressed, sendAcceptActivity, sendRejectActivity } from './utils/activity' -import request from 'request' -// import as from 'activitystrea.ms' -import NitroDataSource from './NitroDataSource' -import router from './routes' -import Collections from './Collections' -import { v4 as uuid } from 'uuid' -import CONFIG from '../config' -const debug = require('debug')('ea') - -let activityPub = null - -export { activityPub } - -export default class ActivityPub { - constructor(activityPubEndpointUri, internalGraphQlUri) { - this.endpoint = activityPubEndpointUri - this.dataSource = new NitroDataSource(internalGraphQlUri) - this.collections = new Collections(this.dataSource) - } - - static init(server) { - if (!activityPub) { - activityPub = new ActivityPub(CONFIG.CLIENT_URI, CONFIG.GRAPHQL_URI) - - // integrate into running graphql express server - server.express.set('ap', activityPub) - server.express.use(router) - console.log('-> ActivityPub middleware added to the graphql express server') // eslint-disable-line no-console - } else { - console.log('-> ActivityPub middleware already added to the graphql express server') // eslint-disable-line no-console - } - } - - // handleFollowActivity(activity) { - // debug(`inside FOLLOW ${activity.actor}`) - // const toActorName = extractNameFromId(activity.object) - // const fromDomain = extractDomainFromUrl(activity.actor) - // const dataSource = this.dataSource - - // return new Promise((resolve, reject) => { - // request( - // { - // url: activity.actor, - // headers: { - // Accept: 'application/activity+json', - // }, - // }, - // async (err, response, toActorObject) => { - // if (err) return reject(err) - // // save shared inbox - // toActorObject = JSON.parse(toActorObject) - // await this.dataSource.addSharedInboxEndpoint(toActorObject.endpoints.sharedInbox) - - // const followersCollectionPage = await this.dataSource.getFollowersCollectionPage( - // activity.object, - // ) - - // const followActivity = as - // .follow() - // .id(activity.id) - // .actor(activity.actor) - // .object(activity.object) - - // // add follower if not already in collection - // if (followersCollectionPage.orderedItems.includes(activity.actor)) { - // debug('follower already in collection!') - // debug(`inbox = ${toActorObject.inbox}`) - // resolve( - // sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox), - // ) - // } else { - // followersCollectionPage.orderedItems.push(activity.actor) - // } - // debug(`toActorObject = ${toActorObject}`) - // toActorObject = - // typeof toActorObject !== 'object' ? JSON.parse(toActorObject) : toActorObject - // debug(`followers = ${JSON.stringify(followersCollectionPage.orderedItems, null, 2)}`) - // debug(`inbox = ${toActorObject.inbox}`) - // debug(`outbox = ${toActorObject.outbox}`) - // debug(`followers = ${toActorObject.followers}`) - // debug(`following = ${toActorObject.following}`) - - // try { - // await dataSource.saveFollowersCollectionPage(followersCollectionPage) - // debug('follow activity saved') - // resolve( - // sendAcceptActivity(followActivity, toActorName, fromDomain, toActorObject.inbox), - // ) - // } catch (e) { - // debug('followers update error!', e) - // resolve( - // sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox), - // ) - // } - // }, - // ) - // }) - // } - - handleUndoActivity(activity) { - debug('inside UNDO') - switch (activity.object.type) { - case 'Follow': { - const followActivity = activity.object - return this.dataSource.undoFollowActivity(followActivity.actor, followActivity.object) - } - case 'Like': { - return this.dataSource.deleteShouted(activity) - } - } - } - - handleCreateActivity(activity) { - debug('inside create') - switch (activity.object.type) { - case 'Note': { - const articleObject = activity.object - if (articleObject.inReplyTo) { - return this.dataSource.createComment(activity) - } else { - return this.dataSource.createPost(activity) - } - } - } - } - - handleDeleteActivity(activity) { - debug('inside delete') - switch (activity.object.type) { - case 'Article': - case 'Note': - return this.dataSource.deletePost(activity) - default: - } - } - - handleUpdateActivity(activity) { - debug('inside update') - switch (activity.object.type) { - case 'Note': - case 'Article': - return this.dataSource.updatePost(activity) - default: - } - } - - handleLikeActivity(activity) { - // TODO differ if activity is an Article/Note/etc. - return this.dataSource.createShouted(activity) - } - - handleDislikeActivity(activity) { - // TODO differ if activity is an Article/Note/etc. - return this.dataSource.deleteShouted(activity) - } - - async handleAcceptActivity(activity) { - debug('inside accept') - switch (activity.object.type) { - case 'Follow': { - const followObject = activity.object - const followingCollectionPage = await this.collections.getFollowingCollectionPage( - followObject.actor, - ) - followingCollectionPage.orderedItems.push(followObject.object) - await this.dataSource.saveFollowingCollectionPage(followingCollectionPage) - } - } - } - - getActorObject(url) { - return new Promise((resolve, reject) => { - request( - { - url: url, - headers: { - Accept: 'application/json', - }, - }, - (err, response, body) => { - if (err) { - reject(err) - } - resolve(JSON.parse(body)) - }, - ) - }) - } - - generateStatusId(slug) { - return `https://${this.host}/activitypub/users/${slug}/status/${uuid()}` - } - - async sendActivity(activity) { - delete activity.send - const fromName = extractNameFromId(activity.actor) - if (Array.isArray(activity.to) && isPublicAddressed(activity)) { - debug('is public addressed') - const sharedInboxEndpoints = await this.dataSource.getSharedInboxEndpoints() - // serve shared inbox endpoints - sharedInboxEndpoints.map((sharedInbox) => { - return this.trySend(activity, fromName, new URL(sharedInbox).host, sharedInbox) - }) - activity.to = activity.to.filter((recipient) => { - return !isPublicAddressed({ to: recipient }) - }) - // serve the rest - activity.to.map(async (recipient) => { - debug('serve rest') - const actorObject = await this.getActorObject(recipient) - return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox) - }) - } else if (typeof activity.to === 'string') { - debug('is string') - const actorObject = await this.getActorObject(activity.to) - return this.trySend(activity, fromName, new URL(activity.to).host, actorObject.inbox) - } else if (Array.isArray(activity.to)) { - activity.to.map(async (recipient) => { - const actorObject = await this.getActorObject(recipient) - return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox) - }) - } - } - - async trySend(activity, fromName, host, url, tries = 5) { - try { - return await signAndSend(activity, fromName, host, url) - } catch (e) { - if (tries > 0) { - setTimeout(function () { - return this.trySend(activity, fromName, host, url, --tries) - }, 20000) - } - } - } -} diff --git a/backend/src/activitypub/Collections.js b/backend/src/activitypub/Collections.js deleted file mode 100644 index 4040468cf..000000000 --- a/backend/src/activitypub/Collections.js +++ /dev/null @@ -1,29 +0,0 @@ -export default class Collections { - constructor(dataSource) { - this.dataSource = dataSource - } - - getFollowersCollection(actorId) { - return this.dataSource.getFollowersCollection(actorId) - } - - getFollowersCollectionPage(actorId) { - return this.dataSource.getFollowersCollectionPage(actorId) - } - - getFollowingCollection(actorId) { - return this.dataSource.getFollowingCollection(actorId) - } - - getFollowingCollectionPage(actorId) { - return this.dataSource.getFollowingCollectionPage(actorId) - } - - getOutboxCollection(actorId) { - return this.dataSource.getOutboxCollection(actorId) - } - - getOutboxCollectionPage(actorId) { - return this.dataSource.getOutboxCollectionPage(actorId) - } -} diff --git a/backend/src/activitypub/NitroDataSource.js b/backend/src/activitypub/NitroDataSource.js deleted file mode 100644 index 476c91439..000000000 --- a/backend/src/activitypub/NitroDataSource.js +++ /dev/null @@ -1,575 +0,0 @@ -import { - throwErrorIfApolloErrorOccurred, - extractIdFromActivityId, - extractNameFromId, - constructIdFromName, -} from './utils' -import { createOrderedCollection, createOrderedCollectionPage } from './utils/collection' -import { createArticleObject, isPublicAddressed } from './utils/activity' -import crypto from 'crypto' -import gql from 'graphql-tag' -import { createHttpLink } from 'apollo-link-http' -import { setContext } from 'apollo-link-context' -import { InMemoryCache } from 'apollo-cache-inmemory' -import fetch from 'node-fetch' -import { ApolloClient } from 'apollo-client' -import trunc from 'trunc-html' -const debug = require('debug')('ea:datasource') - -export default class NitroDataSource { - constructor(uri) { - this.uri = uri - const defaultOptions = { - query: { - fetchPolicy: 'network-only', - errorPolicy: 'all', - }, - } - const link = createHttpLink({ uri: this.uri, fetch: fetch }) // eslint-disable-line - const cache = new InMemoryCache() - const authLink = setContext((_, { headers }) => { - // generate the authentication token (maybe from env? Which user?) - const token = - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJuYW1lIjoiUGV0ZXIgTHVzdGlnIiwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9qb2huY2FmYXp6YS8xMjguanBnIiwiaWQiOiJ1MSIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJzbHVnIjoicGV0ZXItbHVzdGlnIiwiaWF0IjoxNTUyNDIwMTExLCJleHAiOjE2Mzg4MjAxMTEsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMCIsInN1YiI6InUxIn0.G7An1yeQUViJs-0Qj-Tc-zm0WrLCMB3M02pfPnm6xzw' - // return the headers to the context so httpLink can read them - return { - headers: { - ...headers, - Authorization: token ? `Bearer ${token}` : '', - }, - } - }) - this.client = new ApolloClient({ - link: authLink.concat(link), - cache: cache, - defaultOptions, - }) - } - - async getFollowersCollection(actorId) { - const slug = extractNameFromId(actorId) - debug(`slug= ${slug}`) - const result = await this.client.query({ - query: gql` - query { - User(slug: "${slug}") { - followedByCount - } - } - `, - }) - debug('successfully fetched followers') - debug(result.data) - if (result.data) { - const actor = result.data.User[0] - const followersCount = actor.followedByCount - - const followersCollection = createOrderedCollection(slug, 'followers') - followersCollection.totalItems = followersCount - - return followersCollection - } else { - throwErrorIfApolloErrorOccurred(result) - } - } - - async getFollowersCollectionPage(actorId) { - const slug = extractNameFromId(actorId) - debug(`getFollowersPage slug = ${slug}`) - const result = await this.client.query({ - query: gql` - query { - User(slug:"${slug}") { - followedBy { - slug - } - followedByCount - } - } - `, - }) - - debug(result.data) - if (result.data) { - const actor = result.data.User[0] - const followers = actor.followedBy - const followersCount = actor.followedByCount - - const followersCollection = createOrderedCollectionPage(slug, 'followers') - followersCollection.totalItems = followersCount - debug(`followers = ${JSON.stringify(followers, null, 2)}`) - await Promise.all( - followers.map(async (follower) => { - followersCollection.orderedItems.push(constructIdFromName(follower.slug)) - }), - ) - - return followersCollection - } else { - throwErrorIfApolloErrorOccurred(result) - } - } - - async getFollowingCollection(actorId) { - const slug = extractNameFromId(actorId) - const result = await this.client.query({ - query: gql` - query { - User(slug:"${slug}") { - followingCount - } - } - `, - }) - - debug(result.data) - if (result.data) { - const actor = result.data.User[0] - const followingCount = actor.followingCount - - const followingCollection = createOrderedCollection(slug, 'following') - followingCollection.totalItems = followingCount - - return followingCollection - } else { - throwErrorIfApolloErrorOccurred(result) - } - } - - async getFollowingCollectionPage(actorId) { - const slug = extractNameFromId(actorId) - const result = await this.client.query({ - query: gql` - query { - User(slug:"${slug}") { - following { - slug - } - followingCount - } - } - `, - }) - - debug(result.data) - if (result.data) { - const actor = result.data.User[0] - const following = actor.following - const followingCount = actor.followingCount - - const followingCollection = createOrderedCollectionPage(slug, 'following') - followingCollection.totalItems = followingCount - - await Promise.all( - following.map(async (user) => { - followingCollection.orderedItems.push(await constructIdFromName(user.slug)) - }), - ) - - return followingCollection - } else { - throwErrorIfApolloErrorOccurred(result) - } - } - - async getOutboxCollection(actorId) { - const slug = extractNameFromId(actorId) - const result = await this.client.query({ - query: gql` - query { - User(slug:"${slug}") { - contributions { - title - slug - content - contentExcerpt - createdAt - } - } - } - `, - }) - - debug(result.data) - if (result.data) { - const actor = result.data.User[0] - const posts = actor.contributions - - const outboxCollection = createOrderedCollection(slug, 'outbox') - outboxCollection.totalItems = posts.length - - return outboxCollection - } else { - throwErrorIfApolloErrorOccurred(result) - } - } - - async getOutboxCollectionPage(actorId) { - const slug = extractNameFromId(actorId) - debug(`inside getting outbox collection page => ${slug}`) - const result = await this.client.query({ - query: gql` - query { - User(slug:"${slug}") { - actorId - contributions { - id - activityId - objectId - title - slug - content - contentExcerpt - createdAt - author { - slug - } - } - } - } - `, - }) - - debug(result.data) - if (result.data) { - const actor = result.data.User[0] - const posts = actor.contributions - - const outboxCollection = createOrderedCollectionPage(slug, 'outbox') - outboxCollection.totalItems = posts.length - await Promise.all( - posts.map(async (post) => { - outboxCollection.orderedItems.push( - await createArticleObject( - post.activityId, - post.objectId, - post.content, - post.author.slug, - post.id, - post.createdAt, - ), - ) - }), - ) - - debug('after createNote') - return outboxCollection - } else { - throwErrorIfApolloErrorOccurred(result) - } - } - - async undoFollowActivity(fromActorId, toActorId) { - const fromUserId = await this.ensureUser(fromActorId) - const toUserId = await this.ensureUser(toActorId) - const result = await this.client.mutate({ - mutation: gql` - mutation { - RemoveUserFollowedBy(from: {id: "${fromUserId}"}, to: {id: "${toUserId}"}) { - from { name } - } - } - `, - }) - debug(`undoFollowActivity result = ${JSON.stringify(result, null, 2)}`) - throwErrorIfApolloErrorOccurred(result) - } - - async saveFollowersCollectionPage(followersCollection, onlyNewestItem = true) { - debug('inside saveFollowers') - let orderedItems = followersCollection.orderedItems - const toUserName = extractNameFromId(followersCollection.id) - const toUserId = await this.ensureUser(constructIdFromName(toUserName)) - orderedItems = onlyNewestItem ? [orderedItems.pop()] : orderedItems - - return Promise.all( - orderedItems.map(async (follower) => { - debug(`follower = ${follower}`) - const fromUserId = await this.ensureUser(follower) - debug(`fromUserId = ${fromUserId}`) - debug(`toUserId = ${toUserId}`) - const result = await this.client.mutate({ - mutation: gql` - mutation { - AddUserFollowedBy(from: {id: "${fromUserId}"}, to: {id: "${toUserId}"}) { - from { name } - } - } - `, - }) - debug(`addUserFollowedBy edge = ${JSON.stringify(result, null, 2)}`) - throwErrorIfApolloErrorOccurred(result) - debug('saveFollowers: added follow edge successfully') - }), - ) - } - - async saveFollowingCollectionPage(followingCollection, onlyNewestItem = true) { - debug('inside saveFollowers') - let orderedItems = followingCollection.orderedItems - const fromUserName = extractNameFromId(followingCollection.id) - const fromUserId = await this.ensureUser(constructIdFromName(fromUserName)) - orderedItems = onlyNewestItem ? [orderedItems.pop()] : orderedItems - return Promise.all( - orderedItems.map(async (following) => { - debug(`follower = ${following}`) - const toUserId = await this.ensureUser(following) - debug(`fromUserId = ${fromUserId}`) - debug(`toUserId = ${toUserId}`) - const result = await this.client.mutate({ - mutation: gql` - mutation { - AddUserFollowing(from: {id: "${fromUserId}"}, to: {id: "${toUserId}"}) { - from { name } - } - } - `, - }) - debug(`addUserFollowing edge = ${JSON.stringify(result, null, 2)}`) - throwErrorIfApolloErrorOccurred(result) - debug('saveFollowing: added follow edge successfully') - }), - ) - } - - async createPost(activity) { - // TODO how to handle the to field? Now the post is just created, doesn't matter who is the recipient - // createPost - const postObject = activity.object - if (!isPublicAddressed(postObject)) { - return debug( - 'createPost: not send to public (sending to specific persons is not implemented yet)', - ) - } - const title = postObject.summary - ? postObject.summary - : postObject.content.split(' ').slice(0, 5).join(' ') - const postId = extractIdFromActivityId(postObject.id) - debug('inside create post') - let result = await this.client.mutate({ - mutation: gql` - mutation { - CreatePost(content: "${postObject.content}", contentExcerpt: "${trunc( - postObject.content, - 120, - )}", title: "${title}", id: "${postId}", objectId: "${postObject.id}", activityId: "${ - activity.id - }") { - id - } - } - `, - }) - - throwErrorIfApolloErrorOccurred(result) - - // ensure user and add author to post - const userId = await this.ensureUser(postObject.attributedTo) - debug(`userId = ${userId}`) - debug(`postId = ${postId}`) - result = await this.client.mutate({ - mutation: gql` - mutation { - AddPostAuthor(from: {id: "${userId}"}, to: {id: "${postId}"}) { - from { - name - } - } - } - `, - }) - - throwErrorIfApolloErrorOccurred(result) - } - - async deletePost(activity) { - const result = await this.client.mutate({ - mutation: gql` - mutation { - DeletePost(id: "${extractIdFromActivityId(activity.object.id)}") { - title - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - } - - async updatePost(activity) { - const postObject = activity.object - const postId = extractIdFromActivityId(postObject.id) - const date = postObject.updated ? postObject.updated : new Date().toISOString() - const result = await this.client.mutate({ - mutation: gql` - mutation { - UpdatePost(content: "${postObject.content}", contentExcerpt: "${ - trunc(postObject.content, 120).html - }", id: "${postId}", updatedAt: "${date}") { - title - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - } - - async createShouted(activity) { - const userId = await this.ensureUser(activity.actor) - const postId = extractIdFromActivityId(activity.object) - const result = await this.client.mutate({ - mutation: gql` - mutation { - AddUserShouted(from: {id: "${userId}"}, to: {id: "${postId}"}) { - from { - name - } - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - if (!result.data.AddUserShouted) { - debug('something went wrong shouting post') - throw Error('User or Post not exists') - } - } - - async deleteShouted(activity) { - const userId = await this.ensureUser(activity.actor) - const postId = extractIdFromActivityId(activity.object) - const result = await this.client.mutate({ - mutation: gql` - mutation { - RemoveUserShouted(from: {id: "${userId}"}, to: {id: "${postId}"}) { - from { - name - } - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - if (!result.data.AddUserShouted) { - debug('something went wrong disliking a post') - throw Error('User or Post not exists') - } - } - - async getSharedInboxEndpoints() { - const result = await this.client.query({ - query: gql` - query { - SharedInboxEndpoint { - uri - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - return result.data.SharedInboxEnpoint - } - - async addSharedInboxEndpoint(uri) { - try { - const result = await this.client.mutate({ - mutation: gql` - mutation { - CreateSharedInboxEndpoint(uri: "${uri}") - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - return true - } catch (e) { - return false - } - } - - async createComment(activity) { - const postObject = activity.object - let result = await this.client.mutate({ - mutation: gql` - mutation { - CreateComment(content: "${ - postObject.content - }", activityId: "${extractIdFromActivityId(activity.id)}") { - id - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - - const toUserId = await this.ensureUser(activity.actor) - const result2 = await this.client.mutate({ - mutation: gql` - mutation { - AddCommentAuthor(from: {id: "${result.data.CreateComment.id}"}, to: {id: "${toUserId}"}) { - id - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result2) - - const postId = extractIdFromActivityId(postObject.inReplyTo) - result = await this.client.mutate({ - mutation: gql` - mutation { - AddCommentPost(from: { id: "${result.data.CreateComment.id}", to: { id: "${postId}" }}) { - id - } - } - `, - }) - - throwErrorIfApolloErrorOccurred(result) - } - - /** - * This function will search for user existence and will create a disabled user with a random 16 bytes password when no user is found. - * - * @param actorId - * @returns {Promise<*>} - */ - async ensureUser(actorId) { - debug(`inside ensureUser = ${actorId}`) - const name = extractNameFromId(actorId) - const queryResult = await this.client.query({ - query: gql` - query { - User(slug: "${name}") { - id - } - } - `, - }) - - if ( - queryResult.data && - Array.isArray(queryResult.data.User) && - queryResult.data.User.length > 0 - ) { - debug('ensureUser: user exists.. return id') - // user already exists.. return the id - return queryResult.data.User[0].id - } else { - debug('ensureUser: user not exists.. createUser') - // user does not exist.. create it - const pw = crypto.randomBytes(16).toString('hex') - const slug = name.toLowerCase().split(' ').join('-') - const result = await this.client.mutate({ - mutation: gql` - mutation { - CreateUser(password: "${pw}", slug:"${slug}", actorId: "${actorId}", name: "${name}", email: "${slug}@test.org") { - id - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - - return result.data.CreateUser.id - } - } -} diff --git a/backend/src/activitypub/routes/inbox.js b/backend/src/activitypub/routes/inbox.js deleted file mode 100644 index f0f88f7e6..000000000 --- a/backend/src/activitypub/routes/inbox.js +++ /dev/null @@ -1,54 +0,0 @@ -import express from 'express' -import { activityPub } from '../ActivityPub' - -const debug = require('debug')('ea:inbox') - -const router = express.Router() - -// Shared Inbox endpoint (federated Server) -// For now its only able to handle Note Activities!! -router.post('/', async function (req, res, next) { - debug(`Content-Type = ${req.get('Content-Type')}`) - debug(`body = ${JSON.stringify(req.body, null, 2)}`) - debug(`Request headers = ${JSON.stringify(req.headers, null, 2)}`) - switch (req.body.type) { - case 'Create': - await activityPub.handleCreateActivity(req.body).catch(next) - break - case 'Undo': - await activityPub.handleUndoActivity(req.body).catch(next) - break - // case 'Follow': - // await activityPub.handleFollowActivity(req.body).catch(next) - // break - case 'Delete': - await activityPub.handleDeleteActivity(req.body).catch(next) - break - /* eslint-disable */ - case 'Update': - await activityPub.handleUpdateActivity(req.body).catch(next) - break - case 'Accept': - await activityPub.handleAcceptActivity(req.body).catch(next) - case 'Reject': - // Do nothing - break - case 'Add': - break - case 'Remove': - break - case 'Like': - await activityPub.handleLikeActivity(req.body).catch(next) - break - case 'Dislike': - await activityPub.handleDislikeActivity(req.body).catch(next) - break - case 'Announce': - debug('else!!') - debug(JSON.stringify(req.body, null, 2)) - } - /* eslint-enable */ - res.status(200).end() -}) - -export default router diff --git a/backend/src/activitypub/routes/index.js b/backend/src/activitypub/routes/index.js deleted file mode 100644 index 00ba7c22d..000000000 --- a/backend/src/activitypub/routes/index.js +++ /dev/null @@ -1,29 +0,0 @@ -import user from './user' -import inbox from './inbox' -import express from 'express' -import cors from 'cors' -import verify from './verify' - -export default function () { - const router = express.Router() - router.use( - '/activitypub/users', - cors(), - express.json({ - type: ['application/activity+json', 'application/ld+json', 'application/json'], - }), - express.urlencoded({ extended: true }), - user, - ) - router.use( - '/activitypub/inbox', - cors(), - express.json({ - type: ['application/activity+json', 'application/ld+json', 'application/json'], - }), - express.urlencoded({ extended: true }), - verify, - inbox, - ) - return router -} diff --git a/backend/src/activitypub/routes/serveUser.js b/backend/src/activitypub/routes/serveUser.js deleted file mode 100644 index dd7d80811..000000000 --- a/backend/src/activitypub/routes/serveUser.js +++ /dev/null @@ -1,54 +0,0 @@ -import { createActor } from '../utils/actor' -const gql = require('graphql-tag') -const debug = require('debug')('ea:serveUser') - -export async function serveUser(req, res, next) { - let name = req.params.name - - if (name.startsWith('@')) { - name = name.slice(1) - } - - debug(`name = ${name}`) - const result = await req.app - .get('ap') - .dataSource.client.query({ - query: gql` - query { - User(slug: "${name}") { - publicKey - } - } - `, - }) - .catch((reason) => { - debug(`serveUser User fetch error: ${reason}`) - }) - - if (result.data && Array.isArray(result.data.User) && result.data.User.length > 0) { - const publicKey = result.data.User[0].publicKey - const actor = createActor(name, publicKey) - debug(`actor = ${JSON.stringify(actor, null, 2)}`) - debug( - `accepts json = ${req.accepts([ - 'application/activity+json', - 'application/ld+json', - 'application/json', - ])}`, - ) - if (req.accepts(['application/activity+json', 'application/ld+json', 'application/json'])) { - return res.json(actor) - } else if (req.accepts('text/html')) { - // TODO show user's profile page instead of the actor object - /* const outbox = JSON.parse(result.outbox) - const posts = outbox.orderedItems.filter((el) => { return el.object.type === 'Note'}) - const actor = result.actor - debug(posts) */ - // res.render('user', { user: actor, posts: JSON.stringify(posts)}) - return res.json(actor) - } - } else { - debug(`error getting publicKey for actor ${name}`) - next() - } -} diff --git a/backend/src/activitypub/routes/user.js b/backend/src/activitypub/routes/user.js deleted file mode 100644 index 8dfdbc91d..000000000 --- a/backend/src/activitypub/routes/user.js +++ /dev/null @@ -1,92 +0,0 @@ -import { sendCollection } from '../utils/collection' -import express from 'express' -import { serveUser } from './serveUser' -import { activityPub } from '../ActivityPub' -import verify from './verify' - -const router = express.Router() -const debug = require('debug')('ea:user') - -router.get('/:name', async function (req, res, next) { - debug('inside user.js -> serveUser') - await serveUser(req, res, next) -}) - -router.get('/:name/following', (req, res) => { - debug('inside user.js -> serveFollowingCollection') - const name = req.params.name - if (!name) { - res.status(400).send('Bad request! Please specify a name.') - } else { - const collectionName = req.query.page ? 'followingPage' : 'following' - sendCollection(collectionName, req, res) - } -}) - -router.get('/:name/followers', (req, res) => { - debug('inside user.js -> serveFollowersCollection') - const name = req.params.name - if (!name) { - return res.status(400).send('Bad request! Please specify a name.') - } else { - const collectionName = req.query.page ? 'followersPage' : 'followers' - sendCollection(collectionName, req, res) - } -}) - -router.get('/:name/outbox', (req, res) => { - debug('inside user.js -> serveOutboxCollection') - const name = req.params.name - if (!name) { - return res.status(400).send('Bad request! Please specify a name.') - } else { - const collectionName = req.query.page ? 'outboxPage' : 'outbox' - sendCollection(collectionName, req, res) - } -}) - -router.post('/:name/inbox', verify, async function (req, res, next) { - debug(`body = ${JSON.stringify(req.body, null, 2)}`) - debug(`actorId = ${req.body.actor}`) - // const result = await saveActorId(req.body.actor) - switch (req.body.type) { - case 'Create': - await activityPub.handleCreateActivity(req.body).catch(next) - break - case 'Undo': - await activityPub.handleUndoActivity(req.body).catch(next) - break - // case 'Follow': - // await activityPub.handleFollowActivity(req.body).catch(next) - // break - case 'Delete': - await activityPub.handleDeleteActivity(req.body).catch(next) - break - /* eslint-disable */ - case 'Update': - await activityPub.handleUpdateActivity(req.body).catch(next) - break - case 'Accept': - await activityPub.handleAcceptActivity(req.body).catch(next) - case 'Reject': - // Do nothing - break - case 'Add': - break - case 'Remove': - break - case 'Like': - await activityPub.handleLikeActivity(req.body).catch(next) - break - case 'Dislike': - await activityPub.handleDislikeActivity(req.body).catch(next) - break - case 'Announce': - debug('else!!') - debug(JSON.stringify(req.body, null, 2)) - } - /* eslint-enable */ - res.status(200).end() -}) - -export default router diff --git a/backend/src/activitypub/routes/verify.js b/backend/src/activitypub/routes/verify.js deleted file mode 100644 index 33603805f..000000000 --- a/backend/src/activitypub/routes/verify.js +++ /dev/null @@ -1,20 +0,0 @@ -import { verifySignature } from '../security' -const debug = require('debug')('ea:verify') - -export default async (req, res, next) => { - debug(`actorId = ${req.body.actor}`) - // TODO stop if signature validation fails - if ( - await verifySignature( - `${req.protocol}://${req.hostname}:${req.app.get('port')}${req.originalUrl}`, - req.headers, - ) - ) { - debug('verify = true') - next() - } else { - // throw Error('Signature validation failed!') - debug('verify = false') - next() - } -} diff --git a/backend/src/activitypub/routes/webfinger.js b/backend/src/activitypub/routes/webfinger.js deleted file mode 100644 index 6b8f3e14c..000000000 --- a/backend/src/activitypub/routes/webfinger.js +++ /dev/null @@ -1,59 +0,0 @@ -import express from 'express' -import CONFIG from '../../config/' -import cors from 'cors' - -const debug = require('debug')('ea:webfinger') -const regex = /acct:([a-z0-9_-]*)@([a-z0-9_-]*)/ - -const createWebFinger = (name) => { - const { host } = new URL(CONFIG.CLIENT_URI) - return { - subject: `acct:${name}@${host}`, - links: [ - { - rel: 'self', - type: 'application/activity+json', - href: `${CONFIG.CLIENT_URI}/activitypub/users/${name}`, - }, - ], - } -} - -export async function handler(req, res) { - const { resource = '' } = req.query - // eslint-disable-next-line no-unused-vars - const [_, name, domain] = resource.match(regex) || [] - if (!(name && domain)) - return res.status(400).json({ - error: 'Query parameter "?resource=acct:@" is missing.', - }) - - const session = req.app.get('driver').session() - try { - const [slug] = await session.readTransaction(async (t) => { - const result = await t.run('MATCH (u:User {slug: $slug}) RETURN u.slug AS slug', { - slug: name, - }) - return result.records.map((record) => record.get('slug')) - }) - if (!slug) - return res.status(404).json({ - error: `No record found for "${name}@${domain}".`, - }) - const webFinger = createWebFinger(name) - return res.contentType('application/jrd+json').json(webFinger) - } catch (error) { - debug(error) - return res.status(500).json({ - error: `Something went terribly wrong. Please visit ${CONFIG.SUPPORT_URL}`, - }) - } finally { - session.close() - } -} - -export default function () { - const router = express.Router() - router.use('/webfinger', cors(), express.urlencoded({ extended: true }), handler) - return router -} diff --git a/backend/src/activitypub/routes/webfinger.spec.js b/backend/src/activitypub/routes/webfinger.spec.js deleted file mode 100644 index 33b4f552f..000000000 --- a/backend/src/activitypub/routes/webfinger.spec.js +++ /dev/null @@ -1,123 +0,0 @@ -import { handler } from './webfinger' -import Factory, { cleanDatabase } from '../../db/factories' -import { getDriver } from '../../db/neo4j' -import CONFIG from '../../config' - -let resource, res, json, status, contentType - -const driver = getDriver() - -const request = () => { - json = jest.fn() - status = jest.fn(() => ({ json })) - contentType = jest.fn(() => ({ json })) - res = { status, contentType } - const req = { - app: { - get: (key) => { - return { - driver, - }[key] - }, - }, - query: { - resource, - }, - } - return handler(req, res) -} - -beforeAll(async () => { - await cleanDatabase() -}) - -afterAll(async () => { - await cleanDatabase() - driver.close() -}) - -// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543 -afterEach(async () => { - await cleanDatabase() -}) - -describe('webfinger', () => { - describe('no ressource', () => { - beforeEach(() => { - resource = undefined - }) - - it('sends HTTP 400', async () => { - await request() - expect(status).toHaveBeenCalledWith(400) - expect(json).toHaveBeenCalledWith({ - error: 'Query parameter "?resource=acct:@" is missing.', - }) - }) - }) - - describe('?resource query param', () => { - describe('is missing acct:', () => { - beforeEach(() => { - resource = 'some-user@domain' - }) - - it('sends HTTP 400', async () => { - await request() - expect(status).toHaveBeenCalledWith(400) - expect(json).toHaveBeenCalledWith({ - error: 'Query parameter "?resource=acct:@" is missing.', - }) - }) - }) - - describe('has no domain', () => { - beforeEach(() => { - resource = 'acct:some-user@' - }) - - it('sends HTTP 400', async () => { - await request() - expect(status).toHaveBeenCalledWith(400) - expect(json).toHaveBeenCalledWith({ - error: 'Query parameter "?resource=acct:@" is missing.', - }) - }) - }) - - describe('with acct:', () => { - beforeEach(() => { - resource = 'acct:some-user@domain' - }) - - it('returns error as json', async () => { - await request() - expect(status).toHaveBeenCalledWith(404) - expect(json).toHaveBeenCalledWith({ - error: 'No record found for "some-user@domain".', - }) - }) - - describe('given a user for acct', () => { - beforeEach(async () => { - await Factory.build('user', { slug: 'some-user' }) - }) - - it('returns user object', async () => { - await request() - expect(contentType).toHaveBeenCalledWith('application/jrd+json') - expect(json).toHaveBeenCalledWith({ - links: [ - { - href: `${CONFIG.CLIENT_URI}/activitypub/users/some-user`, - rel: 'self', - type: 'application/activity+json', - }, - ], - subject: `acct:some-user@${new URL(CONFIG.CLIENT_URI).host}`, - }) - }) - }) - }) - }) -}) diff --git a/backend/src/activitypub/security/httpSignature.spec.js b/backend/src/activitypub/security/httpSignature.spec.js deleted file mode 100644 index 0c6fbb8b5..000000000 --- a/backend/src/activitypub/security/httpSignature.spec.js +++ /dev/null @@ -1,104 +0,0 @@ -import { generateRsaKeyPair, createSignature, verifySignature } from '.' -import crypto from 'crypto' -import request from 'request' -jest.mock('request') - -let privateKey -let publicKey -let headers -const passphrase = 'a7dsf78sadg87ad87sfagsadg78' - -describe('activityPub/security', () => { - beforeEach(() => { - const pair = generateRsaKeyPair({ passphrase }) - privateKey = pair.privateKey - publicKey = pair.publicKey - headers = { - Date: '2019-03-08T14:35:45.759Z', - Host: 'democracy-app.de', - 'Content-Type': 'application/json', - } - }) - - describe('createSignature', () => { - describe('returned http signature', () => { - let signatureB64 - let httpSignature - - beforeEach(() => { - const signer = crypto.createSign('rsa-sha256') - signer.update( - '(request-target): post /activitypub/users/max/inbox\ndate: 2019-03-08T14:35:45.759Z\nhost: democracy-app.de\ncontent-type: application/json', - ) - signatureB64 = signer.sign({ key: privateKey, passphrase }, 'base64') - httpSignature = createSignature({ - privateKey, - keyId: 'https://human-connection.org/activitypub/users/lea#main-key', - url: 'https://democracy-app.de/activitypub/users/max/inbox', - headers, - passphrase, - }) - }) - - it('contains keyId', () => { - expect(httpSignature).toContain( - 'keyId="https://human-connection.org/activitypub/users/lea#main-key"', - ) - }) - - it('contains default algorithm "rsa-sha256"', () => { - expect(httpSignature).toContain('algorithm="rsa-sha256"') - }) - - it('contains headers', () => { - expect(httpSignature).toContain('headers="(request-target) date host content-type"') - }) - - it('contains signature', () => { - expect(httpSignature).toContain('signature="' + signatureB64 + '"') - }) - }) - }) - - describe('verifySignature', () => { - let httpSignature - - beforeEach(() => { - httpSignature = createSignature({ - privateKey, - keyId: 'http://localhost:4001/activitypub/users/test-user#main-key', - url: 'https://democracy-app.de/activitypub/users/max/inbox', - headers, - passphrase, - }) - const body = { - publicKey: { - id: 'https://localhost:4001/activitypub/users/test-user#main-key', - owner: 'https://localhost:4001/activitypub/users/test-user', - publicKeyPem: publicKey, - }, - } - - const mockedRequest = jest.fn((_, callback) => callback(null, null, JSON.stringify(body))) - request.mockImplementation(mockedRequest) - }) - - it('resolves false', async () => { - await expect( - verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers), - ).resolves.toEqual(false) - }) - - describe('valid signature', () => { - beforeEach(() => { - headers.Signature = httpSignature - }) - - it('resolves true', async () => { - await expect( - verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers), - ).resolves.toEqual(true) - }) - }) - }) -}) diff --git a/backend/src/activitypub/security/index.js b/backend/src/activitypub/security/index.js deleted file mode 100644 index 399bc7d9b..000000000 --- a/backend/src/activitypub/security/index.js +++ /dev/null @@ -1,172 +0,0 @@ -// import dotenv from 'dotenv' -// import { resolve } from 'path' -import crypto from 'crypto' -import request from 'request' -import CONFIG from './../../config' -const debug = require('debug')('ea:security') - -// TODO Does this reference a local config? Why? -// dotenv.config({ path: resolve('src', 'activitypub', '.env') }) - -export function generateRsaKeyPair(options = {}) { - const { passphrase = CONFIG.PRIVATE_KEY_PASSPHRASE } = options - return crypto.generateKeyPairSync('rsa', { - modulusLength: 4096, - publicKeyEncoding: { - type: 'spki', - format: 'pem', - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem', - cipher: 'aes-256-cbc', - passphrase, - }, - }) -} - -// signing -export function createSignature(options) { - const { - privateKey, - keyId, - url, - headers = {}, - algorithm = 'rsa-sha256', - passphrase = CONFIG.PRIVATE_KEY_PASSPHRASE, - } = options - if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) { - throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`) - } - const signer = crypto.createSign(algorithm) - const signingString = constructSigningString(url, headers) - signer.update(signingString) - const signatureB64 = signer.sign({ key: privateKey, passphrase }, 'base64') - const headersString = Object.keys(headers).reduce((result, key) => { - return result + ' ' + key.toLowerCase() - }, '') - return `keyId="${keyId}",algorithm="${algorithm}",headers="(request-target)${headersString}",signature="${signatureB64}"` -} - -// verifying -export function verifySignature(url, headers) { - return new Promise((resolve, reject) => { - const signatureHeader = headers.signature ? headers.signature : headers.Signature - if (!signatureHeader) { - debug('No Signature header present!') - resolve(false) - } - debug(`Signature Header = ${signatureHeader}`) - const signature = extractKeyValueFromSignatureHeader(signatureHeader, 'signature') - const algorithm = extractKeyValueFromSignatureHeader(signatureHeader, 'algorithm') - const headersString = extractKeyValueFromSignatureHeader(signatureHeader, 'headers') - const keyId = extractKeyValueFromSignatureHeader(signatureHeader, 'keyId') - - if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) { - debug('Unsupported hash algorithm specified!') - resolve(false) - } - - const usedHeaders = headersString.split(' ') - const verifyHeaders = {} - Object.keys(headers).forEach((key) => { - if (usedHeaders.includes(key.toLowerCase())) { - verifyHeaders[key.toLowerCase()] = headers[key] - } - }) - const signingString = constructSigningString(url, verifyHeaders) - debug(`keyId= ${keyId}`) - request( - { - url: keyId, - headers: { - Accept: 'application/json', - }, - }, - (err, response, body) => { - if (err) reject(err) - debug(`body = ${body}`) - const actor = JSON.parse(body) - const publicKeyPem = actor.publicKey.publicKeyPem - resolve(httpVerify(publicKeyPem, signature, signingString, algorithm)) - }, - ) - }) -} - -// private: signing -function constructSigningString(url, headers) { - const urlObj = new URL(url) - const signingString = `(request-target): post ${urlObj.pathname}${ - urlObj.search !== '' ? urlObj.search : '' - }` - return Object.keys(headers).reduce((result, key) => { - return result + `\n${key.toLowerCase()}: ${headers[key]}` - }, signingString) -} - -// private: verifying -function httpVerify(pubKey, signature, signingString, algorithm) { - if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) { - throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`) - } - const verifier = crypto.createVerify(algorithm) - verifier.update(signingString) - return verifier.verify(pubKey, signature, 'base64') -} - -// private: verifying -// This function can be used to extract the signature,headers,algorithm etc. out of the Signature Header. -// Just pass what you want as key -function extractKeyValueFromSignatureHeader(signatureHeader, key) { - const keyString = signatureHeader.split(',').filter((el) => { - return !!el.startsWith(key) - })[0] - - let firstEqualIndex = keyString.search('=') - // When headers are requested add 17 to the index to remove "(request-target) " from the string - if (key === 'headers') { - firstEqualIndex += 17 - } - return keyString.substring(firstEqualIndex + 2, keyString.length - 1) -} - -// Obtained from invoking crypto.getHashes() -export const SUPPORTED_HASH_ALGORITHMS = [ - 'rsa-md4', - 'rsa-md5', - 'rsa-mdC2', - 'rsa-ripemd160', - 'rsa-sha1', - 'rsa-sha1-2', - 'rsa-sha224', - 'rsa-sha256', - 'rsa-sha384', - 'rsa-sha512', - 'blake2b512', - 'blake2s256', - 'md4', - 'md4WithRSAEncryption', - 'md5', - 'md5-sha1', - 'md5WithRSAEncryption', - 'mdc2', - 'mdc2WithRSA', - 'ripemd', - 'ripemd160', - 'ripemd160WithRSA', - 'rmd160', - 'sha1', - 'sha1WithRSAEncryption', - 'sha224', - 'sha224WithRSAEncryption', - 'sha256', - 'sha256WithRSAEncryption', - 'sha384', - 'sha384WithRSAEncryption', - 'sha512', - 'sha512WithRSAEncryption', - 'ssl3-md5', - 'ssl3-sha1', - 'whirlpool', -] diff --git a/backend/src/activitypub/utils/activity.js b/backend/src/activitypub/utils/activity.js deleted file mode 100644 index 2199361d8..000000000 --- a/backend/src/activitypub/utils/activity.js +++ /dev/null @@ -1,117 +0,0 @@ -import { activityPub } from '../ActivityPub' -import { throwErrorIfApolloErrorOccurred } from './index' -// import { signAndSend, throwErrorIfApolloErrorOccurred } from './index' - -import crypto from 'crypto' -// import as from 'activitystrea.ms' -import gql from 'graphql-tag' -// const debug = require('debug')('ea:utils:activity') - -export function createNoteObject(text, name, id, published) { - const createUuid = crypto.randomBytes(16).toString('hex') - - return { - '@context': 'https://www.w3.org/ns/activitystreams', - id: `${activityPub.endpoint}/activitypub/users/${name}/status/${createUuid}`, - type: 'Create', - actor: `${activityPub.endpoint}/activitypub/users/${name}`, - object: { - id: `${activityPub.endpoint}/activitypub/users/${name}/status/${id}`, - type: 'Note', - published: published, - attributedTo: `${activityPub.endpoint}/activitypub/users/${name}`, - content: text, - to: 'https://www.w3.org/ns/activitystreams#Public', - }, - } -} - -export async function createArticleObject(activityId, objectId, text, name, id, published) { - const actorId = await getActorId(name) - - return { - '@context': 'https://www.w3.org/ns/activitystreams', - id: `${activityId}`, - type: 'Create', - actor: `${actorId}`, - object: { - id: `${objectId}`, - type: 'Article', - published: published, - attributedTo: `${actorId}`, - content: text, - to: 'https://www.w3.org/ns/activitystreams#Public', - }, - } -} - -export async function getActorId(name) { - const result = await activityPub.dataSource.client.query({ - query: gql` - query { - User(slug: "${name}") { - actorId - } - } - `, - }) - throwErrorIfApolloErrorOccurred(result) - if (Array.isArray(result.data.User) && result.data.User[0]) { - return result.data.User[0].actorId - } else { - throw Error(`No user with name: ${name}`) - } -} - -// export function sendAcceptActivity(theBody, name, targetDomain, url) { -// as.accept() -// .id( -// `${activityPub.endpoint}/activitypub/users/${name}/status/` + -// crypto.randomBytes(16).toString('hex'), -// ) -// .actor(`${activityPub.endpoint}/activitypub/users/${name}`) -// .object(theBody) -// .prettyWrite((err, doc) => { -// if (!err) { -// return signAndSend(doc, name, targetDomain, url) -// } else { -// debug(`error serializing Accept object: ${err}`) -// throw new Error('error serializing Accept object') -// } -// }) -// } - -// export function sendRejectActivity(theBody, name, targetDomain, url) { -// as.reject() -// .id( -// `${activityPub.endpoint}/activitypub/users/${name}/status/` + -// crypto.randomBytes(16).toString('hex'), -// ) -// .actor(`${activityPub.endpoint}/activitypub/users/${name}`) -// .object(theBody) -// .prettyWrite((err, doc) => { -// if (!err) { -// return signAndSend(doc, name, targetDomain, url) -// } else { -// debug(`error serializing Accept object: ${err}`) -// throw new Error('error serializing Accept object') -// } -// }) -// } - -export function isPublicAddressed(postObject) { - if (typeof postObject.to === 'string') { - postObject.to = [postObject.to] - } - if (typeof postObject === 'string') { - postObject.to = [postObject] - } - if (Array.isArray(postObject)) { - postObject.to = postObject - } - return ( - postObject.to.includes('Public') || - postObject.to.includes('as:Public') || - postObject.to.includes('https://www.w3.org/ns/activitystreams#Public') - ) -} diff --git a/backend/src/activitypub/utils/actor.js b/backend/src/activitypub/utils/actor.js deleted file mode 100644 index e07397bdc..000000000 --- a/backend/src/activitypub/utils/actor.js +++ /dev/null @@ -1,24 +0,0 @@ -import { activityPub } from '../ActivityPub' - -export function createActor(name, pubkey) { - return { - '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'], - id: `${activityPub.endpoint}/activitypub/users/${name}`, - type: 'Person', - preferredUsername: `${name}`, - name: `${name}`, - following: `${activityPub.endpoint}/activitypub/users/${name}/following`, - followers: `${activityPub.endpoint}/activitypub/users/${name}/followers`, - inbox: `${activityPub.endpoint}/activitypub/users/${name}/inbox`, - outbox: `${activityPub.endpoint}/activitypub/users/${name}/outbox`, - url: `${activityPub.endpoint}/activitypub/@${name}`, - endpoints: { - sharedInbox: `${activityPub.endpoint}/activitypub/inbox`, - }, - publicKey: { - id: `${activityPub.endpoint}/activitypub/users/${name}#main-key`, - owner: `${activityPub.endpoint}/activitypub/users/${name}`, - publicKeyPem: pubkey, - }, - } -} diff --git a/backend/src/activitypub/utils/collection.js b/backend/src/activitypub/utils/collection.js deleted file mode 100644 index 9cb71fe39..000000000 --- a/backend/src/activitypub/utils/collection.js +++ /dev/null @@ -1,70 +0,0 @@ -import { activityPub } from '../ActivityPub' -import { constructIdFromName } from './index' -const debug = require('debug')('ea:utils:collections') - -export function createOrderedCollection(name, collectionName) { - return { - '@context': 'https://www.w3.org/ns/activitystreams', - id: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`, - summary: `${name}s ${collectionName} collection`, - type: 'OrderedCollection', - first: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`, - totalItems: 0, - } -} - -export function createOrderedCollectionPage(name, collectionName) { - return { - '@context': 'https://www.w3.org/ns/activitystreams', - id: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`, - summary: `${name}s ${collectionName} collection`, - type: 'OrderedCollectionPage', - totalItems: 0, - partOf: `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`, - orderedItems: [], - } -} -export function sendCollection(collectionName, req, res) { - const name = req.params.name - const id = constructIdFromName(name) - - switch (collectionName) { - case 'followers': - attachThenCatch(activityPub.collections.getFollowersCollection(id), res) - break - - case 'followersPage': - attachThenCatch(activityPub.collections.getFollowersCollectionPage(id), res) - break - - case 'following': - attachThenCatch(activityPub.collections.getFollowingCollection(id), res) - break - - case 'followingPage': - attachThenCatch(activityPub.collections.getFollowingCollectionPage(id), res) - break - - case 'outbox': - attachThenCatch(activityPub.collections.getOutboxCollection(id), res) - break - - case 'outboxPage': - attachThenCatch(activityPub.collections.getOutboxCollectionPage(id), res) - break - - default: - res.status(500).end() - } -} - -function attachThenCatch(promise, res) { - return promise - .then((collection) => { - res.status(200).contentType('application/activity+json').send(collection) - }) - .catch((err) => { - debug(`error getting a Collection: = ${err}`) - res.status(500).end() - }) -} diff --git a/backend/src/activitypub/utils/index.js b/backend/src/activitypub/utils/index.js deleted file mode 100644 index aa3ff2101..000000000 --- a/backend/src/activitypub/utils/index.js +++ /dev/null @@ -1,111 +0,0 @@ -import { activityPub } from '../ActivityPub' -import gql from 'graphql-tag' -import { createSignature } from '../security' -import request from 'request' -import CONFIG from './../../config' -const debug = require('debug')('ea:utils') - -export function extractNameFromId(uri) { - const urlObject = new URL(uri) - const pathname = urlObject.pathname - const splitted = pathname.split('/') - - return splitted[splitted.indexOf('users') + 1] -} - -export function extractIdFromActivityId(uri) { - const urlObject = new URL(uri) - const pathname = urlObject.pathname - const splitted = pathname.split('/') - - return splitted[splitted.indexOf('status') + 1] -} -export function constructIdFromName(name, fromDomain = activityPub.endpoint) { - return `${fromDomain}/activitypub/users/${name}` -} - -export function extractDomainFromUrl(url) { - return new URL(url).host -} - -export function throwErrorIfApolloErrorOccurred(result) { - if (result.error && (result.error.message || result.error.errors)) { - throw new Error( - `${result.error.message ? result.error.message : result.error.errors[0].message}`, - ) - } -} - -export function signAndSend(activity, fromName, targetDomain, url) { - // fix for development: replace with http - url = url.indexOf('localhost') > -1 ? url.replace('https', 'http') : url - debug(`passhprase = ${CONFIG.PRIVATE_KEY_PASSPHRASE}`) - return new Promise((resolve, reject) => { - debug('inside signAndSend') - // get the private key - activityPub.dataSource.client - .query({ - query: gql` - query { - User(slug: "${fromName}") { - privateKey - } - } - `, - }) - .then((result) => { - if (result.error) { - reject(result.error) - } else { - // add security context - const parsedActivity = JSON.parse(activity) - if (Array.isArray(parsedActivity['@context'])) { - parsedActivity['@context'].push('https://w3id.org/security/v1') - } else { - const context = [parsedActivity['@context']] - context.push('https://w3id.org/security/v1') - parsedActivity['@context'] = context - } - - // deduplicate context strings - parsedActivity['@context'] = [...new Set(parsedActivity['@context'])] - const privateKey = result.data.User[0].privateKey - const date = new Date().toUTCString() - - debug(`url = ${url}`) - request( - { - url: url, - headers: { - Host: targetDomain, - Date: date, - Signature: createSignature({ - privateKey, - keyId: `${activityPub.endpoint}/activitypub/users/${fromName}#main-key`, - url, - headers: { - Host: targetDomain, - Date: date, - 'Content-Type': 'application/activity+json', - }, - }), - 'Content-Type': 'application/activity+json', - }, - method: 'POST', - body: JSON.stringify(parsedActivity), - }, - (error, response) => { - if (error) { - debug(`Error = ${JSON.stringify(error, null, 2)}`) - reject(error) - } else { - debug('Response Headers:', JSON.stringify(response.headers, null, 2)) - debug('Response Body:', JSON.stringify(response.body, null, 2)) - resolve() - } - }, - ) - } - }) - }) -} diff --git a/backend/src/config/emails.js b/backend/src/config/emails.ts similarity index 100% rename from backend/src/config/emails.js rename to backend/src/config/emails.ts diff --git a/backend/src/config/index.js b/backend/src/config/index.ts similarity index 89% rename from backend/src/config/index.js rename to backend/src/config/index.ts index 7df780cfc..b6098df11 100644 --- a/backend/src/config/index.js +++ b/backend/src/config/index.ts @@ -1,6 +1,6 @@ import dotenv from 'dotenv' -import emails from './emails.js' -import metadata from './metadata.js' +import emails from './emails' +import metadata from './metadata' // Load env file if (require.resolve) { @@ -15,10 +15,11 @@ if (require.resolve) { } // Use Cypress env or process.env +declare let Cypress: any | undefined const env = typeof Cypress !== 'undefined' ? Cypress.env() : process.env // eslint-disable-line no-undef const environment = { - NODE_ENV: env.NODE_ENV || process.NODE_ENV, + NODE_ENV: env.NODE_ENV || process.env.NODE_ENV, DEBUG: env.NODE_ENV !== 'production' && env.DEBUG, TEST: env.NODE_ENV === 'test', PRODUCTION: env.NODE_ENV === 'production', @@ -90,14 +91,12 @@ const options = { } // Check if all required configs are present -if (require.resolve) { - // are we in a nodejs environment? - Object.entries(required).map((entry) => { - if (!entry[1]) { - throw new Error(`ERROR: "${entry[0]}" env variable is missing.`) - } - }) -} +Object.entries(required).map((entry) => { + if (!entry[1]) { + throw new Error(`ERROR: "${entry[0]}" env variable is missing.`) + } + return entry +}) export default { ...environment, diff --git a/backend/src/config/logos.js b/backend/src/config/logos.ts similarity index 76% rename from backend/src/config/logos.js rename to backend/src/config/logos.ts index d093c7b46..41b83b30c 100644 --- a/backend/src/config/logos.js +++ b/backend/src/config/logos.ts @@ -1,4 +1,4 @@ -// this file is duplicated in `backend/src/config/logos.js` and `webapp/constants/logos.js` and replaced on rebranding +// this file is duplicated in `backend/src/config/logos` and `webapp/constants/logos.js` and replaced on rebranding // this are the paths in the webapp export default { LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg', diff --git a/backend/src/config/metadata.js b/backend/src/config/metadata.ts similarity index 69% rename from backend/src/config/metadata.js rename to backend/src/config/metadata.ts index d40308e80..282fcb655 100644 --- a/backend/src/config/metadata.js +++ b/backend/src/config/metadata.ts @@ -1,4 +1,4 @@ -// this file is duplicated in `backend/src/config/metadata.js` and `webapp/constants/metadata.js` and replaced on rebranding +// this file is duplicated in `backend/src/config/metadata` and `webapp/constants/metadata.js` and replaced on rebranding export default { APPLICATION_NAME: 'ocelot.social', APPLICATION_SHORT_NAME: 'ocelot', diff --git a/backend/src/constants/categories.js b/backend/src/constants/categories.ts similarity index 95% rename from backend/src/constants/categories.js rename to backend/src/constants/categories.ts index 0d61a041a..6365d268a 100644 --- a/backend/src/constants/categories.js +++ b/backend/src/constants/categories.ts @@ -1,4 +1,4 @@ -// this file is duplicated in `backend/src/constants/metadata.js` and `webapp/constants/metadata.js` +// this file is duplicated in `backend/src/constants/metadata` and `webapp/constants/metadata.js` export const CATEGORIES_MIN = 1 export const CATEGORIES_MAX = 3 diff --git a/backend/src/constants/groups.js b/backend/src/constants/groups.ts similarity index 62% rename from backend/src/constants/groups.js rename to backend/src/constants/groups.ts index aec19eac5..b1c305add 100644 --- a/backend/src/constants/groups.js +++ b/backend/src/constants/groups.ts @@ -1,3 +1,3 @@ -// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js` +// this file is duplicated in `backend/src/constants/group` and `webapp/constants/group.js` export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 50 // with removed HTML tags export const DESCRIPTION_EXCERPT_HTML_LENGTH = 250 // with removed HTML tags diff --git a/backend/src/constants/registration.js b/backend/src/constants/registration.js deleted file mode 100644 index 9e63e478e..000000000 --- a/backend/src/constants/registration.js +++ /dev/null @@ -1,5 +0,0 @@ -// this file is duplicated in `backend/src/config/metadata.js` and `webapp/constants/metadata.js` -export default { - NONCE_LENGTH: 5, - INVITE_CODE_LENGTH: 6, -} diff --git a/backend/src/constants/registration.ts b/backend/src/constants/registration.ts new file mode 100644 index 000000000..a08be3521 --- /dev/null +++ b/backend/src/constants/registration.ts @@ -0,0 +1,5 @@ +// this file is duplicated in `backend/src/config/metadata` and `webapp/constants/metadata.js` +export default { + NONCE_LENGTH: 5, + INVITE_CODE_LENGTH: 6, +} diff --git a/backend/src/db/clean.js b/backend/src/db/clean.ts similarity index 100% rename from backend/src/db/clean.js rename to backend/src/db/clean.ts diff --git a/backend/src/db/compiler.ts b/backend/src/db/compiler.ts new file mode 100644 index 000000000..8b09ac9c3 --- /dev/null +++ b/backend/src/db/compiler.ts @@ -0,0 +1,2 @@ +const tsNode = require('ts-node') +module.exports = tsNode.register diff --git a/backend/src/db/factories.js b/backend/src/db/factories.ts similarity index 98% rename from backend/src/db/factories.js rename to backend/src/db/factories.ts index 7a365b80d..4ec34e289 100644 --- a/backend/src/db/factories.js +++ b/backend/src/db/factories.ts @@ -4,8 +4,8 @@ import { hashSync } from 'bcryptjs' import { Factory } from 'rosie' import { faker } from '@faker-js/faker' import { getDriver, getNeode } from './neo4j' -import CONFIG from '../config/index.js' -import generateInviteCode from '../schema/resolvers/helpers/generateInviteCode.js' +import CONFIG from '../config/index' +import generateInviteCode from '../schema/resolvers/helpers/generateInviteCode' const neode = getNeode() @@ -15,7 +15,7 @@ const uniqueImageUrl = (imageUrl) => { return newUrl.toString() } -export const cleanDatabase = async (options = {}) => { +export const cleanDatabase = async (options: any = {}) => { const { driver = getDriver() } = options const session = driver.session() try { diff --git a/backend/src/db/migrate/store.js b/backend/src/db/migrate/store.ts similarity index 100% rename from backend/src/db/migrate/store.js rename to backend/src/db/migrate/store.ts diff --git a/backend/src/db/migrate/template.js b/backend/src/db/migrate/template.ts similarity index 100% rename from backend/src/db/migrate/template.js rename to backend/src/db/migrate/template.ts diff --git a/backend/src/db/migrations-examples/20200123150105-merge_duplicate_user_accounts.js b/backend/src/db/migrations-examples/20200123150105-merge_duplicate_user_accounts.ts similarity index 96% rename from backend/src/db/migrations-examples/20200123150105-merge_duplicate_user_accounts.js rename to backend/src/db/migrations-examples/20200123150105-merge_duplicate_user_accounts.ts index 0914d6b22..7d98d9dcc 100644 --- a/backend/src/db/migrations-examples/20200123150105-merge_duplicate_user_accounts.js +++ b/backend/src/db/migrations-examples/20200123150105-merge_duplicate_user_accounts.ts @@ -18,13 +18,13 @@ export function up(next) { rxSession .beginTransaction() .pipe( - flatMap((txc) => + flatMap((txc: any) => concat( txc .run('MATCH (email:EmailAddress) RETURN email {.email}') .records() .pipe( - map((record) => { + map((record: any) => { const { email } = record.get('email') const normalizedEmail = normalizeEmail(email) return { email, normalizedEmail } @@ -45,7 +45,7 @@ export function up(next) { ) .records() .pipe( - map((r) => ({ + map((r: any) => ({ oldEmail: email, email: r.get('email'), user: r.get('user'), diff --git a/backend/src/db/migrations-examples/20200123150110-merge_duplicate_location_nodes.js b/backend/src/db/migrations-examples/20200123150110-merge_duplicate_location_nodes.ts similarity index 95% rename from backend/src/db/migrations-examples/20200123150110-merge_duplicate_location_nodes.js rename to backend/src/db/migrations-examples/20200123150110-merge_duplicate_location_nodes.ts index 66560ec51..10b77c6dd 100644 --- a/backend/src/db/migrations-examples/20200123150110-merge_duplicate_location_nodes.js +++ b/backend/src/db/migrations-examples/20200123150110-merge_duplicate_location_nodes.ts @@ -12,7 +12,7 @@ export function up(next) { rxSession .beginTransaction() .pipe( - flatMap((transaction) => + flatMap((transaction: any) => concat( transaction .run( @@ -23,7 +23,7 @@ export function up(next) { ) .records() .pipe( - map((record) => { + map((record: any) => { const { id: locationId } = record.get('location') return { locationId } }), @@ -40,7 +40,7 @@ export function up(next) { ) .records() .pipe( - map((record) => ({ + map((record: any) => ({ location: record.get('location'), updatedLocation: record.get('updatedLocation'), })), diff --git a/backend/src/db/migrations-examples/20200127110135-create_muted_relationship_between_existing_blocked_relationships.js b/backend/src/db/migrations-examples/20200127110135-create_muted_relationship_between_existing_blocked_relationships.ts similarity index 100% rename from backend/src/db/migrations-examples/20200127110135-create_muted_relationship_between_existing_blocked_relationships.js rename to backend/src/db/migrations-examples/20200127110135-create_muted_relationship_between_existing_blocked_relationships.ts diff --git a/backend/src/db/migrations-examples/20200206190233-swap_latitude_with_longitude.js b/backend/src/db/migrations-examples/20200206190233-swap_latitude_with_longitude.ts similarity index 100% rename from backend/src/db/migrations-examples/20200206190233-swap_latitude_with_longitude.js rename to backend/src/db/migrations-examples/20200206190233-swap_latitude_with_longitude.ts diff --git a/backend/src/db/migrations-examples/20200207080200-fulltext_index_for_tags.js b/backend/src/db/migrations-examples/20200207080200-fulltext_index_for_tags.ts similarity index 100% rename from backend/src/db/migrations-examples/20200207080200-fulltext_index_for_tags.js rename to backend/src/db/migrations-examples/20200207080200-fulltext_index_for_tags.ts diff --git a/backend/src/db/migrations-examples/20200213230248-add_unique_index_to_image_url.js b/backend/src/db/migrations-examples/20200213230248-add_unique_index_to_image_url.ts similarity index 100% rename from backend/src/db/migrations-examples/20200213230248-add_unique_index_to_image_url.js rename to backend/src/db/migrations-examples/20200213230248-add_unique_index_to_image_url.ts diff --git a/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.js b/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.ts similarity index 98% rename from backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.js rename to backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.ts index ee9aba023..356004237 100644 --- a/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.js +++ b/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.ts @@ -3,7 +3,7 @@ import { existsSync, createReadStream } from 'fs' import path from 'path' import { S3 } from 'aws-sdk' import mime from 'mime-types' -import { s3Configs } from '../../config' +import s3Configs from '../../config' import https from 'https' export const description = ` diff --git a/backend/src/db/migrations-examples/20200320200315-refactor_all_images_to_separate_type.js b/backend/src/db/migrations-examples/20200320200315-refactor_all_images_to_separate_type.ts similarity index 100% rename from backend/src/db/migrations-examples/20200320200315-refactor_all_images_to_separate_type.js rename to backend/src/db/migrations-examples/20200320200315-refactor_all_images_to_separate_type.ts diff --git a/backend/src/db/migrations-examples/20200323140300-remove_deleted_users_obsolete_attributes.js b/backend/src/db/migrations-examples/20200323140300-remove_deleted_users_obsolete_attributes.ts similarity index 100% rename from backend/src/db/migrations-examples/20200323140300-remove_deleted_users_obsolete_attributes.js rename to backend/src/db/migrations-examples/20200323140300-remove_deleted_users_obsolete_attributes.ts diff --git a/backend/src/db/migrations-examples/20200323160336-remove_deleted_posts_obsolete_attributes.js b/backend/src/db/migrations-examples/20200323160336-remove_deleted_posts_obsolete_attributes.ts similarity index 100% rename from backend/src/db/migrations-examples/20200323160336-remove_deleted_posts_obsolete_attributes.js rename to backend/src/db/migrations-examples/20200323160336-remove_deleted_posts_obsolete_attributes.ts diff --git a/backend/src/db/migrations-examples/20200326160326-remove_dangling_image_urls.js b/backend/src/db/migrations-examples/20200326160326-remove_dangling_image_urls.ts similarity index 100% rename from backend/src/db/migrations-examples/20200326160326-remove_dangling_image_urls.js rename to backend/src/db/migrations-examples/20200326160326-remove_dangling_image_urls.ts diff --git a/backend/src/db/migrations/1613589876420-null_mutation.js b/backend/src/db/migrations/1613589876420-null_mutation.ts similarity index 100% rename from backend/src/db/migrations/1613589876420-null_mutation.js rename to backend/src/db/migrations/1613589876420-null_mutation.ts diff --git a/backend/src/db/migrations/1614023644903-add-clickedCount-to-posts.js b/backend/src/db/migrations/1614023644903-add-clickedCount-to-posts.ts similarity index 100% rename from backend/src/db/migrations/1614023644903-add-clickedCount-to-posts.js rename to backend/src/db/migrations/1614023644903-add-clickedCount-to-posts.ts diff --git a/backend/src/db/migrations/1614177130817-add-viewedTeaserCount-to-posts.js b/backend/src/db/migrations/1614177130817-add-viewedTeaserCount-to-posts.ts similarity index 100% rename from backend/src/db/migrations/1614177130817-add-viewedTeaserCount-to-posts.js rename to backend/src/db/migrations/1614177130817-add-viewedTeaserCount-to-posts.ts diff --git a/backend/src/db/migrations/20210506150512-add-donations-node.js b/backend/src/db/migrations/20210506150512-add-donations-node.ts similarity index 100% rename from backend/src/db/migrations/20210506150512-add-donations-node.js rename to backend/src/db/migrations/20210506150512-add-donations-node.ts diff --git a/backend/src/db/migrations/20210923140939-add-sendNotificationEmails-property-to-all-users.js b/backend/src/db/migrations/20210923140939-add-sendNotificationEmails-property-to-all-users.ts similarity index 100% rename from backend/src/db/migrations/20210923140939-add-sendNotificationEmails-property-to-all-users.js rename to backend/src/db/migrations/20210923140939-add-sendNotificationEmails-property-to-all-users.ts diff --git a/backend/src/db/migrations/20220803060819-create_fulltext_indices_and_unique_keys_for_groups.js b/backend/src/db/migrations/20220803060819-create_fulltext_indices_and_unique_keys_for_groups.ts similarity index 86% rename from backend/src/db/migrations/20220803060819-create_fulltext_indices_and_unique_keys_for_groups.js rename to backend/src/db/migrations/20220803060819-create_fulltext_indices_and_unique_keys_for_groups.ts index b87e5632a..63e40c72b 100644 --- a/backend/src/db/migrations/20220803060819-create_fulltext_indices_and_unique_keys_for_groups.js +++ b/backend/src/db/migrations/20220803060819-create_fulltext_indices_and_unique_keys_for_groups.ts @@ -11,13 +11,13 @@ export async function up(next) { const transaction = session.beginTransaction() try { - // Implement your migration here. - await transaction.run(` - CREATE CONSTRAINT ON ( group:Group ) ASSERT group.id IS UNIQUE - `) - await transaction.run(` - CREATE CONSTRAINT ON ( group:Group ) ASSERT group.slug IS UNIQUE - `) + // Those two indexes already exist + // await transaction.run(` + // CREATE CONSTRAINT ON ( group:Group ) ASSERT group.id IS UNIQUE + // `) + // await transaction.run(` + // CREATE CONSTRAINT ON ( group:Group ) ASSERT group.slug IS UNIQUE + // `) await transaction.run(` CALL db.index.fulltext.createNodeIndex("group_fulltext_search",["Group"],["name", "slug", "about", "description"]) `) diff --git a/backend/src/db/migrations/20230320130345-fulltext-search-indexes.js b/backend/src/db/migrations/20230320130345-fulltext-search-indexes.ts similarity index 99% rename from backend/src/db/migrations/20230320130345-fulltext-search-indexes.js rename to backend/src/db/migrations/20230320130345-fulltext-search-indexes.ts index 11029bea6..40ebc6c2e 100644 --- a/backend/src/db/migrations/20230320130345-fulltext-search-indexes.js +++ b/backend/src/db/migrations/20230320130345-fulltext-search-indexes.ts @@ -10,7 +10,7 @@ export async function up(next) { try { // Drop indexes if they exist because due to legacy code they might be set already const indexesResponse = await transaction.run(`CALL db.indexes()`) - const indexes = indexesResponse.records.map((record) => record.get('indexName')) + const indexes = indexesResponse.records.map((record) => record.get('name')) if (indexes.indexOf('user_fulltext_search') > -1) { await transaction.run(`CALL db.index.fulltext.drop("user_fulltext_search")`) } diff --git a/backend/src/db/migrations/20230329150329-article-label-for-posts.js b/backend/src/db/migrations/20230329150329-article-label-for-posts.ts similarity index 100% rename from backend/src/db/migrations/20230329150329-article-label-for-posts.js rename to backend/src/db/migrations/20230329150329-article-label-for-posts.ts diff --git a/backend/src/db/migrations/20230608130637-add-postType-property.ts b/backend/src/db/migrations/20230608130637-add-postType-property.ts new file mode 100644 index 000000000..433577715 --- /dev/null +++ b/backend/src/db/migrations/20230608130637-add-postType-property.ts @@ -0,0 +1,53 @@ +import { getDriver } from '../../db/neo4j' + +export const description = 'Add postType property Article to all posts' + +export async function up(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + + try { + await transaction.run(` + MATCH (post:Post) + SET post.postType = 'Article' + RETURN post + `) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} + +export async function down(next) { + const driver = getDriver() + const session = driver.session() + const transaction = session.beginTransaction() + + try { + await transaction.run(` + MATCH (post:Post) + REMOVE post.postType + RETURN post + `) + await transaction.commit() + next() + } catch (error) { + // eslint-disable-next-line no-console + console.log(error) + await transaction.rollback() + // eslint-disable-next-line no-console + console.log('rolled back') + throw new Error(error) + } finally { + session.close() + } +} diff --git a/backend/src/db/neo4j.js b/backend/src/db/neo4j.ts similarity index 100% rename from backend/src/db/neo4j.js rename to backend/src/db/neo4j.ts diff --git a/backend/src/db/seed.js b/backend/src/db/seed.ts similarity index 52% rename from backend/src/db/seed.js rename to backend/src/db/seed.ts index a8f8b9c68..7286683dd 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.ts @@ -11,6 +11,8 @@ import { changeGroupMemberRoleMutation, } from '../graphql/groups' import { createPostMutation } from '../graphql/posts' +import { createRoomMutation } from '../graphql/rooms' +import { createMessageMutation } from '../graphql/messages' import { createCommentMutation } from '../graphql/comments' import { categories } from '../constants/categories' @@ -38,247 +40,238 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }) const { mutate } = createTestClient(server) - const [Hamburg, Berlin, Germany, Paris, France] = await Promise.all([ - Factory.build('location', { - id: 'region.5127278006398860', - name: 'Hamburg', - type: 'region', - lng: 10.0, - lat: 53.55, - nameES: 'Hamburgo', - nameFR: 'Hambourg', - nameIT: 'Amburgo', - nameEN: 'Hamburg', - namePT: 'Hamburgo', - nameDE: 'Hamburg', - nameNL: 'Hamburg', - namePL: 'Hamburg', - nameRU: 'Гамбург', - }), - Factory.build('location', { - id: 'region.14880313158564380', - type: 'region', - name: 'Berlin', - lng: 13.38333, - lat: 52.51667, - nameES: 'Berlín', - nameFR: 'Berlin', - nameIT: 'Berlino', - nameEN: 'Berlin', - namePT: 'Berlim', - nameDE: 'Berlin', - nameNL: 'Berlijn', - namePL: 'Berlin', - nameRU: 'Берлин', - }), - Factory.build('location', { - id: 'country.10743216036480410', - name: 'Germany', - type: 'country', - namePT: 'Alemanha', - nameDE: 'Deutschland', - nameES: 'Alemania', - nameNL: 'Duitsland', - namePL: 'Niemcy', - nameFR: 'Allemagne', - nameIT: 'Germania', - nameEN: 'Germany', - nameRU: 'Германия', - }), - Factory.build('location', { - id: 'region.9397217726497330', - name: 'Paris', - type: 'region', - lng: 2.35183, - lat: 48.85658, - nameES: 'París', - nameFR: 'Paris', - nameIT: 'Parigi', - nameEN: 'Paris', - namePT: 'Paris', - nameDE: 'Paris', - nameNL: 'Parijs', - namePL: 'Paryż', - nameRU: 'Париж', - }), - Factory.build('location', { - id: 'country.9759535382641660', - name: 'France', - type: 'country', - namePT: 'França', - nameDE: 'Frankreich', - nameES: 'Francia', - nameNL: 'Frankrijk', - namePL: 'Francja', - nameFR: 'France', - nameIT: 'Francia', - nameEN: 'France', - nameRU: 'Франция', - }), - ]) - await Promise.all([ - Berlin.relateTo(Germany, 'isIn'), - Hamburg.relateTo(Germany, 'isIn'), - Paris.relateTo(France, 'isIn'), - ]) + // locations + const Hamburg = await Factory.build('location', { + id: 'region.5127278006398860', + name: 'Hamburg', + type: 'region', + lng: 10.0, + lat: 53.55, + nameES: 'Hamburgo', + nameFR: 'Hambourg', + nameIT: 'Amburgo', + nameEN: 'Hamburg', + namePT: 'Hamburgo', + nameDE: 'Hamburg', + nameNL: 'Hamburg', + namePL: 'Hamburg', + nameRU: 'Гамбург', + }) + const Berlin = await Factory.build('location', { + id: 'region.14880313158564380', + type: 'region', + name: 'Berlin', + lng: 13.38333, + lat: 52.51667, + nameES: 'Berlín', + nameFR: 'Berlin', + nameIT: 'Berlino', + nameEN: 'Berlin', + namePT: 'Berlim', + nameDE: 'Berlin', + nameNL: 'Berlijn', + namePL: 'Berlin', + nameRU: 'Берлин', + }) + const Germany = await Factory.build('location', { + id: 'country.10743216036480410', + name: 'Germany', + type: 'country', + namePT: 'Alemanha', + nameDE: 'Deutschland', + nameES: 'Alemania', + nameNL: 'Duitsland', + namePL: 'Niemcy', + nameFR: 'Allemagne', + nameIT: 'Germania', + nameEN: 'Germany', + nameRU: 'Германия', + }) + const Paris = await Factory.build('location', { + id: 'region.9397217726497330', + name: 'Paris', + type: 'region', + lng: 2.35183, + lat: 48.85658, + nameES: 'París', + nameFR: 'Paris', + nameIT: 'Parigi', + nameEN: 'Paris', + namePT: 'Paris', + nameDE: 'Paris', + nameNL: 'Parijs', + namePL: 'Paryż', + nameRU: 'Париж', + }) + const France = await Factory.build('location', { + id: 'country.9759535382641660', + name: 'France', + type: 'country', + namePT: 'França', + nameDE: 'Frankreich', + nameES: 'Francia', + nameNL: 'Frankrijk', + namePL: 'Francja', + nameFR: 'France', + nameIT: 'Francia', + nameEN: 'France', + nameRU: 'Франция', + }) + await Berlin.relateTo(Germany, 'isIn') + await Hamburg.relateTo(Germany, 'isIn') + await Paris.relateTo(France, 'isIn') - const [racoon, rabbit, wolf, bear, turtle, rhino] = await Promise.all([ - Factory.build('badge', { - id: 'indiegogo_en_racoon', - icon: '/img/badges/indiegogo_en_racoon.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_rabbit', - icon: '/img/badges/indiegogo_en_rabbit.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_wolf', - icon: '/img/badges/indiegogo_en_wolf.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_bear', - icon: '/img/badges/indiegogo_en_bear.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_turtle', - icon: '/img/badges/indiegogo_en_turtle.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_rhino', - icon: '/img/badges/indiegogo_en_rhino.svg', - }), - ]) + // badges + const racoon = await Factory.build('badge', { + id: 'indiegogo_en_racoon', + icon: '/img/badges/indiegogo_en_racoon.svg', + }) + const rabbit = await Factory.build('badge', { + id: 'indiegogo_en_rabbit', + icon: '/img/badges/indiegogo_en_rabbit.svg', + }) + const wolf = await Factory.build('badge', { + id: 'indiegogo_en_wolf', + icon: '/img/badges/indiegogo_en_wolf.svg', + }) + const bear = await Factory.build('badge', { + id: 'indiegogo_en_bear', + icon: '/img/badges/indiegogo_en_bear.svg', + }) + const turtle = await Factory.build('badge', { + id: 'indiegogo_en_turtle', + icon: '/img/badges/indiegogo_en_turtle.svg', + }) + const rhino = await Factory.build('badge', { + id: 'indiegogo_en_rhino', + icon: '/img/badges/indiegogo_en_rhino.svg', + }) - const [peterLustig, bobDerBaumeister, jennyRostock, huey, dewey, louie, dagobert] = - await Promise.all([ - Factory.build( - 'user', - { - id: 'u1', - name: 'Peter Lustig', - slug: 'peter-lustig', - role: 'admin', - }, - { - email: 'admin@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u2', - name: 'Bob der Baumeister', - slug: 'bob-der-baumeister', - role: 'moderator', - }, - { - email: 'moderator@example.org', - avatar: null, - }, - ), - Factory.build( - 'user', - { - id: 'u3', - name: 'Jenny Rostock', - slug: 'jenny-rostock', - role: 'user', - }, - { - email: 'user@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u4', - name: 'Huey', - slug: 'huey', - role: 'user', - }, - { - email: 'huey@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u5', - name: 'Dewey', - slug: 'dewey', - role: 'user', - }, - { - email: 'dewey@example.org', - avatar: null, - }, - ), - Factory.build( - 'user', - { - id: 'u6', - name: 'Louie', - slug: 'louie', - role: 'user', - }, - { - email: 'louie@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u7', - name: 'Dagobert', - slug: 'dagobert', - role: 'user', - }, - { - email: 'dagobert@example.org', - }, - ), - ]) + // users + const peterLustig = await Factory.build( + 'user', + { + id: 'u1', + name: 'Peter Lustig', + slug: 'peter-lustig', + role: 'admin', + }, + { + email: 'admin@example.org', + }, + ) + const bobDerBaumeister = await Factory.build( + 'user', + { + id: 'u2', + name: 'Bob der Baumeister', + slug: 'bob-der-baumeister', + role: 'moderator', + }, + { + email: 'moderator@example.org', + avatar: null, + }, + ) + const jennyRostock = await Factory.build( + 'user', + { + id: 'u3', + name: 'Jenny Rostock', + slug: 'jenny-rostock', + role: 'user', + }, + { + email: 'user@example.org', + }, + ) + const huey = await Factory.build( + 'user', + { + id: 'u4', + name: 'Huey', + slug: 'huey', + role: 'user', + }, + { + email: 'huey@example.org', + }, + ) + const dewey = await Factory.build( + 'user', + { + id: 'u5', + name: 'Dewey', + slug: 'dewey', + role: 'user', + }, + { + email: 'dewey@example.org', + avatar: null, + }, + ) + const louie = await Factory.build( + 'user', + { + id: 'u6', + name: 'Louie', + slug: 'louie', + role: 'user', + }, + { + email: 'louie@example.org', + }, + ) + const dagobert = await Factory.build( + 'user', + { + id: 'u7', + name: 'Dagobert', + slug: 'dagobert', + role: 'user', + }, + { + email: 'dagobert@example.org', + }, + ) - await Promise.all([ - peterLustig.relateTo(Berlin, 'isIn'), - bobDerBaumeister.relateTo(Hamburg, 'isIn'), - jennyRostock.relateTo(Paris, 'isIn'), - huey.relateTo(Paris, 'isIn'), - ]) + await peterLustig.relateTo(Berlin, 'isIn') + await bobDerBaumeister.relateTo(Hamburg, 'isIn') + await jennyRostock.relateTo(Paris, 'isIn') + await huey.relateTo(Paris, 'isIn') - await Promise.all([ - peterLustig.relateTo(racoon, 'rewarded'), - peterLustig.relateTo(rhino, 'rewarded'), - peterLustig.relateTo(wolf, 'rewarded'), - bobDerBaumeister.relateTo(racoon, 'rewarded'), - bobDerBaumeister.relateTo(turtle, 'rewarded'), - jennyRostock.relateTo(bear, 'rewarded'), - dagobert.relateTo(rabbit, 'rewarded'), + await peterLustig.relateTo(racoon, 'rewarded') + await peterLustig.relateTo(rhino, 'rewarded') + await peterLustig.relateTo(wolf, 'rewarded') + await bobDerBaumeister.relateTo(racoon, 'rewarded') + await bobDerBaumeister.relateTo(turtle, 'rewarded') + await jennyRostock.relateTo(bear, 'rewarded') + await dagobert.relateTo(rabbit, 'rewarded') - peterLustig.relateTo(bobDerBaumeister, 'friends'), - peterLustig.relateTo(jennyRostock, 'friends'), - bobDerBaumeister.relateTo(jennyRostock, 'friends'), + await peterLustig.relateTo(bobDerBaumeister, 'friends') + await peterLustig.relateTo(jennyRostock, 'friends') + await bobDerBaumeister.relateTo(jennyRostock, 'friends') - peterLustig.relateTo(jennyRostock, 'following'), - peterLustig.relateTo(huey, 'following'), - bobDerBaumeister.relateTo(huey, 'following'), - jennyRostock.relateTo(huey, 'following'), - huey.relateTo(dewey, 'following'), - dewey.relateTo(huey, 'following'), - louie.relateTo(jennyRostock, 'following'), + await peterLustig.relateTo(jennyRostock, 'following') + await peterLustig.relateTo(huey, 'following') + await bobDerBaumeister.relateTo(huey, 'following') + await jennyRostock.relateTo(huey, 'following') + await huey.relateTo(dewey, 'following') + await dewey.relateTo(huey, 'following') + await louie.relateTo(jennyRostock, 'following') - huey.relateTo(dagobert, 'muted'), - dewey.relateTo(dagobert, 'muted'), - louie.relateTo(dagobert, 'muted'), + await huey.relateTo(dagobert, 'muted') + await dewey.relateTo(dagobert, 'muted') + await louie.relateTo(dagobert, 'muted') - dagobert.relateTo(huey, 'blocked'), - dagobert.relateTo(dewey, 'blocked'), - dagobert.relateTo(louie, 'blocked'), - ]) + await dagobert.relateTo(huey, 'blocked') + await dagobert.relateTo(dewey, 'blocked') + await dagobert.relateTo(louie, 'blocked') + // categories await Promise.all( categories.map(({ icon, name }, index) => { - Factory.build('category', { + return Factory.build('category', { id: `cat${index + 1}`, slug: name, name, @@ -287,23 +280,20 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }), ) - const [environment, nature, democracy, freedom] = await Promise.all([ - Factory.build('tag', { - id: 'Environment', - }), - Factory.build('tag', { - id: 'Nature', - }), - Factory.build('tag', { - id: 'Democracy', - }), - Factory.build('tag', { - id: 'Freedom', - }), - ]) - - // Create Groups + const environment = await Factory.build('tag', { + id: 'Environment', + }) + const nature = await Factory.build('tag', { + id: 'Nature', + }) + const democracy = await Factory.build('tag', { + id: 'Democracy', + }) + const freedom = await Factory.build('tag', { + id: 'Freedom', + }) + // groups authenticatedUser = await peterLustig.toJson() await Promise.all([ mutate({ @@ -596,166 +586,236 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }), ]) - // Create Posts + // Create Events (by peter lustig) + authenticatedUser = await peterLustig.toJson() + const now = new Date() - const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([ - Factory.build( - 'post', - { - id: 'p0', - language: sample(languages), - }, - { - categoryIds: ['cat16'], - author: peterLustig, - image: Factory.build('image', { - url: faker.image.unsplash.food(300, 169), - sensitive: true, - aspectRatio: 300 / 169, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p1', - language: sample(languages), - }, - { - categoryIds: ['cat1'], - author: bobDerBaumeister, - image: Factory.build('image', { - url: faker.image.unsplash.technology(300, 1500), - aspectRatio: 300 / 1500, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p3', - language: sample(languages), - }, - { - categoryIds: ['cat3'], - author: huey, - }, - ), - Factory.build( - 'post', - { - id: 'p4', - language: sample(languages), - }, - { + await Promise.all([ + mutate({ + mutation: createPostMutation(), + variables: { + id: 'e0', + title: 'Illegaler Kindergeburtstag', + content: 'Elli hat nächste Woche Geburtstag. Wir feiern das!', categoryIds: ['cat4'], - author: dewey, + postType: 'Event', + eventInput: { + eventStart: new Date( + now.getFullYear(), + now.getMonth(), + now.getDate() + 7, + ).toISOString(), + eventVenue: 'Ellis Kinderzimmer', + eventLocationName: 'Deutschland', + }, }, - ), - Factory.build( - 'post', - { - id: 'p5', - language: sample(languages), - }, - { + }), + mutate({ + mutation: createPostMutation(), + variables: { + id: 'e1', + title: 'Wir Schützen den Stuttgarter Schlossgarten', + content: 'Kein Baum wird gefällt werden!', categoryIds: ['cat5'], - author: louie, + postType: 'Event', + eventInput: { + eventStart: new Date( + now.getFullYear(), + now.getMonth(), + now.getDate() + 1, + ).toISOString(), + eventVenue: 'Schlossgarten', + eventLocationName: 'Stuttgart', + }, }, - ), - Factory.build( - 'post', - { - id: 'p6', - language: sample(languages), + }), + mutate({ + mutation: createPostMutation(), + variables: { + id: 'e2', + title: 'IT 4 Change Treffen', + content: 'Wir sitzen eine Woche zusammen rum und glotzen uns blöde an.', + categoryIds: ['cat5'], + postType: 'Event', + eventInput: { + eventStart: new Date( + now.getFullYear(), + now.getMonth(), + now.getDate() + 1, + ).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 4).toISOString(), + eventVenue: 'Ferienlager', + eventLocationName: 'Bahra, Sachsen', + }, }, - { - categoryIds: ['cat6'], - author: peterLustig, - image: Factory.build('image', { - url: faker.image.unsplash.buildings(300, 857), - aspectRatio: 300 / 857, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p9', - language: sample(languages), - }, - { - categoryIds: ['cat9'], - author: huey, - }, - ), - Factory.build( - 'post', - { - id: 'p10', - }, - { - categoryIds: ['cat10'], - author: dewey, - image: Factory.build('image', { - sensitive: true, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p11', - language: sample(languages), - }, - { - categoryIds: ['cat11'], - author: louie, - image: Factory.build('image', { - url: faker.image.unsplash.people(300, 901), - aspectRatio: 300 / 901, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p13', - language: sample(languages), - }, - { - categoryIds: ['cat13'], - author: bobDerBaumeister, - }, - ), - Factory.build( - 'post', - { - id: 'p14', - language: sample(languages), - }, - { - categoryIds: ['cat14'], - author: jennyRostock, - image: Factory.build('image', { - url: faker.image.unsplash.objects(300, 200), - aspectRatio: 300 / 450, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p15', - language: sample(languages), - }, - { - categoryIds: ['cat15'], - author: huey, - }, - ), + }), ]) + let passedEvent = await neode.find('Post', 'e1') + await passedEvent.update({ eventStart: new Date(2010, 8, 30, 10).toISOString() }) + passedEvent = await neode.find('Post', 'e2') + await passedEvent.update({ + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 3).toISOString(), + }) + + // posts (articles) + const p0 = await Factory.build( + 'post', + { + id: 'p0', + language: sample(languages), + }, + { + categoryIds: ['cat16'], + author: peterLustig, + image: Factory.build('image', { + url: faker.image.unsplash.food(300, 169), + sensitive: true, + aspectRatio: 300 / 169, + }), + }, + ) + const p1 = await Factory.build( + 'post', + { + id: 'p1', + language: sample(languages), + }, + { + categoryIds: ['cat1'], + author: bobDerBaumeister, + image: Factory.build('image', { + url: faker.image.unsplash.technology(300, 1500), + aspectRatio: 300 / 1500, + }), + }, + ) + const p3 = await Factory.build( + 'post', + { + id: 'p3', + language: sample(languages), + }, + { + categoryIds: ['cat3'], + author: huey, + }, + ) + const p4 = await Factory.build( + 'post', + { + id: 'p4', + language: sample(languages), + }, + { + categoryIds: ['cat4'], + author: dewey, + }, + ) + const p5 = await Factory.build( + 'post', + { + id: 'p5', + language: sample(languages), + }, + { + categoryIds: ['cat5'], + author: louie, + }, + ) + const p6 = await Factory.build( + 'post', + { + id: 'p6', + language: sample(languages), + }, + { + categoryIds: ['cat6'], + author: peterLustig, + image: Factory.build('image', { + url: faker.image.unsplash.buildings(300, 857), + aspectRatio: 300 / 857, + }), + }, + ) + const p9 = await Factory.build( + 'post', + { + id: 'p9', + language: sample(languages), + }, + { + categoryIds: ['cat9'], + author: huey, + }, + ) + const p10 = await Factory.build( + 'post', + { + id: 'p10', + }, + { + categoryIds: ['cat10'], + author: dewey, + image: Factory.build('image', { + sensitive: true, + }), + }, + ) + const p11 = await Factory.build( + 'post', + { + id: 'p11', + language: sample(languages), + }, + { + categoryIds: ['cat11'], + author: louie, + image: Factory.build('image', { + url: faker.image.unsplash.people(300, 901), + aspectRatio: 300 / 901, + }), + }, + ) + const p13 = await Factory.build( + 'post', + { + id: 'p13', + language: sample(languages), + }, + { + categoryIds: ['cat13'], + author: bobDerBaumeister, + }, + ) + const p14 = await Factory.build( + 'post', + { + id: 'p14', + language: sample(languages), + }, + { + categoryIds: ['cat14'], + author: jennyRostock, + image: Factory.build('image', { + url: faker.image.unsplash.objects(300, 200), + aspectRatio: 300 / 450, + }), + }, + ) + const p15 = await Factory.build( + 'post', + { + id: 'p15', + language: sample(languages), + }, + { + categoryIds: ['cat15'], + author: huey, + }, + ) + + // invite code await Factory.build( 'inviteCode', { @@ -852,8 +912,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) authenticatedUser = null - const comments = await Promise.all([ - Factory.build( + const comments: any[] = [] + comments.push( + await Factory.build( 'comment', { id: 'c1', @@ -863,7 +924,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p1', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c2', @@ -873,7 +934,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p1', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c3', @@ -883,7 +944,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p3', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c5', @@ -893,7 +954,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p3', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c6', @@ -903,7 +964,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p4', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c7', @@ -913,7 +974,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p2', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c8', @@ -923,7 +984,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c9', @@ -933,7 +994,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c10', @@ -943,7 +1004,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c11', @@ -953,7 +1014,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c12', @@ -963,133 +1024,126 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - ]) + ) const trollingComment = comments[0] - await Promise.all([ - democracy.relateTo(p3, 'post'), - democracy.relateTo(p11, 'post'), - democracy.relateTo(p15, 'post'), - democracy.relateTo(p7, 'post'), - environment.relateTo(p1, 'post'), - environment.relateTo(p5, 'post'), - environment.relateTo(p9, 'post'), - environment.relateTo(p13, 'post'), - freedom.relateTo(p0, 'post'), - freedom.relateTo(p4, 'post'), - freedom.relateTo(p8, 'post'), - freedom.relateTo(p12, 'post'), - nature.relateTo(p2, 'post'), - nature.relateTo(p6, 'post'), - nature.relateTo(p10, 'post'), - nature.relateTo(p14, 'post'), - peterLustig.relateTo(p15, 'emoted', { emotion: 'surprised' }), - bobDerBaumeister.relateTo(p15, 'emoted', { emotion: 'surprised' }), - jennyRostock.relateTo(p15, 'emoted', { emotion: 'surprised' }), - huey.relateTo(p15, 'emoted', { emotion: 'surprised' }), - dewey.relateTo(p15, 'emoted', { emotion: 'surprised' }), - louie.relateTo(p15, 'emoted', { emotion: 'surprised' }), - dagobert.relateTo(p15, 'emoted', { emotion: 'surprised' }), - bobDerBaumeister.relateTo(p14, 'emoted', { emotion: 'cry' }), - jennyRostock.relateTo(p13, 'emoted', { emotion: 'angry' }), - huey.relateTo(p12, 'emoted', { emotion: 'funny' }), - dewey.relateTo(p11, 'emoted', { emotion: 'surprised' }), - louie.relateTo(p10, 'emoted', { emotion: 'cry' }), - dewey.relateTo(p9, 'emoted', { emotion: 'happy' }), - huey.relateTo(p8, 'emoted', { emotion: 'angry' }), - jennyRostock.relateTo(p7, 'emoted', { emotion: 'funny' }), - bobDerBaumeister.relateTo(p6, 'emoted', { emotion: 'surprised' }), - peterLustig.relateTo(p5, 'emoted', { emotion: 'cry' }), - bobDerBaumeister.relateTo(p4, 'emoted', { emotion: 'happy' }), - jennyRostock.relateTo(p3, 'emoted', { emotion: 'angry' }), - huey.relateTo(p2, 'emoted', { emotion: 'funny' }), - dewey.relateTo(p1, 'emoted', { emotion: 'surprised' }), - louie.relateTo(p0, 'emoted', { emotion: 'cry' }), - ]) + await democracy.relateTo(p3, 'post') + await democracy.relateTo(p11, 'post') + await democracy.relateTo(p15, 'post') + await democracy.relateTo(p7, 'post') + await environment.relateTo(p1, 'post') + await environment.relateTo(p5, 'post') + await environment.relateTo(p9, 'post') + await environment.relateTo(p13, 'post') + await freedom.relateTo(p0, 'post') + await freedom.relateTo(p4, 'post') + await freedom.relateTo(p8, 'post') + await freedom.relateTo(p12, 'post') + await nature.relateTo(p2, 'post') + await nature.relateTo(p6, 'post') + await nature.relateTo(p10, 'post') + await nature.relateTo(p14, 'post') + await peterLustig.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await bobDerBaumeister.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await jennyRostock.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await huey.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await dewey.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await louie.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await dagobert.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await bobDerBaumeister.relateTo(p14, 'emoted', { emotion: 'cry' }) + await jennyRostock.relateTo(p13, 'emoted', { emotion: 'angry' }) + await huey.relateTo(p12, 'emoted', { emotion: 'funny' }) + await dewey.relateTo(p11, 'emoted', { emotion: 'surprised' }) + await louie.relateTo(p10, 'emoted', { emotion: 'cry' }) + await dewey.relateTo(p9, 'emoted', { emotion: 'happy' }) + await huey.relateTo(p8, 'emoted', { emotion: 'angry' }) + await jennyRostock.relateTo(p7, 'emoted', { emotion: 'funny' }) + await bobDerBaumeister.relateTo(p6, 'emoted', { emotion: 'surprised' }) + await peterLustig.relateTo(p5, 'emoted', { emotion: 'cry' }) + await bobDerBaumeister.relateTo(p4, 'emoted', { emotion: 'happy' }) + await jennyRostock.relateTo(p3, 'emoted', { emotion: 'angry' }) + await huey.relateTo(p2, 'emoted', { emotion: 'funny' }) + await dewey.relateTo(p1, 'emoted', { emotion: 'surprised' }) + await louie.relateTo(p0, 'emoted', { emotion: 'cry' }) - await Promise.all([ - peterLustig.relateTo(p1, 'shouted'), - peterLustig.relateTo(p6, 'shouted'), - bobDerBaumeister.relateTo(p0, 'shouted'), - bobDerBaumeister.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p7, 'shouted'), - huey.relateTo(p8, 'shouted'), - huey.relateTo(p9, 'shouted'), - dewey.relateTo(p10, 'shouted'), - peterLustig.relateTo(p2, 'shouted'), - peterLustig.relateTo(p6, 'shouted'), - bobDerBaumeister.relateTo(p0, 'shouted'), - bobDerBaumeister.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p7, 'shouted'), - huey.relateTo(p8, 'shouted'), - huey.relateTo(p9, 'shouted'), - louie.relateTo(p10, 'shouted'), - ]) + await peterLustig.relateTo(p1, 'shouted') + await peterLustig.relateTo(p6, 'shouted') + await bobDerBaumeister.relateTo(p0, 'shouted') + await bobDerBaumeister.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p7, 'shouted') + await huey.relateTo(p8, 'shouted') + await huey.relateTo(p9, 'shouted') + await dewey.relateTo(p10, 'shouted') + await peterLustig.relateTo(p2, 'shouted') + await peterLustig.relateTo(p6, 'shouted') + await bobDerBaumeister.relateTo(p0, 'shouted') + await bobDerBaumeister.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p7, 'shouted') + await huey.relateTo(p8, 'shouted') + await huey.relateTo(p9, 'shouted') + await louie.relateTo(p10, 'shouted') - const reports = await Promise.all([ - Factory.build('report'), - Factory.build('report'), - Factory.build('report'), - Factory.build('report'), - ]) + const reports: any[] = [] + reports.push( + await Factory.build('report'), + await Factory.build('report'), + await Factory.build('report'), + await Factory.build('report'), + ) const reportAgainstDagobert = reports[0] const reportAgainstTrollingPost = reports[1] const reportAgainstTrollingComment = reports[2] const reportAgainstDewey = reports[3] // report resource first time - await Promise.all([ - reportAgainstDagobert.relateTo(jennyRostock, 'filed', { - resourceId: 'u7', - reasonCategory: 'discrimination_etc', - reasonDescription: 'This user is harassing me with bigoted remarks!', - }), - reportAgainstDagobert.relateTo(dagobert, 'belongsTo'), - reportAgainstTrollingPost.relateTo(jennyRostock, 'filed', { - resourceId: 'p2', - reasonCategory: 'doxing', - reasonDescription: "This shouldn't be shown to anybody else! It's my private thing!", - }), - reportAgainstTrollingPost.relateTo(p2, 'belongsTo'), - reportAgainstTrollingComment.relateTo(huey, 'filed', { - resourceId: 'c1', - reasonCategory: 'other', - reasonDescription: 'This comment is bigoted', - }), - reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'), - reportAgainstDewey.relateTo(dagobert, 'filed', { - resourceId: 'u5', - reasonCategory: 'discrimination_etc', - reasonDescription: 'This user is harassing me!', - }), - reportAgainstDewey.relateTo(dewey, 'belongsTo'), - ]) + await reportAgainstDagobert.relateTo(jennyRostock, 'filed', { + resourceId: 'u7', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This user is harassing me with bigoted remarks!', + }) + await reportAgainstDagobert.relateTo(dagobert, 'belongsTo') + await reportAgainstTrollingPost.relateTo(jennyRostock, 'filed', { + resourceId: 'p2', + reasonCategory: 'doxing', + reasonDescription: "This shouldn't be shown to anybody else! It's my private thing!", + }) + await reportAgainstTrollingPost.relateTo(p2, 'belongsTo') + await reportAgainstTrollingComment.relateTo(huey, 'filed', { + resourceId: 'c1', + reasonCategory: 'other', + reasonDescription: 'This comment is bigoted', + }) + await reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo') + await reportAgainstDewey.relateTo(dagobert, 'filed', { + resourceId: 'u5', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This user is harassing me!', + }) + await reportAgainstDewey.relateTo(dewey, 'belongsTo') // report resource a second time - await Promise.all([ - reportAgainstDagobert.relateTo(louie, 'filed', { - resourceId: 'u7', - reasonCategory: 'discrimination_etc', - reasonDescription: 'this user is attacking me for who I am!', - }), - reportAgainstDagobert.relateTo(dagobert, 'belongsTo'), - reportAgainstTrollingPost.relateTo(peterLustig, 'filed', { - resourceId: 'p2', - reasonCategory: 'discrimination_etc', - reasonDescription: 'This post is bigoted', - }), - reportAgainstTrollingPost.relateTo(p2, 'belongsTo'), + await reportAgainstDagobert.relateTo(louie, 'filed', { + resourceId: 'u7', + reasonCategory: 'discrimination_etc', + reasonDescription: 'this user is attacking me for who I am!', + }) + await reportAgainstDagobert.relateTo(dagobert, 'belongsTo') + await reportAgainstTrollingPost.relateTo(peterLustig, 'filed', { + resourceId: 'p2', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This post is bigoted', + }) + await reportAgainstTrollingPost.relateTo(p2, 'belongsTo') - reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'filed', { - resourceId: 'c1', - reasonCategory: 'pornographic_content_links', - reasonDescription: 'This comment is porno!!!', - }), - reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'), - ]) + await reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'filed', { + resourceId: 'c1', + reasonCategory: 'pornographic_content_links', + reasonDescription: 'This comment is porno!!!', + }) + await reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo') const disableVariables = { resourceId: 'undefined-resource', @@ -1098,46 +1152,46 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] } // review resource first time - await Promise.all([ - reportAgainstDagobert.relateTo(bobDerBaumeister, 'reviewed', { - ...disableVariables, - resourceId: 'u7', - }), - dagobert.update({ disabled: true, updatedAt: new Date().toISOString() }), - reportAgainstTrollingPost.relateTo(peterLustig, 'reviewed', { - ...disableVariables, - resourceId: 'p2', - }), - p2.update({ disabled: true, updatedAt: new Date().toISOString() }), - reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'reviewed', { - ...disableVariables, - resourceId: 'c1', - }), - trollingComment.update({ disabled: true, updatedAt: new Date().toISOString() }), - ]) + await reportAgainstDagobert.relateTo(bobDerBaumeister, 'reviewed', { + ...disableVariables, + resourceId: 'u7', + }) + await dagobert.update({ disabled: true, updatedAt: new Date().toISOString() }) + await reportAgainstTrollingPost.relateTo(peterLustig, 'reviewed', { + ...disableVariables, + resourceId: 'p2', + }) + await p2.update({ disabled: true, updatedAt: new Date().toISOString() }) + await reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'reviewed', { + ...disableVariables, + resourceId: 'c1', + }) + await trollingComment.update({ disabled: true, updatedAt: new Date().toISOString() }) // second review of resource and close report - await Promise.all([ - reportAgainstDagobert.relateTo(peterLustig, 'reviewed', { - resourceId: 'u7', - disable: false, - closed: true, - }), - dagobert.update({ disabled: false, updatedAt: new Date().toISOString(), closed: true }), - reportAgainstTrollingPost.relateTo(bobDerBaumeister, 'reviewed', { - resourceId: 'p2', - disable: true, - closed: true, - }), - p2.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }), - reportAgainstTrollingComment.relateTo(peterLustig, 'reviewed', { - ...disableVariables, - resourceId: 'c1', - disable: true, - closed: true, - }), - trollingComment.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }), - ]) + await reportAgainstDagobert.relateTo(peterLustig, 'reviewed', { + resourceId: 'u7', + disable: false, + closed: true, + }) + await dagobert.update({ disabled: false, updatedAt: new Date().toISOString(), closed: true }) + await reportAgainstTrollingPost.relateTo(bobDerBaumeister, 'reviewed', { + resourceId: 'p2', + disable: true, + closed: true, + }) + await p2.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }) + await reportAgainstTrollingComment.relateTo(peterLustig, 'reviewed', { + ...disableVariables, + resourceId: 'c1', + disable: true, + closed: true, + }) + await trollingComment.update({ + disabled: true, + updatedAt: new Date().toISOString(), + closed: true, + }) const additionalUsers = await Promise.all( [...Array(30).keys()].map(() => Factory.build('user')), @@ -1501,6 +1555,90 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ) await Factory.build('donations') + + // Chat + authenticatedUser = await huey.toJson() + const { data: roomHueyPeter } = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: (await peterLustig.toJson()).id, + }, + }) + + for (let i = 0; i < 30; i++) { + authenticatedUser = await huey.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: roomHueyPeter?.CreateRoom.id, + content: faker.lorem.sentence(), + }, + }) + authenticatedUser = await peterLustig.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: roomHueyPeter?.CreateRoom.id, + content: faker.lorem.sentence(), + }, + }) + } + + authenticatedUser = await huey.toJson() + const { data: roomHueyJenny } = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: (await jennyRostock.toJson()).id, + }, + }) + for (let i = 0; i < 1000; i++) { + authenticatedUser = await huey.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: roomHueyJenny?.CreateRoom.id, + content: faker.lorem.sentence(), + }, + }) + authenticatedUser = await jennyRostock.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: roomHueyJenny?.CreateRoom.id, + content: faker.lorem.sentence(), + }, + }) + } + + for (const user of additionalUsers) { + authenticatedUser = await jennyRostock.toJson() + const { data: room } = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: (await user.toJson()).id, + }, + }) + + for (let i = 0; i < 29; i++) { + authenticatedUser = await jennyRostock.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: room?.CreateRoom.id, + content: faker.lorem.sentence(), + }, + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: room?.CreateRoom.id, + content: faker.lorem.sentence(), + }, + }) + } + } + /* eslint-disable-next-line no-console */ console.log('Seeded Data...') await driver.close() diff --git a/backend/src/graphql/authentications.js b/backend/src/graphql/authentications.ts similarity index 100% rename from backend/src/graphql/authentications.js rename to backend/src/graphql/authentications.ts diff --git a/backend/src/graphql/comments.js b/backend/src/graphql/comments.ts similarity index 100% rename from backend/src/graphql/comments.js rename to backend/src/graphql/comments.ts diff --git a/backend/src/graphql/groups.js b/backend/src/graphql/groups.ts similarity index 100% rename from backend/src/graphql/groups.js rename to backend/src/graphql/groups.ts diff --git a/backend/src/graphql/messages.ts b/backend/src/graphql/messages.ts new file mode 100644 index 000000000..fde45083b --- /dev/null +++ b/backend/src/graphql/messages.ts @@ -0,0 +1,47 @@ +import gql from 'graphql-tag' + +export const createMessageMutation = () => { + return gql` + mutation ($roomId: ID!, $content: String!) { + CreateMessage(roomId: $roomId, content: $content) { + id + content + senderId + username + avatar + date + saved + distributed + seen + } + } + ` +} + +export const messageQuery = () => { + return gql` + query ($roomId: ID!, $first: Int, $offset: Int) { + Message(roomId: $roomId, first: $first, offset: $offset, orderBy: indexId_desc) { + _id + id + indexId + content + senderId + username + avatar + date + saved + distributed + seen + } + } + ` +} + +export const markMessagesAsSeen = () => { + return gql` + mutation ($messageIds: [String!]) { + MarkMessagesAsSeen(messageIds: $messageIds) + } + ` +} diff --git a/backend/src/graphql/notifications.js b/backend/src/graphql/notifications.ts similarity index 100% rename from backend/src/graphql/notifications.js rename to backend/src/graphql/notifications.ts diff --git a/backend/src/graphql/posts.js b/backend/src/graphql/posts.ts similarity index 100% rename from backend/src/graphql/posts.js rename to backend/src/graphql/posts.ts diff --git a/backend/src/graphql/rooms.ts b/backend/src/graphql/rooms.ts new file mode 100644 index 000000000..294b50641 --- /dev/null +++ b/backend/src/graphql/rooms.ts @@ -0,0 +1,65 @@ +import gql from 'graphql-tag' + +export const createRoomMutation = () => { + return gql` + mutation ($userId: ID!) { + CreateRoom(userId: $userId) { + id + roomId + roomName + lastMessageAt + unreadCount + users { + _id + id + name + avatar { + url + } + } + } + } + ` +} + +export const roomQuery = () => { + return gql` + query Room($first: Int, $offset: Int, $id: ID) { + Room(first: $first, offset: $offset, id: $id, orderBy: createdAt_desc) { + id + roomId + roomName + lastMessageAt + unreadCount + lastMessage { + _id + id + content + senderId + username + avatar + date + saved + distributed + seen + } + users { + _id + id + name + avatar { + url + } + } + } + } + ` +} + +export const unreadRoomsQuery = () => { + return gql` + query { + UnreadRooms + } + ` +} diff --git a/backend/src/graphql/userManagement.js b/backend/src/graphql/userManagement.ts similarity index 100% rename from backend/src/graphql/userManagement.js rename to backend/src/graphql/userManagement.ts diff --git a/backend/src/helpers/asyncForEach.js b/backend/src/helpers/asyncForEach.ts similarity index 100% rename from backend/src/helpers/asyncForEach.js rename to backend/src/helpers/asyncForEach.ts diff --git a/backend/src/helpers/encryptPassword.js b/backend/src/helpers/encryptPassword.ts similarity index 100% rename from backend/src/helpers/encryptPassword.js rename to backend/src/helpers/encryptPassword.ts diff --git a/backend/src/helpers/jest.js b/backend/src/helpers/jest.ts similarity index 100% rename from backend/src/helpers/jest.js rename to backend/src/helpers/jest.ts diff --git a/backend/src/helpers/walkRecursive.js b/backend/src/helpers/walkRecursive.ts similarity index 94% rename from backend/src/helpers/walkRecursive.js rename to backend/src/helpers/walkRecursive.ts index 26a3a01b2..f560cf9cb 100644 --- a/backend/src/helpers/walkRecursive.js +++ b/backend/src/helpers/walkRecursive.ts @@ -5,7 +5,7 @@ * @property fieldName String * @property callback Function */ -function walkRecursive(data, fields, fieldName, callback, _key) { +function walkRecursive(data, fields, fieldName, callback, _key?) { if (!Array.isArray(fields)) { throw new Error('please provide an fields array for the walkRecursive helper') } diff --git a/backend/src/jwt/decode.spec.js b/backend/src/jwt/decode.spec.ts similarity index 100% rename from backend/src/jwt/decode.spec.js rename to backend/src/jwt/decode.spec.ts diff --git a/backend/src/jwt/decode.js b/backend/src/jwt/decode.ts similarity index 100% rename from backend/src/jwt/decode.js rename to backend/src/jwt/decode.ts diff --git a/backend/src/jwt/encode.spec.js b/backend/src/jwt/encode.spec.ts similarity index 100% rename from backend/src/jwt/encode.spec.js rename to backend/src/jwt/encode.spec.ts diff --git a/backend/src/jwt/encode.js b/backend/src/jwt/encode.ts similarity index 100% rename from backend/src/jwt/encode.js rename to backend/src/jwt/encode.ts diff --git a/backend/src/middleware/activityPubMiddleware.js b/backend/src/middleware/activityPubMiddleware.js deleted file mode 100644 index 712ca6c8a..000000000 --- a/backend/src/middleware/activityPubMiddleware.js +++ /dev/null @@ -1,56 +0,0 @@ -import { generateRsaKeyPair } from '../activitypub/security' -import { activityPub } from '../activitypub/ActivityPub' -// import as from 'activitystrea.ms' - -// const debug = require('debug')('backend:schema') - -export default { - Mutation: { - // CreatePost: async (resolve, root, args, context, info) => { - // args.activityId = activityPub.generateStatusId(context.user.slug) - // args.objectId = activityPub.generateStatusId(context.user.slug) - - // const post = await resolve(root, args, context, info) - - // const { user: author } = context - // const actorId = author.actorId - // debug(`actorId = ${actorId}`) - // const createActivity = await new Promise((resolve, reject) => { - // as.create() - // .id(`${actorId}/status/${args.activityId}`) - // .actor(`${actorId}`) - // .object( - // as - // .article() - // .id(`${actorId}/status/${post.id}`) - // .content(post.content) - // .to('https://www.w3.org/ns/activitystreams#Public') - // .publishedNow() - // .attributedTo(`${actorId}`), - // ) - // .prettyWrite((err, doc) => { - // if (err) { - // reject(err) - // } else { - // debug(doc) - // const parsedDoc = JSON.parse(doc) - // parsedDoc.send = true - // resolve(JSON.stringify(parsedDoc)) - // } - // }) - // }) - // try { - // await activityPub.sendActivity(createActivity) - // } catch (e) { - // debug(`error sending post activity\n${e}`) - // } - // return post - // }, - SignupVerification: async (resolve, root, args, context, info) => { - const keys = generateRsaKeyPair() - Object.assign(args, keys) - args.actorId = `${activityPub.host}/activitypub/users/${args.slug}` - return resolve(root, args, context, info) - }, - }, -} diff --git a/backend/src/middleware/chatMiddleware.ts b/backend/src/middleware/chatMiddleware.ts new file mode 100644 index 000000000..c28d6a70d --- /dev/null +++ b/backend/src/middleware/chatMiddleware.ts @@ -0,0 +1,57 @@ +import { isArray } from 'lodash' + +const setRoomProps = (room) => { + if (room.users) { + room.users.forEach((user) => { + user._id = user.id + }) + } + if (room.lastMessage) { + room.lastMessage._id = room.lastMessage.id + } +} + +const setMessageProps = (message, context) => { + message._id = message.id + if (message.senderId !== context.user.id) { + message.distributed = true + } +} + +const roomProperties = async (resolve, root, args, context, info) => { + const resolved = await resolve(root, args, context, info) + if (resolved) { + if (isArray(resolved)) { + resolved.forEach((room) => { + setRoomProps(room) + }) + } else { + setRoomProps(resolved) + } + } + return resolved +} + +const messageProperties = async (resolve, root, args, context, info) => { + const resolved = await resolve(root, args, context, info) + if (resolved) { + if (isArray(resolved)) { + resolved.forEach((message) => { + setMessageProps(message, context) + }) + } else { + setMessageProps(resolved, context) + } + } + return resolved +} + +export default { + Query: { + Room: roomProperties, + Message: messageProperties, + }, + Mutation: { + CreateRoom: roomProperties, + }, +} diff --git a/backend/src/middleware/excerptMiddleware.js b/backend/src/middleware/excerptMiddleware.ts similarity index 100% rename from backend/src/middleware/excerptMiddleware.js rename to backend/src/middleware/excerptMiddleware.ts diff --git a/backend/src/middleware/hashtags/extractHashtags.spec.js b/backend/src/middleware/hashtags/extractHashtags.spec.ts similarity index 100% rename from backend/src/middleware/hashtags/extractHashtags.spec.js rename to backend/src/middleware/hashtags/extractHashtags.spec.ts diff --git a/backend/src/middleware/hashtags/extractHashtags.js b/backend/src/middleware/hashtags/extractHashtags.ts similarity index 93% rename from backend/src/middleware/hashtags/extractHashtags.js rename to backend/src/middleware/hashtags/extractHashtags.ts index 4c7667557..7570802af 100644 --- a/backend/src/middleware/hashtags/extractHashtags.js +++ b/backend/src/middleware/hashtags/extractHashtags.ts @@ -8,7 +8,7 @@ import { exec, build } from 'xregexp/xregexp-all.js' // 2. If it starts with a digit '0-9' than a unicode letter has to follow. const regX = build('^((\\pL+[\\pL0-9]*)|([0-9]+\\pL+[\\pL0-9]*))$') -export default function (content) { +export default function (content?) { if (!content) return [] const $ = cheerio.load(content) // We can not search for class '.hashtag', because the classes are removed at the 'xss' middleware. @@ -18,7 +18,7 @@ export default function (content) { return $(el).attr('data-hashtag-id') }) .get() - const hashtags = [] + const hashtags: any = [] ids.forEach((id) => { const match = exec(id, regX) if (match != null) { diff --git a/backend/src/middleware/hashtags/hashtagsMiddleware.spec.js b/backend/src/middleware/hashtags/hashtagsMiddleware.spec.ts similarity index 100% rename from backend/src/middleware/hashtags/hashtagsMiddleware.spec.js rename to backend/src/middleware/hashtags/hashtagsMiddleware.spec.ts diff --git a/backend/src/middleware/hashtags/hashtagsMiddleware.js b/backend/src/middleware/hashtags/hashtagsMiddleware.ts similarity index 100% rename from backend/src/middleware/hashtags/hashtagsMiddleware.js rename to backend/src/middleware/hashtags/hashtagsMiddleware.ts diff --git a/backend/src/middleware/helpers/cleanHtml.js b/backend/src/middleware/helpers/cleanHtml.ts similarity index 100% rename from backend/src/middleware/helpers/cleanHtml.js rename to backend/src/middleware/helpers/cleanHtml.ts diff --git a/backend/src/middleware/helpers/email/sendMail.js b/backend/src/middleware/helpers/email/sendMail.ts similarity index 95% rename from backend/src/middleware/helpers/email/sendMail.js rename to backend/src/middleware/helpers/email/sendMail.ts index 59d3b090b..359efc91e 100644 --- a/backend/src/middleware/helpers/email/sendMail.js +++ b/backend/src/middleware/helpers/email/sendMail.ts @@ -1,12 +1,12 @@ import CONFIG from '../../../config' -import { cleanHtml } from '../../../middleware/helpers/cleanHtml.js' +import { cleanHtml } from '../../../middleware/helpers/cleanHtml' import nodemailer from 'nodemailer' import { htmlToText } from 'nodemailer-html-to-text' const hasEmailConfig = CONFIG.SMTP_HOST && CONFIG.SMTP_PORT const hasAuthData = CONFIG.SMTP_USERNAME && CONFIG.SMTP_PASSWORD -let sendMailCallback = async () => {} +let sendMailCallback: any = async () => {} if (!hasEmailConfig) { if (!CONFIG.TEST) { // eslint-disable-next-line no-console @@ -29,7 +29,7 @@ if (!hasEmailConfig) { cleanHtml(templateArgs.html, 'dummyKey', { allowedTags: ['a'], allowedAttributes: { a: ['href'] }, - }).replace(/&/g, '&'), + } as any).replace(/&/g, '&'), ) } } diff --git a/backend/src/middleware/helpers/email/templateBuilder.spec.js b/backend/src/middleware/helpers/email/templateBuilder.spec.ts similarity index 99% rename from backend/src/middleware/helpers/email/templateBuilder.spec.js rename to backend/src/middleware/helpers/email/templateBuilder.spec.ts index d5b0edf21..cb516c0a9 100644 --- a/backend/src/middleware/helpers/email/templateBuilder.spec.js +++ b/backend/src/middleware/helpers/email/templateBuilder.spec.ts @@ -1,5 +1,5 @@ import CONFIG from '../../../config' -import logosWebapp from '../../../config/logos.js' +import logosWebapp from '../../../config/logos' import { signupTemplate, emailVerificationTemplate, diff --git a/backend/src/middleware/helpers/email/templateBuilder.js b/backend/src/middleware/helpers/email/templateBuilder.ts similarity index 97% rename from backend/src/middleware/helpers/email/templateBuilder.js rename to backend/src/middleware/helpers/email/templateBuilder.ts index bf174ef48..78d7a9bf9 100644 --- a/backend/src/middleware/helpers/email/templateBuilder.js +++ b/backend/src/middleware/helpers/email/templateBuilder.ts @@ -1,7 +1,7 @@ import mustache from 'mustache' import CONFIG from '../../../config' -import metadata from '../../../config/metadata.js' -import logosWebapp from '../../../config/logos.js' +import metadata from '../../../config/metadata' +import logosWebapp from '../../../config/logos' import * as templates from './templates' import * as templatesEN from './templates/en' diff --git a/backend/src/middleware/helpers/email/templates/en/index.js b/backend/src/middleware/helpers/email/templates/de/index.ts similarity index 100% rename from backend/src/middleware/helpers/email/templates/en/index.js rename to backend/src/middleware/helpers/email/templates/de/index.ts diff --git a/backend/src/middleware/helpers/email/templates/de/index.js b/backend/src/middleware/helpers/email/templates/en/index.ts similarity index 100% rename from backend/src/middleware/helpers/email/templates/de/index.js rename to backend/src/middleware/helpers/email/templates/en/index.ts diff --git a/backend/src/middleware/helpers/email/templates/index.js b/backend/src/middleware/helpers/email/templates/index.ts similarity index 100% rename from backend/src/middleware/helpers/email/templates/index.js rename to backend/src/middleware/helpers/email/templates/index.ts diff --git a/backend/src/middleware/includedFieldsMiddleware.js b/backend/src/middleware/includedFieldsMiddleware.ts similarity index 100% rename from backend/src/middleware/includedFieldsMiddleware.js rename to backend/src/middleware/includedFieldsMiddleware.ts diff --git a/backend/src/middleware/index.js b/backend/src/middleware/index.ts similarity index 95% rename from backend/src/middleware/index.js rename to backend/src/middleware/index.ts index 22e92e1a3..08c872db7 100644 --- a/backend/src/middleware/index.js +++ b/backend/src/middleware/index.ts @@ -1,7 +1,5 @@ import { applyMiddleware } from 'graphql-middleware' import CONFIG from './../config' - -import activityPub from './activityPubMiddleware' import softDelete from './softDelete/softDeleteMiddleware' import sluggify from './sluggifyMiddleware' import excerpt from './excerptMiddleware' @@ -16,13 +14,13 @@ import login from './login/loginMiddleware' import sentry from './sentryMiddleware' import languages from './languages/languages' import userInteractions from './userInteractions' +import chatMiddleware from './chatMiddleware' export default (schema) => { const middlewares = { sentry, permissions, xss, - activityPub, validation, sluggify, excerpt, @@ -34,6 +32,7 @@ export default (schema) => { orderBy, languages, userInteractions, + chatMiddleware, } let order = [ @@ -52,6 +51,7 @@ export default (schema) => { 'softDelete', 'includedFields', 'orderBy', + 'chatMiddleware', ] // add permisions middleware at the first position (unless we're seeding) diff --git a/backend/src/middleware/languages/languages.spec.js b/backend/src/middleware/languages/languages.spec.ts similarity index 100% rename from backend/src/middleware/languages/languages.spec.js rename to backend/src/middleware/languages/languages.spec.ts diff --git a/backend/src/middleware/languages/languages.js b/backend/src/middleware/languages/languages.ts similarity index 91% rename from backend/src/middleware/languages/languages.js rename to backend/src/middleware/languages/languages.ts index 087252975..83d4e424c 100644 --- a/backend/src/middleware/languages/languages.js +++ b/backend/src/middleware/languages/languages.ts @@ -1,5 +1,5 @@ import LanguageDetect from 'languagedetect' -import { removeHtmlTags } from '../helpers/cleanHtml.js' +import { removeHtmlTags } from '../helpers/cleanHtml' const setPostLanguage = (text) => { const lngDetector = new LanguageDetect() diff --git a/backend/src/middleware/login/loginMiddleware.js b/backend/src/middleware/login/loginMiddleware.ts similarity index 100% rename from backend/src/middleware/login/loginMiddleware.js rename to backend/src/middleware/login/loginMiddleware.ts diff --git a/backend/src/middleware/notifications/mentions/extractMentionedUsers.spec.js b/backend/src/middleware/notifications/mentions/extractMentionedUsers.spec.ts similarity index 100% rename from backend/src/middleware/notifications/mentions/extractMentionedUsers.spec.js rename to backend/src/middleware/notifications/mentions/extractMentionedUsers.spec.ts diff --git a/backend/src/middleware/notifications/mentions/extractMentionedUsers.js b/backend/src/middleware/notifications/mentions/extractMentionedUsers.ts similarity index 92% rename from backend/src/middleware/notifications/mentions/extractMentionedUsers.js rename to backend/src/middleware/notifications/mentions/extractMentionedUsers.ts index e7e23ace7..ccee18af9 100644 --- a/backend/src/middleware/notifications/mentions/extractMentionedUsers.js +++ b/backend/src/middleware/notifications/mentions/extractMentionedUsers.ts @@ -1,6 +1,6 @@ import cheerio from 'cheerio' -export default (content) => { +export default (content?) => { if (!content) return [] const $ = cheerio.load(content) const userIds = $('a.mention[data-mention-id]') diff --git a/backend/src/middleware/notifications/notificationsMiddleware.spec.js b/backend/src/middleware/notifications/notificationsMiddleware.spec.ts similarity index 99% rename from backend/src/middleware/notifications/notificationsMiddleware.spec.js rename to backend/src/middleware/notifications/notificationsMiddleware.spec.ts index a9046b09f..6cec5c940 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.spec.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.spec.ts @@ -50,7 +50,7 @@ beforeAll(async () => { context: () => { return { user: authenticatedUser, - neode: neode, + neode, driver, } }, @@ -576,7 +576,7 @@ describe('notifications', () => { read: false, }, }), - ).resolves.toMatchObject(expected, { errors: undefined }) + ).resolves.toMatchObject({ ...expected, errors: undefined }) }) }) diff --git a/backend/src/middleware/notifications/notificationsMiddleware.js b/backend/src/middleware/notifications/notificationsMiddleware.ts similarity index 89% rename from backend/src/middleware/notifications/notificationsMiddleware.js rename to backend/src/middleware/notifications/notificationsMiddleware.ts index 1c97e9591..706e46c51 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.ts @@ -15,7 +15,7 @@ const queryNotificationEmails = async (context, notificationUserIds) => { RETURN emailAddress {.email} ` const session = context.driver.session() - const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const writeTxResultPromise = session.readTransaction(async (transaction) => { const emailAddressTransactionResponse = await transaction.run(userEmailCypher, { notificationUserIds, }) @@ -140,16 +140,18 @@ const postAuthorOfComment = async (commentId, { context }) => { const notifyOwnersOfGroup = async (groupId, userId, reason, context) => { const cypher = ` + MATCH (user:User { id: $userId }) MATCH (group:Group { id: $groupId })<-[membership:MEMBER_OF]-(owner:User) WHERE membership.role = 'owner' - WITH owner, group + WITH owner, group, user, membership MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(owner) - WITH group, owner, notification + WITH group, owner, notification, user, membership SET notification.read = FALSE SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) SET notification.updatedAt = toString(datetime()) SET notification.relatedUserId = $userId - RETURN notification {.*, from: group, to: properties(owner)} + WITH owner, group { __typename: 'Group', .*, myRole: membership.roleInGroup } AS finalGroup, user, notification + RETURN notification {.*, from: finalGroup, to: properties(owner), relatedUser: properties(user) } ` const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { @@ -173,16 +175,20 @@ const notifyOwnersOfGroup = async (groupId, userId, reason, context) => { const notifyMemberOfGroup = async (groupId, userId, reason, context) => { const { user: owner } = context const cypher = ` + MATCH (owner:User { id: $ownerId }) MATCH (user:User { id: $userId }) MATCH (group:Group { id: $groupId }) - WITH user, group + OPTIONAL MATCH (user)-[membership:MEMBER_OF]->(group) + WITH user, group, owner, membership MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(user) - WITH group, user, notification + WITH group, user, notification, owner, membership SET notification.read = FALSE SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) SET notification.updatedAt = toString(datetime()) SET notification.relatedUserId = $ownerId - RETURN notification {.*, from: group, to: properties(user)} + WITH group { __typename: 'Group', .*, myRole: membership.roleInGroup } AS finalGroup, + notification, user, owner + RETURN notification {.*, from: finalGroup, to: properties(user), relatedUser: properties(owner) } ` const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { @@ -238,11 +244,11 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => { [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts WITH resource, user, notification, authors, posts, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource + resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'Group']][0], author: authors[0], post: posts[0]} AS finalResource SET notification.read = FALSE SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) SET notification.updatedAt = toString(datetime()) - RETURN notification {.*, from: finalResource, to: properties(user)} + RETURN notification {.*, from: finalResource, to: properties(user), relatedUser: properties(user) } ` const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { @@ -276,9 +282,14 @@ const notifyUsersOfComment = async (label, commentId, postAuthorId, reason, cont SET notification.read = FALSE SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) SET notification.updatedAt = toString(datetime()) - WITH notification, postAuthor, post, + WITH notification, postAuthor, post, commenter, comment {.*, __typename: labels(comment)[0], author: properties(commenter), post: post {.*, author: properties(postAuthor) } } AS finalResource - RETURN notification {.*, from: finalResource, to: properties(postAuthor)} + RETURN notification { + .*, + from: finalResource, + to: properties(postAuthor), + relatedUser: properties(commenter) + } `, { commentId, postAuthorId, reason }, ) diff --git a/backend/src/middleware/orderByMiddleware.spec.js b/backend/src/middleware/orderByMiddleware.spec.ts similarity index 100% rename from backend/src/middleware/orderByMiddleware.spec.js rename to backend/src/middleware/orderByMiddleware.spec.ts diff --git a/backend/src/middleware/orderByMiddleware.js b/backend/src/middleware/orderByMiddleware.ts similarity index 100% rename from backend/src/middleware/orderByMiddleware.js rename to backend/src/middleware/orderByMiddleware.ts diff --git a/backend/src/middleware/permissionsMiddleware.spec.js b/backend/src/middleware/permissionsMiddleware.spec.ts similarity index 100% rename from backend/src/middleware/permissionsMiddleware.spec.js rename to backend/src/middleware/permissionsMiddleware.spec.ts diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.ts similarity index 98% rename from backend/src/middleware/permissionsMiddleware.js rename to backend/src/middleware/permissionsMiddleware.ts index 6cd8f39d6..f87f4b079 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.ts @@ -406,6 +406,9 @@ export default shield( queryLocations: isAuthenticated, availableRoles: isAdmin, getInviteCode: isAuthenticated, // and inviteRegistration + Room: isAuthenticated, + Message: isAuthenticated, + UnreadRooms: isAuthenticated, }, Mutation: { '*': deny, @@ -459,6 +462,9 @@ export default shield( switchUserRole: isAdmin, markTeaserAsViewed: allow, saveCategorySettings: isAuthenticated, + CreateRoom: isAuthenticated, + CreateMessage: isAuthenticated, + MarkMessagesAsSeen: isAuthenticated, }, User: { email: or(isMyOwn, isAdmin), diff --git a/backend/src/middleware/sentryMiddleware.js b/backend/src/middleware/sentryMiddleware.ts similarity index 86% rename from backend/src/middleware/sentryMiddleware.js rename to backend/src/middleware/sentryMiddleware.ts index 8891b8677..73f393eef 100644 --- a/backend/src/middleware/sentryMiddleware.js +++ b/backend/src/middleware/sentryMiddleware.ts @@ -1,7 +1,7 @@ import { sentry } from 'graphql-middleware-sentry' import CONFIG from '../config' -let sentryMiddleware = (resolve, root, args, context, resolveInfo) => +let sentryMiddleware: any = (resolve, root, args, context, resolveInfo) => resolve(root, args, context, resolveInfo) if (CONFIG.SENTRY_DSN_BACKEND) { @@ -12,7 +12,7 @@ if (CONFIG.SENTRY_DSN_BACKEND) { release: CONFIG.COMMIT, environment: CONFIG.NODE_ENV, }, - withScope: (scope, error, context) => { + withScope: (scope, error, context: any) => { scope.setUser({ id: context.user && context.user.id, }) diff --git a/backend/src/middleware/sluggifyMiddleware.js b/backend/src/middleware/sluggifyMiddleware.ts similarity index 100% rename from backend/src/middleware/sluggifyMiddleware.js rename to backend/src/middleware/sluggifyMiddleware.ts diff --git a/backend/src/middleware/slugify/uniqueSlug.spec.js b/backend/src/middleware/slugify/uniqueSlug.spec.ts similarity index 70% rename from backend/src/middleware/slugify/uniqueSlug.spec.js rename to backend/src/middleware/slugify/uniqueSlug.spec.ts index d002eae03..659a439c2 100644 --- a/backend/src/middleware/slugify/uniqueSlug.spec.js +++ b/backend/src/middleware/slugify/uniqueSlug.spec.ts @@ -1,22 +1,22 @@ import uniqueSlug from './uniqueSlug' describe('uniqueSlug', () => { - it('slugifies given string', () => { + it('slugifies given string', async () => { const string = 'Hello World' const isUnique = jest.fn().mockResolvedValue(true) - expect(uniqueSlug(string, isUnique)).resolves.toEqual('hello-world') + await expect(uniqueSlug(string, isUnique)).resolves.toEqual('hello-world') }) - it('increments slugified string until unique', () => { + it('increments slugified string until unique', async () => { const string = 'Hello World' const isUnique = jest.fn().mockResolvedValueOnce(false).mockResolvedValueOnce(true) - expect(uniqueSlug(string, isUnique)).resolves.toEqual('hello-world-1') + await expect(uniqueSlug(string, isUnique)).resolves.toEqual('hello-world-1') }) - it('slugify null string', () => { + it('slugify null string', async () => { const string = null const isUnique = jest.fn().mockResolvedValue(true) - expect(uniqueSlug(string, isUnique)).resolves.toEqual('anonymous') + await expect(uniqueSlug(string, isUnique)).resolves.toEqual('anonymous') }) it('Converts umlaut to a two letter equivalent', async () => { diff --git a/backend/src/middleware/slugify/uniqueSlug.js b/backend/src/middleware/slugify/uniqueSlug.ts similarity index 100% rename from backend/src/middleware/slugify/uniqueSlug.js rename to backend/src/middleware/slugify/uniqueSlug.ts diff --git a/backend/src/middleware/slugifyMiddleware.spec.js b/backend/src/middleware/slugifyMiddleware.spec.ts similarity index 100% rename from backend/src/middleware/slugifyMiddleware.spec.js rename to backend/src/middleware/slugifyMiddleware.spec.ts diff --git a/backend/src/middleware/softDelete/softDeleteMiddleware.spec.js b/backend/src/middleware/softDelete/softDeleteMiddleware.spec.ts similarity index 100% rename from backend/src/middleware/softDelete/softDeleteMiddleware.spec.js rename to backend/src/middleware/softDelete/softDeleteMiddleware.spec.ts diff --git a/backend/src/middleware/softDelete/softDeleteMiddleware.js b/backend/src/middleware/softDelete/softDeleteMiddleware.ts similarity index 100% rename from backend/src/middleware/softDelete/softDeleteMiddleware.js rename to backend/src/middleware/softDelete/softDeleteMiddleware.ts diff --git a/backend/src/middleware/userInteractions.spec.js b/backend/src/middleware/userInteractions.spec.ts similarity index 100% rename from backend/src/middleware/userInteractions.spec.js rename to backend/src/middleware/userInteractions.spec.ts diff --git a/backend/src/middleware/userInteractions.js b/backend/src/middleware/userInteractions.ts similarity index 100% rename from backend/src/middleware/userInteractions.js rename to backend/src/middleware/userInteractions.ts diff --git a/backend/src/middleware/validation/validationMiddleware.spec.js b/backend/src/middleware/validation/validationMiddleware.spec.ts similarity index 100% rename from backend/src/middleware/validation/validationMiddleware.spec.js rename to backend/src/middleware/validation/validationMiddleware.spec.ts diff --git a/backend/src/middleware/validation/validationMiddleware.js b/backend/src/middleware/validation/validationMiddleware.ts similarity index 97% rename from backend/src/middleware/validation/validationMiddleware.js rename to backend/src/middleware/validation/validationMiddleware.ts index 20933a777..ff26f5ef1 100644 --- a/backend/src/middleware/validation/validationMiddleware.js +++ b/backend/src/middleware/validation/validationMiddleware.ts @@ -64,7 +64,7 @@ const validateReview = async (resolve, root, args, context, info) => { WHERE resource:User OR resource:Post OR resource:Comment OPTIONAL MATCH (:User)-[filed:FILED]->(:Report {closed: false})-[:BELONGS_TO]->(resource) OPTIONAL MATCH (resource)<-[:WROTE]-(author:User) - RETURN labels(resource)[0] AS label, author, filed + RETURN [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'User']][0] AS label, author, filed `, { resourceId, diff --git a/backend/src/middleware/xssMiddleware.js b/backend/src/middleware/xssMiddleware.ts similarity index 90% rename from backend/src/middleware/xssMiddleware.js rename to backend/src/middleware/xssMiddleware.ts index 9b15e9712..ede0cc199 100644 --- a/backend/src/middleware/xssMiddleware.js +++ b/backend/src/middleware/xssMiddleware.ts @@ -1,5 +1,5 @@ import walkRecursive from '../helpers/walkRecursive' -import { cleanHtml } from '../middleware/helpers/cleanHtml.js' +import { cleanHtml } from '../middleware/helpers/cleanHtml' // exclamation mark separetes field names, that should not be sanitized const fields = [ diff --git a/backend/src/models/Badge.js b/backend/src/models/Badge.ts similarity index 100% rename from backend/src/models/Badge.js rename to backend/src/models/Badge.ts diff --git a/backend/src/models/Category.js b/backend/src/models/Category.ts similarity index 100% rename from backend/src/models/Category.js rename to backend/src/models/Category.ts diff --git a/backend/src/models/Comment.js b/backend/src/models/Comment.ts similarity index 100% rename from backend/src/models/Comment.js rename to backend/src/models/Comment.ts diff --git a/backend/src/models/Donations.js b/backend/src/models/Donations.ts similarity index 100% rename from backend/src/models/Donations.js rename to backend/src/models/Donations.ts diff --git a/backend/src/models/EmailAddress.js b/backend/src/models/EmailAddress.ts similarity index 100% rename from backend/src/models/EmailAddress.js rename to backend/src/models/EmailAddress.ts diff --git a/backend/src/models/Group.js b/backend/src/models/Group.ts similarity index 100% rename from backend/src/models/Group.js rename to backend/src/models/Group.ts diff --git a/backend/src/models/Image.js b/backend/src/models/Image.ts similarity index 100% rename from backend/src/models/Image.js rename to backend/src/models/Image.ts diff --git a/backend/src/models/InviteCode.js b/backend/src/models/InviteCode.ts similarity index 100% rename from backend/src/models/InviteCode.js rename to backend/src/models/InviteCode.ts diff --git a/backend/src/models/Location.js b/backend/src/models/Location.ts similarity index 100% rename from backend/src/models/Location.js rename to backend/src/models/Location.ts diff --git a/backend/src/models/Migration.js b/backend/src/models/Migration.ts similarity index 100% rename from backend/src/models/Migration.js rename to backend/src/models/Migration.ts diff --git a/backend/src/models/Post.js b/backend/src/models/Post.ts similarity index 95% rename from backend/src/models/Post.js rename to backend/src/models/Post.ts index 235e7d68d..e206ea1f5 100644 --- a/backend/src/models/Post.js +++ b/backend/src/models/Post.ts @@ -57,4 +57,5 @@ export default { }, }, pinned: { type: 'boolean', default: null, valid: [null, true] }, + postType: { type: 'string', default: 'Article', valid: ['Article', 'Event'] }, } diff --git a/backend/src/models/Report.js b/backend/src/models/Report.ts similarity index 100% rename from backend/src/models/Report.js rename to backend/src/models/Report.ts diff --git a/backend/src/models/SocialMedia.js b/backend/src/models/SocialMedia.ts similarity index 100% rename from backend/src/models/SocialMedia.js rename to backend/src/models/SocialMedia.ts diff --git a/backend/src/models/Tag.js b/backend/src/models/Tag.ts similarity index 100% rename from backend/src/models/Tag.js rename to backend/src/models/Tag.ts diff --git a/backend/src/models/UnverifiedEmailAddress.js b/backend/src/models/UnverifiedEmailAddress.ts similarity index 100% rename from backend/src/models/UnverifiedEmailAddress.js rename to backend/src/models/UnverifiedEmailAddress.ts diff --git a/backend/src/models/User.spec.js b/backend/src/models/User.spec.ts similarity index 100% rename from backend/src/models/User.spec.js rename to backend/src/models/User.spec.ts diff --git a/backend/src/models/User.js b/backend/src/models/User.ts similarity index 100% rename from backend/src/models/User.js rename to backend/src/models/User.ts diff --git a/backend/src/models/index.js b/backend/src/models/index.js deleted file mode 100644 index 347c3a029..000000000 --- a/backend/src/models/index.js +++ /dev/null @@ -1,37 +0,0 @@ -// NOTE: We cannot use `fs` here to clean up the code. Cypress breaks on any npm -// module that is not browser-compatible. Node's `fs` module is server-side only -export default { - Image: typeof Cypress !== 'undefined' ? require('./Image.js') : require('./Image.js').default, - Badge: typeof Cypress !== 'undefined' ? require('./Badge.js') : require('./Badge.js').default, - User: typeof Cypress !== 'undefined' ? require('./User.js') : require('./User.js').default, - Group: typeof Cypress !== 'undefined' ? require('./Group.js') : require('./Group.js').default, - EmailAddress: - typeof Cypress !== 'undefined' - ? require('./EmailAddress.js') - : require('./EmailAddress.js').default, - UnverifiedEmailAddress: - typeof Cypress !== 'undefined' - ? require('./UnverifiedEmailAddress.js') - : require('./UnverifiedEmailAddress.js').default, - SocialMedia: - typeof Cypress !== 'undefined' - ? require('./SocialMedia.js') - : require('./SocialMedia.js').default, - Post: typeof Cypress !== 'undefined' ? require('./Post.js') : require('./Post.js').default, - Comment: - typeof Cypress !== 'undefined' ? require('./Comment.js') : require('./Comment.js').default, - Category: - typeof Cypress !== 'undefined' ? require('./Category.js') : require('./Category.js').default, - Tag: typeof Cypress !== 'undefined' ? require('./Tag.js') : require('./Tag.js').default, - Location: - typeof Cypress !== 'undefined' ? require('./Location.js') : require('./Location.js').default, - Donations: - typeof Cypress !== 'undefined' ? require('./Donations.js') : require('./Donations.js').default, - Report: typeof Cypress !== 'undefined' ? require('./Report.js') : require('./Report.js').default, - Migration: - typeof Cypress !== 'undefined' ? require('./Migration.js') : require('./Migration.js').default, - InviteCode: - typeof Cypress !== 'undefined' - ? require('./InviteCode.js') - : require('./InviteCode.js').default, -} diff --git a/backend/src/models/index.ts b/backend/src/models/index.ts new file mode 100644 index 000000000..f7d338684 --- /dev/null +++ b/backend/src/models/index.ts @@ -0,0 +1,29 @@ +// NOTE: We cannot use `fs` here to clean up the code. Cypress breaks on any npm +// module that is not browser-compatible. Node's `fs` module is server-side only +declare let Cypress: any | undefined +export default { + Image: typeof Cypress !== 'undefined' ? require('./Image') : require('./Image').default, + Badge: typeof Cypress !== 'undefined' ? require('./Badge') : require('./Badge').default, + User: typeof Cypress !== 'undefined' ? require('./User') : require('./User').default, + Group: typeof Cypress !== 'undefined' ? require('./Group') : require('./Group').default, + EmailAddress: + typeof Cypress !== 'undefined' ? require('./EmailAddress') : require('./EmailAddress').default, + UnverifiedEmailAddress: + typeof Cypress !== 'undefined' + ? require('./UnverifiedEmailAddress') + : require('./UnverifiedEmailAddress').default, + SocialMedia: + typeof Cypress !== 'undefined' ? require('./SocialMedia') : require('./SocialMedia').default, + Post: typeof Cypress !== 'undefined' ? require('./Post') : require('./Post').default, + Comment: typeof Cypress !== 'undefined' ? require('./Comment') : require('./Comment').default, + Category: typeof Cypress !== 'undefined' ? require('./Category') : require('./Category').default, + Tag: typeof Cypress !== 'undefined' ? require('./Tag') : require('./Tag').default, + Location: typeof Cypress !== 'undefined' ? require('./Location') : require('./Location').default, + Donations: + typeof Cypress !== 'undefined' ? require('./Donations') : require('./Donations').default, + Report: typeof Cypress !== 'undefined' ? require('./Report') : require('./Report').default, + Migration: + typeof Cypress !== 'undefined' ? require('./Migration') : require('./Migration').default, + InviteCode: + typeof Cypress !== 'undefined' ? require('./InviteCode') : require('./InviteCode').default, +} diff --git a/backend/src/schema/index.js b/backend/src/schema/index.ts similarity index 100% rename from backend/src/schema/index.js rename to backend/src/schema/index.ts diff --git a/backend/src/schema/resolvers/Upload.js b/backend/src/schema/resolvers/Upload.ts similarity index 100% rename from backend/src/schema/resolvers/Upload.js rename to backend/src/schema/resolvers/Upload.ts diff --git a/backend/src/schema/resolvers/badges.js b/backend/src/schema/resolvers/badges.ts similarity index 100% rename from backend/src/schema/resolvers/badges.js rename to backend/src/schema/resolvers/badges.ts diff --git a/backend/src/schema/resolvers/comments.spec.js b/backend/src/schema/resolvers/comments.spec.ts similarity index 100% rename from backend/src/schema/resolvers/comments.spec.js rename to backend/src/schema/resolvers/comments.spec.ts diff --git a/backend/src/schema/resolvers/comments.js b/backend/src/schema/resolvers/comments.ts similarity index 98% rename from backend/src/schema/resolvers/comments.js rename to backend/src/schema/resolvers/comments.ts index a3a0c7290..c6f07245c 100644 --- a/backend/src/schema/resolvers/comments.js +++ b/backend/src/schema/resolvers/comments.ts @@ -21,7 +21,7 @@ export default { MATCH (post:Post {id: $postId}) MATCH (author:User {id: $userId}) WITH post, author - CREATE (comment:Comment {params}) + CREATE (comment:Comment $params) SET comment.createdAt = toString(datetime()) SET comment.updatedAt = toString(datetime()) MERGE (post)<-[:COMMENTS]-(comment)<-[:WROTE]-(author) diff --git a/backend/src/schema/resolvers/donations.spec.js b/backend/src/schema/resolvers/donations.spec.ts similarity index 100% rename from backend/src/schema/resolvers/donations.spec.js rename to backend/src/schema/resolvers/donations.spec.ts diff --git a/backend/src/schema/resolvers/donations.js b/backend/src/schema/resolvers/donations.ts similarity index 100% rename from backend/src/schema/resolvers/donations.js rename to backend/src/schema/resolvers/donations.ts diff --git a/backend/src/schema/resolvers/emails.spec.js b/backend/src/schema/resolvers/emails.spec.ts similarity index 100% rename from backend/src/schema/resolvers/emails.spec.js rename to backend/src/schema/resolvers/emails.spec.ts diff --git a/backend/src/schema/resolvers/emails.js b/backend/src/schema/resolvers/emails.ts similarity index 100% rename from backend/src/schema/resolvers/emails.js rename to backend/src/schema/resolvers/emails.ts diff --git a/backend/src/schema/resolvers/embeds.spec.js b/backend/src/schema/resolvers/embeds.spec.ts similarity index 94% rename from backend/src/schema/resolvers/embeds.spec.js rename to backend/src/schema/resolvers/embeds.spec.ts index b22927d1b..8e7a69891 100644 --- a/backend/src/schema/resolvers/embeds.spec.js +++ b/backend/src/schema/resolvers/embeds.spec.ts @@ -6,10 +6,11 @@ import createServer from '../../server' import gql from 'graphql-tag' jest.mock('node-fetch') +const mockedFetch = jest.mocked(fetch) const { Response } = jest.requireActual('node-fetch') afterEach(() => { - fetch.mockRestore() + mockedFetch.mockRestore() }) let variables = {} @@ -80,9 +81,9 @@ describe('Query', () => { describe('given a video link', () => { beforeEach(() => { - fetch + mockedFetch .mockReturnValueOnce(Promise.resolve(new Response(''))) - .mockReturnValueOnce(Promise.resolve(JSON.stringify({}))) + .mockReturnValueOnce(Promise.resolve(new Response(JSON.stringify({})))) variables = { url: 'https://www.w3schools.com/html/mov_bbb.mp4' } }) @@ -112,9 +113,9 @@ describe('Query', () => { describe('given a Facebook link', () => { beforeEach(() => { - fetch + mockedFetch .mockReturnValueOnce(Promise.resolve(new Response(HumanConnectionOrg))) - .mockReturnValueOnce(Promise.resolve('invalid json')) + .mockReturnValueOnce(Promise.resolve(new Response('invalid json'))) variables = { url: 'https://www.facebook.com/HumanConnectionOrg/' } }) @@ -146,9 +147,9 @@ describe('Query', () => { describe('given a Github link', () => { beforeEach(() => { - fetch + mockedFetch .mockReturnValueOnce(Promise.resolve(new Response(pr3934))) - .mockReturnValueOnce(Promise.resolve(JSON.stringify({}))) + .mockReturnValueOnce(Promise.resolve(new Response(JSON.stringify({})))) variables = { url: 'https://github.com/Human-Connection/Human-Connection/pull/960' } }) @@ -180,7 +181,7 @@ Have all the information for the brand in separate config files. Set these defau describe('given a youtube link', () => { beforeEach(() => { - fetch + mockedFetch .mockReturnValueOnce(Promise.resolve(new Response(babyLovesCat))) .mockReturnValueOnce(Promise.resolve(babyLovesCatEmbedResponse)) variables = { url: 'https://www.youtube.com/watch?v=qkdXAtO40Fo&t=18s' } diff --git a/backend/src/schema/resolvers/embeds.js b/backend/src/schema/resolvers/embeds.ts similarity index 93% rename from backend/src/schema/resolvers/embeds.js rename to backend/src/schema/resolvers/embeds.ts index 016352950..a75365ec7 100644 --- a/backend/src/schema/resolvers/embeds.js +++ b/backend/src/schema/resolvers/embeds.ts @@ -1,4 +1,4 @@ -import scrape from './embeds/scraper.js' +import scrape from './embeds/scraper' import { undefinedToNullResolver } from './helpers/Resolver' export default { diff --git a/backend/src/schema/resolvers/embeds/findProvider.spec.js b/backend/src/schema/resolvers/embeds/findProvider.spec.ts similarity index 100% rename from backend/src/schema/resolvers/embeds/findProvider.spec.js rename to backend/src/schema/resolvers/embeds/findProvider.spec.ts diff --git a/backend/src/schema/resolvers/embeds/findProvider.js b/backend/src/schema/resolvers/embeds/findProvider.ts similarity index 100% rename from backend/src/schema/resolvers/embeds/findProvider.js rename to backend/src/schema/resolvers/embeds/findProvider.ts diff --git a/backend/src/schema/resolvers/embeds/scraper.js b/backend/src/schema/resolvers/embeds/scraper.ts similarity index 100% rename from backend/src/schema/resolvers/embeds/scraper.js rename to backend/src/schema/resolvers/embeds/scraper.ts diff --git a/backend/src/schema/resolvers/filter-posts.spec.js b/backend/src/schema/resolvers/filter-posts.spec.ts similarity index 100% rename from backend/src/schema/resolvers/filter-posts.spec.js rename to backend/src/schema/resolvers/filter-posts.spec.ts diff --git a/backend/src/schema/resolvers/follow.spec.js b/backend/src/schema/resolvers/follow.spec.ts similarity index 97% rename from backend/src/schema/resolvers/follow.spec.js rename to backend/src/schema/resolvers/follow.spec.ts index 0d9d524ff..c9d8dc1bf 100644 --- a/backend/src/schema/resolvers/follow.spec.js +++ b/backend/src/schema/resolvers/follow.spec.ts @@ -147,7 +147,7 @@ describe('follow', () => { variables, }) const relation = await neode.cypher( - 'MATCH (user:User {id: {id}})-[relationship:FOLLOWS]->(followed:User) WHERE relationship.createdAt IS NOT NULL RETURN relationship', + 'MATCH (user:User {id: $id})-[relationship:FOLLOWS]->(followed:User) WHERE relationship.createdAt IS NOT NULL RETURN relationship', { id: 'u1' }, ) const relationshipProperties = relation.records.map( diff --git a/backend/src/schema/resolvers/follow.js b/backend/src/schema/resolvers/follow.ts similarity index 97% rename from backend/src/schema/resolvers/follow.js rename to backend/src/schema/resolvers/follow.ts index 80cce8400..6cf4938c7 100644 --- a/backend/src/schema/resolvers/follow.js +++ b/backend/src/schema/resolvers/follow.ts @@ -29,7 +29,7 @@ export default { * It's suggested to use query builder feature (https://github.com/adam-cowley/neode/issues/67) * However, pure cypher query looks cleaner IMO */ - await neode.cypher( + await neode.writeCypher( `MATCH (user:User {id: $currentUser.id})-[relation:FOLLOWS]->(followedUser:User {id: $followedUserId}) DELETE relation RETURN COUNT(relation) > 0 as isFollowed`, diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.ts similarity index 95% rename from backend/src/schema/resolvers/groups.spec.js rename to backend/src/schema/resolvers/groups.spec.ts index 13291383d..315388490 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.ts @@ -270,7 +270,7 @@ describe('in mode', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await mutate({ mutation: createGroupMutation(), variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -339,7 +339,7 @@ describe('in mode', () => { '0123456789', }, }) - expect(errors[0]).toHaveProperty('message', 'Description too short!') + expect(errors![0]).toHaveProperty('message', 'Description too short!') }) }) }) @@ -382,7 +382,7 @@ describe('in mode', () => { mutation: createGroupMutation(), variables: { ...variables, categoryIds: null }, }) - expect(errors[0]).toHaveProperty('message', 'Too view categories!') + expect(errors![0]).toHaveProperty('message', 'Too view categories!') }) }) @@ -392,7 +392,7 @@ describe('in mode', () => { mutation: createGroupMutation(), variables: { ...variables, categoryIds: [] }, }) - expect(errors[0]).toHaveProperty('message', 'Too view categories!') + expect(errors![0]).toHaveProperty('message', 'Too view categories!') }) }) }) @@ -403,7 +403,7 @@ describe('in mode', () => { mutation: createGroupMutation(), variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] }, }) - expect(errors[0]).toHaveProperty('message', 'Too many categories!') + expect(errors![0]).toHaveProperty('message', 'Too many categories!') }) }) }) @@ -424,7 +424,7 @@ describe('in mode', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupQuery(), variables: {} }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -577,7 +577,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(3) + expect(result.data?.Group.length).toBe(3) }) describe('categories', () => { @@ -635,7 +635,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(1) + expect(result.data?.Group.length).toBe(1) }) }) @@ -657,7 +657,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(1) + expect(result.data?.Group.length).toBe(1) }) }) @@ -667,7 +667,7 @@ describe('in mode', () => { query: groupQuery(), variables: { id: 'second-hidden-group' }, }) - expect(result.data.Group.length).toBe(0) + expect(result.data?.Group.length).toBe(0) }) }) @@ -677,7 +677,7 @@ describe('in mode', () => { query: groupQuery(), variables: { id: 'hidden-group' }, }) - expect(result.data.Group.length).toBe(0) + expect(result.data?.Group.length).toBe(0) }) }) }) @@ -701,7 +701,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(1) + expect(result.data?.Group.length).toBe(1) }) }) @@ -723,7 +723,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(1) + expect(result.data?.Group.length).toBe(1) }) }) @@ -733,7 +733,7 @@ describe('in mode', () => { query: groupQuery(), variables: { slug: 'second-investigative-journalism-group' }, }) - expect(result.data.Group.length).toBe(0) + expect(result.data?.Group.length).toBe(0) }) }) @@ -743,7 +743,7 @@ describe('in mode', () => { query: groupQuery(), variables: { slug: 'investigative-journalism-group' }, }) - expect(result.data.Group.length).toBe(0) + expect(result.data?.Group.length).toBe(0) }) }) }) @@ -768,7 +768,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(2) + expect(result.data?.Group.length).toBe(2) }) }) @@ -787,7 +787,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.Group.length).toBe(1) + expect(result.data?.Group.length).toBe(1) }) }) }) @@ -813,7 +813,7 @@ describe('in mode', () => { userId: 'current-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -994,7 +994,7 @@ describe('in mode', () => { userId: 'owner-of-closed-group', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1040,7 +1040,7 @@ describe('in mode', () => { id: 'not-existing-group', } const { errors } = await query({ query: groupMembersQuery(), variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1234,7 +1234,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(3) + expect(result.data?.GroupMembers.length).toBe(3) }) }) @@ -1267,7 +1267,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(3) + expect(result.data?.GroupMembers.length).toBe(3) }) }) @@ -1300,7 +1300,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(3) + expect(result.data?.GroupMembers.length).toBe(3) }) }) }) @@ -1343,7 +1343,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(3) + expect(result.data?.GroupMembers.length).toBe(3) }) }) @@ -1376,7 +1376,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(3) + expect(result.data?.GroupMembers.length).toBe(3) }) }) @@ -1387,7 +1387,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery(), variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1398,7 +1398,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery(), variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1445,7 +1445,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(4) + expect(result.data?.GroupMembers.length).toBe(4) }) }) @@ -1482,7 +1482,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(4) + expect(result.data?.GroupMembers.length).toBe(4) }) }) @@ -1519,7 +1519,7 @@ describe('in mode', () => { }, errors: undefined, }) - expect(result.data.GroupMembers.length).toBe(4) + expect(result.data?.GroupMembers.length).toBe(4) }) }) @@ -1530,7 +1530,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery(), variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1541,7 +1541,7 @@ describe('in mode', () => { it('throws authorization error', async () => { const { errors } = await query({ query: groupMembersQuery(), variables }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1568,7 +1568,7 @@ describe('in mode', () => { roleInGroup: 'pending', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1723,7 +1723,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1749,7 +1749,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1798,7 +1798,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1821,7 +1821,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1844,7 +1844,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1902,7 +1902,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1925,7 +1925,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1942,7 +1942,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -1965,7 +1965,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -1982,7 +1982,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2005,7 +2005,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2022,7 +2022,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2112,7 +2112,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2129,7 +2129,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2152,7 +2152,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2169,7 +2169,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2192,7 +2192,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2209,7 +2209,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2299,7 +2299,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2322,7 +2322,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2345,7 +2345,7 @@ describe('in mode', () => { mutation: changeGroupMemberRoleMutation(), variables, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2409,7 +2409,7 @@ describe('in mode', () => { userId: 'current-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2526,7 +2526,7 @@ describe('in mode', () => { userId: 'owner-member-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2540,7 +2540,7 @@ describe('in mode', () => { userId: 'second-owner-member-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2554,7 +2554,7 @@ describe('in mode', () => { userId: 'none-member-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2568,7 +2568,7 @@ describe('in mode', () => { userId: 'usual-member-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2582,7 +2582,7 @@ describe('in mode', () => { userId: 'admin-member-user', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) @@ -2608,7 +2608,7 @@ describe('in mode', () => { slug: 'my-best-group', }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2861,7 +2861,7 @@ describe('in mode', () => { '0123456789', }, }) - expect(errors[0]).toHaveProperty('message', 'Description too short!') + expect(errors![0]).toHaveProperty('message', 'Description too short!') }) }) }) @@ -2908,7 +2908,7 @@ describe('in mode', () => { categoryIds: [], }, }) - expect(errors[0]).toHaveProperty('message', 'Too view categories!') + expect(errors![0]).toHaveProperty('message', 'Too view categories!') }) }) }) @@ -2922,7 +2922,7 @@ describe('in mode', () => { categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'], }, }) - expect(errors[0]).toHaveProperty('message', 'Too many categories!') + expect(errors![0]).toHaveProperty('message', 'Too many categories!') }) }) }) @@ -2942,7 +2942,7 @@ describe('in mode', () => { categoryIds: ['cat4', 'cat27'], }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) @@ -2960,7 +2960,7 @@ describe('in mode', () => { categoryIds: ['cat4', 'cat27'], }, }) - expect(errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(errors![0]).toHaveProperty('message', 'Not Authorized!') }) }) }) diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.ts similarity index 99% rename from backend/src/schema/resolvers/groups.js rename to backend/src/schema/resolvers/groups.ts index 5ec1700b9..cd1eb8db3 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.ts @@ -3,7 +3,7 @@ import { UserInputError } from 'apollo-server' import CONFIG from '../../config' import { CATEGORIES_MIN, CATEGORIES_MAX } from '../../constants/categories' import { DESCRIPTION_WITHOUT_HTML_LENGTH_MIN } from '../../constants/groups' -import { removeHtmlTags } from '../../middleware/helpers/cleanHtml.js' +import { removeHtmlTags } from '../../middleware/helpers/cleanHtml' import Resolver, { removeUndefinedNullValuesFromObject, convertObjectToCypherMapLiteral, diff --git a/backend/src/schema/resolvers/helpers/Resolver.js b/backend/src/schema/resolvers/helpers/Resolver.ts similarity index 97% rename from backend/src/schema/resolvers/helpers/Resolver.js rename to backend/src/schema/resolvers/helpers/Resolver.ts index 6e8211521..58d1512d7 100644 --- a/backend/src/schema/resolvers/helpers/Resolver.js +++ b/backend/src/schema/resolvers/helpers/Resolver.ts @@ -10,7 +10,7 @@ export const undefinedToNullResolver = (list) => { return resolvers } -export default function Resolver(type, options = {}) { +export default function Resolver(type, options: any = {}) { const { idAttribute = 'id', undefinedToNull = [], @@ -44,7 +44,7 @@ export default function Resolver(type, options = {}) { } } - const booleanResolver = (obj) => { + const booleanResolver = (obj: any[]) => { const resolvers = {} for (const [key, condition] of Object.entries(obj)) { resolvers[key] = async (parent, params, { cypherParams, driver }, resolveInfo) => { diff --git a/backend/src/schema/resolvers/helpers/createPasswordReset.js b/backend/src/schema/resolvers/helpers/createPasswordReset.ts similarity index 100% rename from backend/src/schema/resolvers/helpers/createPasswordReset.js rename to backend/src/schema/resolvers/helpers/createPasswordReset.ts diff --git a/backend/src/schema/resolvers/helpers/databaseLogger.js b/backend/src/schema/resolvers/helpers/databaseLogger.ts similarity index 100% rename from backend/src/schema/resolvers/helpers/databaseLogger.js rename to backend/src/schema/resolvers/helpers/databaseLogger.ts diff --git a/backend/src/schema/resolvers/helpers/events.js b/backend/src/schema/resolvers/helpers/events.ts similarity index 82% rename from backend/src/schema/resolvers/helpers/events.js rename to backend/src/schema/resolvers/helpers/events.ts index 84e64299d..835088d8c 100644 --- a/backend/src/schema/resolvers/helpers/events.js +++ b/backend/src/schema/resolvers/helpers/events.ts @@ -1,29 +1,32 @@ import { UserInputError } from 'apollo-server' export const validateEventParams = (params) => { + let locationName = null if (params.postType && params.postType === 'Event') { const { eventInput } = params validateEventDate(eventInput.eventStart) params.eventStart = eventInput.eventStart + if (eventInput.eventEnd) { validateEventEnd(eventInput.eventStart, eventInput.eventEnd) params.eventEnd = eventInput.eventEnd + } else { + params.eventEnd = null } + if (eventInput.eventLocationName && !eventInput.eventVenue) { throw new UserInputError('Event venue must be present if event location is given!') } params.eventVenue = eventInput.eventVenue - params.eventLocationName = eventInput.eventLocationName + params.eventLocationName = eventInput.eventLocationName && eventInput.eventLocationName.trim() + if (params.eventLocationName) { + locationName = params.eventLocationName + } else { + params.eventLocationName = null + } params.eventIsOnline = !!eventInput.eventIsOnline } delete params.eventInput - let locationName - if (params.eventLocationName) { - locationName = params.eventLocationName - } else { - params.eventLocationName = null - locationName = null - } return locationName } diff --git a/backend/src/schema/resolvers/helpers/existingEmailAddress.js b/backend/src/schema/resolvers/helpers/existingEmailAddress.ts similarity index 100% rename from backend/src/schema/resolvers/helpers/existingEmailAddress.js rename to backend/src/schema/resolvers/helpers/existingEmailAddress.ts diff --git a/backend/src/schema/resolvers/helpers/filterForMutedUsers.js b/backend/src/schema/resolvers/helpers/filterForMutedUsers.ts similarity index 92% rename from backend/src/schema/resolvers/helpers/filterForMutedUsers.js rename to backend/src/schema/resolvers/helpers/filterForMutedUsers.ts index 5094039ee..1d1369e0d 100644 --- a/backend/src/schema/resolvers/helpers/filterForMutedUsers.js +++ b/backend/src/schema/resolvers/helpers/filterForMutedUsers.ts @@ -1,4 +1,4 @@ -import { getMutedUsers } from '../users.js' +import { getMutedUsers } from '../users' import { mergeWith, isArray } from 'lodash' export const filterForMutedUsers = async (params, context) => { diff --git a/backend/src/schema/resolvers/helpers/filterInvisiblePosts.js b/backend/src/schema/resolvers/helpers/filterInvisiblePosts.ts similarity index 100% rename from backend/src/schema/resolvers/helpers/filterInvisiblePosts.js rename to backend/src/schema/resolvers/helpers/filterInvisiblePosts.ts diff --git a/backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.js b/backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.ts similarity index 100% rename from backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.js rename to backend/src/schema/resolvers/helpers/filterPostsOfMyGroups.ts diff --git a/backend/src/schema/resolvers/helpers/generateInviteCode.js b/backend/src/schema/resolvers/helpers/generateInviteCode.ts similarity index 89% rename from backend/src/schema/resolvers/helpers/generateInviteCode.js rename to backend/src/schema/resolvers/helpers/generateInviteCode.ts index 99c752eb0..5a123ff88 100644 --- a/backend/src/schema/resolvers/helpers/generateInviteCode.js +++ b/backend/src/schema/resolvers/helpers/generateInviteCode.ts @@ -4,7 +4,7 @@ export default function generateInviteCode() { // 6 random numbers in [ 0, 35 ] are 36 possible numbers (10 [0-9] + 26 [A-Z]) return Array.from( { length: CONSTANTS_REGISTRATION.INVITE_CODE_LENGTH }, - (n = Math.floor(Math.random() * 36)) => { + (n: number = Math.floor(Math.random() * 36)) => { // n > 9: it is a letter (ASCII 65 is A) -> 10 + 55 = 65 // else: it is a number (ASCII 48 is 0) -> 0 + 48 = 48 return String.fromCharCode(n > 9 ? n + 55 : n + 48) diff --git a/backend/src/schema/resolvers/helpers/generateNonce.js b/backend/src/schema/resolvers/helpers/generateNonce.ts similarity index 85% rename from backend/src/schema/resolvers/helpers/generateNonce.js rename to backend/src/schema/resolvers/helpers/generateNonce.ts index 50aa8489e..f08b3ccd6 100644 --- a/backend/src/schema/resolvers/helpers/generateNonce.js +++ b/backend/src/schema/resolvers/helpers/generateNonce.ts @@ -4,7 +4,7 @@ import CONSTANTS_REGISTRATION from './../../../constants/registration' export default function generateNonce() { return Array.from( { length: CONSTANTS_REGISTRATION.NONCE_LENGTH }, - (n = Math.floor(Math.random() * 10)) => { + (n: number = Math.floor(Math.random() * 10)) => { return String.fromCharCode(n + 48) }, ).join('') diff --git a/backend/src/schema/resolvers/helpers/normalizeEmail.js b/backend/src/schema/resolvers/helpers/normalizeEmail.ts similarity index 100% rename from backend/src/schema/resolvers/helpers/normalizeEmail.js rename to backend/src/schema/resolvers/helpers/normalizeEmail.ts diff --git a/backend/src/schema/resolvers/images.js b/backend/src/schema/resolvers/images.ts similarity index 100% rename from backend/src/schema/resolvers/images.js rename to backend/src/schema/resolvers/images.ts diff --git a/backend/src/schema/resolvers/images/images.spec.js b/backend/src/schema/resolvers/images/images.spec.ts similarity index 99% rename from backend/src/schema/resolvers/images/images.spec.js rename to backend/src/schema/resolvers/images/images.spec.ts index b14c59f28..d46972ce0 100644 --- a/backend/src/schema/resolvers/images/images.spec.js +++ b/backend/src/schema/resolvers/images/images.spec.ts @@ -170,6 +170,7 @@ describe('mergeImage', () => { }) }) + // eslint-disable-next-line jest/no-disabled-tests it.skip('automatically creates different image sizes', async () => { await expect( mergeImage(post, 'HERO_IMAGE', imageInput, { uploadCallback, deleteCallback }), diff --git a/backend/src/schema/resolvers/images/images.js b/backend/src/schema/resolvers/images/images.ts similarity index 99% rename from backend/src/schema/resolvers/images/images.js rename to backend/src/schema/resolvers/images/images.ts index 180c6d090..b99b13a10 100644 --- a/backend/src/schema/resolvers/images/images.js +++ b/backend/src/schema/resolvers/images/images.ts @@ -10,7 +10,7 @@ import CONFIG from '../../../config' // const widths = [34, 160, 320, 640, 1024] const { AWS_ENDPOINT: endpoint, AWS_REGION: region, AWS_BUCKET: Bucket, S3_CONFIGURED } = CONFIG -export async function deleteImage(resource, relationshipType, opts = {}) { +export async function deleteImage(resource, relationshipType, opts: any = {}) { sanitizeRelationshipType(relationshipType) const { transaction, deleteCallback } = opts if (!transaction) return wrapTransaction(deleteImage, [resource, relationshipType], opts) @@ -32,7 +32,7 @@ export async function deleteImage(resource, relationshipType, opts = {}) { return image } -export async function mergeImage(resource, relationshipType, imageInput, opts = {}) { +export async function mergeImage(resource, relationshipType, imageInput, opts: any = {}) { if (typeof imageInput === 'undefined') return if (imageInput === null) return deleteImage(resource, relationshipType, opts) sanitizeRelationshipType(relationshipType) diff --git a/backend/src/schema/resolvers/index.js b/backend/src/schema/resolvers/index.ts similarity index 63% rename from backend/src/schema/resolvers/index.js rename to backend/src/schema/resolvers/index.ts index 3d3a91d68..1aeadbea2 100644 --- a/backend/src/schema/resolvers/index.js +++ b/backend/src/schema/resolvers/index.ts @@ -1,5 +1,6 @@ import path from 'path' import { fileLoader, mergeResolvers } from 'merge-graphql-schemas' -const resolversArray = fileLoader(path.join(__dirname, './!(*.spec).js')) +// the files must be correctly evaluated in built and dev state - therefore accept both js & ts files +const resolversArray = fileLoader(path.join(__dirname, './!(*.spec).(ts|js)')) export default mergeResolvers(resolversArray) diff --git a/backend/src/schema/resolvers/inviteCodes.spec.js b/backend/src/schema/resolvers/inviteCodes.spec.ts similarity index 100% rename from backend/src/schema/resolvers/inviteCodes.spec.js rename to backend/src/schema/resolvers/inviteCodes.spec.ts diff --git a/backend/src/schema/resolvers/inviteCodes.js b/backend/src/schema/resolvers/inviteCodes.ts similarity index 100% rename from backend/src/schema/resolvers/inviteCodes.js rename to backend/src/schema/resolvers/inviteCodes.ts diff --git a/backend/src/schema/resolvers/locations.spec.js b/backend/src/schema/resolvers/locations.spec.ts similarity index 100% rename from backend/src/schema/resolvers/locations.spec.js rename to backend/src/schema/resolvers/locations.spec.ts diff --git a/backend/src/schema/resolvers/locations.js b/backend/src/schema/resolvers/locations.ts similarity index 100% rename from backend/src/schema/resolvers/locations.js rename to backend/src/schema/resolvers/locations.ts diff --git a/backend/src/schema/resolvers/messages.spec.ts b/backend/src/schema/resolvers/messages.spec.ts new file mode 100644 index 000000000..628034be5 --- /dev/null +++ b/backend/src/schema/resolvers/messages.spec.ts @@ -0,0 +1,528 @@ +import { createTestClient } from 'apollo-server-testing' +import Factory, { cleanDatabase } from '../../db/factories' +import { getNeode, getDriver } from '../../db/neo4j' +import { createRoomMutation, roomQuery } from '../../graphql/rooms' +import { createMessageMutation, messageQuery, markMessagesAsSeen } from '../../graphql/messages' +import createServer from '../../server' + +const driver = getDriver() +const neode = getNeode() + +let query +let mutate +let authenticatedUser +let chattingUser, otherChattingUser, notChattingUser + +beforeAll(async () => { + await cleanDatabase() + + const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + cypherParams: { + currentUserId: authenticatedUser ? authenticatedUser.id : null, + }, + } + }, + }) + query = createTestClient(server).query + mutate = createTestClient(server).mutate +}) + +afterAll(async () => { + await cleanDatabase() + driver.close() +}) + +describe('Message', () => { + let roomId: string + + beforeAll(async () => { + ;[chattingUser, otherChattingUser, notChattingUser] = await Promise.all([ + Factory.build('user', { + id: 'chatting-user', + name: 'Chatting User', + }), + Factory.build('user', { + id: 'other-chatting-user', + name: 'Other Chatting User', + }), + Factory.build('user', { + id: 'not-chatting-user', + name: 'Not Chatting User', + }), + ]) + }) + + describe('create message', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + await expect( + mutate({ + mutation: createMessageMutation(), + variables: { + roomId: 'some-id', + content: 'Some bla bla bla', + }, + }), + ).resolves.toMatchObject({ + errors: [{ message: 'Not Authorized!' }], + }) + }) + }) + + describe('authenticated', () => { + beforeAll(async () => { + authenticatedUser = await chattingUser.toJson() + }) + + describe('room does not exist', () => { + it('returns null', async () => { + await expect( + mutate({ + mutation: createMessageMutation(), + variables: { + roomId: 'some-id', + content: 'Some bla bla bla', + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + CreateMessage: null, + }, + }) + }) + }) + + describe('room exists', () => { + beforeAll(async () => { + const room = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'other-chatting-user', + }, + }) + roomId = room.data.CreateRoom.id + }) + + describe('user chats in room', () => { + it('returns the message', async () => { + await expect( + mutate({ + mutation: createMessageMutation(), + variables: { + roomId, + content: 'Some nice message to other chatting user', + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + CreateMessage: { + id: expect.any(String), + content: 'Some nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: false, + seen: false, + }, + }, + }) + }) + + describe('room is updated as well', () => { + it('has last message set', async () => { + const result = await query({ query: roomQuery() }) + await expect(result).toMatchObject({ + errors: undefined, + data: { + Room: [ + expect.objectContaining({ + lastMessageAt: expect.any(String), + unreadCount: 0, + lastMessage: expect.objectContaining({ + _id: result.data.Room[0].lastMessage.id, + id: expect.any(String), + content: 'Some nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: false, + seen: false, + }), + }), + ], + }, + }) + }) + }) + + describe('unread count for other user', () => { + it('has unread count = 1', async () => { + authenticatedUser = await otherChattingUser.toJson() + await expect(query({ query: roomQuery() })).resolves.toMatchObject({ + errors: undefined, + data: { + Room: [ + expect.objectContaining({ + lastMessageAt: expect.any(String), + unreadCount: 1, + lastMessage: expect.objectContaining({ + _id: expect.any(String), + id: expect.any(String), + content: 'Some nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: false, + seen: false, + }), + }), + ], + }, + }) + }) + }) + }) + + describe('user does not chat in room', () => { + beforeAll(async () => { + authenticatedUser = await notChattingUser.toJson() + }) + + it('returns null', async () => { + await expect( + mutate({ + mutation: createMessageMutation(), + variables: { + roomId, + content: 'I have no access to this room!', + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + CreateMessage: null, + }, + }) + }) + }) + }) + }) + }) + + describe('message query', () => { + describe('unauthenticated', () => { + beforeAll(() => { + authenticatedUser = null + }) + + it('throws authorization error', async () => { + await expect( + query({ + query: messageQuery(), + variables: { + roomId: 'some-id', + }, + }), + ).resolves.toMatchObject({ + errors: [{ message: 'Not Authorized!' }], + }) + }) + }) + + describe('authenticated', () => { + beforeAll(async () => { + authenticatedUser = await otherChattingUser.toJson() + }) + + describe('room does not exists', () => { + it('returns null', async () => { + await expect( + query({ + query: messageQuery(), + variables: { + roomId: 'some-id', + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + Message: [], + }, + }) + }) + }) + + describe('room exists with authenticated user chatting', () => { + it('returns the messages', async () => { + const result = await query({ + query: messageQuery(), + variables: { + roomId, + }, + }) + expect(result).toMatchObject({ + errors: undefined, + data: { + Message: [ + { + id: expect.any(String), + _id: result.data.Message[0].id, + indexId: 0, + content: 'Some nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: true, + seen: false, + }, + ], + }, + }) + }) + + describe('more messages', () => { + beforeAll(async () => { + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId, + content: 'A nice response message to chatting user', + }, + }) + authenticatedUser = await chattingUser.toJson() + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId, + content: 'And another nice message to other chatting user', + }, + }) + }) + + it('returns the messages', async () => { + await expect( + query({ + query: messageQuery(), + variables: { + roomId, + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + Message: [ + expect.objectContaining({ + id: expect.any(String), + indexId: 0, + content: 'Some nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: true, + seen: false, + }), + expect.objectContaining({ + id: expect.any(String), + indexId: 1, + content: 'A nice response message to chatting user', + senderId: 'other-chatting-user', + username: 'Other Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: true, + seen: false, + }), + expect.objectContaining({ + id: expect.any(String), + indexId: 2, + content: 'And another nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + saved: true, + distributed: false, + seen: false, + }), + ], + }, + }) + }) + + it('returns the messages paginated', async () => { + await expect( + query({ + query: messageQuery(), + variables: { + roomId, + first: 2, + offset: 0, + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + Message: [ + expect.objectContaining({ + id: expect.any(String), + indexId: 1, + content: 'A nice response message to chatting user', + senderId: 'other-chatting-user', + username: 'Other Chatting User', + avatar: expect.any(String), + date: expect.any(String), + }), + expect.objectContaining({ + id: expect.any(String), + indexId: 2, + content: 'And another nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + }), + ], + }, + }) + + await expect( + query({ + query: messageQuery(), + variables: { + roomId, + first: 2, + offset: 2, + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + Message: [ + expect.objectContaining({ + id: expect.any(String), + indexId: 0, + content: 'Some nice message to other chatting user', + senderId: 'chatting-user', + username: 'Chatting User', + avatar: expect.any(String), + date: expect.any(String), + }), + ], + }, + }) + }) + }) + }) + + describe('room exists, authenticated user not in room', () => { + beforeAll(async () => { + authenticatedUser = await notChattingUser.toJson() + }) + + it('returns null', async () => { + await expect( + query({ + query: messageQuery(), + variables: { + roomId, + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + Message: [], + }, + }) + }) + }) + }) + }) + + describe('marks massges as seen', () => { + describe('unauthenticated', () => { + beforeAll(() => { + authenticatedUser = null + }) + + it('throws authorization error', async () => { + await expect( + mutate({ + mutation: markMessagesAsSeen(), + variables: { + messageIds: ['some-id'], + }, + }), + ).resolves.toMatchObject({ + errors: [{ message: 'Not Authorized!' }], + }) + }) + }) + + describe('authenticated', () => { + const messageIds: string[] = [] + beforeAll(async () => { + authenticatedUser = await otherChattingUser.toJson() + const msgs = await query({ + query: messageQuery(), + variables: { + roomId, + }, + }) + msgs.data.Message.forEach((m) => messageIds.push(m.id)) + }) + + it('returns true', async () => { + await expect( + mutate({ + mutation: markMessagesAsSeen(), + variables: { + messageIds, + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + MarkMessagesAsSeen: true, + }, + }) + }) + + it('has seen prop set to true', async () => { + await expect( + query({ + query: messageQuery(), + variables: { + roomId, + }, + }), + ).resolves.toMatchObject({ + data: { + Message: [ + expect.objectContaining({ seen: true }), + expect.objectContaining({ seen: false }), + expect.objectContaining({ seen: true }), + ], + }, + }) + }) + }) + }) +}) diff --git a/backend/src/schema/resolvers/messages.ts b/backend/src/schema/resolvers/messages.ts new file mode 100644 index 000000000..984d17cc2 --- /dev/null +++ b/backend/src/schema/resolvers/messages.ts @@ -0,0 +1,133 @@ +import { neo4jgraphql } from 'neo4j-graphql-js' +import Resolver from './helpers/Resolver' + +export default { + Query: { + Message: async (object, params, context, resolveInfo) => { + const { roomId } = params + delete params.roomId + if (!params.filter) params.filter = {} + params.filter.room = { + id: roomId, + users_some: { + id: context.user.id, + }, + } + + const resolved = await neo4jgraphql(object, params, context, resolveInfo) + + if (resolved) { + const undistributedMessagesIds = resolved + .filter((msg) => !msg.distributed && msg.senderId !== context.user.id) + .map((msg) => msg.id) + if (undistributedMessagesIds.length > 0) { + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const setDistributedCypher = ` + MATCH (m:Message) WHERE m.id IN $undistributedMessagesIds + SET m.distributed = true + RETURN m { .* } + ` + const setDistributedTxResponse = await transaction.run(setDistributedCypher, { + undistributedMessagesIds, + }) + const messages = await setDistributedTxResponse.records.map((record) => record.get('m')) + return messages + }) + try { + await writeTxResultPromise + } finally { + session.close() + } + // send subscription to author to updated the messages + } + } + return resolved.reverse() + }, + }, + Mutation: { + CreateMessage: async (_parent, params, context, _resolveInfo) => { + const { roomId, content } = params + const { + user: { id: currentUserId }, + } = context + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const createMessageCypher = ` + MATCH (currentUser:User { id: $currentUserId })-[:CHATS_IN]->(room:Room { id: $roomId }) + OPTIONAL MATCH (currentUser)-[:AVATAR_IMAGE]->(image:Image) + OPTIONAL MATCH (m:Message)-[:INSIDE]->(room) + WITH MAX(m.indexId) as maxIndex, room, currentUser, image + CREATE (currentUser)-[:CREATED]->(message:Message { + createdAt: toString(datetime()), + id: apoc.create.uuid(), + indexId: CASE WHEN maxIndex IS NOT NULL THEN maxIndex + 1 ELSE 0 END, + content: $content, + saved: true, + distributed: false, + seen: false + })-[:INSIDE]->(room) + SET room.lastMessageAt = toString(datetime()) + RETURN message { + .*, + senderId: currentUser.id, + username: currentUser.name, + avatar: image.url, + date: message.createdAt + } + ` + const createMessageTxResponse = await transaction.run(createMessageCypher, { + currentUserId, + roomId, + content, + }) + const [message] = await createMessageTxResponse.records.map((record) => + record.get('message'), + ) + return message + }) + try { + const message = await writeTxResultPromise + return message + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, + MarkMessagesAsSeen: async (_parent, params, context, _resolveInfo) => { + const { messageIds } = params + const currentUserId = context.user.id + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const setSeenCypher = ` + MATCH (m:Message)<-[:CREATED]-(user:User) + WHERE m.id IN $messageIds AND NOT user.id = $currentUserId + SET m.seen = true + RETURN m { .* } + ` + const setSeenTxResponse = await transaction.run(setSeenCypher, { + messageIds, + currentUserId, + }) + const messages = await setSeenTxResponse.records.map((record) => record.get('m')) + return messages + }) + try { + await writeTxResultPromise + // send subscription to author to updated the messages + return true + } finally { + session.close() + } + }, + }, + Message: { + ...Resolver('Message', { + hasOne: { + author: '<-[:CREATED]-(related:User)', + room: '-[:INSIDE]->(related:Room)', + }, + }), + }, +} diff --git a/backend/src/schema/resolvers/moderation.spec.js b/backend/src/schema/resolvers/moderation.spec.ts similarity index 100% rename from backend/src/schema/resolvers/moderation.spec.js rename to backend/src/schema/resolvers/moderation.spec.ts diff --git a/backend/src/schema/resolvers/moderation.js b/backend/src/schema/resolvers/moderation.ts similarity index 90% rename from backend/src/schema/resolvers/moderation.js rename to backend/src/schema/resolvers/moderation.ts index c261d187e..a29a411aa 100644 --- a/backend/src/schema/resolvers/moderation.js +++ b/backend/src/schema/resolvers/moderation.ts @@ -12,13 +12,13 @@ export default { MATCH (resource {id: $params.resourceId})<-[:BELONGS_TO]-(report:Report {closed: false}) WHERE resource:User OR resource:Post OR resource:Comment MERGE (report)<-[review:REVIEWED]-(moderator) - ON CREATE SET review.createdAt = $dateTime, review.updatedAt = review.createdAt + ON CREATE SET review.createdAt = $dateTime, review.updatedAt = $dateTime ON MATCH SET review.updatedAt = $dateTime SET review.disable = $params.disable SET report.updatedAt = $dateTime, report.disable = review.disable, report.closed = $params.closed SET resource.disabled = report.disable - WITH review, report, resource {.*, __typename: labels(resource)[0]} AS finalResource + WITH review, report, resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'User']][0]} AS finalResource RETURN review {.*, report: properties(report), resource: properties(finalResource)} ` const reviewWriteTxResultPromise = session.writeTransaction(async (txc) => { diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.ts similarity index 99% rename from backend/src/schema/resolvers/notifications.spec.js rename to backend/src/schema/resolvers/notifications.spec.ts index 9deaea457..60539d77f 100644 --- a/backend/src/schema/resolvers/notifications.spec.js +++ b/backend/src/schema/resolvers/notifications.spec.ts @@ -238,7 +238,7 @@ describe('given some notifications', () => { variables: { ...variables, read: false }, }) await expect(response).toMatchObject(expected) - await expect(response.data.notifications.length).toEqual(2) // double-check + await expect(response.data.notifications).toHaveLength(2) // double-check }) describe('if a resource gets deleted', () => { diff --git a/backend/src/schema/resolvers/notifications.js b/backend/src/schema/resolvers/notifications.ts similarity index 87% rename from backend/src/schema/resolvers/notifications.js rename to backend/src/schema/resolvers/notifications.ts index c3b882146..e427de227 100644 --- a/backend/src/schema/resolvers/notifications.js +++ b/backend/src/schema/resolvers/notifications.ts @@ -51,10 +51,10 @@ export default { OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(relatedUser) WITH user, notification, resource, membership, relatedUser, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: [l IN labels(post) WHERE NOT l = 'Post']} ] AS posts WITH resource, user, notification, authors, posts, relatedUser, membership, resource {.*, - __typename: labels(resource)[0], + __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'Group']][0], author: authors[0], post: posts[0], myRole: membership.role } AS finalResource @@ -90,10 +90,10 @@ export default { SET notification.read = TRUE WITH user, notification, resource, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: [l IN labels(post) WHERE NOT l = 'Post']} ] AS posts OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user) WITH resource, user, notification, authors, posts, membership, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role } AS finalResource + resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'Group']][0], author: authors[0], post: posts[0], myRole: membership.role } AS finalResource RETURN notification {.*, from: finalResource, to: properties(user)} `, { resourceId: args.id, id: currentUser.id }, @@ -120,10 +120,10 @@ export default { SET notification.read = TRUE WITH user, notification, resource, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: [l IN labels(post) WHERE NOT l = 'Post']} ] AS posts OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user) WITH resource, user, notification, authors, posts, membership, - resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role} AS finalResource + resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'Group']][0], author: authors[0], post: posts[0], myRole: membership.role} AS finalResource RETURN notification {.*, from: finalResource, to: properties(user)} `, { id: currentUser.id }, diff --git a/backend/src/schema/resolvers/passwordReset.spec.js b/backend/src/schema/resolvers/passwordReset.spec.ts similarity index 99% rename from backend/src/schema/resolvers/passwordReset.spec.js rename to backend/src/schema/resolvers/passwordReset.spec.ts index fa5f26e58..3d17ff481 100644 --- a/backend/src/schema/resolvers/passwordReset.spec.js +++ b/backend/src/schema/resolvers/passwordReset.spec.ts @@ -119,7 +119,7 @@ describe('passwordReset', () => { }) describe('resetPassword', () => { - const setup = async (options = {}) => { + const setup = async (options: any = {}) => { const { email = 'user@example.org', issuedAt = new Date(), nonce = '12345' } = options await createPasswordReset({ driver, email, issuedAt, nonce }) } diff --git a/backend/src/schema/resolvers/passwordReset.js b/backend/src/schema/resolvers/passwordReset.ts similarity index 100% rename from backend/src/schema/resolvers/passwordReset.js rename to backend/src/schema/resolvers/passwordReset.ts diff --git a/backend/src/schema/resolvers/posts.spec.js b/backend/src/schema/resolvers/posts.spec.ts similarity index 99% rename from backend/src/schema/resolvers/posts.spec.js rename to backend/src/schema/resolvers/posts.spec.ts index 87d09e262..7a549449f 100644 --- a/backend/src/schema/resolvers/posts.spec.js +++ b/backend/src/schema/resolvers/posts.spec.ts @@ -907,6 +907,7 @@ describe('UpdatePost', () => { }) }) + // eslint-disable-next-line jest/no-disabled-tests describe.skip('params.image', () => { describe('is object', () => { beforeEach(() => { diff --git a/backend/src/schema/resolvers/posts.js b/backend/src/schema/resolvers/posts.ts similarity index 97% rename from backend/src/schema/resolvers/posts.js rename to backend/src/schema/resolvers/posts.ts index c7d2eebdb..0bd4507b5 100644 --- a/backend/src/schema/resolvers/posts.js +++ b/backend/src/schema/resolvers/posts.ts @@ -21,12 +21,22 @@ const maintainPinnedPosts = (params) => { return params } +const filterEventDates = (params) => { + if (params.filter?.eventStart_gte) { + const date = params.filter.eventStart_gte + delete params.filter.eventStart_gte + params.filter = { ...params.filter, OR: [{ eventStart_gte: date }, { eventEnd_gte: date }] } + } + return params +} + export default { Query: { Post: async (object, params, context, resolveInfo) => { params = await filterPostsOfMyGroups(params, context) params = await filterInvisiblePosts(params, context) params = await filterForMutedUsers(params, context) + params = filterEventDates(params) params = await maintainPinnedPosts(params) return neo4jgraphql(object, params, context, resolveInfo) }, @@ -136,7 +146,7 @@ export default { MERGE (post)<-[:WROTE]-(author) ${categoriesCypher} ${groupCypher} - RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post") } + RETURN post {.*, postType: [l IN labels(post) WHERE NOT l = 'Post'] } `, { userId: context.user.id, categoryIds, groupId, params }, ) @@ -204,7 +214,7 @@ export default { ` } - updatePostCypher += `RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post")}` + updatePostCypher += `RETURN post {.*, postType: [l IN labels(post) WHERE NOT l = 'Post']}` const updatePostVariables = { categoryIds, params } try { const writeTxResultPromise = session.writeTransaction(async (transaction) => { diff --git a/backend/src/schema/resolvers/postsInGroups.spec.js b/backend/src/schema/resolvers/postsInGroups.spec.ts similarity index 100% rename from backend/src/schema/resolvers/postsInGroups.spec.js rename to backend/src/schema/resolvers/postsInGroups.spec.ts diff --git a/backend/src/schema/resolvers/registration.spec.js b/backend/src/schema/resolvers/registration.spec.ts similarity index 99% rename from backend/src/schema/resolvers/registration.spec.js rename to backend/src/schema/resolvers/registration.spec.ts index bfc6a5fa6..54e7f1ba7 100644 --- a/backend/src/schema/resolvers/registration.spec.js +++ b/backend/src/schema/resolvers/registration.spec.ts @@ -251,7 +251,7 @@ describe('SignupVerification', () => { it('connects User with EmailAddress', async () => { const cypher = ` - MATCH(email:EmailAddress)-[:BELONGS_TO]->(u:User {name: {name}}) + MATCH(email:EmailAddress)-[:BELONGS_TO]->(u:User {name: $name}) RETURN email ` await mutate({ mutation, variables }) @@ -281,7 +281,7 @@ describe('SignupVerification', () => { it('marks the EmailAddress as primary', async () => { const cypher = ` - MATCH(email:EmailAddress)<-[:PRIMARY_EMAIL]-(u:User {name: {name}}) + MATCH(email:EmailAddress)<-[:PRIMARY_EMAIL]-(u:User {name: $name}) RETURN email ` await mutate({ mutation, variables }) diff --git a/backend/src/schema/resolvers/registration.js b/backend/src/schema/resolvers/registration.ts similarity index 98% rename from backend/src/schema/resolvers/registration.js rename to backend/src/schema/resolvers/registration.ts index c988acfb2..8d5aac346 100644 --- a/backend/src/schema/resolvers/registration.js +++ b/backend/src/schema/resolvers/registration.ts @@ -28,7 +28,7 @@ export default { }, SignupVerification: async (_parent, args, context) => { const { termsAndConditionsAgreedVersion } = args - const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g) + const regEx = /^[0-9]+\.[0-9]+\.[0-9]+$/g if (!regEx.test(termsAndConditionsAgreedVersion)) { throw new UserInputError('Invalid version format!') } diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.ts similarity index 99% rename from backend/src/schema/resolvers/reports.spec.js rename to backend/src/schema/resolvers/reports.spec.ts index 96ef07d03..bc47778c1 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.ts @@ -728,7 +728,7 @@ describe('file a report on a resource', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { authenticatedUser = null - expect(query({ query: reportsQuery })).resolves.toMatchObject({ + await expect(query({ query: reportsQuery })).resolves.toMatchObject({ data: { reports: null }, errors: [{ message: 'Not Authorized!' }], }) @@ -738,7 +738,7 @@ describe('file a report on a resource', () => { describe('authenticated', () => { it('role "user" gets no reports', async () => { authenticatedUser = await currentUser.toJson() - expect(query({ query: reportsQuery })).resolves.toMatchObject({ + await expect(query({ query: reportsQuery })).resolves.toMatchObject({ data: { reports: null }, errors: [{ message: 'Not Authorized!' }], }) diff --git a/backend/src/schema/resolvers/reports.js b/backend/src/schema/resolvers/reports.ts similarity index 92% rename from backend/src/schema/resolvers/reports.js rename to backend/src/schema/resolvers/reports.ts index 431bbaefc..f7945e060 100644 --- a/backend/src/schema/resolvers/reports.js +++ b/backend/src/schema/resolvers/reports.ts @@ -13,11 +13,11 @@ export default { MATCH (resource {id: $resourceId}) WHERE resource:User OR resource:Post OR resource:Comment MERGE (resource)<-[:BELONGS_TO]-(report:Report {closed: false}) - ON CREATE SET report.id = randomUUID(), report.createdAt = $createdAt, report.updatedAt = report.createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = resource.disabled, report.closed = false + ON CREATE SET report.id = randomUUID(), report.createdAt = $createdAt, report.updatedAt = $createdAt, report.rule = 'latestReviewUpdatedAtRules', report.disable = resource.disabled, report.closed = false WITH submitter, resource, report CREATE (report)<-[filed:FILED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter) - WITH filed, report, resource {.*, __typename: labels(resource)[0]} AS finalResource + WITH filed, report, resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'User']][0]} AS finalResource RETURN filed {.*, reportId: report.id, resource: properties(finalResource)} AS filedReport `, { @@ -92,8 +92,8 @@ export default { [(submitter:User)-[filed:FILED]->(report) | filed {.*, submitter: properties(submitter)} ] as filed, [(moderator:User)-[reviewed:REVIEWED]->(report) | reviewed {.*, moderator: properties(moderator)} ] as reviewed, [(resource)<-[:WROTE]-(author:User) | author {.*} ] as optionalAuthors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] as optionalCommentedPosts, - resource {.*, __typename: labels(resource)[0] } as resourceWithType + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: [l IN labels(post) WHERE NOT l = 'Post']} ] as optionalCommentedPosts, + resource {.*, __typename: [l IN labels(resource) WHERE l IN ['Post', 'Comment', 'User']][0] } as resourceWithType WITH report, optionalAuthors, optionalCommentedPosts, reviewed, filed, resourceWithType {.*, post: optionalCommentedPosts[0], author: optionalAuthors[0] } as finalResource RETURN report {.*, resource: finalResource, filed: filed, reviewed: reviewed } diff --git a/backend/src/schema/resolvers/rewards.spec.js b/backend/src/schema/resolvers/rewards.spec.ts similarity index 100% rename from backend/src/schema/resolvers/rewards.spec.js rename to backend/src/schema/resolvers/rewards.spec.ts diff --git a/backend/src/schema/resolvers/rewards.js b/backend/src/schema/resolvers/rewards.ts similarity index 100% rename from backend/src/schema/resolvers/rewards.js rename to backend/src/schema/resolvers/rewards.ts diff --git a/backend/src/schema/resolvers/roles.js b/backend/src/schema/resolvers/roles.ts similarity index 100% rename from backend/src/schema/resolvers/roles.js rename to backend/src/schema/resolvers/roles.ts diff --git a/backend/src/schema/resolvers/rooms.spec.ts b/backend/src/schema/resolvers/rooms.spec.ts new file mode 100644 index 000000000..ee291a6c9 --- /dev/null +++ b/backend/src/schema/resolvers/rooms.spec.ts @@ -0,0 +1,604 @@ +import { createTestClient } from 'apollo-server-testing' +import Factory, { cleanDatabase } from '../../db/factories' +import { getNeode, getDriver } from '../../db/neo4j' +import { createRoomMutation, roomQuery, unreadRoomsQuery } from '../../graphql/rooms' +import { createMessageMutation } from '../../graphql/messages' +import createServer from '../../server' + +const driver = getDriver() +const neode = getNeode() + +let query +let mutate +let authenticatedUser +let chattingUser, otherChattingUser, notChattingUser + +beforeAll(async () => { + await cleanDatabase() + + const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + cypherParams: { + currentUserId: authenticatedUser ? authenticatedUser.id : null, + }, + } + }, + }) + query = createTestClient(server).query + mutate = createTestClient(server).mutate +}) + +afterAll(async () => { + await cleanDatabase() + driver.close() +}) + +describe('Room', () => { + let roomId: string + + beforeAll(async () => { + ;[chattingUser, otherChattingUser, notChattingUser] = await Promise.all([ + Factory.build('user', { + id: 'chatting-user', + name: 'Chatting User', + }), + Factory.build('user', { + id: 'other-chatting-user', + name: 'Other Chatting User', + }), + Factory.build('user', { + id: 'not-chatting-user', + name: 'Not Chatting User', + }), + Factory.build('user', { + id: 'second-chatting-user', + name: 'Second Chatting User', + }), + Factory.build('user', { + id: 'third-chatting-user', + name: 'Third Chatting User', + }), + ]) + }) + + describe('create room', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + await expect( + mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'some-id', + }, + }), + ).resolves.toMatchObject({ + errors: [{ message: 'Not Authorized!' }], + }) + }) + }) + + describe('authenticated', () => { + beforeAll(async () => { + authenticatedUser = await chattingUser.toJson() + }) + + describe('user id does not exist', () => { + it('returns null', async () => { + await expect( + mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'not-existing-user', + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + CreateRoom: null, + }, + }) + }) + }) + + describe('user id is self', () => { + it('throws error', async () => { + await expect( + mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'chatting-user', + }, + }), + ).resolves.toMatchObject({ + errors: [{ message: 'Cannot create a room with self' }], + }) + }) + }) + + describe('user id exists', () => { + it('returns the id of the room', async () => { + const result = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'other-chatting-user', + }, + }) + roomId = result.data.CreateRoom.id + expect(result).toMatchObject({ + errors: undefined, + data: { + CreateRoom: { + id: expect.any(String), + roomId: result.data.CreateRoom.id, + roomName: 'Other Chatting User', + unreadCount: 0, + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'other-chatting-user', + id: 'other-chatting-user', + name: 'Other Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + }, + }) + }) + }) + + describe('create room with same user id', () => { + it('returns the id of the room', async () => { + await expect( + mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'other-chatting-user', + }, + }), + ).resolves.toMatchObject({ + errors: undefined, + data: { + CreateRoom: { + id: roomId, + }, + }, + }) + }) + }) + }) + }) + + describe('query room', () => { + describe('unauthenticated', () => { + beforeAll(() => { + authenticatedUser = null + }) + + it('throws authorization error', async () => { + await expect(query({ query: roomQuery() })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorized!' }], + }) + }) + }) + + describe('authenticated', () => { + describe('as creator of room', () => { + beforeAll(async () => { + authenticatedUser = await chattingUser.toJson() + }) + + it('returns the room', async () => { + const result = await query({ query: roomQuery() }) + expect(result).toMatchObject({ + errors: undefined, + data: { + Room: [ + { + id: expect.any(String), + roomId: result.data.Room[0].id, + roomName: 'Other Chatting User', + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'other-chatting-user', + id: 'other-chatting-user', + name: 'Other Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + ], + }, + }) + }) + }) + + describe('as chatter of room', () => { + beforeAll(async () => { + authenticatedUser = await otherChattingUser.toJson() + }) + + it('returns the room', async () => { + const result = await query({ query: roomQuery() }) + expect(result).toMatchObject({ + errors: undefined, + data: { + Room: [ + { + id: expect.any(String), + roomId: result.data.Room[0].id, + roomName: 'Chatting User', + unreadCount: 0, + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'other-chatting-user', + id: 'other-chatting-user', + name: 'Other Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + ], + }, + }) + }) + }) + + describe('as not chatter of room', () => { + beforeAll(async () => { + authenticatedUser = await notChattingUser.toJson() + }) + + it('returns no rooms', async () => { + await expect(query({ query: roomQuery() })).resolves.toMatchObject({ + errors: undefined, + data: { + Room: [], + }, + }) + }) + }) + }) + }) + + describe('unread rooms query', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + authenticatedUser = null + await expect( + query({ + query: unreadRoomsQuery(), + }), + ).resolves.toMatchObject({ + errors: [{ message: 'Not Authorized!' }], + }) + }) + }) + + describe('authenticated', () => { + let otherRoomId: string + + beforeAll(async () => { + authenticatedUser = await chattingUser.toJson() + const result = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'not-chatting-user', + }, + }) + otherRoomId = result.data.CreateRoom.roomId + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: otherRoomId, + content: 'Message to not chatting user', + }, + }) + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId, + content: '1st message to other chatting user', + }, + }) + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId, + content: '2nd message to other chatting user', + }, + }) + authenticatedUser = await otherChattingUser.toJson() + const result2 = await mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'not-chatting-user', + }, + }) + otherRoomId = result2.data.CreateRoom.roomId + await mutate({ + mutation: createMessageMutation(), + variables: { + roomId: otherRoomId, + content: 'Other message to not chatting user', + }, + }) + }) + + describe('as chatting user', () => { + it('has 0 unread rooms', async () => { + authenticatedUser = await chattingUser.toJson() + await expect( + query({ + query: unreadRoomsQuery(), + }), + ).resolves.toMatchObject({ + data: { + UnreadRooms: 0, + }, + }) + }) + }) + + describe('as other chatting user', () => { + it('has 1 unread rooms', async () => { + authenticatedUser = await otherChattingUser.toJson() + await expect( + query({ + query: unreadRoomsQuery(), + }), + ).resolves.toMatchObject({ + data: { + UnreadRooms: 1, + }, + }) + }) + }) + + describe('as not chatting user', () => { + it('has 2 unread rooms', async () => { + authenticatedUser = await notChattingUser.toJson() + await expect( + query({ + query: unreadRoomsQuery(), + }), + ).resolves.toMatchObject({ + data: { + UnreadRooms: 2, + }, + }) + }) + }) + }) + }) + + describe('query several rooms', () => { + beforeAll(async () => { + authenticatedUser = await chattingUser.toJson() + await mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'second-chatting-user', + }, + }) + await mutate({ + mutation: createRoomMutation(), + variables: { + userId: 'third-chatting-user', + }, + }) + }) + + it('returns the rooms paginated', async () => { + expect(await query({ query: roomQuery(), variables: { first: 3, offset: 0 } })).toMatchObject( + { + errors: undefined, + data: { + Room: [ + { + id: expect.any(String), + roomId: expect.any(String), + roomName: 'Third Chatting User', + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'third-chatting-user', + id: 'third-chatting-user', + name: 'Third Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + { + id: expect.any(String), + roomId: expect.any(String), + roomName: 'Second Chatting User', + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'second-chatting-user', + id: 'second-chatting-user', + name: 'Second Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + { + id: expect.any(String), + roomId: expect.any(String), + roomName: 'Not Chatting User', + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'not-chatting-user', + id: 'not-chatting-user', + name: 'Not Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + ], + }, + }, + ) + expect(await query({ query: roomQuery(), variables: { first: 3, offset: 3 } })).toMatchObject( + { + errors: undefined, + data: { + Room: [ + { + id: expect.any(String), + roomId: expect.any(String), + roomName: 'Other Chatting User', + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'other-chatting-user', + id: 'other-chatting-user', + name: 'Other Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + ], + }, + }, + ) + }) + }) + + describe('query single room', () => { + let result: any = null + beforeAll(async () => { + authenticatedUser = await chattingUser.toJson() + result = await query({ query: roomQuery() }) + }) + describe('as chatter of room', () => { + it('returns the room', async () => { + expect( + await query({ + query: roomQuery(), + variables: { first: 2, offset: 0, id: result.data.Room[0].id }, + }), + ).toMatchObject({ + errors: undefined, + data: { + Room: [ + { + id: expect.any(String), + roomId: expect.any(String), + roomName: 'Third Chatting User', + users: expect.arrayContaining([ + { + _id: 'chatting-user', + id: 'chatting-user', + name: 'Chatting User', + avatar: { + url: expect.any(String), + }, + }, + { + _id: 'third-chatting-user', + id: 'third-chatting-user', + name: 'Third Chatting User', + avatar: { + url: expect.any(String), + }, + }, + ]), + }, + ], + }, + }) + }) + describe('as not chatter of room', () => { + beforeAll(async () => { + authenticatedUser = await notChattingUser.toJson() + }) + it('returns no room', async () => { + authenticatedUser = await notChattingUser.toJson() + expect( + await query({ + query: roomQuery(), + variables: { first: 2, offset: 0, id: result.data.Room[0].id }, + }), + ).toMatchObject({ + errors: undefined, + data: { + Room: [], + }, + }) + }) + }) + }) + }) +}) diff --git a/backend/src/schema/resolvers/rooms.ts b/backend/src/schema/resolvers/rooms.ts new file mode 100644 index 000000000..8460977f1 --- /dev/null +++ b/backend/src/schema/resolvers/rooms.ts @@ -0,0 +1,93 @@ +import { neo4jgraphql } from 'neo4j-graphql-js' +import Resolver from './helpers/Resolver' + +export default { + Query: { + Room: async (object, params, context, resolveInfo) => { + if (!params.filter) params.filter = {} + params.filter.users_some = { + id: context.user.id, + } + return neo4jgraphql(object, params, context, resolveInfo) + }, + UnreadRooms: async (object, params, context, resolveInfo) => { + const { + user: { id: currentUserId }, + } = context + const session = context.driver.session() + const readTxResultPromise = session.readTransaction(async (transaction) => { + const unreadRoomsCypher = ` + MATCH (:User { id: $currentUserId })-[:CHATS_IN]->(room:Room)<-[:INSIDE]-(message:Message)<-[:CREATED]-(sender:User) + WHERE NOT sender.id = $currentUserId AND NOT message.seen + RETURN toString(COUNT(DISTINCT room)) AS count + ` + const unreadRoomsTxResponse = await transaction.run(unreadRoomsCypher, { currentUserId }) + return unreadRoomsTxResponse.records.map((record) => record.get('count'))[0] + }) + try { + const count = await readTxResultPromise + return count + } finally { + session.close() + } + }, + }, + Mutation: { + CreateRoom: async (_parent, params, context, _resolveInfo) => { + const { userId } = params + const { + user: { id: currentUserId }, + } = context + if (userId === currentUserId) { + throw new Error('Cannot create a room with self') + } + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const createRoomCypher = ` + MATCH (currentUser:User { id: $currentUserId }) + MATCH (user:User { id: $userId }) + MERGE (currentUser)-[:CHATS_IN]->(room:Room)<-[:CHATS_IN]-(user) + ON CREATE SET + room.createdAt = toString(datetime()), + room.id = apoc.create.uuid() + WITH room, user, currentUser + OPTIONAL MATCH (room)<-[:INSIDE]-(message:Message)<-[:CREATED]-(sender:User) + WHERE NOT sender.id = $currentUserId AND NOT message.seen + WITH room, user, currentUser, message, + user.name AS roomName + RETURN room { + .*, + users: [properties(currentUser), properties(user)], + roomName: roomName, + unreadCount: toString(COUNT(DISTINCT message)) + } + ` + const createRommTxResponse = await transaction.run(createRoomCypher, { + userId, + currentUserId, + }) + const [room] = await createRommTxResponse.records.map((record) => record.get('room')) + return room + }) + try { + const room = await writeTxResultPromise + if (room) { + room.roomId = room.id + } + return room + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, + }, + Room: { + ...Resolver('Room', { + undefinedToNull: ['lastMessageAt'], + hasMany: { + users: '<-[:CHATS_IN]-(related:User)', + }, + }), + }, +} diff --git a/backend/src/schema/resolvers/searches.spec.js b/backend/src/schema/resolvers/searches.spec.ts similarity index 100% rename from backend/src/schema/resolvers/searches.spec.js rename to backend/src/schema/resolvers/searches.spec.ts diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.ts similarity index 93% rename from backend/src/schema/resolvers/searches.js rename to backend/src/schema/resolvers/searches.ts index a67abe90d..fba74ecc7 100644 --- a/backend/src/schema/resolvers/searches.js +++ b/backend/src/schema/resolvers/searches.ts @@ -12,7 +12,7 @@ const cypherTemplate = (setup) => ` RETURN ${setup.returnClause} AS result - SKIP $skip + SKIP toInteger($skip) ${setup.limit} ` @@ -38,14 +38,14 @@ const searchPostsSetup = { [(resource)<-[:SHOUTED]-(user:User) | user] AS shouter`, returnClause: `resource { .*, - __typename: labels(resource)[0], + __typename: 'Post', author: properties(author), commentsCount: toString(size(comments)), shoutedCount: toString(size(shouter)), clickedCount: toString(resource.clickedCount), viewedTeaserCount: toString(resource.viewedTeaserCount) }`, - limit: 'LIMIT $limit', + limit: 'LIMIT toInteger($limit)', } const searchUsersSetup = { @@ -53,8 +53,8 @@ const searchUsersSetup = { match: 'MATCH (resource:User)', whereClause: simpleWhereClause, withClause: '', - returnClause: 'resource {.*, __typename: labels(resource)[0]}', - limit: 'LIMIT $limit', + returnClause: `resource {.*, __typename: 'User'}`, + limit: 'LIMIT toInteger($limit)', } const searchHashtagsSetup = { @@ -62,8 +62,8 @@ const searchHashtagsSetup = { match: 'MATCH (resource:Tag)', whereClause: simpleWhereClause, withClause: '', - returnClause: 'resource {.*, __typename: labels(resource)[0]}', - limit: 'LIMIT $limit', + returnClause: `resource {.*, __typename: 'Tag'}`, + limit: 'LIMIT toInteger($limit)', } const searchGroupsSetup = { @@ -77,8 +77,8 @@ const searchGroupsSetup = { AND (resource.groupType IN ['public', 'closed'] OR membership.role IN ['usual', 'admin', 'owner'])`, withClause: 'WITH resource, membership', - returnClause: 'resource { .*, myRole: membership.role, __typename: labels(resource)[0] }', - limit: 'LIMIT $limit', + returnClause: `resource { .*, myRole: membership.role, __typename: 'Group' }`, + limit: 'LIMIT toInteger($limit)', } const countSetup = { @@ -244,7 +244,7 @@ export default { ] params.limit = 15 - const type = multiSearchMap.find((obj) => obj.symbol === searchType) + const type: any = multiSearchMap.find((obj) => obj.symbol === searchType) return getSearchResults(context, type.setup, params) }, }, diff --git a/backend/src/schema/resolvers/searches/queryString.spec.js b/backend/src/schema/resolvers/searches/queryString.spec.ts similarity index 100% rename from backend/src/schema/resolvers/searches/queryString.spec.js rename to backend/src/schema/resolvers/searches/queryString.spec.ts diff --git a/backend/src/schema/resolvers/searches/queryString.js b/backend/src/schema/resolvers/searches/queryString.ts similarity index 100% rename from backend/src/schema/resolvers/searches/queryString.js rename to backend/src/schema/resolvers/searches/queryString.ts diff --git a/backend/src/schema/resolvers/shout.spec.js b/backend/src/schema/resolvers/shout.spec.ts similarity index 100% rename from backend/src/schema/resolvers/shout.spec.js rename to backend/src/schema/resolvers/shout.spec.ts diff --git a/backend/src/schema/resolvers/shout.js b/backend/src/schema/resolvers/shout.ts similarity index 100% rename from backend/src/schema/resolvers/shout.js rename to backend/src/schema/resolvers/shout.ts diff --git a/backend/src/schema/resolvers/socialMedia.spec.js b/backend/src/schema/resolvers/socialMedia.spec.ts similarity index 100% rename from backend/src/schema/resolvers/socialMedia.spec.js rename to backend/src/schema/resolvers/socialMedia.spec.ts diff --git a/backend/src/schema/resolvers/socialMedia.js b/backend/src/schema/resolvers/socialMedia.ts similarity index 100% rename from backend/src/schema/resolvers/socialMedia.js rename to backend/src/schema/resolvers/socialMedia.ts diff --git a/backend/src/schema/resolvers/statistics.spec.js b/backend/src/schema/resolvers/statistics.spec.ts similarity index 100% rename from backend/src/schema/resolvers/statistics.spec.js rename to backend/src/schema/resolvers/statistics.spec.ts diff --git a/backend/src/schema/resolvers/statistics.js b/backend/src/schema/resolvers/statistics.ts similarity index 97% rename from backend/src/schema/resolvers/statistics.js rename to backend/src/schema/resolvers/statistics.ts index d9b7c153e..b454ce8f4 100644 --- a/backend/src/schema/resolvers/statistics.js +++ b/backend/src/schema/resolvers/statistics.ts @@ -4,7 +4,7 @@ export default { Query: { statistics: async (_parent, _args, { driver }) => { const session = driver.session() - const counts = {} + const counts: any = {} try { const mapping = { countUsers: 'User', diff --git a/backend/src/schema/resolvers/transactions/inviteCodes.js b/backend/src/schema/resolvers/transactions/inviteCodes.ts similarity index 100% rename from backend/src/schema/resolvers/transactions/inviteCodes.js rename to backend/src/schema/resolvers/transactions/inviteCodes.ts diff --git a/backend/src/schema/resolvers/userData.spec.js b/backend/src/schema/resolvers/userData.spec.ts similarity index 100% rename from backend/src/schema/resolvers/userData.spec.js rename to backend/src/schema/resolvers/userData.spec.ts diff --git a/backend/src/schema/resolvers/userData.js b/backend/src/schema/resolvers/userData.ts similarity index 100% rename from backend/src/schema/resolvers/userData.js rename to backend/src/schema/resolvers/userData.ts diff --git a/backend/src/schema/resolvers/user_management.spec.js b/backend/src/schema/resolvers/user_management.spec.ts similarity index 100% rename from backend/src/schema/resolvers/user_management.spec.js rename to backend/src/schema/resolvers/user_management.spec.ts diff --git a/backend/src/schema/resolvers/user_management.js b/backend/src/schema/resolvers/user_management.ts similarity index 100% rename from backend/src/schema/resolvers/user_management.js rename to backend/src/schema/resolvers/user_management.ts diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.ts similarity index 99% rename from backend/src/schema/resolvers/users.spec.js rename to backend/src/schema/resolvers/users.spec.ts index f256c6363..bc976fb24 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.ts @@ -590,7 +590,7 @@ describe('save category settings', () => { beforeEach(async () => { await Promise.all( categories.map(({ icon, name }, index) => { - Factory.build('category', { + return Factory.build('category', { id: `cat${index + 1}`, slug: name, name, diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.ts similarity index 98% rename from backend/src/schema/resolvers/users.js rename to backend/src/schema/resolvers/users.ts index 1ce3b986f..6f79a4ea9 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.ts @@ -81,7 +81,7 @@ export default { muteUser: async (_parent, params, context, _resolveInfo) => { const { user: currentUser } = context if (currentUser.id === params.id) return null - await neode.cypher( + await neode.writeCypher( ` MATCH(u:User {id: $currentUser.id})-[previousRelationship:FOLLOWS]->(b:User {id: $params.id}) DELETE previousRelationship @@ -98,7 +98,7 @@ export default { unmuteUser: async (_parent, params, context, _resolveInfo) => { const { user: currentUser } = context if (currentUser.id === params.id) return null - await neode.cypher( + await neode.writeCypher( ` MATCH(u:User {id: $currentUser.id})-[previousRelationship:MUTED]->(b:User {id: $params.id}) DELETE previousRelationship @@ -144,7 +144,7 @@ export default { params.locationName = params.locationName === '' ? null : params.locationName const { termsAndConditionsAgreedVersion } = params if (termsAndConditionsAgreedVersion) { - const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g) + const regEx = /^[0-9]+\.[0-9]+\.[0-9]+$/g if (!regEx.test(termsAndConditionsAgreedVersion)) { throw new ForbiddenError('Invalid version format!') } @@ -319,7 +319,7 @@ export default { email: async (parent, params, context, resolveInfo) => { if (typeof parent.email !== 'undefined') return parent.email const { id } = parent - const statement = `MATCH(u:User {id: {id}})-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e` + const statement = `MATCH(u:User {id: $id})-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e` const result = await neode.cypher(statement, { id }) const [{ email }] = result.records.map((r) => r.get('e').properties) return email diff --git a/backend/src/schema/resolvers/users/location.spec.js b/backend/src/schema/resolvers/users/location.spec.ts similarity index 100% rename from backend/src/schema/resolvers/users/location.spec.js rename to backend/src/schema/resolvers/users/location.spec.ts diff --git a/backend/src/schema/resolvers/users/location.js b/backend/src/schema/resolvers/users/location.ts similarity index 98% rename from backend/src/schema/resolvers/users/location.js rename to backend/src/schema/resolvers/users/location.ts index 54d73560b..0c3f55595 100644 --- a/backend/src/schema/resolvers/users/location.js +++ b/backend/src/schema/resolvers/users/location.ts @@ -72,7 +72,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s let locationId if (locationName !== null) { - const res = await fetch( + const res: any = await fetch( `https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent( locationName, )}.json?access_token=${ @@ -155,7 +155,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s } export const queryLocations = async ({ place, lang }) => { - const res = await fetch( + const res: any = await fetch( `https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${CONFIG.MAPBOX_TOKEN}&types=region,place,country&language=${lang}`, ) // Return empty array if no location found or error occurred diff --git a/backend/src/schema/resolvers/users/mutedUsers.spec.js b/backend/src/schema/resolvers/users/mutedUsers.spec.ts similarity index 99% rename from backend/src/schema/resolvers/users/mutedUsers.spec.js rename to backend/src/schema/resolvers/users/mutedUsers.spec.ts index 20e37f627..762893af0 100644 --- a/backend/src/schema/resolvers/users/mutedUsers.spec.js +++ b/backend/src/schema/resolvers/users/mutedUsers.spec.ts @@ -59,7 +59,7 @@ describe('mutedUsers', () => { it('throws permission error', async () => { const { query } = createTestClient(server) const result = await query({ query: mutedUserQuery }) - expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!') + expect(result.errors![0]).toHaveProperty('message', 'Not Authorized!') }) describe('authenticated and given a muted user', () => { diff --git a/backend/src/schema/resolvers/viewedTeaserCount.spec.js b/backend/src/schema/resolvers/viewedTeaserCount.spec.ts similarity index 100% rename from backend/src/schema/resolvers/viewedTeaserCount.spec.js rename to backend/src/schema/resolvers/viewedTeaserCount.spec.ts diff --git a/backend/src/schema/types/index.js b/backend/src/schema/types/index.ts similarity index 100% rename from backend/src/schema/types/index.js rename to backend/src/schema/types/index.ts diff --git a/backend/src/schema/types/type/Location.gql b/backend/src/schema/types/type/Location.gql index fad24cc26..9cb5c970a 100644 --- a/backend/src/schema/types/type/Location.gql +++ b/backend/src/schema/types/type/Location.gql @@ -25,4 +25,3 @@ type LocationMapBox { type Query { queryLocations(place: String!, lang: String!): [LocationMapBox]! } - diff --git a/backend/src/schema/types/type/Message.gql b/backend/src/schema/types/type/Message.gql new file mode 100644 index 000000000..764181dd9 --- /dev/null +++ b/backend/src/schema/types/type/Message.gql @@ -0,0 +1,46 @@ +# input _MessageFilter { +# room: _RoomFilter +# } + +enum _MessageOrdering { + indexId_desc +} + +type Message { + id: ID! + indexId: Int! + createdAt: String + updatedAt: String + + content: String! + + author: User! @relation(name: "CREATED", direction: "IN") + room: Room! @relation(name: "INSIDE", direction: "OUT") + + senderId: String! @cypher(statement: "MATCH (this)<-[:CREATED]-(user:User) RETURN user.id") + username: String! @cypher(statement: "MATCH (this)<-[:CREATED]-(user:User) RETURN user.name") + avatar: String @cypher(statement: "MATCH (this)<-[:CREATED]-(:User)-[:AVATAR_IMAGE]->(image:Image) RETURN image.url") + date: String! @cypher(statement: "RETURN this.createdAt") + + saved: Boolean + distributed: Boolean + seen: Boolean +} + +type Mutation { + CreateMessage( + roomId: ID! + content: String! + ): Message + + MarkMessagesAsSeen(messageIds: [String!]): Boolean +} + +type Query { + Message( + roomId: ID!, + first: Int + offset: Int + orderBy: [_MessageOrdering] + ): [Message] +} diff --git a/backend/src/schema/types/type/Post.gql b/backend/src/schema/types/type/Post.gql index af1e14188..7e6d1d0e7 100644 --- a/backend/src/schema/types/type/Post.gql +++ b/backend/src/schema/types/type/Post.gql @@ -84,7 +84,8 @@ input _PostFilter { group: _GroupFilter postsInMyGroups: Boolean postType_in: [PostType] - eventStart_gte: String + eventStart_gte: String + eventEnd_gte: String } enum _PostOrdering { @@ -177,7 +178,7 @@ type Post { group: Group @relation(name: "IN", direction: "OUT") postType: [PostType] - @cypher(statement: "RETURN filter(l IN labels(this) WHERE NOT l = 'Post')") + @cypher(statement: "RETURN [l IN labels(this) WHERE NOT l = 'Post']") eventLocationName: String eventLocation: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l") diff --git a/backend/src/schema/types/type/Room.gql b/backend/src/schema/types/type/Room.gql new file mode 100644 index 000000000..0ddc65533 --- /dev/null +++ b/backend/src/schema/types/type/Room.gql @@ -0,0 +1,52 @@ +# input _RoomFilter { +# AND: [_RoomFilter!] +# OR: [_RoomFilter!] +# id: ID +# users_some: _UserFilter +# } + +# TODO change this to last message date +enum _RoomOrdering { + createdAt_desc +} + +type Room { + id: ID! + createdAt: String + updatedAt: String + + users: [User]! @relation(name: "CHATS_IN", direction: "IN") + + roomId: String! @cypher(statement: "RETURN this.id") + roomName: String! @cypher(statement: "MATCH (this)<-[:CHATS_IN]-(user:User) WHERE NOT user.id = $cypherParams.currentUserId RETURN user.name") + avatar: String! @cypher(statement: "MATCH (this)<-[:CHATS_IN]-(user:User) WHERE NOT user.id = $cypherParams.currentUserId RETURN user.avatar.url") + + lastMessageAt: String + + lastMessage: Message @cypher(statement: """ + MATCH (this)<-[:INSIDE]-(message:Message) + WITH message ORDER BY message.indexId DESC LIMIT 1 + RETURN message + """) + + unreadCount: Int @cypher(statement: """ + MATCH (this)<-[:INSIDE]-(message:Message)<-[:CREATED]-(user:User) + WHERE NOT user.id = $cypherParams.currentUserId + AND NOT message.seen + RETURN count(message) + """) +} + +type Mutation { + CreateRoom( + userId: ID! + ): Room +} + +type Query { + Room( + id: ID + orderBy: [_RoomOrdering] + ): [Room] + UnreadRooms: Int +} diff --git a/backend/src/server.spec.js b/backend/src/server.spec.ts similarity index 100% rename from backend/src/server.spec.js rename to backend/src/server.spec.ts diff --git a/backend/src/server.js b/backend/src/server.ts similarity index 93% rename from backend/src/server.js rename to backend/src/server.ts index d0b205035..b4d63c007 100644 --- a/backend/src/server.js +++ b/backend/src/server.ts @@ -7,7 +7,6 @@ import middleware from './middleware' import { getNeode, getDriver } from './db/neo4j' import decode from './jwt/decode' import schema from './schema' -import webfinger from './activitypub/routes/webfinger' import { RedisPubSub } from 'graphql-redis-subscriptions' import { PubSub } from 'graphql-subscriptions' import Redis from 'ioredis' @@ -58,7 +57,7 @@ export const context = async (options) => { } } -const createServer = (options) => { +const createServer = (options?) => { const defaults = { context, schema: middleware(schema), @@ -87,12 +86,11 @@ const createServer = (options) => { app.use( helmet( (CONFIG.DEBUG && { contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }) || {}, - ), + ) as any, ) - app.use('/.well-known/', webfinger()) app.use(express.static('public')) - app.use(bodyParser.json({ limit: '10mb' })) - app.use(bodyParser.urlencoded({ limit: '10mb', extended: true })) + app.use(bodyParser.json({ limit: '10mb' }) as any) + app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }) as any) app.use(graphqlUploadExpress()) server.applyMiddleware({ app, path: '/' }) const httpServer = http.createServer(app) diff --git a/backend/test/features/activity-delete.feature b/backend/test/features/activity-delete.feature deleted file mode 100644 index 76c734952..000000000 --- a/backend/test/features/activity-delete.feature +++ /dev/null @@ -1,55 +0,0 @@ -Feature: Delete an object - I want to delete objects - - Background: - Given our own server runs at "http://localhost:4123" - And we have the following users in our database: - | Slug | - | bernd-das-brot| - And I send a POST request with the following activity to "/activitypub/users/bernd-das-brot/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://aronda.org/users/bernd-das-brot/status/lka7dfzkjn2398hsfd", - "type": "Create", - "actor": "https://aronda.org/users/bernd-das-brot", - "object": { - "id": "https://aronda.org/users/bernd-das-brot/status/kljsdfg9843jknsdf234", - "type": "Article", - "published": "2019-02-07T19:37:55.002Z", - "attributedTo": "https://aronda.org/users/bernd-das-brot", - "content": "Hi Max, how are you?", - "to": "https://www.w3.org/ns/activitystreams#Public" - } - } - """ - - Scenario: Deleting a post (Article Object) - When I send a POST request with the following activity to "/activitypub/users/bernd-das-brot/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/karl-heinz/status/a4DJ2afdg323v32641vna42lkj685kasd2", - "type": "Delete", - "object": { - "id": "https://aronda.org/activitypub/users/bernd-das-brot/status/kljsdfg9843jknsdf234", - "type": "Article", - "published": "2019-02-07T19:37:55.002Z", - "attributedTo": "https://aronda.org/activitypub/users/bernd-das-brot", - "content": "Hi Max, how are you?", - "to": "https://www.w3.org/ns/activitystreams#Public" - } - } - """ - Then I expect the status code to be 200 - And the object is removed from the outbox collection of "bernd-das-brot" - """ - { - "id": "https://aronda.org/activitypub/users/bernd-das-brot/status/kljsdfg9843jknsdf234", - "type": "Article", - "published": "2019-02-07T19:37:55.002Z", - "attributedTo": "https://aronda.org/activitypub/users/bernd-das-brot", - "content": "Hi Max, how are you?", - "to": "https://www.w3.org/ns/activitystreams#Public" - } - """ diff --git a/backend/test/features/activity-follow.feature b/backend/test/features/activity-follow.feature deleted file mode 100644 index 7aa0c447d..000000000 --- a/backend/test/features/activity-follow.feature +++ /dev/null @@ -1,51 +0,0 @@ -Feature: Follow a user - I want to be able to follow a user on another instance. - Also if I do not want to follow a previous followed user anymore, - I want to undo the follow. - - Background: - Given our own server runs at "http://localhost:4123" - And we have the following users in our database: - | Slug | - | stuart-little | - | tero-vota | - - @wip - Scenario: Send a follow to a user inbox and make sure it's added to the right followers collection - When I send a POST request with the following activity to "/activitypub/users/tero-vota/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83", - "type": "Follow", - "actor": "http://localhost:4123/activitypub/users/stuart-little", - "object": "http://localhost:4123/activitypub/users/tero-vota" - } - """ - Then I expect the status code to be 200 - And the follower is added to the followers collection of "tero-vota" - """ - http://localhost:4123/activitypub/users/stuart-little - """ - - Scenario: Send an undo activity to revert the previous follow activity - When I send a POST request with the following activity to "/activitypub/users/stuart-little/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/tero-vota/status/a4DJ2afdg323v32641vna42lkj685kasd2", - "type": "Undo", - "actor": "http://localhost:4123/activitypub/users/tero-vota", - "object": { - "id": "http://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83", - "type": "Follow", - "actor": "http://localhost:4123/activitypub/users/stuart-little", - "object": "http://localhost:4123/activitypub/users/tero-vota" - } - } - """ - Then I expect the status code to be 200 - And the follower is removed from the followers collection of "tero-vota" - """ - http://localhost:4123/activitypub/users/stuart-little - """ diff --git a/backend/test/features/activity-like.feature b/backend/test/features/activity-like.feature deleted file mode 100644 index 26ef9c857..000000000 --- a/backend/test/features/activity-like.feature +++ /dev/null @@ -1,43 +0,0 @@ -Feature: Like an object like an article or note - As a user I want to like others posts - Also if I do not want to follow a previous followed user anymore, - I want to undo the follow. - - Background: - Given our own server runs at "http://localhost:4123" - And we have the following users in our database: - | Slug | - | karl-heinz | - | peter-lustiger | - And I send a POST request with the following activity to "/activitypub/users/bernd-das-brot/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/karl-heinz/status/faslkasa7dasfzkjn2398hsfd", - "type": "Create", - "actor": "http://localhost:4123/activitypub/users/karl-heinz", - "object": { - "id": "http://localhost:4123/activitypub/users/karl-heinz/status/dkasfljsdfaafg9843jknsdf", - "type": "Article", - "published": "2019-02-07T19:37:55.002Z", - "attributedTo": "http://localhost:4123/activitypub/users/karl-heinz", - "content": "Hi Max, how are you?", - "to": "https://www.w3.org/ns/activitystreams#Public" - } - } - """ - - @wip - Scenario: Send a like of a person to an users inbox and make sure it's added to the likes collection - When I send a POST request with the following activity to "/activitypub/users/karl-heinz/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/peter-lustiger/status/83J23549sda1k72fsa4567na42312455kad83", - "type": "Like", - "actor": "http://localhost:4123/activitypub/users/peter-lustiger", - "object": "http://localhost:4123/activitypub/users/karl-heinz/status/dkasfljsdfaafg9843jknsdf" - } - """ - Then I expect the status code to be 200 - And the post with id "dkasfljsdfaafg9843jknsdf" has been liked by "peter-lustiger" diff --git a/backend/test/features/collection.feature b/backend/test/features/collection.feature deleted file mode 100644 index 1bb4737e0..000000000 --- a/backend/test/features/collection.feature +++ /dev/null @@ -1,101 +0,0 @@ -Feature: Receiving collections - As a member of the Fediverse I want to be able of fetching collections - - Background: - Given our own server runs at "http://localhost:4123" - And we have the following users in our database: - | Slug | - | renate-oberdorfer | - - Scenario: Send a request to the outbox URI of peter-lustig and expect a ordered collection - When I send a GET request to "/activitypub/users/renate-oberdorfer/outbox" - Then I expect the status code to be 200 - And I receive the following json: - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox", - "summary": "renate-oberdorfers outbox collection", - "type": "OrderedCollection", - "first": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox?page=true", - "totalItems": 0 - } - """ - - Scenario: Send a request to the following URI of peter-lustig and expect a ordered collection - When I send a GET request to "/activitypub/users/renate-oberdorfer/following" - Then I expect the status code to be 200 - And I receive the following json: - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/following", - "summary": "renate-oberdorfers following collection", - "type": "OrderedCollection", - "first": "http://localhost:4123/activitypub/users/renate-oberdorfer/following?page=true", - "totalItems": 0 - } - """ - - Scenario: Send a request to the followers URI of peter-lustig and expect a ordered collection - When I send a GET request to "/activitypub/users/renate-oberdorfer/followers" - Then I expect the status code to be 200 - And I receive the following json: - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers", - "summary": "renate-oberdorfers followers collection", - "type": "OrderedCollection", - "first": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers?page=true", - "totalItems": 0 - } - """ - - Scenario: Send a request to the outbox URI of peter-lustig and expect a paginated outbox collection - When I send a GET request to "/activitypub/users/renate-oberdorfer/outbox?page=true" - Then I expect the status code to be 200 - And I receive the following json: - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox?page=true", - "summary": "renate-oberdorfers outbox collection", - "type": "OrderedCollectionPage", - "totalItems": 0, - "partOf": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox", - "orderedItems": [] - } - """ - - Scenario: Send a request to the following URI of peter-lustig and expect a paginated following collection - When I send a GET request to "/activitypub/users/renate-oberdorfer/following?page=true" - Then I expect the status code to be 200 - And I receive the following json: - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/following?page=true", - "summary": "renate-oberdorfers following collection", - "type": "OrderedCollectionPage", - "totalItems": 0, - "partOf": "http://localhost:4123/activitypub/users/renate-oberdorfer/following", - "orderedItems": [] - } - """ - - Scenario: Send a request to the followers URI of peter-lustig and expect a paginated followers collection - When I send a GET request to "/activitypub/users/renate-oberdorfer/followers?page=true" - Then I expect the status code to be 200 - And I receive the following json: - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers?page=true", - "summary": "renate-oberdorfers followers collection", - "type": "OrderedCollectionPage", - "totalItems": 0, - "partOf": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers", - "orderedItems": [] - } - """ diff --git a/backend/test/features/object-article.feature b/backend/test/features/object-article.feature deleted file mode 100644 index 030e408e9..000000000 --- a/backend/test/features/object-article.feature +++ /dev/null @@ -1,30 +0,0 @@ -Feature: Send and receive Articles - I want to send and receive article's via ActivityPub - - Background: - Given our own server runs at "http://localhost:4123" - And we have the following users in our database: - | Slug | - | marvin | - | max | - - Scenario: Send an article to a user inbox and make sure it's added to the inbox - When I send a POST request with the following activity to "/activitypub/users/max/inbox": - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://aronda.org/users/marvin/status/lka7dfzkjn2398hsfd", - "type": "Create", - "actor": "https://aronda.org/users/marvin", - "object": { - "id": "https://aronda.org/users/marvin/status/kljsdfg9843jknsdf", - "type": "Article", - "published": "2019-02-07T19:37:55.002Z", - "attributedTo": "https://aronda.org/users/marvin", - "content": "Hi Max, how are you?", - "to": "as:Public" - } - } - """ - Then I expect the status code to be 200 - And the post with id "kljsdfg9843jknsdf" to be created diff --git a/backend/test/features/support/steps.js b/backend/test/features/support/steps.js deleted file mode 100644 index e15801f83..000000000 --- a/backend/test/features/support/steps.js +++ /dev/null @@ -1,157 +0,0 @@ -// features/support/steps.js -import { Given, When, Then, AfterAll } from 'cucumber' -import { expect } from 'chai' -// import { client } from '../../../src/activitypub/apollo-client' -import { GraphQLClient } from 'graphql-request' -import Factory from '../../../src/db/factories' -const debug = require('debug')('ea:test:steps') - -const client = new GraphQLClient(host) - -function createUser (slug) { - debug(`creating user ${slug}`) - return Factory.build('user', { - name: slug, - }, { - password: '1234', - email: 'example@test.org', - }) - // await login({ email: 'example@test.org', password: '1234' }) -} - -Given('our own server runs at {string}', function (string) { - // just documenation -}) - -Given('we have the following users in our database:', function (dataTable) { - return Promise.all(dataTable.hashes().map((user) => { - return createUser(user.Slug) - })) -}) - -When('I send a GET request to {string}', async function (pathname) { - const response = await this.get(pathname) - this.lastContentType = response.lastContentType - - this.lastResponses.push(response.lastResponse) - this.statusCode = response.statusCode -}) - -When('I send a POST request with the following activity to {string}:', async function (inboxUrl, activity) { - debug(`inboxUrl = ${inboxUrl}`) - debug(`activity = ${activity}`) - const splitted = inboxUrl.split('/') - const slug = splitted[splitted.indexOf('users') + 1] - let result - do { - result = await client.request(` - query { - User(slug: "${slug}") { - id - slug - actorId - } - } - `) - } while (result.User.length === 0) - this.lastInboxUrl = inboxUrl - this.lastActivity = activity - const response = await this.post(inboxUrl, activity) - - this.lastResponses.push(response.lastResponse) - this.lastResponse = response.lastResponse - this.statusCode = response.statusCode -}) - -Then('I receive the following json:', function (docString) { - const parsedDocString = JSON.parse(docString) - const parsedLastResponse = JSON.parse(this.lastResponses.shift()) - if (Array.isArray(parsedDocString.orderedItems)) { - parsedDocString.orderedItems.forEach((el) => { - delete el.id - if (el.object) delete el.object.published - }) - parsedLastResponse.orderedItems.forEach((el) => { - delete el.id - if (el.object) delete el.object.published - }) - } - if (parsedDocString.publicKey && parsedDocString.publicKey.publicKeyPem) { - delete parsedDocString.publicKey.publicKeyPem - delete parsedLastResponse.publicKey.publicKeyPem - } - expect(parsedDocString).to.eql(parsedLastResponse) -}) - -Then('I expect the Content-Type to be {string}', function (contentType) { - expect(this.lastContentType).to.equal(contentType) -}) - -Then('I expect the status code to be {int}', function (statusCode) { - expect(this.statusCode).to.equal(statusCode) -}) - -Then('the activity is added to the {string} collection', async function (collectionName) { - const response = await this.get(this.lastInboxUrl.replace('inbox', collectionName) + '?page=true') - debug(`orderedItems = ${JSON.parse(response.lastResponse).orderedItems}`) - expect(JSON.parse(response.lastResponse).orderedItems).to.include(JSON.parse(this.lastActivity).object) -}) - -Then('the follower is added to the followers collection of {string}', async function (userName, follower) { - const response = await this.get(`/activitypub/users/${userName}/followers?page=true`) - const responseObject = JSON.parse(response.lastResponse) - expect(responseObject.orderedItems).to.include(follower) -}) - -Then('the follower is removed from the followers collection of {string}', async function (userName, follower) { - const response = await this.get(`/activitypub/users/${userName}/followers?page=true`) - const responseObject = JSON.parse(response.lastResponse) - expect(responseObject.orderedItems).to.not.include(follower) -}) - -Then('the post with id {string} to be created', async function (id) { - let result - do { - result = await client.request(` - query { - Post(id: "${id}") { - title - } - } - `) - } while (result.Post.length === 0) - - expect(result.Post).to.be.an('array').that.is.not.empty // eslint-disable-line -}) - -Then('the object is removed from the outbox collection of {string}', async function (name, object) { - const response = await this.get(`/activitypub/users/${name}/outbox?page=true`) - const parsedResponse = JSON.parse(response.lastResponse) - expect(parsedResponse.orderedItems).to.not.include(object) -}) - -Then('I send a GET request to {string} and expect a ordered collection', () => { - -}) - -Then('the activity is added to the users inbox collection', async function () { - -}) - -Then('the post with id {string} has been liked by {string}', async function (id, slug) { - let result - do { - result = await client.request(` - query { - Post(id: "${id}") { - shoutedBy { - slug - } - } - } - `) - } while (result.Post.length === 0) - - expect(result.Post[0].shoutedBy).to.be.an('array').that.is.not.empty // eslint-disable-line - expect(result.Post[0].shoutedBy[0].slug).to.equal(slug) -}) diff --git a/backend/test/features/webfinger.feature b/backend/test/features/webfinger.feature deleted file mode 100644 index cbca5ac10..000000000 --- a/backend/test/features/webfinger.feature +++ /dev/null @@ -1,39 +0,0 @@ -Feature: Webfinger discovery - From an external server, e.g. Mastodon - I want to search for an actor alias - In order to follow the actor - - Background: - Given our own server runs at "http://localhost:4123" - And we have the following users in our database: - | Slug | - | peter-lustiger | - - Scenario: Receiving an actor object - When I send a GET request to "/activitypub/users/peter-lustiger" - Then I receive the following json: - """ - { - "@context": [ - "https://www.w3.org/ns/activitystreams", - "https://w3id.org/security/v1" - ], - "id": "http://localhost:4123/activitypub/users/peter-lustiger", - "type": "Person", - "preferredUsername": "peter-lustiger", - "name": "peter-lustiger", - "following": "http://localhost:4123/activitypub/users/peter-lustiger/following", - "followers": "http://localhost:4123/activitypub/users/peter-lustiger/followers", - "inbox": "http://localhost:4123/activitypub/users/peter-lustiger/inbox", - "outbox": "http://localhost:4123/activitypub/users/peter-lustiger/outbox", - "url": "http://localhost:4123/activitypub/@peter-lustiger", - "endpoints": { - "sharedInbox": "http://localhost:4123/activitypub/inbox" - }, - "publicKey": { - "id": "http://localhost:4123/activitypub/users/peter-lustiger#main-key", - "owner": "http://localhost:4123/activitypub/users/peter-lustiger", - "publicKeyPem": "adglkjlk89235kjn8obn2384f89z5bv9..." - } - } - """ diff --git a/backend/test/features/world.js b/backend/test/features/world.js deleted file mode 100644 index be436b536..000000000 --- a/backend/test/features/world.js +++ /dev/null @@ -1,58 +0,0 @@ -// features/support/world.js -import { setWorldConstructor } from 'cucumber' -import request from 'request' -const debug = require('debug')('ea:test:world') - -class CustomWorld { - constructor () { - // webFinger.feature - this.lastResponses = [] - this.lastContentType = null - this.lastInboxUrl = null - this.lastActivity = null - // object-article.feature - this.statusCode = null - } - get (pathname) { - return new Promise((resolve, reject) => { - request(`http://localhost:4123/${this.replaceSlashes(pathname)}`, { - headers: { - 'Accept': 'application/activity+json' - }}, function (error, response, body) { - if (!error) { - debug(`get content-type = ${response.headers['content-type']}`) - debug(`get body = ${JSON.stringify(typeof body === 'string' ? JSON.parse(body) : body, null, 2)}`) - resolve({ lastResponse: body, lastContentType: response.headers['content-type'], statusCode: response.statusCode }) - } else { - reject(error) - } - }) - }) - } - - replaceSlashes (pathname) { - return pathname.replace(/^\/+/, '') - } - - post (pathname, activity) { - return new Promise((resolve, reject) => { - request({ - url: `http://localhost:4123/${this.replaceSlashes(pathname)}`, - method: 'POST', - headers: { - 'Content-Type': 'application/activity+json' - }, - body: activity - }, function (error, response, body) { - if (!error) { - debug(`post response = ${response.headers['content-type']}`) - resolve({ lastResponse: body, lastContentType: response.headers['content-type'], statusCode: response.statusCode }) - } else { - reject(error) - } - }) - }) - } -} - -setWorldConstructor(CustomWorld) diff --git a/backend/test/setup.js b/backend/test/setup.ts similarity index 87% rename from backend/test/setup.js rename to backend/test/setup.ts index 4501da899..d2f24bd40 100644 --- a/backend/test/setup.js +++ b/backend/test/setup.ts @@ -2,7 +2,7 @@ // https://stackoverflow.com/questions/68468203/why-am-i-getting-textencoder-is-not-defined-in-jest import { TextEncoder, TextDecoder } from 'util' global.TextEncoder = TextEncoder -global.TextDecoder = TextDecoder +global.TextDecoder = TextDecoder as any // Metascraper takes longer nowadays, double time jest.setTimeout(10000) \ No newline at end of file diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 3271196ed..b6f3526a3 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -44,7 +44,7 @@ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ /* JavaScript Support */ - "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ @@ -83,13 +83,13 @@ /* Type Checking */ "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + "useUnknownInCatchVariables": false, /* Default catch clause variables as 'unknown' instead of 'any'. */ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ @@ -106,6 +106,4 @@ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, - "include": ["./src/**/*"], - "exclude": ["./src/**/*.spec.ts", "./src/**/*.spec.js"] } diff --git a/backend/yarn.lock b/backend/yarn.lock index 9cba61b21..7c1fa2f6b 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -10,6 +10,14 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@apollo/protobufjs@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.0.4.tgz#cf01747a55359066341f31b5ce8db17df44244e0" @@ -71,11 +79,23 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" + integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== + dependencies: + "@babel/highlight" "^7.22.5" + "@babel/compat-data@^7.20.5": version "7.20.14" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.14.tgz#4106fc8b755f3e3ee0a0a7c27dde5de1d2b2baf8" integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw== +"@babel/compat-data@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" + integrity sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA== + "@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" @@ -85,7 +105,7 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.3": +"@babel/core@^7.1.0", "@babel/core@^7.12.3": version "7.20.12" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== @@ -106,6 +126,27 @@ json5 "^2.2.2" semver "^6.3.0" +"@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.5.tgz#d67d9747ecf26ee7ecd3ebae1ee22225fe902a89" + integrity sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.5" + "@babel/generator" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helpers" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + "@babel/core@~7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" @@ -137,6 +178,16 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" +"@babel/generator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" + integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA== + dependencies: + "@babel/types" "^7.22.5" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" @@ -163,6 +214,17 @@ lru-cache "^5.1.1" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02" + integrity sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw== + dependencies: + "@babel/compat-data" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + "@babel/helper-compilation-targets@^7.8.7": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" @@ -205,6 +267,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== +"@babel/helper-environment-visitor@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" + integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== + "@babel/helper-explode-assignable-expression@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" @@ -221,6 +288,14 @@ "@babel/template" "^7.18.10" "@babel/types" "^7.19.0" +"@babel/helper-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" + integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== + dependencies: + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.5" + "@babel/helper-function-name@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" @@ -244,6 +319,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-hoist-variables@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" @@ -265,6 +347,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-module-imports@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" + integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.9.0": version "7.20.11" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" @@ -279,6 +368,20 @@ "@babel/traverse" "^7.20.10" "@babel/types" "^7.20.7" +"@babel/helper-module-transforms@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" + integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" + "@babel/helper-optimise-call-expression@^7.18.6", "@babel/helper-optimise-call-expression@^7.8.3": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" @@ -286,7 +389,7 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.20.2" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== @@ -338,6 +441,13 @@ dependencies: "@babel/types" "^7.20.2" +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration@^7.18.6", "@babel/helper-split-export-declaration@^7.8.3": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" @@ -345,21 +455,43 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-split-export-declaration@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz#88cf11050edb95ed08d596f7a044462189127a08" + integrity sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-string-parser@^7.19.4": version "7.19.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1", "@babel/helper-validator-identifier@^7.9.5": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + "@babel/helper-validator-option@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== +"@babel/helper-validator-option@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" + integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== + "@babel/helper-wrap-function@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" @@ -379,6 +511,15 @@ "@babel/traverse" "^7.20.13" "@babel/types" "^7.20.7" +"@babel/helpers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820" + integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q== + dependencies: + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" + "@babel/highlight@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" @@ -388,6 +529,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" + integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/node@~7.8.7": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.8.7.tgz#4213ea99f0c86cc1cf460e61131e7acbb723e13a" @@ -407,6 +557,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.15.tgz#eec9f36d8eaf0948bb88c87a46784b5ee9fd0c89" integrity sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg== +"@babel/parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" + integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== + "@babel/parser@^7.7.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" @@ -550,13 +705,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -1026,6 +1174,15 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" +"@babel/template@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" + integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" + "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.13", "@babel/traverse@^7.20.7", "@babel/traverse@^7.7.2", "@babel/traverse@^7.9.0": version "7.20.13" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473" @@ -1042,6 +1199,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1" + integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/generator" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" @@ -1066,6 +1239,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" + integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + to-fast-properties "^2.0.0" + "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" @@ -1095,6 +1277,38 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.5.2" + 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" + +"@eslint/js@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0" + integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg== + "@faker-js/faker@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-7.6.0.tgz#9ea331766084288634a9247fcd8b84f16ff4ba07" @@ -1165,6 +1379,25 @@ dependencies: "@hapi/hoek" "^8.3.0" +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1181,164 +1414,142 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.4.2.tgz#f78374905c2454764152904a344a2d5226b0ef09" - integrity sha512-0I/rEJwMpV9iwi9cDEnT71a5nNGK9lj8Z4+1pRAU2x/thVXCDnaTGrvxyK+cAqZTFVFCiR+hfVrP4l2m+dCmQg== +"@jest/console@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" + integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^29.4.2" - jest-util "^29.4.2" + jest-message-util "^27.5.1" + jest-util "^27.5.1" slash "^3.0.0" -"@jest/core@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.4.2.tgz#6e999b67bdc2df9d96ba9b142465bda71ee472c2" - integrity sha512-KGuoQah0P3vGNlaS/l9/wQENZGNKGoWb+OPxh3gz+YzG7/XExvYu34MzikRndQCdM2S0tzExN4+FL37i6gZmCQ== +"@jest/core@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" + integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== dependencies: - "@jest/console" "^29.4.2" - "@jest/reporters" "^29.4.2" - "@jest/test-result" "^29.4.2" - "@jest/transform" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/console" "^27.5.1" + "@jest/reporters" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - ci-info "^3.2.0" + emittery "^0.8.1" exit "^0.1.2" graceful-fs "^4.2.9" - jest-changed-files "^29.4.2" - jest-config "^29.4.2" - jest-haste-map "^29.4.2" - jest-message-util "^29.4.2" - jest-regex-util "^29.4.2" - jest-resolve "^29.4.2" - jest-resolve-dependencies "^29.4.2" - jest-runner "^29.4.2" - jest-runtime "^29.4.2" - jest-snapshot "^29.4.2" - jest-util "^29.4.2" - jest-validate "^29.4.2" - jest-watcher "^29.4.2" + jest-changed-files "^27.5.1" + jest-config "^27.5.1" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-resolve-dependencies "^27.5.1" + jest-runner "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + jest-watcher "^27.5.1" micromatch "^4.0.4" - pretty-format "^29.4.2" + rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.4.2.tgz#ee92c316ee2fbdf0bcd9d2db0ef42d64fea26b56" - integrity sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ== +"@jest/environment@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" + integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== dependencies: - "@jest/fake-timers" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" - jest-mock "^29.4.2" + jest-mock "^27.5.1" -"@jest/expect-utils@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.4.2.tgz#cd0065dfdd8e8a182aa350cc121db97b5eed7b3f" - integrity sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA== +"@jest/fake-timers@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" + integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== dependencies: - jest-get-type "^29.4.2" - -"@jest/expect@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.4.2.tgz#2d4a6a41b29380957c5094de19259f87f194578b" - integrity sha512-NUAeZVApzyaeLjfWIV/64zXjA2SS+NuUPHpAlO7IwVMGd5Vf9szTl9KEDlxY3B4liwLO31os88tYNHl6cpjtKQ== - dependencies: - expect "^29.4.2" - jest-snapshot "^29.4.2" - -"@jest/fake-timers@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.4.2.tgz#af43ee1a5720b987d0348f80df98f2cb17d45cd0" - integrity sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ== - dependencies: - "@jest/types" "^29.4.2" - "@sinonjs/fake-timers" "^10.0.2" + "@jest/types" "^27.5.1" + "@sinonjs/fake-timers" "^8.0.1" "@types/node" "*" - jest-message-util "^29.4.2" - jest-mock "^29.4.2" - jest-util "^29.4.2" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-util "^27.5.1" -"@jest/globals@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.4.2.tgz#73f85f5db0e17642258b25fd0b9fc89ddedb50eb" - integrity sha512-zCk70YGPzKnz/I9BNFDPlK+EuJLk21ur/NozVh6JVM86/YYZtZHqxFFQ62O9MWq7uf3vIZnvNA0BzzrtxD9iyg== +"@jest/globals@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" + integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== dependencies: - "@jest/environment" "^29.4.2" - "@jest/expect" "^29.4.2" - "@jest/types" "^29.4.2" - jest-mock "^29.4.2" + "@jest/environment" "^27.5.1" + "@jest/types" "^27.5.1" + expect "^27.5.1" -"@jest/reporters@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.4.2.tgz#6abfa923941daae0acc76a18830ee9e79a22042d" - integrity sha512-10yw6YQe75zCgYcXgEND9kw3UZZH5tJeLzWv4vTk/2mrS1aY50A37F+XT2hPO5OqQFFnUWizXD8k1BMiATNfUw== +"@jest/reporters@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" + integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.4.2" - "@jest/test-result" "^29.4.2" - "@jest/transform" "^29.4.2" - "@jest/types" "^29.4.2" - "@jridgewell/trace-mapping" "^0.3.15" + "@jest/console" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" - glob "^7.1.3" + glob "^7.1.2" graceful-fs "^4.2.9" istanbul-lib-coverage "^3.0.0" istanbul-lib-instrument "^5.1.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-message-util "^29.4.2" - jest-util "^29.4.2" - jest-worker "^29.4.2" + jest-haste-map "^27.5.1" + jest-resolve "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" slash "^3.0.0" + source-map "^0.6.0" string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.1.0" -"@jest/schemas@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.2.tgz#cf7cfe97c5649f518452b176c47ed07486270fc1" - integrity sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g== +"@jest/source-map@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" + integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== dependencies: - "@sinclair/typebox" "^0.25.16" - -"@jest/source-map@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.4.2.tgz#f9815d59e25cd3d6828e41489cd239271018d153" - integrity sha512-tIoqV5ZNgYI9XCKXMqbYe5JbumcvyTgNN+V5QW4My033lanijvCD0D4PI9tBw4pRTqWOc00/7X3KVvUh+qnF4Q== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" callsites "^3.0.0" graceful-fs "^4.2.9" + source-map "^0.6.0" -"@jest/test-result@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.4.2.tgz#34b0ba069f2e3072261e4884c8fb6bd15ed6fb8d" - integrity sha512-HZsC3shhiHVvMtP+i55MGR5bPcc3obCFbA5bzIOb8pCjwBZf11cZliJncCgaVUbC5yoQNuGqCkC0Q3t6EItxZA== +"@jest/test-result@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" + integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== dependencies: - "@jest/console" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/console" "^27.5.1" + "@jest/types" "^27.5.1" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.4.2.tgz#8b48e5bc4af80b42edacaf2a733d4f295edf28fb" - integrity sha512-9Z2cVsD6CcObIVrWigHp2McRJhvCxL27xHtrZFgNC1RwnoSpDx6fZo8QYjJmziFlW9/hr78/3sxF54S8B6v8rg== +"@jest/test-sequencer@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" + integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== dependencies: - "@jest/test-result" "^29.4.2" + "@jest/test-result" "^27.5.1" graceful-fs "^4.2.9" - jest-haste-map "^29.4.2" - slash "^3.0.0" + jest-haste-map "^27.5.1" + jest-runtime "^27.5.1" "@jest/transform@^25.2.6": version "25.2.6" @@ -1362,26 +1573,26 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/transform@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.4.2.tgz#b24b72dbab4c8675433a80e222d6a8ef4656fb81" - integrity sha512-kf1v5iTJHn7p9RbOsBuc/lcwyPtJaZJt5885C98omWz79NIeD3PfoiiaPSu7JyCyFzNOIzKhmMhQLUhlTL9BvQ== +"@jest/transform@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" + integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.4.2" - "@jridgewell/trace-mapping" "^0.3.15" + "@babel/core" "^7.1.0" + "@jest/types" "^27.5.1" babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.9" - jest-haste-map "^29.4.2" - jest-regex-util "^29.4.2" - jest-util "^29.4.2" + jest-haste-map "^27.5.1" + jest-regex-util "^27.5.1" + jest-util "^27.5.1" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" - write-file-atomic "^4.0.2" + source-map "^0.6.1" + write-file-atomic "^3.0.0" "@jest/types@^25.2.6": version "25.2.6" @@ -1393,16 +1604,15 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^29.4.2": - version "29.4.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.2.tgz#8f724a414b1246b2bfd56ca5225d9e1f39540d82" - integrity sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw== +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== dependencies: - "@jest/schemas" "^29.4.2" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" - "@types/yargs" "^17.0.8" + "@types/yargs" "^16.0.0" chalk "^4.0.0" "@jridgewell/gen-mapping@^0.1.0": @@ -1413,6 +1623,15 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" @@ -1450,7 +1669,15 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.17": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -1547,11 +1774,24 @@ "@nodelib/fs.stat" "2.0.3" run-parallel "^1.1.9" +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + "@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== +"@nodelib/fs.stat@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + "@nodelib/fs.walk@^1.2.3": version "1.2.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" @@ -1560,6 +1800,14 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + "@npmcli/fs@^2.1.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865" @@ -1576,6 +1824,18 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@pkgr/utils@^2.3.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.1.tgz#adf291d0357834c410ce80af16e711b56c7b1cd3" + integrity sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w== + dependencies: + cross-spawn "^7.0.3" + fast-glob "^3.2.12" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.5.0" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -1708,29 +1968,24 @@ "@sentry/types" "5.15.4" tslib "^1.9.3" -"@sinclair/typebox@^0.25.16": - version "0.25.21" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272" - integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g== - "@sindresorhus/is@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.1.tgz#d26729db850fa327b7cacc5522252194404226f5" integrity sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g== -"@sinonjs/commons@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" - integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== +"@sinonjs/commons@^1.7.0": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz#d10549ed1f423d80639c528b6c7f5a1017747d0c" - integrity sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw== +"@sinonjs/fake-timers@^8.0.1": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== dependencies: - "@sinonjs/commons" "^2.0.0" + "@sinonjs/commons" "^1.7.0" "@szmarczak/http-timer@^4.0.5": version "4.0.6" @@ -1739,6 +1994,11 @@ dependencies: defer-to-connect "^2.0.0" +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" @@ -1771,6 +2031,17 @@ dependencies: "@types/node" "*" +"@types/babel__core@^7.0.0": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.1.tgz#916ecea274b0c776fec721e333e55762d3a9614b" + integrity sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + "@types/babel__core@^7.1.0": version "7.1.2" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f" @@ -1815,6 +2086,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/babel__traverse@^7.0.4": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.1.tgz#dd6f1d2411ae677dcb2db008c962598be31d6acf" + integrity sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg== + dependencies: + "@babel/types" "^7.20.7" + "@types/body-parser@*", "@types/body-parser@1.19.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" @@ -1898,7 +2176,7 @@ dependencies: "@types/node" "*" -"@types/graceful-fs@^4.1.3": +"@types/graceful-fs@^4.1.2": version "4.1.6" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== @@ -1952,10 +2230,23 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/json-schema@^7.0.3": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" - integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== +"@types/jest@^27.0.2": + version "27.5.2" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c" + integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA== + dependencies: + jest-matcher-utils "^27.0.0" + pretty-format "^27.0.0" + +"@types/json-schema@^7.0.9": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/keygrip@*": version "1.0.2" @@ -2022,6 +2313,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.26.tgz#a8a119960bff16b823be4c617da028570779bcfd" integrity sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw== +"@types/node@^20.2.5": + version "20.2.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" + integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== + "@types/prettier@^2.1.5": version "2.7.2" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" @@ -2044,6 +2340,11 @@ dependencies: "@types/node" "*" +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + "@types/serve-static@*": version "1.13.4" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.4.tgz#6662a93583e5a6cabca1b23592eb91e12fa80e7c" @@ -2076,10 +2377,10 @@ dependencies: "@types/yargs-parser" "*" -"@types/yargs@^17.0.8": - version "17.0.22" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.22.tgz#7dd37697691b5f17d020f3c63e7a45971ff71e9a" - integrity sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g== +"@types/yargs@^16.0.0": + version "16.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.5.tgz#12cc86393985735a283e387936398c2f9e5f88e3" + integrity sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ== dependencies: "@types/yargs-parser" "*" @@ -2093,25 +2394,89 @@ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== -"@typescript-eslint/experimental-utils@^2.5.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.0.tgz#ed70bef72822bff54031ff0615fc888b9e2b6e8a" - integrity sha512-34BAFpNOwHXeqT+AvdalLxOvcPYnCxA5JGmBAFL64RGMdP0u65rXjii7l/nwpgk5aLEE1LaqF+SsCU0/Cb64xA== +"@typescript-eslint/eslint-plugin@^5.57.1": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz#2f4bea6a3718bed2ba52905358d0f45cd3620d31" + integrity sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg== dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.6.0" - eslint-scope "^5.0.0" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/type-utils" "5.60.0" + "@typescript-eslint/utils" "5.60.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" -"@typescript-eslint/typescript-estree@2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.0.tgz#d3e9d8e001492e2b9124c4d4bd4e7f03c0fd7254" - integrity sha512-A3lSBVIdj2Gp0lFEL6in2eSPqJ33uAc3Ko+Y4brhjkxzjbzLnwBH22CwsW2sCo+iwogfIyvb56/AJri15H0u5Q== +"@typescript-eslint/parser@^5.57.1": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.60.0.tgz#08f4daf5fc6548784513524f4f2f359cebb4068a" + integrity sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ== dependencies: - debug "^4.1.1" - glob "^7.1.4" - is-glob "^4.0.1" - lodash.unescape "4.0.1" - semver "^6.3.0" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/typescript-estree" "5.60.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz#ae511967b4bd84f1d5e179bb2c82857334941c1c" + integrity sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ== + dependencies: + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/visitor-keys" "5.60.0" + +"@typescript-eslint/type-utils@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz#69b09087eb12d7513d5b07747e7d47f5533aa228" + integrity sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g== + dependencies: + "@typescript-eslint/typescript-estree" "5.60.0" + "@typescript-eslint/utils" "5.60.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.60.0.tgz#3179962b28b4790de70e2344465ec97582ce2558" + integrity sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA== + +"@typescript-eslint/typescript-estree@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz#4ddf1a81d32a850de66642d9b3ad1e3254fb1600" + integrity sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ== + dependencies: + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/visitor-keys" "5.60.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.60.0", "@typescript-eslint/utils@^5.10.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.60.0.tgz#4667c5aece82f9d4f24a667602f0f300864b554c" + integrity sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/typescript-estree" "5.60.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz#b48b29da3f5f31dd1656281727004589d2722a66" + integrity sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw== + dependencies: + "@typescript-eslint/types" "5.60.0" + eslint-visitor-keys "^3.3.0" "@wry/context@^0.4.0": version "0.4.4" @@ -2128,7 +2493,7 @@ dependencies: tslib "^1.9.3" -abab@^2.0.6: +abab@^2.0.3, abab@^2.0.5, abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== @@ -2146,21 +2511,39 @@ accepts@^1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-jsx@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" - integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^7.1.0: +acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.2.4, acorn@^8.8.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== + acorn@^8.4.1: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" @@ -2203,7 +2586,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^3.2.0" -ajv@^6.10.0, ajv@^6.10.2: +ajv@^6.10.0: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== @@ -2213,7 +2596,7 @@ ajv@^6.10.0, ajv@^6.10.2: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.12.3: +ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2247,17 +2630,12 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.1.0, ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.1.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -2648,6 +3026,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -2663,18 +3046,29 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= -array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" + 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" array-union@^2.1.0: version "2.1.0" @@ -2686,14 +3080,25 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== -array.prototype.flat@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.2.tgz#8f3c71d245ba349b6b64b4078f76f5576f1fd723" - integrity sha512-VXjh7lAL4KXKF2hY4FnEW9eRW6IhdvFW1sN/JwLbmECbCgACCnBHNyP3lFiYuttr0jxRN9Bsc5+G27dMseSWqQ== +array.prototype.flat@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== dependencies: - define-properties "^1.1.3" - es-abstract "^1.15.0" - function-bind "^1.1.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" asn1@~0.2.3: version "0.2.6" @@ -2744,11 +3149,6 @@ assignment@2.2.0: resolved "https://registry.yarnpkg.com/assignment/-/assignment-2.2.0.tgz#f5b5bc2d160d69986e8700cd38f567c0aabe101e" integrity sha1-9bW8LRYNaZhuhwDNOPVnwKq+EB4= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - async-each@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" @@ -2781,6 +3181,11 @@ audio-extensions@0.0.0: resolved "https://registry.yarnpkg.com/audio-extensions/-/audio-extensions-0.0.0.tgz#d0eefe077fb9eb625898eed9985890548cf1f8d2" integrity sha1-0O7+B3+562JYmO7ZmFiQVIzx+NI= +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + aws-sdk@^2.652.0: version "2.652.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.652.0.tgz#00a4dd3a4ce588448895c42d25e967f2a23b487c" @@ -2823,15 +3228,16 @@ babel-eslint@~10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.4.2.tgz#b17b9f64be288040877cbe2649f91ac3b63b2ba6" - integrity sha512-vcghSqhtowXPG84posYkkkzcZsdayFkubUgbE3/1tuGbX7AQtwCkkNA/wIbB0BMjuCPoqTkiDyKN7Ty7d3uwNQ== +babel-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" + integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== dependencies: - "@jest/transform" "^29.4.2" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.4.2" + babel-preset-jest "^27.5.1" chalk "^4.0.0" graceful-fs "^4.2.9" slash "^3.0.0" @@ -2876,14 +3282,14 @@ babel-plugin-jest-hoist@^25.2.6: "@babel/types" "^7.3.3" "@types/babel__traverse" "^7.0.6" -babel-plugin-jest-hoist@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.2.tgz#22aa43e255230f02371ffef1cac7eedef58f60bc" - integrity sha512-5HZRCfMeWypFEonRbEkwWXtNS1sQK159LhRVyRuLzyfVBxDy/34Tr/rg4YVi0SScSJ4fqeaR/OIeceJ/LaQ0pQ== +babel-plugin-jest-hoist@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" + integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" + "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" babel-plugin-transform-runtime@^6.23.0: @@ -2920,12 +3326,12 @@ babel-preset-jest@^25.2.6: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" babel-plugin-jest-hoist "^25.2.6" -babel-preset-jest@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.4.2.tgz#f0b20c6a79a9f155515e72a2d4f537fe002a4e38" - integrity sha512-ecWdaLY/8JyfUDr0oELBMpj3R5I1L6ZqG+kRJmwqfHtLWuPrJStR0LUkvUhfykJWTsXXMnohsayN/twltBbDrQ== +babel-preset-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" + integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== dependencies: - babel-plugin-jest-hoist "^29.4.2" + babel-plugin-jest-hoist "^27.5.1" babel-preset-current-node-syntax "^1.0.0" babel-runtime@^6.22.0: @@ -2986,6 +3392,11 @@ becke-ch--regex--s0-0-v1--base--pl--lib@^1.4.0: resolved "https://registry.yarnpkg.com/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz#429ceebbfa5f7e936e78d73fbdc7da7162b20e20" integrity sha1-Qpzuu/pffpNueNc/vcfacWKyDiA= +big-integer@^1.6.44: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -3035,6 +3446,13 @@ boxen@^1.2.1: term-size "^1.2.0" widest-line "^2.0.0" +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -3073,6 +3491,11 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + browserslist@^4.21.3: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" @@ -3094,6 +3517,13 @@ browserslist@^4.8.3, browserslist@^4.9.1: escalade "^3.1.1" node-releases "^1.1.71" +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -3128,6 +3558,20 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +builtins@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + busboy@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b" @@ -3197,6 +3641,14 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -3273,7 +3725,7 @@ chalk@2.3.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3290,7 +3742,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3303,11 +3755,6 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -3455,13 +3902,6 @@ cli-boxes@^1.0.0: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-table3@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" @@ -3472,11 +3912,6 @@ cli-table3@^0.5.1: optionalDependencies: colors "^1.1.2" -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - clipboardy@1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2" @@ -3485,13 +3920,13 @@ clipboardy@1.2.2: arch "^2.1.0" execa "^0.8.0" -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" - strip-ansi "^6.0.1" + strip-ansi "^6.0.0" wrap-ansi "^7.0.0" clone-response@^1.0.2: @@ -3580,7 +4015,7 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.19.0, commander@^2.20.3: +commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -3637,11 +4072,6 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -3666,11 +4096,6 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -3760,7 +4185,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -3780,7 +4205,7 @@ cross-spawn@^7.0.1: shebang-command "^2.0.0" which "^2.0.1" -cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3830,6 +4255,23 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + cssstyle@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-3.0.0.tgz#17ca9c87d26eac764bb8cfd00583cff21ce0277a" @@ -3898,6 +4340,15 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + data-urls@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4" @@ -3907,24 +4358,24 @@ data-urls@^4.0.0: whatwg-mimetype "^3.0.0" whatwg-url "^12.0.0" -dateformat@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" - integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== dayjs@^1.10.0: version "1.10.6" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63" integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@~4.1.1: +debug@4: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -3938,14 +4389,21 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.3: +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -decimal.js@^10.4.3: +decimal.js@^10.2.1, decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== @@ -3979,7 +4437,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@~0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -3994,11 +4452,34 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + defer-to-connect@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -4006,6 +4487,14 @@ define-properties@^1.1.2, define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -4075,10 +4564,10 @@ dicer@0.3.0: dependencies: streamsearch "0.1.2" -diff-sequences@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.2.tgz#711fe6bd8a5869fe2539cee4a5152425ff671fda" - integrity sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw== +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== diff@^4.0.1: version "4.0.1" @@ -4092,13 +4581,12 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" - isarray "^1.0.0" doctrine@^3.0.0: version "3.0.0" @@ -4169,6 +4657,13 @@ domelementtype@^2.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + domexception@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" @@ -4254,16 +4749,16 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +dotenv@^16.0.0: + version "16.1.4" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.1.4.tgz#67ac1a10cd9c25f5ba604e4e08bc77c0ebe0ca8c" + integrity sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw== + dotenv@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" integrity sha512-XcaMACOr3JMVcEv0Y/iUM2XaOsATRZ3U1In41/1jjK6vJZ2PZbQ1bzCG8uvaByfaBpl9gqc9QWJovpUGBXLLYQ== -dotenv@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" - integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== - dotenv@~8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" @@ -4312,15 +4807,10 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.295.tgz#911d5df67542bf7554336142eb302c5ec90bba66" integrity sha512-lEO94zqf1bDA3aepxwnWoHUjA8sZ+2owgcSZjYQy0+uOSEclJX0VieZC+r+wLpSxUHRd6gG32znTWmr+5iGzFw== -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== emoji-regex@^8.0.0: version "8.0.0" @@ -4346,6 +4836,14 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +enhanced-resolve@^5.12.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + entities@^1.1.1, entities@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -4376,7 +4874,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -4390,34 +4888,6 @@ error-stack-parser@^2.0.1: dependencies: stackframe "^1.0.4" -es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - -es-abstract@^1.15.0: - version "1.16.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.3.tgz#52490d978f96ff9f89ec15b5cf244304a5bca161" - integrity sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.7.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" - es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: version "1.17.6" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" @@ -4435,6 +4905,74 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + 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" + +es-abstract@^1.5.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" @@ -4489,7 +5027,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -4504,110 +5042,142 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -eslint-config-prettier@~6.15.0: - version "6.15.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" - integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== dependencies: - get-stdin "^6.0.0" + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" -eslint-config-standard@~14.1.1: - version "14.1.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" - integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== +eslint-config-prettier@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== -eslint-import-resolver-node@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== +eslint-config-standard@^17.0.0: + version "17.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz#40ffb8595d47a6b242e07cbfd49dc211ed128975" + integrity sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q== + +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== dependencies: - debug "^2.6.9" - resolve "^1.5.0" + debug "^3.2.7" + is-core-module "^2.11.0" + resolve "^1.22.1" -eslint-module-utils@^2.4.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz#cdf0b40d623032274ccd2abd7e64c4e524d6e19c" - integrity sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw== +eslint-import-resolver-typescript@^3.5.4: + version "3.5.5" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz#0a9034ae7ed94b254a360fbea89187b60ea7456d" + integrity sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw== dependencies: - debug "^2.6.9" - pkg-dir "^2.0.0" + debug "^4.3.4" + enhanced-resolve "^5.12.0" + eslint-module-utils "^2.7.4" + get-tsconfig "^4.5.0" + globby "^13.1.3" + is-core-module "^2.11.0" + is-glob "^4.0.3" + synckit "^0.8.5" -eslint-plugin-es@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" - integrity sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng== +eslint-module-utils@^2.7.4: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-es@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz#f0822f0c18a535a97c3e714e89f88586a7641ec9" + integrity sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ== dependencies: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-import@~2.20.2: - version "2.20.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d" - integrity sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg== +eslint-plugin-import@^2.27.5: + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== dependencies: - array-includes "^3.0.3" - array.prototype.flat "^1.2.1" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.4.1" + 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" - minimatch "^3.0.4" - object.values "^1.1.0" - read-pkg-up "^2.0.0" - resolve "^1.12.0" + 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" -eslint-plugin-jest@~23.8.2: - version "23.8.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz#6f28b41c67ef635f803ebd9e168f6b73858eb8d4" - integrity sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg== +eslint-plugin-jest@^27.2.1: + version "27.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz#be4ded5f91905d9ec89aa8968d39c71f3b072c0c" + integrity sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw== dependencies: - "@typescript-eslint/experimental-utils" "^2.5.0" + "@typescript-eslint/utils" "^5.10.0" -eslint-plugin-node@~11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" - integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== +eslint-plugin-n@^15.7.0: + version "15.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz#e29221d8f5174f84d18f2eb94765f2eeea033b90" + integrity sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q== dependencies: - eslint-plugin-es "^3.0.0" - eslint-utils "^2.0.0" + builtins "^5.0.1" + eslint-plugin-es "^4.1.0" + eslint-utils "^3.0.0" ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" + is-core-module "^2.11.0" + minimatch "^3.1.2" + resolve "^1.22.1" + semver "^7.3.8" -eslint-plugin-prettier@~3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" - integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== +eslint-plugin-prettier@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-promise@~4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" - integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== +eslint-plugin-promise@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816" + integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig== -eslint-plugin-standard@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" - integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== - -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-plugin-security@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz#0e9c4a471f6e4d3ca16413c7a4a51f3966ba16e4" + integrity sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ== dependencies: - esrecurse "^4.1.0" + safe-regex "^2.1.1" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: - eslint-visitor-keys "^1.1.0" + esrecurse "^4.3.0" + estraverse "^5.2.0" eslint-utils@^2.0.0: version "2.0.0" @@ -4616,87 +5186,111 @@ eslint-utils@^2.0.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@~6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@^8.37.0: + version "8.43.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094" + integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q== dependencies: - "@babel/code-frame" "^7.0.0" + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.43.0" + "@humanwhocodes/config-array" "^0.11.10" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" + 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" + graphemer "^1.4.0" + ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" - js-yaml "^3.13.1" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" + optionator "^0.9.1" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" text-table "^0.2.0" - v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== dependencies: - acorn "^7.1.0" - acorn-jsx "^5.1.0" - eslint-visitor-keys "^1.1.0" + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4776,6 +5370,21 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +execa@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" + integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== + 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" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -4794,16 +5403,15 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.4.2.tgz#2ae34eb88de797c64a1541ad0f1e2ea8a7a7b492" - integrity sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ== +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== dependencies: - "@jest/expect-utils" "^29.4.2" - jest-get-type "^29.4.2" - jest-matcher-utils "^29.4.2" - jest-message-util "^29.4.2" - jest-util "^29.4.2" + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" express@^4.0.0, express@^4.17.1: version "4.17.1" @@ -4866,15 +5474,6 @@ extendable-error@^0.1.5: resolved "https://registry.yarnpkg.com/extendable-error/-/extendable-error-0.1.5.tgz#122308a7097bc89a263b2c4fbf089c78140e3b6d" integrity sha1-EiMIpwl7yJomOyxPvwiceBQOO20= -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -4909,7 +5508,7 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w== -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -4930,12 +5529,23 @@ fast-glob@^3.1.1: merge2 "^1.3.0" micromatch "^4.0.2" -fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + 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" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -4961,12 +5571,12 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" file-extension@~4.0.5: version "4.0.5" @@ -5012,13 +5622,6 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -5034,25 +5637,39 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + locate-path "^6.0.0" + path-exists "^4.0.0" -flatted@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== fn-name@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c" integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -5166,10 +5783,20 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functions-have-names@^1.2.2, functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gauge@^4.0.3: version "4.0.4" @@ -5214,16 +5841,21 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -5243,11 +5875,26 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" -get-stream@^6.0.0: +get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-tsconfig@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.6.0.tgz#e977690993a42f3e320e932427502a40f7af6d05" + integrity sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg== + dependencies: + resolve-pkg-maps "^1.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -5278,13 +5925,27 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: +glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== dependencies: is-glob "^4.0.1" +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob@^7.0.0: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -5297,7 +5958,7 @@ glob@^7.0.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -5332,12 +5993,19 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^12.1.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" - integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== dependencies: - type-fest "^0.8.1" + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" globby@11.0.0: version "11.0.0" @@ -5351,6 +6019,36 @@ globby@11.0.0: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + 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" + +globby@^13.1.3: + version "13.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.0.tgz#7dd5678d765c4680c2e6d106230d86cb727cb1af" + integrity sha512-jWsQfayf13NvqKUIL3Ta+CIqMnvlaIDFveWE/dpOZ9+3AMEJozsxDvKA02zync9UuvOM8rOXzsD5GqKP4OnWPQ== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^4.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -5400,6 +6098,16 @@ graceful-fs@^4.2.6: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + graphql-auth-directives@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/graphql-auth-directives/-/graphql-auth-directives-2.1.0.tgz#85b83817844e2ec5fba8fe5de444287d6dd0f85a" @@ -5516,6 +6224,11 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" @@ -5531,11 +6244,35 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -5608,10 +6345,12 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hosted-git-info@^2.1.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" - integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" html-encoding-sniffer@^3.0.0: version "3.0.0" @@ -5709,6 +6448,15 @@ http-errors@^1.7.3, http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -5764,6 +6512,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -5771,7 +6524,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5807,16 +6560,16 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - ignore@^5.1.1, ignore@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + image-extensions@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/image-extensions/-/image-extensions-1.1.0.tgz#b8e6bf6039df0056e333502a00b6637a3105d894" @@ -5830,6 +6583,14 @@ import-fresh@^3.0.0: parent-module "^1.0.0" resolve-from "^4.0.0" +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -5891,25 +6652,6 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inquirer@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" - integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== - dependencies: - ansi-escapes "^4.2.1" - chalk "^2.4.2" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^4.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - insane@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/insane/-/insane-2.6.1.tgz#c7dcae7b51c20346883b71078fad6ce0483c198f" @@ -5923,6 +6665,15 @@ install-artifact-from-github@^1.3.3: resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.3.tgz#57d89bacfa0f47d7307fe41b6247cda9f9a8079c" integrity sha512-x79SL0d8WOi1ZjXSTUqqs0GPQZ92YArJAN9O46wgU9wdH2U9ecyyhB9YGDbPe2OLV4ptmt6AZYRQZ2GydQZosQ== +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -5989,11 +6740,27 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -6008,11 +6775,24 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-callable@^1.1.3, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + is-callable@^1.1.4, is-callable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" @@ -6032,6 +6812,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -6076,6 +6863,16 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -6134,6 +6931,20 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-installed-globally@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" @@ -6147,11 +6958,23 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -6176,6 +6999,11 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -6188,11 +7016,6 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -6212,6 +7035,14 @@ is-regex@^1.1.0: dependencies: has-symbols "^1.0.1" +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-relative-url@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-relative-url/-/is-relative-url-2.0.0.tgz#72902d7fe04b3d4792e7db15f9db84b7204c9cef" @@ -6231,6 +7062,13 @@ is-retry-allowed@^1.0.0: resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -6241,6 +7079,18 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + is-symbol@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -6248,6 +7098,24 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + 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-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -6269,11 +7137,25 @@ is-uri@~1.2.4: parse-uri "~1.0.3" punycode2 "~1.0.0" +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -6368,129 +7250,145 @@ iterall@^1.1.3, iterall@^1.2.1, iterall@^1.2.2, iterall@^1.3.0: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== -jest-changed-files@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.4.2.tgz#bee1fafc8b620d6251423d1978a0080546bc4376" - integrity sha512-Qdd+AXdqD16PQa+VsWJpxR3kN0JyOCX1iugQfx5nUgAsI4gwsKviXkpclxOK9ZnwaY2IQVHz+771eAvqeOlfuw== +jest-changed-files@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" + integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== dependencies: + "@jest/types" "^27.5.1" execa "^5.0.0" - p-limit "^3.1.0" + throat "^6.0.1" -jest-circus@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.4.2.tgz#2d00c04baefd0ee2a277014cd494d4b5970663ed" - integrity sha512-wW3ztp6a2P5c1yOc1Cfrt5ozJ7neWmqeXm/4SYiqcSriyisgq63bwFj1NuRdSR5iqS0CMEYwSZd89ZA47W9zUg== +jest-circus@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" + integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== dependencies: - "@jest/environment" "^29.4.2" - "@jest/expect" "^29.4.2" - "@jest/test-result" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" + expect "^27.5.1" is-generator-fn "^2.0.0" - jest-each "^29.4.2" - jest-matcher-utils "^29.4.2" - jest-message-util "^29.4.2" - jest-runtime "^29.4.2" - jest-snapshot "^29.4.2" - jest-util "^29.4.2" - p-limit "^3.1.0" - pretty-format "^29.4.2" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" slash "^3.0.0" stack-utils "^2.0.3" + throat "^6.0.1" -jest-cli@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.4.2.tgz#94a2f913a0a7a49d11bee98ad88bf48baae941f4" - integrity sha512-b+eGUtXq/K2v7SH3QcJvFvaUaCDS1/YAZBYz0m28Q/Ppyr+1qNaHmVYikOrbHVbZqYQs2IeI3p76uy6BWbXq8Q== +jest-cli@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" + integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== dependencies: - "@jest/core" "^29.4.2" - "@jest/test-result" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/core" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^29.4.2" - jest-util "^29.4.2" - jest-validate "^29.4.2" + jest-config "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" prompts "^2.0.1" - yargs "^17.3.1" + yargs "^16.2.0" -jest-config@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.4.2.tgz#15386dd9ed2f7059516915515f786b8836a98f07" - integrity sha512-919CtnXic52YM0zW4C1QxjG6aNueX1kBGthuMtvFtRTAxhKfJmiXC9qwHmi6o2josjbDz8QlWyY55F1SIVmCWA== +jest-config@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" + integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.4.2" - "@jest/types" "^29.4.2" - babel-jest "^29.4.2" + "@babel/core" "^7.8.0" + "@jest/test-sequencer" "^27.5.1" + "@jest/types" "^27.5.1" + babel-jest "^27.5.1" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" - glob "^7.1.3" + glob "^7.1.1" graceful-fs "^4.2.9" - jest-circus "^29.4.2" - jest-environment-node "^29.4.2" - jest-get-type "^29.4.2" - jest-regex-util "^29.4.2" - jest-resolve "^29.4.2" - jest-runner "^29.4.2" - jest-util "^29.4.2" - jest-validate "^29.4.2" + jest-circus "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-get-type "^27.5.1" + jest-jasmine2 "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runner "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^29.4.2" + pretty-format "^27.5.1" slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.4.2.tgz#b88502d5dc02d97f6512d73c37da8b36f49b4871" - integrity sha512-EK8DSajVtnjx9sa1BkjZq3mqChm2Cd8rIzdXkQMA8e0wuXq53ypz6s5o5V8HRZkoEt2ywJ3eeNWFKWeYr8HK4g== +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== dependencies: chalk "^4.0.0" - diff-sequences "^29.4.2" - jest-get-type "^29.4.2" - pretty-format "^29.4.2" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-docblock@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.2.tgz#c78a95eedf9a24c0a6cc16cf2abdc4b8b0f2531b" - integrity sha512-dV2JdahgClL34Y5vLrAHde3nF3yo2jKRH+GIYJuCpfqwEJZcikzeafVTGAjbOfKPG17ez9iWXwUYp7yefeCRag== +jest-docblock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" + integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== dependencies: detect-newline "^3.0.0" -jest-each@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.4.2.tgz#e1347aff1303f4c35470827a62c029d389c5d44a" - integrity sha512-trvKZb0JYiCndc55V1Yh0Luqi7AsAdDWpV+mKT/5vkpnnFQfuQACV72IoRV161aAr6kAVIBpmYzwhBzm34vQkA== +jest-each@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" + integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^27.5.1" chalk "^4.0.0" - jest-get-type "^29.4.2" - jest-util "^29.4.2" - pretty-format "^29.4.2" + jest-get-type "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" -jest-environment-node@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.4.2.tgz#0eab835b41e25fd0c1a72f62665fc8db08762ad2" - integrity sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w== +jest-environment-jsdom@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" + integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== dependencies: - "@jest/environment" "^29.4.2" - "@jest/fake-timers" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" - jest-mock "^29.4.2" - jest-util "^29.4.2" + jest-mock "^27.5.1" + jest-util "^27.5.1" + jsdom "^16.6.0" -jest-get-type@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.2.tgz#7cb63f154bca8d8f57364d01614477d466fa43fe" - integrity sha512-vERN30V5i2N6lqlFu4ljdTqQAgrkTFMC9xaIIfOPYBw04pufjXRty5RuXBiB1d72tGbURa/UgoiHB90ruOSivg== +jest-environment-node@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" + integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== jest-haste-map@^25.2.6: version "25.2.6" @@ -6511,66 +7409,89 @@ jest-haste-map@^25.2.6: optionalDependencies: fsevents "^2.1.2" -jest-haste-map@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.4.2.tgz#9112df3f5121e643f1b2dcbaa86ab11b0b90b49a" - integrity sha512-WkUgo26LN5UHPknkezrBzr7lUtV1OpGsp+NfXbBwHztsFruS3gz+AMTTBcEklvi8uPzpISzYjdKXYZQJXBnfvw== +jest-haste-map@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" + integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== dependencies: - "@jest/types" "^29.4.2" - "@types/graceful-fs" "^4.1.3" + "@jest/types" "^27.5.1" + "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.9" - jest-regex-util "^29.4.2" - jest-util "^29.4.2" - jest-worker "^29.4.2" + jest-regex-util "^27.5.1" + jest-serializer "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" micromatch "^4.0.4" - walker "^1.0.8" + walker "^1.0.7" optionalDependencies: fsevents "^2.3.2" -jest-leak-detector@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.4.2.tgz#8f05c6680e0cb46a1d577c0d3da9793bed3ea97b" - integrity sha512-Wa62HuRJmWXtX9F00nUpWlrbaH5axeYCdyRsOs/+Rb1Vb6+qWTlB5rKwCCRKtorM7owNwKsyJ8NRDUcZ8ghYUA== +jest-jasmine2@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" + integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== dependencies: - jest-get-type "^29.4.2" - pretty-format "^29.4.2" + "@jest/environment" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + throat "^6.0.1" -jest-matcher-utils@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.4.2.tgz#08d0bf5abf242e3834bec92c7ef5071732839e85" - integrity sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg== +jest-leak-detector@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" + integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== + dependencies: + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== dependencies: chalk "^4.0.0" - jest-diff "^29.4.2" - jest-get-type "^29.4.2" - pretty-format "^29.4.2" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-message-util@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.2.tgz#309a2924eae6ca67cf7f25781a2af1902deee717" - integrity sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g== +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.4.2" + "@jest/types" "^27.5.1" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^29.4.2" + pretty-format "^27.5.1" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.4.2.tgz#e1054be66fb3e975d26d4528fcde6979e4759de8" - integrity sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g== +jest-mock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^27.5.1" "@types/node" "*" - jest-util "^29.4.2" jest-pnp-resolver@^1.2.2: version "1.2.3" @@ -6582,87 +7503,88 @@ jest-regex-util@^25.2.6: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.2.6.tgz#d847d38ba15d2118d3b06390056028d0f2fd3964" integrity sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw== -jest-regex-util@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.2.tgz#19187cca35d301f8126cf7a021dd4dcb7b58a1ca" - integrity sha512-XYZXOqUl1y31H6VLMrrUL1ZhXuiymLKPz0BO1kEeR5xER9Tv86RZrjTm74g5l9bPJQXA/hyLdaVPN/sdqfteig== +jest-regex-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== -jest-resolve-dependencies@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.2.tgz#6359db606f5967b68ca8bbe9dbc07a4306c12bf7" - integrity sha512-6pL4ptFw62rjdrPk7rRpzJYgcRqRZNsZTF1VxVTZMishbO6ObyWvX57yHOaNGgKoADtAHRFYdHQUEvYMJATbDg== +jest-resolve-dependencies@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" + integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== dependencies: - jest-regex-util "^29.4.2" - jest-snapshot "^29.4.2" + "@jest/types" "^27.5.1" + jest-regex-util "^27.5.1" + jest-snapshot "^27.5.1" -jest-resolve@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.4.2.tgz#8831f449671d08d161fe493003f61dc9b55b808e" - integrity sha512-RtKWW0mbR3I4UdkOrW7552IFGLYQ5AF9YrzD0FnIOkDu0rAMlA5/Y1+r7lhCAP4nXSBTaE7ueeqj6IOwZpgoqw== +jest-resolve@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" + integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== dependencies: + "@jest/types" "^27.5.1" chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^29.4.2" + jest-haste-map "^27.5.1" jest-pnp-resolver "^1.2.2" - jest-util "^29.4.2" - jest-validate "^29.4.2" + jest-util "^27.5.1" + jest-validate "^27.5.1" resolve "^1.20.0" - resolve.exports "^2.0.0" + resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.4.2.tgz#2bcecf72303369df4ef1e6e983c22a89870d5125" - integrity sha512-wqwt0drm7JGjwdH+x1XgAl+TFPH7poowMguPQINYxaukCqlczAcNLJiK+OLxUxQAEWMdy+e6nHZlFHO5s7EuRg== +jest-runner@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" + integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== dependencies: - "@jest/console" "^29.4.2" - "@jest/environment" "^29.4.2" - "@jest/test-result" "^29.4.2" - "@jest/transform" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/console" "^27.5.1" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" - emittery "^0.13.1" + emittery "^0.8.1" graceful-fs "^4.2.9" - jest-docblock "^29.4.2" - jest-environment-node "^29.4.2" - jest-haste-map "^29.4.2" - jest-leak-detector "^29.4.2" - jest-message-util "^29.4.2" - jest-resolve "^29.4.2" - jest-runtime "^29.4.2" - jest-util "^29.4.2" - jest-watcher "^29.4.2" - jest-worker "^29.4.2" - p-limit "^3.1.0" - source-map-support "0.5.13" + jest-docblock "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-haste-map "^27.5.1" + jest-leak-detector "^27.5.1" + jest-message-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runtime "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + source-map-support "^0.5.6" + throat "^6.0.1" -jest-runtime@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.4.2.tgz#d86b764c5b95d76cb26ed1f32644e99de5d5c134" - integrity sha512-3fque9vtpLzGuxT9eZqhxi+9EylKK/ESfhClv4P7Y9sqJPs58LjVhTt8jaMp/pRO38agll1CkSu9z9ieTQeRrw== +jest-runtime@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" + integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== dependencies: - "@jest/environment" "^29.4.2" - "@jest/fake-timers" "^29.4.2" - "@jest/globals" "^29.4.2" - "@jest/source-map" "^29.4.2" - "@jest/test-result" "^29.4.2" - "@jest/transform" "^29.4.2" - "@jest/types" "^29.4.2" - "@types/node" "*" + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/globals" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" + execa "^5.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^29.4.2" - jest-message-util "^29.4.2" - jest-mock "^29.4.2" - jest-regex-util "^29.4.2" - jest-resolve "^29.4.2" - jest-snapshot "^29.4.2" - jest-util "^29.4.2" - semver "^7.3.5" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" slash "^3.0.0" strip-bom "^4.0.0" @@ -6673,35 +7595,41 @@ jest-serializer@^25.2.6: dependencies: graceful-fs "^4.2.4" -jest-snapshot@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.4.2.tgz#ba1fb9abb279fd2c85109ff1757bc56b503bbb3a" - integrity sha512-PdfubrSNN5KwroyMH158R23tWcAXJyx4pvSvWls1dHoLCaUhGul9rsL3uVjtqzRpkxlkMavQjGuWG1newPgmkw== +jest-serializer@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== dependencies: - "@babel/core" "^7.11.6" + "@types/node" "*" + graceful-fs "^4.2.9" + +jest-snapshot@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" + integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== + dependencies: + "@babel/core" "^7.7.2" "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.4.2" - "@jest/transform" "^29.4.2" - "@jest/types" "^29.4.2" - "@types/babel__traverse" "^7.0.6" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^29.4.2" + expect "^27.5.1" graceful-fs "^4.2.9" - jest-diff "^29.4.2" - jest-get-type "^29.4.2" - jest-haste-map "^29.4.2" - jest-matcher-utils "^29.4.2" - jest-message-util "^29.4.2" - jest-util "^29.4.2" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + jest-haste-map "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-util "^27.5.1" natural-compare "^1.4.0" - pretty-format "^29.4.2" - semver "^7.3.5" + pretty-format "^27.5.1" + semver "^7.3.2" jest-util@^25.2.6: version "25.2.6" @@ -6713,42 +7641,41 @@ jest-util@^25.2.6: is-ci "^2.0.0" make-dir "^3.0.0" -jest-util@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.2.tgz#3db8580b295df453a97de4a1b42dd2578dabd2c2" - integrity sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g== +jest-util@^27.0.0, jest-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.4.2.tgz#3b3f8c4910ab9a3442d2512e2175df6b3f77b915" - integrity sha512-tto7YKGPJyFbhcKhIDFq8B5od+eVWD/ySZ9Tvcp/NGCvYA4RQbuzhbwYWtIjMT5W5zA2W0eBJwu4HVw34d5G6Q== +jest-validate@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" + integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== dependencies: - "@jest/types" "^29.4.2" + "@jest/types" "^27.5.1" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^29.4.2" + jest-get-type "^27.5.1" leven "^3.1.0" - pretty-format "^29.4.2" + pretty-format "^27.5.1" -jest-watcher@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.4.2.tgz#09c0f4c9a9c7c0807fcefb1445b821c6f7953b7c" - integrity sha512-onddLujSoGiMJt+tKutehIidABa175i/Ays+QvKxCqBwp7fvxP3ZhKsrIdOodt71dKxqk4sc0LN41mWLGIK44w== +jest-watcher@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" + integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== dependencies: - "@jest/test-result" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.4.2" + jest-util "^27.5.1" string-length "^4.0.1" jest-worker@^25.2.6: @@ -6759,25 +7686,23 @@ jest-worker@^25.2.6: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.4.2.tgz#d9b2c3bafc69311d84d94e7fb45677fc8976296f" - integrity sha512-VIuZA2hZmFyRbchsUCHEehoSf2HEl0YVF8SDJqtPnKorAaBuh42V8QsLnde0XP5F6TyCynGPEGgBOn3Fc+wZGw== +jest-worker@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" - jest-util "^29.4.2" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@29.4: - version "29.4.2" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.4.2.tgz#4c2127d03a71dc187f386156ef155dbf323fb7be" - integrity sha512-+5hLd260vNIHu+7ZgMIooSpKl7Jp5pHKb51e73AJU3owd5dEo/RfVwHbA/na3C/eozrt3hJOLGf96c7EWwIAzg== +jest@^27.2.4: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" + integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== dependencies: - "@jest/core" "^29.4.2" - "@jest/types" "^29.4.2" + "@jest/core" "^27.5.1" import-local "^3.0.2" - jest-cli "^29.4.2" + jest-cli "^27.5.1" jmespath@0.15.0: version "0.15.0" @@ -6802,11 +7727,51 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + jsdom@~22.1.0: version "22.1.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-22.1.0.tgz#0fca6d1a37fbeb7f4aac93d1090d782c56b611c8" @@ -6876,11 +7841,18 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^2.1.2, json5@^2.2.2: +json5@2.x, json5@^2.1.2, json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + jsonwebtoken@^8.3.0, jsonwebtoken@~8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" @@ -6991,7 +7963,15 @@ levenary@^1.1.1: dependencies: leven "^3.1.0" -levn@^0.3.0, levn@~0.3.0: +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== @@ -7013,24 +7993,6 @@ linkifyjs@~2.1.8: react "^16.4.2" react-dom "^16.4.2" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -7046,6 +8008,13 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash-es@^4.17.11: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" @@ -7101,6 +8070,16 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.mergewith@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" @@ -7116,11 +8095,6 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== -lodash.unescape@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" - integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= - lodash@4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -7131,7 +8105,7 @@ lodash@^4.15.0, lodash@^4.17.14, lodash@~4.17.11, lodash@~4.17.14: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.13, lodash@^4.17.15, lodash@~4.17.21: +lodash@^4.17.13, lodash@^4.17.15, lodash@^4.7.0, lodash@~4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7229,7 +8203,7 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -make-error@^1.1.1: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -7309,6 +8283,11 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== +merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + metascraper-audio@^5.34.4: version "5.34.4" resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.34.4.tgz#84437c3962a9186cda69510229f6b68e6a25563a" @@ -7467,19 +8446,19 @@ microsoft-capitalize@~1.0.5: resolved "https://registry.yarnpkg.com/microsoft-capitalize/-/microsoft-capitalize-1.0.5.tgz#bcaf915039f14224c8cfd74c31cea42fecacbb31" integrity sha512-iqDMU9J643BHg8Zp7EMZNLTp6Pgs2f1S2SMnCW2VlUqMs17xCZ5vwVjalBJEGVcUfG+/1ePqeEGcMW3VfzHK5A== -migrate@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/migrate/-/migrate-1.7.0.tgz#23fb97aa33145788030a1a91187a0ee32a49acbf" - integrity sha512-I63YykITgWyI+ET4KO8xGePYkR9U7CtSe/RrR13vLbZSpUcAh4/ry2GswNv7Lywcsp3BaDHj7YdjC7ihVYCFmw== +migrate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/migrate/-/migrate-2.0.0.tgz#eef68ac206f658d96ddfaf81c8c5999d71694956" + integrity sha512-Oklla7q1Ok3UZZOGL67wkFlKfZHAxdT7NusHwHgzPBfokbCvYDEEGM8Bx7G5jDuoRNiA7R261Y2CwZX0cyx9CQ== dependencies: - chalk "^2.4.1" - commander "^2.19.0" - dateformat "^3.0.3" - dotenv "^6.1.0" + chalk "^4.1.2" + commander "^2.20.3" + dateformat "^4.6.3" + dotenv "^16.0.0" inherits "^2.0.3" - minimatch "^3.0.4" - mkdirp "^0.5.1" - slug "^0.9.2" + minimatch "^9.0.1" + mkdirp "^3.0.1" + slug "^8.2.2" mime-db@1.43.0: version "1.43.0" @@ -7520,6 +8499,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + mimic-fn@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b" @@ -7547,7 +8531,7 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimatch@^3.1.1: +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -7561,12 +8545,19 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" + integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== + dependencies: + brace-expansion "^2.0.1" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -7674,6 +8665,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + moment@2.21.0: version "2.21.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" @@ -7704,11 +8700,6 @@ mustache@^4.2.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - mz@^2.4.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -7745,6 +8736,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -7956,16 +8952,6 @@ nopt@~1.0.10: dependencies: abbrev "1" -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -8015,6 +9001,13 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -8054,6 +9047,11 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= +nwsapi@^2.2.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.5.tgz#a52744c61b3889dd44b0a158687add39b8d935e2" + integrity sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ== + nwsapi@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.4.tgz#fd59d5e904e8e1f03c25a7d5a15cfa16c714a1e5" @@ -8083,6 +9081,11 @@ object-hash@^2.0.3: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" @@ -8115,6 +9118,16 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -8138,15 +9151,14 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: - define-properties "^1.1.3" - es-abstract "^1.12.0" - function-bind "^1.1.1" - has "^1.0.3" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" on-finished@~2.3.0: version "2.3.0" @@ -8162,13 +9174,30 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + optimism@^0.10.0: version "0.10.2" resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.10.2.tgz#626b6fd28b0923de98ecb36a3fd2d3d4e5632dd9" @@ -8176,7 +9205,7 @@ optimism@^0.10.0: dependencies: "@wry/context" "^0.4.0" -optionator@^0.8.3: +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -8188,12 +9217,24 @@ optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + 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" + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -8216,13 +9257,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" @@ -8237,20 +9271,13 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -8265,7 +9292,7 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-locate@~5.0.0: +p-locate@^5.0.0, p-locate@~5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== @@ -8284,11 +9311,6 @@ p-reflect@~2.1.0: resolved "https://registry.yarnpkg.com/p-reflect/-/p-reflect-2.1.0.tgz#5d67c7b3c577c4e780b9451fc9129675bd99fe67" integrity sha512-paHV8NUz8zDHu5lhr/ngGWQiW067DK/+IbJ+RfZ4k+s8y4EKyYCz8pGYWjxCg35eHztpJAt+NUgvN4L+GCbPlg== -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -8318,13 +9340,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -8358,6 +9373,11 @@ parse5-htmlparser2-tree-adapter@^7.0.0: domhandler "^5.0.2" parse5 "^7.0.0" +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + parse5@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" @@ -8425,6 +9445,11 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -8435,13 +9460,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -8467,11 +9485,6 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -8494,13 +9507,6 @@ pirates@^4.0.1, pirates@^4.0.4: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -8529,6 +9535,11 @@ postcss@^7.0.27: source-map "^0.6.1" supports-color "^6.1.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -8546,19 +9557,19 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" - integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== +prettier@^2.8.7: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== -pretty-format@^29.4.2: - version "29.4.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.2.tgz#64bf5ccc0d718c03027d94ac957bdd32b3fb2401" - integrity sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg== +pretty-format@^27.0.0, pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== dependencies: - "@jest/schemas" "^29.4.2" + ansi-regex "^5.0.1" ansi-styles "^5.0.0" - react-is "^18.0.0" + react-is "^17.0.1" private@^0.1.8: version "0.1.8" @@ -8743,10 +9754,10 @@ react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== react@^16.4.2: version "16.9.0" @@ -8757,23 +9768,6 @@ react@^16.4.2: object-assign "^4.1.1" prop-types "^15.6.2" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - readable-stream@^2.0.2, readable-stream@^2.0.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -8888,10 +9882,19 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexp-tree@~0.1.1: + version "0.1.27" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" + integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== + +regexp.prototype.flags@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" regexpp@^3.0.0: version "3.0.0" @@ -9034,17 +10037,22 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== -resolve.exports@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" - integrity sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg== +resolve.exports@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" + integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.3, resolve@^1.5.0: +resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.3: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== @@ -9060,6 +10068,15 @@ resolve@^1.20.0, resolve@^1.3.2: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + responselike@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" @@ -9067,14 +10084,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -9090,13 +10099,6 @@ reusify@^1.0.0: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@^2.6.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -9104,7 +10106,7 @@ rimraf@^2.6.1: dependencies: glob "^7.1.3" -rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -9126,25 +10128,18 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== dependencies: - is-promise "^2.1.0" + execa "^5.0.0" run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== -rxjs@^6.4.0: - version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== - dependencies: - tslib "^1.9.0" - rxjs@^6.6.3: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" @@ -9167,6 +10162,15 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -9174,6 +10178,13 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" +safe-regex@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" + integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== + dependencies: + regexp-tree "~0.1.1" + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -9220,6 +10231,13 @@ sax@>=0.6.0, sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + saxes@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" @@ -9247,21 +10265,35 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - semver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: +semver@7.x: + version "7.5.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec" + integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw== + dependencies: + lru-cache "^6.0.0" + +semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.0.0, semver@^7.3.2, semver@^7.3.7, semver@^7.3.8: + version "7.5.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb" + integrity sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ== + dependencies: + lru-cache "^6.0.0" + semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" @@ -9357,6 +10389,15 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -9377,21 +10418,15 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -slug@^0.9.2: - version "0.9.4" - resolved "https://registry.yarnpkg.com/slug/-/slug-0.9.4.tgz#fad5f1ef33150830c7688cd8500514576eccabd8" - integrity sha512-3YHq0TeJ4+AIFbJm+4UWSQs5A1mmeWOTQqydW3OoPmQfNKxlO96NDRTIrp+TBkmvEsEFrd+Z/LXw8OD/6OlZ5g== - dependencies: - unicode ">= 0.3.1" +slug@^8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/slug/-/slug-8.2.2.tgz#33b019a857a11fc4773c1e9a9f60e3da651a9e5d" + integrity sha512-5ByW6qXqPeG0Tmlkh24JhdXhvQsbaJSjVr3GgGxUV0BSskZKKBZZfFWxezap8+fh1vxBN9GVbqI1V6nqAFxlBg== slug@~6.0.0: version "6.0.0" @@ -9471,14 +10506,6 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@^0.5.16: version "0.5.16" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" @@ -9487,6 +10514,14 @@ source-map-support@^0.5.16: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" @@ -9502,36 +10537,15 @@ source-map@^0.5.0, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -9675,14 +10689,14 @@ string-width@^1.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" string.prototype.trimend@^1.0.1: version "1.0.1" @@ -9692,21 +10706,14 @@ string.prototype.trimend@^1.0.1: define-properties "^1.1.3" es-abstract "^1.17.5" -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" string.prototype.trimstart@^1.0.1: version "1.0.1" @@ -9716,6 +10723,15 @@ string.prototype.trimstart@^1.0.1: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -9744,13 +10760,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -9778,12 +10787,12 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== -strip-json-comments@^3.1.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -9839,6 +10848,14 @@ supports-color@^8.0.0: dependencies: has-flag "^4.0.0" +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -9859,15 +10876,18 @@ synchronous-promise@^2.0.10: resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.10.tgz#e64c6fd3afd25f423963353043f4a68ebd397fd8" integrity sha512-6PC+JRGmNjiG3kJ56ZMNWDPL8hjyghF5cMXIFOKg+NiwwEZZIvxTWd0pinWKyD227odg9ygF8xVhhz7gb8Uq7A== -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +synckit@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" + integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + "@pkgr/utils" "^2.3.1" + tslib "^2.5.0" + +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== tar@^4: version "4.4.10" @@ -9901,6 +10921,14 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -9929,10 +10957,10 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +throat@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe" + integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ== timed-out@^4.0.0: version "4.0.1" @@ -9962,6 +10990,11 @@ titleize@1.0.0: resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.0.tgz#7d350722061830ba6617631e0cfd3ea08398d95a" integrity sha1-fTUHIgYYMLpmF2MeDP0+oIOY2Vo= +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + tlds@^1.187.0: version "1.203.1" resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.203.1.tgz#4dc9b02f53de3315bc98b80665e13de3edfc1dfc" @@ -9984,13 +11017,6 @@ tldts@~6.0.1: dependencies: tldts-core "^6.0.3" -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -10050,6 +11076,16 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" +tough-cookie@^4.0.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tough-cookie@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" @@ -10068,6 +11104,13 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + tr46@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" @@ -10115,6 +11158,20 @@ ts-invariant@^0.4.0: dependencies: tslib "^1.9.3" +ts-jest@^27.0.5: + version "27.1.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.5.tgz#0ddf1b163fbaae3d5b7504a1e65c914a95cff297" + integrity sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^27.0.0" + json5 "2.x" + lodash.memoize "4.x" + make-error "1.x" + semver "7.x" + yargs-parser "20.x" + ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -10134,16 +11191,38 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +tsconfig-paths@^3.14.1: + version "3.14.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + tslib@1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== -tslib@^1.10.0, tslib@^1.11.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -10156,6 +11235,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -10168,6 +11254,11 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -10178,11 +11269,6 @@ type-fest@^0.3.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - type-is@^1.6.16, type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -10196,6 +11282,15 @@ type@^1.0.1: resolved "https://registry.yarnpkg.com/type/-/type-1.0.3.tgz#16f5d39f27a2d28d86e48f8981859e9d3296c179" integrity sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg== +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -10203,10 +11298,20 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" - integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +typescript@^4.9.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" undefsafe@^2.0.2: version "2.0.2" @@ -10243,11 +11348,6 @@ unicode-property-aliases-ecmascript@^1.0.4: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== -"unicode@>= 0.3.1": - version "11.0.1" - resolved "https://registry.yarnpkg.com/unicode/-/unicode-11.0.1.tgz#735bd422ec75cf28d396eb224d535d168d5f1db6" - integrity sha512-+cHtykLb+eF1yrSLWTwcYBrqJkTfX7Quoyg7Juhe6uylF43ZbMdxMuSHNYlnyLT8T7POAvavgBthzUF9AIaQvQ== - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -10304,6 +11404,11 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" @@ -10456,19 +11561,14 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== - -v8-to-istanbul@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" - integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== +v8-to-istanbul@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== dependencies: - "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" + source-map "^0.7.3" v8flags@^3.1.1: version "3.1.3" @@ -10477,14 +11577,6 @@ v8flags@^3.1.1: dependencies: homedir-polyfill "^1.0.1" -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - validator@^13.9.0: version "13.9.0" resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" @@ -10514,6 +11606,20 @@ video-extensions@~1.2.0: resolved "https://registry.yarnpkg.com/video-extensions/-/video-extensions-1.2.0.tgz#62f449f403b853f02da40964cbf34143f7d96731" integrity sha512-TriMl18BHEsh2KuuSA065tbu4SNAC9fge7k8uKoTTofTq89+Xsg4K1BGbmSVETwUZhqSjd9KwRCNwXAW/buXMg== +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + w3c-xmlserializer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" @@ -10521,18 +11627,35 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" -walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: +walker@^1.0.7, walker@~1.0.5: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: makeerror "1.0.12" +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + whatwg-encoding@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" @@ -10540,6 +11663,11 @@ whatwg-encoding@^2.0.0: dependencies: iconv-lite "0.6.3" +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + whatwg-mimetype@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" @@ -10553,6 +11681,38 @@ whatwg-url@^12.0.0, whatwg-url@^12.0.1: tr46 "^4.1.1" webidl-conversions "^7.0.0" +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + 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" + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -10596,7 +11756,7 @@ widest-line@^2.0.0: dependencies: string-width "^2.1.1" -word-wrap@~1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -10634,21 +11794,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - "ws@^5.2.0 || ^6.0.0 || ^7.0.0": version "7.5.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" @@ -10661,6 +11806,11 @@ ws@^6.0.0: dependencies: async-limiter "~1.0.0" +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + ws@^8.13.0: version "8.13.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" @@ -10671,6 +11821,11 @@ xdg-basedir@^3.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + xml-name-validator@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" @@ -10739,23 +11894,23 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-parser@20.x, yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs@^17.3.1: - version "17.6.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: - cliui "^8.0.1" + cliui "^7.0.2" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.3" + string-width "^4.2.0" y18n "^5.0.5" - yargs-parser "^21.1.1" + yargs-parser "^20.2.2" yn@3.1.1: version "3.1.1" diff --git a/cypress/create-cucumber-html-report.js b/cypress/create-cucumber-html-report.js new file mode 100644 index 000000000..9720f4281 --- /dev/null +++ b/cypress/create-cucumber-html-report.js @@ -0,0 +1,12 @@ +const report = require("multiple-cucumber-html-reporter"); + +const reportTitle = "Ocelot webapp end-to-end test report" + +report.generate({ + jsonDir: "reports/json_logs", + reportPath: "./reports/cucumber_html_report", + pageTitle: reportTitle, + reportName: reportTitle, + pageFooter: "
", + hideMetadata: true +}); \ No newline at end of file diff --git a/cypress/cypress.config.js b/cypress/cypress.config.js index 2d2cefc47..b1d80575e 100644 --- a/cypress/cypress.config.js +++ b/cypress/cypress.config.js @@ -21,13 +21,7 @@ async function setupNodeEvents(on, config) { return testStore[name] }, }); - - on("after:run", (results) => { - if (results) { - console.log(results.status); - } - }); - + return config; } @@ -42,10 +36,7 @@ module.exports = defineConfig({ baseUrl: "http://localhost:3000", specPattern: "cypress/e2e/**/*.feature", supportFile: "cypress/support/e2e.js", - retries: { - runMode: 2, - openMode: 0, - }, + retries: 0, video: false, setupNodeEvents, }, diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 88836b4f1..92e8bf1f7 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -13,9 +13,8 @@ // Cypress.Commands.add('login', (email, password) => { ... }) /* globals Cypress cy */ -import "cypress-file-upload"; import { GraphQLClient, request } from 'graphql-request' -import CONFIG from '../../backend/src/config' +import CONFIG from '../../backend/build/src/config' const authenticatedHeaders = (variables) => { const mutation = ` diff --git a/cypress/support/factories.js b/cypress/support/factories.js index b08d83526..a901d867f 100644 --- a/cypress/support/factories.js +++ b/cypress/support/factories.js @@ -1,9 +1,9 @@ -import Factory from '../../backend/src/db/factories' -import { getNeode } from '../../backend/src/db/neo4j' +import Factory from '../../backend/build/src/db/factories' +import { getNeode } from '../../backend/build/src/db/neo4j' const neodeInstance = getNeode() -beforeEach(() => cy.then(() => neodeInstance.cypher('MATCH (everything) DETACH DELETE everything;'))) +beforeEach(() => cy.then(() => neodeInstance.writeCypher('MATCH (everything) DETACH DELETE everything;'))) Cypress.Commands.add('neode', () => { return neodeInstance diff --git a/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js b/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js index 019cc956a..478851f92 100644 --- a/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js +++ b/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js @@ -1,28 +1,27 @@ import { Then } from "@badeball/cypress-cucumber-preprocessor"; Then("I should be able to {string} a teaser image", condition => { - // cy.reload() + let postTeaserImage = "" + switch(condition){ - case 'change': - cy.get('.delete-image-button') + case "change": + postTeaserImage = "humanconnection.png" + cy.get(".delete-image-button") .click() - cy.fixture('humanconnection.png').as('postTeaserImage').then(function() { - cy.get("#postdropzone").upload( - { fileContent: this.postTeaserImage, fileName: 'humanconnection.png', mimeType: "image/png" }, - { subjectType: "drag-n-drop", force: true } - ).wait(750); - }) + cy.get("#postdropzone").selectFile( + { contents: `cypress/fixtures/${postTeaserImage}`, fileName: postTeaserImage, mimeType: "image/png" }, + { action: "drag-drop", force: true } + ).wait(750); break; - case 'add': - cy.fixture('onourjourney.png').as('postTeaserImage').then(function() { - cy.get("#postdropzone").upload( - { fileContent: this.postTeaserImage, fileName: 'onourjourney.png', mimeType: "image/png" }, - { subjectType: "drag-n-drop", force: true } - ).wait(750); - }) + case "add": + postTeaserImage = "onourjourney.png" + cy.get("#postdropzone").selectFile( + { contents: `cypress/fixtures/${postTeaserImage}`, fileName: postTeaserImage, mimeType: "image/png" }, + { action: "drag-drop", force: true } + ).wait(750); break; - case 'remove': - cy.get('.delete-image-button') + case "remove": + cy.get(".delete-image-button") .click() break; } diff --git a/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js b/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js index 27be5a99d..b1b2401e2 100644 --- a/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js +++ b/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js @@ -2,13 +2,11 @@ import { Then } from "@badeball/cypress-cucumber-preprocessor"; Then("I should be able to change my profile picture", () => { const avatarUpload = "onourjourney.png"; - - cy.fixture(avatarUpload, "base64").then(fileContent => { - cy.get("#customdropzone").upload( - { fileContent, fileName: avatarUpload, mimeType: "image/png" }, - { subjectType: "drag-n-drop", force: true } - ); - }); + + cy.get("#customdropzone").selectFile( + { contents: `cypress/fixtures/${avatarUpload}`, fileName: avatarUpload, mimeType: "image/png" }, + { action: "drag-drop" } + ); cy.get(".profile-page-avatar img") .should("have.attr", "src") .and("contains", "onourjourney"); diff --git a/cypress/support/step_definitions/common/I_am_logged_in_as_{string}.js b/cypress/support/step_definitions/common/I_am_logged_in_as_{string}.js index dfbfd519c..1dbaa3d94 100644 --- a/cypress/support/step_definitions/common/I_am_logged_in_as_{string}.js +++ b/cypress/support/step_definitions/common/I_am_logged_in_as_{string}.js @@ -1,5 +1,5 @@ import { Given } from "@badeball/cypress-cucumber-preprocessor"; -import encode from '../../../../backend/src/jwt/encode' +import encode from '../../../../backend/build/src/jwt/encode' Given("I am logged in as {string}", slug => { cy.neode() diff --git a/deployment/TODO-next-update.md b/deployment/TODO-next-update.md index 8630275b7..8e30d1f47 100644 --- a/deployment/TODO-next-update.md +++ b/deployment/TODO-next-update.md @@ -2,6 +2,10 @@ When you overtake this deploy and rebrand repo to your network you have to recognize the following changes and doings: +## Version >= 2.7.0 with 'ocelotDockerVersionTag' 2.7.0-470 + +- You have to rename all `.js` files to `.ts` in `branding/constants` + ## Version >= 2.4.0 with 'ocelotDockerVersionTag' 2.4.0-298 - You have to set `SHOW_CONTENT_FILTER_HEADER_MENU` and `SHOW_CONTENT_FILTER_MASONRY_GRID` in `branding/constants/filter.js` originally in main code file `webapp/constants/filter.js` to your preferred value. diff --git a/deployment/configurations/stage.ocelot.social b/deployment/configurations/stage.ocelot.social index be3ac7ad2..fdc2e52fa 160000 --- a/deployment/configurations/stage.ocelot.social +++ b/deployment/configurations/stage.ocelot.social @@ -1 +1 @@ -Subproject commit be3ac7ad29f37d6a00fb3203db302cd91cebb9fa +Subproject commit fdc2e52fa444b300e1c4736600bc0e9ae3314222 diff --git a/deployment/scripts/cluster.reseed.sh b/deployment/scripts/cluster.reseed.sh index 4d544bfe8..7bd44153b 100755 --- a/deployment/scripts/cluster.reseed.sh +++ b/deployment/scripts/cluster.reseed.sh @@ -15,4 +15,4 @@ echo "Using CONFIGURATION=${CONFIGURATION}" KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml} # clean & seed -kubectl --kubeconfig=${KUBECONFIG} -n default exec -it $(kubectl --kubeconfig=${KUBECONFIG} -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await build/db/clean.js && node --experimental-repl-await build/db/seed.js" \ No newline at end of file +kubectl --kubeconfig=${KUBECONFIG} -n default exec -it $(kubectl --kubeconfig=${KUBECONFIG} -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await build/src/db/clean.js && node --experimental-repl-await build/src/db/seed.js" \ No newline at end of file diff --git a/deployment/src/docker/backend.Dockerfile b/deployment/src/docker/backend.Dockerfile index 2d8132d0c..a0b6e4ed4 100644 --- a/deployment/src/docker/backend.Dockerfile +++ b/deployment/src/docker/backend.Dockerfile @@ -12,9 +12,9 @@ FROM $APP_IMAGE_CODE as code ARG CONFIGURATION=example # copy public constants and email templates into the Docker image to brand it -COPY configurations/${CONFIGURATION}/branding/constants/emails.js src/config/ -COPY configurations/${CONFIGURATION}/branding/constants/logos.js src/config/ -COPY configurations/${CONFIGURATION}/branding/constants/metadata.js src/config/ +COPY configurations/${CONFIGURATION}/branding/constants/emails.ts src/config/ +COPY configurations/${CONFIGURATION}/branding/constants/logos.ts src/config/ +COPY configurations/${CONFIGURATION}/branding/constants/metadata.ts src/config/ COPY configurations/${CONFIGURATION}/branding/email/ src/middleware/helpers/email/ ################################################################################## @@ -38,7 +38,7 @@ COPY --from=build ${DOCKER_WORKDIR}/build ./build COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules # TODO - externalize the uploads so we can copy the whole folder COPY --from=build ${DOCKER_WORKDIR}/public/img/ ./public/img/ -COPY --from=build ${DOCKER_WORKDIR}/public/providers.json ./public/providers.json +COPY --from=build ${DOCKER_WORKDIR}/public/providers.json ./build/public/providers.json # Copy package.json for script definitions (lock file should not be needed) COPY --from=build ${DOCKER_WORKDIR}/package.json ./package.json diff --git a/deployment/src/docker/maintenance.Dockerfile b/deployment/src/docker/maintenance.Dockerfile index b699e7f20..95501252c 100644 --- a/deployment/src/docker/maintenance.Dockerfile +++ b/deployment/src/docker/maintenance.Dockerfile @@ -14,6 +14,7 @@ ARG CONFIGURATION=example # copy public constants into the Docker image to brand it COPY configurations/${CONFIGURATION}/branding/static/ static/ COPY configurations/${CONFIGURATION}/branding/constants/ constants/ +RUN /bin/sh -c 'cd constants && for f in *.ts; do mv -- "$f" "${f%.ts}.js"; done' # locales COPY configurations/${CONFIGURATION}/branding/locales/*.json locales/tmp/ diff --git a/deployment/src/docker/webapp.Dockerfile b/deployment/src/docker/webapp.Dockerfile index f0c75e392..d811219c3 100644 --- a/deployment/src/docker/webapp.Dockerfile +++ b/deployment/src/docker/webapp.Dockerfile @@ -14,6 +14,7 @@ ARG CONFIGURATION=example # copy public constants into the Docker image to brand it COPY configurations/${CONFIGURATION}/branding/static/ static/ COPY configurations/${CONFIGURATION}/branding/constants/ constants/ +RUN /bin/sh -c 'cd constants && for f in *.ts; do mv -- "$f" "${f%.ts}.js"; done' COPY configurations/${CONFIGURATION}/branding/locales/html/ locales/html/ COPY configurations/${CONFIGURATION}/branding/assets/styles/imports/ assets/styles/imports/ COPY configurations/${CONFIGURATION}/branding/assets/fonts/ assets/fonts/ diff --git a/deployment/src/kubernetes/README.md b/deployment/src/kubernetes/README.md index 1c0c8e2d8..126c37e9c 100644 --- a/deployment/src/kubernetes/README.md +++ b/deployment/src/kubernetes/README.md @@ -293,7 +293,7 @@ $ kubectl -n default rollout status deployment/ocelot-neo4j --timeout=240s $ kubectl config get-contexts # reset and seed Neo4j database via backend for staging -$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await build/db/clean.js && node --experimental-repl-await build/db/seed.js" +$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await build/src/db/clean.js && node --experimental-repl-await build/src/db/seed.js" ``` diff --git a/deployment/src/kubernetes/templates/neo4j/ConfigMap.yml b/deployment/src/kubernetes/templates/neo4j/ConfigMap.yml index 9f0aa4bee..f71f11285 100644 --- a/deployment/src/kubernetes/templates/neo4j/ConfigMap.yml +++ b/deployment/src/kubernetes/templates/neo4j/ConfigMap.yml @@ -18,4 +18,6 @@ data: NEO4J_dbms_memory_heap_max__size: "{{ .Values.NEO4J.DBMS_MEMORY_HEAP_MAX_SIZE }}" NEO4J_dbms_memory_pagecache_size: "{{ .Values.NEO4J.DBMS_MEMORY_PAGECACHE_SIZE }}" NEO4J_dbms_security_procedures_unrestricted: "{{ .Values.NEO4J.DBMS_SECURITY_PROCEDURES_UNRESTRICTED }}" + NEO4J_dbms_allow__format__migration: "true" + NEO4J_dbms_allow__upgrade: "true" NEO4J_apoc_import_file_enabled: "{{ .Values.NEO4J.APOC_IMPORT_FILE_ENABLED }}" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index aeb26e4fd..41a03a7fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -111,6 +111,8 @@ services: # TODO: This sounds scary for a production environment - NEO4J_AUTH=none - NEO4J_dbms_security_procedures_unrestricted=algo.*,apoc.* + - NEO4J_dbms_allow__format__migration=true + - NEO4J_dbms_allow__upgrade=true # Uncomment following line for Neo4j Enterprise version instead of Community version # TODO: clarify if that is the only thing needed to unlock the Enterprise version # - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes diff --git a/neo4j/Dockerfile b/neo4j/Dockerfile index dc5a912f0..a88c16c09 100644 --- a/neo4j/Dockerfile +++ b/neo4j/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # COMMUNITY ###################################################################### ################################################################################## -FROM amd64/neo4j:3.5.14 as community +FROM amd64/neo4j:4.4-community as community # ENVs ## We Cannot do `$(date -u +'%Y-%m-%dT%H:%M:%SZ')` here so we use unix timestamp=0 @@ -31,15 +31,15 @@ LABEL maintainer="devops@ocelot.social" ## install: wget, htop (TODO: why do we need htop?) RUN apt-get update && apt-get -y install wget htop ## install: apoc plugin for neo4j -RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/3.5.0.4/apoc-3.5.0.4-all.jar -P plugins/ +RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/4.4.0.17/apoc-4.4.0.17-all.jar -P plugins/ ################################################################################## # ENTERPRISE ##################################################################### ################################################################################## -FROM neo4j:3.5.14-enterprise as enterprise +FROM neo4j:4.4-enterprise as enterprise # Install Additional Software ## install: wget, htop (TODO: why do we need htop?) RUN apt-get update && apt-get -y install wget htop ## install: apoc plugin for neo4j -RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/3.5.0.4/apoc-3.5.0.4-all.jar -P plugins/ \ No newline at end of file +RUN wget https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/4.4.0.17/apoc-4.4.0.17-all.jar -P plugins/ \ No newline at end of file diff --git a/package.json b/package.json index 78157131d..368ff46e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social", - "version": "2.6.0", + "version": "2.7.0", "description": "Free and open source software program code available to run social networks.", "author": "ocelot.social Community", "license": "MIT", @@ -10,19 +10,31 @@ "url": "https://github.com/Ocelot-Social-Community/Ocelot-Social.git" }, "cypress-cucumber-preprocessor": { - "nonGlobalStepDefinitions": true + "stepDefinitions": "cypress/support/step_definitions/**/*.js", + "json": { + "enabled": true, + "output": "cypress/reports/json_logs/cucumber_log.json", + "formatter": "cucumber-json-formatter" + }, + "messages": { + "enabled": true, + "output": "cypress/reports/json_logs/messages.ndjson" + }, + "html": { + "enabled": false + } }, "scripts": { "db:seed": "cd backend && yarn run db:seed", "db:reset": "cd backend && yarn run db:reset", - "cypress:run": "cypress run --browser electron --config-file ./cypress/cypress.config.js", - "cypress:open": "cypress open --browser electron --config-file ./cypress/cypress.config.js", + "cypress:run": "cypress run --e2e --browser electron --config-file ./cypress/cypress.config.js", + "cypress:open": "cypress open --e2e --browser electron --config-file ./cypress/cypress.config.js", "cucumber:setup": "cd backend && yarn run dev", "cucumber": "wait-on tcp:4000 && cucumber-js --require-module @babel/register --exit", "release": "yarn version --no-git-tag-version --no-commit-hooks --no-commit && auto-changelog --latest-version $(node -p -e \"require('./package.json').version\") && cd backend && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp/maintenance/source && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../../../package.json').version\")" }, "devDependencies": { - "@babel/core": "^7.21.8", + "@babel/core": "^7.22.5", "@babel/preset-env": "^7.22.4", "@babel/register": "^7.12.10", "@badeball/cypress-cucumber-preprocessor": "^18.0.1", diff --git a/webapp/Dockerfile.maintenance b/webapp/Dockerfile.maintenance index a6db9e612..91dc1c832 100644 --- a/webapp/Dockerfile.maintenance +++ b/webapp/Dockerfile.maintenance @@ -1,7 +1,7 @@ ################################################################################## # BASE ########################################################################### ################################################################################## -FROM node:20.2.0-alpine3.17 as base +FROM node:20.3.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/assets/_new/icons/svgs/chat-bubble.svg b/webapp/assets/_new/icons/svgs/chat-bubble.svg new file mode 100644 index 000000000..377b52f2f --- /dev/null +++ b/webapp/assets/_new/icons/svgs/chat-bubble.svg @@ -0,0 +1,4 @@ + +chat-bubble + + \ No newline at end of file diff --git a/webapp/assets/_new/styles/export.scss b/webapp/assets/_new/styles/export.scss new file mode 100644 index 000000000..88b42bfc9 --- /dev/null +++ b/webapp/assets/_new/styles/export.scss @@ -0,0 +1,30 @@ + +:export { + colorPrimary: $color-primary; + colorPrimaryActive: $color-primary-active; + colorPrimaryLight: $color-primary-light; + + borderColorSoft: $border-color-soft; + + borderRadiusBase: $border-radius-base; + + textColorBase: $text-color-base; + textColorSoft: $text-color-soft; + textColorInverse: $text-color-inverse; + + boxShadowBase: $box-shadow-base; + + backgroundColorBase: $background-color-base; + backgroundColorSoft: $background-color-soft; + backgroundColorSoftest: $background-color-softest; + backgroundColorPrimary: $background-color-primary; + + colorNeutral30: $color-neutral-30; + + chatMessageColor: $chat-message-color; + + chatMessageBgMe: $chat-message-bg-me; + chatMessageBgOthers: $chat-message-bg-others; + + chatNewMessageColor: $chat-new-message-color; + } \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.scss b/webapp/assets/_new/styles/tokens.scss index 22e0214ff..e001ffa84 100644 --- a/webapp/assets/_new/styles/tokens.scss +++ b/webapp/assets/_new/styles/tokens.scss @@ -406,4 +406,14 @@ $color-toast-green: $color-success; $color-ribbon-event: $background-color-third; $color-ribbon-event-active: $background-color-third-active; $color-ribbon-article: $background-color-secondary; -$color-ribbon-article-active: $background-color-secondary-active; \ No newline at end of file +$color-ribbon-article-active: $background-color-secondary-active; + +/** + * @tokens Chat Color + */ + +$chat-message-bg-me: $color-primary-light; +$chat-message-color: $text-color-base; +$chat-message-bg-others: $color-neutral-80; +$chat-sidemenu-bg: $color-secondary-active; +$chat-new-message-color: $color-secondary-active; diff --git a/webapp/components/Chat/Chat.vue b/webapp/components/Chat/Chat.vue new file mode 100644 index 000000000..f638b9b0c --- /dev/null +++ b/webapp/components/Chat/Chat.vue @@ -0,0 +1,330 @@ + + + + diff --git a/webapp/components/ChatNotificationMenu/ChatNotificationMenu.vue b/webapp/components/ChatNotificationMenu/ChatNotificationMenu.vue new file mode 100644 index 000000000..016410216 --- /dev/null +++ b/webapp/components/ChatNotificationMenu/ChatNotificationMenu.vue @@ -0,0 +1,41 @@ + + + diff --git a/webapp/components/ContributionForm/ContributionForm.spec.js b/webapp/components/ContributionForm/ContributionForm.spec.js index 6b9db448b..9095665fc 100644 --- a/webapp/components/ContributionForm/ContributionForm.spec.js +++ b/webapp/components/ContributionForm/ContributionForm.spec.js @@ -1,8 +1,8 @@ import { mount } from '@vue/test-utils' import ContributionForm from './ContributionForm.vue' +import PostMutations from '~/graphql/PostMutations.js' import Vuex from 'vuex' -import PostMutations from '~/graphql/PostMutations.js' import ImageUploader from '~/components/Uploader/ImageUploader' import MutationObserver from 'mutation-observer' @@ -108,6 +108,10 @@ describe('ContributionForm.vue', () => { await wrapper.vm.updateEditorContent(postContent) }) + it('has no event data block', () => { + expect(wrapper.find('div.eventDatas').exists()).toBe(false) + }) + it('title cannot be empty', async () => { postTitleInput.setValue('') wrapper.find('form').trigger('submit') @@ -293,5 +297,88 @@ describe('ContributionForm.vue', () => { }) }) }) + + describe('Events', () => { + beforeEach(() => { + propsData.createEvent = true + wrapper = Wrapper() + }) + + it('has event data block', () => { + expect(wrapper.find('div.eventDatas').exists()).toBe(true) + }) + + describe('is online event', () => { + it('has false as default', () => { + expect(wrapper.vm.formData.eventIsOnline).toBe(false) + }) + + it('has input for event location', () => { + expect(wrapper.find('input[name="eventLocationName"]').exists()).toBe(true) + }) + + describe('click is online event', () => { + beforeEach(() => { + wrapper.find('input[name="eventIsOnline"]').setChecked(true) + }) + + it('has no input for event location', () => { + expect(wrapper.find('input[name="eventLocationName"]').exists()).toBe(false) + }) + }) + + describe('invalid form', () => { + beforeEach(() => { + wrapper.find('input[name="title"]').setValue('Illegaler Kindergeburtstag') + wrapper.vm.updateEditorContent('Elli hat Geburtstag!') + }) + + it('has submit button disabled', () => { + expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled') + }) + }) + + describe('valid form', () => { + const now = new Date() + + beforeEach(() => { + wrapper.find('input[name="title"]').setValue('Illegaler Kindergeburtstag') + wrapper.vm.updateEditorContent('Elli hat Geburtstag!') + wrapper + .findComponent({ name: 'DatePicker' }) + .vm.$emit('change', new Date(now.getFullYear(), now.getMonth() + 1).toISOString()) + wrapper.find('input[name="eventVenue"]').setValue('Ellis Kinderzimmer') + wrapper.find('input[name="eventLocationName"]').setValue('Deutschland') + }) + + it('has submit button not disabled', () => { + expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe(undefined) + }) + + describe('submit', () => { + beforeEach(() => { + wrapper.find('form').trigger('submit') + }) + + it('calls create post', () => { + expect(mocks.$apollo.mutate).toHaveBeenCalledWith({ + mutation: PostMutations().CreatePost, + variables: expect.objectContaining({ + title: 'Illegaler Kindergeburtstag', + content: 'Elli hat Geburtstag!', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventVenue: 'Ellis Kinderzimmer', + eventLocationName: 'Deutschland', + eventIsOnline: false, + eventEnd: null, + }, + }), + }) + }) + }) + }) + }) + }) }) }) diff --git a/webapp/components/ContributionForm/ContributionForm.vue b/webapp/components/ContributionForm/ContributionForm.vue index 997a25341..0067dab72 100644 --- a/webapp/components/ContributionForm/ContributionForm.vue +++ b/webapp/components/ContributionForm/ContributionForm.vue @@ -54,13 +54,13 @@ -
+

- + -
+
-
+
- +
- + - - + +
@@ -113,10 +116,10 @@
- +
@@ -131,9 +134,11 @@
{{ $t('post.viewEvent.eventIsOnline') }}
@@ -153,7 +158,7 @@ - + null, }, - creatEvent: { + createEvent: { type: Boolean, default: false, }, @@ -252,24 +257,6 @@ export default { eventVenue: eventVenue || '', eventIsOnline: eventIsOnline || false, }, - formSchema: { - title: { required: true, min: 3, max: 100 }, - content: { required: true }, - imageBlurred: { required: false }, - categoryIds: { - type: 'array', - required: this.categoriesActive, - validator: (_, value = []) => { - if (this.categoriesActive && (value.length === 0 || value.length > 3)) { - return [new Error(this.$t('common.validations.categories'))] - } - return [] - }, - }, - eventStart: { required: !!this.creatEvent }, - eventVenue: { required: !!this.creatEvent, min: 3, max: 100 }, - eventLocationName: { required: !!this.creatEvent, min: 3, max: 100 }, - }, loading: false, users: [], hashtags: [], @@ -283,14 +270,69 @@ export default { ...mapGetters({ currentUser: 'auth/user', }), + formSchema() { + return { + title: { required: true, min: 3, max: 100 }, + content: { required: true }, + imageBlurred: { required: false }, + categoryIds: { + type: 'array', + required: this.categoriesActive, + validator: (_, value = []) => { + if (this.categoriesActive && (value.length === 0 || value.length > 3)) { + return [new Error(this.$t('common.validations.categories'))] + } + return [] + }, + }, + eventStart: { required: !!this.createEvent }, + eventVenue: { + required: !!this.createEvent, + min: 3, + max: 100, + validator: (_, value = '') => { + if (!this.createEvent) return [] + if (!value.trim()) { + return [new Error(this.$t('common.validations.eventVenueNotEmpty'))] + } + if (value.length < 3 || value.length > 100) { + return [ + new Error(this.$t('common.validations.eventVenueLength', { min: 3, max: 100 })), + ] + } + return [] + }, + }, + eventLocationName: { + required: !!this.createEvent && !this.formData.eventIsOnline, + min: 3, + max: 100, + validator: (_, value = '') => { + if (!this.createEvent) return [] + if (this.formData.eventIsOnline) return [] + if (!value.trim()) { + return [new Error(this.$t('common.validations.eventLocationNameNotEmpty'))] + } + if (value.length < 3 || value.length > 100) { + return [ + new Error( + this.$t('common.validations.eventLocationNameLength', { min: 3, max: 100 }), + ), + ] + } + return [] + }, + }, + } + }, eventInput() { - if (this.creatEvent) { + if (this.createEvent) { return { eventStart: this.formData.eventStart, eventVenue: this.formData.eventVenue, eventEnd: this.formData.eventEnd, eventIsOnline: this.formData.eventIsOnline, - eventLocationName: this.formData.eventLocationName, + eventLocationName: !this.formData.eventIsOnline ? this.formData.eventLocationName : null, } } return undefined @@ -310,6 +352,9 @@ export default { groupCategories() { return this.group && this.group.categories }, + showEventLocationName() { + return !this.formData.eventIsOnline + }, }, watch: { groupCategories() { @@ -356,7 +401,7 @@ export default { id: this.contribution.id || null, image, groupId: this.groupId, - postType: !this.creatEvent ? 'Article' : 'Event', + postType: !this.createEvent ? 'Article' : 'Event', eventInput: this.eventInput, }, }) @@ -378,6 +423,15 @@ export default { updateEditorContent(value) { this.$refs.contributionForm.update('content', value) }, + changeEventIsOnline(event) { + this.$refs.contributionForm.update('eventIsOnline', this.formData.eventIsOnline) + }, + changeEventEnd(event) { + this.$refs.contributionForm.update('eventEnd', event) + }, + changeEventStart(event) { + this.$refs.contributionForm.update('eventStart', event) + }, addHeroImage(file) { this.formData.image = null if (file) { @@ -443,6 +497,24 @@ export default { margin-top: -10px; } } + // style override to handle dynamic inputs + .event-location-grid { + grid-template-columns: repeat(2, 1fr) !important; + } + + .event-grid-item { + // important needed because of component inline style + grid-row-end: span 3 !important; + } + .event-grid-item-z-helper { + z-index: 20; + } + .event-grid-item-margin-helper { + margin-top: 10px; + } + .event-grid-item-font-helper { + font-size: larger; + } } .contribution-form > .base-card { @@ -491,6 +563,12 @@ export default { min-width: fit-content; } } + + > .buttons-footer-helper { + margin-right: 16px; + // important needed because of component inline style + margin-bottom: 6px !important; + } } .blur-toggle { diff --git a/webapp/components/DateTimeRange/DateTimeRange.vue b/webapp/components/DateTimeRange/DateTimeRange.vue new file mode 100644 index 000000000..de9b442c5 --- /dev/null +++ b/webapp/components/DateTimeRange/DateTimeRange.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/webapp/components/HeaderMenu/HeaderMenu.vue b/webapp/components/HeaderMenu/HeaderMenu.vue index b5622d7ed..f4d48220e 100644 --- a/webapp/components/HeaderMenu/HeaderMenu.vue +++ b/webapp/components/HeaderMenu/HeaderMenu.vue @@ -74,6 +74,10 @@