From 4538fa22ab54b8d699a0e7ffa97dfc86cef95624 Mon Sep 17 00:00:00 2001 From: Kevin Barabash Date: Thu, 16 Feb 2023 11:54:10 -0500 Subject: [PATCH] FEI-4957.4: Run codemod to convert files to TypeScript (#526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary: This changeset was generated using the follow commands: - cd ../flow-to-typescript-codemod - yarn typescriptify convert -p ../wonder-stuff --write --delete - // manually change 'export {* as jest} from "jest"' to be 'export * as jest from "jest"' in wonder-stuff - yarn typescriptify fix --autoSuppressErrors --jiraSlug FEI-5011 -p ../wonder-stuff --config ../wonder-stuff/tsconfig.json - // manually rename prettierrc.ts to prettierrc.js - cd ../wonder-stuff - yarn format The next PR will fix all the TypeScript errors Issue: FEI-4957 ## Test plan: - yarn tsc --noEmit, see a bunch of errors ``` Found 24 errors in 7 files. Errors Files 2 packages/wonder-stuff-i18n/src/utils/emoji-for-locale.ts:46 10 packages/wonder-stuff-sentry/src/normalize-sentry-data.ts:34 2 packages/wonder-stuff-server-google/src/start-server.ts:26 1 packages/wonder-stuff-server/src/middleware/default-error-logging.ts:18 1 packages/wonder-stuff-server/src/middleware/default-request-logging.ts:18 4 packages/wonder-stuff-server/src/start-server.ts:37 4 packages/wonder-stuff-server/src/types.ts:1 ``` Author: kevinbarabash Reviewers: jeresig, somewhatabstract, kevinbarabash Required Reviewers: Approved By: jeresig, somewhatabstract Checks: ✅ CodeQL, ⏭ Test, ❌ Lint, flow, and coverage check (ubuntu-latest, 16.x), ✅ Analyze (javascript), ✅ gerald, ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 16.x), ⏭ dependabot Pull Request URL: https://github.com/Khan/wonder-stuff/pull/526 --- .changeset/fifty-grapes-guess.md | 11 + flow-typed/@google-cloud/logging-winston.js | 37 --- flow-typed/express-winston.js | 51 --- flow-typed/superagent.js | 308 ------------------ packages/eslint-config-khan/.prettierrc.js | 1 - ...p => build-caused-by-message.test.ts.snap} | 0 ...js.snap => errors-from-error.test.ts.snap} | 0 ...r.test.js.snap => kind-error.test.ts.snap} | 0 ...est.js => build-caused-by-message.test.ts} | 7 +- ...etadata.test.js => clone-metadata.test.ts} | 22 +- .../{clone.test.js => clone.test.ts} | 11 +- ...ntries.flowtest.js => entries.flowtest.ts} | 18 +- .../{entries.test.js => entries.test.ts} | 6 +- ...{error-info.test.js => error-info.test.ts} | 17 +- ...rror.test.js => errors-from-error.test.ts} | 11 +- .../{errors.test.js => errors.test.ts} | 5 +- ...or.test.js => get-kind-from-error.test.ts} | 3 +- ... => get-original-stack-from-error.test.ts} | 1 - .../{keys.flowtest.js => keys.flowtest.ts} | 13 +- .../__tests__/{keys.test.js => keys.test.ts} | 7 +- ...{kind-error.test.js => kind-error.test.ts} | 22 +- ...ringify.test.js => safe-stringify.test.ts} | 25 +- ...middle.test.js => truncate-middle.test.ts} | 3 +- ...{values.flowtest.js => values.flowtest.ts} | 20 +- .../{values.test.js => values.test.ts} | 7 +- ...-message.js => build-caused-by-message.ts} | 7 +- .../{clone-metadata.js => clone-metadata.ts} | 8 +- .../src/{clone.js => clone.ts} | 7 +- packages/wonder-stuff-core/src/entries.js | 16 - .../src/{error-info.js => error-info.ts} | 11 +- ...ors-from-error.js => errors-from-error.ts} | 6 +- .../src/{errors.js => errors.ts} | 2 - ...d-from-error.js => get-kind-from-error.ts} | 1 - ...or.js => get-original-stack-from-error.ts} | 2 +- .../src/{index.js => index.ts} | 4 +- packages/wonder-stuff-core/src/keys.js | 13 - .../src/{kind-error.js => kind-error.ts} | 46 +-- .../{safe-stringify.js => safe-stringify.ts} | 10 +- ...{truncate-middle.js => truncate-middle.ts} | 1 - .../src/{types.js => types.ts} | 5 +- packages/wonder-stuff-core/src/values.js | 14 - ...ll-i18n-strings.js => all-i18n-strings.ts} | 1 - .../bin/{gen-potfile.js => gen-potfile.ts} | 1 - .../src/{index.js => index.ts} | 1 - ...18n-plugin.test.js => i18n-plugin.test.ts} | 70 ++-- .../{i18n-plugin.js => i18n-plugin.ts} | 95 +++--- ...ocale.test.js => emoji-for-locale.test.ts} | 1 - ...ract-i18n.test.js => extract-i18n.test.ts} | 5 +- ...{i18n-utils.test.js => i18n-utils.test.ts} | 9 +- ...ize-file.test.js => localize-file.test.ts} | 29 +- ...ile-utils.test.js => pofile-utils.test.ts} | 38 ++- ...moji-for-locale.js => emoji-for-locale.ts} | 4 +- .../{extract-i18n.js => extract-i18n.ts} | 25 +- .../utils/{i18n-utils.js => i18n-utils.ts} | 15 +- .../{localize-file.js => localize-file.ts} | 26 +- .../{pofile-utils.js => pofile-utils.ts} | 19 +- ...t.js.snap => kind-error-data.test.ts.snap} | 0 ...ta.test.js => collate-sentry-data.test.ts} | 13 +- ....js => get-sentry-data-from-error.test.ts} | 6 +- ...s => is-reserved-context-property.test.ts} | 3 +- ...ey.test.js => is-reserved-tag-key.test.ts} | 3 +- ...valid.test.js => is-tag-key-valid.test.ts} | 7 +- ...r-data.test.js => kind-error-data.test.ts} | 70 ++-- ...rror.test.js => kind-sentry-error.test.ts} | 8 +- ....test.js => normalize-sentry-data.test.ts} | 28 +- ...er.test.js => sentry-data-reducer.test.ts} | 5 +- ...lue.test.js => truncate-tag-value.test.ts} | 3 +- ...-sentry-data.js => collate-sentry-data.ts} | 11 +- ....js => default-kind-error-data-options.ts} | 1 - ...ty-sentry-data.js => empty-sentry-data.ts} | 3 +- ...error.js => get-sentry-data-from-error.ts} | 3 +- .../src/{index.js => index.ts} | 1 - ...rty.js => is-reserved-context-property.ts} | 1 - ...rved-tag-key.js => is-reserved-tag-key.ts} | 1 - ...s-tag-key-valid.js => is-tag-key-valid.ts} | 2 - ...{kind-error-data.js => kind-error-data.ts} | 18 +- ...d-sentry-error.js => kind-sentry-error.ts} | 30 +- ...entry-data.js => normalize-sentry-data.ts} | 23 +- ...data-reducer.js => sentry-data-reducer.ts} | 8 +- ...ate-tag-value.js => truncate-tag-value.ts} | 1 - .../src/{types.js => types.ts} | 67 ++-- ...l.test.js.snap => trace-impl.test.ts.snap} | 0 ...t.js => add-app-engine-middleware.test.ts} | 65 ++-- ...fo.test.js => get-app-engine-info.test.ts} | 3 +- ...st.js => get-appengine-request-id.test.ts} | 17 +- .../{get-delta.test.js => get-delta.test.ts} | 6 +- ...ons.test.js => setup-integrations.test.ts} | 40 +-- ...rt-server.test.js => start-server.test.ts} | 35 +- ...{trace-impl.test.js => trace-impl.test.ts} | 89 +++-- .../{trace.test.js => trace.test.ts} | 47 ++- ...leware.js => add-app-engine-middleware.ts} | 17 +- ...-engine-info.js => get-app-engine-info.ts} | 1 - ...est-id.js => get-app-engine-request-id.ts} | 7 +- ...etadata.js => get-default-log-metadata.ts} | 5 +- .../src/get-delta.js | 13 - .../src/get-delta.ts | 13 + .../src/{index.js => index.ts} | 1 - ...-app-engine-request-id-middleware.test.ts} | 78 ++--- ... make-app-engine-request-id-middleware.ts} | 10 +- ...-integrations.js => setup-integrations.ts} | 3 +- .../src/{start-server.js => start-server.ts} | 12 +- .../src/{trace-impl.js => trace-impl.ts} | 14 +- .../src/{trace.js => trace.ts} | 11 +- .../src/{types.js => types.ts} | 49 +-- ...nap => get-logging-transport.test.ts.snap} | 0 ...e-logger.test.js => create-logger.test.ts} | 24 +- ...-url.test.js => get-agent-for-url.test.ts} | 1 - ...{get-logger.test.js => get-logger.test.ts} | 16 +- ....test.js => get-logging-transport.test.ts} | 13 +- ...ger.test.js => get-request-logger.test.ts} | 17 +- ...-mode.test.js => get-runtime-mode.test.ts} | 24 +- ...oot-logger.test.js => root-logger.test.ts} | 7 +- ...rt-server.test.js => start-server.test.ts} | 296 ++++++++--------- .../{create-logger.js => create-logger.ts} | 6 +- .../src/{errors.js => errors.ts} | 1 - ...-agent-for-url.js => get-agent-for-url.ts} | 3 +- .../src/{get-logger.js => get-logger.ts} | 5 +- ...-transport.js => get-logging-transport.ts} | 9 +- ...equest-logger.js => get-request-logger.ts} | 7 +- ...et-runtime-mode.js => get-runtime-mode.ts} | 5 +- .../src/{index.js => index.ts} | 1 - ....test.js => default-error-logging.test.ts} | 9 +- ...est.js => default-request-logging.test.ts} | 9 +- .../src/middleware/default-error-logging.js | 19 -- .../src/middleware/default-error-logging.ts | 22 ++ ...-logging.js => default-request-logging.ts} | 17 +- .../src/middleware/{index.js => index.ts} | 1 - .../src/{root-logger.js => root-logger.ts} | 5 +- .../src/{start-server.js => start-server.ts} | 33 +- .../src/{types.js => types.ts} | 56 ++-- ...y-for.test.js => data-factory-for.test.ts} | 12 +- ...ata-factory-for.js => data-factory-for.ts} | 6 +- .../src/{index.js => index.ts} | 1 - ...odules.test.js => isolate-modules.test.ts} | 1 - .../__tests__/{wait.test.js => wait.test.ts} | 1 - .../src/jest/{index.js => index.ts} | 1 - ...ssert-jest.test.js => assert-jest.test.ts} | 1 - ...d-wait.test.js => unverified-wait.test.ts} | 12 +- ...ers.test.js => verify-real-timers.test.ts} | 1 - .../{assert-jest.js => assert-jest.ts} | 1 - ...nning-in-jest.js => is-running-in-jest.ts} | 1 - .../src/jest/internal/unverified-wait.js | 12 - .../src/jest/internal/unverified-wait.ts | 18 + ...y-real-timers.js => verify-real-timers.ts} | 3 - ...{isolate-modules.js => isolate-modules.ts} | 3 +- .../src/jest/{wait.js => wait.ts} | 10 +- 146 files changed, 1095 insertions(+), 1545 deletions(-) create mode 100644 .changeset/fifty-grapes-guess.md delete mode 100644 flow-typed/@google-cloud/logging-winston.js delete mode 100644 flow-typed/express-winston.js delete mode 100644 flow-typed/superagent.js rename packages/wonder-stuff-core/src/__tests__/__snapshots__/{build-caused-by-message.test.js.snap => build-caused-by-message.test.ts.snap} (100%) rename packages/wonder-stuff-core/src/__tests__/__snapshots__/{errors-from-error.test.js.snap => errors-from-error.test.ts.snap} (100%) rename packages/wonder-stuff-core/src/__tests__/__snapshots__/{kind-error.test.js.snap => kind-error.test.ts.snap} (100%) rename packages/wonder-stuff-core/src/__tests__/{build-caused-by-message.test.js => build-caused-by-message.test.ts} (95%) rename packages/wonder-stuff-core/src/__tests__/{clone-metadata.test.js => clone-metadata.test.ts} (67%) rename packages/wonder-stuff-core/src/__tests__/{clone.test.js => clone.test.ts} (95%) rename packages/wonder-stuff-core/src/__tests__/{entries.flowtest.js => entries.flowtest.ts} (70%) rename packages/wonder-stuff-core/src/__tests__/{entries.test.js => entries.test.ts} (85%) rename packages/wonder-stuff-core/src/__tests__/{error-info.test.js => error-info.test.ts} (92%) rename packages/wonder-stuff-core/src/__tests__/{errors-from-error.test.js => errors-from-error.test.ts} (83%) rename packages/wonder-stuff-core/src/__tests__/{errors.test.js => errors.test.ts} (61%) rename packages/wonder-stuff-core/src/__tests__/{get-kind-from-error.test.js => get-kind-from-error.test.ts} (96%) rename packages/wonder-stuff-core/src/__tests__/{get-original-stack-from-error.test.js => get-original-stack-from-error.test.ts} (99%) rename packages/wonder-stuff-core/src/__tests__/{keys.flowtest.js => keys.flowtest.ts} (71%) rename packages/wonder-stuff-core/src/__tests__/{keys.test.js => keys.test.ts} (72%) rename packages/wonder-stuff-core/src/__tests__/{kind-error.test.js => kind-error.test.ts} (94%) rename packages/wonder-stuff-core/src/__tests__/{safe-stringify.test.js => safe-stringify.test.ts} (87%) rename packages/wonder-stuff-core/src/__tests__/{truncate-middle.test.js => truncate-middle.test.ts} (96%) rename packages/wonder-stuff-core/src/__tests__/{values.flowtest.js => values.flowtest.ts} (73%) rename packages/wonder-stuff-core/src/__tests__/{values.test.js => values.test.ts} (73%) rename packages/wonder-stuff-core/src/{build-caused-by-message.js => build-caused-by-message.ts} (83%) rename packages/wonder-stuff-core/src/{clone-metadata.js => clone-metadata.ts} (78%) rename packages/wonder-stuff-core/src/{clone.js => clone.ts} (69%) delete mode 100644 packages/wonder-stuff-core/src/entries.js rename packages/wonder-stuff-core/src/{error-info.js => error-info.ts} (97%) rename packages/wonder-stuff-core/src/{errors-from-error.js => errors-from-error.ts} (82%) rename packages/wonder-stuff-core/src/{errors.js => errors.ts} (98%) rename packages/wonder-stuff-core/src/{get-kind-from-error.js => get-kind-from-error.ts} (96%) rename packages/wonder-stuff-core/src/{get-original-stack-from-error.js => get-original-stack-from-error.ts} (72%) rename packages/wonder-stuff-core/src/{index.js => index.ts} (61%) delete mode 100644 packages/wonder-stuff-core/src/keys.js rename packages/wonder-stuff-core/src/{kind-error.js => kind-error.ts} (88%) rename packages/wonder-stuff-core/src/{safe-stringify.js => safe-stringify.ts} (96%) rename packages/wonder-stuff-core/src/{truncate-middle.js => truncate-middle.ts} (99%) rename packages/wonder-stuff-core/src/{types.js => types.ts} (58%) delete mode 100644 packages/wonder-stuff-core/src/values.js rename packages/wonder-stuff-i18n/src/bin/{all-i18n-strings.js => all-i18n-strings.ts} (98%) mode change 100755 => 100644 rename packages/wonder-stuff-i18n/src/bin/{gen-potfile.js => gen-potfile.ts} (99%) mode change 100755 => 100644 rename packages/wonder-stuff-i18n/src/{index.js => index.ts} (98%) rename packages/wonder-stuff-i18n/src/plugins/__tests__/{i18n-plugin.test.js => i18n-plugin.test.ts} (90%) rename packages/wonder-stuff-i18n/src/plugins/{i18n-plugin.js => i18n-plugin.ts} (88%) rename packages/wonder-stuff-i18n/src/utils/__tests__/{emoji-for-locale.test.js => emoji-for-locale.test.ts} (98%) rename packages/wonder-stuff-i18n/src/utils/__tests__/{extract-i18n.test.js => extract-i18n.test.ts} (99%) rename packages/wonder-stuff-i18n/src/utils/__tests__/{i18n-utils.test.js => i18n-utils.test.ts} (97%) rename packages/wonder-stuff-i18n/src/utils/__tests__/{localize-file.test.js => localize-file.test.ts} (94%) rename packages/wonder-stuff-i18n/src/utils/__tests__/{pofile-utils.test.js => pofile-utils.test.ts} (76%) rename packages/wonder-stuff-i18n/src/utils/{emoji-for-locale.js => emoji-for-locale.ts} (79%) rename packages/wonder-stuff-i18n/src/utils/{extract-i18n.js => extract-i18n.ts} (96%) rename packages/wonder-stuff-i18n/src/utils/{i18n-utils.js => i18n-utils.ts} (88%) rename packages/wonder-stuff-i18n/src/utils/{localize-file.js => localize-file.ts} (92%) rename packages/wonder-stuff-i18n/src/utils/{pofile-utils.js => pofile-utils.ts} (92%) rename packages/wonder-stuff-sentry/src/__tests__/__snapshots__/{kind-error-data.test.js.snap => kind-error-data.test.ts.snap} (100%) rename packages/wonder-stuff-sentry/src/__tests__/{collate-sentry-data.test.js => collate-sentry-data.test.ts} (97%) rename packages/wonder-stuff-sentry/src/__tests__/{get-sentry-data-from-error.test.js => get-sentry-data-from-error.test.ts} (75%) rename packages/wonder-stuff-sentry/src/__tests__/{is-reserved-context-property.test.js => is-reserved-context-property.test.ts} (68%) rename packages/wonder-stuff-sentry/src/__tests__/{is-reserved-tag-key.test.js => is-reserved-tag-key.test.ts} (73%) rename packages/wonder-stuff-sentry/src/__tests__/{is-tag-key-valid.test.js => is-tag-key-valid.test.ts} (66%) rename packages/wonder-stuff-sentry/src/__tests__/{kind-error-data.test.js => kind-error-data.test.ts} (84%) rename packages/wonder-stuff-sentry/src/__tests__/{kind-sentry-error.test.js => kind-sentry-error.test.ts} (92%) rename packages/wonder-stuff-sentry/src/__tests__/{normalize-sentry-data.test.js => normalize-sentry-data.test.ts} (90%) rename packages/wonder-stuff-sentry/src/__tests__/{sentry-data-reducer.test.js => sentry-data-reducer.test.ts} (99%) rename packages/wonder-stuff-sentry/src/__tests__/{truncate-tag-value.test.js => truncate-tag-value.test.ts} (95%) rename packages/wonder-stuff-sentry/src/{collate-sentry-data.js => collate-sentry-data.ts} (90%) rename packages/wonder-stuff-sentry/src/{default-kind-error-data-options.js => default-kind-error-data-options.ts} (97%) rename packages/wonder-stuff-sentry/src/{empty-sentry-data.js => empty-sentry-data.ts} (63%) rename packages/wonder-stuff-sentry/src/{get-sentry-data-from-error.js => get-sentry-data-from-error.ts} (91%) rename packages/wonder-stuff-sentry/src/{index.js => index.ts} (96%) rename packages/wonder-stuff-sentry/src/{is-reserved-context-property.js => is-reserved-context-property.ts} (98%) rename packages/wonder-stuff-sentry/src/{is-reserved-tag-key.js => is-reserved-tag-key.ts} (98%) rename packages/wonder-stuff-sentry/src/{is-tag-key-valid.js => is-tag-key-valid.ts} (98%) rename packages/wonder-stuff-sentry/src/{kind-error-data.js => kind-error-data.ts} (90%) rename packages/wonder-stuff-sentry/src/{kind-sentry-error.js => kind-sentry-error.ts} (90%) rename packages/wonder-stuff-sentry/src/{normalize-sentry-data.js => normalize-sentry-data.ts} (89%) rename packages/wonder-stuff-sentry/src/{sentry-data-reducer.js => sentry-data-reducer.ts} (91%) rename packages/wonder-stuff-sentry/src/{truncate-tag-value.js => truncate-tag-value.ts} (98%) rename packages/wonder-stuff-sentry/src/{types.js => types.ts} (76%) rename packages/wonder-stuff-server-google/src/__tests__/__snapshots__/{trace-impl.test.js.snap => trace-impl.test.ts.snap} (100%) rename packages/wonder-stuff-server-google/src/__tests__/{add-app-engine-middleware.test.js => add-app-engine-middleware.test.ts} (74%) rename packages/wonder-stuff-server-google/src/__tests__/{get-app-engine-info.test.js => get-app-engine-info.test.ts} (96%) rename packages/wonder-stuff-server-google/src/__tests__/{get-appengine-request-id.test.js => get-appengine-request-id.test.ts} (83%) rename packages/wonder-stuff-server-google/src/__tests__/{get-delta.test.js => get-delta.test.ts} (66%) rename packages/wonder-stuff-server-google/src/__tests__/{setup-integrations.test.js => setup-integrations.test.ts} (72%) rename packages/wonder-stuff-server-google/src/__tests__/{start-server.test.js => start-server.test.ts} (86%) rename packages/wonder-stuff-server-google/src/__tests__/{trace-impl.test.js => trace-impl.test.ts} (73%) rename packages/wonder-stuff-server-google/src/__tests__/{trace.test.js => trace.test.ts} (76%) rename packages/wonder-stuff-server-google/src/{add-app-engine-middleware.js => add-app-engine-middleware.ts} (63%) rename packages/wonder-stuff-server-google/src/{get-app-engine-info.js => get-app-engine-info.ts} (98%) rename packages/wonder-stuff-server-google/src/{get-app-engine-request-id.js => get-app-engine-request-id.ts} (87%) rename packages/wonder-stuff-server-google/src/{get-default-log-metadata.js => get-default-log-metadata.ts} (79%) delete mode 100644 packages/wonder-stuff-server-google/src/get-delta.js create mode 100644 packages/wonder-stuff-server-google/src/get-delta.ts rename packages/wonder-stuff-server-google/src/{index.js => index.ts} (92%) rename packages/wonder-stuff-server-google/src/middleware/__tests__/{make-app-engine-request-id-middleware.test.js => make-app-engine-request-id-middleware.test.ts} (65%) rename packages/wonder-stuff-server-google/src/middleware/{make-app-engine-request-id-middleware.js => make-app-engine-request-id-middleware.ts} (80%) rename packages/wonder-stuff-server-google/src/{setup-integrations.js => setup-integrations.ts} (94%) rename packages/wonder-stuff-server-google/src/{start-server.js => start-server.ts} (86%) rename packages/wonder-stuff-server-google/src/{trace-impl.js => trace-impl.ts} (92%) rename packages/wonder-stuff-server-google/src/{trace.js => trace.ts} (89%) rename packages/wonder-stuff-server-google/src/{types.js => types.ts} (83%) rename packages/wonder-stuff-server/src/__tests__/__snapshots__/{get-logging-transport.test.js.snap => get-logging-transport.test.ts.snap} (100%) rename packages/wonder-stuff-server/src/__tests__/{create-logger.test.js => create-logger.test.ts} (72%) rename packages/wonder-stuff-server/src/__tests__/{get-agent-for-url.test.js => get-agent-for-url.test.ts} (99%) rename packages/wonder-stuff-server/src/__tests__/{get-logger.test.js => get-logger.test.ts} (67%) rename packages/wonder-stuff-server/src/__tests__/{get-logging-transport.test.js => get-logging-transport.test.ts} (74%) rename packages/wonder-stuff-server/src/__tests__/{get-request-logger.test.js => get-request-logger.test.ts} (77%) rename packages/wonder-stuff-server/src/__tests__/{get-runtime-mode.test.js => get-runtime-mode.test.ts} (76%) rename packages/wonder-stuff-server/src/__tests__/{root-logger.test.js => root-logger.test.ts} (84%) rename packages/wonder-stuff-server/src/__tests__/{start-server.test.js => start-server.test.ts} (87%) rename packages/wonder-stuff-server/src/{create-logger.js => create-logger.ts} (69%) rename packages/wonder-stuff-server/src/{errors.js => errors.ts} (99%) rename packages/wonder-stuff-server/src/{get-agent-for-url.js => get-agent-for-url.ts} (97%) rename packages/wonder-stuff-server/src/{get-logger.js => get-logger.ts} (88%) rename packages/wonder-stuff-server/src/{get-logging-transport.js => get-logging-transport.ts} (89%) rename packages/wonder-stuff-server/src/{get-request-logger.js => get-request-logger.ts} (82%) rename packages/wonder-stuff-server/src/{get-runtime-mode.js => get-runtime-mode.ts} (89%) rename packages/wonder-stuff-server/src/{index.js => index.ts} (98%) rename packages/wonder-stuff-server/src/middleware/__tests__/{default-error-logging.test.js => default-error-logging.test.ts} (81%) rename packages/wonder-stuff-server/src/middleware/__tests__/{default-request-logging.test.js => default-request-logging.test.ts} (81%) delete mode 100644 packages/wonder-stuff-server/src/middleware/default-error-logging.js create mode 100644 packages/wonder-stuff-server/src/middleware/default-error-logging.ts rename packages/wonder-stuff-server/src/middleware/{default-request-logging.js => default-request-logging.ts} (64%) rename packages/wonder-stuff-server/src/middleware/{index.js => index.ts} (93%) rename packages/wonder-stuff-server/src/{root-logger.js => root-logger.ts} (78%) rename packages/wonder-stuff-server/src/{start-server.js => start-server.ts} (90%) rename packages/wonder-stuff-server/src/{types.js => types.ts} (68%) rename packages/wonder-stuff-testing/src/__tests__/{data-factory-for.test.js => data-factory-for.test.ts} (65%) rename packages/wonder-stuff-testing/src/{data-factory-for.js => data-factory-for.ts} (89%) rename packages/wonder-stuff-testing/src/{index.js => index.ts} (90%) rename packages/wonder-stuff-testing/src/jest/__tests__/{isolate-modules.test.js => isolate-modules.test.ts} (99%) rename packages/wonder-stuff-testing/src/jest/__tests__/{wait.test.js => wait.test.ts} (99%) rename packages/wonder-stuff-testing/src/jest/{index.js => index.ts} (89%) rename packages/wonder-stuff-testing/src/jest/internal/__tests__/{assert-jest.test.js => assert-jest.test.ts} (98%) rename packages/wonder-stuff-testing/src/jest/internal/__tests__/{unverified-wait.test.js => unverified-wait.test.ts} (72%) rename packages/wonder-stuff-testing/src/jest/internal/__tests__/{verify-real-timers.test.js => verify-real-timers.test.ts} (99%) rename packages/wonder-stuff-testing/src/jest/internal/{assert-jest.js => assert-jest.ts} (97%) rename packages/wonder-stuff-testing/src/jest/internal/{is-running-in-jest.js => is-running-in-jest.ts} (97%) delete mode 100644 packages/wonder-stuff-testing/src/jest/internal/unverified-wait.js create mode 100644 packages/wonder-stuff-testing/src/jest/internal/unverified-wait.ts rename packages/wonder-stuff-testing/src/jest/internal/{verify-real-timers.js => verify-real-timers.ts} (94%) rename packages/wonder-stuff-testing/src/jest/{isolate-modules.js => isolate-modules.ts} (90%) rename packages/wonder-stuff-testing/src/jest/{wait.js => wait.ts} (93%) diff --git a/.changeset/fifty-grapes-guess.md b/.changeset/fifty-grapes-guess.md new file mode 100644 index 00000000..2256e8ed --- /dev/null +++ b/.changeset/fifty-grapes-guess.md @@ -0,0 +1,11 @@ +--- +"@khanacademy/wonder-stuff-server-google": minor +"@khanacademy/wonder-stuff-testing": minor +"@khanacademy/wonder-stuff-sentry": minor +"@khanacademy/wonder-stuff-server": minor +"@khanacademy/eslint-config": minor +"@khanacademy/wonder-stuff-core": minor +"@khanacademy/wonder-stuff-i18n": minor +--- + +Migrate to TypeScript diff --git a/flow-typed/@google-cloud/logging-winston.js b/flow-typed/@google-cloud/logging-winston.js deleted file mode 100644 index a3729c76..00000000 --- a/flow-typed/@google-cloud/logging-winston.js +++ /dev/null @@ -1,37 +0,0 @@ -// @flow -declare module "@google-cloud/logging-winston" { - declare type loggingwinston$Callback = ( - err: Error, - apiResponse: {...}, - ) => void; - - declare interface loggingwinston$Options { - // TODO: Fill this out - } - declare class loggingwinston$LoggingWinston extends $winstonTransport { - constructor(options?: loggingwinston$Options): this; - log(info: any, callback: loggingwinston$Callback): void; - } - - declare interface loggingwinston$express { - makeMiddleware< - Req: express$Request = express$Request, - Res: express$Response = express$Response, - >( - logger: $winstonLogger<$winstonNpmLogLevels>, - transport: loggingwinston$LoggingWinston, - ): Promise>; - makeMiddleware< - Req: express$Request = express$Request, - Res: express$Response = express$Response, - >( - logger: $winstonLogger<$winstonNpmLogLevels>, - options?: loggingwinston$Options, - ): Promise>; - } - - declare module.exports: { - LoggingWinston: typeof loggingwinston$LoggingWinston, - express: loggingwinston$express, - }; -} diff --git a/flow-typed/express-winston.js b/flow-typed/express-winston.js deleted file mode 100644 index 782e06e6..00000000 --- a/flow-typed/express-winston.js +++ /dev/null @@ -1,51 +0,0 @@ -// @flow -declare module "express-winston" { - declare type express$Handler = ( - req: express$Request, - res: express$Response, - next: express$NextFunction, - ) => mixed; - declare type express$ErrorRequestHandler = ( - error: Error, - req: express$Request, - res: express$Response, - next: express$NextFunction, - ) => mixed; - - declare interface expresswinston$BaseLoggerOptions { - expressFormat?: boolean; - format?: $winstonFormat; - level?: string; - meta?: boolean; - } - - declare type expresswinston$LoggerOptionsWithTransports = { - transports?: Array<$winstonTransport>, - ... - } & expresswinston$BaseLoggerOptions; - - declare type expresswinston$LoggerOptions = expresswinston$LoggerOptionsWithTransports; - - declare function expresswinston$logger( - options: expresswinston$LoggerOptions, - ): express$Handler; - - declare interface expresswinston$BaseErrorLoggerOptions { - level?: string; - } - - declare type expresswinston$ErrorLoggerOptionsWithTransports = { - transports?: Array<$winstonTransport>, - ... - } & expresswinston$BaseErrorLoggerOptions; - - declare type expresswinston$ErrorLoggerOptions = expresswinston$ErrorLoggerOptionsWithTransports; - declare function expresswinston$errorLogger( - options: expresswinston$ErrorLoggerOptions, - ): express$ErrorRequestHandler; - - declare module.exports: { - logger: typeof expresswinston$logger, - errorLogger: typeof expresswinston$errorLogger, - }; -} diff --git a/flow-typed/superagent.js b/flow-typed/superagent.js deleted file mode 100644 index fff0bc0d..00000000 --- a/flow-typed/superagent.js +++ /dev/null @@ -1,308 +0,0 @@ -// @flow -declare type superagent$CallbackHandler = ( - err: any, - res: ?superagent$Response, -) => ?boolean; - -declare type superagent$Serializer = (obj: any) => string; - -declare type superagent$BrowserParser = (str: string) => any; - -declare type superagent$NodeParser = ( - res: superagent$Response, - callback: (err: Error | null, body: any) => void, -) => void; - -declare type superagent$Parser = - | superagent$BrowserParser - | superagent$NodeParser; - -declare type superagent$MultipartValueSingle = - | Blob - | Buffer - | stream$Readable - | string - | boolean - | number; - -declare type superagent$MultipartValue = - | superagent$MultipartValueSingle - | superagent$MultipartValueSingle[]; - -declare interface superagent$SuperAgentRequest extends superagent$Request { - agent<+SocketT = net$Socket>( - agent?: http$Agent, - ): superagent$SuperAgentRequest; -} - -declare type cookiejar$CookieJar = $FlowFixMe; - -declare interface superagent$SuperAgentStatic extends stream$Stream { - (url: string): superagent$SuperAgentRequest; - (method: string, url: string): superagent$SuperAgentRequest; - - agent(): superagent$SuperAgentStatic & superagent$Request; - serialize: {[type: string]: superagent$Serializer}; - parse: {[type: string]: superagent$Parser}; - - jar: cookiejar$CookieJar; - attachCookies(req: superagent$SuperAgentRequest): void; - checkout( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - connect( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - copy( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - del( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - delete( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - get( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - head( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - lock( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - merge( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - mkactivity( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - mkcol( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - move( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - notify( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - options( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - patch( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - post( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - propfind( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - proppatch( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - purge( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - put( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - report( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - saveCookies(res: superagent$Response): void; - search( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - subscribe( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - trace( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - unlock( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; - unsubscribe( - url: string, - callback?: superagent$CallbackHandler, - ): superagent$SuperAgentRequest; -} - -declare interface superagent$HTTPError extends Error { - status: number; - text: string; - method: string; - path: string; -} - -declare interface superagent$Response extends stream$Readable { - accepted: boolean; - badRequest: boolean; - body: any; - charset: string; - clientError: boolean; - error: false | superagent$HTTPError; - files: any; - forbidden: boolean; - get(header: string): string; - get(header: "Set-Cookie"): string[]; - header: any; - info: boolean; - links: {...}; - noContent: boolean; - notAcceptable: boolean; - notFound: boolean; - ok: boolean; - redirect: boolean; - serverError: boolean; - status: number; - statusType: number; - text: string; - type: string; - unauthorized: boolean; - xhr: XMLHttpRequest; - redirects: string[]; -} - -declare interface superagent$Request extends Promise { - cookies: string; - method: string; - url: string; - abort(): void; - accept(type: string): superagent$Request; - attach( - field: string, - file: superagent$MultipartValueSingle, - options?: string | {filename?: string, contentType?: string}, - ): superagent$Request; - auth( - user: string, - pass: string, - options?: {type: "basic" | "auto"}, - ): superagent$Request; - auth(token: string, options: {type: "bearer"}): superagent$Request; - buffer(val?: boolean): superagent$Request; - ca(cert: string | string[] | Buffer | Buffer[]): superagent$Request; - cert(cert: string | string[] | Buffer | Buffer[]): superagent$Request; - clearTimeout(): superagent$Request; - disableTLSCerts(): superagent$Request; - end(callback?: superagent$CallbackHandler): void; - field(name: string, val: superagent$MultipartValue): superagent$Request; - field(fields: { - [fieldName: string]: superagent$MultipartValue, - }): superagent$Request; - get(field: string): string; - key(cert: string | string[] | Buffer | Buffer[]): superagent$Request; - ok(callback: (res: superagent$Response) => boolean): superagent$Request; - on(name: "error", handler: (err: any) => void): superagent$Request; - on( - name: "progress", - handler: (event: superagent$ProgressEvent) => void, - ): superagent$Request; - on( - name: "response", - handler: (response: superagent$Response) => void, - ): superagent$Request; - on(name: string, handler: (event: any) => void): superagent$Request; - parse(parser: superagent$Parser): superagent$Request; - part(): superagent$Request; - pfx( - cert: - | string - | string[] - | Buffer - | Buffer[] - | {pfx: string | Buffer, passphrase: string}, - ): superagent$Request; - pipe(stream: stream$Writable, options?: {...}): stream$Writable; - query(val: {...} | string): superagent$Request; - redirects(n: number): superagent$Request; - responseType(type: string): superagent$Request; - retry( - count?: number, - callback?: superagent$CallbackHandler, - ): superagent$Request; - send(data?: string | {...}): superagent$Request; - serialize(serializer: superagent$Serializer): superagent$Request; - set(field: {...}): superagent$Request; - set(field: string, val: string): superagent$Request; - set(field: "Cookie", val: string[]): superagent$Request; - timeout( - ms: number | {deadline?: number, response?: number}, - ): superagent$Request; - trustLocalhost(enabled?: boolean): superagent$Request; - type(val: string): superagent$Request; - unset(field: string): superagent$Request; - use(fn: superagent$Plugin): superagent$Request; - withCredentials(): superagent$Request; - write(data: string | Buffer, encoding?: string): superagent$Request; - maxResponseSize(size: number): superagent$Request; - - /** - * Added by superagent-cache-plugin - */ - cacheWhenEmpty(cacheWhenEmpty: boolean): superagent$Response; - doQuery(doQuery: boolean): superagent$Request; - expiration(expiration: ?number): superagent$Request; - forceUpdate(forceUpdate: ?boolean): superagent$Request; - pruneQuery(pruneQuery: Array): superagent$Request; - pruneHeader(pruneHeader: Array): superagent$Request; - prune( - prune: ( - response: superagent$Response, - gutResponse: (superagent$Response) => any, - ) => any, - ): superagent$Request; - responseProp(responseProp: string): superagent$Request; -} - -declare type superagent$Plugin = (req: superagent$SuperAgentRequest) => void; - -declare type superagent$ProgressEvent = { - direction: "download" | "upload", - loaded: number, - percent?: number, - total?: number, -}; - -declare module "superagent" { - declare export type CallbackHandler = superagent$CallbackHandler; - declare export type Serializer = superagent$Serializer; - declare export type BrowserParser = superagent$BrowserParser; - declare export type NodeParser = superagent$NodeParser; - declare export type Parser = superagent$Parser; - declare export type MultipartValueSingle = superagent$MultipartValueSingle; - declare export type MultipartValue = superagent$MultipartValue; - declare export type Response = superagent$Response; - declare export type SuperAgentRequest = superagent$SuperAgentRequest; - declare export type Request = superagent$Request; - declare export type Plugin = superagent$Plugin; - - declare module.exports: superagent$SuperAgentStatic; -} diff --git a/packages/eslint-config-khan/.prettierrc.js b/packages/eslint-config-khan/.prettierrc.js index 453b9c46..5c735889 100644 --- a/packages/eslint-config-khan/.prettierrc.js +++ b/packages/eslint-config-khan/.prettierrc.js @@ -1,5 +1,4 @@ /* eslint-disable import/no-commonjs */ -// @flow module.exports = { printWidth: 80, tabWidth: 4, diff --git a/packages/wonder-stuff-core/src/__tests__/__snapshots__/build-caused-by-message.test.js.snap b/packages/wonder-stuff-core/src/__tests__/__snapshots__/build-caused-by-message.test.ts.snap similarity index 100% rename from packages/wonder-stuff-core/src/__tests__/__snapshots__/build-caused-by-message.test.js.snap rename to packages/wonder-stuff-core/src/__tests__/__snapshots__/build-caused-by-message.test.ts.snap diff --git a/packages/wonder-stuff-core/src/__tests__/__snapshots__/errors-from-error.test.js.snap b/packages/wonder-stuff-core/src/__tests__/__snapshots__/errors-from-error.test.ts.snap similarity index 100% rename from packages/wonder-stuff-core/src/__tests__/__snapshots__/errors-from-error.test.js.snap rename to packages/wonder-stuff-core/src/__tests__/__snapshots__/errors-from-error.test.ts.snap diff --git a/packages/wonder-stuff-core/src/__tests__/__snapshots__/kind-error.test.js.snap b/packages/wonder-stuff-core/src/__tests__/__snapshots__/kind-error.test.ts.snap similarity index 100% rename from packages/wonder-stuff-core/src/__tests__/__snapshots__/kind-error.test.js.snap rename to packages/wonder-stuff-core/src/__tests__/__snapshots__/kind-error.test.ts.snap diff --git a/packages/wonder-stuff-core/src/__tests__/build-caused-by-message.test.js b/packages/wonder-stuff-core/src/__tests__/build-caused-by-message.test.ts similarity index 95% rename from packages/wonder-stuff-core/src/__tests__/build-caused-by-message.test.js rename to packages/wonder-stuff-core/src/__tests__/build-caused-by-message.test.ts index 9a0c1730..ab19d3da 100644 --- a/packages/wonder-stuff-core/src/__tests__/build-caused-by-message.test.js +++ b/packages/wonder-stuff-core/src/__tests__/build-caused-by-message.test.ts @@ -1,4 +1,3 @@ -// @flow import {buildCausedByMessage} from "../build-caused-by-message"; describe("#buildCausedByMessage", () => { @@ -20,7 +19,7 @@ describe("#buildCausedByMessage", () => { it.each([null, undefined])( "should only include cause if it is non-null", - (testCase) => { + (testCase: any) => { // Arrange const consequence = "No more Halloween candy"; const cause = testCase; @@ -35,7 +34,7 @@ describe("#buildCausedByMessage", () => { it.each([null, undefined])( "should default nullish consequences to (empty message)", - (testCase) => { + (testCase: any) => { // Arrange const consequence = testCase; const cause = null; @@ -50,7 +49,7 @@ describe("#buildCausedByMessage", () => { it.each([" ", "\n\t\t"])( "should default whitespace strings to (empty message)", - (testCase) => { + (testCase: any) => { // Arrange const consequence = testCase; const cause = testCase; diff --git a/packages/wonder-stuff-core/src/__tests__/clone-metadata.test.js b/packages/wonder-stuff-core/src/__tests__/clone-metadata.test.ts similarity index 67% rename from packages/wonder-stuff-core/src/__tests__/clone-metadata.test.js rename to packages/wonder-stuff-core/src/__tests__/clone-metadata.test.ts index fea6cc20..0c21b0dc 100644 --- a/packages/wonder-stuff-core/src/__tests__/clone-metadata.test.js +++ b/packages/wonder-stuff-core/src/__tests__/clone-metadata.test.ts @@ -1,10 +1,9 @@ -// @flow import {cloneMetadata} from "../clone-metadata"; describe("#cloneMetadata", () => { it.each([undefined, null])( "should return the metadata when it is %s", - (value) => { + (value: any) => { // Arrange // Act @@ -34,15 +33,19 @@ describe("#cloneMetadata", () => { boolean: "true", undefined: undefined, null: null, - }; + } as const; // Act const result = cloneMetadata(metadata); + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'string' because it is a read-only property. metadata.string = "baz"; + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'number' because it is a read-only property. metadata.number = "43"; + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'boolean' because it is a read-only property. metadata.boolean = "false"; + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'undefined' because it is a read-only property. metadata.undefined = "foo"; - // $FlowIgnore[incompatible-type] + // @ts-expect-error [FEI-5011] - TS2704 - The operand of a 'delete' operator cannot be a read-only property. | TS2790 - The operand of a 'delete' operator must be optional. delete metadata.null; // Assert @@ -60,10 +63,12 @@ describe("#cloneMetadata", () => { // Arrange const metadata = { array: [1, 2, 3], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly array: readonly [1, 2, 3]; }' is not assignable to parameter of type 'Readonly'. const result = cloneMetadata(metadata); + // @ts-expect-error [FEI-5011] - TS2339 - Property 'push' does not exist on type 'readonly [1, 2, 3]'. metadata.array.push(4); // Assert @@ -80,10 +85,11 @@ describe("#cloneMetadata", () => { a: 1, b: 2, }, - }; + } as const; // Act const result = cloneMetadata(metadata); + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'a' because it is a read-only property. metadata.object.a = 3; // Assert @@ -113,10 +119,12 @@ describe("#cloneMetadata", () => { ], }, }, - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly object: { readonly a: 1; readonly b: 2; readonly c: { readonly d: 3; readonly e: readonly [4, 5, { readonly nested: "in here"; }]; }; }; }' is not assignable to parameter of type 'Readonly'. const result = cloneMetadata(metadata); + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'nested' because it is a read-only property. metadata.object.c.e[2].nested = "in there"; // Assert diff --git a/packages/wonder-stuff-core/src/__tests__/clone.test.js b/packages/wonder-stuff-core/src/__tests__/clone.test.ts similarity index 95% rename from packages/wonder-stuff-core/src/__tests__/clone.test.js rename to packages/wonder-stuff-core/src/__tests__/clone.test.ts index d1c402fc..17e336a6 100644 --- a/packages/wonder-stuff-core/src/__tests__/clone.test.js +++ b/packages/wonder-stuff-core/src/__tests__/clone.test.ts @@ -1,10 +1,9 @@ -// @flow import {clone} from "../clone"; describe("#clone", () => { it.each([undefined, null])( "should return the value when it is %s", - (value) => { + (value: any) => { // Arrange // Act @@ -23,7 +22,7 @@ describe("#clone", () => { boolean: "true", undefined: undefined, null: null, - }; + } as const; // Act const result = clone(originalValue); @@ -37,7 +36,7 @@ describe("#clone", () => { // Arrange const originalValue = { array: [1, 2, 3], - }; + } as const; // Act const result = clone(originalValue); @@ -54,7 +53,7 @@ describe("#clone", () => { a: 1, b: 2, }, - }; + } as const; // Act const result = clone(originalValue); @@ -81,7 +80,7 @@ describe("#clone", () => { ], }, }, - }; + } as const; // Act const result = clone(originalValue); diff --git a/packages/wonder-stuff-core/src/__tests__/entries.flowtest.js b/packages/wonder-stuff-core/src/__tests__/entries.flowtest.ts similarity index 70% rename from packages/wonder-stuff-core/src/__tests__/entries.flowtest.js rename to packages/wonder-stuff-core/src/__tests__/entries.flowtest.ts index e47ebd75..6dfba467 100644 --- a/packages/wonder-stuff-core/src/__tests__/entries.flowtest.js +++ b/packages/wonder-stuff-core/src/__tests__/entries.flowtest.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module '../entries' or its corresponding type declarations. import {entries} from "../entries"; { @@ -7,12 +7,12 @@ import {entries} from "../entries"; a: 1, b: "2", c: [3, 4], - }; + } as const; const entries1 = entries(obj1); // This works because the keys are all strings - const [_]: [string, mixed] = entries1[0]; + const [_]: [string, unknown] = entries1[0]; } { @@ -21,16 +21,15 @@ import {entries} from "../entries"; a: 1, b: "2", c: [3, 4], - }; + } as const; const entries2 = entries(obj2); // This works because the returned tuple type is of a supertype of all key // names and the value type (which we don't care about for this flow check). - const [_]: ["a" | "b" | "c", mixed] = entries2[0]; + const [_]: ["a" | "b" | "c", unknown] = entries2[0]; // This errors because we try to get a key of only one type. - // $FlowExpectedError[incompatible-type] - const [__]: ["a", mixed] = entries2[0]; + const [__]: ["a", unknown] = entries2[0]; } { @@ -39,7 +38,7 @@ import {entries} from "../entries"; a: 1, b: "2", c: [3, 4], - }; + } as const; const entries1 = entries(obj1); @@ -48,14 +47,15 @@ import {entries} from "../entries"; const [_, __]: [string, number | string | Array] = entries1[0]; // This errors because not all values are a number. - // $FlowExpectedError[incompatible-type] const [___, ____]: [string, number] = entries1[0]; } { // should work with class instances class Foo { + // @ts-expect-error [FEI-5011] - TS2564 - Property 'a' has no initializer and is not definitely assigned in the constructor. a: string; + // @ts-expect-error [FEI-5011] - TS2564 - Property 'b' has no initializer and is not definitely assigned in the constructor. b: string; } const foo = new Foo(); diff --git a/packages/wonder-stuff-core/src/__tests__/entries.test.js b/packages/wonder-stuff-core/src/__tests__/entries.test.ts similarity index 85% rename from packages/wonder-stuff-core/src/__tests__/entries.test.js rename to packages/wonder-stuff-core/src/__tests__/entries.test.ts index 5503d947..51e56aa6 100644 --- a/packages/wonder-stuff-core/src/__tests__/entries.test.js +++ b/packages/wonder-stuff-core/src/__tests__/entries.test.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module '../entries' or its corresponding type declarations. import {entries} from "../entries"; describe("#entries", () => { @@ -9,7 +9,7 @@ describe("#entries", () => { a: 1, b: "2", c: [3, 4], - }; + } as const; // Act entries(obj); @@ -24,7 +24,7 @@ describe("#entries", () => { a: 1, b: "2", c: [3, 4], - }; + } as const; jest.spyOn(Object, "entries").mockReturnValueOnce([ ["e", 1], ["f", 2], diff --git a/packages/wonder-stuff-core/src/__tests__/error-info.test.js b/packages/wonder-stuff-core/src/__tests__/error-info.test.ts similarity index 92% rename from packages/wonder-stuff-core/src/__tests__/error-info.test.js rename to packages/wonder-stuff-core/src/__tests__/error-info.test.ts index 0a570e86..52926169 100644 --- a/packages/wonder-stuff-core/src/__tests__/error-info.test.js +++ b/packages/wonder-stuff-core/src/__tests__/error-info.test.ts @@ -1,4 +1,3 @@ -// @flow import * as BuildCausedByMessage from "../build-caused-by-message"; import {ErrorInfo} from "../error-info"; @@ -77,6 +76,7 @@ describe("ErrorInfo", () => { // Act const act = () => // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'null' is not assignable to parameter of type 'ErrorInfo'. ErrorInfo.fromConsequenceAndCause(null, cause); // Assert @@ -96,6 +96,7 @@ describe("ErrorInfo", () => { // Act const act = () => // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'null' is not assignable to parameter of type 'ErrorInfo'. ErrorInfo.fromConsequenceAndCause(consequence, null); // Assert @@ -134,6 +135,7 @@ describe("ErrorInfo", () => { // Act const act = () => // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'null' is not assignable to parameter of type 'ErrorInfo'. ErrorInfo.fromConsequenceAndCause(null, cause); // Assert @@ -153,6 +155,7 @@ describe("ErrorInfo", () => { // Act const act = () => // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'null' is not assignable to parameter of type 'ErrorInfo'. ErrorInfo.fromConsequenceAndCause(consequence, null); // Assert @@ -260,7 +263,7 @@ describe("ErrorInfo", () => { describe("when not built for production", () => { it("should throw if error is not an Error", () => { // Arrange - // $FlowIgnore[incompatible-type] + // @ts-expect-error [FEI-5011] - TS2739 - Type '{}' is missing the following properties from type 'Error': name, message const error: Error = {}; // Act @@ -306,7 +309,7 @@ describe("ErrorInfo", () => { it("should not throw if error is not an Error", () => { // Arrange - // $FlowIgnore[incompatible-type] + // @ts-expect-error [FEI-5011] - TS2739 - Type '{}' is missing the following properties from type 'Error': name, message const error: Error = {}; // Act @@ -395,6 +398,7 @@ describe("ErrorInfo", () => { // Arrange const error = new Error("test"); const stackAndToString = "Error: test\nframe1\nframe2\nframe3"; + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. | TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. jest.spyOn(error, "toString").mockReturnValue(stackAndToString); error.stack = stackAndToString; @@ -413,7 +417,6 @@ describe("ErrorInfo", () => { it("should create an empty stack array if there is no stack", () => { // Arrange const error = new Error("test"); - // $FlowIgnore[incompatible-type] delete error.stack; // Act @@ -428,7 +431,7 @@ describe("ErrorInfo", () => { describe("when not built for production", () => { it("should throw if error is not an Error", () => { // Arrange - // $FlowIgnore[incompatible-type] + // @ts-expect-error [FEI-5011] - TS2739 - Type '{}' is missing the following properties from type 'Error': name, message const error: Error = {}; // Act @@ -448,7 +451,7 @@ describe("ErrorInfo", () => { it("should not throw if error is not an Error", () => { // Arrange - // $FlowIgnore[incompatible-type] + // @ts-expect-error [FEI-5011] - TS2739 - Type '{}' is missing the following properties from type 'Error': name, message const error: Error = {}; // Act @@ -502,6 +505,7 @@ describe("ErrorInfo", () => { // Arrange const error = new Error("test"); const stackAndToString = "Error: test\nframe1\nframe2\nframe3"; + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. | TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. jest.spyOn(error, "toString").mockReturnValue(stackAndToString); error.stack = stackAndToString; @@ -520,7 +524,6 @@ describe("ErrorInfo", () => { it("should create an empty stack array if there is no stack", () => { // Arrange const error = new Error("test"); - // $FlowIgnore[incompatible-type] delete error.stack; // Act diff --git a/packages/wonder-stuff-core/src/__tests__/errors-from-error.test.js b/packages/wonder-stuff-core/src/__tests__/errors-from-error.test.ts similarity index 83% rename from packages/wonder-stuff-core/src/__tests__/errors-from-error.test.js rename to packages/wonder-stuff-core/src/__tests__/errors-from-error.test.ts index ef8c4ca5..9f7f333f 100644 --- a/packages/wonder-stuff-core/src/__tests__/errors-from-error.test.js +++ b/packages/wonder-stuff-core/src/__tests__/errors-from-error.test.ts @@ -1,4 +1,3 @@ -// @flow import {KindError} from "../kind-error"; import {errorsFromError, Order} from "../errors-from-error"; @@ -7,11 +6,12 @@ import type {Options as KindErrorOptions} from "../kind-error"; describe("#errorsFromError", () => { it.each([null, undefined, "NOT_A_GOOD_VALUE", 42])( "should throw if the order is invalid", - (testCase) => { + (testCase: any) => { // Arrange const error = new Error("test"); // Act + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. const act = () => Array.from(errorsFromError(error, testCase)); // Assert @@ -21,15 +21,17 @@ describe("#errorsFromError", () => { it.each([null, undefined])( "should yield an empty sequence if the error is nullish", - (error) => { + (error: any) => { // Arrange // Act const result = Array.from( + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. errorsFromError(error, Order.ConsequenceFirst), ); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeEmpty' does not exist on type 'JestMatchers'. expect(result).toBeEmpty(); }, ); @@ -40,6 +42,7 @@ describe("#errorsFromError", () => { // Act const result = Array.from( + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. errorsFromError(error, Order.ConsequenceFirst), ); @@ -64,6 +67,7 @@ describe("#errorsFromError", () => { // Act const result = Array.from( + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. errorsFromError(rootError, Order.ConsequenceFirst), ); @@ -89,6 +93,7 @@ describe("#errorsFromError", () => { // Act const result = Array.from( + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. errorsFromError(rootError, Order.CauseFirst), ); diff --git a/packages/wonder-stuff-core/src/__tests__/errors.test.js b/packages/wonder-stuff-core/src/__tests__/errors.test.ts similarity index 61% rename from packages/wonder-stuff-core/src/__tests__/errors.test.js rename to packages/wonder-stuff-core/src/__tests__/errors.test.ts index f7150601..47e4e7fd 100644 --- a/packages/wonder-stuff-core/src/__tests__/errors.test.js +++ b/packages/wonder-stuff-core/src/__tests__/errors.test.ts @@ -1,4 +1,3 @@ -// @flow import {Errors} from "../errors"; describe("Errors", () => { @@ -9,6 +8,7 @@ describe("Errors", () => { const result = Object.isFrozen(Errors); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeTrue' does not exist on type 'JestMatchers'. expect(result).toBeTrue(); }); @@ -17,10 +17,11 @@ describe("Errors", () => { // Act const result = Object.values(Errors).every( - (v) => typeof v === "string", + (v: any) => typeof v === "string", ); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeTrue' does not exist on type 'JestMatchers'. expect(result).toBeTrue(); }); }); diff --git a/packages/wonder-stuff-core/src/__tests__/get-kind-from-error.test.js b/packages/wonder-stuff-core/src/__tests__/get-kind-from-error.test.ts similarity index 96% rename from packages/wonder-stuff-core/src/__tests__/get-kind-from-error.test.js rename to packages/wonder-stuff-core/src/__tests__/get-kind-from-error.test.ts index d4b48d6e..9844f677 100644 --- a/packages/wonder-stuff-core/src/__tests__/get-kind-from-error.test.js +++ b/packages/wonder-stuff-core/src/__tests__/get-kind-from-error.test.ts @@ -1,4 +1,3 @@ -// @flow import {Errors} from "../errors"; import {getKindFromError} from "../get-kind-from-error"; import {KindError} from "../kind-error"; @@ -6,7 +5,7 @@ import {KindError} from "../kind-error"; describe("#getKindFromError", () => { it.each([null, undefined, new Error("test")])( "should return Errors.Unknown for a non-KindError value like %s", - (error) => { + (error: any) => { // Arrange // Act diff --git a/packages/wonder-stuff-core/src/__tests__/get-original-stack-from-error.test.js b/packages/wonder-stuff-core/src/__tests__/get-original-stack-from-error.test.ts similarity index 99% rename from packages/wonder-stuff-core/src/__tests__/get-original-stack-from-error.test.js rename to packages/wonder-stuff-core/src/__tests__/get-original-stack-from-error.test.ts index 2e717a41..6b22275f 100644 --- a/packages/wonder-stuff-core/src/__tests__/get-original-stack-from-error.test.js +++ b/packages/wonder-stuff-core/src/__tests__/get-original-stack-from-error.test.ts @@ -1,4 +1,3 @@ -// @flow import {getOriginalStackFromError} from "../get-original-stack-from-error"; import {KindError} from "../kind-error"; diff --git a/packages/wonder-stuff-core/src/__tests__/keys.flowtest.js b/packages/wonder-stuff-core/src/__tests__/keys.flowtest.ts similarity index 71% rename from packages/wonder-stuff-core/src/__tests__/keys.flowtest.js rename to packages/wonder-stuff-core/src/__tests__/keys.flowtest.ts index b096648c..7ebfe77b 100644 --- a/packages/wonder-stuff-core/src/__tests__/keys.flowtest.js +++ b/packages/wonder-stuff-core/src/__tests__/keys.flowtest.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module '../keys' or its corresponding type declarations. import {keys} from "../keys"; { @@ -6,7 +6,7 @@ import {keys} from "../keys"; const obj1 = { a: 1, b: "2", - }; + } as const; const keys1 = keys(obj1); const _: string = keys1[0]; @@ -18,7 +18,7 @@ import {keys} from "../keys"; a: 1, b: "2", c: [3, 4], - }; + } as const; // This works because the return type is an array of a supertype of all key // names, thanks to $Keys<>. @@ -28,14 +28,15 @@ import {keys} from "../keys"; // This errors because we try to get a key of only one type. Flow sees this // as a bad call rather than a bad assignment. Hence the expectation on // the callsite, not the assignment. - // $FlowExpectedError[incompatible-call] const keys2bad = keys(obj2); const __: "a" = keys2bad[0]; } { // should work with more specific object types - const obj3: {|[string]: string|} = { + const obj3: { + [key: string]: string; + } = { a: "1", b: "2", }; @@ -47,7 +48,9 @@ import {keys} from "../keys"; { // should work with class instances class Foo { + // @ts-expect-error [FEI-5011] - TS2564 - Property 'a' has no initializer and is not definitely assigned in the constructor. a: string; + // @ts-expect-error [FEI-5011] - TS2564 - Property 'b' has no initializer and is not definitely assigned in the constructor. b: string; } const foo = new Foo(); diff --git a/packages/wonder-stuff-core/src/__tests__/keys.test.js b/packages/wonder-stuff-core/src/__tests__/keys.test.ts similarity index 72% rename from packages/wonder-stuff-core/src/__tests__/keys.test.js rename to packages/wonder-stuff-core/src/__tests__/keys.test.ts index 25149893..844d2fd5 100644 --- a/packages/wonder-stuff-core/src/__tests__/keys.test.js +++ b/packages/wonder-stuff-core/src/__tests__/keys.test.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module '../keys' or its corresponding type declarations. import {keys} from "../keys"; describe("#keys", () => { @@ -9,7 +9,7 @@ describe("#keys", () => { a: 1, b: "2", c: [3, 4], - }; + } as const; // Act keys(obj); @@ -24,7 +24,8 @@ describe("#keys", () => { a: 1, b: "2", c: [3, 4], - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'string[]'. jest.spyOn(Object, "keys").mockReturnValueOnce("THE RESULT"); // Act diff --git a/packages/wonder-stuff-core/src/__tests__/kind-error.test.js b/packages/wonder-stuff-core/src/__tests__/kind-error.test.ts similarity index 94% rename from packages/wonder-stuff-core/src/__tests__/kind-error.test.js rename to packages/wonder-stuff-core/src/__tests__/kind-error.test.ts index 1818209d..95051747 100644 --- a/packages/wonder-stuff-core/src/__tests__/kind-error.test.js +++ b/packages/wonder-stuff-core/src/__tests__/kind-error.test.ts @@ -1,4 +1,3 @@ -// @flow import * as CloneMetadata from "../clone-metadata"; import {ErrorInfo} from "../error-info"; import {Errors} from "../errors"; @@ -64,6 +63,7 @@ describe("KindError", () => { const error = new KindError("MESSAGE"); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toEndWith' does not exist on type 'JestMatchers'. expect(error.name).toEndWith("Error"); }); @@ -76,13 +76,14 @@ describe("KindError", () => { }); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toEndWith' does not exist on type 'JestMatchers'. expect(error.name).toEndWith("CUSTOM_NAMEError"); }); describe("when not built for production", () => { it.each(["N A M E", "NA\nME"])( "should throw if the name has whitespace like %s", - (name) => { + (name: any) => { // Arrange // Act @@ -96,7 +97,7 @@ describe("KindError", () => { it.each(["K I N D", "KI\nND"])( "should throw if the kind has whitespace like %s", - (kind) => { + (kind: any) => { // Arrange // Act @@ -109,7 +110,7 @@ describe("KindError", () => { it.each(["P R E F I X", "PRE\nFIX"])( "should throw if the prefix has whitespace like %s", - (prefix) => { + (prefix: any) => { // Arrange // Act @@ -159,7 +160,7 @@ describe("KindError", () => { it.each(["N A M E", "NA\nME"])( "should not throw validation error if the name has whitespace like %s", - (name) => { + (name: any) => { // Arrange // Act @@ -175,7 +176,7 @@ describe("KindError", () => { it.each(["K I N D", "KI\nND"])( "should not throw validation error if the kind has whitespace like %s", - (kind) => { + (kind: any) => { // Arrange // Act @@ -190,7 +191,7 @@ describe("KindError", () => { it.each(["P R E F I X", "PRE\nFIX"])( "should not throw validation error if the prefix has whitespace like %s", - (prefix) => { + (prefix: any) => { // Arrange // Act @@ -235,9 +236,10 @@ describe("KindError", () => { // Arrange const metadata = { foo: "bar", - }; + } as const; const cloneMetadataSpy = jest .spyOn(CloneMetadata, "cloneMetadata") + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '"CLONED_METADATA"' is not assignable to parameter of type 'Readonly | null | undefined'. .mockReturnValue("CLONED_METADATA"); // Act @@ -307,6 +309,7 @@ describe("KindError", () => { const act = () => new KindError("MESSAGE", Errors.Unknown, { // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string' is not assignable to type 'Error | null | undefined'. cause: "NOT_AN_ERROR", }); @@ -329,6 +332,7 @@ describe("KindError", () => { const act = () => new KindError("MESSAGE", Errors.Unknown, { // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string' is not assignable to type 'Error | null | undefined'. cause: "NOT_AN_ERROR", }); @@ -464,7 +468,7 @@ describe("KindError", () => { describe.each([undefined, null, false])( "when composite stack is %s", - (compositeStackValue) => { + (compositeStackValue: any) => { it("should set the stack to the normalized stack, not the combined stack", () => { // Arrange const normalizedErrorInfo = new ErrorInfo( diff --git a/packages/wonder-stuff-core/src/__tests__/safe-stringify.test.js b/packages/wonder-stuff-core/src/__tests__/safe-stringify.test.ts similarity index 87% rename from packages/wonder-stuff-core/src/__tests__/safe-stringify.test.js rename to packages/wonder-stuff-core/src/__tests__/safe-stringify.test.ts index 71832c34..3c149b70 100644 --- a/packages/wonder-stuff-core/src/__tests__/safe-stringify.test.js +++ b/packages/wonder-stuff-core/src/__tests__/safe-stringify.test.ts @@ -1,4 +1,3 @@ -// @flow import {safeStringify} from "../safe-stringify"; describe("#safeStringify", () => { @@ -8,7 +7,7 @@ describe("#safeStringify", () => { const value = { a: 1, b: 2, - }; + } as const; // Act const result = safeStringify(value); @@ -21,7 +20,7 @@ describe("#safeStringify", () => { describe("with default value argument", () => { it.each([null, undefined])( "should return the default for nullish values", - (value) => { + (value: any) => { // Arrange const defaultValue = "default"; @@ -50,6 +49,7 @@ describe("#safeStringify", () => { it("should return the default if JSON.stringify returns a nullish value", () => { // Arrange const defaultValue = "default"; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'undefined' is not assignable to parameter of type 'string'. jest.spyOn(JSON, "stringify").mockReturnValue(undefined); // Act @@ -63,11 +63,11 @@ describe("#safeStringify", () => { describe("with options argument", () => { it.each([null, undefined])( "should return the default for nullish values", - (value) => { + (value: any) => { // Arrange const options = { defaultValue: "default", - }; + } as const; // Act const result = safeStringify(value, options); @@ -81,7 +81,7 @@ describe("#safeStringify", () => { // Arrange const options = { defaultValue: "default", - }; + } as const; jest.spyOn(JSON, "stringify").mockImplementation(() => { throw new Error("error"); }); @@ -97,7 +97,8 @@ describe("#safeStringify", () => { // Arrange const options = { defaultValue: "default", - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'undefined' is not assignable to parameter of type 'string'. jest.spyOn(JSON, "stringify").mockReturnValue(undefined); // Act @@ -109,7 +110,7 @@ describe("#safeStringify", () => { it("should not pretty format if the indent option is not given", () => { // Arrange - const options = {}; + const options: Record = {}; // Act const result = safeStringify({field: 1}, options); @@ -120,11 +121,11 @@ describe("#safeStringify", () => { it.each([null, undefined, 0])( "should not pretty format if the indent option is %s", - (value) => { + (value: any) => { // Arrange const options = { indent: value, - }; + } as const; // Act const result = safeStringify({field: 1}, options); @@ -136,11 +137,11 @@ describe("#safeStringify", () => { it.each([2, 4])( "should pretty format if the indent option is %s", - (value) => { + (value: any) => { // Arrange const options = { indent: value, - }; + } as const; const expectedIndex = Array(value).fill(" ").join(""); // Act diff --git a/packages/wonder-stuff-core/src/__tests__/truncate-middle.test.js b/packages/wonder-stuff-core/src/__tests__/truncate-middle.test.ts similarity index 96% rename from packages/wonder-stuff-core/src/__tests__/truncate-middle.test.js rename to packages/wonder-stuff-core/src/__tests__/truncate-middle.test.ts index 1cf54926..0a0ca6a0 100644 --- a/packages/wonder-stuff-core/src/__tests__/truncate-middle.test.js +++ b/packages/wonder-stuff-core/src/__tests__/truncate-middle.test.ts @@ -1,10 +1,9 @@ -// @flow import {truncateMiddle} from "../truncate-middle"; describe("#truncateMiddle", () => { it.each(["", "ABCDE", "ABCDEFGH"])( "should return the given string if it is less than or equal to given max length", - (testPoint) => { + (testPoint: any) => { // Arrange // Act diff --git a/packages/wonder-stuff-core/src/__tests__/values.flowtest.js b/packages/wonder-stuff-core/src/__tests__/values.flowtest.ts similarity index 73% rename from packages/wonder-stuff-core/src/__tests__/values.flowtest.js rename to packages/wonder-stuff-core/src/__tests__/values.flowtest.ts index dd668f5b..418ac005 100644 --- a/packages/wonder-stuff-core/src/__tests__/values.flowtest.js +++ b/packages/wonder-stuff-core/src/__tests__/values.flowtest.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module '../values' or its corresponding type declarations. import {values} from "../values"; { @@ -7,7 +7,7 @@ import {values} from "../values"; a: 1, b: "2", c: [3, 4], - }; + } as const; const obj1Values = values(obj1); // This works because the variable is typed to all the possible value types. @@ -15,13 +15,14 @@ import {values} from "../values"; // This errors because the variable is only typed to string, but the value // could be a number, string, or array of numbers. - // $FlowExpectedError[incompatible-type] const __: string = obj1Values[1]; } { // should work with explicit object-as-map types - const map1: {|[string]: number|} = { + const map1: { + [key: string]: number; + } = { a: 1, b: 2, c: 3, @@ -33,14 +34,13 @@ import {values} from "../values"; // This errors because the variable is typed to string, and that is not // a number. - // $FlowExpectedError[incompatible-type] const __: string = map1Values[1]; } { // should return type Array for empty object - const emptyObj = {}; - const _: Array = values(emptyObj); + const emptyObj: Record = {}; + const _: Array = values(emptyObj); } { @@ -48,21 +48,21 @@ import {values} from "../values"; const obj2 = { a: 1, b: "2", - }; + } as const; // This errors because the return type of values() is not Array - // $FlowExpectedError[incompatible-type] const _: Array = values(obj2); // This errors because the object does not have values that are all numbers. - // $FlowExpectedError[incompatible-call] const __ = values(obj2); } { // should work with class instances class Foo { + // @ts-expect-error [FEI-5011] - TS2564 - Property 'a' has no initializer and is not definitely assigned in the constructor. a: string; + // @ts-expect-error [FEI-5011] - TS2564 - Property 'b' has no initializer and is not definitely assigned in the constructor. b: string; } const foo = new Foo(); diff --git a/packages/wonder-stuff-core/src/__tests__/values.test.js b/packages/wonder-stuff-core/src/__tests__/values.test.ts similarity index 73% rename from packages/wonder-stuff-core/src/__tests__/values.test.js rename to packages/wonder-stuff-core/src/__tests__/values.test.ts index e4eb524f..5647966f 100644 --- a/packages/wonder-stuff-core/src/__tests__/values.test.js +++ b/packages/wonder-stuff-core/src/__tests__/values.test.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module '../values' or its corresponding type declarations. import {values} from "../values"; describe("#values", () => { @@ -9,7 +9,7 @@ describe("#values", () => { a: 1, b: "2", c: [3, 4], - }; + } as const; // Act values(obj); @@ -24,7 +24,8 @@ describe("#values", () => { a: 1, b: "2", c: [3, 4], - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'any[]'. jest.spyOn(Object, "values").mockReturnValue("THE RESULT"); // Act diff --git a/packages/wonder-stuff-core/src/build-caused-by-message.js b/packages/wonder-stuff-core/src/build-caused-by-message.ts similarity index 83% rename from packages/wonder-stuff-core/src/build-caused-by-message.js rename to packages/wonder-stuff-core/src/build-caused-by-message.ts index 06f4a643..a8922236 100644 --- a/packages/wonder-stuff-core/src/build-caused-by-message.js +++ b/packages/wonder-stuff-core/src/build-caused-by-message.ts @@ -1,4 +1,3 @@ -// @flow /** * Builds a string that describes the causal relationship between two messages. * @@ -8,10 +7,10 @@ * @returns {string} A string that indicates `consequence` is caused by `cause`. */ export const buildCausedByMessage = ( - consequence: ?string, - cause: ?string, + consequence?: string | null, + cause?: string | null, ): string => { - const messageOrDefault = (message: ?string): string => + const messageOrDefault = (message?: string | null): string => message?.trim() || "(empty message)"; const consequenceMessage = messageOrDefault(consequence); diff --git a/packages/wonder-stuff-core/src/clone-metadata.js b/packages/wonder-stuff-core/src/clone-metadata.ts similarity index 78% rename from packages/wonder-stuff-core/src/clone-metadata.js rename to packages/wonder-stuff-core/src/clone-metadata.ts index 37315cc4..5fbfae66 100644 --- a/packages/wonder-stuff-core/src/clone-metadata.js +++ b/packages/wonder-stuff-core/src/clone-metadata.ts @@ -1,4 +1,3 @@ -// @flow import {clone} from "./clone"; import type {Metadata} from "./types"; @@ -8,9 +7,9 @@ import type {Metadata} from "./types"; * This performs a deep clone of the given metadata and returns a read-only * clone. */ -export const cloneMetadata = ( - metadata: ?$ReadOnly, -): ?$ReadOnly => { +export const cloneMetadata = ( + metadata?: Readonly | null, +): Readonly | null | undefined => { // If it's null or undefined, just return it as-is. if (metadata == null) { return metadata; @@ -21,6 +20,5 @@ export const cloneMetadata = ( // We know that we have cloned the incoming data and so our clone is of // the correct type. - // $FlowIgnore[incompatible-return] return Object.freeze(clonedValue); }; diff --git a/packages/wonder-stuff-core/src/clone.js b/packages/wonder-stuff-core/src/clone.ts similarity index 69% rename from packages/wonder-stuff-core/src/clone.js rename to packages/wonder-stuff-core/src/clone.ts index 41a6b469..57bebd74 100644 --- a/packages/wonder-stuff-core/src/clone.js +++ b/packages/wonder-stuff-core/src/clone.ts @@ -1,5 +1,3 @@ -// @flow - /** * Clone a value and all of its nested values. * @@ -14,14 +12,15 @@ export const clone = (value: T): T => { } if (Array.isArray(value)) { + // @ts-expect-error [FEI-5011] - TS2322 - Type 'any[]' is not assignable to type 'T'. return value.map(clone); } return Object.keys(value).reduce((acc, key) => { + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'. acc[key] = clone(value[key]); return acc; // We need to cast to any here so that the value is a valid // match for T in the return type after the accumulator is done. - // $FlowIgnore[unclear-type] - }, ({}: any)); + }, {} as any); }; diff --git a/packages/wonder-stuff-core/src/entries.js b/packages/wonder-stuff-core/src/entries.js deleted file mode 100644 index f6f05a7c..00000000 --- a/packages/wonder-stuff-core/src/entries.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow -/** - * Return an array of key/value tuples for an object. - * - * @param {$ReadOnly} obj The object for which the values are - * to be returned. - * @returns {Array<[K, V]>} An array of key/value tuples for the object. - */ -export function entries( - obj: $ReadOnly, -): Array<[K, V]> { - // This cast is deliberate as Object.entries is typed to return - // Array<[string, mixed]>, but we want to return Array<[K, V]>. - // $FlowIgnore[unclear-type] - return (Object.entries(obj): any); -} diff --git a/packages/wonder-stuff-core/src/error-info.js b/packages/wonder-stuff-core/src/error-info.ts similarity index 97% rename from packages/wonder-stuff-core/src/error-info.js rename to packages/wonder-stuff-core/src/error-info.ts index b88c38b4..8ffdccda 100644 --- a/packages/wonder-stuff-core/src/error-info.js +++ b/packages/wonder-stuff-core/src/error-info.ts @@ -1,4 +1,3 @@ -// @flow import {buildCausedByMessage} from "./build-caused-by-message"; /** @@ -8,14 +7,14 @@ import {buildCausedByMessage} from "./build-caused-by-message"; * information. */ export class ErrorInfo { - +_name: string; - +_message: string; - +_stackFrames: $ReadOnlyArray; + readonly _name: string; + readonly _message: string; + readonly _stackFrames: ReadonlyArray; constructor( name: string, message: string, - stackFrames: $ReadOnlyArray, + stackFrames: ReadonlyArray, ) { this._name = name; this._message = message; @@ -50,7 +49,7 @@ export class ErrorInfo { * * Index 0 being the top of the stack. */ - get stack(): $ReadOnlyArray { + get stack(): ReadonlyArray { // Copy the stack array just to be sure our internal state won't // mutate outside our control. return [...this._stackFrames]; diff --git a/packages/wonder-stuff-core/src/errors-from-error.js b/packages/wonder-stuff-core/src/errors-from-error.ts similarity index 82% rename from packages/wonder-stuff-core/src/errors-from-error.js rename to packages/wonder-stuff-core/src/errors-from-error.ts index ace72464..174f3a46 100644 --- a/packages/wonder-stuff-core/src/errors-from-error.js +++ b/packages/wonder-stuff-core/src/errors-from-error.ts @@ -1,4 +1,3 @@ -// @flow import {KindError} from "./kind-error"; import {Errors} from "./errors"; @@ -7,7 +6,7 @@ export const Order = Object.freeze({ CauseFirst: "cause-first", }); -export type SequenceOrder = $Values; +export type SequenceOrder = (typeof Order)[keyof typeof Order]; /** * Given an error, generates a sequence of `Error`s. @@ -20,7 +19,7 @@ export type SequenceOrder = $Values; * causal error and ends with the given error. */ export function* errorsFromError( - error: ?Error, + error: Error | null | undefined, order: SequenceOrder, ): Iterator { if (order !== Order.CauseFirst && order !== Order.ConsequenceFirst) { @@ -38,6 +37,7 @@ export function* errorsFromError( yield error; } if (error instanceof KindError) { + // @ts-expect-error [FEI-5011] - TS2488 - Type 'Iterator' must have a '[Symbol.iterator]()' method that returns an iterator. yield* errorsFromError(error.cause, order); } if (order === Order.CauseFirst) { diff --git a/packages/wonder-stuff-core/src/errors.js b/packages/wonder-stuff-core/src/errors.ts similarity index 98% rename from packages/wonder-stuff-core/src/errors.js rename to packages/wonder-stuff-core/src/errors.ts index 984ef615..fae0ac0f 100644 --- a/packages/wonder-stuff-core/src/errors.js +++ b/packages/wonder-stuff-core/src/errors.ts @@ -1,5 +1,3 @@ -// @flow - /** * @typedef {Object} Errors A base error taxonomy for consumers of this core * library to build off. diff --git a/packages/wonder-stuff-core/src/get-kind-from-error.js b/packages/wonder-stuff-core/src/get-kind-from-error.ts similarity index 96% rename from packages/wonder-stuff-core/src/get-kind-from-error.js rename to packages/wonder-stuff-core/src/get-kind-from-error.ts index a74966f7..ad2c47c1 100644 --- a/packages/wonder-stuff-core/src/get-kind-from-error.js +++ b/packages/wonder-stuff-core/src/get-kind-from-error.ts @@ -1,4 +1,3 @@ -// @flow import {KindError} from "./kind-error"; import {Errors} from "./errors"; diff --git a/packages/wonder-stuff-core/src/get-original-stack-from-error.js b/packages/wonder-stuff-core/src/get-original-stack-from-error.ts similarity index 72% rename from packages/wonder-stuff-core/src/get-original-stack-from-error.js rename to packages/wonder-stuff-core/src/get-original-stack-from-error.ts index 893f82f1..3b263660 100644 --- a/packages/wonder-stuff-core/src/get-original-stack-from-error.js +++ b/packages/wonder-stuff-core/src/get-original-stack-from-error.ts @@ -1,4 +1,3 @@ -// @flow import {KindError} from "./kind-error"; /** @@ -8,5 +7,6 @@ export const getOriginalStackFromError = (error: Error): string => { if (error instanceof KindError) { return error.originalStack; } + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string | undefined' is not assignable to type 'string'. return error.stack; }; diff --git a/packages/wonder-stuff-core/src/index.js b/packages/wonder-stuff-core/src/index.ts similarity index 61% rename from packages/wonder-stuff-core/src/index.js rename to packages/wonder-stuff-core/src/index.ts index 15431d91..99da6593 100644 --- a/packages/wonder-stuff-core/src/index.js +++ b/packages/wonder-stuff-core/src/index.ts @@ -1,7 +1,9 @@ -// @flow export {clone} from "./clone"; +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module './entries' or its corresponding type declarations. export {entries} from "./entries"; +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module './keys' or its corresponding type declarations. export {keys} from "./keys"; +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module './values' or its corresponding type declarations. export {values} from "./values"; export {Errors} from "./errors"; export {errorsFromError, Order} from "./errors-from-error"; diff --git a/packages/wonder-stuff-core/src/keys.js b/packages/wonder-stuff-core/src/keys.js deleted file mode 100644 index 19a18423..00000000 --- a/packages/wonder-stuff-core/src/keys.js +++ /dev/null @@ -1,13 +0,0 @@ -// @flow -/** - * Return an array of the enumerable keys of an object. - * - * @param {$ReadOnly} obj The object for which the values are - * to be returned. - * @returns {Array<$Keys>} An array of the enumerable keys of an object. - */ -export function keys( - obj: $ReadOnly, -): Array<$Keys> { - return Object.keys(obj); -} diff --git a/packages/wonder-stuff-core/src/kind-error.js b/packages/wonder-stuff-core/src/kind-error.ts similarity index 88% rename from packages/wonder-stuff-core/src/kind-error.js rename to packages/wonder-stuff-core/src/kind-error.ts index be7b0396..bb893f3f 100644 --- a/packages/wonder-stuff-core/src/kind-error.js +++ b/packages/wonder-stuff-core/src/kind-error.ts @@ -1,4 +1,3 @@ -// @flow import {Errors} from "./errors"; import {ErrorInfo} from "./error-info"; import {cloneMetadata} from "./clone-metadata"; @@ -8,56 +7,50 @@ import type {Metadata} from "./types"; /** * Options for constructing a `KindError`. */ -export type Options = {| +export type Options = { /** * An error responsible for the error being created. * * @type {?Error} */ - cause?: ?Error, - + cause?: Error | null | undefined; /** * Data to be attached to the error. * * @type {?Metadata} */ - metadata?: ?Metadata, - + metadata?: Metadata | null | undefined; /** * A prefix for the error name. * * @type {?string} */ - prefix?: ?string, - + prefix?: string | null | undefined; /** * A name for the error. * * @type {?string} */ - name?: ?string, - + name?: string | null | undefined; /** * The number of stack frames to strip from the error. * * @type {?number} */ - stripStackFrames?: ?number, - + stripStackFrames?: number | null | undefined; /** * The minimum number of stack frames to try and retain. * * @type {?number} */ - minimumFrameCount?: ?number, - + minimumFrameCount?: number | null | undefined; /** * Should we create a composite stack from the causal error chain or not? * * @type {?boolean} */ - compositeStack?: ?boolean, -|}; + compositeStack?: boolean | null | undefined; +}; /** * An error to describe detailed states and relationships. @@ -68,11 +61,11 @@ export type Options = {| * logging setups like Sentry or winston. */ export class KindError extends Error { - +kind: string; - +originalMessage: string; - +originalStack: string; - +metadata: ?$ReadOnly; - +cause: ?Error; + readonly kind: string; + readonly originalMessage: string; + readonly originalStack: string; + readonly metadata: Readonly | null | undefined; + readonly cause: Error | null | undefined; /** * Creates an instance of `KindError`. @@ -152,6 +145,7 @@ export class KindError extends Error { this.kind = kind; // Capture the original stack trace, in case we change it. + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string | undefined' is not assignable to type 'string'. this.originalStack = this.stack; // The cause of this error, if there is one. @@ -165,16 +159,6 @@ export class KindError extends Error { minimumFrameCount ?? 1, ); - /** - * $FlowIgnore[incompatible-type] - * Flow doesn't like us leaving KAError temporarily without a - * stack, but I don't want this crashing because we try to - * assign to a readonly thing, so being mildly cautious. - * - * We're going to replace the stack with our normalized one or - * one combined with our cause - so we need to make sure the old one is - * gone. - */ delete this.stack; // The default is the normalized stack. diff --git a/packages/wonder-stuff-core/src/safe-stringify.js b/packages/wonder-stuff-core/src/safe-stringify.ts similarity index 96% rename from packages/wonder-stuff-core/src/safe-stringify.js rename to packages/wonder-stuff-core/src/safe-stringify.ts index dde437ef..5468b8e3 100644 --- a/packages/wonder-stuff-core/src/safe-stringify.js +++ b/packages/wonder-stuff-core/src/safe-stringify.ts @@ -1,5 +1,3 @@ -// @flow - /** * Options to modify how a safe stringifying operation works. */ @@ -10,8 +8,7 @@ type SafeStringifyOptions = { * @default '""' Empty string * @type {string} */ - defaultValue?: string, - + defaultValue?: string; /** * A number indicating how many spaces to indent nested structures. * When not given, there will be no indentation nor additional newlines. @@ -19,7 +16,7 @@ type SafeStringifyOptions = { * @default undefined No indentation * @type {?number} */ - indent?: ?number, + indent?: number | null | undefined; }; interface safeStringifyFn { @@ -37,7 +34,6 @@ interface safeStringifyFn { * @returns {string} The stringified value or the default value. */ (value: T, options?: SafeStringifyOptions): string; - /** * Stringify an item, returning an empty string on error, null, or undefined. * @@ -76,7 +72,7 @@ export const safeStringify: safeStringifyFn = ( } try { return JSON.stringify(value, null, indent ?? 0) ?? defaultValue; - } catch (_) { + } catch (_: any) { return defaultValue; } }; diff --git a/packages/wonder-stuff-core/src/truncate-middle.js b/packages/wonder-stuff-core/src/truncate-middle.ts similarity index 99% rename from packages/wonder-stuff-core/src/truncate-middle.js rename to packages/wonder-stuff-core/src/truncate-middle.ts index d6595341..29036334 100644 --- a/packages/wonder-stuff-core/src/truncate-middle.js +++ b/packages/wonder-stuff-core/src/truncate-middle.ts @@ -1,4 +1,3 @@ -// @flow const ELLIPSIS = "..."; /** diff --git a/packages/wonder-stuff-core/src/types.js b/packages/wonder-stuff-core/src/types.ts similarity index 58% rename from packages/wonder-stuff-core/src/types.js rename to packages/wonder-stuff-core/src/types.ts index 04e66f0c..926a073a 100644 --- a/packages/wonder-stuff-core/src/types.js +++ b/packages/wonder-stuff-core/src/types.ts @@ -1,5 +1,4 @@ -// @flow -type MetadataPrimitive = string | number | boolean | null | void; +type MetadataPrimitive = string | number | boolean | null | undefined; type MetadataArray = Array>; /** @@ -9,5 +8,5 @@ export type Metadata = { [name: string]: | Metadata | MetadataPrimitive - | MetadataArray, + | MetadataArray; }; diff --git a/packages/wonder-stuff-core/src/values.js b/packages/wonder-stuff-core/src/values.js deleted file mode 100644 index 73401dad..00000000 --- a/packages/wonder-stuff-core/src/values.js +++ /dev/null @@ -1,14 +0,0 @@ -// @flow -/** - * Return an array of the enumerable property values of an object. - * - * @param {$ReadOnly} obj The object for which the values are - * to be returned. - * @returns {Array} An array of the enumerable property values of the object. - */ -export function values(obj: $ReadOnly): Array { - // This is a deliberate cast through any. - // Object.values returns Array and we want to return Array. - // $FlowIgnore[unclear-type] - return (Object.values(obj): Array); -} diff --git a/packages/wonder-stuff-i18n/src/bin/all-i18n-strings.js b/packages/wonder-stuff-i18n/src/bin/all-i18n-strings.ts old mode 100755 new mode 100644 similarity index 98% rename from packages/wonder-stuff-i18n/src/bin/all-i18n-strings.js rename to packages/wonder-stuff-i18n/src/bin/all-i18n-strings.ts index 6c01b269..d8536b92 --- a/packages/wonder-stuff-i18n/src/bin/all-i18n-strings.js +++ b/packages/wonder-stuff-i18n/src/bin/all-i18n-strings.ts @@ -1,5 +1,4 @@ #!/usr/bin/env node -// @flow /* istanbul ignore file */ /* eslint-disable no-console */ /** diff --git a/packages/wonder-stuff-i18n/src/bin/gen-potfile.js b/packages/wonder-stuff-i18n/src/bin/gen-potfile.ts old mode 100755 new mode 100644 similarity index 99% rename from packages/wonder-stuff-i18n/src/bin/gen-potfile.js rename to packages/wonder-stuff-i18n/src/bin/gen-potfile.ts index ea23d98f..7a6aa561 --- a/packages/wonder-stuff-i18n/src/bin/gen-potfile.js +++ b/packages/wonder-stuff-i18n/src/bin/gen-potfile.ts @@ -1,5 +1,4 @@ #!/usr/bin/env node -// @flow /* istanbul ignore file */ /** * Generates a POT file containing all strings marked for translation. The POT diff --git a/packages/wonder-stuff-i18n/src/index.js b/packages/wonder-stuff-i18n/src/index.ts similarity index 98% rename from packages/wonder-stuff-i18n/src/index.js rename to packages/wonder-stuff-i18n/src/index.ts index 6eb09840..4657ca52 100644 --- a/packages/wonder-stuff-i18n/src/index.js +++ b/packages/wonder-stuff-i18n/src/index.ts @@ -1,4 +1,3 @@ -// @flow /* istanbul ignore file */ export {default as I18nPlugin} from "./plugins/i18n-plugin"; export {extractStrings} from "./utils/extract-i18n"; diff --git a/packages/wonder-stuff-i18n/src/plugins/__tests__/i18n-plugin.test.js b/packages/wonder-stuff-i18n/src/plugins/__tests__/i18n-plugin.test.ts similarity index 90% rename from packages/wonder-stuff-i18n/src/plugins/__tests__/i18n-plugin.test.js rename to packages/wonder-stuff-i18n/src/plugins/__tests__/i18n-plugin.test.ts index 27dc7d04..cdb02d26 100644 --- a/packages/wonder-stuff-i18n/src/plugins/__tests__/i18n-plugin.test.js +++ b/packages/wonder-stuff-i18n/src/plugins/__tests__/i18n-plugin.test.ts @@ -1,17 +1,16 @@ -// @flow import I18nPlugin from "../i18n-plugin"; import type {TranslatedLocaleStrings} from "../../utils/i18n-utils"; import type {TranslatedStrings, Assets} from "../i18n-plugin"; -type ResolvedAssets = {| - [string]: ResolvedAsset, -|}; +type ResolvedAssets = { + [key: string]: ResolvedAsset; +}; -type ResolvedAsset = {| - source: string, - size: number, -|}; +type ResolvedAsset = { + source: string; + size: number; +}; describe("I18nPlugin", () => { describe("constructor", () => { @@ -22,7 +21,7 @@ describe("I18nPlugin", () => { // Assert expect(() => { - // $FlowIgnore + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. new I18nPlugin(); // eslint-disable-line no-new }).toThrowErrorMatchingInlineSnapshot( `"I18nPlugin requires options"`, @@ -36,7 +35,7 @@ describe("I18nPlugin", () => { // Assert expect(() => { - // $FlowIgnore + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{}' is not assignable to parameter of type 'Options'. new I18nPlugin({}); // eslint-disable-line no-new }).toThrowErrorMatchingInlineSnapshot( `"Must provide locales to localize to"`, @@ -50,7 +49,7 @@ describe("I18nPlugin", () => { // Assert expect(() => { - // $FlowIgnore + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ locales: never[]; }' is not assignable to parameter of type 'Options'. new I18nPlugin({locales: []}); // eslint-disable-line no-new }).toThrowErrorMatchingInlineSnapshot( `"Must provide a function to get the strings to localize"`, @@ -174,7 +173,7 @@ describe("I18nPlugin", () => { return 1; }, }, - }; + } as const; const locales = ["es", "pt"]; const plugin = new I18nPlugin({ locales, @@ -208,7 +207,9 @@ describe("I18nPlugin", () => { const stringAssets: ResolvedAssets = {}; for (const assetName of Object.keys(assets)) { stringAssets[assetName] = { + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly "test.deadbeefc0ffeec0ffee.js": { readonly source: () => string; readonly size: () => number; }; readonly "test-pluralonly.deadbeefc0ffeec0ffe2.js": { readonly source: () => string; readonly size: () => number; }; }'. source: assets[assetName].source(), + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly "test.deadbeefc0ffeec0ffee.js": { readonly source: () => string; readonly size: () => number; }; readonly "test-pluralonly.deadbeefc0ffeec0ffe2.js": { readonly source: () => string; readonly size: () => number; }; }'. size: assets[assetName].size(), }; } @@ -296,7 +297,7 @@ describe("I18nPlugin", () => { return 1; }, }, - }; + } as const; const locales = ["es", "pt"]; const plugin = new I18nPlugin({ locales, @@ -317,7 +318,9 @@ describe("I18nPlugin", () => { const stringAssets: ResolvedAssets = {}; for (const assetName of Object.keys(assets)) { stringAssets[assetName] = { + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly "test.css": { readonly source: () => string; readonly size: () => number; }; readonly "font.woff2": { readonly source: () => string; readonly size: () => number; }; }'. source: assets[assetName].source(), + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly "test.css": { readonly source: () => string; readonly size: () => number; }; readonly "font.woff2": { readonly source: () => string; readonly size: () => number; }; }'. size: assets[assetName].size(), }; } @@ -401,7 +404,7 @@ describe("I18nPlugin", () => { locales, silent: true, getI18nStrings: jest.fn().mockResolvedValue({}), - shouldLocalizeAsset: (assetName) => + shouldLocalizeAsset: (assetName: any) => assetName.startsWith("runtime.") || assetName.startsWith("chunk-map."), }); @@ -591,7 +594,7 @@ describe("I18nPlugin", () => { deadbeefc0ffeec0ffe2: "efba0b9130c816f63328", deadbeefc0ffeec0ffee: "68b8d9a0a2ba472e983b", }, - }; + } as const; const assets = { "test.deadbeefc0ffeec0ffee.js": { source() { @@ -665,7 +668,7 @@ describe("I18nPlugin", () => { return 1; }, }, - }; + } as const; const getLocalePath = (locale: string) => `/prod/${locale}`; const locales = ["es", "pt"]; const plugin = new I18nPlugin({ @@ -673,7 +676,7 @@ describe("I18nPlugin", () => { silent: true, getI18nStrings: jest.fn().mockResolvedValue({}), getLocalePath, - shouldLocalizeManifest: (assetName, locale) => + shouldLocalizeManifest: (assetName: any, locale: any) => assetName.includes(`/${locale}/`), }); @@ -686,7 +689,9 @@ describe("I18nPlugin", () => { const stringAssets: ResolvedAssets = {}; for (const assetName of Object.keys(assets)) { stringAssets[assetName] = { + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly "test.deadbeefc0ffeec0ffee.js": { readonly source: () => string; readonly size: () => number; }; readonly "runtime.deadbeefc0ffeec0ffe2.js": { readonly source: () => string; readonly size: () => number; }; ... 6 more ...; readonly "../pages/pt/page-1234.html": { ...; }; }'. source: assets[assetName].source(), + // @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly "test.deadbeefc0ffeec0ffee.js": { readonly source: () => string; readonly size: () => number; }; readonly "runtime.deadbeefc0ffeec0ffe2.js": { readonly source: () => string; readonly size: () => number; }; ... 6 more ...; readonly "../pages/pt/page-1234.html": { ...; }; }'. size: assets[assetName].size(), }; } @@ -748,7 +753,7 @@ describe("I18nPlugin", () => { deadbeefc0ffeec0ffe2: "efba0b9130c816f63328", deadbeefc0ffeec0ffee: "68b8d9a0a2ba472e983b", }, - }; + } as const; const assets: Assets = { "../manifests/es/webpack-manifest-1234.json": { source() { @@ -815,7 +820,7 @@ describe("I18nPlugin", () => { deadbeefc0ffeec0ffe2: "efba0b9130c816f63328", deadbeefc0ffeec0ffee: "68b8d9a0a2ba472e983b", }, - }; + } as const; const assets: Assets = { "../manifests/es/webpack-manifest-1234.json": { source() { @@ -876,22 +881,19 @@ describe("I18nPlugin", () => { describe("onEmit", () => { it("processes all the necessary steps", async () => { // Arrange - const assets = {}; - const translatedStrings = {translatedStrings: true}; - const hashMap = {hashMap: true}; + const assets: Record = {}; + const translatedStrings = {translatedStrings: true} as const; + const hashMap = {hashMap: true} as const; const locales = ["es", "pt"]; const plugin = new I18nPlugin({ locales, silent: true, getI18nStrings: jest.fn().mockResolvedValue({}), }); - // $FlowIgnore This is a mock. plugin.getTranslatedStrings = jest .fn() .mockReturnValue(translatedStrings); - // $FlowIgnore This is a mock. plugin.translateAssets = jest.fn().mockReturnValue(hashMap); - // $FlowIgnore This is a mock. plugin.localizeManifests = jest.fn(); const callback = jest.fn(); @@ -899,22 +901,18 @@ describe("I18nPlugin", () => { await plugin.onEmit({assets}, callback); // Assert - // $FlowIgnore This is a mock. expect(plugin.getTranslatedStrings).toHaveBeenCalledWith(locales); - // $FlowIgnore This is a mock. expect(plugin.translateAssets).toHaveBeenCalledWith({ assets, translatedStrings, localizeRuntimeFiles: false, }); - // $FlowIgnore This is a mock. expect(plugin.translateAssets).toHaveBeenCalledWith({ assets, translatedStrings, hashMap, localizeRuntimeFiles: true, }); - // $FlowIgnore This is a mock. expect(plugin.localizeManifests).toHaveBeenCalledWith({ assets, hashMap, @@ -924,22 +922,19 @@ describe("I18nPlugin", () => { it("skips all the steps when there are no valid locales", async () => { // Arrange - const assets = {}; - const translatedStrings = {translatedStrings: true}; - const hashMap = {hashMap: true}; - const locales = []; + const assets: Record = {}; + const translatedStrings = {translatedStrings: true} as const; + const hashMap = {hashMap: true} as const; + const locales: Array = []; const plugin = new I18nPlugin({ locales, silent: true, getI18nStrings: jest.fn().mockResolvedValue({}), }); - // $FlowIgnore This is a mock. plugin.getTranslatedStrings = jest .fn() .mockReturnValue(translatedStrings); - // $FlowIgnore This is a mock. plugin.translateAssets = jest.fn().mockReturnValue(hashMap); - // $FlowIgnore This is a mock. plugin.localizeManifests = jest.fn(); const callback = jest.fn(); @@ -947,11 +942,8 @@ describe("I18nPlugin", () => { await plugin.onEmit({assets}, callback); // Assert - // $FlowIgnore This is a mock. expect(plugin.getTranslatedStrings).not.toHaveBeenCalled(); - // $FlowIgnore This is a mock. expect(plugin.translateAssets).not.toHaveBeenCalled(); - // $FlowIgnore This is a mock. expect(plugin.localizeManifests).not.toHaveBeenCalled(); expect(callback).toHaveBeenCalled(); }); diff --git a/packages/wonder-stuff-i18n/src/plugins/i18n-plugin.js b/packages/wonder-stuff-i18n/src/plugins/i18n-plugin.ts similarity index 88% rename from packages/wonder-stuff-i18n/src/plugins/i18n-plugin.js rename to packages/wonder-stuff-i18n/src/plugins/i18n-plugin.ts index e45905be..ac5977d2 100644 --- a/packages/wonder-stuff-i18n/src/plugins/i18n-plugin.js +++ b/packages/wonder-stuff-i18n/src/plugins/i18n-plugin.ts @@ -1,4 +1,3 @@ -// @flow /** * A plugin to create translated versions of Webpack builds. After Webpack compiles * all the JS bundles, this plugin goes through all the generated assets and @@ -18,6 +17,7 @@ * */ import path from "path"; +// @ts-expect-error [FEI-5011] - TS7016 - Could not find a declaration file for module 'async'. '/Users/kevinbarabash/khan/wonder-stuff/node_modules/async/dist/async.js' implicitly has an 'any' type. import {eachLimit} from "async"; import * as I18nUtils from "../utils/i18n-utils"; @@ -49,7 +49,7 @@ const addAsset = (assets: Assets, relFilePath: string, data: string) => { }; export type TranslatedStrings = { - [locale: string]: TranslatedLocaleStrings, + [locale: string]: TranslatedLocaleStrings; }; type Options = { @@ -57,8 +57,7 @@ type Options = { * The locales to build. Should be a list of strings like "pt", "es", etc. * Be sure to not include "en" in this list, as that is the default locale. */ - locales: Array, - + locales: Array; /** * Get localized strings for a particular locale. * @@ -77,75 +76,71 @@ type Options = { * ... * } */ - getI18nStrings: (locale: string) => Promise, - + getI18nStrings: (locale: string) => Promise; /** * Provide a partial path to the Webpack output directory that includes * the locale. Defaults to: "//". */ - getLocalePath?: (locale: string) => string, - + getLocalePath?: (locale: string) => string; /** * Indicate if an asset should have the hashes and URLs inside of it * updated to use the new locale. Defaults to handling any bundle named * "runtime" (you will want to do this for any bundle that contains * the runtime or has references to other JS files) */ - shouldLocalizeAsset?: (assetName: string) => boolean, - + shouldLocalizeAsset?: (assetName: string) => boolean; /** * Determine if a file should be processed, meaning if it should be copied * over to the new locale directory. Defaults to all files. */ - shouldProcessAsset?: (assetName: string) => boolean, - + shouldProcessAsset?: (assetName: string) => boolean; /** * Determine if a manifest file, for a given locale should be modified to * point to the new JS files or assets. Defaults to processing all '.html' * files. */ - shouldLocalizeManifest?: (assetName: string, locale: string) => boolean, - + shouldLocalizeManifest?: (assetName: string, locale: string) => boolean; /** * Should the plugin log any messages to the console? Defaults to true. */ - silent?: boolean, - + silent?: boolean; /** * Should the plugin log any timing information? None is logged by default. */ timing?: { - start: (string) => void, - end: (string) => void, - ... - }, + start: (arg1: string) => void; + end: (arg1: string) => void; + }; }; type InternalOptions = { - locales: Array, - silent?: boolean, + locales: Array; + silent?: boolean; timing?: { - start: (string) => void, - end: (string) => void, - ... - }, - getI18nStrings: (locale: string) => Promise, - getLocalePath: (locale: string) => string, - shouldLocalizeAsset: (assetName: string) => boolean, - shouldProcessAsset: (assetName: string) => boolean, - shouldLocalizeManifest: (assetName: string, locale: string) => boolean, + start: (arg1: string) => void; + end: (arg1: string) => void; + }; + getI18nStrings: (locale: string) => Promise; + getLocalePath: (locale: string) => string; + shouldLocalizeAsset: (assetName: string) => boolean; + shouldProcessAsset: (assetName: string) => boolean; + shouldLocalizeManifest: (assetName: string, locale: string) => boolean; }; -type LocaleHashMap = {[oldHash: string]: string}; -type HashMaps = {[locale: string]: LocaleHashMap}; +type LocaleHashMap = { + [oldHash: string]: string; +}; +type HashMaps = { + [locale: string]: LocaleHashMap; +}; -type Asset = {| - source: () => string, - size: () => number, -|}; +type Asset = { + source: () => string; + size: () => number; +}; export type Assets = { - [assetName: string]: Asset, + [assetName: string]: Asset; }; export default class I18nPlugin { @@ -183,7 +178,8 @@ export default class I18nPlugin { } /* istanbul ignore next */ - apply(compiler: $FlowFixMe) { + apply(compiler: any) { + // @ts-expect-error [FEI-5011] - TS7006 - Parameter 'options' implicitly has an 'any' type. | TS7006 - Parameter 'callback' implicitly has an 'any' type. compiler.hooks.emit.tapAsync("I18nPlugin", (options, callback) => this.onEmit(options, callback), ); @@ -194,7 +190,7 @@ export default class I18nPlugin { * * @param {...any} args the args to log out to the console */ - log(...args: Array<$FlowFixMe>) { + log(...args: Array) { const {silent} = this.options; if (silent === false || silent == null) { // eslint-disable-next-line no-console @@ -223,6 +219,7 @@ export default class I18nPlugin { } // Download the strings for each locale in parallel + // @ts-expect-error [FEI-5011] - TS7006 - Parameter 'locale' implicitly has an 'any' type. await eachLimit(locales, 4, async (locale) => { this.log( `Retreiving strings for ${locale} ${getEmojiForLocale(locale)}`, @@ -251,10 +248,10 @@ export default class I18nPlugin { localizeRuntimeFiles, hashMap, }: { - assets: Assets, - translatedStrings: TranslatedStrings, - localizeRuntimeFiles: boolean, - hashMap?: HashMaps, + assets: Assets; + translatedStrings: TranslatedStrings; + localizeRuntimeFiles: boolean; + hashMap?: HashMaps; }): HashMaps { const { locales, @@ -279,7 +276,7 @@ export default class I18nPlugin { // Initialize the map of old hashes to new hashes for each locale if (!hashMap) { - hashMap = ({}: HashMaps); + hashMap = {} as HashMaps; for (const locale of locales) { hashMap[locale] = {}; @@ -380,7 +377,7 @@ export default class I18nPlugin { * * @param {assets: Object, hashMap: } options */ - localizeManifests({assets, hashMap}: {assets: Assets, hashMap: HashMaps}) { + localizeManifests({assets, hashMap}: {assets: Assets; hashMap: HashMaps}) { const {locales, timing, shouldLocalizeManifest, getLocalePath} = this.options; @@ -427,7 +424,11 @@ export default class I18nPlugin { * @returns void */ async onEmit( - {assets}: {assets: Assets}, + { + assets, + }: { + assets: Assets; + }, callback: () => void, ): Promise { const {locales} = this.options; diff --git a/packages/wonder-stuff-i18n/src/utils/__tests__/emoji-for-locale.test.js b/packages/wonder-stuff-i18n/src/utils/__tests__/emoji-for-locale.test.ts similarity index 98% rename from packages/wonder-stuff-i18n/src/utils/__tests__/emoji-for-locale.test.js rename to packages/wonder-stuff-i18n/src/utils/__tests__/emoji-for-locale.test.ts index 4f69c98b..c6dcc5c8 100644 --- a/packages/wonder-stuff-i18n/src/utils/__tests__/emoji-for-locale.test.js +++ b/packages/wonder-stuff-i18n/src/utils/__tests__/emoji-for-locale.test.ts @@ -1,4 +1,3 @@ -// @flow import {getEmojiForLocale} from "../emoji-for-locale"; describe("getEmojiForLocale", () => { diff --git a/packages/wonder-stuff-i18n/src/utils/__tests__/extract-i18n.test.js b/packages/wonder-stuff-i18n/src/utils/__tests__/extract-i18n.test.ts similarity index 99% rename from packages/wonder-stuff-i18n/src/utils/__tests__/extract-i18n.test.js rename to packages/wonder-stuff-i18n/src/utils/__tests__/extract-i18n.test.ts index 4bd98a82..dc5a13ca 100644 --- a/packages/wonder-stuff-i18n/src/utils/__tests__/extract-i18n.test.js +++ b/packages/wonder-stuff-i18n/src/utils/__tests__/extract-i18n.test.ts @@ -1,4 +1,3 @@ -// @flow import {extractStrings} from "../extract-i18n"; const TEST_FILE = ` @@ -108,7 +107,7 @@ const zg = a(b("asdf"))._("Doesn't even use a variable."); describe("extractStrings", () => { it("extracts strings from a file", () => { // Arrange - const results = []; + const results: Array = []; // Act for (const match of extractStrings(TEST_FILE)) { @@ -397,7 +396,7 @@ describe("extractStrings", () => { it("extracted string exactly matches positions", () => { // Arrange - const results = []; + const results: Array = []; // Act for (const match of extractStrings(TEST_FILE)) { diff --git a/packages/wonder-stuff-i18n/src/utils/__tests__/i18n-utils.test.js b/packages/wonder-stuff-i18n/src/utils/__tests__/i18n-utils.test.ts similarity index 97% rename from packages/wonder-stuff-i18n/src/utils/__tests__/i18n-utils.test.js rename to packages/wonder-stuff-i18n/src/utils/__tests__/i18n-utils.test.ts index 7a67c3c5..d36a25e5 100644 --- a/packages/wonder-stuff-i18n/src/utils/__tests__/i18n-utils.test.js +++ b/packages/wonder-stuff-i18n/src/utils/__tests__/i18n-utils.test.ts @@ -1,4 +1,3 @@ -// @flow import fs from "fs"; import { @@ -28,7 +27,7 @@ describe("getIgnoreGlobs", () => { it("returns nothing if no .i18nignore file is found", () => { // Arrange - const expectedGlobs = []; + const expectedGlobs: Array = []; const ancesdir = require("ancesdir"); ancesdir.mockImplementation(() => { throw new Error("No such file"); @@ -108,7 +107,7 @@ describe("translateString", () => { const translation = { Hello: "Hallo", World: "Welt", - }; + } as const; // Act const translatedFileContents = translateString( @@ -127,7 +126,7 @@ describe("translateString", () => { const fileContents = `i18n._("Hello");\ni18n._("World");`; const translation = { Hello: "Hallo", - }; + } as const; // Act const translatedFileContents = translateString( @@ -147,7 +146,7 @@ describe("translateString", () => { const translation = { Hello: "Hallo", World: "Welt", - }; + } as const; const strings = getI18nStringsFromString(fileContents); // Act diff --git a/packages/wonder-stuff-i18n/src/utils/__tests__/localize-file.test.js b/packages/wonder-stuff-i18n/src/utils/__tests__/localize-file.test.ts similarity index 94% rename from packages/wonder-stuff-i18n/src/utils/__tests__/localize-file.test.js rename to packages/wonder-stuff-i18n/src/utils/__tests__/localize-file.test.ts index e5c45793..a27e3088 100644 --- a/packages/wonder-stuff-i18n/src/utils/__tests__/localize-file.test.js +++ b/packages/wonder-stuff-i18n/src/utils/__tests__/localize-file.test.ts @@ -1,4 +1,3 @@ -// @flow import { extractHashFromFileName, localizeString, @@ -70,7 +69,7 @@ describe("localizeString", () => { // Arrange const locale = "es"; const content = "A simple path: /genwebpack/prod/en/foo.js"; - const hashMap = {}; + const hashMap: Record = {}; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -89,7 +88,7 @@ describe("localizeString", () => { // Arrange const locale = "es"; const content = "/genwebpack/prod/en/a.js /genwebpack/prod/en/b.js"; - const hashMap = {}; + const hashMap: Record = {}; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -110,7 +109,7 @@ describe("localizeString", () => { // Arrange const locale = "es"; const content = "/genwebpack/prod/pt/a.js /genwebpack/prod/hu/b.js"; - const hashMap = {}; + const hashMap: Record = {}; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -133,7 +132,7 @@ describe("localizeString", () => { const content = "/genwebpack/prod/en/foo.3e083afe95f447481cad.js"; const hashMap = { "3e083afe95f447481cad": "593cff1d8e1e383f2471", - }; + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -158,7 +157,7 @@ describe("localizeString", () => { const hashMap = { "3e083afe95f447481cad": "593cff1d8e1e383f2471", "29d70669460257a74073": "9e0f5e0d0704dd61ee2f", - }; + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -183,7 +182,7 @@ describe("localizeString", () => { const hashMap = { "3e083afe95f447481cad": "593cff1d8e1e383f2471", "29d70669460257a74073": "9e0f5e0d0704dd61ee2f", - }; + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -208,7 +207,7 @@ describe("localizeString", () => { const hashMap = { "3e083afe95f447481cad": "593cff1d8e1e383f2471", "29d70669460257a74073": "9e0f5e0d0704dd61ee2f", - }; + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -247,7 +246,9 @@ describe("localizeFile", () => { const content = "genwebpack/prod/en/file.2e083afe95f447481cad.js"; const oldHash = "3e083afe95f447481cad"; const locale = "es"; - const hashMap = {"2e083afe95f447481cad": "4e083afe95f447481cad"}; + const hashMap = { + "2e083afe95f447481cad": "4e083afe95f447481cad", + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -274,7 +275,9 @@ describe("localizeFile", () => { const content = "genwebpack/prod/en/file.2e083afe95f447481cad.js"; const oldHash = "3e083afe95f447481cad"; const locale = "es"; - const hashMap = {"2e083afe95f447481cad": "4e083afe95f447481cad"}; + const hashMap = { + "2e083afe95f447481cad": "4e083afe95f447481cad", + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -304,7 +307,7 @@ describe("localizeFile", () => { const hashMap = { "2e083afe95f447481cad": "4e083afe95f447481cad", c0ffee: "3e083afe95f447481cad", - }; + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act @@ -332,7 +335,9 @@ describe("localizeFile", () => { const content = "genwebpack/prod/en/file.2e083afe95f447481cad.js"; const oldHash = null; const locale = "es"; - const hashMap = {"2e083afe95f447481cad": "4e083afe95f447481cad"}; + const hashMap = { + "2e083afe95f447481cad": "4e083afe95f447481cad", + } as const; const getLocalePath = (locale: string) => `/prod/${locale}/`; // Act diff --git a/packages/wonder-stuff-i18n/src/utils/__tests__/pofile-utils.test.js b/packages/wonder-stuff-i18n/src/utils/__tests__/pofile-utils.test.ts similarity index 76% rename from packages/wonder-stuff-i18n/src/utils/__tests__/pofile-utils.test.js rename to packages/wonder-stuff-i18n/src/utils/__tests__/pofile-utils.test.ts index 1f6dcaa7..d3bbba37 100644 --- a/packages/wonder-stuff-i18n/src/utils/__tests__/pofile-utils.test.js +++ b/packages/wonder-stuff-i18n/src/utils/__tests__/pofile-utils.test.ts @@ -1,4 +1,3 @@ -// @flow import fs from "fs"; import path from "path"; @@ -24,9 +23,10 @@ describe("buildPoItem", () => { type: "_", msgids: ["an extracted english string"], comments: [], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["an extracted english string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. const result = buildPoItem(fileName, extractedString); // Assert @@ -58,9 +58,10 @@ describe("buildPoItem", () => { type: "ngettext", msgids: ["%(num)s english string", "%(num)s plural string"], comments: [], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "ngettext"; readonly msgids: readonly ["%(num)s english string", "%(num)s plural string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. const result = buildPoItem(fileName, extractedString); // Assert @@ -94,9 +95,10 @@ describe("buildPoItem", () => { type: "_", msgids: ["an extracted english string %(name)s"], comments: [], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["an extracted english string %(name)s"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. const result = buildPoItem(fileName, extractedString); // Assert @@ -130,9 +132,10 @@ describe("buildPoItem", () => { type: "_", msgids: ["an extracted english string"], comments: ["a simple comment"], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["an extracted english string"]; readonly comments: readonly ["a simple comment"]; }' is not assignable to parameter of type 'ExtractedString'. const result = buildPoItem(fileName, extractedString); // Assert @@ -168,7 +171,8 @@ describe("mergePoItem", () => { type: "_", msgids: ["an extracted english string"], comments: [], - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["an extracted english string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. const item1 = buildPoItem(fileName1, extractedString1); const fileName2 = "test/some-file2.js"; const extractedString2 = { @@ -178,9 +182,10 @@ describe("mergePoItem", () => { type: "_", msgids: ["an extracted english string"], comments: [], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 12; readonly startOffset: 200; readonly endOffset: 229; readonly type: "_"; readonly msgids: readonly ["an extracted english string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. mergePoItem(item1, fileName2, extractedString2); // Assert @@ -212,7 +217,8 @@ describe("mergePoItem", () => { type: "_", msgids: ["an extracted english string"], comments: ["comment 1"], - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["an extracted english string"]; readonly comments: readonly ["comment 1"]; }' is not assignable to parameter of type 'ExtractedString'. const item1 = buildPoItem(fileName1, extractedString1); const fileName2 = "test/some-file2.js"; const extractedString2 = { @@ -222,9 +228,10 @@ describe("mergePoItem", () => { type: "_", msgids: ["an extracted english string"], comments: ["comment 2"], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 12; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["an extracted english string"]; readonly comments: readonly ["comment 2"]; }' is not assignable to parameter of type 'ExtractedString'. mergePoItem(item1, fileName2, extractedString2); // Assert @@ -259,7 +266,8 @@ describe("mergePoItem", () => { type: "ngettext", msgids: ["a singular string", "a plural string"], comments: [], - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "ngettext"; readonly msgids: readonly ["a singular string", "a plural string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. const item1 = buildPoItem(fileName1, extractedString1); const fileName2 = "test/some-file2.js"; const extractedString2 = { @@ -269,9 +277,10 @@ describe("mergePoItem", () => { type: "ngettext", msgids: ["a singular string", "a plural string"], comments: [], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 12; readonly startOffset: 200; readonly endOffset: 229; readonly type: "ngettext"; readonly msgids: readonly ["a singular string", "a plural string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. mergePoItem(item1, fileName2, extractedString2); // Assert @@ -303,7 +312,8 @@ describe("mergePoItem", () => { type: "_", msgids: ["a singular string"], comments: [], - }; + } as const; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 10; readonly startOffset: 100; readonly endOffset: 129; readonly type: "_"; readonly msgids: readonly ["a singular string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. const item1 = buildPoItem(fileName1, extractedString1); const fileName2 = "test/some-file2.js"; const extractedString2 = { @@ -313,15 +323,17 @@ describe("mergePoItem", () => { type: "ngettext", msgids: ["a singular string", "a plural string"], comments: [], - }; + } as const; const errorSpy = jest .spyOn(console, "error") .mockImplementation(() => {}); const exitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '() => void' is not assignable to parameter of type '(code?: number | undefined) => never'. .mockImplementation(() => {}); // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly linePos: 12; readonly startOffset: 200; readonly endOffset: 229; readonly type: "ngettext"; readonly msgids: readonly ["a singular string", "a plural string"]; readonly comments: readonly []; }' is not assignable to parameter of type 'ExtractedString'. mergePoItem(item1, fileName2, extractedString2); // Assert diff --git a/packages/wonder-stuff-i18n/src/utils/emoji-for-locale.js b/packages/wonder-stuff-i18n/src/utils/emoji-for-locale.ts similarity index 79% rename from packages/wonder-stuff-i18n/src/utils/emoji-for-locale.js rename to packages/wonder-stuff-i18n/src/utils/emoji-for-locale.ts index fbdd0fd0..826697ee 100644 --- a/packages/wonder-stuff-i18n/src/utils/emoji-for-locale.js +++ b/packages/wonder-stuff-i18n/src/utils/emoji-for-locale.ts @@ -1,4 +1,3 @@ -// @flow /** * Provide an emoji to represent a locale. * @@ -37,12 +36,13 @@ const LOCALE_TO_EMOJI_MAP = { ta: "🇱🇰", // Tamil -- Sri Lanka tr: "🇹🇷", // Turkish -- Turkey "zh-hans": "🇹🇼", // Mandarin -- Taiwan -}; +} as const; /** * Given a locale, get an emoji representing that locale. * * @param {string} locale the locale string to get the emoji for */ +// @ts-expect-error [FEI-5011] - TS7053 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly accents: "✨"; readonly bg: "🇧🇬"; readonly bn: "🇮🇳"; readonly boxes: "📦"; readonly cs: "🇨🇿"; readonly da: "🇩🇰"; readonly de: "🇩🇪"; readonly en: "🇬🇧"; readonly "en-pt": "☠️"; ... 22 more ...; readonly "zh-hans": "🇹🇼"; }'. export const getEmojiForLocale = (locale: string): string => LOCALE_TO_EMOJI_MAP[locale] || ""; diff --git a/packages/wonder-stuff-i18n/src/utils/extract-i18n.js b/packages/wonder-stuff-i18n/src/utils/extract-i18n.ts similarity index 96% rename from packages/wonder-stuff-i18n/src/utils/extract-i18n.js rename to packages/wonder-stuff-i18n/src/utils/extract-i18n.ts index 1aeb5626..52e2e73c 100644 --- a/packages/wonder-stuff-i18n/src/utils/extract-i18n.js +++ b/packages/wonder-stuff-i18n/src/utils/extract-i18n.ts @@ -1,19 +1,17 @@ -// @flow - -export type ExtractedString = {| +export type ExtractedString = { // The line number of the string in the original file. - linePos: number, + linePos: number; // The starting position of the string in the original file. - startOffset: number, + startOffset: number; // The ending position of the string in the original file. - endOffset: number, + endOffset: number; // The type of string, such as "_", "$_", or "ngettext". - type: string, + type: string; // The strings found (will be one for singular, two for plural) - msgids: Array, + msgids: Array; // The comments associated with the string. - comments: Array, -|}; + comments: Array; +}; // Used by the `re` function below, allowing for writing multi-line regexes // with comments. @@ -31,7 +29,6 @@ const regexClean = (piece: string) => * Builds a regex pattern (as a string) which can then be turned into a full * regex by calling: `new RegEx(...)`. */ -// $FlowIgnore Flow doesn't handled tagged template literals well. const re = ({raw}: any, ...interpolations: Array) => interpolations.reduce( (regex, insert, index) => regex + insert + regexClean(raw[index + 1]), @@ -307,7 +304,7 @@ const STRIP_COMMENT_RE = new RegExp( * The second argument is an optional string which can be specified to leave a * comment intact (not remove it). */ -const stripJSComments = (jsCode: string, keep: ?string = null) => +const stripJSComments = (jsCode: string, keep: string | null = null) => jsCode.replace(STRIP_COMMENT_RE, (match) => keep != null && keep !== "" && match.includes(keep) ? match @@ -337,7 +334,7 @@ const convertEscapes = (textString: string) => */ const extractAndCombineString = (textString: string): string => { // Look for the string segments (either double or single quote) - const parts = []; + const parts: Array = []; for (const match of textString.matchAll(INNER_STRINGS_RE)) { parts.push(match[1] || match[2]); } @@ -378,6 +375,7 @@ const extractAndCombineComment = (commentString: string): Array => { comments.push(comment.replace(/I18N:\s*/, "").trim()); } else if (comment.trim()) { // Or is this just appending to an existing comment? + // @ts-expect-error [FEI-5011] - TS7022 - 'oldComment' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. const oldComment = comments[comments.length - 1]; comments[comments.length - 1] = (oldComment ? oldComment + " " : "") + comment.trim(); @@ -488,6 +486,7 @@ export function* extractStrings( const endOffset = textString.indexOf( groups.ngettext_plural, + // @ts-expect-error [FEI-5011] - TS2532 - Object is possibly 'undefined'. match.index + groups.ngettext_singular.length, ) + groups.ngettext_plural.length; yield { diff --git a/packages/wonder-stuff-i18n/src/utils/i18n-utils.js b/packages/wonder-stuff-i18n/src/utils/i18n-utils.ts similarity index 88% rename from packages/wonder-stuff-i18n/src/utils/i18n-utils.js rename to packages/wonder-stuff-i18n/src/utils/i18n-utils.ts index 09bb8eb1..2bc2672d 100644 --- a/packages/wonder-stuff-i18n/src/utils/i18n-utils.js +++ b/packages/wonder-stuff-i18n/src/utils/i18n-utils.ts @@ -1,7 +1,7 @@ -// @flow import fs from "fs"; import path from "path"; +// @ts-expect-error [FEI-5011] - TS7016 - Could not find a declaration file for module 'ancesdir'. '/Users/kevinbarabash/khan/wonder-stuff/node_modules/ancesdir/dist/index.js' implicitly has an 'any' type. import ancesdir from "ancesdir"; import {extractStrings} from "./extract-i18n"; @@ -9,7 +9,12 @@ import {extractStrings} from "./extract-i18n"; import type {ExtractedString} from "./extract-i18n"; export type TranslatedLocaleStrings = { - [msgid: string]: string | {|lang: string, messages: Array|}, + [msgid: string]: + | string + | { + lang: string; + messages: Array; + }; }; /** @@ -35,7 +40,7 @@ export const getIgnoreGlobs = ( // Remove empty strings .filter((line) => !!line) ); - } catch (e) { + } catch (e: any) { // If the file doesn't exist, then we're not ignoring any files. return []; } @@ -51,7 +56,7 @@ export const getIgnoreGlobs = ( export const getI18nStringsFromString = ( textString: string, ): Array => { - const strings = []; + const strings: Array = []; // Get all the strings that need to be replaced, but in reverse // order, so that it's easier to insert them in the right place. @@ -80,7 +85,7 @@ export const translateString = ( // If no pre-parsed strings where provided, then we need to parse them // (providing pre-parsed strings can be a performance optimization, // especially if you're translating a file into multiple languages). - strings?: Array = getI18nStringsFromString(textString), + strings: Array = getI18nStringsFromString(textString), ): string => { let translatedSource = textString; diff --git a/packages/wonder-stuff-i18n/src/utils/localize-file.js b/packages/wonder-stuff-i18n/src/utils/localize-file.ts similarity index 92% rename from packages/wonder-stuff-i18n/src/utils/localize-file.js rename to packages/wonder-stuff-i18n/src/utils/localize-file.ts index 9a57c894..7db3bafd 100644 --- a/packages/wonder-stuff-i18n/src/utils/localize-file.js +++ b/packages/wonder-stuff-i18n/src/utils/localize-file.ts @@ -1,4 +1,3 @@ -// @flow /** * Utility that localizes Webpack-generated files with the correct public * path to properly handle dynamic loading of bundles. Used by @@ -58,10 +57,15 @@ export const localizeString = ({ hashMap, getLocalePath, }: { - locale: string, - content: string, - hashMap?: ?{[string]: string}, - getLocalePath: (string) => string, + locale: string; + content: string; + hashMap?: + | { + [key: string]: string; + } + | null + | undefined; + getLocalePath: (arg1: string) => string; }): string => { // Replace all English paths with the path to the locale const newContent = content.replace( @@ -105,11 +109,13 @@ export const localizeFile = ({ hashMap, getLocalePath, }: { - content: string, - locale: string, - oldHash: ?string, - hashMap: {[string]: string}, - getLocalePath: (string) => string, + content: string; + locale: string; + oldHash: string | null | undefined; + hashMap: { + [key: string]: string; + }; + getLocalePath: (arg1: string) => string; }): string => { const newContent = localizeString({ locale, diff --git a/packages/wonder-stuff-i18n/src/utils/pofile-utils.js b/packages/wonder-stuff-i18n/src/utils/pofile-utils.ts similarity index 92% rename from packages/wonder-stuff-i18n/src/utils/pofile-utils.js rename to packages/wonder-stuff-i18n/src/utils/pofile-utils.ts index 6bcab510..3f61555a 100644 --- a/packages/wonder-stuff-i18n/src/utils/pofile-utils.js +++ b/packages/wonder-stuff-i18n/src/utils/pofile-utils.ts @@ -1,4 +1,3 @@ -// @flow import fs from "fs"; import path from "path"; @@ -10,13 +9,15 @@ import {getIgnoreGlobs} from "./i18n-utils"; import type {ExtractedString} from "./extract-i18n"; -type POItem = {| - msgid: string, - msgid_plural: string, - flags: {[string]: boolean}, - references: Array, - extractedComments: Array, -|}; +type POItem = { + msgid: string; + msgid_plural: string; + flags: { + [key: string]: boolean; + }; + references: Array; + extractedComments: Array; +}; /** * Construct a POItem from a filename and extracted string. @@ -30,6 +31,7 @@ export const buildPoItem = ( {linePos, type, msgids: [msgid, plural], comments}: ExtractedString, ): POItem => { // If we haven't seen this string before we build a PO Item. + // @ts-expect-error [FEI-5011] - TS2322 - Type 'Item' is not assignable to type 'POItem'. const poItem: POItem = new PO.Item(); // Add the primary string @@ -164,6 +166,7 @@ export const getPOTFileStringFromFiles = (files: Array): string => { // Normally items would be an array, but we can get away with passing in // the map as internally pofile will just iterate through the items. + // @ts-expect-error [FEI-5011] - TS2740 - Type 'Map' is missing the following properties from type 'Item[]': length, pop, push, concat, and 24 more. potfile.items = getPoItemMap(files); return potfile.toString(); diff --git a/packages/wonder-stuff-sentry/src/__tests__/__snapshots__/kind-error-data.test.js.snap b/packages/wonder-stuff-sentry/src/__tests__/__snapshots__/kind-error-data.test.ts.snap similarity index 100% rename from packages/wonder-stuff-sentry/src/__tests__/__snapshots__/kind-error-data.test.js.snap rename to packages/wonder-stuff-sentry/src/__tests__/__snapshots__/kind-error-data.test.ts.snap diff --git a/packages/wonder-stuff-sentry/src/__tests__/collate-sentry-data.test.js b/packages/wonder-stuff-sentry/src/__tests__/collate-sentry-data.test.ts similarity index 97% rename from packages/wonder-stuff-sentry/src/__tests__/collate-sentry-data.test.js rename to packages/wonder-stuff-sentry/src/__tests__/collate-sentry-data.test.ts index 4d3609a8..4a175bbf 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/collate-sentry-data.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/collate-sentry-data.test.ts @@ -1,11 +1,10 @@ -// @flow import {KindError} from "@khanacademy/wonder-stuff-core"; import {KindSentryError} from "../kind-sentry-error"; import {collateSentryData} from "../collate-sentry-data"; import {DefaultKindErrorDataOptions} from "../default-kind-error-data-options"; import * as NormalizeSentryData from "../normalize-sentry-data"; -jest.mock("../normalize-sentry-data.js", () => +jest.mock("../normalize-sentry-data", () => jest.requireActual("../normalize-sentry-data"), ); @@ -80,7 +79,7 @@ describe("#collateSentryData", () => { kindTagName: "KIND_TAG", groupByTagName: "GROUP_BY_TAG", concatenatedMessageTagName: "CONCATENATED_MESSAGE_TAG", - }; + } as const; // Act const result = collateSentryData(options, error); @@ -150,7 +149,7 @@ describe("#collateSentryData", () => { const options = { ...DefaultKindErrorDataOptions, causalErrorContextPrefix: "CAUSE", - }; + } as const; // Act const result = collateSentryData(options, error); @@ -227,6 +226,7 @@ describe("#collateSentryData", () => { ); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toIncludeSameMembers' does not exist on type 'JestMatchers'. expect(result.fingerprint).toIncludeSameMembers([ "CAUSE1FINGERPRINT", "CAUSE2FINGERPRINT", @@ -291,7 +291,7 @@ describe("#collateSentryData", () => { kindTagName: "KIND_TAG", groupByTagName: "GROUP_BY_TAG", concatenatedMessageTagName: "CONCATENATED_MESSAGE_TAG", - }; + } as const; // Act const result = collateSentryData(options, error); @@ -383,7 +383,7 @@ describe("#collateSentryData", () => { const options = { ...DefaultKindErrorDataOptions, causalErrorContextPrefix: "CAUSE", - }; + } as const; // Act const result = collateSentryData(options, error); @@ -470,6 +470,7 @@ describe("#collateSentryData", () => { ); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toIncludeSameMembers' does not exist on type 'JestMatchers'. expect(result.fingerprint).toIncludeSameMembers([ "ROOTFINGERPRINT", "CAUSE2FINGERPRINT", diff --git a/packages/wonder-stuff-sentry/src/__tests__/get-sentry-data-from-error.test.js b/packages/wonder-stuff-sentry/src/__tests__/get-sentry-data-from-error.test.ts similarity index 75% rename from packages/wonder-stuff-sentry/src/__tests__/get-sentry-data-from-error.test.js rename to packages/wonder-stuff-sentry/src/__tests__/get-sentry-data-from-error.test.ts index b24cdf0c..51f8ae35 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/get-sentry-data-from-error.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/get-sentry-data-from-error.test.ts @@ -1,11 +1,10 @@ -// @flow import {KindSentryError} from "../kind-sentry-error"; import {getSentryDataFromError} from "../get-sentry-data-from-error"; describe("#getSentryDataFromError", () => { it.each([null, undefined, new Error("test")])( "should return null for a non-KindSentryError value like %s", - (error) => { + (error: any) => { // Arrange // Act @@ -28,8 +27,9 @@ describe("#getSentryDataFromError", () => { }, }, fingerprint: ["fingerprint1"], - }; + } as const; const error = new KindSentryError("test", "CUSTOM_KIND", { + // @ts-expect-error [FEI-5011] - TS2322 - Type '{ readonly tags: { readonly tag1: "tagValue1"; }; readonly contexts: { readonly context1: { readonly context1Key1: "context1Value1"; }; }; readonly fingerprint: readonly ["fingerprint1"]; }' is not assignable to type 'Partial'. sentryData, }); diff --git a/packages/wonder-stuff-sentry/src/__tests__/is-reserved-context-property.test.js b/packages/wonder-stuff-sentry/src/__tests__/is-reserved-context-property.test.ts similarity index 68% rename from packages/wonder-stuff-sentry/src/__tests__/is-reserved-context-property.test.js rename to packages/wonder-stuff-sentry/src/__tests__/is-reserved-context-property.test.ts index ed72f1c2..1be28e69 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/is-reserved-context-property.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/is-reserved-context-property.test.ts @@ -1,4 +1,3 @@ -// @flow import {isReservedContextProperty} from "../is-reserved-context-property"; describe("#isReservedContextProperty", () => { @@ -9,6 +8,7 @@ describe("#isReservedContextProperty", () => { const result = isReservedContextProperty("foo"); // Assert + // @ts-expect-error [FEI-5011] - TS2551 - Property 'toBeFalse' does not exist on type 'JestMatchers'. Did you mean 'toBeFalsy'? expect(result).toBeFalse(); }); @@ -19,6 +19,7 @@ describe("#isReservedContextProperty", () => { const result = isReservedContextProperty("type"); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeTrue' does not exist on type 'JestMatchers'. expect(result).toBeTrue(); }); }); diff --git a/packages/wonder-stuff-sentry/src/__tests__/is-reserved-tag-key.test.js b/packages/wonder-stuff-sentry/src/__tests__/is-reserved-tag-key.test.ts similarity index 73% rename from packages/wonder-stuff-sentry/src/__tests__/is-reserved-tag-key.test.js rename to packages/wonder-stuff-sentry/src/__tests__/is-reserved-tag-key.test.ts index b4147ba3..37de7aaa 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/is-reserved-tag-key.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/is-reserved-tag-key.test.ts @@ -1,4 +1,3 @@ -// @flow import {DefaultKindErrorDataOptions} from "../default-kind-error-data-options"; import {isReservedTagKey} from "../is-reserved-tag-key"; @@ -10,6 +9,7 @@ describe("#isReservedTagKey", () => { const result = isReservedTagKey(DefaultKindErrorDataOptions, "foo"); // Assert + // @ts-expect-error [FEI-5011] - TS2551 - Property 'toBeFalse' does not exist on type 'JestMatchers'. Did you mean 'toBeFalsy'? expect(result).toBeFalse(); }); @@ -23,6 +23,7 @@ describe("#isReservedTagKey", () => { ); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeTrue' does not exist on type 'JestMatchers'. expect(result).toBeTrue(); }); }); diff --git a/packages/wonder-stuff-sentry/src/__tests__/is-tag-key-valid.test.js b/packages/wonder-stuff-sentry/src/__tests__/is-tag-key-valid.test.ts similarity index 66% rename from packages/wonder-stuff-sentry/src/__tests__/is-tag-key-valid.test.js rename to packages/wonder-stuff-sentry/src/__tests__/is-tag-key-valid.test.ts index d754f3d5..2e8a902e 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/is-tag-key-valid.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/is-tag-key-valid.test.ts @@ -1,29 +1,30 @@ -// @flow import {isTagKeyValid} from "../is-tag-key-valid"; describe("#isTagKeyValid", () => { it.each([undefined, "", Array(33).fill("a").join("")])( "should return false if a key is not valid (%s)", - (testPoint) => { + (testPoint: any) => { // Arrange // Act const result = isTagKeyValid(testPoint); // Assert + // @ts-expect-error [FEI-5011] - TS2551 - Property 'toBeFalse' does not exist on type 'JestMatchers'. Did you mean 'toBeFalsy'? expect(result).toBeFalse(); }, ); it.each(["a", Array(32).fill("a").join("")])( "should return true if a key is valid (%s)", - (testPoint) => { + (testPoint: any) => { // Arrange // Act const result = isTagKeyValid(testPoint); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeTrue' does not exist on type 'JestMatchers'. expect(result).toBeTrue(); }, ); diff --git a/packages/wonder-stuff-sentry/src/__tests__/kind-error-data.test.js b/packages/wonder-stuff-sentry/src/__tests__/kind-error-data.test.ts similarity index 84% rename from packages/wonder-stuff-sentry/src/__tests__/kind-error-data.test.js rename to packages/wonder-stuff-sentry/src/__tests__/kind-error-data.test.ts index fca3683d..4e0bc7cc 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/kind-error-data.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/kind-error-data.test.ts @@ -1,4 +1,3 @@ -// @flow import * as CollateSentryData from "../collate-sentry-data"; import {DefaultKindErrorDataOptions} from "../default-kind-error-data-options"; import {EmptySentryData} from "../empty-sentry-data"; @@ -28,15 +27,18 @@ describe("KindErrorData", () => { groupByTagName: `${INVALID_TAG_NAME}-group-by`, concatenatedMessageTagName: `${INVALID_TAG_NAME}-concatenated-message`, }, - ])("should throw if options are invalid (%s)", (badOptions) => { - // Arrange + ])( + "should throw if options are invalid (%s)", + (badOptions: any) => { + // Arrange - // Act - const act = () => new KindErrorData(badOptions); + // Act + const act = () => new KindErrorData(badOptions); - // Assert - expect(act).toThrowErrorMatchingSnapshot(); - }); + // Assert + expect(act).toThrowErrorMatchingSnapshot(); + }, + ); }); describe("when built for production", () => { @@ -53,15 +55,18 @@ describe("KindErrorData", () => { groupByTagName: `${INVALID_TAG_NAME}-group-by`, concatenatedMessageTagName: `${INVALID_TAG_NAME}-concatenated-message`, }, - ])("should not throw if options are invalid (%s)", (badOptions) => { - // Arrange + ])( + "should not throw if options are invalid (%s)", + (badOptions: any) => { + // Arrange - // Act - const act = () => new KindErrorData(badOptions); + // Act + const act = () => new KindErrorData(badOptions); - // Assert - expect(act).not.toThrowError("Invalid options"); - }); + // Assert + expect(act).not.toThrowError("Invalid options"); + }, + ); }); it("should include information when throwing about invalid options", async () => { @@ -70,14 +75,14 @@ describe("KindErrorData", () => { kindTagName: `${INVALID_TAG_NAME}-kind`, groupByTagName: `${INVALID_TAG_NAME}-group-by`, concatenatedMessageTagName: `${INVALID_TAG_NAME}-concatenated-message`, - }; + } as const; // Act - const act = new Promise((resolve, reject) => { + const act = new Promise((resolve: any, reject: any) => { try { // Should not resolve! resolve(new KindErrorData(badOptions)); - } catch (e) { + } catch (e: any) { reject(e); } }); @@ -127,7 +132,7 @@ describe("KindErrorData", () => { const event = { kind: "event", event_id: "event-id", - }; + } as const; // Act const result = registeredProcessor(event); @@ -146,18 +151,18 @@ describe("KindErrorData", () => { }); const enhanceSpy = jest .spyOn(underTest, "enhanceEventWithErrorData") + // @ts-expect-error [FEI-5011] - TS2559 - Type '"ENHANCED"' has no properties in common with type 'SentryEvent'. .mockReturnValue("ENHANCED"); - // $FlowIgnore[escaped-generic] underTest.setupOnce(addGlobalEventProcessorMock, getHub); const registeredProcessor = addGlobalEventProcessorMock.mock.calls[0][0]; const event = { kind: "event", event_id: "event-id", - }; + } as const; const hint = { event_id: "event-id", - }; + } as const; // Act const result = registeredProcessor(event, hint); @@ -178,17 +183,17 @@ describe("KindErrorData", () => { }, ])( "should return the event if the original exception (%s) is not an Error", - (originalException) => { + (originalException: any) => { // Arrange const underTest = new KindErrorData(); const event = { kind: "event", event_id: "event-id", - }; + } as const; const hint = { event_id: "event-id", originalException, - }; + } as const; // Act const result = underTest.enhanceEventWithErrorData(event, hint); @@ -204,7 +209,7 @@ describe("KindErrorData", () => { const event = { kind: "event", event_id: "event-id", - }; + } as const; // Act const result = underTest.enhanceEventWithErrorData(event); @@ -219,16 +224,16 @@ describe("KindErrorData", () => { ...DefaultKindErrorDataOptions, groupByTagName: "GROUP", kindTagName: "KIND", - }; + } as const; const underTest = new KindErrorData(options); const event = { kind: "event", event_id: "event-id", - }; + } as const; const hint = { event_id: "event-id", originalException: new Error("original-exception"), - }; + } as const; const collateSentryDataSpy = jest .spyOn(CollateSentryData, "collateSentryData") .mockReturnValue(EmptySentryData); @@ -249,7 +254,7 @@ describe("KindErrorData", () => { ...DefaultKindErrorDataOptions, groupByTagName: "GROUP", kindTagName: "KIND", - }; + } as const; const underTest = new KindErrorData(options); const event = { kind: "event", @@ -267,11 +272,11 @@ describe("KindErrorData", () => { }, }, fingerprint: ["originalFingerprint"], - }; + } as const; const hint = { event_id: "event-id", originalException: new Error("original-exception"), - }; + } as const; jest.spyOn(CollateSentryData, "collateSentryData").mockReturnValue({ tags: { tag1: "tag1-value", @@ -285,6 +290,7 @@ describe("KindErrorData", () => { }); // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly kind: "event"; readonly event_id: "event-id"; readonly tags: { readonly tag1: "originalValue1"; readonly tag2: "originalValue2"; }; readonly contexts: { readonly context1: { readonly key1: "originalValue1"; }; readonly context2: { ...; }; }; readonly fingerprint: readonly [...]; }' is not assignable to parameter of type 'SentryEvent'. const result = underTest.enhanceEventWithErrorData(event, hint); // Assert diff --git a/packages/wonder-stuff-sentry/src/__tests__/kind-sentry-error.test.js b/packages/wonder-stuff-sentry/src/__tests__/kind-sentry-error.test.ts similarity index 92% rename from packages/wonder-stuff-sentry/src/__tests__/kind-sentry-error.test.js rename to packages/wonder-stuff-sentry/src/__tests__/kind-sentry-error.test.ts index ee54e187..d4895967 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/kind-sentry-error.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/kind-sentry-error.test.ts @@ -1,4 +1,3 @@ -// @flow import {Errors} from "@khanacademy/wonder-stuff-core"; import type {Metadata} from "@khanacademy/wonder-stuff-core"; import {KindSentryError} from "../kind-sentry-error"; @@ -13,6 +12,7 @@ describe("KindSentryError", () => { const {name: result} = new KindSentryError("MESSAGE", "KIND"); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toEndWith' does not exist on type 'JestMatchers'. expect(result).toEndWith("SentryError"); }); @@ -25,6 +25,7 @@ describe("KindSentryError", () => { }); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toEndWith' does not exist on type 'JestMatchers'. expect(result).toEndWith("NAMEError"); }); @@ -37,6 +38,7 @@ describe("KindSentryError", () => { }); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toStartWith' does not exist on type 'JestMatchers'. expect(result).toStartWith("PREFIX"); }); @@ -75,7 +77,7 @@ describe("KindSentryError", () => { const metadata: Metadata = { some: "metadata", }; - const sentryData: $Partial = { + const sentryData: Partial = { tags: { tag1: "tagvalue1", }, @@ -108,7 +110,7 @@ describe("KindSentryError", () => { const metadata: Metadata = { some: "metadata", }; - const sentryData: $Partial = { + const sentryData: Partial = { tags: { tag1: "tagvalue1", }, diff --git a/packages/wonder-stuff-sentry/src/__tests__/normalize-sentry-data.test.js b/packages/wonder-stuff-sentry/src/__tests__/normalize-sentry-data.test.ts similarity index 90% rename from packages/wonder-stuff-sentry/src/__tests__/normalize-sentry-data.test.js rename to packages/wonder-stuff-sentry/src/__tests__/normalize-sentry-data.test.ts index 2a2b4b3f..7a1cab0f 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/normalize-sentry-data.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/normalize-sentry-data.test.ts @@ -1,4 +1,3 @@ -// @flow import {DefaultKindErrorDataOptions} from "../default-kind-error-data-options"; import {normalizeSentryData} from "../normalize-sentry-data"; import * as TruncateTagValue from "../truncate-tag-value"; @@ -22,7 +21,7 @@ describe("#normalizeSentryData", () => { tags: { "": "value1", }, - }; + } as const; // Act const result = () => @@ -40,7 +39,7 @@ describe("#normalizeSentryData", () => { tags: { [DefaultKindErrorDataOptions.kindTagName]: "value1", }, - }; + } as const; // Act const result = () => @@ -60,7 +59,7 @@ describe("#normalizeSentryData", () => { type: "value1", }, }, - }; + } as const; // Act const result = () => @@ -84,7 +83,7 @@ describe("#normalizeSentryData", () => { tags: { "": "value1", }, - }; + } as const; // Act const result = () => @@ -100,7 +99,7 @@ describe("#normalizeSentryData", () => { tags: { [DefaultKindErrorDataOptions.kindTagName]: "value1", }, - }; + } as const; // Act const result = () => @@ -118,7 +117,7 @@ describe("#normalizeSentryData", () => { type: "value1", }, }, - }; + } as const; // Act const result = () => @@ -151,15 +150,15 @@ describe("#normalizeSentryData", () => { notReservedAtAll: "value7", }, }, - }; + } as const; // Act - const act = new Promise((resolve, reject) => { + const act = new Promise((resolve: any, reject: any) => { try { normalizeSentryData(DefaultKindErrorDataOptions, data); // Should never resolve! resolve(); - } catch (e) { + } catch (e: any) { reject(e); } }); @@ -192,7 +191,7 @@ describe("#normalizeSentryData", () => { tags: { tag1: "Untruncated", }, - }; + } as const; // Act const {tags: result} = normalizeSentryData( @@ -209,7 +208,7 @@ describe("#normalizeSentryData", () => { it("should return the validated sentry data", () => { // Arrange jest.spyOn(TruncateTagValue, "truncateTagValue").mockImplementation( - (t) => t, + (t: any) => t, ); const data = { tags: { @@ -225,9 +224,10 @@ describe("#normalizeSentryData", () => { }, }, fingerprint: ["fingerprint1", "fingerprint2"], - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly tags: { readonly tag1: "tag1Value"; readonly tag2: "tag2Value"; }; readonly contexts: { readonly contextOne: { readonly iAm: "a context"; }; readonly contextTwo: { readonly iAmAlso: "a context"; }; }; readonly fingerprint: readonly [...]; }' is not assignable to parameter of type 'Readonly>'. const result = normalizeSentryData(DefaultKindErrorDataOptions, data); // Assert @@ -243,7 +243,7 @@ describe("#normalizeSentryData", () => { {contexts: {aMissingContext: undefined}}, ])( "should set defaults for data not included in the data given to be validated (%s)", - (testPoint) => { + (testPoint: any) => { // Arrange // Act diff --git a/packages/wonder-stuff-sentry/src/__tests__/sentry-data-reducer.test.js b/packages/wonder-stuff-sentry/src/__tests__/sentry-data-reducer.test.ts similarity index 99% rename from packages/wonder-stuff-sentry/src/__tests__/sentry-data-reducer.test.js rename to packages/wonder-stuff-sentry/src/__tests__/sentry-data-reducer.test.ts index 49a47427..ea380a12 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/sentry-data-reducer.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/sentry-data-reducer.test.ts @@ -1,4 +1,3 @@ -// @flow import {sentryDataReducer} from "../sentry-data-reducer"; import {EmptySentryData} from "../empty-sentry-data"; import {DefaultKindErrorDataOptions} from "../default-kind-error-data-options"; @@ -9,7 +8,7 @@ describe("#sentryDataReducer", () => { describe("index is zero", () => { it.each([null, EmptySentryData])( "should return the accumulator when error has no sentry data", - (sentryData) => { + (sentryData: any) => { // Arrange const accumulator: SentryData = { tags: { @@ -154,7 +153,7 @@ describe("#sentryDataReducer", () => { const options = { ...DefaultKindErrorDataOptions, causalErrorContextPrefix: "custom-context-name", - }; + } as const; const accumulator: SentryData = { tags: { tag1: "value1", diff --git a/packages/wonder-stuff-sentry/src/__tests__/truncate-tag-value.test.js b/packages/wonder-stuff-sentry/src/__tests__/truncate-tag-value.test.ts similarity index 95% rename from packages/wonder-stuff-sentry/src/__tests__/truncate-tag-value.test.js rename to packages/wonder-stuff-sentry/src/__tests__/truncate-tag-value.test.ts index 8611021a..7b1d9f3d 100644 --- a/packages/wonder-stuff-sentry/src/__tests__/truncate-tag-value.test.js +++ b/packages/wonder-stuff-sentry/src/__tests__/truncate-tag-value.test.ts @@ -1,10 +1,9 @@ -// @flow import {truncateTagValue} from "../truncate-tag-value"; describe("#truncateTagValue", () => { it.each(["", "ABCDEFGHIJK", Array(200).fill("a").join("")])( "should not truncate tag values that do not need it (%s)", - (testPoint) => { + (testPoint: any) => { // Arrange // Act diff --git a/packages/wonder-stuff-sentry/src/collate-sentry-data.js b/packages/wonder-stuff-sentry/src/collate-sentry-data.ts similarity index 90% rename from packages/wonder-stuff-sentry/src/collate-sentry-data.js rename to packages/wonder-stuff-sentry/src/collate-sentry-data.ts index 2464046f..80eb07c3 100644 --- a/packages/wonder-stuff-sentry/src/collate-sentry-data.js +++ b/packages/wonder-stuff-sentry/src/collate-sentry-data.ts @@ -1,4 +1,3 @@ -// @flow import { errorsFromError, Order, @@ -34,10 +33,11 @@ import type {SentryData, KindErrorDataOptions} from "./types"; export const collateSentryData = ( options: KindErrorDataOptions, error: Error, -): $ReadOnly => { +): Readonly => { // First, get all the errors in the stack. const errors = errorsFromError(error, Order.ConsequenceFirst); - const consquenceAndCauses: $ReadOnlyArray = Array.from(errors); + // @ts-expect-error [FEI-5011] - TS2769 - No overload matches this call. + const consquenceAndCauses: ReadonlyArray = Array.from(errors); // Now, we need to collate this stack as follows: // 1. Any sentryData they hold has to be merged into the collatedData from @@ -45,7 +45,7 @@ export const collateSentryData = ( // take precedent. // 2. Errors, regardless of whether they have sentryData, need to be // given their own context in the data. - const rawCollatedData: $ReadOnly = + const rawCollatedData: Readonly = consquenceAndCauses.reduceRight( (acc, value, index) => sentryDataReducer(options, acc, value, index), @@ -81,8 +81,9 @@ export const collateSentryData = ( ...collatedData.tags, [kindTagName]: truncateTagValue(kindTag), [concatenatedMessageTagName]: truncateTagValue(concatenatedMessageTag), - }; + } as const; if (groupByTag.length) { + // @ts-expect-error [FEI-5011] - TS2542 - Index signature in type '{ readonly [x: string]: string; }' only permits reading. tags[groupByTagName] = truncateTagValue(groupByTag); } diff --git a/packages/wonder-stuff-sentry/src/default-kind-error-data-options.js b/packages/wonder-stuff-sentry/src/default-kind-error-data-options.ts similarity index 97% rename from packages/wonder-stuff-sentry/src/default-kind-error-data-options.js rename to packages/wonder-stuff-sentry/src/default-kind-error-data-options.ts index 057e43c5..2aa6b3fe 100644 --- a/packages/wonder-stuff-sentry/src/default-kind-error-data-options.js +++ b/packages/wonder-stuff-sentry/src/default-kind-error-data-options.ts @@ -1,4 +1,3 @@ -// @flow import type {KindErrorDataOptions} from "./types"; /** diff --git a/packages/wonder-stuff-sentry/src/empty-sentry-data.js b/packages/wonder-stuff-sentry/src/empty-sentry-data.ts similarity index 63% rename from packages/wonder-stuff-sentry/src/empty-sentry-data.js rename to packages/wonder-stuff-sentry/src/empty-sentry-data.ts index 479d69a1..7905456d 100644 --- a/packages/wonder-stuff-sentry/src/empty-sentry-data.js +++ b/packages/wonder-stuff-sentry/src/empty-sentry-data.ts @@ -1,10 +1,9 @@ -// @flow import type {SentryData} from "./types"; /** * An empty sentry data object. */ -export const EmptySentryData: $ReadOnly = Object.freeze({ +export const EmptySentryData: Readonly = Object.freeze({ tags: {}, contexts: {}, fingerprint: [], diff --git a/packages/wonder-stuff-sentry/src/get-sentry-data-from-error.js b/packages/wonder-stuff-sentry/src/get-sentry-data-from-error.ts similarity index 91% rename from packages/wonder-stuff-sentry/src/get-sentry-data-from-error.js rename to packages/wonder-stuff-sentry/src/get-sentry-data-from-error.ts index ede44d7b..30bfbab8 100644 --- a/packages/wonder-stuff-sentry/src/get-sentry-data-from-error.js +++ b/packages/wonder-stuff-sentry/src/get-sentry-data-from-error.ts @@ -1,4 +1,3 @@ -// @flow import {KindSentryError} from "./kind-sentry-error"; import type {SentryData} from "./types"; @@ -11,7 +10,7 @@ import type {SentryData} from "./types"; */ export const getSentryDataFromError = ( error: Error, -): ?$ReadOnly => { +): Readonly | null | undefined => { if (error instanceof KindSentryError) { return error.sentryData; } diff --git a/packages/wonder-stuff-sentry/src/index.js b/packages/wonder-stuff-sentry/src/index.ts similarity index 96% rename from packages/wonder-stuff-sentry/src/index.js rename to packages/wonder-stuff-sentry/src/index.ts index 500f150a..1a42e574 100644 --- a/packages/wonder-stuff-sentry/src/index.js +++ b/packages/wonder-stuff-sentry/src/index.ts @@ -1,4 +1,3 @@ -// @flow export {KindSentryError} from "./kind-sentry-error"; export {KindErrorData} from "./kind-error-data"; diff --git a/packages/wonder-stuff-sentry/src/is-reserved-context-property.js b/packages/wonder-stuff-sentry/src/is-reserved-context-property.ts similarity index 98% rename from packages/wonder-stuff-sentry/src/is-reserved-context-property.js rename to packages/wonder-stuff-sentry/src/is-reserved-context-property.ts index 08c6a7be..0a5dc008 100644 --- a/packages/wonder-stuff-sentry/src/is-reserved-context-property.js +++ b/packages/wonder-stuff-sentry/src/is-reserved-context-property.ts @@ -1,4 +1,3 @@ -// @flow // From: // https://docs.sentry.io/platforms/python/guides/logging/enriching-events/context/ const RESERVED_CONTEXT_PROPERTIES = new Set(["type"]); diff --git a/packages/wonder-stuff-sentry/src/is-reserved-tag-key.js b/packages/wonder-stuff-sentry/src/is-reserved-tag-key.ts similarity index 98% rename from packages/wonder-stuff-sentry/src/is-reserved-tag-key.js rename to packages/wonder-stuff-sentry/src/is-reserved-tag-key.ts index 8da90424..b0636fbd 100644 --- a/packages/wonder-stuff-sentry/src/is-reserved-tag-key.js +++ b/packages/wonder-stuff-sentry/src/is-reserved-tag-key.ts @@ -1,4 +1,3 @@ -// @flow import type {KindErrorDataOptions} from "./types"; /** diff --git a/packages/wonder-stuff-sentry/src/is-tag-key-valid.js b/packages/wonder-stuff-sentry/src/is-tag-key-valid.ts similarity index 98% rename from packages/wonder-stuff-sentry/src/is-tag-key-valid.js rename to packages/wonder-stuff-sentry/src/is-tag-key-valid.ts index 1cf76118..68d541b4 100644 --- a/packages/wonder-stuff-sentry/src/is-tag-key-valid.js +++ b/packages/wonder-stuff-sentry/src/is-tag-key-valid.ts @@ -1,5 +1,3 @@ -// @flow - // Tag keys must be no more than 32 characters long. const MAX_TAG_KEY_LENGTH = 32; diff --git a/packages/wonder-stuff-sentry/src/kind-error-data.js b/packages/wonder-stuff-sentry/src/kind-error-data.ts similarity index 90% rename from packages/wonder-stuff-sentry/src/kind-error-data.js rename to packages/wonder-stuff-sentry/src/kind-error-data.ts index 2c0a4ffb..d3ae660e 100644 --- a/packages/wonder-stuff-sentry/src/kind-error-data.js +++ b/packages/wonder-stuff-sentry/src/kind-error-data.ts @@ -1,4 +1,3 @@ -// @flow import {Errors} from "@khanacademy/wonder-stuff-core"; import type { SentryEvent, @@ -14,18 +13,18 @@ import {DefaultKindErrorDataOptions} from "./default-kind-error-data-options"; import {isTagKeyValid} from "./is-tag-key-valid"; import {KindSentryError} from "./kind-sentry-error"; -type InvalidTags = {| - invalidKindTag?: string, - invalidGroupByTag?: string, - invalidConcatenatedMessageTag?: string, -|}; +type InvalidTags = { + invalidKindTag?: string; + invalidGroupByTag?: string; + invalidConcatenatedMessageTag?: string; +}; export class KindErrorData implements SentryIntegration { static id: string = "KindErrorData"; name: string = KindErrorData.id; - +_options: KindErrorDataOptions; + readonly _options: KindErrorDataOptions; - constructor(options: $Partial = Object.freeze({})) { + constructor(options: Partial = Object.freeze({})) { this._options = { ...DefaultKindErrorDataOptions, ...options, @@ -73,6 +72,7 @@ export class KindErrorData implements SentryIntegration { if (!self) { return event; } + // @ts-expect-error [FEI-5011] - TS2339 - Property 'enhanceEventWithErrorData' does not exist on type 'SentryIntegration'. return self.enhanceEventWithErrorData(event, hint); }, ); @@ -115,7 +115,7 @@ export class KindErrorData implements SentryIntegration { const updatedContexts = { ...event.contexts, ...contexts, - }; + } as const; /** * NOTE: If you don't see Sentry serializing the right depth in your * contexts, increase the `normalizeDepth` option of the Sentry diff --git a/packages/wonder-stuff-sentry/src/kind-sentry-error.js b/packages/wonder-stuff-sentry/src/kind-sentry-error.ts similarity index 90% rename from packages/wonder-stuff-sentry/src/kind-sentry-error.js rename to packages/wonder-stuff-sentry/src/kind-sentry-error.ts index a66f9391..adced220 100644 --- a/packages/wonder-stuff-sentry/src/kind-sentry-error.js +++ b/packages/wonder-stuff-sentry/src/kind-sentry-error.ts @@ -1,4 +1,3 @@ -// @flow import {KindError, Errors} from "@khanacademy/wonder-stuff-core"; import type {Metadata} from "@khanacademy/wonder-stuff-core"; import type {SentryData} from "./types"; @@ -13,8 +12,7 @@ type Options = { * * @type {?Error} */ - cause?: ?Error, - + cause?: Error | null | undefined; /** * Sentry tags, contexts, and fingerprint information to be attached. * @@ -22,8 +20,7 @@ type Options = { * * @type {?$Partial} */ - sentryData?: ?$Partial, - + sentryData?: Partial | null | undefined; /** * Other data to be attached to the error. * @@ -31,42 +28,37 @@ type Options = { * * @type {?Metadata} */ - metadata?: ?Metadata, - + metadata?: Metadata | null | undefined; /** * A prefix to be added to the error name. * * @type {?string} */ - prefix?: ?string, - + prefix?: string | null | undefined; /** * A name for the error. * * @type {?string} */ - name?: ?string, - + name?: string | null | undefined; /** * The number of stack frames to strip from the error. * * @type {?number} */ - stripStackFrames?: ?number, - + stripStackFrames?: number | null | undefined; /** * The minimum number of stack frames to try and retain. * * @type {?number} */ - minimumFrameCount?: ?number, - + minimumFrameCount?: number | null | undefined; /** * Should we create a composite stack from the causal error chain or not? * * @type {?boolean} */ - compositeStack?: ?boolean, + compositeStack?: boolean | null | undefined; }; /** @@ -161,14 +153,12 @@ export class KindSentryError extends KindError { }); } - get sentryData(): $ReadOnly { + get sentryData(): Readonly { // (1) We always ensure there is metadata // (2) We know that the sentry data has the fields we need. // (3) We know that the sentry data in the metadata only has the fields // we need. - // $FlowIgnore[incompatible-use] (1) - // $FlowIgnore[incompatible-return] (2) - // $FlowIgnore[incompatible-indexer] (3) + // @ts-expect-error [FEI-5011] - TS2322 - Type 'MetadataPrimitive | Metadata | MetadataArray' is not assignable to type 'Readonly'. | TS2533 - Object is possibly 'null' or 'undefined'. return this.metadata.sentry; } } diff --git a/packages/wonder-stuff-sentry/src/normalize-sentry-data.js b/packages/wonder-stuff-sentry/src/normalize-sentry-data.ts similarity index 89% rename from packages/wonder-stuff-sentry/src/normalize-sentry-data.js rename to packages/wonder-stuff-sentry/src/normalize-sentry-data.ts index 61ec43a0..a5fad340 100644 --- a/packages/wonder-stuff-sentry/src/normalize-sentry-data.js +++ b/packages/wonder-stuff-sentry/src/normalize-sentry-data.ts @@ -1,4 +1,3 @@ -// @flow import {Errors} from "@khanacademy/wonder-stuff-core"; import {EmptySentryData} from "./empty-sentry-data"; import {KindSentryError} from "./kind-sentry-error"; @@ -25,14 +24,22 @@ import {isReservedContextProperty} from "./is-reserved-context-property"; */ export function normalizeSentryData( options: KindErrorDataOptions, - data: ?$ReadOnly<$Partial>, + data?: Readonly> | null, ): SentryData { // https://docs.sentry.io/platforms/python/guides/logging/enriching-events/tags/ const tags: SentryTags = { ...data?.tags, }; - const invalidKeys = []; - const usedReservedKeys = []; + const invalidKeys: Array< + | MetadataPrimitive + | Metadata + | MetadataArray + > = []; + const usedReservedKeys: Array< + | MetadataPrimitive + | Metadata + | MetadataArray + > = []; // We want to valid tag keys and normalize tag values. // However, we don't bother with the validation production. for (const key of Object.keys(tags)) { @@ -59,9 +66,9 @@ export function normalizeSentryData( // If the contexts contain any reserved property names, report them, but // only in production. if (process.env.NODE_ENV !== "production") { - const reservedPropertyContexts: {| - [string]: Array, - |} = {}; + const reservedPropertyContexts: { + [key: string]: Array; + } = {}; const contexts = data?.contexts; if (contexts != null) { for (const contextName of Object.keys(contexts)) { @@ -97,7 +104,7 @@ export function normalizeSentryData( invalid_tag_keys: invalidKeys, reserved_tag_keys: usedReservedKeys, contexts_with_reserved_properties: - (reservedPropertyContexts: $FlowFixMe), + reservedPropertyContexts as any, }, }, }, diff --git a/packages/wonder-stuff-sentry/src/sentry-data-reducer.js b/packages/wonder-stuff-sentry/src/sentry-data-reducer.ts similarity index 91% rename from packages/wonder-stuff-sentry/src/sentry-data-reducer.js rename to packages/wonder-stuff-sentry/src/sentry-data-reducer.ts index 9d24aaee..3668b12c 100644 --- a/packages/wonder-stuff-sentry/src/sentry-data-reducer.js +++ b/packages/wonder-stuff-sentry/src/sentry-data-reducer.ts @@ -1,4 +1,3 @@ -// @flow import { safeStringify, getOriginalStackFromError, @@ -26,7 +25,7 @@ import {EmptySentryData} from "./empty-sentry-data"; */ export const sentryDataReducer = ( options: KindErrorDataOptions, - accumulator: $ReadOnly, + accumulator: Readonly, current: Error, index: number, ): SentryData => { @@ -49,11 +48,11 @@ export const sentryDataReducer = ( // contexts, tags? // Combine tags by spreading the current tags over the accumulator tags. - const tags = {...accumulatorTags, ...currentTags}; + const tags = {...accumulatorTags, ...currentTags} as const; // Combine contexts by spreading the current contexts over the accumulator // contexts. - const contexts = {...accumulatorContexts, ...currentContexts}; + const contexts = {...accumulatorContexts, ...currentContexts} as const; // Combine fingerprint information, making sure to deduplicate via a Set and // remove any empty strings with a Boolean filter. @@ -65,6 +64,7 @@ export const sentryDataReducer = ( // Next, unless the index is 0, we need to add a context for the error. if (index !== 0) { + // @ts-expect-error [FEI-5011] - TS2542 - Index signature in type '{ readonly [x: string]: Metadata; }' only permits reading. contexts[ `${causalErrorContextPrefix}${index}` // e.g., "Source Error - 1" ] = { diff --git a/packages/wonder-stuff-sentry/src/truncate-tag-value.js b/packages/wonder-stuff-sentry/src/truncate-tag-value.ts similarity index 98% rename from packages/wonder-stuff-sentry/src/truncate-tag-value.js rename to packages/wonder-stuff-sentry/src/truncate-tag-value.ts index 27b05440..26dc76c5 100644 --- a/packages/wonder-stuff-sentry/src/truncate-tag-value.js +++ b/packages/wonder-stuff-sentry/src/truncate-tag-value.ts @@ -1,4 +1,3 @@ -// @flow import {truncateMiddle} from "@khanacademy/wonder-stuff-core"; // Tag values must be no more than 200 characters long. diff --git a/packages/wonder-stuff-sentry/src/types.js b/packages/wonder-stuff-sentry/src/types.ts similarity index 76% rename from packages/wonder-stuff-sentry/src/types.js rename to packages/wonder-stuff-sentry/src/types.ts index 34dcb9b7..dad74ec0 100644 --- a/packages/wonder-stuff-sentry/src/types.js +++ b/packages/wonder-stuff-sentry/src/types.ts @@ -1,4 +1,5 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2307 - Cannot find module 'flow-to-typescript-codemod' or its corresponding type declarations. +import {Flow} from "flow-to-typescript-codemod"; import type {Metadata} from "@khanacademy/wonder-stuff-core"; /** @@ -7,7 +8,7 @@ import type {Metadata} from "@khanacademy/wonder-stuff-core"; * The key of each item is the name of the tag. */ export type SentryTags = { - [name: string]: string, + [name: string]: string; }; /** @@ -23,7 +24,7 @@ export type SentryContext = Metadata; * The key of each item is the name of the context. */ export type SentryContexts = { - [name: string]: SentryContext, + [name: string]: SentryContext; }; /** @@ -48,50 +49,45 @@ export type SentryFingerprint = Array; * associated sentry event. * This is equivalent to using the `setFingerprint` API. */ -export type SentryData = {| +export type SentryData = { /** * This is passed to setTags on the sentry scope. * Tags help categorize things. */ - tags: SentryTags, - + tags: SentryTags; /** * These are each passed to setContext on the sentry scope. * Contexts create a new headed section in the sentry report. * Useful for grouping specific context together. */ - contexts: SentryContexts, - + contexts: SentryContexts; /** * This is passed to setFingerprint on the sentry scope. * The fingerprint helps group like messages that otherwise would not * get grouped. */ - fingerprint: SentryFingerprint, -|}; + fingerprint: SentryFingerprint; +}; export type KindErrorDataOptions = { /** * The name to use for the Sentry tag that indicates the error kind. */ - +kindTagName: string, - + readonly kindTagName: string; /** * The name to use for the Sentry tag that indicates the grouping string. */ - +groupByTagName: string, - + readonly groupByTagName: string; /** * The name to use for the Sentry tag that contains the concatenated error. */ - +concatenatedMessageTagName: string, - + readonly concatenatedMessageTagName: string; /** * The prefix to use for Sentry contexts that contain information about * each error in the causal error chain. * A unique number is appended to the prefix to create the context name. */ - +causalErrorContextPrefix: string, + readonly causalErrorContextPrefix: string; // TODO(somewhatabstract): Allow configuration of which fields we include // in causal error contexts. @@ -122,46 +118,49 @@ export interface SentryEvent { release?: string; dist?: string; environment?: string; - sdk?: $FlowFixMe; + sdk?: any; request?: Request; transaction?: string; - modules?: {[key: string]: string}; + modules?: { + [key: string]: string; + }; fingerprint?: SentryFingerprint; exception?: { - values?: Array<$FlowFixMe>, + values?: Array; }; - stacktrace?: $FlowFixMe; - breadcrumbs?: Array<$FlowFixMe>; + stacktrace?: any; + breadcrumbs?: Array; contexts?: SentryContexts; tags?: SentryTags; extra?: SentryContext; - user?: $FlowFixMe; - type?: $FlowFixMe; - spans?: Array<$FlowFixMe>; - measurements?: $FlowFixMe; - debug_meta?: $FlowFixMe; + user?: any; + type?: any; + spans?: Array; + measurements?: any; + debug_meta?: any; } export interface SentryEventHint { event_id?: string; - captureContext?: $FlowFixMe; - syntheticException?: ?Error; - originalException?: ?(Error | string); - data?: $FlowFixMe; + captureContext?: any; + syntheticException?: Error | null | undefined; + originalException?: Error | string | null | undefined; + data?: any; } export type SentryEventProcessor = ( event: SentryEvent, hint?: SentryEventHint, -) => Promise | ?SentryEvent; +) => Promise | SentryEvent | null | undefined; export interface SentryHub { - getIntegration(integration: Class): ?T; + getIntegration( + integration: Flow.Class, + ): T | null | undefined; } export interface SentryIntegration { name: string; - /** * Sets the integration up only once. * This takes no options on purpose, options should be passed in the constructor diff --git a/packages/wonder-stuff-server-google/src/__tests__/__snapshots__/trace-impl.test.js.snap b/packages/wonder-stuff-server-google/src/__tests__/__snapshots__/trace-impl.test.ts.snap similarity index 100% rename from packages/wonder-stuff-server-google/src/__tests__/__snapshots__/trace-impl.test.js.snap rename to packages/wonder-stuff-server-google/src/__tests__/__snapshots__/trace-impl.test.ts.snap diff --git a/packages/wonder-stuff-server-google/src/__tests__/add-app-engine-middleware.test.js b/packages/wonder-stuff-server-google/src/__tests__/add-app-engine-middleware.test.ts similarity index 74% rename from packages/wonder-stuff-server-google/src/__tests__/add-app-engine-middleware.test.js rename to packages/wonder-stuff-server-google/src/__tests__/add-app-engine-middleware.test.ts index f7f103cc..6db0a16f 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/add-app-engine-middleware.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/add-app-engine-middleware.test.ts @@ -1,4 +1,3 @@ -// @flow import * as Express from "express"; import {Runtime} from "@khanacademy/wonder-stuff-server"; import * as LoggingWinston from "@google-cloud/logging-winston"; @@ -11,11 +10,11 @@ jest.mock("@google-cloud/logging-winston"); describe("#addAppEngineMiddleware", () => { it("should use the passed application", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = {} as any; + const pretendApp = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); // Act @@ -28,15 +27,16 @@ describe("#addAppEngineMiddleware", () => { describe("in production", () => { it("should add the logging-winston middleware", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = {} as any; + const pretendApp = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); jest.spyOn( LoggingWinston.express, "makeMiddleware", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'Promise<(req: ServerRequest, res: ServerResponse, next: Function) => void>'. ).mockReturnValue("FAKE_LW_EXPRESS"); // Act @@ -52,14 +52,15 @@ describe("#addAppEngineMiddleware", () => { it("should pass the logger to logging-winston middleware", async () => { // Arrange - const pretendLogger = ("FAKE_LOGGER": $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = "FAKE_LOGGER" as any; + const pretendApp = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); const lwSpy = jest .spyOn(LoggingWinston.express, "makeMiddleware") + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'Promise<(req: ServerRequest, res: ServerResponse, next: Function) => void>'. .mockReturnValue("FAKE_LW_EXPRESS"); // Act @@ -74,14 +75,14 @@ describe("#addAppEngineMiddleware", () => { }); }); - describe.each([Runtime.Test, Runtime.Development])("in %s", (mode) => { + describe.each([Runtime.Test, Runtime.Development])("in %s", (mode: any) => { it("should not add the logging-winston middleware", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = {} as any; + const pretendApp = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); const lwSpy = jest.spyOn(LoggingWinston.express, "makeMiddleware"); @@ -95,12 +96,12 @@ describe("#addAppEngineMiddleware", () => { it("should add requestID middleware", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const pretendMiddleware = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = {} as any; + const pretendApp = {} as any; + const pretendMiddleware = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); jest.spyOn( MakeAppEngineRequestIDMiddleware, @@ -116,12 +117,12 @@ describe("#addAppEngineMiddleware", () => { it("should pass logger to requestID middleware", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const pretendMiddleware = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = {} as any; + const pretendApp = {} as any; + const pretendMiddleware = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); const makeMiddlewareSpy = jest .spyOn( @@ -139,11 +140,11 @@ describe("#addAppEngineMiddleware", () => { it("should return the updated application", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendApp = ({}: $FlowFixMe); - const newApp = ({ + const pretendLogger = {} as any; + const pretendApp = {} as any; + const newApp = { use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockReturnValue(newApp); // Act diff --git a/packages/wonder-stuff-server-google/src/__tests__/get-app-engine-info.test.js b/packages/wonder-stuff-server-google/src/__tests__/get-app-engine-info.test.ts similarity index 96% rename from packages/wonder-stuff-server-google/src/__tests__/get-app-engine-info.test.js rename to packages/wonder-stuff-server-google/src/__tests__/get-app-engine-info.test.ts index 701a45f9..23070956 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/get-app-engine-info.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/get-app-engine-info.test.ts @@ -1,7 +1,6 @@ -// @flow import {getAppEngineInfo} from "../get-app-engine-info"; -const resetEnv = (name: string, value: ?string): void => { +const resetEnv = (name: string, value?: string | null): void => { if (value == null) { delete process.env[name]; } else { diff --git a/packages/wonder-stuff-server-google/src/__tests__/get-appengine-request-id.test.js b/packages/wonder-stuff-server-google/src/__tests__/get-appengine-request-id.test.ts similarity index 83% rename from packages/wonder-stuff-server-google/src/__tests__/get-appengine-request-id.test.js rename to packages/wonder-stuff-server-google/src/__tests__/get-appengine-request-id.test.ts index bf1cbc97..9d857fb5 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/get-appengine-request-id.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/get-appengine-request-id.test.ts @@ -1,12 +1,11 @@ -// @flow import {getAppEngineRequestID} from "../get-app-engine-request-id"; describe("#getAppEngineRequestID", () => { it("should return null when header is absent", () => { // Arrange - const request = ({ + const request = { header: jest.fn(), - }: $FlowFixMe); + } as any; // Act const result = getAppEngineRequestID(request); @@ -17,13 +16,13 @@ describe("#getAppEngineRequestID", () => { it("should return the requestID when it does not end with 000101xx", () => { // Arrange - const request = ({ - header: jest.fn((key) => + const request = { + header: jest.fn((key: any) => key === "X-Appengine-Request-Log-Id" ? "this-is-a-good-request-id" : null, ), - }: $FlowFixMe); + } as any; // Act const result = getAppEngineRequestID(request); @@ -34,13 +33,13 @@ describe("#getAppEngineRequestID", () => { it("should return a fixed requestID when it does end with 000101xx", () => { // Arrange - const request = ({ - header: jest.fn((key) => + const request = { + header: jest.fn((key: any) => key === "X-Appengine-Request-Log-Id" ? "this-is-a-bad-request-id-000101BD" : null, ), - }: $FlowFixMe); + } as any; // Act const result = getAppEngineRequestID(request); diff --git a/packages/wonder-stuff-server-google/src/__tests__/get-delta.test.js b/packages/wonder-stuff-server-google/src/__tests__/get-delta.test.ts similarity index 66% rename from packages/wonder-stuff-server-google/src/__tests__/get-delta.test.js rename to packages/wonder-stuff-server-google/src/__tests__/get-delta.test.ts index b6507246..c24f7e41 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/get-delta.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/get-delta.test.ts @@ -1,4 +1,3 @@ -// @flow import {getDelta} from "../get-delta"; describe("#getDelta", () => { @@ -8,14 +7,15 @@ describe("#getDelta", () => { a: 30, b: 0, c: 40000, - }; + } as const; const second = { a: 60, b: 30, c: 10000, - }; + } as const; // Act + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly a: 60; readonly b: 30; readonly c: 10000; }' is not assignable to parameter of type '{ readonly a: 30; readonly b: 0; readonly c: 40000; }'. const result = getDelta(first, second); // Assert diff --git a/packages/wonder-stuff-server-google/src/__tests__/setup-integrations.test.js b/packages/wonder-stuff-server-google/src/__tests__/setup-integrations.test.ts similarity index 72% rename from packages/wonder-stuff-server-google/src/__tests__/setup-integrations.test.js rename to packages/wonder-stuff-server-google/src/__tests__/setup-integrations.test.ts index 2f66aafe..eae63860 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/setup-integrations.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/setup-integrations.test.ts @@ -1,4 +1,3 @@ -// @flow import * as DebugAgent from "@google-cloud/debug-agent"; import * as Profiler from "@google-cloud/profiler"; import {Runtime} from "@khanacademy/wonder-stuff-server"; @@ -59,27 +58,30 @@ describe("#setupIntegrations", () => { }); }); - describe.each([Runtime.Test, Runtime.Development])("in %s", (runtime) => { - it("should not setup @google-cloud/debug-agent", async () => { - // Arrange - const agentSpy = jest.spyOn(DebugAgent, "start"); + describe.each([Runtime.Test, Runtime.Development])( + "in %s", + (runtime: any) => { + it("should not setup @google-cloud/debug-agent", async () => { + // Arrange + const agentSpy = jest.spyOn(DebugAgent, "start"); - // Act - await setupIntegrations(runtime); + // Act + await setupIntegrations(runtime); - // Assert - expect(agentSpy).not.toHaveBeenCalled(); - }); + // Assert + expect(agentSpy).not.toHaveBeenCalled(); + }); - it("should not setup @google-cloud/profiler", async () => { - // Arrange - const agentSpy = jest.spyOn(Profiler, "start"); + it("should not setup @google-cloud/profiler", async () => { + // Arrange + const agentSpy = jest.spyOn(Profiler, "start"); - // Act - await setupIntegrations(runtime); + // Act + await setupIntegrations(runtime); - // Assert - expect(agentSpy).not.toHaveBeenCalled(); - }); - }); + // Assert + expect(agentSpy).not.toHaveBeenCalled(); + }); + }, + ); }); diff --git a/packages/wonder-stuff-server-google/src/__tests__/start-server.test.js b/packages/wonder-stuff-server-google/src/__tests__/start-server.test.ts similarity index 86% rename from packages/wonder-stuff-server-google/src/__tests__/start-server.test.js rename to packages/wonder-stuff-server-google/src/__tests__/start-server.test.ts index a69cebff..0e31f274 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/start-server.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/start-server.test.ts @@ -1,4 +1,3 @@ -// @flow import * as Server from "@khanacademy/wonder-stuff-server"; import * as LoggingWinston from "@google-cloud/logging-winston"; import * as AddAppEngineMiddleware from "../add-app-engine-middleware"; @@ -13,6 +12,7 @@ jest.mock("@google-cloud/logging-winston"); describe("#start-server", () => { beforeEach(() => { + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '() => void' is not assignable to parameter of type '(event: string | symbol, listener: (...args: any[]) => void) => Process'. jest.spyOn(process, "on").mockImplementation(() => {}); }); @@ -35,8 +35,8 @@ describe("#start-server", () => { host: "127.0.0.1", mode: Server.Runtime.Test, logLevel: "debug", - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; jest.spyOn( AddAppEngineMiddleware, "addAppEngineMiddleware", @@ -59,8 +59,8 @@ describe("#start-server", () => { host: "127.0.0.1", logLevel: "debug", mode: Server.Runtime.Test, - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; jest.spyOn( AddAppEngineMiddleware, "addAppEngineMiddleware", @@ -86,8 +86,8 @@ describe("#start-server", () => { host: "127.0.0.1", logLevel: "debug", mode: Server.Runtime.Test, - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; jest.spyOn( AddAppEngineMiddleware, "addAppEngineMiddleware", @@ -118,8 +118,8 @@ describe("#start-server", () => { host: "127.0.0.1", logLevel: "debug", mode: Server.Runtime.Test, - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; jest.spyOn( AddAppEngineMiddleware, "addAppEngineMiddleware", @@ -128,6 +128,7 @@ describe("#start-server", () => { GetDefaultLogMetadata, "getDefaultLogMetadata", ).mockReturnValue({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ here: string; }' is not assignable to parameter of type '{ instanceID: string; processID: number; }'. here: "is default metadata", }); @@ -157,8 +158,8 @@ describe("#start-server", () => { host: "127.0.0.1", logLevel: "debug", mode: Server.Runtime.Production, - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; jest.spyOn( AddAppEngineMiddleware, "addAppEngineMiddleware", @@ -167,10 +168,12 @@ describe("#start-server", () => { GetDefaultLogMetadata, "getDefaultLogMetadata", ).mockReturnValue({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ here: string; }' is not assignable to parameter of type '{ instanceID: string; processID: number; }'. here: "is default metadata", }); jest.spyOn(LoggingWinston, "LoggingWinston").mockImplementation( - ({level}) => ({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '({ level, }: any) => { wut: string; }' is not assignable to parameter of type '(options?: Options | undefined) => LoggingWinston'. + ({level}: any) => ({ wut: `FAKE_${level}_LW_TRANSPORT`, }), ); @@ -201,8 +204,8 @@ describe("#start-server", () => { host: "127.0.0.1", logLevel: "debug", mode: Server.Runtime.Test, - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; const addAppEngineMiddlewareSpy = jest .spyOn(AddAppEngineMiddleware, "addAppEngineMiddleware") .mockResolvedValue(pretendApp); @@ -230,8 +233,8 @@ describe("#start-server", () => { host: "127.0.0.1", logLevel: "debug", mode: Server.Runtime.Test, - }; - const pretendApp = ({}: $FlowFixMe); + } as const; + const pretendApp = {} as any; jest.spyOn( AddAppEngineMiddleware, "addAppEngineMiddleware", diff --git a/packages/wonder-stuff-server-google/src/__tests__/trace-impl.test.js b/packages/wonder-stuff-server-google/src/__tests__/trace-impl.test.ts similarity index 73% rename from packages/wonder-stuff-server-google/src/__tests__/trace-impl.test.js rename to packages/wonder-stuff-server-google/src/__tests__/trace-impl.test.ts index cc8900ee..32d12c35 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/trace-impl.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/trace-impl.test.ts @@ -1,4 +1,3 @@ -// @flow import * as GetAppEngineInfo from "../get-app-engine-info"; import {traceImpl} from "../trace-impl"; @@ -7,9 +6,10 @@ jest.mock("../get-app-engine-info"); describe("#trace", () => { it.each([[""], [null], [undefined]])( "should throw if the action is empty/falsy", - (testPoint) => { + (testPoint: any) => { // Arrange - const fakeLogger = ({}: $FlowFixMe); + const fakeLogger = {} as any; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. jest.spyOn(GetAppEngineInfo, "getAppEngineInfo").mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -25,10 +25,11 @@ describe("#trace", () => { it("should log the start of the session", () => { // Arrange - const fakeLogger = ({ + const fakeLogger = { silly: jest.fn(), startTimer: jest.fn(), - }: $FlowFixMe); + } as any; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. jest.spyOn(GetAppEngineInfo, "getAppEngineInfo").mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -43,10 +44,11 @@ describe("#trace", () => { it("should start a timer", () => { // Arrange - const fakeLogger = ({ + const fakeLogger = { silly: jest.fn(), startTimer: jest.fn(), - }: $FlowFixMe); + } as any; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. jest.spyOn(GetAppEngineInfo, "getAppEngineInfo").mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -61,13 +63,14 @@ describe("#trace", () => { it("should create a tracer span", () => { // Arrange - const fakeLogger: $FlowFixMe = { + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn(), }; - const fakeTracer: $FlowFixMe = { + const fakeTracer: any = { createChildSpan: jest.fn(), }; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. jest.spyOn(GetAppEngineInfo, "getAppEngineInfo").mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -84,10 +87,11 @@ describe("#trace", () => { it("should return a trace session", () => { // Arrange - const fakeLogger: $FlowFixMe = { + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn(), }; + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. jest.spyOn(GetAppEngineInfo, "getAppEngineInfo").mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -104,13 +108,14 @@ describe("#trace", () => { describe("#action", () => { it("should give action of the trace", () => { // Arrange - const fakeLogger: $FlowFixMe = { + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn(), }; jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -126,13 +131,14 @@ describe("#trace", () => { it("should be read-only", () => { // Arrange - const fakeLogger: $FlowFixMe = { + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn(), }; jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -140,13 +146,7 @@ describe("#trace", () => { const session = traceImpl(fakeLogger, "ACTION", "MESSAGE"); // Act - /** - * $FlowExpectedError[cannot-write] Flow is going to complain - * because name is readonly. - * We will suppress this because we want to test that runtime - * code is enforcing this. The idea of this test is to ensure - * that folks don't edit out this specific behavior. - */ + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string' is not assignable to type '() => string'. const underTest = () => (session.action = "NEW_ACTION!"); // Assert @@ -165,21 +165,24 @@ describe("#trace", () => { // Arrange const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn(process, "memoryUsage") .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 10000, }) .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 50000, }); jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -206,21 +209,24 @@ describe("#trace", () => { // Arrange const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn(process, "memoryUsage") .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 10000, }) .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 50000, }); jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -247,21 +253,24 @@ describe("#trace", () => { // Arrange const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn(process, "memoryUsage") .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 10000, }) .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 50000, }); jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -292,21 +301,24 @@ describe("#trace", () => { // Arrange const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn(process, "memoryUsage") .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 50000, }) .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 10000, }); jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -340,21 +352,24 @@ describe("#trace", () => { // Arrange const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn(process, "memoryUsage") .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 10000, }) .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 50000, }); jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -391,21 +406,24 @@ describe("#trace", () => { // Arrange const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn(process, "memoryUsage") .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 10000, }) .mockReturnValueOnce({ + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ someMemoryStuff: number; }' is not assignable to parameter of type 'MemoryUsage'. someMemoryStuff: 50000, }); jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", @@ -435,20 +453,21 @@ describe("#trace", () => { const fakeTraceSpan = { addLabel: jest.fn(), endSpan: jest.fn(), - }; - const fakeTracer: $FlowFixMe = { + } as const; + const fakeTracer: any = { createChildSpan: jest.fn().mockReturnValue(fakeTraceSpan), }; const fakeTimer = { done: jest.fn(), - }; - const fakeLogger: $FlowFixMe = { + } as const; + const fakeLogger: any = { silly: jest.fn(), startTimer: jest.fn().mockReturnValue(fakeTimer), }; jest.spyOn( GetAppEngineInfo, "getAppEngineInfo", + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ name: string; version: string; }' is not assignable to parameter of type 'AppEngineInfo'. ).mockReturnValue({ name: "GATEWAY_NAME", version: "GATEWAY_VERSION", diff --git a/packages/wonder-stuff-server-google/src/__tests__/trace.test.js b/packages/wonder-stuff-server-google/src/__tests__/trace.test.ts similarity index 76% rename from packages/wonder-stuff-server-google/src/__tests__/trace.test.js rename to packages/wonder-stuff-server-google/src/__tests__/trace.test.ts index b2947560..fe105a5a 100644 --- a/packages/wonder-stuff-server-google/src/__tests__/trace.test.js +++ b/packages/wonder-stuff-server-google/src/__tests__/trace.test.ts @@ -1,4 +1,3 @@ -// @flow import * as TraceAgent from "@google-cloud/trace-agent"; import * as Server from "@khanacademy/wonder-stuff-server"; import * as TraceImpl from "../trace-impl"; @@ -12,11 +11,11 @@ describe("#trace", () => { describe("with request", () => { it("should pass request to getLogger", () => { // Arrange - const fakeRequest: $FlowFixMe = ({ + const fakeRequest: any = { url: "", - }: $FlowFixMe); - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + } as any; + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); const getLoggerSpy = jest .spyOn(Server, "getLogger") @@ -31,11 +30,11 @@ describe("#trace", () => { it("should invoke the shared trace implementation with the logger and tracer", () => { // Arrange - const fakeRequest: $FlowFixMe = ({ + const fakeRequest: any = { url: "", - }: $FlowFixMe); - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + } as any; + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); jest.spyOn(Server, "getLogger").mockReturnValue(fakeLogger); const traceImplSpy = jest.spyOn(TraceImpl, "traceImpl"); @@ -54,12 +53,12 @@ describe("#trace", () => { it("should return the trace session", () => { // Arrange - const fakeTraceSession: $FlowFixMe = ({}: $FlowFixMe); - const fakeRequest: $FlowFixMe = ({ + const fakeTraceSession: any = {} as any; + const fakeRequest: any = { url: "", - }: $FlowFixMe); - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + } as any; + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); jest.spyOn(Server, "getLogger").mockReturnValue(fakeLogger); jest.spyOn(TraceImpl, "traceImpl").mockReturnValue( @@ -77,8 +76,8 @@ describe("#trace", () => { describe("without logger nor request", () => { it("should invoke the shared trace implementation with the logger and tracer", () => { // Arrange - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); jest.spyOn(Server, "getLogger").mockReturnValue(fakeLogger); const traceImplSpy = jest.spyOn(TraceImpl, "traceImpl"); @@ -97,9 +96,9 @@ describe("#trace", () => { it("should return the trace session", () => { // Arrange - const fakeTraceSession: $FlowFixMe = ({}: $FlowFixMe); - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + const fakeTraceSession: any = {} as any; + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); jest.spyOn(Server, "getLogger").mockReturnValue(fakeLogger); jest.spyOn(TraceImpl, "traceImpl").mockReturnValue( @@ -117,8 +116,8 @@ describe("#trace", () => { describe("with logger", () => { it("should invoke the shared trace implementation with the logger and tracer", () => { // Arrange - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); const traceImplSpy = jest.spyOn(TraceImpl, "traceImpl"); @@ -136,9 +135,9 @@ describe("#trace", () => { it("should return the trace session", () => { // Arrange - const fakeTraceSession: $FlowFixMe = ({}: $FlowFixMe); - const fakeLogger: $FlowFixMe = ({}: $FlowFixMe); - const fakeTracer: $FlowFixMe = ({}: $FlowFixMe); + const fakeTraceSession: any = {} as any; + const fakeLogger: any = {} as any; + const fakeTracer: any = {} as any; jest.spyOn(TraceAgent, "get").mockReturnValue(fakeTracer); jest.spyOn(TraceImpl, "traceImpl").mockReturnValue( fakeTraceSession, diff --git a/packages/wonder-stuff-server-google/src/add-app-engine-middleware.js b/packages/wonder-stuff-server-google/src/add-app-engine-middleware.ts similarity index 63% rename from packages/wonder-stuff-server-google/src/add-app-engine-middleware.js rename to packages/wonder-stuff-server-google/src/add-app-engine-middleware.ts index 83047b68..1103d842 100644 --- a/packages/wonder-stuff-server-google/src/add-app-engine-middleware.js +++ b/packages/wonder-stuff-server-google/src/add-app-engine-middleware.ts @@ -1,6 +1,5 @@ -// @flow import express from "express"; -import type {$Application, $Request, $Response} from "express"; +import type {Application, Request, Response} from "express"; import {Runtime} from "@khanacademy/wonder-stuff-server"; import type {Logger} from "@khanacademy/wonder-stuff-server"; import * as lw from "@google-cloud/logging-winston"; @@ -9,11 +8,17 @@ import {makeAppEngineRequestIDMiddleware} from "./middleware/make-app-engine-req /** * Apply the middleware that we want to use with Google App Engine (GAE). */ -export async function addAppEngineMiddleware( - app: $Application, - mode: $Values, +export async function addAppEngineMiddleware< + TReq extends Request, + TRes extends Response, +>( + // @ts-expect-error [FEI-5011] - TS2315 - Type 'Application' is not generic. + app: Application, + mode: (typeof Runtime)[keyof typeof Runtime], logger: Logger, -): Promise<$Application> { + // @ts-expect-error [FEI-5011] - TS2315 - Type 'Application' is not generic. +): Promise> { + // @ts-expect-error [FEI-5011] - TS2558 - Expected 0 type arguments, but got 2. const middlewareApp = express(); /** diff --git a/packages/wonder-stuff-server-google/src/get-app-engine-info.js b/packages/wonder-stuff-server-google/src/get-app-engine-info.ts similarity index 98% rename from packages/wonder-stuff-server-google/src/get-app-engine-info.js rename to packages/wonder-stuff-server-google/src/get-app-engine-info.ts index 23a63ed9..44975798 100644 --- a/packages/wonder-stuff-server-google/src/get-app-engine-info.js +++ b/packages/wonder-stuff-server-google/src/get-app-engine-info.ts @@ -1,4 +1,3 @@ -// @flow import type {AppEngineInfo} from "./types"; /** diff --git a/packages/wonder-stuff-server-google/src/get-app-engine-request-id.js b/packages/wonder-stuff-server-google/src/get-app-engine-request-id.ts similarity index 87% rename from packages/wonder-stuff-server-google/src/get-app-engine-request-id.js rename to packages/wonder-stuff-server-google/src/get-app-engine-request-id.ts index b71b860b..64fbae6d 100644 --- a/packages/wonder-stuff-server-google/src/get-app-engine-request-id.js +++ b/packages/wonder-stuff-server-google/src/get-app-engine-request-id.ts @@ -1,10 +1,11 @@ -// @flow -import type {$Request} from "express"; +import type {Request} from "express"; /** * Get the GAE request ID for a given request if it exists. */ -export const getAppEngineRequestID = (req: $Request): ?string => { +export const getAppEngineRequestID = ( + req: Request, +): string | null | undefined => { const requestID = req.header("X-Appengine-Request-Log-Id"); if (requestID == null) { return null; diff --git a/packages/wonder-stuff-server-google/src/get-default-log-metadata.js b/packages/wonder-stuff-server-google/src/get-default-log-metadata.ts similarity index 79% rename from packages/wonder-stuff-server-google/src/get-default-log-metadata.js rename to packages/wonder-stuff-server-google/src/get-default-log-metadata.ts index 86b3887d..37195b10 100644 --- a/packages/wonder-stuff-server-google/src/get-default-log-metadata.js +++ b/packages/wonder-stuff-server-google/src/get-default-log-metadata.ts @@ -1,4 +1,3 @@ -// @flow import type {AppEngineInfo} from "./types"; import {getAppEngineInfo} from "./get-app-engine-info"; @@ -6,8 +5,8 @@ import {getAppEngineInfo} from "./get-app-engine-info"; * Get the default log metadata for a Google Cloud app engine server. */ export const getDefaultLogMetadata = (): { - instanceID: AppEngineInfo["instance"], - processID: AppEngineInfo["pid"], + instanceID: AppEngineInfo["instance"]; + processID: AppEngineInfo["pid"]; } => { const {instance, pid} = getAppEngineInfo(); return { diff --git a/packages/wonder-stuff-server-google/src/get-delta.js b/packages/wonder-stuff-server-google/src/get-delta.js deleted file mode 100644 index 218d3aa3..00000000 --- a/packages/wonder-stuff-server-google/src/get-delta.js +++ /dev/null @@ -1,13 +0,0 @@ -// @flow -type NumberObj = { - [key: string]: number, - ... -}; - -export const getDelta = (first: T, second: T): T => { - const result: $Shape = {}; - for (const key of Object.keys(first)) { - result[key] = second[key] - first[key]; - } - return result; -}; diff --git a/packages/wonder-stuff-server-google/src/get-delta.ts b/packages/wonder-stuff-server-google/src/get-delta.ts new file mode 100644 index 00000000..3dea2613 --- /dev/null +++ b/packages/wonder-stuff-server-google/src/get-delta.ts @@ -0,0 +1,13 @@ +type NumberObj = { + [key: string]: number; +}; + +export const getDelta = (first: T, second: T): T => { + const result: Partial = {}; + for (const key of Object.keys(first)) { + // @ts-expect-error [FEI-5011] - TS2536 - Type 'string' cannot be used to index type 'Partial'. + result[key] = second[key] - first[key]; + } + // @ts-expect-error [FEI-5011] - TS2322 - Type 'Partial' is not assignable to type 'T'. + return result; +}; diff --git a/packages/wonder-stuff-server-google/src/index.js b/packages/wonder-stuff-server-google/src/index.ts similarity index 92% rename from packages/wonder-stuff-server-google/src/index.js rename to packages/wonder-stuff-server-google/src/index.ts index b535101d..ab5227f5 100644 --- a/packages/wonder-stuff-server-google/src/index.js +++ b/packages/wonder-stuff-server-google/src/index.ts @@ -1,3 +1,2 @@ -// @flow export {startServer} from "./start-server"; export type {ServerOptions, GoogleCloudIntegrations} from "./types"; diff --git a/packages/wonder-stuff-server-google/src/middleware/__tests__/make-app-engine-request-id-middleware.test.js b/packages/wonder-stuff-server-google/src/middleware/__tests__/make-app-engine-request-id-middleware.test.ts similarity index 65% rename from packages/wonder-stuff-server-google/src/middleware/__tests__/make-app-engine-request-id-middleware.test.js rename to packages/wonder-stuff-server-google/src/middleware/__tests__/make-app-engine-request-id-middleware.test.ts index e469a01c..4601b130 100644 --- a/packages/wonder-stuff-server-google/src/middleware/__tests__/make-app-engine-request-id-middleware.test.js +++ b/packages/wonder-stuff-server-google/src/middleware/__tests__/make-app-engine-request-id-middleware.test.ts @@ -1,4 +1,3 @@ -//@flow import * as Server from "@khanacademy/wonder-stuff-server"; import {makeAppEngineRequestIDMiddleware} from "../make-app-engine-request-id-middleware"; import * as GetAppEngineRequestID from "../../get-app-engine-request-id"; @@ -8,12 +7,13 @@ jest.mock("../../get-app-engine-request-id"); describe("#makeAppEngineRequestIDMiddleware", () => { it("should return middleware function", () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); + const pretendLogger = {} as any; // Act const result = makeAppEngineRequestIDMiddleware(pretendLogger); // Assert + // @ts-expect-error [FEI-5011] - TS2339 - Property 'toBeFunction' does not exist on type 'JestMatchers>'. expect(result).toBeFunction(); }); @@ -28,9 +28,9 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should not call getRequestLogger", () => { // Arrange - const pretendDefaultLogger = ({}: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + const pretendDefaultLogger = {} as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); @@ -40,10 +40,6 @@ describe("#makeAppEngineRequestIDMiddleware", () => { ); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert @@ -52,9 +48,9 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should not create child logger from logger", () => { // Arrange - const pretendDefaultLogger = ({child: jest.fn()}: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + const pretendDefaultLogger = {child: jest.fn()} as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); @@ -63,10 +59,6 @@ describe("#makeAppEngineRequestIDMiddleware", () => { ); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert @@ -75,18 +67,14 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should invoke next", () => { // Arrange - const pretendDefaultLogger = ({}: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + const pretendDefaultLogger = {} as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert @@ -104,9 +92,9 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should use default logger and request with getRequestLogger to get logger", () => { // Arrange - const pretendDefaultLogger = ({child: jest.fn()}: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + const pretendDefaultLogger = {child: jest.fn()} as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); @@ -115,10 +103,6 @@ describe("#makeAppEngineRequestIDMiddleware", () => { .mockReturnValue(pretendDefaultLogger); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert @@ -130,9 +114,9 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should create child logger from logger with requestID", () => { // Arrange - const pretendDefaultLogger = ({child: jest.fn()}: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + const pretendDefaultLogger = {child: jest.fn()} as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); @@ -141,10 +125,6 @@ describe("#makeAppEngineRequestIDMiddleware", () => { ); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert @@ -155,12 +135,12 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should attach child logger to request.log", () => { // Arrange - const pretendChildLogger = ({}: $FlowFixMe); - const pretendDefaultLogger = ({ + const pretendChildLogger = {} as any; + const pretendDefaultLogger = { child: () => pretendChildLogger, - }: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + } as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); @@ -169,10 +149,6 @@ describe("#makeAppEngineRequestIDMiddleware", () => { ); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert @@ -181,9 +157,9 @@ describe("#makeAppEngineRequestIDMiddleware", () => { it("should invoke next", () => { // Arrange - const pretendDefaultLogger = ({child: jest.fn()}: $FlowFixMe); - const pretendRequest = ({}: $FlowFixMe); - const pretendResponse = ({}: $FlowFixMe); + const pretendDefaultLogger = {child: jest.fn()} as any; + const pretendRequest = {} as any; + const pretendResponse = {} as any; const mockNext = jest.fn(); const middleware = makeAppEngineRequestIDMiddleware(pretendDefaultLogger); @@ -192,10 +168,6 @@ describe("#makeAppEngineRequestIDMiddleware", () => { ); // Act - /** - * $FlowIgnore[incompatible-call] The return type of Middleware - * can be error or non-error middleware and this confuses flow. - */ middleware(pretendRequest, pretendResponse, mockNext); // Assert diff --git a/packages/wonder-stuff-server-google/src/middleware/make-app-engine-request-id-middleware.js b/packages/wonder-stuff-server-google/src/middleware/make-app-engine-request-id-middleware.ts similarity index 80% rename from packages/wonder-stuff-server-google/src/middleware/make-app-engine-request-id-middleware.js rename to packages/wonder-stuff-server-google/src/middleware/make-app-engine-request-id-middleware.ts index a755036d..2362dbb9 100644 --- a/packages/wonder-stuff-server-google/src/middleware/make-app-engine-request-id-middleware.js +++ b/packages/wonder-stuff-server-google/src/middleware/make-app-engine-request-id-middleware.ts @@ -1,5 +1,5 @@ -// @flow -import type {$Response, $Request, Middleware, NextFunction} from "express"; +// @ts-expect-error [FEI-5011] - TS2305 - Module '"express"' has no exported member 'Middleware'. +import type {Response, Request, Middleware, NextFunction} from "express"; import {getRequestLogger} from "@khanacademy/wonder-stuff-server"; import type {Logger, RequestWithLog} from "@khanacademy/wonder-stuff-server"; import {getAppEngineRequestID} from "../get-app-engine-request-id"; @@ -9,10 +9,10 @@ import {getAppEngineRequestID} from "../get-app-engine-request-id"; * that will attach the GAE requestID to the log metadata. */ export function makeAppEngineRequestIDMiddleware< - TReq: RequestWithLog<$Request>, - TRes: $Response, + TReq extends RequestWithLog, + TRes extends Response, >(defaultLogger: Logger): Middleware { - return , TRes: $Response>( + return , TRes extends Response>( req: TReq, res: TRes, next: NextFunction, diff --git a/packages/wonder-stuff-server-google/src/setup-integrations.js b/packages/wonder-stuff-server-google/src/setup-integrations.ts similarity index 94% rename from packages/wonder-stuff-server-google/src/setup-integrations.js rename to packages/wonder-stuff-server-google/src/setup-integrations.ts index 470b19d9..1889d69d 100644 --- a/packages/wonder-stuff-server-google/src/setup-integrations.js +++ b/packages/wonder-stuff-server-google/src/setup-integrations.ts @@ -1,4 +1,3 @@ -// @flow import {Runtime} from "@khanacademy/wonder-stuff-server"; import type {GoogleCloudIntegrations} from "./types"; @@ -8,7 +7,7 @@ import type {GoogleCloudIntegrations} from "./types"; * These integrations help debug production services. */ export const setupIntegrations = async ( - mode: $Values, + mode: (typeof Runtime)[keyof typeof Runtime], {debugAgent, profiler}: GoogleCloudIntegrations = { debugAgent: false, profiler: false, diff --git a/packages/wonder-stuff-server-google/src/start-server.js b/packages/wonder-stuff-server-google/src/start-server.ts similarity index 86% rename from packages/wonder-stuff-server-google/src/start-server.js rename to packages/wonder-stuff-server-google/src/start-server.ts index afd8dfe0..0f555ca9 100644 --- a/packages/wonder-stuff-server-google/src/start-server.js +++ b/packages/wonder-stuff-server-google/src/start-server.ts @@ -1,5 +1,4 @@ -// @flow -import type {$Application, $Request, $Response} from "express"; +import type {Application, Request, Response} from "express"; import { startServer as startServerCore, Runtime, @@ -20,12 +19,12 @@ import {getDefaultLogMetadata} from "./get-default-log-metadata"; * middleware before listening on the appropriate port per the passed options. */ export async function startServer< - TReq: RequestWithLog<$Request>, - TRes: $Response, + TReq extends RequestWithLog, + TRes extends Response, >( options: ServerOptions, - app: $Application, -): Promise { + app: Application, +): Promise { const {integrations, logLevel, ...restOptions} = options; /** @@ -47,6 +46,7 @@ export async function startServer< // In production, we use the Google Cloud logging winston transport. restOptions.mode === Runtime.Production ? new lw.LoggingWinston({ + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string | number | symbol' is not assignable to type 'string | undefined'. level: logLevel, }) : null, diff --git a/packages/wonder-stuff-server-google/src/trace-impl.js b/packages/wonder-stuff-server-google/src/trace-impl.ts similarity index 92% rename from packages/wonder-stuff-server-google/src/trace-impl.js rename to packages/wonder-stuff-server-google/src/trace-impl.ts index 15234b41..8fbbc024 100644 --- a/packages/wonder-stuff-server-google/src/trace-impl.js +++ b/packages/wonder-stuff-server-google/src/trace-impl.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2305 - Module '"@google-cloud/trace-agent"' has no exported member 'Tracer'. import type {Tracer} from "@google-cloud/trace-agent"; import {Errors, KindError} from "@khanacademy/wonder-stuff-core"; import type {Logger} from "@khanacademy/wonder-stuff-server"; @@ -75,9 +75,9 @@ export const traceImpl = ( */ const span = tracer?.createChildSpan({name: `${gatewayName}.${action}`}); - const profileLabels: {| - [string]: mixed, - |} = {}; + const profileLabels: { + [key: string]: unknown; + } = {}; const addLabel = (name: string, value: T): void => { /** * Track this so we can also include it in our logging info. @@ -107,7 +107,7 @@ export const traceImpl = ( * and so `getDelta` isn't typed to handle that. Have to rethink * how to make that work. */ - // $FlowFixMe[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'MemoryUsage' is not assignable to parameter of type 'NumberObj'. addLabel("/memory/delta", getDelta(beforeMemory, afterMemory)); addLabel("/memory/final", afterMemory); @@ -119,7 +119,6 @@ export const traceImpl = ( * We suppress flow because we want the TraceSessionInfo to overwrite * things and it's OK if we don't know what things it overwrites. */ - // $FlowIgnore[cannot-spread-indexer] const metadata = { /** * We have to add the default metadata because winston does not @@ -130,7 +129,7 @@ export const traceImpl = ( ...profileLabels, ...info, message: `TRACED ${logMessage}`, - }; + } as const; /** * Let's mark our profile as done. @@ -150,6 +149,7 @@ export const traceImpl = ( }; return { + // @ts-expect-error [FEI-5011] - TS2322 - Type 'string' is not assignable to type '() => string'. get action() { return action; }, diff --git a/packages/wonder-stuff-server-google/src/trace.js b/packages/wonder-stuff-server-google/src/trace.ts similarity index 89% rename from packages/wonder-stuff-server-google/src/trace.js rename to packages/wonder-stuff-server-google/src/trace.ts index 7b6689ba..d37fec52 100644 --- a/packages/wonder-stuff-server-google/src/trace.js +++ b/packages/wonder-stuff-server-google/src/trace.ts @@ -1,7 +1,6 @@ -// @flow import * as traceAgent from "@google-cloud/trace-agent"; import {getLogger} from "@khanacademy/wonder-stuff-server"; -import type {$Request} from "express"; +import type {Request} from "express"; import type {Logger, RequestWithLog} from "@khanacademy/wonder-stuff-server"; import {traceImpl} from "./trace-impl"; import type {ITraceSession} from "./types"; @@ -25,12 +24,11 @@ interface ITrace { * @returns {ITraceSession} The new trace session that was created and is to be * used to end the session. */ - >( + >( action: string, message: string, request?: TReq, ): ITraceSession; - /** * Start tracing an event. * @@ -57,7 +55,7 @@ interface ITrace { export const trace: ITrace = ( action: string, message: string, - requestOrLogger: mixed, + requestOrLogger: unknown, ): ITraceSession => { const tracer = traceAgent.get(); if ( @@ -67,12 +65,11 @@ export const trace: ITrace = ( ) { // We have done a little check to make sure this is either null // or a request, so just tell Flow it's OK. - // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'RequestWithLog>> | undefined'. const logger = getLogger(requestOrLogger); return traceImpl(logger, action, message, tracer); } // At this point, we can assume it's a logger. - // $FlowIgnore[incompatible-call] return traceImpl(requestOrLogger, action, message, tracer); }; diff --git a/packages/wonder-stuff-server-google/src/types.js b/packages/wonder-stuff-server-google/src/types.ts similarity index 83% rename from packages/wonder-stuff-server-google/src/types.js rename to packages/wonder-stuff-server-google/src/types.ts index 49bd9a48..632518ab 100644 --- a/packages/wonder-stuff-server-google/src/types.js +++ b/packages/wonder-stuff-server-google/src/types.ts @@ -1,4 +1,3 @@ -// @flow import type { LogLevel, ServerOptions as BaseServerOptions, @@ -12,13 +11,12 @@ export type GoogleCloudIntegrations = { * Enable the debug agent. * Defaults to false. */ - +debugAgent?: boolean, - + readonly debugAgent?: boolean; /** * Enable the profiler. * Defaults to false. */ - +profiler?: boolean, + readonly profiler?: boolean; }; /** @@ -28,22 +26,19 @@ export type AppEngineInfo = { /** * Usually the value of GAE_SERVICE, if set. Otherwise, "unknown". */ - +name: string, - + readonly name: string; /** * Usually the value of GAE_VERSION, if set. Otherwise, "unknown". */ - +version: string, - + readonly version: string; /** * Usually the value of GAE_INSTANCE, if set. Otherwise, "unknown". */ - +instance: string, - + readonly instance: string; /** * The process identifier. */ - +pid: number, + readonly pid: number; }; /** @@ -53,34 +48,28 @@ export type ServerOptions = { /** * Configuration for various Google Cloud agents that can aid debugging. */ - +integrations?: GoogleCloudIntegrations, - + readonly integrations?: GoogleCloudIntegrations; /** * The name of the server. */ - +name: BaseServerOptions["name"], - + readonly name: BaseServerOptions["name"]; /** * The port on which the server should listen. */ - +port: BaseServerOptions["port"], - + readonly port: BaseServerOptions["port"]; /** * The hostname to which the server should bind. */ - +host: BaseServerOptions["host"], - + readonly host: BaseServerOptions["host"]; /** * What runtime mode the server is running under. */ - +mode: BaseServerOptions["mode"], - + readonly mode: BaseServerOptions["mode"]; /** * The log level at which to log things. Anything at or more serious than * this level will be logged. */ - +logLevel: LogLevel, - + readonly logLevel: LogLevel; /** * Optional value in milliseconds for keepalive timeout of the server. * For running in Google Cloud, this should be higher than the load @@ -91,8 +80,7 @@ export type ServerOptions = { * * Defaults to 90000. */ - +keepAliveTimeout?: BaseServerOptions["keepAliveTimeout"], - + readonly keepAliveTimeout?: BaseServerOptions["keepAliveTimeout"]; /** * When `true`, the "heapdump" package will be loaded, allowing for * heap dumps to be generated on demand using `kill -USR2 ` where @@ -101,7 +89,7 @@ export type ServerOptions = { * Defaults to `false` in production mode, and `true` in all other modes. * Set explicitly to `false` to disable heap dumps in all modes. */ - +allowHeapDumps?: BaseServerOptions["allowHeapDumps"], + readonly allowHeapDumps?: BaseServerOptions["allowHeapDumps"]; }; /** @@ -111,13 +99,12 @@ export type TraceSessionInfo = { /** * The level at which to log the session. */ - +level?: LogLevel, - + readonly level?: LogLevel; /** * Additional metadata about the session. Unlike using `addLabel` on the * trace session, this will only go to logging and not the trace as well. */ - +[datum: string]: mixed, + readonly [datum: string]: unknown; }; /** @@ -127,8 +114,7 @@ export interface ITraceSession { /** * The name of the action being traced as provided when it was started. */ - get action(): string; - + action(): string; /** * Add a label to the trace session. * @@ -138,7 +124,6 @@ export interface ITraceSession { * string in tracing if it isn't one already. */ addLabel(name: string, value: T): void; - /** * End the trace session. * diff --git a/packages/wonder-stuff-server/src/__tests__/__snapshots__/get-logging-transport.test.js.snap b/packages/wonder-stuff-server/src/__tests__/__snapshots__/get-logging-transport.test.ts.snap similarity index 100% rename from packages/wonder-stuff-server/src/__tests__/__snapshots__/get-logging-transport.test.js.snap rename to packages/wonder-stuff-server/src/__tests__/__snapshots__/get-logging-transport.test.ts.snap diff --git a/packages/wonder-stuff-server/src/__tests__/create-logger.test.js b/packages/wonder-stuff-server/src/__tests__/create-logger.test.ts similarity index 72% rename from packages/wonder-stuff-server/src/__tests__/create-logger.test.js rename to packages/wonder-stuff-server/src/__tests__/create-logger.test.ts index bcd229b3..94c11dc7 100644 --- a/packages/wonder-stuff-server/src/__tests__/create-logger.test.js +++ b/packages/wonder-stuff-server/src/__tests__/create-logger.test.ts @@ -1,4 +1,3 @@ -// @flow import winston from "winston"; import {Errors} from "@khanacademy/wonder-stuff-core"; import * as GetLoggingTransport from "../get-logging-transport"; @@ -12,6 +11,7 @@ import {Runtime} from "../types"; describe("#createLogger", () => { beforeEach(() => { // We silence winston's console output. + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ debug: jest.Mock; }' is not assignable to parameter of type 'Logger'. jest.spyOn(winston, "createLogger").mockReturnValue({ debug: jest.fn(), }); @@ -28,7 +28,7 @@ describe("#createLogger", () => { // Assert expect(getLoggingTransportMock).toHaveBeenCalledWith( - (Runtime.Test: string), + Runtime.Test as string, "debug", ); }); @@ -54,6 +54,7 @@ describe("#createLogger", () => { it("should log creation parameters to created logger", () => { // Arrange const debugSpy = jest.fn(); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ debug: jest.Mock; }' is not assignable to parameter of type 'Logger'. jest.spyOn(winston, "createLogger").mockReturnValue({ debug: debugSpy, }); @@ -78,6 +79,7 @@ describe("#createLogger", () => { // Act createLogger({mode: Runtime.Test, level: "info"}); + // @ts-expect-error [FEI-5011] - TS2532 - Object is possibly 'undefined'. const result = createLoggerMock.mock.calls[0][0].format; // Assert @@ -88,11 +90,11 @@ describe("#createLogger", () => { it("should set the error kind when logging an error that has no kind", () => { // Arrange const winstonFormatSpy = jest.spyOn(winston, "format"); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'splat' does not exist on type 'SpyInstance'. winstonFormatSpy.splat = jest.fn(); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'printf' does not exist on type 'SpyInstance'. winstonFormatSpy.printf = jest.fn(); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'combine' does not exist on type 'SpyInstance'. winstonFormatSpy.combine = jest.fn(); createLogger({mode: Runtime.Test, level: "info"}); const formatFn = winstonFormatSpy.mock.calls[0][0]; @@ -110,11 +112,11 @@ describe("#createLogger", () => { it("should not set the error kind when logging an error that has a kind already set", () => { // Arrange const winstonFormatSpy = jest.spyOn(winston, "format"); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'splat' does not exist on type 'SpyInstance'. winstonFormatSpy.splat = jest.fn(); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'printf' does not exist on type 'SpyInstance'. winstonFormatSpy.printf = jest.fn(); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'combine' does not exist on type 'SpyInstance'. winstonFormatSpy.combine = jest.fn(); createLogger({mode: Runtime.Test, level: "info"}); const formatFn = winstonFormatSpy.mock.calls[0][0]; @@ -133,11 +135,11 @@ describe("#createLogger", () => { it("should not set the kind when the level of the message is not error", () => { // Arrange const winstonFormatSpy = jest.spyOn(winston, "format"); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'splat' does not exist on type 'SpyInstance'. winstonFormatSpy.splat = jest.fn(); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'printf' does not exist on type 'SpyInstance'. winstonFormatSpy.printf = jest.fn(); - // $FlowIgnore[prop-missing] + // @ts-expect-error [FEI-5011] - TS2339 - Property 'combine' does not exist on type 'SpyInstance'. winstonFormatSpy.combine = jest.fn(); createLogger({mode: Runtime.Test, level: "info"}); const formatFn = winstonFormatSpy.mock.calls[0][0]; diff --git a/packages/wonder-stuff-server/src/__tests__/get-agent-for-url.test.js b/packages/wonder-stuff-server/src/__tests__/get-agent-for-url.test.ts similarity index 99% rename from packages/wonder-stuff-server/src/__tests__/get-agent-for-url.test.js rename to packages/wonder-stuff-server/src/__tests__/get-agent-for-url.test.ts index f302c906..fa59ab10 100644 --- a/packages/wonder-stuff-server/src/__tests__/get-agent-for-url.test.js +++ b/packages/wonder-stuff-server/src/__tests__/get-agent-for-url.test.ts @@ -1,4 +1,3 @@ -// @flow import {URL} from "url"; describe("#getAgentForURL", () => { diff --git a/packages/wonder-stuff-server/src/__tests__/get-logger.test.js b/packages/wonder-stuff-server/src/__tests__/get-logger.test.ts similarity index 67% rename from packages/wonder-stuff-server/src/__tests__/get-logger.test.js rename to packages/wonder-stuff-server/src/__tests__/get-logger.test.ts index f84ff21b..a5f2cfd7 100644 --- a/packages/wonder-stuff-server/src/__tests__/get-logger.test.js +++ b/packages/wonder-stuff-server/src/__tests__/get-logger.test.ts @@ -1,4 +1,3 @@ -// @flow import * as RootLogger from "../root-logger"; import {getLogger} from "../get-logger"; @@ -13,7 +12,7 @@ describe("get-logger.js", () => { describe("#getLogger", () => { it("should return the root logger when there is no request", async () => { // Arrange - const fakeLogger = {}; + const fakeLogger: Record = {}; jest.spyOn(RootLogger, "getRootLogger").mockReturnValue(fakeLogger); // Act @@ -25,11 +24,11 @@ describe("get-logger.js", () => { it("should return the root logger when the request has no log", async () => { // Arrange - const fakeLogger = {}; + const fakeLogger: Record = {}; jest.spyOn(RootLogger, "getRootLogger").mockReturnValue(fakeLogger); // Act - // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{}' is not assignable to parameter of type 'RequestWithLog>>'. const result = getLogger({}); // Assert @@ -38,16 +37,15 @@ describe("get-logger.js", () => { it("should return the request logger when the request has a log", async () => { // Arrange - const fakeLogger = {}; + const fakeLogger: Record = {}; jest.spyOn(RootLogger, "getRootLogger").mockReturnValue(fakeLogger); - const pretendRequestLogger = {}; + const pretendRequestLogger: Record = {}; const pretendRequest = { log: pretendRequestLogger, - }; + } as const; // Act - // $FlowIgnore[prop-missing] - // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '{ readonly log: Record; }' is not assignable to parameter of type 'RequestWithLog>>'. const result = getLogger(pretendRequest); // Assert diff --git a/packages/wonder-stuff-server/src/__tests__/get-logging-transport.test.js b/packages/wonder-stuff-server/src/__tests__/get-logging-transport.test.ts similarity index 74% rename from packages/wonder-stuff-server/src/__tests__/get-logging-transport.test.js rename to packages/wonder-stuff-server/src/__tests__/get-logging-transport.test.ts index 4800350d..b8c8c8fa 100644 --- a/packages/wonder-stuff-server/src/__tests__/get-logging-transport.test.js +++ b/packages/wonder-stuff-server/src/__tests__/get-logging-transport.test.ts @@ -1,4 +1,3 @@ -// @flow import winston from "winston"; // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they // have fixed: @@ -23,9 +22,11 @@ describe("#getLoggingTransport", () => { it("should format log messages to include metadata", () => { // Arrange const fakePrintF = jest.fn(); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. | TS2339 - Property 'mockReturnValue' does not exist on type 'never'. jest.spyOn(winston.format, "combine", "get").mockReturnValue( jest.fn(), ); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. | TS2339 - Property 'mockReturnValue' does not exist on type 'never'. jest.spyOn(winston.format, "printf", "get").mockReturnValue( fakePrintF, ); @@ -52,7 +53,7 @@ describe("#getLoggingTransport", () => { // Arrange // Act - // $FlowIgnore[incompatible-call] + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '"MADE UP RUNTIME MODE"' is not assignable to parameter of type '"production" | "test" | "development"'. const result = getLoggingTransport("MADE UP RUNTIME MODE", "silly"); // Assert @@ -73,12 +74,14 @@ describe("#getLoggingTransport", () => { it.each([undefined, {other: "metadata"}, {}])( "should format log messages to include metadata when present (%s)", - (otherMetadata) => { + (otherMetadata: any) => { // Arrange const fakePrintF = jest.fn(); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. | TS2339 - Property 'mockReturnValue' does not exist on type 'never'. jest.spyOn(winston.format, "combine", "get").mockReturnValue( jest.fn(), ); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. | TS2339 - Property 'mockReturnValue' does not exist on type 'never'. jest.spyOn(winston.format, "printf", "get").mockReturnValue( fakePrintF, ); @@ -110,13 +113,15 @@ describe("#getLoggingTransport", () => { it.each([undefined, {other: "metadata"}, {}])( "should format log messages to include metadata when present (%s)", - (otherMetadata) => { + (otherMetadata: any) => { // Arrange jest.spyOn(winston, "createLogger"); const fakePrintF = jest.fn(); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. | TS2339 - Property 'mockReturnValue' does not exist on type 'never'. jest.spyOn(winston.format, "combine", "get").mockReturnValue( jest.fn(), ); + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'string' is not assignable to parameter of type 'never'. | TS2339 - Property 'mockReturnValue' does not exist on type 'never'. jest.spyOn(winston.format, "printf", "get").mockReturnValue( fakePrintF, ); diff --git a/packages/wonder-stuff-server/src/__tests__/get-request-logger.test.js b/packages/wonder-stuff-server/src/__tests__/get-request-logger.test.ts similarity index 77% rename from packages/wonder-stuff-server/src/__tests__/get-request-logger.test.js rename to packages/wonder-stuff-server/src/__tests__/get-request-logger.test.ts index 72a24d6a..0eb7ec4e 100644 --- a/packages/wonder-stuff-server/src/__tests__/get-request-logger.test.js +++ b/packages/wonder-stuff-server/src/__tests__/get-request-logger.test.ts @@ -1,4 +1,3 @@ -// @flow import {getRequestLogger} from "../get-request-logger"; describe("#getRequestLogger", () => { @@ -18,7 +17,7 @@ describe("#getRequestLogger", () => { // Arrange // Act - const underTest = () => getRequestLogger(null, ({}: $FlowFixMe)); + const underTest = () => getRequestLogger(null, {} as any); // Assert expect(underTest).toThrowErrorMatchingInlineSnapshot( @@ -28,7 +27,7 @@ describe("#getRequestLogger", () => { it("should return the default logger when there is no request", () => { // Arrange - const pretendDefaultLogger = ({}: $FlowFixMe); + const pretendDefaultLogger = {} as any; // Act const result = getRequestLogger(pretendDefaultLogger); @@ -39,10 +38,10 @@ describe("#getRequestLogger", () => { it("should return the default logger when the request has no log", () => { // Arrange - const pretendDefaultLogger = ({}: $FlowFixMe); + const pretendDefaultLogger = {} as any; // Act - const result = getRequestLogger(pretendDefaultLogger, ({}: $FlowFixMe)); + const result = getRequestLogger(pretendDefaultLogger, {} as any); // Assert expect(result).toBe(pretendDefaultLogger); @@ -50,12 +49,12 @@ describe("#getRequestLogger", () => { it.each([{}, null])( "should return the request logger when the request has a log", - (defaultLogger) => { + (defaultLogger: any) => { // Arrange - const pretendRequestLogger = ({}: $FlowFixMe); - const pretendRequest = ({ + const pretendRequestLogger = {} as any; + const pretendRequest = { log: pretendRequestLogger, - }: $FlowFixMe); + } as any; // Act const result = getRequestLogger(defaultLogger, pretendRequest); diff --git a/packages/wonder-stuff-server/src/__tests__/get-runtime-mode.test.js b/packages/wonder-stuff-server/src/__tests__/get-runtime-mode.test.ts similarity index 76% rename from packages/wonder-stuff-server/src/__tests__/get-runtime-mode.test.js rename to packages/wonder-stuff-server/src/__tests__/get-runtime-mode.test.ts index 99878a0c..31d12245 100644 --- a/packages/wonder-stuff-server/src/__tests__/get-runtime-mode.test.js +++ b/packages/wonder-stuff-server/src/__tests__/get-runtime-mode.test.ts @@ -1,4 +1,3 @@ -// @flow // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they // have fixed: // https://github.com/import-js/eslint-plugin-import/issues/2073 @@ -19,7 +18,7 @@ describe("#getRuntimeMode", () => { [Runtime.Development, "dev"], [Runtime.Development, "development"], [Runtime.Test, "test"], - ])("should return %s for given %s", (expectation, nodeEnv) => { + ])("should return %s for given %s", (expectation: any, nodeEnv: any) => { // Arrange process.env.NODE_ENV = nodeEnv; @@ -35,16 +34,19 @@ describe("#getRuntimeMode", () => { [Runtime.Development, undefined], [Runtime.Production, "blah"], [Runtime.Development, "blah"], - ])("should return %s if NODE_ENV unrecognised", (expectation, nodeEnv) => { - // Arrange - process.env.NODE_ENV = nodeEnv; + ])( + "should return %s if NODE_ENV unrecognised", + (expectation: any, nodeEnv: any) => { + // Arrange + process.env.NODE_ENV = nodeEnv; - // Act - const result = getRuntimeMode(expectation); + // Act + const result = getRuntimeMode(expectation); - // Assert - expect(result).toBe(expectation); - }); + // Assert + expect(result).toBe(expectation); + }, + ); it.each([ [Runtime.Development, "development"], @@ -53,7 +55,7 @@ describe("#getRuntimeMode", () => { [Runtime.Production, "test"], ])( "should ignore default of %s and give precedent to NODE_ENV=%s", - (defaultValue, nodeEnv) => { + (defaultValue: any, nodeEnv: any) => { // Arrange process.env.NODE_ENV = nodeEnv; diff --git a/packages/wonder-stuff-server/src/__tests__/root-logger.test.js b/packages/wonder-stuff-server/src/__tests__/root-logger.test.ts similarity index 84% rename from packages/wonder-stuff-server/src/__tests__/root-logger.test.js rename to packages/wonder-stuff-server/src/__tests__/root-logger.test.ts index 34c746b3..7f623ce0 100644 --- a/packages/wonder-stuff-server/src/__tests__/root-logger.test.js +++ b/packages/wonder-stuff-server/src/__tests__/root-logger.test.ts @@ -1,4 +1,3 @@ -// @flow describe("root-logger.js", () => { beforeEach(() => { jest.resetModules(); @@ -8,10 +7,10 @@ describe("root-logger.js", () => { it("should throw if called more than once", () => { // Arrange const {setRootLogger} = require("../root-logger"); - setRootLogger(({}: $FlowFixMe)); + setRootLogger({} as any); // Act - const underTest = () => setRootLogger(({}: $FlowFixMe)); + const underTest = () => setRootLogger({} as any); // Assert expect(underTest).toThrowErrorMatchingInlineSnapshot( @@ -23,7 +22,7 @@ describe("root-logger.js", () => { describe("#getRootLogger", () => { it("should return the value passed to setRootLogger", () => { // Arrange - const fakeLogger: $FlowFixMe = {}; + const fakeLogger: any = {}; const {getRootLogger, setRootLogger} = require("../root-logger"); setRootLogger(fakeLogger); diff --git a/packages/wonder-stuff-server/src/__tests__/start-server.test.js b/packages/wonder-stuff-server/src/__tests__/start-server.test.ts similarity index 87% rename from packages/wonder-stuff-server/src/__tests__/start-server.test.js rename to packages/wonder-stuff-server/src/__tests__/start-server.test.ts index 91d908d8..f52164d1 100644 --- a/packages/wonder-stuff-server/src/__tests__/start-server.test.js +++ b/packages/wonder-stuff-server/src/__tests__/start-server.test.ts @@ -1,4 +1,3 @@ -// @flow import * as Express from "express"; import * as RootLogger from "../root-logger"; import * as DefaultRequestLogging from "../middleware/default-request-logging"; @@ -19,12 +18,13 @@ jest.mock("../middleware/default-request-logging"); describe("#start-server", () => { beforeEach(() => { + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type '() => void' is not assignable to parameter of type '(event: string | symbol, listener: (...args: any[]) => void) => Process'. jest.spyOn(process, "on").mockImplementation(() => {}); }); it("should set the root logger to the given logger", async () => { // Arrange - const logger: $FlowFixMe = { + const logger: any = { debug: jest.fn(), }; const options = { @@ -33,8 +33,8 @@ describe("#start-server", () => { host: "127.0.0.1", logger, mode: Runtime.Test, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn(), use: jest.fn().mockReturnThis(), }; @@ -50,9 +50,9 @@ describe("#start-server", () => { it.each(Array.from(Object.values(Runtime)))( "should import heapdumps if allowHeapDumps is true", - async (mode) => { + async (mode: any) => { // Arrange - const logger: $FlowFixMe = { + const logger: any = { debug: jest.fn(), }; const options = { @@ -62,13 +62,13 @@ describe("#start-server", () => { logger, mode, allowHeapDumps: true, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -88,7 +88,7 @@ describe("#start-server", () => { it("should import heapdumps if not production", async () => { // Arrange - const logger: $FlowFixMe = { + const logger: any = { debug: jest.fn(), }; const options = { @@ -97,13 +97,13 @@ describe("#start-server", () => { host: "127.0.0.1", logger, mode: Runtime.Development, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -122,7 +122,7 @@ describe("#start-server", () => { it("should not import heapdumps if in production", async () => { // Arrange - const logger: $FlowFixMe = { + const logger: any = { debug: jest.fn(), }; const options = { @@ -131,13 +131,13 @@ describe("#start-server", () => { host: "127.0.0.1", logger, mode: Runtime.Production, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -152,7 +152,7 @@ describe("#start-server", () => { it("should not import heapdumps if explicitly told not to", async () => { // Arrange - const logger: $FlowFixMe = { + const logger: any = { debug: jest.fn(), }; const options = { @@ -162,13 +162,13 @@ describe("#start-server", () => { logger, mode: Runtime.Development, allowHeapDumps: false, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -187,16 +187,16 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -219,17 +219,17 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, includeRequestMiddleware: false, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -254,16 +254,16 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -285,17 +285,17 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, includeErrorMiddleware: false, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -319,12 +319,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn(), use: jest.fn().mockReturnThis(), }; @@ -347,20 +347,20 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", port: "PORT", }), on: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -382,30 +382,30 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; - let connectionHandler; + } as const; + let connectionHandler: any; const fakeServer = { address: () => ({ address: "ADDRESS", port: "PORT", }), - on: jest.fn().mockImplementation((event, fn) => { + on: jest.fn().mockImplementation((event: any, fn: any) => { if (event === "connection") { connectionHandler = fn; } }), - }; + } as const; const fakeConnection = { remoteAddress: "CONNECTION_ADDRESS", remotePort: "CONNECTION_PORT", on: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -428,18 +428,18 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, keepAliveTimeout: 42, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -459,17 +459,17 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -489,25 +489,25 @@ describe("#start-server", () => { ${42} | ${5042} `( "should set headersTimeout to $headersTimeout when keepAliveTimeout is $keepAliveTimeout", - async ({keepAliveTimeout, headersTimeout}) => { + async ({keepAliveTimeout, headersTimeout}: any) => { // Arrange const options = { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, keepAliveTimeout, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), keepAliveTimeout: 0, headersTimeout: 0, - }; - const pretendApp: $FlowFixMe = { + } as const; + const pretendApp: any = { listen: jest.fn().mockReturnValue(fakeServer), use: jest.fn().mockReturnThis(), }; @@ -529,14 +529,14 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { debug: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const listenMock = jest.fn().mockReturnValue(null); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -561,13 +561,13 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const listenMock = jest.fn().mockReturnValue(null); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -588,23 +588,23 @@ describe("#start-server", () => { it.each([[null, undefined, "ADDRESS"]])( "should report start failure if address is %s", - async (address) => { + async (address: any) => { // Arrange const options = { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { warn: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => address, on: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -629,20 +629,20 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", port: "PORT", }), on: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -668,13 +668,13 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const listenMock = jest.fn().mockReturnValue(null); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -697,11 +697,11 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", @@ -709,9 +709,9 @@ describe("#start-server", () => { }), on: jest.fn(), close: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -737,12 +737,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", @@ -750,9 +750,9 @@ describe("#start-server", () => { }), on: jest.fn(), close: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -760,6 +760,7 @@ describe("#start-server", () => { const processOnSpy = jest.spyOn(process, "on"); const processExitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. .mockReturnValue(); await startServer(options, pretendApp); const errorSpy = jest.spyOn(options.logger, "error"); @@ -786,12 +787,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", @@ -799,16 +800,17 @@ describe("#start-server", () => { }), on: jest.fn(), close: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp = ({ + const pretendApp = { listen: listenMock, use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockImplementation(() => pretendApp); const processOnSpy = jest.spyOn(process, "on"); const processExitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. .mockReturnValue(); await startServer(options, pretendApp); const errorSpy = jest.spyOn(options.logger, "error"); @@ -835,12 +837,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", @@ -848,9 +850,9 @@ describe("#start-server", () => { }), on: jest.fn(), close: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -858,6 +860,7 @@ describe("#start-server", () => { const processOnSpy = jest.spyOn(process, "on"); const processExitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. .mockReturnValue(); await startServer(options, pretendApp); const errorSpy = jest.spyOn(options.logger, "error"); @@ -879,12 +882,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", @@ -894,9 +897,9 @@ describe("#start-server", () => { close: jest.fn().mockImplementation(() => { throw new Error("CLOSE ERROR"); }), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; @@ -904,6 +907,7 @@ describe("#start-server", () => { const processOnSpy = jest.spyOn(process, "on"); const processExitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. .mockReturnValue(); await startServer(options, pretendApp); const errorSpy = jest.spyOn(options.logger, "error"); @@ -928,12 +932,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: () => ({ address: "ADDRESS", @@ -944,16 +948,17 @@ describe("#start-server", () => { // eslint-disable-next-line no-throw-literal throw null; }), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp = ({ + const pretendApp = { listen: listenMock, use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockImplementation(() => pretendApp); const processOnSpy = jest.spyOn(process, "on"); const processExitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. .mockReturnValue(); await startServer(options, pretendApp); const errorSpy = jest.spyOn(options.logger, "error"); @@ -978,12 +983,12 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), error: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; + } as const; const fakeServer = { address: jest.fn(), on: jest.fn(), @@ -991,16 +996,17 @@ describe("#start-server", () => { // eslint-disable-next-line no-throw-literal throw {}; }), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp = ({ + const pretendApp = { listen: listenMock, use: jest.fn().mockReturnThis(), - }: $FlowFixMe); + } as any; jest.spyOn(Express, "default").mockImplementation(() => pretendApp); const processOnSpy = jest.spyOn(process, "on"); const processExitSpy = jest .spyOn(process, "exit") + // @ts-expect-error [FEI-5011] - TS2554 - Expected 1 arguments, but got 0. .mockReturnValue(); await startServer(options, pretendApp); const errorSpy = jest.spyOn(options.logger, "error"); @@ -1025,41 +1031,41 @@ describe("#start-server", () => { name: "TEST_GATEWAY", port: 42, host: "127.0.0.1", - logger: ({ + logger: { info: jest.fn(), - }: $FlowFixMe), + } as any, mode: Runtime.Test, - }; - let connectionHandler; + } as const; + let connectionHandler: any; const fakeServer = { address: jest.fn(), - on: jest.fn().mockImplementation((event, fn) => { + on: jest.fn().mockImplementation((event: any, fn: any) => { if (event === "connection") { connectionHandler = fn; } }), close: jest.fn(), - }; + } as const; const fakeConnection1 = { remoteAddress: "CONNECTION_ADDRESS1", remotePort: "CONNECTION_PORT1", on: jest.fn(), destroy: jest.fn(), - }; + } as const; const fakeConnection2 = { remoteAddress: "CONNECTION_ADDRESS2", remotePort: "CONNECTION_PORT2", on: jest.fn(), destroy: jest.fn(), - }; + } as const; const fakeConnection3 = { remoteAddress: "CONNECTION_ADDRESS3", remotePort: "CONNECTION_PORT3", on: jest.fn(), destroy: jest.fn(), - }; + } as const; const listenMock = jest.fn().mockReturnValue(fakeServer); - const pretendApp: $FlowFixMe = { + const pretendApp: any = { listen: listenMock, use: jest.fn().mockReturnThis(), }; diff --git a/packages/wonder-stuff-server/src/create-logger.js b/packages/wonder-stuff-server/src/create-logger.ts similarity index 69% rename from packages/wonder-stuff-server/src/create-logger.js rename to packages/wonder-stuff-server/src/create-logger.ts index 8019aa0b..40504d79 100644 --- a/packages/wonder-stuff-server/src/create-logger.js +++ b/packages/wonder-stuff-server/src/create-logger.ts @@ -1,5 +1,5 @@ -// @flow import winston from "winston"; +// @ts-expect-error [FEI-5011] - TS2305 - Module '"winston"' has no exported member 'NpmLogLevels'. import type {NpmLogLevels} from "winston"; import {Errors} from "./errors"; @@ -16,6 +16,7 @@ export const createLogger = ({ defaultMetadata, transport, }: LoggingOptions): Logger => { + // @ts-expect-error [FEI-5011] - TS2558 - Expected 0 type arguments, but got 1. const winstonLogger = winston.createLogger({ level, transports: transport ?? getLoggingTransport(mode, level), @@ -31,7 +32,8 @@ export const createLogger = ({ }); winstonLogger.debug( - `Created logger (Level=${level} Mode=${(mode: string)})`, + // @ts-expect-error [FEI-5011] - TS2731 - Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. + `Created logger (Level=${level} Mode=${mode as string})`, ); return winstonLogger; diff --git a/packages/wonder-stuff-server/src/errors.js b/packages/wonder-stuff-server/src/errors.ts similarity index 99% rename from packages/wonder-stuff-server/src/errors.js rename to packages/wonder-stuff-server/src/errors.ts index a0b09b41..980561e7 100644 --- a/packages/wonder-stuff-server/src/errors.js +++ b/packages/wonder-stuff-server/src/errors.ts @@ -1,4 +1,3 @@ -// @flow import {Errors as CoreErrors} from "@khanacademy/wonder-stuff-core"; /** diff --git a/packages/wonder-stuff-server/src/get-agent-for-url.js b/packages/wonder-stuff-server/src/get-agent-for-url.ts similarity index 97% rename from packages/wonder-stuff-server/src/get-agent-for-url.js rename to packages/wonder-stuff-server/src/get-agent-for-url.ts index 7c026416..892c4ee7 100644 --- a/packages/wonder-stuff-server/src/get-agent-for-url.js +++ b/packages/wonder-stuff-server/src/get-agent-for-url.ts @@ -1,4 +1,3 @@ -// @flow import type {URL} from "url"; import type {Agent as HttpAgent} from "http"; import type {Agent as HttpsAgent} from "https"; @@ -37,7 +36,7 @@ import {Errors} from "./errors"; * retaining large chunks of memory and creating memory leaks. */ export const getAgentForURL = (url: URL): HttpAgent | HttpsAgent => { - const agentOptions = {keepAlive: true}; + const agentOptions = {keepAlive: true} as const; switch (url.protocol) { case "http:": const http = require("http"); diff --git a/packages/wonder-stuff-server/src/get-logger.js b/packages/wonder-stuff-server/src/get-logger.ts similarity index 88% rename from packages/wonder-stuff-server/src/get-logger.js rename to packages/wonder-stuff-server/src/get-logger.ts index 7494cf13..81da846f 100644 --- a/packages/wonder-stuff-server/src/get-logger.js +++ b/packages/wonder-stuff-server/src/get-logger.ts @@ -1,5 +1,4 @@ -// @flow -import type {$Request} from "express"; +import type {Request} from "express"; import {getRequestLogger} from "./get-request-logger"; import {getRootLogger} from "./root-logger"; import type {Logger, RequestWithLog} from "./types"; @@ -17,7 +16,7 @@ import type {Logger, RequestWithLog} from "./types"; * is no request to use for context, it is equivalent to explicitly requesting * the top-level logger. */ -export const getLogger = >( +export const getLogger = >( request?: TReq, ): Logger => { const rootLogger = getRootLogger(); diff --git a/packages/wonder-stuff-server/src/get-logging-transport.js b/packages/wonder-stuff-server/src/get-logging-transport.ts similarity index 89% rename from packages/wonder-stuff-server/src/get-logging-transport.js rename to packages/wonder-stuff-server/src/get-logging-transport.ts index 455d19f0..1bfe3c9b 100644 --- a/packages/wonder-stuff-server/src/get-logging-transport.js +++ b/packages/wonder-stuff-server/src/get-logging-transport.ts @@ -1,6 +1,6 @@ -// @flow import stream from "stream"; import winston from "winston"; +// @ts-expect-error [FEI-5011] - TS2724 - '"winston"' has no exported member named 'Transport'. Did you mean 'transport'? | TS2724 - '"winston"' has no exported member named 'Format'. Did you mean 'format'? import type {Transport, Format} from "winston"; import {Runtime} from "./types"; @@ -24,7 +24,9 @@ const devFormatter = ({level, message, ...metadata}: Info): string => { /** * Build the formatters to give us some nice dev output. */ -const getFormatters = (mode: $Values): Format => { +const getFormatters = ( + mode: (typeof Runtime)[keyof typeof Runtime], +): Format => { const formatters: Array = [ winston.format.splat(), // Allows for %s style substitutions ]; @@ -36,7 +38,6 @@ const getFormatters = (mode: $Values): Format => { * This must be added after the cli formatter if it is to be used in * the dev output. */ - // $FlowIgnore[prop-missing] formatters.push(winston.format.printf((info) => devFormatter(info))); return winston.format.combine(...formatters); }; @@ -45,7 +46,7 @@ const getFormatters = (mode: $Values): Format => { * Gets the logging transport for the given mode. */ export const getLoggingTransport = ( - mode: $Values, + mode: (typeof Runtime)[keyof typeof Runtime], logLevel: LogLevel, ): Transport => { switch (mode) { diff --git a/packages/wonder-stuff-server/src/get-request-logger.js b/packages/wonder-stuff-server/src/get-request-logger.ts similarity index 82% rename from packages/wonder-stuff-server/src/get-request-logger.js rename to packages/wonder-stuff-server/src/get-request-logger.ts index 0e44fb9e..f9dcab8b 100644 --- a/packages/wonder-stuff-server/src/get-request-logger.js +++ b/packages/wonder-stuff-server/src/get-request-logger.ts @@ -1,5 +1,4 @@ -// @flow -import type {$Request} from "express"; +import type {Request} from "express"; import {KindError} from "@khanacademy/wonder-stuff-core"; import {Errors} from "./errors"; import type {Logger, RequestWithLog} from "./types"; @@ -10,8 +9,8 @@ import type {Logger, RequestWithLog} from "./types"; * If there is a request log, it is returned, otherwise the default logger is * returned. If both do not exist, an error is thrown. */ -export const getRequestLogger = >( - defaultLogger: ?Logger, +export const getRequestLogger = >( + defaultLogger?: Logger | null, request?: TReq, ): Logger => { if (defaultLogger == null) { diff --git a/packages/wonder-stuff-server/src/get-runtime-mode.js b/packages/wonder-stuff-server/src/get-runtime-mode.ts similarity index 89% rename from packages/wonder-stuff-server/src/get-runtime-mode.js rename to packages/wonder-stuff-server/src/get-runtime-mode.ts index 768c346e..53c96f0c 100644 --- a/packages/wonder-stuff-server/src/get-runtime-mode.js +++ b/packages/wonder-stuff-server/src/get-runtime-mode.ts @@ -1,4 +1,3 @@ -// @flow // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they // have fixed: // https://github.com/import-js/eslint-plugin-import/issues/2073 @@ -14,8 +13,8 @@ import {Runtime} from "./types"; * @returns {Runtime} The runtime mode of production, development, or test. */ export const getRuntimeMode = ( - defaultMode: $Values, -): $Values => { + defaultMode: (typeof Runtime)[keyof typeof Runtime], +): (typeof Runtime)[keyof typeof Runtime] => { switch (process.env.NODE_ENV) { case "test": return Runtime.Test; diff --git a/packages/wonder-stuff-server/src/index.js b/packages/wonder-stuff-server/src/index.ts similarity index 98% rename from packages/wonder-stuff-server/src/index.js rename to packages/wonder-stuff-server/src/index.ts index 54eda365..41d4e542 100644 --- a/packages/wonder-stuff-server/src/index.js +++ b/packages/wonder-stuff-server/src/index.ts @@ -1,4 +1,3 @@ -// @flow export type {LogLevel, Logger, ServerOptions, RequestWithLog} from "./types"; // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they // have fixed: diff --git a/packages/wonder-stuff-server/src/middleware/__tests__/default-error-logging.test.js b/packages/wonder-stuff-server/src/middleware/__tests__/default-error-logging.test.ts similarity index 81% rename from packages/wonder-stuff-server/src/middleware/__tests__/default-error-logging.test.js rename to packages/wonder-stuff-server/src/middleware/__tests__/default-error-logging.test.ts index c7765f94..7870788b 100644 --- a/packages/wonder-stuff-server/src/middleware/__tests__/default-error-logging.test.js +++ b/packages/wonder-stuff-server/src/middleware/__tests__/default-error-logging.test.ts @@ -1,4 +1,3 @@ -//@flow import * as ExpressWinston from "express-winston"; import {defaultErrorLogging} from "../default-error-logging"; @@ -7,8 +6,8 @@ jest.mock("express-winston"); describe("#defaultErrorLogging", () => { it("should return express-winston error logger", () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendErrorMiddleware = ({}: $FlowFixMe); + const pretendLogger = {} as any; + const pretendErrorMiddleware = {} as any; jest.spyOn(ExpressWinston, "errorLogger").mockReturnValue( pretendErrorMiddleware, ); @@ -22,8 +21,8 @@ describe("#defaultErrorLogging", () => { it("should pass given logger to express winston", () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendErrorMiddleware = ({}: $FlowFixMe); + const pretendLogger = {} as any; + const pretendErrorMiddleware = {} as any; const errorLoggerSpy = jest .spyOn(ExpressWinston, "errorLogger") .mockReturnValue(pretendErrorMiddleware); diff --git a/packages/wonder-stuff-server/src/middleware/__tests__/default-request-logging.test.js b/packages/wonder-stuff-server/src/middleware/__tests__/default-request-logging.test.ts similarity index 81% rename from packages/wonder-stuff-server/src/middleware/__tests__/default-request-logging.test.js rename to packages/wonder-stuff-server/src/middleware/__tests__/default-request-logging.test.ts index 2851d840..c490dcc6 100644 --- a/packages/wonder-stuff-server/src/middleware/__tests__/default-request-logging.test.js +++ b/packages/wonder-stuff-server/src/middleware/__tests__/default-request-logging.test.ts @@ -1,4 +1,3 @@ -// @flow import * as ExpressWinston from "express-winston"; import {defaultRequestLogging} from "../default-request-logging"; @@ -7,8 +6,8 @@ jest.mock("express-winston"); describe("#defaultRequestLogging", () => { it("should return express-winston middleware", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendExpressWinstonMiddleware = ({}: $FlowFixMe); + const pretendLogger = {} as any; + const pretendExpressWinstonMiddleware = {} as any; jest.spyOn(ExpressWinston, "logger").mockReturnValue( pretendExpressWinstonMiddleware, ); @@ -22,8 +21,8 @@ describe("#defaultRequestLogging", () => { it("should create middleware with logger", async () => { // Arrange - const pretendLogger = ({}: $FlowFixMe); - const pretendExpressWinstonMiddleware = ({}: $FlowFixMe); + const pretendLogger = {} as any; + const pretendExpressWinstonMiddleware = {} as any; const middlewareSpy = jest .spyOn(ExpressWinston, "logger") .mockReturnValue(pretendExpressWinstonMiddleware); diff --git a/packages/wonder-stuff-server/src/middleware/default-error-logging.js b/packages/wonder-stuff-server/src/middleware/default-error-logging.js deleted file mode 100644 index 3ac97f32..00000000 --- a/packages/wonder-stuff-server/src/middleware/default-error-logging.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow -import expressWinston from "express-winston"; - -import type {Middleware, $Request, $Response} from "express"; -import type {Logger} from "../types"; - -/** - * Create middleware for reporting errors. - */ -export const defaultErrorLogging = ( - logger: Logger, -): Middleware => - /** - * Express-winston types aren't parameterized, so we suppress the error. - */ - expressWinston.errorLogger({ - level: "error", - winstonInstance: logger, - }); diff --git a/packages/wonder-stuff-server/src/middleware/default-error-logging.ts b/packages/wonder-stuff-server/src/middleware/default-error-logging.ts new file mode 100644 index 00000000..2485590f --- /dev/null +++ b/packages/wonder-stuff-server/src/middleware/default-error-logging.ts @@ -0,0 +1,22 @@ +import expressWinston from "express-winston"; + +// @ts-expect-error [FEI-5011] - TS2305 - Module '"express"' has no exported member 'Middleware'. +import type {Middleware, Request, Response} from "express"; +import type {Logger} from "../types"; + +/** + * Create middleware for reporting errors. + */ +export const defaultErrorLogging = < + TReq extends Request, + TRes extends Response, +>( + logger: Logger, +): Middleware +/** + * Express-winston types aren't parameterized, so we suppress the error. + */ => + expressWinston.errorLogger({ + level: "error", + winstonInstance: logger, + }); diff --git a/packages/wonder-stuff-server/src/middleware/default-request-logging.js b/packages/wonder-stuff-server/src/middleware/default-request-logging.ts similarity index 64% rename from packages/wonder-stuff-server/src/middleware/default-request-logging.js rename to packages/wonder-stuff-server/src/middleware/default-request-logging.ts index e6ccadd6..2043a1c8 100644 --- a/packages/wonder-stuff-server/src/middleware/default-request-logging.js +++ b/packages/wonder-stuff-server/src/middleware/default-request-logging.ts @@ -1,18 +1,21 @@ -// @flow import expressWinston from "express-winston"; -import type {Middleware, $Request, $Response} from "express"; +// @ts-expect-error [FEI-5011] - TS2305 - Module '"express"' has no exported member 'Middleware'. +import type {Middleware, Request, Response} from "express"; import type {Logger} from "../types"; /** * Create middleware for tracking requests. */ -export const defaultRequestLogging = ( +export const defaultRequestLogging = < + TReq extends Request, + TRes extends Response, +>( logger: Logger, -): Middleware => - /** - * We use express-winston to log requests for us. - */ +): Middleware +/** + * We use express-winston to log requests for us. + */ => expressWinston.logger({ /** * Specify the level that this logger logs at. diff --git a/packages/wonder-stuff-server/src/middleware/index.js b/packages/wonder-stuff-server/src/middleware/index.ts similarity index 93% rename from packages/wonder-stuff-server/src/middleware/index.js rename to packages/wonder-stuff-server/src/middleware/index.ts index d6fa3cfc..099581b4 100644 --- a/packages/wonder-stuff-server/src/middleware/index.js +++ b/packages/wonder-stuff-server/src/middleware/index.ts @@ -1,3 +1,2 @@ -// @flow export {defaultErrorLogging} from "./default-error-logging"; export {defaultRequestLogging} from "./default-request-logging"; diff --git a/packages/wonder-stuff-server/src/root-logger.js b/packages/wonder-stuff-server/src/root-logger.ts similarity index 78% rename from packages/wonder-stuff-server/src/root-logger.js rename to packages/wonder-stuff-server/src/root-logger.ts index 85949ca2..2915565c 100644 --- a/packages/wonder-stuff-server/src/root-logger.js +++ b/packages/wonder-stuff-server/src/root-logger.ts @@ -1,14 +1,13 @@ -// @flow import {KindError} from "@khanacademy/wonder-stuff-core"; import {Errors} from "./errors"; import type {Logger} from "./types"; -let rootLogger: ?Logger = null; +let rootLogger: Logger | null | undefined = null; /** * Get the root-level logger. */ -export const getRootLogger: () => ?Logger = () => rootLogger; +export const getRootLogger: () => Logger | null | undefined = () => rootLogger; /** * Set the root-level logger. diff --git a/packages/wonder-stuff-server/src/start-server.js b/packages/wonder-stuff-server/src/start-server.ts similarity index 90% rename from packages/wonder-stuff-server/src/start-server.js rename to packages/wonder-stuff-server/src/start-server.ts index 87c64561..490e8b86 100644 --- a/packages/wonder-stuff-server/src/start-server.js +++ b/packages/wonder-stuff-server/src/start-server.ts @@ -1,5 +1,4 @@ -// @flow -import type {$Application, $Request, $Response} from "express"; +import type {Application, Request, Response} from "express"; import express from "express"; import {setRootLogger} from "./root-logger"; // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they @@ -19,8 +18,8 @@ import * as middleware from "./middleware/index"; * options. */ export async function startServer< - TReq: RequestWithLog<$Request>, - TRes: $Response, + TReq extends RequestWithLog, + TRes extends Response, >( { logger, @@ -33,8 +32,9 @@ export async function startServer< includeErrorMiddleware = true, includeRequestMiddleware = true, }: ServerOptions, - app: $Application, -): Promise { + // @ts-expect-error [FEI-5011] - TS2315 - Type 'Application' is not generic. + app: Application, +): Promise { /** * Setup logging. * We create the root logger once and then share it via a singleton. @@ -57,14 +57,12 @@ export async function startServer< ) { try { /* eslint-disable import/no-unassigned-import */ - // $FlowIgnore[cannot-resolve-module] - // $FlowIgnore[untyped-import] require("heapdump"); /* eslint-enable import/no-unassigned-import */ logger.debug( `Heapdumps enabled. To create a heap snapshot at any time, run "kill -USR2 ${process.pid}".`, ); - } catch (e) { + } catch (e: any) { // heapdump is an optional peer dependency, so if it is absent, // that is perfectly fine. } @@ -73,6 +71,7 @@ export async function startServer< /** * Add middleware per options. */ + // @ts-expect-error [FEI-5011] - TS2558 - Expected 0 type arguments, but got 2. const appWithMiddleware = express(); if (includeRequestMiddleware) { appWithMiddleware.use(middleware.defaultRequestLogging(logger)); @@ -88,10 +87,10 @@ export async function startServer< * We need the variable so we can reference it inside the error handling * callback. Feels a bit nasty, but it works. */ - const server: ?http$Server = appWithMiddleware.listen( + const server: http.Server | null | undefined = appWithMiddleware.listen( port, host, - (err: ?Error) => { + (err?: Error | null) => { if (server == null || err != null) { logger.error( `${name} appears not to have started: ${ @@ -124,17 +123,16 @@ export async function startServer< * trying to close. So, let's track them and provide a means for us to\ * destroy them. */ - const connections: {| - [string]: net$Socket, - |} = {}; + const connections: { + [key: string]: net.Socket; + } = {}; const closeConnections = () => { for (const connection of Object.values(connections)) { // Connection is type mixed, so we need to tell flow this is OK. - // $FlowIgnore[incompatible-use] connection.destroy(); } }; - server?.on("connection", (connection: net$Socket) => { + server?.on("connection", (connection: net.Socket) => { const key = `${connection.remoteAddress ?? ""}:${ connection.remotePort }`; @@ -166,6 +164,7 @@ export async function startServer< logger.info("SIGINT received, shutting down server."); try { + // @ts-expect-error [FEI-5011] - TS7006 - Parameter 'err' implicitly has an 'any' type. server.close((err) => { if (err) { logger.error( @@ -182,7 +181,7 @@ export async function startServer< } }); closeConnections(); - } catch (err) { + } catch (err: any) { logger.error( `Error closing server: ${err?.message || "Unknown Error"}`, { diff --git a/packages/wonder-stuff-server/src/types.js b/packages/wonder-stuff-server/src/types.ts similarity index 68% rename from packages/wonder-stuff-server/src/types.js rename to packages/wonder-stuff-server/src/types.ts index ad117f19..16527e9c 100644 --- a/packages/wonder-stuff-server/src/types.js +++ b/packages/wonder-stuff-server/src/types.ts @@ -1,4 +1,4 @@ -// @flow +// @ts-expect-error [FEI-5011] - TS2305 - Module '"winston"' has no exported member 'NpmLogLevels'. | TS2724 - '"winston"' has no exported member named 'Info'. Did you mean 'info'? | TS2724 - '"winston"' has no exported member named 'Transport'. Did you mean 'transport'? import type { NpmLogLevels, Logger as WinstonLogger, @@ -6,7 +6,7 @@ import type { Transport, } from "winston"; -import type {$Request} from "express"; +import type {Request} from "express"; /** * Describes logging metdata. @@ -16,11 +16,12 @@ export type Info = WinstonInfo; /** * Defines the different log levels. */ -export type LogLevel = $Keys; +export type LogLevel = keyof NpmLogLevels; /** * Describes the interface for logging gateway activity. */ +// @ts-expect-error [FEI-5011] - TS2315 - Type 'Logger' is not generic. export type Logger = WinstonLogger; /** @@ -28,10 +29,10 @@ export type Logger = WinstonLogger; */ // TODO(FEI-5001): Replace with TS enum export const Runtime = { - Production: ("production": "production"), - Development: ("development": "development"), - Test: ("test": "test"), -}; + Production: "production" as const, + Development: "development" as const, + Test: "test" as const, +} as const; /** * Options to configure logging. @@ -40,25 +41,22 @@ export type LoggingOptions = { /** * The runtime mode. */ - mode: $Values, - + mode: (typeof Runtime)[keyof typeof Runtime]; /** * Log only if the level of a logged entry is less than or equal to this * level. Enables filtering out of debug message in production, for example. */ - level: LogLevel, - + level: LogLevel; /** * Metadata to attach to every logged entry, by default. * Defaults to null. */ - defaultMetadata?: {...} | (() => {...}), - + defaultMetadata?: Record | (() => Record); /** * The transport to use for handling log entries. When not specified or * null, this will be determined using `getLoggingTransport`. */ - transport?: ?Transport, + transport?: Transport | null | undefined; }; /** @@ -68,28 +66,23 @@ export type ServerOptions = { /** * The name of the server. */ - +name: string, - + readonly name: string; /** * The port on which the server should listen. */ - +port: number, - + readonly port: number; /** * The hostname to which the server should bind. */ - +host: string, - + readonly host: string; /** * The logger to use for logging. */ - +logger: Logger, - + readonly logger: Logger; /** * What runtime mode the server is running under. */ - +mode: $Values, - + readonly mode: (typeof Runtime)[keyof typeof Runtime]; /** * Optional value in milliseconds for keepalive timeout of the server. * For running in Google Cloud, this should be higher than the load @@ -100,8 +93,7 @@ export type ServerOptions = { * * Defaults to 90000. */ - +keepAliveTimeout?: number, - + readonly keepAliveTimeout?: number; /** * When `true`, the "heapdump" package will be loaded, allowing for * heap dumps to be generated on demand using `kill -USR2 ` where @@ -110,21 +102,19 @@ export type ServerOptions = { * Defaults to `false` in production mode, and `true` in all other modes. * Set explicitly to `false` to disable heap dumps in all modes. */ - +allowHeapDumps?: boolean, - + readonly allowHeapDumps?: boolean; /** * When `true` or omitted, the default express-winston-based error logging * middleware is included. When `false`, this is not included. */ - +includeErrorMiddleware?: boolean, - + readonly includeErrorMiddleware?: boolean; /** * When `true` or omitted, the default express-winston-based request logging * middleware is included. When `false`, this is not included. */ - +includeRequestMiddleware?: boolean, + readonly includeRequestMiddleware?: boolean; }; -export type RequestWithLog = TReq & { - log?: Logger, +export type RequestWithLog = TReq & { + log?: Logger; }; diff --git a/packages/wonder-stuff-testing/src/__tests__/data-factory-for.test.js b/packages/wonder-stuff-testing/src/__tests__/data-factory-for.test.ts similarity index 65% rename from packages/wonder-stuff-testing/src/__tests__/data-factory-for.test.js rename to packages/wonder-stuff-testing/src/__tests__/data-factory-for.test.ts index ae114de5..bae452ad 100644 --- a/packages/wonder-stuff-testing/src/__tests__/data-factory-for.test.js +++ b/packages/wonder-stuff-testing/src/__tests__/data-factory-for.test.ts @@ -1,10 +1,9 @@ -// @flow import {dataFactoryFor} from "../data-factory-for"; describe("dataFactoryFor", () => { describe("returns a function that", () => { it("should return a clone of the default data", () => { - const BASE_OBJECT = {x: 5, y: 10}; + const BASE_OBJECT = {x: 5, y: 10} as const; const dataFactory = dataFactoryFor(BASE_OBJECT); @@ -14,10 +13,11 @@ describe("dataFactoryFor", () => { }); it("should merge object passed to factory with the base object", () => { - const BASE_OBJECT = {x: 5, y: 10}; + const BASE_OBJECT = {x: 5, y: 10} as const; const dataFactory = dataFactoryFor(BASE_OBJECT); + // @ts-expect-error [FEI-5011] - TS2322 - Type '100' is not assignable to type '5 | undefined'. const data = dataFactory({x: 100}); expect(data).toEqual({ x: 100, @@ -29,12 +29,14 @@ describe("dataFactoryFor", () => { const BASE_OBJECT = { p: {x: 5, y: 10}, q: {x: 0, y: 1}, - }; + } as const; const dataFactory = dataFactoryFor(BASE_OBJECT); - const p = {x: 20, y: 30}; + const p = {x: 20, y: 30} as const; + // @ts-expect-error [FEI-5011] - TS2322 - Type '{ readonly x: 20; readonly y: 30; }' is not assignable to type '{ readonly x: 5; readonly y: 10; }'. const data = dataFactory({p}); + // @ts-expect-error [FEI-5011] - TS2540 - Cannot assign to 'x' because it is a read-only property. data.p.x = 100; expect(p).toEqual({x: 20, y: 30}); diff --git a/packages/wonder-stuff-testing/src/data-factory-for.js b/packages/wonder-stuff-testing/src/data-factory-for.ts similarity index 89% rename from packages/wonder-stuff-testing/src/data-factory-for.js rename to packages/wonder-stuff-testing/src/data-factory-for.ts index 13e63485..f9a68758 100644 --- a/packages/wonder-stuff-testing/src/data-factory-for.js +++ b/packages/wonder-stuff-testing/src/data-factory-for.ts @@ -1,4 +1,3 @@ -// @flow import {clone} from "@khanacademy/wonder-stuff-core"; /** @@ -46,13 +45,14 @@ import {clone} from "@khanacademy/wonder-stuff-core"; * } */ export const dataFactoryFor = - (baseObject: T): ((partialObject?: $Partial) => T) => + (baseObject: T): ((partialObject?: Partial) => T) => ( // $FlowIgnore[incompatible-type]: Flow thinks that {} can't be assigned to Partial - partialObject: $Partial = Object.freeze({}), + partialObject: Partial = Object.freeze({}), ): T => { // NOTE: we clone the result to prevent tests from modifying // either `defaultObject` or `partialObject` when performing // deep updates on the return object returned by the factory. + // @ts-expect-error [FEI-5011] - TS2322 - Type 'T & Partial' is not assignable to type 'T'. return clone({...baseObject, ...partialObject}); }; diff --git a/packages/wonder-stuff-testing/src/index.js b/packages/wonder-stuff-testing/src/index.ts similarity index 90% rename from packages/wonder-stuff-testing/src/index.js rename to packages/wonder-stuff-testing/src/index.ts index 9332de4b..89710067 100644 --- a/packages/wonder-stuff-testing/src/index.js +++ b/packages/wonder-stuff-testing/src/index.ts @@ -1,3 +1,2 @@ -// @flow export * as jest from "./jest/index"; export {dataFactoryFor} from "./data-factory-for"; diff --git a/packages/wonder-stuff-testing/src/jest/__tests__/isolate-modules.test.js b/packages/wonder-stuff-testing/src/jest/__tests__/isolate-modules.test.ts similarity index 99% rename from packages/wonder-stuff-testing/src/jest/__tests__/isolate-modules.test.js rename to packages/wonder-stuff-testing/src/jest/__tests__/isolate-modules.test.ts index 0343564d..1584f60a 100644 --- a/packages/wonder-stuff-testing/src/jest/__tests__/isolate-modules.test.js +++ b/packages/wonder-stuff-testing/src/jest/__tests__/isolate-modules.test.ts @@ -1,4 +1,3 @@ -// @flow import {isolateModules} from "../isolate-modules"; import * as AssertJest from "../internal/assert-jest"; diff --git a/packages/wonder-stuff-testing/src/jest/__tests__/wait.test.js b/packages/wonder-stuff-testing/src/jest/__tests__/wait.test.ts similarity index 99% rename from packages/wonder-stuff-testing/src/jest/__tests__/wait.test.js rename to packages/wonder-stuff-testing/src/jest/__tests__/wait.test.ts index 8dceb9b6..6ef755f5 100644 --- a/packages/wonder-stuff-testing/src/jest/__tests__/wait.test.js +++ b/packages/wonder-stuff-testing/src/jest/__tests__/wait.test.ts @@ -1,4 +1,3 @@ -// @flow import {wait, waitForAnimationFrame} from "../wait"; import * as VerifyRealTimers from "../internal/verify-real-timers"; import * as UnverifiedWait from "../internal/unverified-wait"; diff --git a/packages/wonder-stuff-testing/src/jest/index.js b/packages/wonder-stuff-testing/src/jest/index.ts similarity index 89% rename from packages/wonder-stuff-testing/src/jest/index.js rename to packages/wonder-stuff-testing/src/jest/index.ts index b7e9861b..b0f7128a 100644 --- a/packages/wonder-stuff-testing/src/jest/index.js +++ b/packages/wonder-stuff-testing/src/jest/index.ts @@ -1,3 +1,2 @@ -// @flow export {isolateModules} from "./isolate-modules"; export {wait} from "./wait"; diff --git a/packages/wonder-stuff-testing/src/jest/internal/__tests__/assert-jest.test.js b/packages/wonder-stuff-testing/src/jest/internal/__tests__/assert-jest.test.ts similarity index 98% rename from packages/wonder-stuff-testing/src/jest/internal/__tests__/assert-jest.test.js rename to packages/wonder-stuff-testing/src/jest/internal/__tests__/assert-jest.test.ts index 6a0542c5..6997b70e 100644 --- a/packages/wonder-stuff-testing/src/jest/internal/__tests__/assert-jest.test.js +++ b/packages/wonder-stuff-testing/src/jest/internal/__tests__/assert-jest.test.ts @@ -1,4 +1,3 @@ -// @flow import {assertJest} from "../assert-jest"; import * as IsRunningInJest from "../is-running-in-jest"; diff --git a/packages/wonder-stuff-testing/src/jest/internal/__tests__/unverified-wait.test.js b/packages/wonder-stuff-testing/src/jest/internal/__tests__/unverified-wait.test.ts similarity index 72% rename from packages/wonder-stuff-testing/src/jest/internal/__tests__/unverified-wait.test.js rename to packages/wonder-stuff-testing/src/jest/internal/__tests__/unverified-wait.test.ts index 8667f49c..392010e1 100644 --- a/packages/wonder-stuff-testing/src/jest/internal/__tests__/unverified-wait.test.js +++ b/packages/wonder-stuff-testing/src/jest/internal/__tests__/unverified-wait.test.ts @@ -1,4 +1,3 @@ -// @flow import {unverifiedWait} from "../unverified-wait"; describe("#unverifiedWait", () => { @@ -15,7 +14,7 @@ describe("#unverifiedWait", () => { // Arrange const setTimeoutSpy = jest .spyOn(global, "setTimeout") - .mockImplementation((fn) => fn()); + .mockImplementation((fn: any) => fn()); // Act await unverifiedWait(42, 1); @@ -28,7 +27,7 @@ describe("#unverifiedWait", () => { // Arrange const setTimeoutSpy = jest .spyOn(global, "setTimeout") - .mockImplementation((fn) => fn()); + .mockImplementation((fn: any) => fn()); // Act await unverifiedWait(1, 42); @@ -39,11 +38,12 @@ describe("#unverifiedWait", () => { it("should resolve one promise per count", async () => { // Arrange - jest.spyOn(global, "setTimeout").mockImplementation((fn) => fn()); + jest.spyOn(global, "setTimeout").mockImplementation((fn: any) => fn()); const countResolves = jest.fn(); - global.Promise = jest.fn().mockImplementation((fn) => { - return new RealPromise((resolve, reject) => { + // @ts-expect-error [FEI-5011] - TS2740 - Type 'Mock' is missing the following properties from type 'PromiseConstructor': all, race, reject, resolve, and 2 more. + global.Promise = jest.fn().mockImplementation((fn: any) => { + return new RealPromise((resolve: any, reject: any) => { const countedResolve = () => { countResolves(); resolve(); diff --git a/packages/wonder-stuff-testing/src/jest/internal/__tests__/verify-real-timers.test.js b/packages/wonder-stuff-testing/src/jest/internal/__tests__/verify-real-timers.test.ts similarity index 99% rename from packages/wonder-stuff-testing/src/jest/internal/__tests__/verify-real-timers.test.js rename to packages/wonder-stuff-testing/src/jest/internal/__tests__/verify-real-timers.test.ts index 5c105f35..d4e54704 100644 --- a/packages/wonder-stuff-testing/src/jest/internal/__tests__/verify-real-timers.test.js +++ b/packages/wonder-stuff-testing/src/jest/internal/__tests__/verify-real-timers.test.ts @@ -1,5 +1,4 @@ /* eslint-disable no-console */ -// @flow import {Errors} from "@khanacademy/wonder-stuff-core"; import * as AssertJest from "../assert-jest"; import {verifyRealTimers} from "../verify-real-timers"; diff --git a/packages/wonder-stuff-testing/src/jest/internal/assert-jest.js b/packages/wonder-stuff-testing/src/jest/internal/assert-jest.ts similarity index 97% rename from packages/wonder-stuff-testing/src/jest/internal/assert-jest.js rename to packages/wonder-stuff-testing/src/jest/internal/assert-jest.ts index c3d60958..8f5898ff 100644 --- a/packages/wonder-stuff-testing/src/jest/internal/assert-jest.js +++ b/packages/wonder-stuff-testing/src/jest/internal/assert-jest.ts @@ -1,4 +1,3 @@ -// @flow import {KindError, Errors} from "@khanacademy/wonder-stuff-core"; import {isRunningInJest} from "./is-running-in-jest"; diff --git a/packages/wonder-stuff-testing/src/jest/internal/is-running-in-jest.js b/packages/wonder-stuff-testing/src/jest/internal/is-running-in-jest.ts similarity index 97% rename from packages/wonder-stuff-testing/src/jest/internal/is-running-in-jest.js rename to packages/wonder-stuff-testing/src/jest/internal/is-running-in-jest.ts index bec8b008..fcf4bbe4 100644 --- a/packages/wonder-stuff-testing/src/jest/internal/is-running-in-jest.js +++ b/packages/wonder-stuff-testing/src/jest/internal/is-running-in-jest.ts @@ -1,4 +1,3 @@ -// @flow // istanbul ignore file /** * Determine if jest is running or not. diff --git a/packages/wonder-stuff-testing/src/jest/internal/unverified-wait.js b/packages/wonder-stuff-testing/src/jest/internal/unverified-wait.js deleted file mode 100644 index 7853782f..00000000 --- a/packages/wonder-stuff-testing/src/jest/internal/unverified-wait.js +++ /dev/null @@ -1,12 +0,0 @@ -// @flow -export const unverifiedWait = (delay: number, count: number): Promise => - new Promise((resolve, reject) => { - // eslint-disable-next-line no-restricted-syntax - setTimeout(() => { - if (count > 1) { - resolve(unverifiedWait(delay, count - 1)); - } else { - resolve(); - } - }, delay); - }); diff --git a/packages/wonder-stuff-testing/src/jest/internal/unverified-wait.ts b/packages/wonder-stuff-testing/src/jest/internal/unverified-wait.ts new file mode 100644 index 00000000..a27c6b06 --- /dev/null +++ b/packages/wonder-stuff-testing/src/jest/internal/unverified-wait.ts @@ -0,0 +1,18 @@ +export const unverifiedWait = (delay: number, count: number): Promise => + new Promise( + ( + resolve: (result: Promise | undefined) => void, + reject: (error?: any) => void, + ) => { + // eslint-disable-next-line no-restricted-syntax + setTimeout(() => { + if (count > 1) { + // @ts-expect-error [FEI-5011] - TS2345 - Argument of type 'Promise' is not assignable to parameter of type 'Promise'. + resolve(unverifiedWait(delay, count - 1)); + } else { + // @ts-expect-error [FEI-5011] - TS2794 - Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'? + resolve(); + } + }, delay); + }, + ); diff --git a/packages/wonder-stuff-testing/src/jest/internal/verify-real-timers.js b/packages/wonder-stuff-testing/src/jest/internal/verify-real-timers.ts similarity index 94% rename from packages/wonder-stuff-testing/src/jest/internal/verify-real-timers.js rename to packages/wonder-stuff-testing/src/jest/internal/verify-real-timers.ts index 3fdcf4f5..10dd316d 100644 --- a/packages/wonder-stuff-testing/src/jest/internal/verify-real-timers.js +++ b/packages/wonder-stuff-testing/src/jest/internal/verify-real-timers.ts @@ -1,4 +1,3 @@ -// @flow import {KindError, Errors} from "@khanacademy/wonder-stuff-core"; import {assertJest} from "./assert-jest"; @@ -14,7 +13,6 @@ export const verifyRealTimers = () => { // change this behavior we would silently start just working. // eslint-disable-next-line no-console const oldWarn = console.warn; - // $FlowIgnore[cannot-write] console.warn = () => {}; // eslint-disable-line no-console try { @@ -31,7 +29,6 @@ export const verifyRealTimers = () => { ); } } finally { - // $FlowIgnore[cannot-write] console.warn = oldWarn; // eslint-disable-line no-console } }; diff --git a/packages/wonder-stuff-testing/src/jest/isolate-modules.js b/packages/wonder-stuff-testing/src/jest/isolate-modules.ts similarity index 90% rename from packages/wonder-stuff-testing/src/jest/isolate-modules.js rename to packages/wonder-stuff-testing/src/jest/isolate-modules.ts index 08c899b6..bfb2a044 100644 --- a/packages/wonder-stuff-testing/src/jest/isolate-modules.js +++ b/packages/wonder-stuff-testing/src/jest/isolate-modules.ts @@ -1,4 +1,3 @@ -// @flow import {assertJest} from "./internal/assert-jest"; /** @@ -23,6 +22,6 @@ export const isolateModules = (action: () => T): T => { // We know that we'll have a result of the appropriate type at this point. // We could use a promise to make everything happy, but this doesn't need // to be async, so why bother. - // $FlowIgnore[incompatible-return] + // @ts-expect-error [FEI-5011] - TS2454 - Variable 'result' is used before being assigned. return result; }; diff --git a/packages/wonder-stuff-testing/src/jest/wait.js b/packages/wonder-stuff-testing/src/jest/wait.ts similarity index 93% rename from packages/wonder-stuff-testing/src/jest/wait.js rename to packages/wonder-stuff-testing/src/jest/wait.ts index 1fc6e857..3ce85f4a 100644 --- a/packages/wonder-stuff-testing/src/jest/wait.js +++ b/packages/wonder-stuff-testing/src/jest/wait.ts @@ -1,23 +1,21 @@ -// @flow import {verifyRealTimers} from "./internal/verify-real-timers"; import {unverifiedWait} from "./internal/unverified-wait"; import {assertJest} from "./internal/assert-jest"; assertJest(); -type WaitOptions = {| +type WaitOptions = { /** * The time in milliseconds to wait on each wait. * Defaults to 0. Any number less than 0 will be treated as 0. */ - delay?: number, - + delay?: number; /** * The number of times to wait. * Defaults to 1. Any number below 1 will be treated as 1. */ - count?: number, -|}; + count?: number; +}; /** * Wait for the given delay as many times as indicated.