@plugjs/plug 0.0.1
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/LICENSE.md +211 -0
- package/NOTICE.md +13 -0
- package/README.md +7 -0
- package/dist/assert.cjs +72 -0
- package/dist/assert.cjs.map +6 -0
- package/dist/assert.mjs +41 -0
- package/dist/assert.mjs.map +6 -0
- package/dist/async.cjs +58 -0
- package/dist/async.cjs.map +6 -0
- package/dist/async.mjs +30 -0
- package/dist/async.mjs.map +6 -0
- package/dist/build.cjs +136 -0
- package/dist/build.cjs.map +6 -0
- package/dist/build.mjs +110 -0
- package/dist/build.mjs.map +6 -0
- package/dist/files.cjs +113 -0
- package/dist/files.cjs.map +6 -0
- package/dist/files.mjs +88 -0
- package/dist/files.mjs.map +6 -0
- package/dist/fork.cjs +177 -0
- package/dist/fork.cjs.map +6 -0
- package/dist/fork.mjs +151 -0
- package/dist/fork.mjs.map +6 -0
- package/dist/helpers.cjs +129 -0
- package/dist/helpers.cjs.map +6 -0
- package/dist/helpers.mjs +97 -0
- package/dist/helpers.mjs.map +6 -0
- package/dist/index.cjs +25 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +6 -0
- package/dist/log/colors.cjs +129 -0
- package/dist/log/colors.cjs.map +6 -0
- package/dist/log/colors.mjs +93 -0
- package/dist/log/colors.mjs.map +6 -0
- package/dist/log/emit.cjs +109 -0
- package/dist/log/emit.cjs.map +6 -0
- package/dist/log/emit.mjs +83 -0
- package/dist/log/emit.mjs.map +6 -0
- package/dist/log/levels.cjs +75 -0
- package/dist/log/levels.cjs.map +6 -0
- package/dist/log/levels.mjs +41 -0
- package/dist/log/levels.mjs.map +6 -0
- package/dist/log/logger.cjs +129 -0
- package/dist/log/logger.cjs.map +6 -0
- package/dist/log/logger.mjs +104 -0
- package/dist/log/logger.mjs.map +6 -0
- package/dist/log/options.cjs +149 -0
- package/dist/log/options.cjs.map +6 -0
- package/dist/log/options.mjs +124 -0
- package/dist/log/options.mjs.map +6 -0
- package/dist/log/report.cjs +284 -0
- package/dist/log/report.cjs.map +6 -0
- package/dist/log/report.mjs +259 -0
- package/dist/log/report.mjs.map +6 -0
- package/dist/log/spinner.cjs +83 -0
- package/dist/log/spinner.cjs.map +6 -0
- package/dist/log/spinner.mjs +57 -0
- package/dist/log/spinner.mjs.map +6 -0
- package/dist/log.cjs +71 -0
- package/dist/log.cjs.map +6 -0
- package/dist/log.mjs +45 -0
- package/dist/log.mjs.map +6 -0
- package/dist/paths.cjs +158 -0
- package/dist/paths.cjs.map +6 -0
- package/dist/paths.mjs +122 -0
- package/dist/paths.mjs.map +6 -0
- package/dist/pipe.cjs +71 -0
- package/dist/pipe.cjs.map +6 -0
- package/dist/pipe.mjs +44 -0
- package/dist/pipe.mjs.map +6 -0
- package/dist/plugs/copy.cjs +95 -0
- package/dist/plugs/copy.cjs.map +6 -0
- package/dist/plugs/copy.mjs +64 -0
- package/dist/plugs/copy.mjs.map +6 -0
- package/dist/plugs/coverage/analysis.cjs +229 -0
- package/dist/plugs/coverage/analysis.cjs.map +6 -0
- package/dist/plugs/coverage/analysis.mjs +202 -0
- package/dist/plugs/coverage/analysis.mjs.map +6 -0
- package/dist/plugs/coverage/report.cjs +215 -0
- package/dist/plugs/coverage/report.cjs.map +6 -0
- package/dist/plugs/coverage/report.mjs +200 -0
- package/dist/plugs/coverage/report.mjs.map +6 -0
- package/dist/plugs/coverage.cjs +142 -0
- package/dist/plugs/coverage.cjs.map +6 -0
- package/dist/plugs/coverage.mjs +117 -0
- package/dist/plugs/coverage.mjs.map +6 -0
- package/dist/plugs/debug.cjs +50 -0
- package/dist/plugs/debug.cjs.map +6 -0
- package/dist/plugs/debug.mjs +25 -0
- package/dist/plugs/debug.mjs.map +6 -0
- package/dist/plugs/esbuild/bundle-locals.cjs +51 -0
- package/dist/plugs/esbuild/bundle-locals.cjs.map +6 -0
- package/dist/plugs/esbuild/bundle-locals.mjs +26 -0
- package/dist/plugs/esbuild/bundle-locals.mjs.map +6 -0
- package/dist/plugs/esbuild/check-dependencies.cjs +140 -0
- package/dist/plugs/esbuild/check-dependencies.cjs.map +6 -0
- package/dist/plugs/esbuild/check-dependencies.mjs +115 -0
- package/dist/plugs/esbuild/check-dependencies.mjs.map +6 -0
- package/dist/plugs/esbuild/fix-extensions.cjs +91 -0
- package/dist/plugs/esbuild/fix-extensions.cjs.map +6 -0
- package/dist/plugs/esbuild/fix-extensions.mjs +60 -0
- package/dist/plugs/esbuild/fix-extensions.mjs.map +6 -0
- package/dist/plugs/esbuild.cjs +109 -0
- package/dist/plugs/esbuild.cjs.map +6 -0
- package/dist/plugs/esbuild.mjs +83 -0
- package/dist/plugs/esbuild.mjs.map +6 -0
- package/dist/plugs/eslint/runner.cjs +91 -0
- package/dist/plugs/eslint/runner.cjs.map +6 -0
- package/dist/plugs/eslint/runner.mjs +68 -0
- package/dist/plugs/eslint/runner.mjs.map +6 -0
- package/dist/plugs/exec.cjs +128 -0
- package/dist/plugs/exec.cjs.map +6 -0
- package/dist/plugs/exec.mjs +96 -0
- package/dist/plugs/exec.mjs.map +6 -0
- package/dist/plugs/filter.cjs +59 -0
- package/dist/plugs/filter.cjs.map +6 -0
- package/dist/plugs/filter.mjs +34 -0
- package/dist/plugs/filter.mjs.map +6 -0
- package/dist/plugs/mocha/reporter.cjs +140 -0
- package/dist/plugs/mocha/reporter.cjs.map +6 -0
- package/dist/plugs/mocha/reporter.mjs +107 -0
- package/dist/plugs/mocha/reporter.mjs.map +6 -0
- package/dist/plugs/mocha/runner.cjs +73 -0
- package/dist/plugs/mocha/runner.cjs.map +6 -0
- package/dist/plugs/mocha/runner.mjs +44 -0
- package/dist/plugs/mocha/runner.mjs.map +6 -0
- package/dist/plugs/tsc/compiler.cjs +74 -0
- package/dist/plugs/tsc/compiler.cjs.map +6 -0
- package/dist/plugs/tsc/compiler.mjs +43 -0
- package/dist/plugs/tsc/compiler.mjs.map +6 -0
- package/dist/plugs/tsc/options.cjs +82 -0
- package/dist/plugs/tsc/options.cjs.map +6 -0
- package/dist/plugs/tsc/options.mjs +51 -0
- package/dist/plugs/tsc/options.mjs.map +6 -0
- package/dist/plugs/tsc/report.cjs +90 -0
- package/dist/plugs/tsc/report.cjs.map +6 -0
- package/dist/plugs/tsc/report.mjs +59 -0
- package/dist/plugs/tsc/report.mjs.map +6 -0
- package/dist/plugs/tsc/runner.cjs +101 -0
- package/dist/plugs/tsc/runner.cjs.map +6 -0
- package/dist/plugs/tsc/runner.mjs +72 -0
- package/dist/plugs/tsc/runner.mjs.map +6 -0
- package/dist/plugs.cjs +31 -0
- package/dist/plugs.cjs.map +6 -0
- package/dist/plugs.mjs +13 -0
- package/dist/plugs.mjs.map +6 -0
- package/dist/run.cjs +95 -0
- package/dist/run.cjs.map +6 -0
- package/dist/run.mjs +70 -0
- package/dist/run.mjs.map +6 -0
- package/dist/task.cjs +39 -0
- package/dist/task.cjs.map +6 -0
- package/dist/task.mjs +14 -0
- package/dist/task.mjs.map +6 -0
- package/dist/utils/asyncfs.cjs +143 -0
- package/dist/utils/asyncfs.cjs.map +6 -0
- package/dist/utils/asyncfs.mjs +83 -0
- package/dist/utils/asyncfs.mjs.map +6 -0
- package/dist/utils/caller.cjs +59 -0
- package/dist/utils/caller.cjs.map +6 -0
- package/dist/utils/caller.mjs +34 -0
- package/dist/utils/caller.mjs.map +6 -0
- package/dist/utils/match.cjs +69 -0
- package/dist/utils/match.cjs.map +6 -0
- package/dist/utils/match.mjs +38 -0
- package/dist/utils/match.mjs.map +6 -0
- package/dist/utils/options.cjs +41 -0
- package/dist/utils/options.cjs.map +6 -0
- package/dist/utils/options.mjs +16 -0
- package/dist/utils/options.mjs.map +6 -0
- package/dist/utils/walk.cjs +104 -0
- package/dist/utils/walk.cjs.map +6 -0
- package/dist/utils/walk.mjs +79 -0
- package/dist/utils/walk.mjs.map +6 -0
- package/extra/cli.mjs +212 -0
- package/extra/ts-loader.mjs +214 -0
- package/extra/webassembly.d.ts +11 -0
- package/package.json +57 -0
- package/src/assert.ts +47 -0
- package/src/async.ts +50 -0
- package/src/files.ts +129 -0
- package/src/fork.ts +263 -0
- package/src/helpers.ts +145 -0
- package/src/index.ts +20 -0
- package/src/log/colors.ts +119 -0
- package/src/log/emit.ts +125 -0
- package/src/log/levels.ts +65 -0
- package/src/log/logger.ts +171 -0
- package/src/log/options.ts +199 -0
- package/src/log/report.ts +433 -0
- package/src/log/spinner.ts +70 -0
- package/src/log.ts +68 -0
- package/src/paths.ts +213 -0
- package/src/pipe.ts +231 -0
- package/src/plugs/copy.ts +113 -0
- package/src/plugs/coverage/analysis.ts +395 -0
- package/src/plugs/coverage/report.ts +337 -0
- package/src/plugs/coverage.ts +194 -0
- package/src/plugs/debug.ts +35 -0
- package/src/plugs/esbuild/bundle-locals.ts +33 -0
- package/src/plugs/esbuild/check-dependencies.ts +158 -0
- package/src/plugs/esbuild/fix-extensions.ts +108 -0
- package/src/plugs/esbuild.ts +128 -0
- package/src/plugs/eslint/runner.ts +112 -0
- package/src/plugs/exec.ts +215 -0
- package/src/plugs/filter.ts +56 -0
- package/src/plugs/mocha/reporter.ts +152 -0
- package/src/plugs/mocha/runner.ts +77 -0
- package/src/plugs/tsc/compiler.ts +66 -0
- package/src/plugs/tsc/options.ts +97 -0
- package/src/plugs/tsc/report.ts +74 -0
- package/src/plugs/tsc/runner.ts +100 -0
- package/src/plugs.ts +33 -0
- package/src/run.ts +160 -0
- package/src/task.ts +26 -0
- package/src/utils/asyncfs.ts +82 -0
- package/src/utils/caller.ts +45 -0
- package/src/utils/match.ts +286 -0
- package/src/utils/options.ts +22 -0
- package/src/utils/walk.ts +136 -0
- package/types/assert.d.ts +18 -0
- package/types/async.d.ts +20 -0
- package/types/build.d.ts +56 -0
- package/types/files.d.ts +44 -0
- package/types/fork.d.ts +57 -0
- package/types/helpers.d.ts +49 -0
- package/types/index.d.ts +14 -0
- package/types/log/colors.d.ts +25 -0
- package/types/log/emit.d.ts +14 -0
- package/types/log/levels.d.ts +52 -0
- package/types/log/logger.d.ts +31 -0
- package/types/log/options.d.ts +40 -0
- package/types/log/report.d.ts +64 -0
- package/types/log/spinner.d.ts +2 -0
- package/types/log.d.ts +10 -0
- package/types/paths.d.ts +76 -0
- package/types/pipe.d.ts +152 -0
- package/types/plugs/copy.d.ts +27 -0
- package/types/plugs/coverage/analysis.d.ts +104 -0
- package/types/plugs/coverage/report.d.ts +53 -0
- package/types/plugs/coverage.d.ts +46 -0
- package/types/plugs/debug.d.ts +14 -0
- package/types/plugs/esbuild/bundle-locals.d.ts +6 -0
- package/types/plugs/esbuild/check-dependencies.d.ts +12 -0
- package/types/plugs/esbuild/fix-extensions.d.ts +29 -0
- package/types/plugs/esbuild.d.ts +24 -0
- package/types/plugs/eslint/runner.d.ts +22 -0
- package/types/plugs/exec.d.ts +90 -0
- package/types/plugs/filter.d.ts +23 -0
- package/types/plugs/mocha/reporter.d.ts +8 -0
- package/types/plugs/mocha/runner.d.ts +34 -0
- package/types/plugs/tsc/compiler.d.ts +24 -0
- package/types/plugs/tsc/options.d.ts +8 -0
- package/types/plugs/tsc/report.d.ts +5 -0
- package/types/plugs/tsc/runner.d.ts +13 -0
- package/types/plugs.d.ts +16 -0
- package/types/run.d.ts +89 -0
- package/types/task.d.ts +15 -0
- package/types/utils/asyncfs.d.ts +37 -0
- package/types/utils/caller.d.ts +7 -0
- package/types/utils/match.d.ts +216 -0
- package/types/utils/options.d.ts +15 -0
- package/types/utils/walk.d.ts +28 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import ts from 'typescript' // TypeScript does NOT support ESM modules
|
|
2
|
+
|
|
3
|
+
import { ERROR, NOTICE, Report, ReportLevel, ReportRecord, WARN } from '../../log.js'
|
|
4
|
+
import { AbsolutePath, resolveAbsolutePath } from '../../paths.js'
|
|
5
|
+
|
|
6
|
+
function convertMessageChain(chain: ts.DiagnosticMessageChain, indent = 0): string[] {
|
|
7
|
+
const message = `${''.padStart(indent * 2)}${chain.messageText}`
|
|
8
|
+
|
|
9
|
+
if (chain.next) {
|
|
10
|
+
const next = chain.next.map((c) => convertMessageChain(c, indent + 1))
|
|
11
|
+
return [ message, ...next.flat(1) ]
|
|
12
|
+
} else {
|
|
13
|
+
return [ message ]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function convertDiagnostics(
|
|
18
|
+
diagnostics: readonly ts.Diagnostic[],
|
|
19
|
+
directory: AbsolutePath,
|
|
20
|
+
): ReportRecord[] {
|
|
21
|
+
return diagnostics.map((diagnostic): ReportRecord => {
|
|
22
|
+
// console.log(diagnostic)
|
|
23
|
+
void directory
|
|
24
|
+
|
|
25
|
+
// Convert the `DiagnosticCategory` to our level
|
|
26
|
+
let level: ReportLevel
|
|
27
|
+
switch (diagnostic.category) {
|
|
28
|
+
case ts.DiagnosticCategory.Error: level = ERROR; break
|
|
29
|
+
case ts.DiagnosticCategory.Warning: level = WARN; break
|
|
30
|
+
default: level = NOTICE
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Convert the `messageText` to a string
|
|
34
|
+
let message: string | string[]
|
|
35
|
+
if (typeof diagnostic.messageText === 'string') {
|
|
36
|
+
message = diagnostic.messageText
|
|
37
|
+
} else {
|
|
38
|
+
message = convertMessageChain(diagnostic.messageText)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Simple variables
|
|
42
|
+
const tags = `TS${diagnostic.code}`
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if (diagnostic.file) {
|
|
46
|
+
const { file: sourceFile, start, length } = diagnostic
|
|
47
|
+
const file = resolveAbsolutePath(directory, sourceFile.fileName)
|
|
48
|
+
const source = sourceFile.getFullText()
|
|
49
|
+
|
|
50
|
+
if (start !== undefined) {
|
|
51
|
+
const position = sourceFile.getLineAndCharacterOfPosition(start)
|
|
52
|
+
let { line, character: column } = position
|
|
53
|
+
column += 1
|
|
54
|
+
line += 1
|
|
55
|
+
|
|
56
|
+
return { level, message, tags, file, source, line, column, length }
|
|
57
|
+
} else {
|
|
58
|
+
return { level, message, tags, file, source }
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
return { level, message, tags }
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Update a report, adding records from an array of {@link ts.Diagnostic} */
|
|
67
|
+
export function updateReport(
|
|
68
|
+
report: Report,
|
|
69
|
+
diagnostics: readonly ts.Diagnostic[],
|
|
70
|
+
directory: AbsolutePath,
|
|
71
|
+
): void {
|
|
72
|
+
const records = convertDiagnostics(diagnostics, directory)
|
|
73
|
+
report.add(...records)
|
|
74
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import ts from 'typescript' // TypeScript does NOT support ESM modules
|
|
2
|
+
|
|
3
|
+
import { failure } from '../../assert.js'
|
|
4
|
+
import { Files } from '../../files.js'
|
|
5
|
+
import { $p, log } from '../../log.js'
|
|
6
|
+
import { getCurrentWorkingDirectory, isFile } from '../../paths.js'
|
|
7
|
+
import { Plug } from '../../pipe.js'
|
|
8
|
+
import { Run } from '../../run.js'
|
|
9
|
+
import { parseOptions, ParseOptions } from '../../utils/options.js'
|
|
10
|
+
import { TypeScriptHost } from './compiler.js'
|
|
11
|
+
import { getCompilerOptions } from './options.js'
|
|
12
|
+
import { updateReport } from './report.js'
|
|
13
|
+
|
|
14
|
+
/* ========================================================================== *
|
|
15
|
+
* WORKER PLUG *
|
|
16
|
+
* ========================================================================== */
|
|
17
|
+
|
|
18
|
+
export default class Tsc implements Plug<Files> {
|
|
19
|
+
private readonly _tsconfig?: string
|
|
20
|
+
private readonly _options: ts.CompilerOptions
|
|
21
|
+
|
|
22
|
+
constructor()
|
|
23
|
+
constructor(config: string)
|
|
24
|
+
constructor(options: ts.CompilerOptions)
|
|
25
|
+
constructor(config: string, options: ts.CompilerOptions)
|
|
26
|
+
|
|
27
|
+
constructor(...args: ParseOptions<ts.CompilerOptions>) {
|
|
28
|
+
const { params: [ tsconfig ], options } = parseOptions(args, {})
|
|
29
|
+
this._tsconfig = tsconfig
|
|
30
|
+
this._options = options
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async pipe(files: Files, run: Run): Promise<Files> {
|
|
34
|
+
const tsconfig = this._tsconfig ?
|
|
35
|
+
run.resolve(this._tsconfig) :
|
|
36
|
+
isFile(files.directory, 'tsconfig.json')
|
|
37
|
+
|
|
38
|
+
const overrides: ts.CompilerOptions = {
|
|
39
|
+
rootDir: files.directory, // by default, our "files" directory
|
|
40
|
+
...this._options, // any other options specified in the constructor
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const { errors, options } = await getCompilerOptions(
|
|
44
|
+
tsconfig, // resolved tsconfig.json from constructor, might be undefined
|
|
45
|
+
overrides, // overrides from constructor, might be an empty object
|
|
46
|
+
run.buildFile) // overrides are defined in the build file, sooo.....
|
|
47
|
+
|
|
48
|
+
const report = run.report('TypeScript Report')
|
|
49
|
+
|
|
50
|
+
// Update report and fail on errors
|
|
51
|
+
updateReport(report, errors, getCurrentWorkingDirectory())
|
|
52
|
+
if (report.errors) report.done(true)
|
|
53
|
+
|
|
54
|
+
const { rootDir, outDir } = options
|
|
55
|
+
const root = rootDir ? run.resolve(rootDir) : files.directory
|
|
56
|
+
const out = outDir ? run.resolve(outDir) : root
|
|
57
|
+
|
|
58
|
+
const host = new TypeScriptHost(root)
|
|
59
|
+
|
|
60
|
+
const paths = [ ...files.absolutePaths() ]
|
|
61
|
+
for (const path of paths) log.trace(`Compiling "${$p(path)}"`)
|
|
62
|
+
|
|
63
|
+
// Get our build file and create the master program
|
|
64
|
+
log.info('Compiling', paths.length, 'files')
|
|
65
|
+
log.debug('Compliation options', options)
|
|
66
|
+
|
|
67
|
+
const program = ts.createProgram(paths, options, host, undefined, errors)
|
|
68
|
+
const diagnostics = ts.getPreEmitDiagnostics(program)
|
|
69
|
+
|
|
70
|
+
// Update report and fail on errors
|
|
71
|
+
updateReport(report, diagnostics, root)
|
|
72
|
+
if (report.errors) report.done(true)
|
|
73
|
+
|
|
74
|
+
const builder = run.files(out)
|
|
75
|
+
const promises: Promise<void>[] = []
|
|
76
|
+
const result = program.emit(undefined, (fileName, code) => {
|
|
77
|
+
promises.push(builder.write(fileName, code).then((file) => {
|
|
78
|
+
log.trace('Written', $p(file))
|
|
79
|
+
}).catch((error) => {
|
|
80
|
+
run.log.error('Error writing to', fileName, error)
|
|
81
|
+
throw failure() // no more logs!
|
|
82
|
+
}))
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
// Update report and fail on errors
|
|
86
|
+
updateReport(report, result.diagnostics, root)
|
|
87
|
+
if (report.errors) report.done(true)
|
|
88
|
+
|
|
89
|
+
// Await for all files to be written and check
|
|
90
|
+
const settlements = await Promise.allSettled(promises)
|
|
91
|
+
const failures = settlements
|
|
92
|
+
.reduce((failures, s) => failures + s.status === 'rejected' ? 1 : 0, 0)
|
|
93
|
+
if (failures) throw failure() // already logged above
|
|
94
|
+
|
|
95
|
+
// All done, build our files and return it
|
|
96
|
+
const outputs = builder.build()
|
|
97
|
+
log.info('TSC produced', outputs.length, 'files into', $p(outputs.directory))
|
|
98
|
+
return outputs
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/plugs.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* ========================================================================== *
|
|
2
|
+
* FORKING PLUGS *
|
|
3
|
+
* ========================================================================== */
|
|
4
|
+
|
|
5
|
+
import { installForking } from './fork.js'
|
|
6
|
+
import { requireResolve } from './paths.js'
|
|
7
|
+
|
|
8
|
+
import type ESLint from './plugs/eslint/runner.js'
|
|
9
|
+
import type Mocha from './plugs/mocha/runner.js'
|
|
10
|
+
import type Tsc from './plugs/tsc/runner.js'
|
|
11
|
+
|
|
12
|
+
declare module './pipe.js' {
|
|
13
|
+
export interface Pipe {
|
|
14
|
+
eslint: PipeExtension<typeof ESLint>
|
|
15
|
+
mocha: PipeExtension<typeof Mocha>
|
|
16
|
+
tsc: PipeExtension<typeof Tsc>
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
installForking('eslint', requireResolve(__fileurl, './plugs/eslint/runner'))
|
|
21
|
+
installForking('mocha', requireResolve(__fileurl, './plugs/mocha/runner'))
|
|
22
|
+
installForking('tsc', requireResolve(__fileurl, './plugs/tsc/runner'))
|
|
23
|
+
|
|
24
|
+
/* ========================================================================== *
|
|
25
|
+
* STANDARD IN-PROCESS PLUGS *
|
|
26
|
+
* ========================================================================== */
|
|
27
|
+
|
|
28
|
+
export * from './plugs/copy.js'
|
|
29
|
+
export * from './plugs/coverage.js'
|
|
30
|
+
export * from './plugs/debug.js'
|
|
31
|
+
export * from './plugs/esbuild.js'
|
|
32
|
+
export * from './plugs/exec.js'
|
|
33
|
+
export * from './plugs/filter.js'
|
package/src/run.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { assert } from './assert.js'
|
|
3
|
+
import { Files, FilesBuilder } from './files.js'
|
|
4
|
+
import { createReport, getLevelNumber, getLogger, Logger, LogLevelString, Report } from './log.js'
|
|
5
|
+
import { AbsolutePath, getCurrentWorkingDirectory, isAbsolutePath, resolveAbsolutePath } from './paths.js'
|
|
6
|
+
import { Pipe, PipeImpl } from './pipe.js'
|
|
7
|
+
import { ParseOptions, parseOptions } from './utils/options.js'
|
|
8
|
+
import { walk, WalkOptions } from './utils/walk.js'
|
|
9
|
+
|
|
10
|
+
/** The {@link FindOptions} interface defines the options for finding files. */
|
|
11
|
+
export interface FindOptions extends WalkOptions {
|
|
12
|
+
/**
|
|
13
|
+
* The directory where to start looking for files according to the rules
|
|
14
|
+
* specified in {@link Run.resolve}.
|
|
15
|
+
*/
|
|
16
|
+
directory?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The {@link Run} interface defines the context in which a {@link Task} is
|
|
21
|
+
* invoked.
|
|
22
|
+
*
|
|
23
|
+
* Runs keep track of the invocation stack (to avoid circular dependencies) and
|
|
24
|
+
* of the cached results for {@link Task} invocations.
|
|
25
|
+
*/
|
|
26
|
+
export interface Run {
|
|
27
|
+
/**
|
|
28
|
+
* The _name_ of the task associated with this {@link Run} (if one is).
|
|
29
|
+
*
|
|
30
|
+
* Tasks can have different names in different builds, this refers to the
|
|
31
|
+
* _task name_ in the build being executed.
|
|
32
|
+
*/
|
|
33
|
+
readonly taskName: string
|
|
34
|
+
/** The absolute file name of the build */
|
|
35
|
+
readonly buildFile: AbsolutePath,
|
|
36
|
+
/** For convenience, the directory of the build file */
|
|
37
|
+
readonly buildDir: AbsolutePath,
|
|
38
|
+
/** The {@link Logger} associated with this instance. */
|
|
39
|
+
readonly log: Logger
|
|
40
|
+
|
|
41
|
+
/** Set the logging level within this {@link Run} */
|
|
42
|
+
setLogLevel(level: LogLevelString): void
|
|
43
|
+
|
|
44
|
+
/** Call another {@link Task} from this one. */
|
|
45
|
+
call(name: string): Promise<Files | undefined>
|
|
46
|
+
|
|
47
|
+
/** Create a new {@link Report} with the given _title_ */
|
|
48
|
+
report(title: string): Report
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a path in the context of this {@link Run}.
|
|
52
|
+
*
|
|
53
|
+
* If the path starts with `@...` it is considered to be relative to the
|
|
54
|
+
* {@link process.cwd | current working directory}, otherwise it will be
|
|
55
|
+
* resolved against the build file where the task was originally defined in.
|
|
56
|
+
*/
|
|
57
|
+
resolve(...paths: string[]): AbsolutePath
|
|
58
|
+
|
|
59
|
+
/** Create a {@link FilesBuilder} cloning an existing {@link Files}. */
|
|
60
|
+
files(files: Files): FilesBuilder
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a {@link FilesBuilder} instance resolving the directory specified
|
|
64
|
+
* according to the rules specified in {@link Run.resolve}.
|
|
65
|
+
*/
|
|
66
|
+
files(...paths: string[]): FilesBuilder
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Find files according to the globs and {@link FindOptions} specified.
|
|
70
|
+
*/
|
|
71
|
+
find(glob: string, ...args: ParseOptions<FindOptions>): Pipe & Promise<Files>
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create a new {@link Pipe} wrapping the specified {@link Files}.
|
|
75
|
+
*/
|
|
76
|
+
pipe(files: Files | Promise<Files>): Pipe & Promise<Files>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Constructor options for our default {@link Run} implementation */
|
|
80
|
+
export interface RunConstructionOptions {
|
|
81
|
+
readonly taskName: string,
|
|
82
|
+
readonly buildDir: AbsolutePath,
|
|
83
|
+
readonly buildFile: AbsolutePath,
|
|
84
|
+
readonly log?: Logger,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Our default {@link Run} implementation */
|
|
88
|
+
export class RunImpl implements Run {
|
|
89
|
+
readonly taskName: string
|
|
90
|
+
readonly buildFile: AbsolutePath
|
|
91
|
+
readonly buildDir: AbsolutePath
|
|
92
|
+
readonly log: Logger
|
|
93
|
+
|
|
94
|
+
constructor(options: RunConstructionOptions)
|
|
95
|
+
|
|
96
|
+
constructor({ taskName, buildDir, buildFile, log }: RunConstructionOptions) {
|
|
97
|
+
this.taskName = taskName
|
|
98
|
+
this.buildDir = buildDir
|
|
99
|
+
this.buildFile = buildFile
|
|
100
|
+
this.log = log || getLogger(taskName)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Set the logging level within this {@link Run} */
|
|
104
|
+
setLogLevel(level: LogLevelString): void {
|
|
105
|
+
this.log.level = getLevelNumber(level)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
report(title: string): Report {
|
|
109
|
+
return createReport(title, this.taskName)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
resolve(...paths: string[]): AbsolutePath {
|
|
113
|
+
const path = join(...paths)
|
|
114
|
+
if (! path) return this.buildDir
|
|
115
|
+
|
|
116
|
+
if (path.startsWith('@')) {
|
|
117
|
+
const relative = path.substring(1)
|
|
118
|
+
assert(! isAbsolutePath(relative), `Path component of "${path}" is absolute`)
|
|
119
|
+
return resolveAbsolutePath(getCurrentWorkingDirectory(), relative)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (isAbsolutePath(path)) return path
|
|
123
|
+
|
|
124
|
+
return resolveAbsolutePath(this.buildDir, path)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
files(files: Files): FilesBuilder
|
|
128
|
+
files(...paths: string[]): FilesBuilder
|
|
129
|
+
files(first: Files | string | undefined, ...paths: string[]): FilesBuilder {
|
|
130
|
+
if (typeof first === 'string') {
|
|
131
|
+
return Files.builder(this.resolve(first, ...paths))
|
|
132
|
+
} else if (first) {
|
|
133
|
+
return Files.builder(first)
|
|
134
|
+
} else {
|
|
135
|
+
return Files.builder(this.resolve())
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
find(glob: string, ...args: ParseOptions<FindOptions>): Pipe & Promise<Files> {
|
|
140
|
+
const { params, options: { directory, ...options } } = parseOptions(args, {})
|
|
141
|
+
|
|
142
|
+
const promise = Promise.resolve().then(async () => {
|
|
143
|
+
const builder = this.files(directory || '.')
|
|
144
|
+
for await (const file of walk(builder.directory, [ glob, ...params ], options)) {
|
|
145
|
+
builder.add(file)
|
|
146
|
+
}
|
|
147
|
+
return builder.build()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
return this.pipe(promise)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
pipe(files: Files | Promise<Files>): Pipe & Promise<Files> {
|
|
154
|
+
return new PipeImpl(files, this)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
call(name: string): Promise<Files | undefined> {
|
|
158
|
+
throw new Error(`Unable to call task "${name}"`)
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/task.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BuildContext, TaskDefinition, ThisBuild } from './build.js'
|
|
2
|
+
import type { Files } from './files.js'
|
|
3
|
+
import type { Run } from './run.js'
|
|
4
|
+
|
|
5
|
+
/* ========================================================================== *
|
|
6
|
+
* TASK *
|
|
7
|
+
* ========================================================================== */
|
|
8
|
+
|
|
9
|
+
export interface Task<T extends Files | undefined = Files | undefined> {
|
|
10
|
+
/** The {@link BuildContext} of where this task was originally defined */
|
|
11
|
+
readonly context: BuildContext
|
|
12
|
+
|
|
13
|
+
/** Invoked by the {@link Run} when actually executing this {@link Task} */
|
|
14
|
+
call(thisBuild: ThisBuild<any>, run: Run): Promise<T>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class TaskImpl implements Task<Files | undefined> {
|
|
18
|
+
constructor(
|
|
19
|
+
readonly context: BuildContext,
|
|
20
|
+
private readonly _definition: TaskDefinition<any>,
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
async call(self: ThisBuild<any>, run: Run): Promise<Files | undefined> {
|
|
24
|
+
return (await this._definition.call(self, self, run)) || undefined
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { constants } from 'node:fs'
|
|
2
|
+
import fsp from 'node:fs/promises'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* I have no idea why sometimes stacks don't have a trace when coming out of
|
|
6
|
+
* the "node:fs/promises" api... There is a _stack_ property on the object
|
|
7
|
+
* but it simply includes the first line (if so), no thing further...
|
|
8
|
+
*
|
|
9
|
+
* Upon further inspection, it _seems_ this is related to some issues with the
|
|
10
|
+
* Error.captureStackTrace(...) function. If we pass a function to it as
|
|
11
|
+
* second parameter in our functions below, we end up with no stacks as well!
|
|
12
|
+
*
|
|
13
|
+
* So, for now, let's catch all errors, invoke `Error.captureStackTrace`
|
|
14
|
+
* manually without any parameter (besides the error itself), and fail with
|
|
15
|
+
* this.
|
|
16
|
+
*
|
|
17
|
+
* Hopefully, it'll get fixed, eventually, but for now let's keep this wrapper
|
|
18
|
+
* around!
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/* Process every entry in "node:fs/promises" */
|
|
22
|
+
const fs = Object.entries(fsp as any).reduce((fs, [ key, val ]) => {
|
|
23
|
+
if (typeof val === 'function') {
|
|
24
|
+
/* If the value is a function, wrap it! */
|
|
25
|
+
const f = function(...args: any[]): any {
|
|
26
|
+
/* Call the function, and _catch_ any error */
|
|
27
|
+
return val.apply(fsp, args).catch((error: any) => {
|
|
28
|
+
/* For any error caught, we fill in the stack trace */
|
|
29
|
+
Error.captureStackTrace(error)
|
|
30
|
+
throw error
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Make sure that the functions are called correctly */
|
|
35
|
+
Object.defineProperty(f, 'name', { value: key })
|
|
36
|
+
/* Assign the wrapper to our exports */
|
|
37
|
+
fs[key] = f
|
|
38
|
+
} else {
|
|
39
|
+
/* Not a function, no wrapping... */
|
|
40
|
+
fs[key] = val
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Return the "reduced" exports */
|
|
44
|
+
return fs
|
|
45
|
+
}, { constants } as any) as typeof fsp & { constants: typeof constants }
|
|
46
|
+
|
|
47
|
+
/* Export _our_ version of the "node:fs/promises" module */
|
|
48
|
+
export default fs
|
|
49
|
+
|
|
50
|
+
/* Export all the wrappers to "node:fs/promises" individually */
|
|
51
|
+
export const access = fs.access
|
|
52
|
+
export const copyFile = fs.copyFile
|
|
53
|
+
export const cp = fs.cp
|
|
54
|
+
export const open = fs.open
|
|
55
|
+
export const opendir = fs.opendir
|
|
56
|
+
export const rename = fs.rename
|
|
57
|
+
export const truncate = fs.truncate
|
|
58
|
+
export const rm = fs.rm
|
|
59
|
+
export const rmdir = fs.rmdir
|
|
60
|
+
export const mkdir = fs.mkdir
|
|
61
|
+
export const readdir = fs.readdir
|
|
62
|
+
export const readlink = fs.readlink
|
|
63
|
+
export const symlink = fs.symlink
|
|
64
|
+
export const lstat = fs.lstat
|
|
65
|
+
export const stat = fs.stat
|
|
66
|
+
export const link = fs.link
|
|
67
|
+
export const unlink = fs.unlink
|
|
68
|
+
export const chmod = fs.chmod
|
|
69
|
+
export const lchmod = fs.lchmod
|
|
70
|
+
export const lchown = fs.lchown
|
|
71
|
+
export const chown = fs.chown
|
|
72
|
+
export const utimes = fs.utimes
|
|
73
|
+
export const lutimes = fs.lutimes
|
|
74
|
+
export const realpath = fs.realpath
|
|
75
|
+
export const mkdtemp = fs.mkdtemp
|
|
76
|
+
export const writeFile = fs.writeFile
|
|
77
|
+
export const appendFile = fs.appendFile
|
|
78
|
+
export const readFile = fs.readFile
|
|
79
|
+
export const watch = fs.watch
|
|
80
|
+
|
|
81
|
+
/* Export constants from "node:/fs" in addition */
|
|
82
|
+
export { constants } from 'node:fs'
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { statSync } from 'node:fs'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { assert } from '../assert.js'
|
|
4
|
+
import { AbsolutePath, assertAbsolutePath } from '../paths.js'
|
|
5
|
+
|
|
6
|
+
export interface Location {
|
|
7
|
+
file: AbsolutePath,
|
|
8
|
+
line?: number | undefined,
|
|
9
|
+
column?: number | undefined,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function findCaller(of: (...args: any[]) => any): Location {
|
|
13
|
+
const oldPrepareStackTrace = Error.prepareStackTrace
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
Error.prepareStackTrace = (_, stackTraces): Location | undefined => {
|
|
17
|
+
const nullableFileOrUrl = stackTraces[0].getFileName()
|
|
18
|
+
if (! nullableFileOrUrl) return
|
|
19
|
+
|
|
20
|
+
const nullableLine = stackTraces[0].getColumnNumber()
|
|
21
|
+
const nullableColumn = stackTraces[0].getColumnNumber()
|
|
22
|
+
|
|
23
|
+
const line = typeof nullableLine === 'number' ? nullableLine : undefined
|
|
24
|
+
const column = typeof nullableColumn === 'number' ? nullableColumn : undefined
|
|
25
|
+
|
|
26
|
+
const file =
|
|
27
|
+
nullableFileOrUrl.startsWith('file:/') ?
|
|
28
|
+
fileURLToPath(nullableFileOrUrl) :
|
|
29
|
+
nullableFileOrUrl
|
|
30
|
+
|
|
31
|
+
assertAbsolutePath(file)
|
|
32
|
+
return { file, line, column }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const record: { stack?: Location } = {}
|
|
36
|
+
Error.captureStackTrace(record, of)
|
|
37
|
+
const location = record.stack
|
|
38
|
+
|
|
39
|
+
assert(location, 'Unable to determine build file name')
|
|
40
|
+
assert(statSync(location.file).isFile(), `Build file "${location.file}" not found`)
|
|
41
|
+
return location
|
|
42
|
+
} finally {
|
|
43
|
+
Error.prepareStackTrace = oldPrepareStackTrace
|
|
44
|
+
}
|
|
45
|
+
}
|