diff --git a/CHANGELOG.md b/CHANGELOG.md index 324d27b4caa8..dbb137d4a0ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- `[jest-cli, jest-config]` Add support for the `jest.config.ts` configuration file ([#10564](https://github.com/facebook/jest/pull/10564)) + ### Fixes ### Chore & Maintenance diff --git a/docs/Configuration.md b/docs/Configuration.md index 9e485fcafc34..6daa5f26ceab 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -3,7 +3,7 @@ id: configuration title: Configuring Jest --- -Jest's configuration can be defined in the `package.json` file of your project, or through a `jest.config.js` file or through the `--config ` option. If you'd like to use your `package.json` to store Jest's config, the `"jest"` key should be used on the top level so Jest will know how to find your settings: +Jest's configuration can be defined in the `package.json` file of your project, or through a `jest.config.js`, or `jest.config.ts` file or through the `--config ` option. If you'd like to use your `package.json` to store Jest's config, the `"jest"` key should be used on the top level so Jest will know how to find your settings: ```json { @@ -18,12 +18,12 @@ Or through JavaScript: ```js // jest.config.js -//Sync object +// Sync object module.exports = { verbose: true, }; -//Or async function +// Or async function module.exports = async () => { return { verbose: true, @@ -31,6 +31,26 @@ module.exports = async () => { }; ``` +Or through TypeScript (if `ts-node` is installed): + +```ts +// jest.config.ts +import type {Config} from '@jest/types'; + +// Sync object +const config: Config.InitialOptions = { + verbose: true, +}; +export default config; + +// Or async function +export default async (): Promise => { + return { + verbose: true, + }; +}; +``` + Please keep in mind that the resulting configuration must be JSON-serializable. When using the `--config` option, the JSON file must not contain a "jest" key: diff --git a/e2e/__tests__/__snapshots__/jest.config.ts.test.ts.snap b/e2e/__tests__/__snapshots__/jest.config.ts.test.ts.snap new file mode 100644 index 000000000000..231d926a36de --- /dev/null +++ b/e2e/__tests__/__snapshots__/jest.config.ts.test.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`traverses directory tree up until it finds jest.config 1`] = ` + console.log +<>/jest.config.ts/some/nested/directory + + at Object.log (__tests__/a-giraffe.js:3:27) + +`; + +exports[`traverses directory tree up until it finds jest.config 2`] = ` +PASS ../../../__tests__/a-giraffe.js + ✓ giraffe + ✓ abc +`; + +exports[`traverses directory tree up until it finds jest.config 3`] = ` +Test Suites: 1 passed, 1 total +Tests: 2 passed, 2 total +Snapshots: 0 total +Time: <> +Ran all test suites. +`; + +exports[`works with jest.config.ts 1`] = ` +PASS __tests__/a-giraffe.js + ✓ giraffe +`; + +exports[`works with jest.config.ts 2`] = ` +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: <> +Ran all test suites. +`; diff --git a/e2e/__tests__/jest.config.ts.test.ts b/e2e/__tests__/jest.config.ts.test.ts new file mode 100644 index 000000000000..9b3edcef87ff --- /dev/null +++ b/e2e/__tests__/jest.config.ts.test.ts @@ -0,0 +1,83 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import * as path from 'path'; +import {wrap} from 'jest-snapshot-serializer-raw'; +import runJest from '../runJest'; +import {cleanup, extractSummary, writeFiles} from '../Utils'; + +const DIR = path.resolve(__dirname, '../jest.config.ts'); + +beforeEach(() => cleanup(DIR)); +afterAll(() => cleanup(DIR)); + +test('works with jest.config.ts', () => { + writeFiles(DIR, { + '__tests__/a-giraffe.js': `test('giraffe', () => expect(1).toBe(1));`, + 'jest.config.ts': `export default {testEnvironment: 'jest-environment-node', testRegex: '.*-giraffe.js'};`, + 'package.json': '{}', + }); + + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false']); + const {rest, summary} = extractSummary(stderr); + expect(exitCode).toBe(0); + expect(wrap(rest)).toMatchSnapshot(); + expect(wrap(summary)).toMatchSnapshot(); +}); + +test('traverses directory tree up until it finds jest.config', () => { + writeFiles(DIR, { + '__tests__/a-giraffe.js': ` + const slash = require('slash'); + test('giraffe', () => expect(1).toBe(1)); + test('abc', () => console.log(slash(process.cwd()))); + `, + 'jest.config.ts': `export default {testEnvironment: 'jest-environment-node', testRegex: '.*-giraffe.js'};`, + 'package.json': '{}', + 'some/nested/directory/file.js': '// nothing special', + }); + + const {stderr, exitCode, stdout} = runJest( + path.join(DIR, 'some', 'nested', 'directory'), + ['-w=1', '--ci=false'], + {skipPkgJsonCheck: true}, + ); + + // Snapshot the console.loged `process.cwd()` and make sure it stays the same + expect( + wrap(stdout.replace(/^\W+(.*)e2e/gm, '<>')), + ).toMatchSnapshot(); + + const {rest, summary} = extractSummary(stderr); + expect(exitCode).toBe(0); + expect(wrap(rest)).toMatchSnapshot(); + expect(wrap(summary)).toMatchSnapshot(); +}); + +test('it does type check the config', () => { + writeFiles(DIR, { + '__tests__/a-giraffe.js': `test('giraffe', () => expect(1).toBe(1));`, + 'jest.config.ts': `export default { testTimeout: "10000" }`, + 'package.json': '{}', + }); + + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false']); + expect(stderr).toMatch('must be of type'); + expect(exitCode).toBe(1); +}); + +test('invalid JS in jest.config.ts', () => { + writeFiles(DIR, { + '__tests__/a-giraffe.js': `test('giraffe', () => expect(1).toBe(1));`, + 'jest.config.ts': `export default i'll break this file yo`, + 'package.json': '{}', + }); + + const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false']); + expect(stderr).toMatch('TSError: ⨯ Unable to compile TypeScript:'); + expect(exitCode).toBe(1); +}); diff --git a/package.json b/package.json index eec05964f672..899223832694 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "strip-ansi": "^6.0.0", "tempy": "^0.6.0", "throat": "^5.0.0", + "ts-node": "^9.0.0", "type-fest": "^0.16.0", "typescript": "^4.0.2", "which": "^2.0.1" diff --git a/packages/jest-cli/src/__tests__/cli/args.test.ts b/packages/jest-cli/src/__tests__/cli/args.test.ts index 55fe1255671d..5d2e5e5570e4 100644 --- a/packages/jest-cli/src/__tests__/cli/args.test.ts +++ b/packages/jest-cli/src/__tests__/cli/args.test.ts @@ -82,13 +82,13 @@ describe('check', () => { it('raises an exception if config is not a valid JSON string', () => { const argv = {config: 'x:1'} as Config.Argv; expect(() => check(argv)).toThrow( - 'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .mjs, .cjs, .json', + 'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .ts, .mjs, .cjs, .json', ); }); it('raises an exception if config is not a supported file type', () => { const message = - 'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .mjs, .cjs, .json'; + 'The --config option requires a JSON string literal, or a file path with one of these extensions: .js, .ts, .mjs, .cjs, .json'; expect(() => check({config: 'jest.configjs'} as Config.Argv)).toThrow( message, diff --git a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap index 70e36b545cad..e90ed19aae3e 100644 --- a/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap +++ b/packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap @@ -45,9 +45,81 @@ Object { } `; +exports[`init has-jest-config-file-ts ask the user whether to override config or not user answered with "Yes" 1`] = ` +Object { + "initial": true, + "message": "It seems that you already have a jest configuration, do you want to override it?", + "name": "continue", + "type": "confirm", +} +`; + +exports[`init project using jest.config.ts ask the user whether he wants to use Typescript or not user answered with "Yes" 1`] = ` +Array [ + Object { + "initial": true, + "message": "Would you like to use Jest when running \\"test\\" script in \\"package.json\\"?", + "name": "scripts", + "type": "confirm", + }, + Object { + "initial": false, + "message": "Would you like to use Typescript for the configuration file?", + "name": "useTypescript", + "type": "confirm", + }, + Object { + "choices": Array [ + Object { + "title": "node", + "value": "node", + }, + Object { + "title": "jsdom (browser-like)", + "value": "jsdom", + }, + ], + "initial": 0, + "message": "Choose the test environment that will be used for testing", + "name": "environment", + "type": "select", + }, + Object { + "initial": false, + "message": "Do you want Jest to add coverage reports?", + "name": "coverage", + "type": "confirm", + }, + Object { + "choices": Array [ + Object { + "title": "v8", + "value": "v8", + }, + Object { + "title": "babel", + "value": "babel", + }, + ], + "initial": 0, + "message": "Which provider should be used to instrument code for coverage?", + "name": "coverageProvider", + "type": "select", + }, + Object { + "initial": false, + "message": "Automatically clear mock calls and instances between every test?", + "name": "clearMocks", + "type": "confirm", + }, +] +`; + exports[`init project with package.json and no jest config all questions answered with answer: "No" should return the default configuration (an empty config) 1`] = ` -"// For a detailed explanation regarding each configuration property, visit: -// https://jestjs.io/docs/en/configuration.html +"/* + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/en/configuration.html + */ module.exports = { // All imported modules in your tests should be mocked automatically diff --git a/packages/jest-cli/src/init/__tests__/fixtures/has_jest_config_file_ts/jest.config.ts b/packages/jest-cli/src/init/__tests__/fixtures/has_jest_config_file_ts/jest.config.ts new file mode 100644 index 000000000000..d291155b7a10 --- /dev/null +++ b/packages/jest-cli/src/init/__tests__/fixtures/has_jest_config_file_ts/jest.config.ts @@ -0,0 +1,8 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +export default {}; diff --git a/packages/jest-cli/src/init/__tests__/fixtures/has_jest_config_file_ts/package.json b/packages/jest-cli/src/init/__tests__/fixtures/has_jest_config_file_ts/package.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/jest-cli/src/init/__tests__/fixtures/has_jest_config_file_ts/package.json @@ -0,0 +1 @@ +{} diff --git a/packages/jest-cli/src/init/__tests__/fixtures/test_generated_jest_config_ts/package.json b/packages/jest-cli/src/init/__tests__/fixtures/test_generated_jest_config_ts/package.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/jest-cli/src/init/__tests__/fixtures/test_generated_jest_config_ts/package.json @@ -0,0 +1 @@ +{} diff --git a/packages/jest-cli/src/init/__tests__/init.test.js b/packages/jest-cli/src/init/__tests__/init.test.js index e8b1b2fe1265..d8d820393c51 100644 --- a/packages/jest-cli/src/init/__tests__/init.test.js +++ b/packages/jest-cli/src/init/__tests__/init.test.js @@ -66,7 +66,7 @@ describe('init', () => { expect(writtenJestConfigFilename.endsWith('.mjs')).toBe(true); expect(typeof writtenJestConfig).toBe('string'); - expect(writtenJestConfig.split('\n')[3]).toBe('export default {'); + expect(writtenJestConfig.split('\n')[5]).toBe('export default {'); }); }); @@ -193,6 +193,34 @@ describe('init', () => { }, ); + describe('project using jest.config.ts', () => { + describe('ask the user whether he wants to use Typescript or not', () => { + it('user answered with "Yes"', async () => { + prompts.mockReturnValueOnce({useTypescript: true}); + + await init(resolveFromFixture('test_generated_jest_config_ts')); + + expect(prompts.mock.calls[0][0]).toMatchSnapshot(); + + const jestConfigFileName = fs.writeFileSync.mock.calls[0][0]; + const writtenJestConfig = fs.writeFileSync.mock.calls[0][1]; + + expect(jestConfigFileName).toContain('/jest.config.ts'); + expect(writtenJestConfig.split('\n')[5]).toBe('export default {'); + }); + + it('user answered with "No"', async () => { + prompts.mockReturnValueOnce({useTypescript: false}); + + await init(resolveFromFixture('test_generated_jest_config_ts')); + + const jestConfigFileName = fs.writeFileSync.mock.calls[0][0]; + + expect(jestConfigFileName).not.toContain('jest.config.ts'); + }); + }); + }); + describe('has jest config in package.json', () => { it('should ask the user whether to override config or not', async () => { prompts.mockReturnValueOnce({continue: true}).mockReturnValueOnce({}); diff --git a/packages/jest-cli/src/init/generate_config_file.ts b/packages/jest-cli/src/init/generate_config_file.ts index 4d7f8a428c3f..a7fdff6e277a 100644 --- a/packages/jest-cli/src/init/generate_config_file.ts +++ b/packages/jest-cli/src/init/generate_config_file.ts @@ -35,7 +35,13 @@ const generateConfigFile = ( results: Record, generateEsm = false, ): string => { - const {coverage, coverageProvider, clearMocks, environment} = results; + const { + useTypescript, + coverage, + coverageProvider, + clearMocks, + environment, + } = results; const overrides: Record = {}; @@ -81,10 +87,20 @@ const generateConfigFile = ( } } + const configHeaderMessage = `/* + * For a detailed explanation regarding each configuration property${ + useTypescript ? ' and type check' : '' + }, visit: + * https://jestjs.io/docs/en/configuration.html + */ + +`; + return ( - '// For a detailed explanation regarding each configuration property, visit:\n' + - '// https://jestjs.io/docs/en/configuration.html\n\n' + - (generateEsm ? 'export default {\n' : 'module.exports = {\n') + + configHeaderMessage + + (useTypescript || generateEsm + ? 'export default {\n' + : 'module.exports = {\n') + properties.join('\n') + '};\n' ); diff --git a/packages/jest-cli/src/init/index.ts b/packages/jest-cli/src/init/index.ts index 82b0fceffa4b..cdc5a5298ade 100644 --- a/packages/jest-cli/src/init/index.ts +++ b/packages/jest-cli/src/init/index.ts @@ -21,11 +21,13 @@ const { JEST_CONFIG_BASE_NAME, JEST_CONFIG_EXT_MJS, JEST_CONFIG_EXT_JS, + JEST_CONFIG_EXT_TS, JEST_CONFIG_EXT_ORDER, PACKAGE_JSON, } = constants; type PromptsResults = { + useTypescript: boolean; clearMocks: boolean; coverage: boolean; coverageProvider: boolean; @@ -64,16 +66,6 @@ export default async ( const existingJestConfigExt = JEST_CONFIG_EXT_ORDER.find(ext => fs.existsSync(path.join(rootDir, getConfigFilename(ext))), ); - const jestConfigPath = existingJestConfigExt - ? getConfigFilename(existingJestConfigExt) - : path.join( - rootDir, - getConfigFilename( - projectPackageJson.type === 'module' - ? JEST_CONFIG_EXT_MJS - : JEST_CONFIG_EXT_JS, - ), - ); if (hasJestProperty || existingJestConfigExt) { const result: {continue: boolean} = await prompts({ @@ -122,6 +114,18 @@ export default async ( return; } + // Determine if Jest should use JS or TS for the config file + const jestConfigFileExt = results.useTypescript + ? JEST_CONFIG_EXT_TS + : projectPackageJson.type === 'module' + ? JEST_CONFIG_EXT_MJS + : JEST_CONFIG_EXT_JS; + + // Determine Jest config path + const jestConfigPath = existingJestConfigExt + ? getConfigFilename(existingJestConfigExt) + : path.join(rootDir, getConfigFilename(jestConfigFileExt)); + const shouldModifyScripts = results.scripts; if (shouldModifyScripts || hasJestProperty) { diff --git a/packages/jest-cli/src/init/questions.ts b/packages/jest-cli/src/init/questions.ts index ae8671848b64..235411dc441a 100644 --- a/packages/jest-cli/src/init/questions.ts +++ b/packages/jest-cli/src/init/questions.ts @@ -8,6 +8,12 @@ import type {PromptObject} from 'prompts'; const defaultQuestions: Array = [ + { + initial: false, + message: 'Would you like to use Typescript for the configuration file?', + name: 'useTypescript', + type: 'confirm', + }, { choices: [ {title: 'node', value: 'node'}, diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 26df83ee27aa..549658f47ce6 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -9,6 +9,14 @@ "license": "MIT", "main": "build/index.js", "types": "build/index.d.ts", + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + }, "dependencies": { "@babel/core": "^7.1.0", "@jest/test-sequencer": "^26.5.3", @@ -33,7 +41,9 @@ "@types/babel__core": "^7.0.4", "@types/glob": "^7.1.1", "@types/graceful-fs": "^4.1.3", - "@types/micromatch": "^4.0.0" + "@types/micromatch": "^4.0.0", + "ts-node": "^9.0.0", + "typescript": "^4.0.3" }, "engines": { "node": ">= 10.14.2" diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index 0fba06b58295..b90166c73877 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -81,7 +81,7 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( writeFiles(DIR, {[relativeJestConfigPath]: ''}); - // jest.config.js takes presedence + // jest.config.js takes precedence // absolute expect( diff --git a/packages/jest-config/src/constants.ts b/packages/jest-config/src/constants.ts index 3ae6c9701ece..9873b4b344c1 100644 --- a/packages/jest-config/src/constants.ts +++ b/packages/jest-config/src/constants.ts @@ -15,9 +15,11 @@ export const JEST_CONFIG_BASE_NAME = 'jest.config'; export const JEST_CONFIG_EXT_CJS = '.cjs'; export const JEST_CONFIG_EXT_MJS = '.mjs'; export const JEST_CONFIG_EXT_JS = '.js'; +export const JEST_CONFIG_EXT_TS = '.ts'; export const JEST_CONFIG_EXT_JSON = '.json'; export const JEST_CONFIG_EXT_ORDER = Object.freeze([ JEST_CONFIG_EXT_JS, + JEST_CONFIG_EXT_TS, JEST_CONFIG_EXT_MJS, JEST_CONFIG_EXT_CJS, JEST_CONFIG_EXT_JSON, diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index c0cc2326a7ec..17f930260df2 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -74,7 +74,7 @@ export async function readConfig( config.rootDir = config.rootDir || packageRootOrConfig; rawOptions = config; // A string passed to `--config`, which is either a direct path to the config - // or a path to directory containing `package.json` or `jest.config.js` + // or a path to directory containing `package.json`, `jest.config.js` or `jest.config.ts` } else if (!skipArgvConfigOption && typeof argv.config == 'string') { configPath = resolveConfigPath(argv.config, process.cwd()); rawOptions = await readConfigFileAndSetRootDir(configPath); diff --git a/packages/jest-config/src/readConfigFileAndSetRootDir.ts b/packages/jest-config/src/readConfigFileAndSetRootDir.ts index 06cbaecc10d6..47f1d6823efc 100644 --- a/packages/jest-config/src/readConfigFileAndSetRootDir.ts +++ b/packages/jest-config/src/readConfigFileAndSetRootDir.ts @@ -9,22 +9,34 @@ import * as path from 'path'; import {pathToFileURL} from 'url'; import * as fs from 'graceful-fs'; import type {Config} from '@jest/types'; +import {interopRequireDefault} from 'jest-util'; +import type {Register} from 'ts-node'; // @ts-expect-error: vendored import jsonlint from './vendor/jsonlint'; -import {JEST_CONFIG_EXT_JSON, PACKAGE_JSON} from './constants'; +import { + JEST_CONFIG_EXT_JSON, + JEST_CONFIG_EXT_TS, + PACKAGE_JSON, +} from './constants'; // Read the configuration and set its `rootDir` // 1. If it's a `package.json` file, we look into its "jest" property -// 2. For any other file, we just require it. If we receive an 'ERR_REQUIRE_ESM' +// 2. If it's a `jest.config.ts` file, we use `ts-node` to transpile & require it +// 3. For any other file, we just require it. If we receive an 'ERR_REQUIRE_ESM' // from node, perform a dynamic import instead. export default async function readConfigFileAndSetRootDir( configPath: Config.Path, ): Promise { + const isTS = configPath.endsWith(JEST_CONFIG_EXT_TS); const isJSON = configPath.endsWith(JEST_CONFIG_EXT_JSON); let configObject; try { - configObject = require(configPath); + if (isTS) { + configObject = await loadTSConfigFile(configPath); + } else { + configObject = require(configPath); + } } catch (error) { if (error.code === 'ERR_REQUIRE_ESM') { try { @@ -54,6 +66,11 @@ export default async function readConfigFileAndSetRootDir( `Jest: Failed to parse config file ${configPath}\n` + ` ${jsonlint.errors(fs.readFileSync(configPath, 'utf8'))}`, ); + } else if (isTS) { + throw new Error( + `Jest: Failed to parse the TypeScript config file ${configPath}\n` + + ` ${error}`, + ); } else { throw error; } @@ -81,3 +98,36 @@ export default async function readConfigFileAndSetRootDir( return configObject; } + +// Load the TypeScript configuration +const loadTSConfigFile = async ( + configPath: Config.Path, +): Promise => { + let registerer: Register; + + // Register TypeScript compiler instance + try { + registerer = require('ts-node').register(); + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + `Jest: 'ts-node' is required for the TypeScript configuration files. Make sure it is installed\nError: ${e.message}`, + ); + } + + throw e; + } + + registerer.enabled(true); + + let configObject = interopRequireDefault(require(configPath)).default; + + // In case the config is a function which imports more Typescript code + if (typeof configObject === 'function') { + configObject = await configObject(); + } + + registerer.enabled(false); + + return configObject; +}; diff --git a/yarn.lock b/yarn.lock index e28ec1643087..e5177dc89236 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4367,6 +4367,13 @@ __metadata: languageName: node linkType: hard +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 81b3b40b1529c4fbf75b12f7c3e6fb2dcce9e78072063babc169de9b4f40777788f3d2b04380f659ef676a756e03ccfbfe78adf4477353bda906295fa69dab89 + languageName: node + linkType: hard + "argparse@npm:^1.0.10, argparse@npm:^1.0.7": version: 1.0.10 resolution: "argparse@npm:1.0.10" @@ -11452,6 +11459,13 @@ fsevents@^1.2.7: jest-validate: ^26.5.3 micromatch: ^4.0.2 pretty-format: ^26.5.2 + ts-node: ^9.0.0 + typescript: ^4.0.3 + peerDependencies: + ts-node: ">=9.0.0" + peerDependenciesMeta: + ts-node: + optional: true languageName: unknown linkType: soft @@ -13035,6 +13049,13 @@ fsevents@^1.2.7: languageName: node linkType: hard +"make-error@npm:^1.1.1": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: 2c780bab8409b865e8ee86697c599a2bf2765ec64d21eb67ccda27050e039f983feacad05a0d43aba3c966ea03d305d2612e94fec45474bcbc61181f57c5bb88 + languageName: node + linkType: hard + "make-fetch-happen@npm:^5.0.0": version: 5.0.2 resolution: "make-fetch-happen@npm:5.0.2" @@ -17097,6 +17118,7 @@ fsevents@^1.2.7: strip-ansi: ^6.0.0 tempy: ^0.6.0 throat: ^5.0.0 + ts-node: ^9.0.0 type-fest: ^0.16.0 typescript: ^4.0.2 which: ^2.0.1 @@ -17732,7 +17754,7 @@ fsevents@^1.2.7: languageName: node linkType: hard -"source-map-support@npm:^0.5.16": +"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.17": version: 0.5.19 resolution: "source-map-support@npm:0.5.19" dependencies: @@ -18907,6 +18929,26 @@ fsevents@^1.2.7: languageName: node linkType: hard +"ts-node@npm:^9.0.0": + version: 9.0.0 + resolution: "ts-node@npm:9.0.0" + dependencies: + arg: ^4.1.0 + diff: ^4.0.1 + make-error: ^1.1.1 + source-map-support: ^0.5.17 + yn: 3.1.1 + peerDependencies: + typescript: ">=2.7" + bin: + ts-node: dist/bin.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: 49d2ab087fc4b93f0a292e426ea6d242a80d1a4809ac008758bb0170aea1a85cd4182792c1d70889285fe5328cd8bd1ffb1e5108d1c4f31c39dbe9151ea4cabe + languageName: node + linkType: hard + "tsconfig-paths@npm:^3.9.0": version: 3.9.0 resolution: "tsconfig-paths@npm:3.9.0" @@ -19060,7 +19102,7 @@ fsevents@^1.2.7: languageName: node linkType: hard -"typescript@*, typescript@^4.0.2": +"typescript@*, typescript@^4.0.2, typescript@^4.0.3": version: 4.0.3 resolution: "typescript@npm:4.0.3" bin: @@ -19070,7 +19112,7 @@ fsevents@^1.2.7: languageName: node linkType: hard -"typescript@patch:typescript@*#builtin, typescript@patch:typescript@^4.0.2#builtin": +"typescript@patch:typescript@*#builtin, typescript@patch:typescript@^4.0.2#builtin, typescript@patch:typescript@^4.0.3#builtin": version: 4.0.3 resolution: "typescript@patch:typescript@npm%3A4.0.3#builtin::version=4.0.3&hash=5bf698" bin: @@ -20169,6 +20211,13 @@ fsevents@^1.2.7: languageName: node linkType: hard +"yn@npm:3.1.1": + version: 3.1.1 + resolution: "yn@npm:3.1.1" + checksum: bff63b80568d80c711670935427494dde47cdf97e8b04196b140ce0af519c81c5ee857eddad0caa8b422dd65aea0157bbfaacbb1546bebba623f0f383d5d9ae5 + languageName: node + linkType: hard + "zone.js@npm:~0.10.2": version: 0.10.3 resolution: "zone.js@npm:0.10.3"