@plugjs/tsgo 0.0.6 → 0.1.0
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/dist/diagnostics.d.ts +2 -4
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +8 -35
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.d.ts +55 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/typescript.d.ts +9 -6
- package/dist/typescript.d.ts.map +1 -1
- package/dist/typescript.js +113 -106
- package/dist/typescript.js.map +1 -1
- package/dist/utils.d.ts +17 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +58 -0
- package/dist/utils.js.map +1 -0
- package/package.json +6 -6
- package/src/diagnostics.ts +21 -60
- package/src/index.ts +65 -7
- package/src/typescript.ts +121 -112
- package/src/utils.ts +64 -0
- package/dist/projects.d.ts +0 -72
- package/dist/projects.d.ts.map +0 -1
- package/dist/projects.js +0 -209
- package/dist/projects.js.map +0 -1
- package/src/projects.ts +0 -271
package/dist/utils.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { assert } from '@plugjs/plug/asserts';
|
|
2
|
+
import { resolveFile } from '@plugjs/plug/paths';
|
|
3
|
+
import { EmitOnly } from 'typescript/unstable/async';
|
|
4
|
+
/**
|
|
5
|
+
* Find the TypeScript project configuration file for a given path.
|
|
6
|
+
*
|
|
7
|
+
* The path specified can be a `tsconfig.json` file name or a directory
|
|
8
|
+
* containing a `tsconfig.json` file.
|
|
9
|
+
*
|
|
10
|
+
* The returned path is the absolute path of the actual `tsconfig.json` file.
|
|
11
|
+
*/
|
|
12
|
+
export function findProjectConfig(path) {
|
|
13
|
+
// The specified path can be either a file or a directory containing a
|
|
14
|
+
// "tsconfig.json" file: resolve as a file, then assume it's a directory
|
|
15
|
+
let file = resolveFile(path);
|
|
16
|
+
if (!file)
|
|
17
|
+
file = resolveFile(path, 'tsconfig.json');
|
|
18
|
+
assert(file, `TypeScript configuration file not found in "${path}"`);
|
|
19
|
+
return file;
|
|
20
|
+
}
|
|
21
|
+
/** Convert a diagnostic level option for deprecations into a consistent value. */
|
|
22
|
+
export function diagnosticDeprecationLevel(deprecations) {
|
|
23
|
+
switch (deprecations) {
|
|
24
|
+
// If *warn* we report deprecations as warnings
|
|
25
|
+
case 'warn':
|
|
26
|
+
return 'warn';
|
|
27
|
+
// If *off* or *false* we don't report deprecations at all
|
|
28
|
+
case 'off':
|
|
29
|
+
case false:
|
|
30
|
+
return 'off';
|
|
31
|
+
// If *notice* or *true* (default) we report deprecations as notices
|
|
32
|
+
/* coverage ignore next */ case 'notice':
|
|
33
|
+
/* coverage ignore next */ case true:
|
|
34
|
+
default:
|
|
35
|
+
return 'notice';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Convert a emit only option into its corresponding enum value. */
|
|
39
|
+
export function emitOnlyOption(emitOnly) {
|
|
40
|
+
switch (emitOnly) {
|
|
41
|
+
// If *none* or *false* we don't emit anything
|
|
42
|
+
case 'none':
|
|
43
|
+
case false:
|
|
44
|
+
return null; // This is "none"
|
|
45
|
+
// If *js* we only emit JavaScript files
|
|
46
|
+
case 'js':
|
|
47
|
+
return EmitOnly.OnlyJs;
|
|
48
|
+
// If *dts* we only emit declaration files
|
|
49
|
+
case 'dts':
|
|
50
|
+
return EmitOnly.OnlyDts;
|
|
51
|
+
// In all other cases we emit all files
|
|
52
|
+
/* coverage ignore next */ case 'all':
|
|
53
|
+
/* coverage ignore next */ case true:
|
|
54
|
+
default:
|
|
55
|
+
return EmitOnly.All;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAKpD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IAClD,sEAAsE;IACtE,wEAAwE;IACxE,IAAI,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;IAC5B,IAAI,CAAC,IAAI;QAAE,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,eAAe,CAAC,CAAA;IACpD,MAAM,CAAC,IAAI,EAAE,+CAA+C,IAAI,GAAG,CAAC,CAAA;IACpE,OAAO,IAAI,CAAA;AACb,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,0BAA0B,CACxC,YAAsD;IAEtD,QAAQ,YAAY,EAAE,CAAC;QACrB,+CAA+C;QAC/C,KAAK,MAAM;YACT,OAAO,MAAM,CAAA;QACf,0DAA0D;QAC1D,KAAK,KAAK,CAAC;QACX,KAAK,KAAK;YACR,OAAO,KAAK,CAAA;QACd,oEAAoE;QACpE,0BAA0B,CAAC,KAAK,QAAQ,CAAC;QACzC,0BAA0B,CAAC,KAAK,IAAI,CAAC;QACrC;YACE,OAAO,QAAQ,CAAA;IACnB,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,QAAwC;IACrE,QAAQ,QAAQ,EAAE,CAAC;QACjB,8CAA8C;QAC9C,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK;YACR,OAAO,IAAI,CAAA,CAAC,iBAAiB;QAC/B,wCAAwC;QACxC,KAAK,IAAI;YACP,OAAO,QAAQ,CAAC,MAAM,CAAA;QACxB,0CAA0C;QAC1C,KAAK,KAAK;YACR,OAAO,QAAQ,CAAC,OAAO,CAAA;QACzB,uCAAuC;QACvC,0BAA0B,CAAC,KAAK,KAAK,CAAC;QACtC,0BAA0B,CAAC,KAAK,IAAI,CAAC;QACrC;YACE,OAAO,QAAQ,CAAC,GAAG,CAAA;IACvB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plugjs/tsgo",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "TypeScript 7.1 support for PlugJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"build",
|
|
@@ -55,12 +55,12 @@
|
|
|
55
55
|
"typescript": "^7.1.0-dev"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@plugjs/cov8": "^0.7.
|
|
59
|
-
"@plugjs/expect5": "^0.7.
|
|
60
|
-
"@plugjs/oxc": "^0.1.
|
|
61
|
-
"@plugjs/plug": "^0.7.
|
|
58
|
+
"@plugjs/cov8": "^0.7.11",
|
|
59
|
+
"@plugjs/expect5": "^0.7.11",
|
|
60
|
+
"@plugjs/oxc": "^0.1.13",
|
|
61
|
+
"@plugjs/plug": "^0.7.11"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@plugjs/plug": "^0.7.
|
|
64
|
+
"@plugjs/plug": "^0.7.11"
|
|
65
65
|
}
|
|
66
66
|
}
|
package/src/diagnostics.ts
CHANGED
|
@@ -3,11 +3,9 @@ import { assertAbsolutePath } from '@plugjs/plug/paths'
|
|
|
3
3
|
import { DiagnosticCategory } from 'typescript/unstable/async'
|
|
4
4
|
|
|
5
5
|
import type { ReportRecord } from '@plugjs/plug/logging'
|
|
6
|
-
import type {
|
|
7
|
-
import type { SourceFile } from 'typescript/unstable/ast'
|
|
8
|
-
import type { Diagnostic, Program } from 'typescript/unstable/async'
|
|
6
|
+
import type { Diagnostic } from 'typescript/unstable/async'
|
|
9
7
|
|
|
10
|
-
function convertDiagnostic(diagnostic: Diagnostic
|
|
8
|
+
function convertDiagnostic(diagnostic: Diagnostic): ReportRecord {
|
|
11
9
|
const record: ReportRecord & { tags: string[] } = {
|
|
12
10
|
level: NOTICE,
|
|
13
11
|
message: diagnostic.text,
|
|
@@ -31,22 +29,21 @@ function convertDiagnostic(diagnostic: Diagnostic, sourceFile?: SourceFile): Rep
|
|
|
31
29
|
record.file = diagnostic.fileName
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
if (
|
|
35
|
-
const pos =
|
|
32
|
+
if (diagnostic.startPosition) {
|
|
33
|
+
const pos = diagnostic.startPosition
|
|
36
34
|
record.line = pos.line + 1
|
|
37
35
|
record.column = pos.character + 1
|
|
38
36
|
record.length = diagnostic.end - diagnostic.pos
|
|
39
|
-
record.source =
|
|
37
|
+
record.source = diagnostic.source
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
return record
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
export
|
|
43
|
+
export function convertDiagnostics(
|
|
46
44
|
diagnostics: readonly Diagnostic[],
|
|
47
|
-
program: Program,
|
|
48
45
|
deprecations: 'warn' | 'notice' | 'off' = 'notice',
|
|
49
|
-
):
|
|
46
|
+
): ReportRecord[] {
|
|
50
47
|
// Filter out any duplicate diagnostic *before* we convert them to report
|
|
51
48
|
// records (that might be expensive because of source file lookups)
|
|
52
49
|
const seen = new Set<string>()
|
|
@@ -65,59 +62,23 @@ export async function convertDiagnostics(
|
|
|
65
62
|
})
|
|
66
63
|
|
|
67
64
|
// Convert all diagnostics to report records
|
|
68
|
-
const converted =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
diagnostic = { ...diagnostic, category: DiagnosticCategory.Warning }
|
|
79
|
-
}
|
|
65
|
+
const converted = unique.map((diagnostic) => {
|
|
66
|
+
// Anything not an error is not critical
|
|
67
|
+
const isNonCritical = diagnostic.category !== DiagnosticCategory.Error
|
|
68
|
+
|
|
69
|
+
// First of all see how we need to handle non-error deprecations: when
|
|
70
|
+
// "off" we suppress them, when "warn" we convert them to warnings...
|
|
71
|
+
if (diagnostic.reportsDeprecated && isNonCritical) {
|
|
72
|
+
if (deprecations === 'off') return // simply filter this out...
|
|
73
|
+
if (deprecations === 'warn') {
|
|
74
|
+
diagnostic = { ...diagnostic, category: DiagnosticCategory.Warning }
|
|
80
75
|
}
|
|
76
|
+
}
|
|
81
77
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
: /* coverage ignore next */ undefined
|
|
86
|
-
|
|
87
|
-
// If the source file is in the default library (e.g. "lib.dom.ts") or
|
|
88
|
-
// from an external library (in "node_modules") then we ONLY keep errors
|
|
89
|
-
// and (we ignore things like warnings, suggestions, ...)
|
|
90
|
-
const isExternal = sourceFileMetadata?.isDefaultLibrary || sourceFileMetadata?.isFromExternalLibrary
|
|
91
|
-
if (isExternal && isNonCritical) return
|
|
92
|
-
|
|
93
|
-
// Get the source file and its metadata (if any) for the diagnostic...
|
|
94
|
-
// We do this *after* the external check above as getting the source file
|
|
95
|
-
// is quite expensive (especially for things like "lib.es5.dts")...
|
|
96
|
-
const sourceFile = diagnostic.fileName
|
|
97
|
-
? ((await program.getSourceFile(diagnostic.fileName)) ??
|
|
98
|
-
(await program.getConfigSourceFile(diagnostic.fileName)))
|
|
99
|
-
: /* coverage ignore next */ undefined
|
|
100
|
-
|
|
101
|
-
// Convert our diagnostic to a report record and return it
|
|
102
|
-
return convertDiagnostic(diagnostic, sourceFile)
|
|
103
|
-
}),
|
|
104
|
-
)
|
|
78
|
+
// Convert our diagnostic to a report record and return it
|
|
79
|
+
return convertDiagnostic(diagnostic)
|
|
80
|
+
})
|
|
105
81
|
|
|
106
82
|
// Filter out any null/undefined records
|
|
107
83
|
return converted.filter((record): record is ReportRecord => !!record)
|
|
108
84
|
}
|
|
109
|
-
|
|
110
|
-
export async function convertProjectDiagnostics(
|
|
111
|
-
diagnostics: readonly Diagnostic[],
|
|
112
|
-
program: Program,
|
|
113
|
-
fileName: AbsolutePath,
|
|
114
|
-
): Promise<ReportRecord[]> {
|
|
115
|
-
// Make sure that we have a file name for the diagnostics
|
|
116
|
-
const fileDiagnostics = diagnostics.map((diagnostic) => {
|
|
117
|
-
if (diagnostic.fileName) return diagnostic
|
|
118
|
-
return { ...diagnostic, fileName }
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
// Convert the diagnostics to report records and return them
|
|
122
|
-
return convertDiagnostics(fileDiagnostics, program)
|
|
123
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
import { install } from '@plugjs/plug/pipe'
|
|
2
2
|
|
|
3
|
-
import { TypeScript } from './typescript.ts'
|
|
3
|
+
import { TypeScript, TypeScriptBuild } from './typescript.ts'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import type { OverrideCompilerOptions } from 'typescript/unstable/async'
|
|
6
|
+
|
|
7
|
+
/** Options for the `typescriptBuild` plug. */
|
|
8
|
+
export interface TypeScriptBuildOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Force building all projects in the build. Defaults to `true`.
|
|
11
|
+
*
|
|
12
|
+
* This is equivalent to running `tsc --build --force`.
|
|
13
|
+
*/
|
|
14
|
+
force?: boolean
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Skip building downstream projects on error in upstream project. Defaults
|
|
18
|
+
* to `false`.
|
|
19
|
+
*
|
|
20
|
+
* This is equivalent to running `tsc --build --stopBuildOnErrors`.
|
|
21
|
+
*/
|
|
22
|
+
stopBuildOnErrors?: boolean
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Enable verbose logging during the build. Defaults to `true`.
|
|
26
|
+
*
|
|
27
|
+
* This is equivalent to running `tsc --build --verbose`.
|
|
28
|
+
*/
|
|
29
|
+
verbose?: boolean
|
|
30
|
+
|
|
31
|
+
/** Override the default TypeScript compiler options for the build. */
|
|
32
|
+
overrideCompilerOptions?: OverrideCompilerOptions
|
|
33
|
+
}
|
|
9
34
|
|
|
35
|
+
/** Options for the `typescript` plug. */
|
|
36
|
+
export interface TypeScriptOptions {
|
|
10
37
|
/**
|
|
11
38
|
* Controls how deprecation diagnostics are reported. Use `'notice'` or
|
|
12
39
|
* `true` for notices, `'warn'` for warnings, and `'off'` or `false` to
|
|
@@ -23,8 +50,14 @@ export interface TypeScriptOptions {
|
|
|
23
50
|
emitOnly?: 'js' | 'dts' | 'all' | 'none' | boolean
|
|
24
51
|
}
|
|
25
52
|
|
|
26
|
-
/** Options for the {@link tsc}
|
|
27
|
-
export interface TscOptions extends
|
|
53
|
+
/** Options for the {@link tsc} helper. */
|
|
54
|
+
export interface TscOptions extends TypeScriptOptions {
|
|
55
|
+
/** Base directory used to resolve the configuration path. */
|
|
56
|
+
directory?: string
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Options for the {@link tscBuild} helper. */
|
|
60
|
+
export interface TscBuildOptions extends TypeScriptBuildOptions {
|
|
28
61
|
/** Base directory used to resolve the configuration path. */
|
|
29
62
|
directory?: string
|
|
30
63
|
}
|
|
@@ -35,6 +68,8 @@ declare module '@plugjs/plug' {
|
|
|
35
68
|
* Run the {@link https://www.typescriptlang.org/ TypeScript Compiler}
|
|
36
69
|
* version 7 (native) over the `tsconfig.json` configuration files
|
|
37
70
|
* given as input to this {@link Pipe} instance.
|
|
71
|
+
*
|
|
72
|
+
* This is equivalent to running `tsc --project`.
|
|
38
73
|
*/
|
|
39
74
|
typescript(): Pipe
|
|
40
75
|
|
|
@@ -43,12 +78,35 @@ declare module '@plugjs/plug' {
|
|
|
43
78
|
* version 7 (native) over the `tsconfig.json` configuration files
|
|
44
79
|
* given as input to this {@link Pipe} instance.
|
|
45
80
|
*
|
|
81
|
+
* This is equivalent to running `tsc --project`.
|
|
82
|
+
*
|
|
46
83
|
* @param options {@link TypeScriptOptions} to use for the build.
|
|
47
84
|
*/
|
|
48
85
|
typescript(options: TypeScriptOptions): Pipe
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Run the {@link https://www.typescriptlang.org/ TypeScript Builder}
|
|
89
|
+
* version 7 (native) over the `tsconfig.json` configuration files
|
|
90
|
+
* given as input to this {@link Pipe} instance.
|
|
91
|
+
*
|
|
92
|
+
* This is equivalent to running `tsc --build`.
|
|
93
|
+
*/
|
|
94
|
+
typescriptBuild(): Promise<undefined>
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Run the {@link https://www.typescriptlang.org/ TypeScript Builder}
|
|
98
|
+
* version 7 (native) over the `tsconfig.json` configuration files
|
|
99
|
+
* given as input to this {@link Pipe} instance.
|
|
100
|
+
*
|
|
101
|
+
* This is equivalent to running `tsc --build`.
|
|
102
|
+
*
|
|
103
|
+
* @param options {@link TypeScriptBuildOptions} to use for the build.
|
|
104
|
+
*/
|
|
105
|
+
typescriptBuild(options: TypeScriptBuildOptions): Promise<undefined>
|
|
49
106
|
}
|
|
50
107
|
}
|
|
51
108
|
|
|
52
109
|
install('typescript', TypeScript)
|
|
110
|
+
install('typescriptBuild', TypeScriptBuild)
|
|
53
111
|
|
|
54
112
|
export { tsbuild, tsc } from './typescript.ts'
|
package/src/typescript.ts
CHANGED
|
@@ -1,166 +1,133 @@
|
|
|
1
1
|
import { using } from '@plugjs/plug'
|
|
2
|
-
import { assert } from '@plugjs/plug/asserts'
|
|
3
2
|
import { Files } from '@plugjs/plug/files'
|
|
4
3
|
import { ERROR } from '@plugjs/plug/logging'
|
|
5
|
-
import {
|
|
6
|
-
import { API,
|
|
4
|
+
import { assertAbsolutePath, commonPath, isAbsolutePath } from '@plugjs/plug/paths'
|
|
5
|
+
import { API, DiagnosticCategory } from 'typescript/unstable/async'
|
|
7
6
|
|
|
8
7
|
import { convertDiagnostics } from './diagnostics.ts'
|
|
9
|
-
import {
|
|
8
|
+
import { diagnosticDeprecationLevel, emitOnlyOption, findProjectConfig } from './utils.ts'
|
|
10
9
|
|
|
11
|
-
import type { TscOptions, TypeScriptOptions } from './index.ts'
|
|
10
|
+
import type { TscBuildOptions, TscOptions, TypeScriptBuildOptions, TypeScriptOptions } from './index.ts'
|
|
12
11
|
import type { Pipe } from '@plugjs/plug'
|
|
13
12
|
import type { AbsolutePath } from '@plugjs/plug/paths'
|
|
14
13
|
import type { Context, Plug } from '@plugjs/plug/pipe'
|
|
15
|
-
import type {
|
|
14
|
+
import type { BuildOrchestrator } from 'typescript/unstable/async'
|
|
15
|
+
import type { Diagnostic, RootedFilePath } from 'typescript/unstable/proto'
|
|
16
16
|
|
|
17
17
|
/* ========================================================================== *
|
|
18
18
|
* TYPESCRIPT 7 PLUG IMPLEMENTATION *
|
|
19
19
|
* ========================================================================== */
|
|
20
20
|
|
|
21
21
|
export class TypeScript implements Plug<Files> {
|
|
22
|
-
private
|
|
23
|
-
private _reportDeprecations: 'warn' | 'notice' | 'off'
|
|
24
|
-
private _projectReferences: boolean
|
|
25
|
-
|
|
26
|
-
constructor(options: TypeScriptOptions = {}) {
|
|
27
|
-
const { projectReferences, reportDeprecations, emitOnly } = options
|
|
28
|
-
this._projectReferences = !!projectReferences
|
|
29
|
-
|
|
30
|
-
switch (emitOnly) {
|
|
31
|
-
// If *none* or *false* we don't emit any files at all
|
|
32
|
-
case 'none':
|
|
33
|
-
case false:
|
|
34
|
-
this._emitOnly = null
|
|
35
|
-
break
|
|
36
|
-
// If *js* we only emit JavaScript files
|
|
37
|
-
case 'js':
|
|
38
|
-
this._emitOnly = EmitOnly.OnlyJs
|
|
39
|
-
break
|
|
40
|
-
// If *dts* we only emit declaration files
|
|
41
|
-
case 'dts':
|
|
42
|
-
this._emitOnly = EmitOnly.OnlyDts
|
|
43
|
-
break
|
|
44
|
-
// If *all* or *true* (default) we emit all files
|
|
45
|
-
case 'all':
|
|
46
|
-
case true:
|
|
47
|
-
default:
|
|
48
|
-
this._emitOnly = EmitOnly.All
|
|
49
|
-
break
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
switch (reportDeprecations) {
|
|
53
|
-
// If *warn* we report deprecations as warnings
|
|
54
|
-
case 'warn':
|
|
55
|
-
this._reportDeprecations = 'warn'
|
|
56
|
-
break
|
|
57
|
-
// If *off* or *false* we don't report deprecations at all
|
|
58
|
-
case 'off':
|
|
59
|
-
case false:
|
|
60
|
-
this._reportDeprecations = 'off'
|
|
61
|
-
break
|
|
62
|
-
// If *notice* or *true* (default) we report deprecations as notices
|
|
63
|
-
case 'notice':
|
|
64
|
-
case true:
|
|
65
|
-
default:
|
|
66
|
-
this._reportDeprecations = 'notice'
|
|
67
|
-
break
|
|
68
|
-
}
|
|
69
|
-
}
|
|
22
|
+
constructor(private readonly _options: TypeScriptOptions = {}) {}
|
|
70
23
|
|
|
71
24
|
async pipe(files: Files, context: Context): Promise<Files> {
|
|
25
|
+
// Convert our options
|
|
26
|
+
const deprecationsLevel = diagnosticDeprecationLevel(this._options.reportDeprecations)
|
|
27
|
+
const emitOnly = emitOnlyOption(this._options.emitOnly)
|
|
28
|
+
|
|
72
29
|
// Create our TypeScript API and report for this plug
|
|
73
|
-
const api = new API({ cwd: files.directory })
|
|
74
30
|
const report = context.log.report('TypeScript Report')
|
|
75
31
|
|
|
76
32
|
// This is the list of emitted files to return to the pipe...
|
|
77
33
|
const emittedFiles: AbsolutePath[] = []
|
|
78
34
|
|
|
35
|
+
let api: API | undefined = undefined
|
|
79
36
|
try {
|
|
80
|
-
|
|
81
|
-
// to build them.
|
|
82
|
-
let projects: AbsolutePath[]
|
|
83
|
-
let snapshot: Snapshot
|
|
84
|
-
|
|
85
|
-
// First of all figure out whether we have to build project references
|
|
86
|
-
// too or not... This will determine whether we have to resolve them....
|
|
87
|
-
if (this._projectReferences) {
|
|
88
|
-
// Find all project references for the given configuration files
|
|
89
|
-
const projectReferences = await findProjectReferences(api, ...files.absolutePaths())
|
|
90
|
-
report.add(...projectReferences.errors)
|
|
91
|
-
if (report.errors) report.done()
|
|
92
|
-
|
|
93
|
-
// Then determine the build order for all projects and their references
|
|
94
|
-
const projectOrder = resolveProjectOrder(projectReferences.projects)
|
|
95
|
-
report.add(...projectOrder.errors)
|
|
96
|
-
if (report.errors) report.done()
|
|
97
|
-
|
|
98
|
-
// At this point, our list of projects to build is the "order"
|
|
99
|
-
snapshot = await api.updateSnapshot({ openProjects: projectOrder.order })
|
|
100
|
-
projects = [...projectOrder.order]
|
|
101
|
-
} else {
|
|
102
|
-
// If we're not building references, then we just build our files
|
|
103
|
-
const configs = [...files.absolutePaths()].map(findProjectConfig)
|
|
104
|
-
snapshot = await api.updateSnapshot({ openProjects: configs })
|
|
105
|
-
projects = [...configs]
|
|
106
|
-
|
|
107
|
-
// When resolving the project references above, we already processed
|
|
108
|
-
// any configuration files and added any errors to the report...
|
|
109
|
-
// In this case, we have to do it ourselves by reading each config!
|
|
110
|
-
for (const config of configs) {
|
|
111
|
-
const { errors } = await readProjectConfig(api, config)
|
|
112
|
-
report.add(...errors)
|
|
113
|
-
}
|
|
37
|
+
api = new API({ cwd: files.directory })
|
|
114
38
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
39
|
+
// If we're not building references, then we just build our files
|
|
40
|
+
const configs = [...files.absolutePaths()].map(findProjectConfig)
|
|
41
|
+
const snapshot = await api.createSnapshot({ openProjects: configs })
|
|
42
|
+
const projects = snapshot.getProjects()
|
|
118
43
|
|
|
119
44
|
// Now build all projects in the order we determined earlier
|
|
120
45
|
for (const project of projects) {
|
|
121
46
|
// Get the actual TypeScript program for this project...
|
|
122
|
-
const program =
|
|
123
|
-
assert(program, `Project "${project}" not found in snapshot`)
|
|
47
|
+
const program = project.program
|
|
124
48
|
|
|
125
49
|
// Collect compilation diagnostics for this project (has files)
|
|
126
|
-
const
|
|
50
|
+
const fullDiagnostics = await Promise.all([
|
|
127
51
|
program.getBindDiagnostics(),
|
|
52
|
+
program.getConfigFileParsingDiagnostics(),
|
|
53
|
+
program.getDeclarationDiagnostics(),
|
|
54
|
+
program.getGlobalDiagnostics(),
|
|
55
|
+
program.getProgramDiagnostics(),
|
|
128
56
|
program.getSemanticDiagnostics(),
|
|
129
|
-
program.getSyntacticDiagnostics(),
|
|
130
57
|
program.getSuggestionDiagnostics(),
|
|
131
|
-
program.
|
|
58
|
+
program.getSyntacticDiagnostics(),
|
|
132
59
|
]).then((results) => results.flat())
|
|
133
60
|
|
|
61
|
+
// Keep a set of external files we can ignore non-critical diags for
|
|
62
|
+
const externalFiles = new Set<RootedFilePath>()
|
|
63
|
+
|
|
64
|
+
// Filter out diagnostics that are not relevant for this project
|
|
65
|
+
const now = Date.now()
|
|
66
|
+
const diagnostics = (
|
|
67
|
+
await Promise.all(
|
|
68
|
+
fullDiagnostics.map(async (diagnostic) => {
|
|
69
|
+
// Always keep all the errors...
|
|
70
|
+
if (diagnostic.category === DiagnosticCategory.Error) return diagnostic
|
|
71
|
+
|
|
72
|
+
// coverage ignore if // Keep diagnostics that do not have an associated file
|
|
73
|
+
if (!diagnostic.fileName) return diagnostic
|
|
74
|
+
|
|
75
|
+
// coverage ignore if // Before we do all the async resolution below, check our cache
|
|
76
|
+
if (externalFiles.has(diagnostic.fileName)) return undefined
|
|
77
|
+
|
|
78
|
+
// Get the source file metadata for this diagnostic (expensive)
|
|
79
|
+
// and filter out anything from external libraries....
|
|
80
|
+
const metadata = await program.getSourceFileMetadata(diagnostic.fileName)
|
|
81
|
+
if (metadata?.isDefaultLibrary || metadata?.isFromExternalLibrary) {
|
|
82
|
+
externalFiles.add(diagnostic.fileName)
|
|
83
|
+
return undefined
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Anything else, we keep!
|
|
87
|
+
return diagnostic
|
|
88
|
+
}),
|
|
89
|
+
)
|
|
90
|
+
).filter((diagnostic): diagnostic is Diagnostic => !!diagnostic)
|
|
91
|
+
context.log.warn(`Filtered diagnostics in ${Date.now() - now}ms`)
|
|
92
|
+
|
|
134
93
|
// When emitting, let's emit the files
|
|
135
|
-
if (
|
|
94
|
+
if (emitOnly !== null) {
|
|
136
95
|
// Emit the files for this program and collect diagnostics
|
|
137
|
-
const emitted = await program.emit(
|
|
96
|
+
const emitted = await program.emit(emitOnly)
|
|
138
97
|
diagnostics.push(...emitted.diagnostics)
|
|
139
98
|
|
|
140
99
|
// Make sure that we add any emitted file to the list to be returned
|
|
141
100
|
if (emitted.emittedFiles?.length) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
101
|
+
emitted.emittedFiles.forEach((file) => {
|
|
102
|
+
assertAbsolutePath(file)
|
|
103
|
+
emittedFiles.push(file)
|
|
104
|
+
})
|
|
145
105
|
}
|
|
146
106
|
|
|
147
107
|
// Report an error if emitting was skipped for some reason (we should
|
|
148
108
|
// have some diagnostics associated with this, but still...)
|
|
149
109
|
// coverage ignore if // don't know how to test this...
|
|
150
110
|
if (emitted.emitSkipped) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
111
|
+
if (project.configFileName && isAbsolutePath(project.configFileName)) {
|
|
112
|
+
report.add({
|
|
113
|
+
level: ERROR,
|
|
114
|
+
message: `Unable to emit files for this project`,
|
|
115
|
+
file: project.configFileName,
|
|
116
|
+
})
|
|
117
|
+
} else {
|
|
118
|
+
report.add({
|
|
119
|
+
level: ERROR,
|
|
120
|
+
message: `Unable to emit files for unknown project`,
|
|
121
|
+
})
|
|
122
|
+
}
|
|
156
123
|
}
|
|
157
124
|
}
|
|
158
125
|
|
|
159
126
|
// Add all diagnostics to the report
|
|
160
|
-
report.add(...
|
|
127
|
+
report.add(...convertDiagnostics(diagnostics, deprecationsLevel))
|
|
161
128
|
}
|
|
162
129
|
} finally {
|
|
163
|
-
await api.close()
|
|
130
|
+
if (api) await api.close()
|
|
164
131
|
}
|
|
165
132
|
|
|
166
133
|
report.done()
|
|
@@ -172,6 +139,48 @@ export class TypeScript implements Plug<Files> {
|
|
|
172
139
|
}
|
|
173
140
|
}
|
|
174
141
|
|
|
142
|
+
export class TypeScriptBuild implements Plug<void> {
|
|
143
|
+
constructor(private readonly _options: TypeScriptBuildOptions = {}) {}
|
|
144
|
+
|
|
145
|
+
async pipe(files: Files, context: Context): Promise<void> {
|
|
146
|
+
// Destructure the build options for easier access
|
|
147
|
+
const { overrideCompilerOptions = {}, stopBuildOnErrors = false, verbose = true, force = true } = this._options
|
|
148
|
+
|
|
149
|
+
// Create our TypeScript API and report for this plug
|
|
150
|
+
const report = context.log.report('TypeScript Build Report')
|
|
151
|
+
|
|
152
|
+
let api: API | undefined = undefined
|
|
153
|
+
let orchestrator: BuildOrchestrator | undefined = undefined
|
|
154
|
+
try {
|
|
155
|
+
api = new API({ cwd: files.directory })
|
|
156
|
+
orchestrator = await api.createBuildOrchestrator([...files.absolutePaths()], {
|
|
157
|
+
cwd: files.directory,
|
|
158
|
+
// From our options
|
|
159
|
+
overrideCompilerOptions,
|
|
160
|
+
stopBuildOnErrors,
|
|
161
|
+
verbose,
|
|
162
|
+
force,
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
const results = await orchestrator.build()
|
|
166
|
+
|
|
167
|
+
if (results.diagnostics) report.add(...convertDiagnostics(results.diagnostics))
|
|
168
|
+
|
|
169
|
+
if (results.status !== 0) {
|
|
170
|
+
report.add({
|
|
171
|
+
level: ERROR,
|
|
172
|
+
message: `Build failed with status code ${results.status}`,
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
} finally {
|
|
176
|
+
if (orchestrator) await orchestrator.dispose()
|
|
177
|
+
if (api) await api.close()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
report.done()
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
175
184
|
/* ========================================================================== *
|
|
176
185
|
* TYPESCRIPT 7 HELPERS *
|
|
177
186
|
* ========================================================================== */
|
|
@@ -184,7 +193,7 @@ export class TypeScript implements Plug<Files> {
|
|
|
184
193
|
*/
|
|
185
194
|
export function tsc(config: string, options: TscOptions = {}): Pipe {
|
|
186
195
|
const { directory, ...opts } = options
|
|
187
|
-
return using(config, { directory }).plug(new TypeScript(
|
|
196
|
+
return using(config, { directory }).plug(new TypeScript(opts))
|
|
188
197
|
}
|
|
189
198
|
|
|
190
199
|
/* ========================================================================== */
|
|
@@ -196,7 +205,7 @@ export function tsc(config: string, options: TscOptions = {}): Pipe {
|
|
|
196
205
|
*
|
|
197
206
|
* This is roughly equivalent to the command line `tsc --build <config>`.
|
|
198
207
|
*/
|
|
199
|
-
export function tsbuild(config: string, options:
|
|
208
|
+
export function tsbuild(config: string, options: TscBuildOptions): Promise<undefined> {
|
|
200
209
|
const { directory, ...opts } = options
|
|
201
|
-
return using(config, { directory }).plug(new
|
|
210
|
+
return using(config, { directory }).plug(new TypeScriptBuild(opts))
|
|
202
211
|
}
|