@systemfsoftware/stryker-js-typescript-checker 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/dist/index.mjs +1 -3
- package/package.json +3 -3
- package/src/tsconfig-helpers.ts +3 -3
- package/test/integration/nodenext-project.it.spec.ts +101 -0
- package/test/integration/tsconfig-helpers.it.spec.ts +21 -2
- package/testResources/errors/compile-error/tsconfig.json +0 -1
- package/testResources/nodenext-project/package.json +6 -0
- package/testResources/nodenext-project/src/index.ts +5 -0
- package/testResources/nodenext-project/src/util.ts +3 -0
- package/testResources/nodenext-project/tsconfig.json +16 -0
- package/testResources/project-references/tsconfig.settings.json +0 -2
- package/testResources/project-with-ts-buildinfo/tsconfig.json +0 -2
- package/testResources/single-project/tsconfig.json +0 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -2,11 +2,11 @@ $ tsdown
|
|
|
2
2
|
[34mℹ[39m [34mtsdown v0.22.9[39m powered by [38;2;255;126;23mrolldown v1.2.0[39m
|
|
3
3
|
[34mℹ[39m config file: [4m/home/runner/work/systemfsoftware/systemfsoftware/packages/stryker-js/typescript-checker/tsdown.config.ts[24m
|
|
4
4
|
[34mℹ[39m entry: [34m./src/index.ts[39m
|
|
5
|
-
|
|
6
5
|
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
7
|
-
|
|
6
|
+
|
|
8
7
|
[43m WARN [49m `noExternal` is deprecated. Use `deps.alwaysBundle` instead.
|
|
9
8
|
|
|
9
|
+
[34mℹ[39m Build start
|
|
10
10
|
|
|
11
11
|
[43m WARN [49m TypeScript 7.0 does not yet have a stable API and is experimental. Some options will be unavailable.
|
|
12
12
|
|
|
@@ -15,7 +15,7 @@ $ tsdown
|
|
|
15
15
|
See more at [4mhttps://tsdown.dev/options/dependencies#deps-onlybundle[24m
|
|
16
16
|
Detected dependencies in bundle:
|
|
17
17
|
- [34m@jsr/std__jsonc[39m
|
|
18
|
-
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m31.
|
|
18
|
+
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m31.51 kB[22m [2m│ gzip: 8.65 kB[22m
|
|
19
19
|
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m 4.66 kB[22m [2m│ gzip: 1.52 kB[22m
|
|
20
|
-
[34mℹ[39m 2 files, total: 36.
|
|
21
|
-
[32m✔[39m Build complete in [
|
|
20
|
+
[34mℹ[39m 2 files, total: 36.17 kB
|
|
21
|
+
[32m✔[39m Build complete in [32m635ms[39m
|
package/dist/index.mjs
CHANGED
|
@@ -311,9 +311,7 @@ function overrideOptions(config, useBuildMode) {
|
|
|
311
311
|
const compilerOptions = {
|
|
312
312
|
...config.compilerOptions,
|
|
313
313
|
...COMPILER_OPTIONS_OVERRIDES,
|
|
314
|
-
...useBuildMode ? LOW_EMIT_OPTIONS_FOR_PROJECT_REFERENCES : NO_EMIT_OPTIONS_FOR_SINGLE_PROJECT
|
|
315
|
-
target: "es2022",
|
|
316
|
-
moduleResolution: "bundler"
|
|
314
|
+
...useBuildMode ? LOW_EMIT_OPTIONS_FOR_PROJECT_REFERENCES : NO_EMIT_OPTIONS_FOR_SINGLE_PROJECT
|
|
317
315
|
};
|
|
318
316
|
if (!useBuildMode && compilerOptions["declarationDir"] !== void 0 && compilerOptions["declarationDir"] !== null) delete compilerOptions["declarationDir"];
|
|
319
317
|
if (useBuildMode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/stryker-js-typescript-checker",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"rimraf": "^6.1.3",
|
|
31
31
|
"tsdown": "^0.22.9",
|
|
32
32
|
"vitest": "^4",
|
|
33
|
-
"@systemfsoftware/
|
|
34
|
-
"@systemfsoftware/
|
|
33
|
+
"@systemfsoftware/vitest-config": "^0.1.0",
|
|
34
|
+
"@systemfsoftware/tsconfig": "^1.3.1"
|
|
35
35
|
},
|
|
36
36
|
"inlinedDependencies": {
|
|
37
37
|
"@jsr/std__jsonc": "1.0.2"
|
package/src/tsconfig-helpers.ts
CHANGED
|
@@ -117,13 +117,13 @@ export function determineBuildModeEnabled(tsconfigFileName: string): boolean {
|
|
|
117
117
|
* @param useBuildMode whether or not `--build` mode is used
|
|
118
118
|
*/
|
|
119
119
|
export function overrideOptions(config: TsConfig, useBuildMode: boolean): string {
|
|
120
|
+
// `target` and `moduleResolution` are deliberately absent: both belong to the consumer.
|
|
121
|
+
// Forcing `moduleResolution` contradicts `module: NodeNext`/`Node16` (TS5095 + TS5109),
|
|
122
|
+
// and forcing `target` hides lib features the consumer's own target allows (TS2550).
|
|
120
123
|
const compilerOptions: Record<string, unknown> = {
|
|
121
124
|
...config.compilerOptions,
|
|
122
125
|
...COMPILER_OPTIONS_OVERRIDES,
|
|
123
126
|
...(useBuildMode ? LOW_EMIT_OPTIONS_FOR_PROJECT_REFERENCES : NO_EMIT_OPTIONS_FOR_SINGLE_PROJECT),
|
|
124
|
-
// TypeScript 7 removed some legacy defaults that the upstream fixtures still use.
|
|
125
|
-
target: 'es2022',
|
|
126
|
-
moduleResolution: 'bundler',
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
if (
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
|
|
5
|
+
import { CheckStatus } from '@stryker-mutator/api/check'
|
|
6
|
+
import type { Location, Mutant, StrykerOptions } from '@stryker-mutator/api/core'
|
|
7
|
+
import type { Logger } from '@stryker-mutator/api/logging'
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
9
|
+
|
|
10
|
+
import { HybridFileSystem } from '../../src/fs/hybrid-file-system.js'
|
|
11
|
+
import { TypescriptChecker } from '../../src/typescript-checker.js'
|
|
12
|
+
import { TypescriptCompiler } from '../../src/typescript-compiler.js'
|
|
13
|
+
|
|
14
|
+
const resolveTestResource = path.resolve.bind(
|
|
15
|
+
path,
|
|
16
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
17
|
+
'..',
|
|
18
|
+
'..',
|
|
19
|
+
'testResources',
|
|
20
|
+
'nodenext-project',
|
|
21
|
+
) as unknown as typeof path.resolve
|
|
22
|
+
|
|
23
|
+
function createLogger(): Logger {
|
|
24
|
+
return {
|
|
25
|
+
isTraceEnabled: () => false,
|
|
26
|
+
isDebugEnabled: () => false,
|
|
27
|
+
isInfoEnabled: () => false,
|
|
28
|
+
isWarnEnabled: () => false,
|
|
29
|
+
isErrorEnabled: () => false,
|
|
30
|
+
isFatalEnabled: () => false,
|
|
31
|
+
trace: () => {},
|
|
32
|
+
debug: () => {},
|
|
33
|
+
info: () => {},
|
|
34
|
+
warn: () => {},
|
|
35
|
+
error: () => {},
|
|
36
|
+
fatal: () => {},
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function createChecker(tsconfigFile: string): TypescriptChecker {
|
|
41
|
+
const options = {
|
|
42
|
+
tsconfigFile,
|
|
43
|
+
typescriptChecker: { prioritizePerformanceOverAccuracy: true },
|
|
44
|
+
} as unknown as StrykerOptions
|
|
45
|
+
const logger = createLogger()
|
|
46
|
+
const fileSystem = new HybridFileSystem()
|
|
47
|
+
const compiler = new TypescriptCompiler(logger, options, fileSystem)
|
|
48
|
+
return new TypescriptChecker(logger, options, compiler)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const utilSource = fs.readFileSync(resolveTestResource('src', 'util.ts'), 'utf8')
|
|
52
|
+
|
|
53
|
+
function createMutant(
|
|
54
|
+
findText: string,
|
|
55
|
+
replacement: string,
|
|
56
|
+
id: string,
|
|
57
|
+
): Mutant {
|
|
58
|
+
const lines = utilSource.split('\n')
|
|
59
|
+
const lineNumber = lines.findIndex((line) => line.includes(findText))
|
|
60
|
+
if (lineNumber === -1) {
|
|
61
|
+
throw new Error(`Cannot find ${findText} in util.ts`)
|
|
62
|
+
}
|
|
63
|
+
const column = lines[lineNumber]!.indexOf(findText)
|
|
64
|
+
const location: Location = {
|
|
65
|
+
start: { line: lineNumber, column },
|
|
66
|
+
end: { line: lineNumber, column: column + findText.length },
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
id,
|
|
70
|
+
fileName: resolveTestResource('src', 'util.ts'),
|
|
71
|
+
mutatorName: 'test-mutator',
|
|
72
|
+
location,
|
|
73
|
+
replacement,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
describe('Typescript checker on a NodeNext project targeting es2024', () => {
|
|
78
|
+
let sut: TypescriptChecker
|
|
79
|
+
|
|
80
|
+
beforeEach(() => {
|
|
81
|
+
sut = createChecker(resolveTestResource('tsconfig.json'))
|
|
82
|
+
return sut.init()
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
afterEach(() => {
|
|
86
|
+
// @ts-expect-error private close method
|
|
87
|
+
sut.tsCompiler.close()
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should validate a mutant that keeps the project compiling', async () => {
|
|
91
|
+
const mutant = createMutant('value % 2 === 0', 'value % 2 !== 0', 'passing')
|
|
92
|
+
const actual = await sut.check([mutant])
|
|
93
|
+
expect(actual).toEqual({ passing: { status: CheckStatus.Passed } })
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('should invalidate a mutant that violates the declared return type', async () => {
|
|
97
|
+
const mutant = createMutant("'even'", '42', 'breaking')
|
|
98
|
+
const actual = await sut.check([mutant])
|
|
99
|
+
expect(actual['breaking']!.status).toBe(CheckStatus.CompileError)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -142,11 +142,30 @@ describe('overrideOptions', () => {
|
|
|
142
142
|
expect(parsed.compilerOptions).toMatchObject({
|
|
143
143
|
allowUnreachableCode: true,
|
|
144
144
|
noEmit: true,
|
|
145
|
-
target: 'es2022',
|
|
146
|
-
moduleResolution: 'bundler',
|
|
147
145
|
})
|
|
148
146
|
})
|
|
149
147
|
|
|
148
|
+
it('should not inject a moduleResolution that contradicts the consumer module', () => {
|
|
149
|
+
const config = expectRight(
|
|
150
|
+
parseTsConfig('tsconfig.json', '{"compilerOptions":{"module":"NodeNext"}}'),
|
|
151
|
+
)
|
|
152
|
+
const output = JSON.parse(overrideOptions(config, false))
|
|
153
|
+
expect(output.compilerOptions.module).toBe('NodeNext')
|
|
154
|
+
expect(output.compilerOptions.moduleResolution).toBeUndefined()
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('should preserve the consumer target and moduleResolution verbatim', () => {
|
|
158
|
+
const config = expectRight(
|
|
159
|
+
parseTsConfig(
|
|
160
|
+
'tsconfig.json',
|
|
161
|
+
'{"compilerOptions":{"target":"es2024","moduleResolution":"NodeNext"}}',
|
|
162
|
+
),
|
|
163
|
+
)
|
|
164
|
+
const output = JSON.parse(overrideOptions(config, false))
|
|
165
|
+
expect(output.compilerOptions.target).toBe('es2024')
|
|
166
|
+
expect(output.compilerOptions.moduleResolution).toBe('NodeNext')
|
|
167
|
+
})
|
|
168
|
+
|
|
150
169
|
it('should preserve unknown top-level keys and unknown compilerOptions through to the output', () => {
|
|
151
170
|
const config = expectRight(
|
|
152
171
|
parseTsConfig(
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"strict": true,
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
|
|
7
|
+
// `moduleResolution` is deliberately absent and `target` is deliberately newer
|
|
8
|
+
// than es2022: the checker must not supply either. See nodenext-project.it.spec.ts.
|
|
9
|
+
"target": "es2024",
|
|
10
|
+
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
"outDir": "dist",
|
|
13
|
+
"types": []
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*.ts"]
|
|
16
|
+
}
|