mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Cleanup, remove some unneeded dependencies, make it easier to add gulp.watch support later
This commit is contained in:
1 parent
5bc8f957f1
commit
c8c0428162
14 files changed
+539
-678
No files matched your search
@@ -0,0 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
// this just fixes the incorrect types for chalk :/
|
||||
const chalk = /**@type {import("chalk").Chalk}*/(require("chalk").default || require("chalk"));
|
||||
module.exports = chalk;
|
||||
@@ -1,20 +0,0 @@
|
||||
// @ts-check
|
||||
const chalk = /**@type {import("chalk").Chalk}*/(require("chalk").default || require("chalk"));
|
||||
|
||||
exports.useColors = process.stdout.isTTY;
|
||||
for (const arg of process.argv) {
|
||||
if (arg === "--no-color") exports["useColors"] = false;
|
||||
else if (arg === "--color") exports["useColors"] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} message
|
||||
* @param {import("chalk").Chalk} color
|
||||
*/
|
||||
function addColor(message, color) {
|
||||
return exports.useColors ? color(message) : message;
|
||||
}
|
||||
exports.addColor = addColor;
|
||||
|
||||
/** @type {{[P in Exclude<keyof import("chalk").Chalk, "constructor" | "enabled" | "level">]: import("chalk").Chalk[P]}} */
|
||||
exports.color = chalk;
|
||||
@@ -11,20 +11,37 @@ const formatDiagnosticsHost = exports.formatDiagnosticsHost = {
|
||||
|
||||
/**
|
||||
* @param {Diagnostic[]} diagnostics
|
||||
* @param {boolean} [pretty]
|
||||
* @param {{ cwd?: string, pretty?: boolean }} [options]
|
||||
*/
|
||||
function formatDiagnostics(diagnostics, pretty) {
|
||||
return pretty ? ts.formatDiagnosticsWithColorAndContext(diagnostics, formatDiagnosticsHost) :
|
||||
ts.formatDiagnostics(diagnostics, formatDiagnosticsHost);
|
||||
function formatDiagnostics(diagnostics, options) {
|
||||
return options && options.pretty
|
||||
? ts.formatDiagnosticsWithColorAndContext(diagnostics, getFormatDiagnosticsHost(options && options.cwd))
|
||||
: ts.formatDiagnostics(diagnostics, getFormatDiagnosticsHost(options && options.cwd));
|
||||
}
|
||||
exports.formatDiagnostics = formatDiagnostics;
|
||||
|
||||
/** @param {Diagnostic[]} diagnostics */
|
||||
function reportDiagnostics(diagnostics) {
|
||||
log(formatDiagnostics(diagnostics, process.stdout.isTTY));
|
||||
/**
|
||||
* @param {Diagnostic[]} diagnostics
|
||||
* @param {{ cwd?: string }} [options]
|
||||
*/
|
||||
function reportDiagnostics(diagnostics, options) {
|
||||
log(formatDiagnostics(diagnostics, { cwd: options && options.cwd, pretty: process.stdout.isTTY }));
|
||||
}
|
||||
exports.reportDiagnostics = reportDiagnostics;
|
||||
|
||||
/**
|
||||
* @param {string | undefined} cwd
|
||||
* @returns {FormatDiagnosticsHost}
|
||||
*/
|
||||
function getFormatDiagnosticsHost(cwd) {
|
||||
if (!cwd || cwd === process.cwd()) return formatDiagnosticsHost;
|
||||
return {
|
||||
getCanonicalFileName: formatDiagnosticsHost.getCanonicalFileName,
|
||||
getCurrentDirectory: () => cwd,
|
||||
getNewLine: formatDiagnosticsHost.getNewLine
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import("../../lib/typescript").FormatDiagnosticsHost} FormatDiagnosticsHost
|
||||
* @typedef {import("../../lib/typescript").Diagnostic} Diagnostic
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
const cp = require("child_process");
|
||||
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
|
||||
const isWin = /^win/.test(process.platform);
|
||||
const { addColor, color } = require("./colors");
|
||||
const chalk = require("./chalk");
|
||||
|
||||
module.exports = exec;
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = exec;
|
||||
*/
|
||||
function exec(cmd, args, options = {}) {
|
||||
return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => {
|
||||
log(addColor(`${cmd} ${args.join(" ")}`, color.gray));
|
||||
log(`> ${chalk.green(cmd)} ${args.join(" ")}`);
|
||||
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
|
||||
const subshellFlag = isWin ? "/c" : "-c";
|
||||
const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`];
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
// @ts-check
|
||||
/**
|
||||
* @typedef {import("gulp").Gulp} Gulp
|
||||
* @typedef {import("gulp-help").GulpHelp} GulpHelp
|
||||
* @typedef {GulpHelp & { Gulp: new () => Gulp }} DotGulpModule
|
||||
* @type {DotGulpModule}
|
||||
*/
|
||||
module.exports = require("gulp-help")(require("gulp"));
|
||||
+17
-16
@@ -4,26 +4,27 @@ const path = require("path");
|
||||
const gulp = require("./gulp");
|
||||
const newer = require("gulp-newer");
|
||||
const concat = require("gulp-concat");
|
||||
|
||||
module.exports = exports = makeLibraryTargets;
|
||||
const merge2 = require("merge2");
|
||||
|
||||
/** @type {{ libs: string[], paths?: Record<string, string>, sources?: Record<string, string[]> }} */
|
||||
const libraries = readJson("./src/lib/libs.json");
|
||||
const libs = libraries.libs.map(lib => {
|
||||
const relativeSources = ["header.d.ts"].concat(libraries.sources && libraries.sources[lib] || [lib + ".d.ts"]);
|
||||
const relativeTarget = libraries.paths && libraries.paths[lib] || ("lib." + lib + ".d.ts");
|
||||
const sources = relativeSources.map(s => path.posix.join("src/lib", s));
|
||||
const target = `built/local/${relativeTarget}`;
|
||||
return { target, relativeTarget, sources };
|
||||
});
|
||||
exports.libraryTargets = libs.map(lib => lib.target);
|
||||
|
||||
/**
|
||||
* @param {string[]} prepends
|
||||
*/
|
||||
function makeLibraryTargets(prepends) {
|
||||
return libraries.libs.map(lib => {
|
||||
const relativeSources = ["header.d.ts"].concat(libraries.sources && libraries.sources[lib] || [lib + ".d.ts"]);
|
||||
const relativeTarget = libraries.paths && libraries.paths[lib] || ("lib." + lib + ".d.ts");
|
||||
const sources = prepends.concat(relativeSources.map(s => path.posix.join("src/lib", s)));
|
||||
const target = `built/local/${relativeTarget}`;
|
||||
gulp.task(target, /*help*/ false, [], () =>
|
||||
gulp.src(sources)
|
||||
.pipe(newer(target))
|
||||
.pipe(concat(relativeTarget, { newLine: "\n\n" }))
|
||||
.pipe(gulp.dest("built/local")));
|
||||
return target;
|
||||
});
|
||||
}
|
||||
function generateLibs(prepends) {
|
||||
return merge2(libs.map(({ sources, target, relativeTarget }) =>
|
||||
gulp.src(prepends.concat(sources))
|
||||
.pipe(newer(target))
|
||||
.pipe(concat(relativeTarget, { newLine: "\n\n" }))
|
||||
.pipe(gulp.dest("built/local"))));
|
||||
}
|
||||
exports.generateLibs = generateLibs;
|
||||
@@ -1,11 +0,0 @@
|
||||
// @ts-check
|
||||
const { PassThrough } = require("stream");
|
||||
|
||||
/**
|
||||
* @returns {NodeJS.ReadWriteStream}
|
||||
*/
|
||||
function pass() {
|
||||
return new PassThrough({ objectMode: true });
|
||||
}
|
||||
|
||||
module.exports = pass;
|
||||
@@ -1,14 +0,0 @@
|
||||
// @ts-check
|
||||
const fs = require("fs");
|
||||
const insert = require("gulp-insert");
|
||||
const pass = require("./pass");
|
||||
|
||||
/**
|
||||
* @param {(() => string[] | undefined) | string[]} [prepends]
|
||||
* @returns {NodeJS.ReadWriteStream}
|
||||
*/
|
||||
function prepend(prepends) {
|
||||
if (typeof prepends === "function") prepends = prepends();
|
||||
return (prepends || []).reduce((stream, file) => stream.pipe(insert.prepend(fs.readFileSync(file))), pass());
|
||||
}
|
||||
module.exports = prepend;
|
||||
+384
-463
@@ -2,8 +2,6 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const gulp = require("./gulp");
|
||||
const PluginError = require("plugin-error");
|
||||
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
|
||||
const gulpif = require("gulp-if");
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const merge2 = require("merge2");
|
||||
@@ -11,105 +9,140 @@ const tsc = require("gulp-typescript");
|
||||
const tsc_oop = require("./gulp-typescript-oop");
|
||||
const upToDate = require("./upToDate");
|
||||
const ts = require("../../lib/typescript");
|
||||
const debugMode = require("./debugMode");
|
||||
const del = require("del");
|
||||
const needsUpdate = require("./needsUpdate");
|
||||
const mkdirp = require("./mkdirp");
|
||||
const { reportDiagnostics } = require("./diagnostics");
|
||||
const { PassThrough } = require("stream");
|
||||
|
||||
module.exports = exports = project;
|
||||
class CompilationGulp extends gulp.Gulp {
|
||||
/**
|
||||
* @param {import("gulp-help").GulpHelp | import("gulp").Gulp} gulp
|
||||
*/
|
||||
constructor(gulp) {
|
||||
super();
|
||||
// forward notifications to the outer gulp.
|
||||
this.on("task_start", e => gulp.emit("task_start", e));
|
||||
this.on("task_stop", e => gulp.emit("task_stop", e));
|
||||
this.on("task_err", e => gulp.emit("task_err", e));
|
||||
this.on("task_not_found", e => gulp.emit("task_not_found", e));
|
||||
this.on("task_recursion", e => gulp.emit("task_recursion", e));
|
||||
this.on("err", e => gulp.emit("err", e));
|
||||
}
|
||||
|
||||
/** @type {Map<string, Map<string, ResolvedProject>>} */
|
||||
const typescriptProjects = new Map();
|
||||
|
||||
/** @type {Record<string, { typescript: string, deps?: string[] }>} */
|
||||
const typescriptRegistry = { };
|
||||
|
||||
/**
|
||||
* Defines a series of gulp tasks for a TypeScript project, returning the root task name.
|
||||
* @param {string} projectSpec
|
||||
* @param {ProjectOptions} [options]
|
||||
* @param {(project: ParsedCommandLine, destPath: string, options: ResolvedProjectOptions) => NodeJS.ReadWriteStream} [task]
|
||||
*/
|
||||
function project(projectSpec, options, task) {
|
||||
return makeProject(projectSpec, resolveProjectOptions(options), /*referer*/ undefined, task).taskName;
|
||||
dispose() {
|
||||
this.removeAllListeners();
|
||||
this.reset();
|
||||
}
|
||||
|
||||
// Do not reset tasks when `gulp.start()` is called
|
||||
_resetAllTasks() {}
|
||||
_resetSpecificTasks() {}
|
||||
_resetTask() {}
|
||||
}
|
||||
exports.project = project;
|
||||
|
||||
// internal `Gulp` instance for compilation artifacts.
|
||||
const compilationGulp = new CompilationGulp(gulp);
|
||||
|
||||
/** @type {Map<ResolvedProjectSpec, ProjectGraph>} */
|
||||
const projectGraphCache = new Map();
|
||||
|
||||
/** @type {Map<string, { typescript: string, alias: string, paths: ResolvedPathOptions }>} */
|
||||
const typescriptAliasMap = new Map();
|
||||
|
||||
/**
|
||||
* Defines a deferred gulp pipeline for a TypeScript project.
|
||||
* @param {string} projectSpec
|
||||
* @param {ProjectOptions} [options]
|
||||
* @param {(project: ParsedCommandLine, destPath: string, options: ResolvedProjectOptions) => NodeJS.ReadWriteStream} [task]
|
||||
* Defines a gulp orchestration for a TypeScript project, returning a callback that can be used to trigger compilation.
|
||||
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
|
||||
* @param {ProjectOptions} [options] Project compilation options.
|
||||
* @returns {() => Promise<void>}
|
||||
*/
|
||||
function defer(projectSpec, options, task) {
|
||||
function createCompiler(projectSpec, options) {
|
||||
const resolvedOptions = resolveProjectOptions(options);
|
||||
resolvedOptions.defer = true;
|
||||
const resolvedProject = prepareProject(projectSpec, resolvedOptions, /*referer*/ undefined, task);
|
||||
return getProjectTaskFunction(resolvedProject);
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec, resolvedOptions.paths, /*referrer*/ undefined);
|
||||
const taskName = compileTaskName(ensureCompileTask(getOrCreateProjectGraph(resolvedProjectSpec, resolvedOptions.paths), resolvedOptions), resolvedOptions.typescript);
|
||||
return () => new Promise((resolve, reject) => compilationGulp.start(taskName, err => err ? reject(err) : resolve(err)));
|
||||
}
|
||||
exports.defer = defer;
|
||||
exports.createCompiler = createCompiler;
|
||||
|
||||
/**
|
||||
* Defines a series of gulp tasks to clean the outputs of a TypeScript project, returning the root task name.
|
||||
* @param {string} projectSpec
|
||||
* @param {CleanOptions} [options]
|
||||
* Defines and executes a gulp orchestration for a TypeScript project.
|
||||
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
|
||||
* @param {ProjectOptions} [options] Project compilation options.
|
||||
* @returns {Promise<void>}
|
||||
*
|
||||
* @typedef ProjectOptions
|
||||
* @property {string} [cwd] The path to use for the current working directory. Defaults to `process.cwd()`.
|
||||
* @property {string} [base] The path to use as the base for relative paths. Defaults to `cwd`.
|
||||
* @property {string} [typescript] A module specifier or path (relative to gulpfile.js) to the version of TypeScript to use.
|
||||
* @property {Hook} [js] Pipeline hook for .js file outputs. For multiple steps, use `stream-combiner`.
|
||||
* @property {Hook} [dts] Pipeline hook for .d.ts file outputs. For multiple steps, use `stream-combiner`.
|
||||
* @property {boolean} [verbose] Indicates whether verbose logging is enabled.
|
||||
* @property {boolean} [force] Force recompilation (no up-to-date check).
|
||||
* @property {boolean} [inProcess] Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
*
|
||||
* @typedef {NodeJS.ReadWriteStream | (() => NodeJS.ReadWriteStream)} Hook
|
||||
*/
|
||||
function compile(projectSpec, options) {
|
||||
const compiler = createCompiler(projectSpec, options);
|
||||
return compiler();
|
||||
}
|
||||
exports.compile = compile;
|
||||
|
||||
/**
|
||||
* Defines a gulp orchestration to clean the outputs of a TypeScript project, returning a callback that can be used to trigger compilation.
|
||||
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
|
||||
* @param {PathOptions} [options] Project clean options.
|
||||
*/
|
||||
function createCleaner(projectSpec, options) {
|
||||
const paths = resolvePathOptions(options);
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec, paths, /*referrer*/ undefined);
|
||||
const taskName = cleanTaskName(ensureCleanTask(getOrCreateProjectGraph(resolvedProjectSpec, paths)));
|
||||
return () => new Promise((resolve, reject) => compilationGulp.start(taskName, err => err ? reject(err) : resolve(err)));
|
||||
}
|
||||
exports.createCleaner = createCleaner;
|
||||
|
||||
/**
|
||||
* Defines and executes a gulp orchestration to clean the outputs of a TypeScript project.
|
||||
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
|
||||
* @param {PathOptions} [options] Project clean options.
|
||||
*/
|
||||
function clean(projectSpec, options) {
|
||||
return makeClean(projectSpec, resolveCleanOptions(options), /*referer*/ undefined);
|
||||
const cleaner = createCleaner(projectSpec, options);
|
||||
return cleaner();
|
||||
}
|
||||
exports.clean = clean;
|
||||
|
||||
/**
|
||||
* Defines the default task behavior.
|
||||
* @param {ParsedCommandLine} parsedProject
|
||||
* @param {string} destPath
|
||||
* @param {ResolvedTaskConfiguration} options
|
||||
*/
|
||||
function defaultTask(parsedProject, destPath, options) {
|
||||
const { sourceMap, inlineSourceMap, inlineSources = false, sourceRoot, declarationMap } = parsedProject.options;
|
||||
const configFilePath = parsedProject.options.configFilePath;
|
||||
const sourceMapPath = inlineSourceMap ? undefined : ".";
|
||||
const sourceMapOptions = { includeContent: inlineSources, sourceRoot, destPath };
|
||||
const project = options.inProcess
|
||||
? tsc.createProject(configFilePath, Object.assign({}, options.compilerOptions, { typescript: require(options.typescript)}))
|
||||
: tsc_oop.createProject(configFilePath, Object.assign({}, options.compilerOptions), { typescript: options.typescript });
|
||||
const stream = project.src()
|
||||
.pipe(gulpif(!options.force, upToDate(parsedProject, { verbose: options.verbose })))
|
||||
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.init()))
|
||||
.pipe(project());
|
||||
const js = stream.js
|
||||
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
|
||||
const dts = stream.dts
|
||||
.pipe(gulpif(declarationMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
|
||||
return merge2([options.js ? options.js(js) : js, options.dts ? options.dts(dts) : dts])
|
||||
.pipe(gulp.dest(destPath));
|
||||
}
|
||||
exports.defaultTask = defaultTask;
|
||||
|
||||
/**
|
||||
* Adds a named alias for a TypeScript language service path
|
||||
* @param {string} alias
|
||||
* @param {string} typescript
|
||||
* @param {string[]} [deps]
|
||||
* @param {string} alias An alias for a TypeScript version.
|
||||
* @param {string} typescript An alias or module specifier for a TypeScript version.
|
||||
* @param {PathOptions} [options] Options used to resolve the path to `typescript`.
|
||||
*/
|
||||
function addTypeScript(alias, typescript, deps) {
|
||||
typescriptRegistry[alias] = { typescript, deps };
|
||||
function addTypeScript(alias, typescript, options) {
|
||||
const paths = resolvePathOptions(options);
|
||||
typescriptAliasMap.set(alias, { typescript, alias, paths });
|
||||
}
|
||||
exports.addTypeScript = addTypeScript;
|
||||
|
||||
/**
|
||||
* Flattens a project with project references into a single project.
|
||||
* @param {string} projectSpec
|
||||
* @param {string} flattenedProjectSpec
|
||||
* @param {FlattenOptions} [options]
|
||||
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
|
||||
* @param {string} flattenedProjectSpec The output path for the flattened tsconfig.json file.
|
||||
* @param {FlattenOptions} [options] Options used to flatten a project hierarchy.
|
||||
*
|
||||
* @typedef FlattenOptions
|
||||
* @property {string} [cwd] The path to use for the current working directory. Defaults to `process.cwd()`.
|
||||
* @property {CompilerOptions} [compilerOptions] Compiler option overrides.
|
||||
* @property {boolean} [force] Forces creation of the output project.
|
||||
*/
|
||||
function flatten(projectSpec, flattenedProjectSpec, options = {}) {
|
||||
const paths = resolvePathOptions(options);
|
||||
const files = [];
|
||||
const resolvedOutputSpec = path.resolve(flattenedProjectSpec);
|
||||
const resolvedOutputSpec = path.resolve(paths.cwd, flattenedProjectSpec);
|
||||
const resolvedOutputDirectory = path.dirname(resolvedOutputSpec);
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec);
|
||||
const parsedProject = ts.getParsedCommandLineOfConfigFile(resolvedProjectSpec, {}, parseConfigFileHost);
|
||||
recur(parsedProject);
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec, paths, /*referrer*/ undefined);
|
||||
const projectGraph = getOrCreateProjectGraph(resolvedProjectSpec, paths);
|
||||
recur(projectGraph);
|
||||
|
||||
const config = {
|
||||
extends: normalizeSlashes(path.relative(resolvedOutputDirectory, resolvedProjectSpec)),
|
||||
@@ -123,418 +156,384 @@ function flatten(projectSpec, flattenedProjectSpec, options = {}) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedCommandLine} parsedProject
|
||||
* @param {ProjectGraph} projectGraph
|
||||
*/
|
||||
function recur(parsedProject) {
|
||||
if (parsedProject.projectReferences) {
|
||||
for (const ref of parsedProject.projectReferences) {
|
||||
const resolvedProjectSpec = resolveProjectSpec(ref.path, parsedProject);
|
||||
const referencedProject = ts.getParsedCommandLineOfConfigFile(resolvedProjectSpec, {}, parseConfigFileHost);
|
||||
recur(referencedProject);
|
||||
}
|
||||
function recur(projectGraph) {
|
||||
for (const ref of projectGraph.references) {
|
||||
recur(ref.target);
|
||||
}
|
||||
for (const file of parsedProject.fileNames) {
|
||||
files.push(normalizeSlashes(path.relative(resolvedOutputDirectory, path.resolve(file))));
|
||||
for (const file of projectGraph.project.fileNames) {
|
||||
files.push(normalizeSlashes(path.relative(resolvedOutputDirectory, path.resolve(projectGraph.projectDirectory, file))));
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.flatten = flatten;
|
||||
|
||||
/**
|
||||
* @param {string} typescript
|
||||
* Resolve a TypeScript specifier into a fully-qualified module specifier and any requisite dependencies.
|
||||
* @param {string} typescript An unresolved module specifier to a TypeScript version.
|
||||
* @param {ResolvedPathOptions} paths Paths used to resolve `typescript`.
|
||||
* @returns {ResolvedTypeScript}
|
||||
*
|
||||
* @typedef {string & {_isResolvedTypeScript: never}} ResolvedTypeScriptSpec
|
||||
*
|
||||
* @typedef ResolvedTypeScript
|
||||
* @property {ResolvedTypeScriptSpec} typescript
|
||||
* @property {string} [alias]
|
||||
*/
|
||||
function resolveTypeScript(typescript) {
|
||||
/** @type {string[] | undefined} */
|
||||
let deps;
|
||||
while (typescript in typescriptRegistry) {
|
||||
const entry = typescriptRegistry[typescript];
|
||||
typescript = entry.typescript;
|
||||
if (!deps) deps = entry.deps;
|
||||
function resolveTypeScript(typescript, paths) {
|
||||
let alias;
|
||||
while (typescriptAliasMap.has(typescript)) {
|
||||
({ typescript, alias, paths } = typescriptAliasMap.get(typescript));
|
||||
}
|
||||
|
||||
if (typescript === "default") {
|
||||
typescript = require.resolve("../../lib/typescript");
|
||||
}
|
||||
else if (isPath(typescript)) {
|
||||
typescript = path.resolve(process.cwd(), typescript);
|
||||
typescript = path.resolve(paths.cwd, typescript);
|
||||
}
|
||||
|
||||
return { typescript, deps };
|
||||
return { typescript: /**@type {ResolvedTypeScriptSpec}*/(normalizeSlashes(typescript)), alias };
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a suffix to append to Gulp task names that vary by TypeScript version.
|
||||
* @param {ResolvedTypeScript} typescript A resolved module specifier to a TypeScript version.
|
||||
* @param {ResolvedPathOptions} paths Paths used to resolve a relative reference to `typescript`.
|
||||
*/
|
||||
function getTaskNameSuffix(typescript, paths) {
|
||||
return typescript.typescript === resolveTypeScript("default", paths).typescript ? "" :
|
||||
typescript.alias ? `@${typescript.alias}` :
|
||||
isPath(typescript.typescript) ? `@${normalizeSlashes(path.relative(paths.base, typescript.typescript))}` :
|
||||
`@${typescript}`;
|
||||
}
|
||||
|
||||
/** @type {ResolvedPathOptions} */
|
||||
const defaultPaths = { cwd: process.cwd(), base: process.cwd() };
|
||||
|
||||
/**
|
||||
* @param {PathOptions | undefined} options Path options to resolve and normalize.
|
||||
* @returns {ResolvedPathOptions}
|
||||
*
|
||||
* @typedef PathOptions
|
||||
* @property {string} [cwd] The path to use for the current working directory. Defaults to `process.cwd()`.
|
||||
* @property {string} [base] The path to use as the base for relative paths. Defaults to `cwd`.
|
||||
*
|
||||
* @typedef ResolvedPathOptions
|
||||
* @property {string} cwd The path to use for the current working directory. Defaults to `process.cwd()`.
|
||||
* @property {string} base The path to use as the base for relative paths. Defaults to `cwd`.
|
||||
*/
|
||||
function resolvePathOptions(options) {
|
||||
const cwd = options && options.cwd ? path.resolve(process.cwd(), options.cwd) : process.cwd();
|
||||
const base = options && options.base ? path.resolve(cwd, options.base) : cwd;
|
||||
return cwd === defaultPaths.cwd && base === defaultPaths.base ? defaultPaths : { cwd, base };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ProjectOptions} [options]
|
||||
* @returns {ResolvedProjectOptions}
|
||||
*
|
||||
* @typedef ResolvedProjectOptions
|
||||
* @property {ResolvedPathOptions} paths
|
||||
* @property {ResolvedTypeScript} typescript A resolved reference to a TypeScript implementation.
|
||||
* @property {Hook} [js] Pipeline hook for .js file outputs.
|
||||
* @property {Hook} [dts] Pipeline hook for .d.ts file outputs.
|
||||
* @property {boolean} [verbose] Indicates whether verbose logging is enabled.
|
||||
* @property {boolean} [force] Force recompilation (no up-to-date check).
|
||||
* @property {boolean} [inProcess] Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
*/
|
||||
function resolveProjectOptions(options = {}) {
|
||||
const resolvedTypeScript = resolveTypeScript(options.typescript || "default");
|
||||
const paths = resolvePathOptions(options);
|
||||
const typescript = resolveTypeScript(options.typescript || "default", paths);
|
||||
return {
|
||||
typescript: resolvedTypeScript.typescript,
|
||||
deps: concat(options.deps, resolvedTypeScript.deps),
|
||||
compilerOptions: options.compilerOptions || {},
|
||||
paths,
|
||||
typescript,
|
||||
js: options.js,
|
||||
dts: options.dts,
|
||||
debug: resolveProjectConfiguration(options.debug),
|
||||
release: resolveProjectConfiguration(options.release),
|
||||
verbose: options.verbose || false,
|
||||
force: options.force || false,
|
||||
inProcess: options.inProcess || false,
|
||||
defer: false
|
||||
inProcess: options.inProcess || false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CleanOptions} [options]
|
||||
* @returns {ResolvedCleanOptions}
|
||||
* @param {Hook} hook
|
||||
* @returns {NodeJS.ReadWriteStream}
|
||||
*/
|
||||
function resolveCleanOptions(options = {}) {
|
||||
const resolvedTypeScript = resolveTypeScript(options.typescript || "default");
|
||||
return { typescript: resolvedTypeScript.typescript };
|
||||
function evaluateHook(hook) {
|
||||
return (typeof hook === "function" ? hook() : hook) || new PassThrough({ objectMode: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ProjectConfiguration} [config]
|
||||
* @returns {ResolvedProjectConfiguration}
|
||||
* @param {ResolvedProjectOptions} left
|
||||
* @param {ResolvedProjectOptions} right
|
||||
* @returns {ResolvedProjectOptions}
|
||||
*/
|
||||
function resolveProjectConfiguration(config = {}) {
|
||||
function mergeProjectOptions(left, right) {
|
||||
if (left.typescript !== right.typescript) throw new Error("Cannot merge project options targeting different TypeScript packages");
|
||||
if (tryReuseProjectOptions(left, right)) return left;
|
||||
return {
|
||||
compilerOptions: config.compilerOptions || {},
|
||||
deps: config.deps,
|
||||
js: config.js,
|
||||
dts: config.dts,
|
||||
force: config.force,
|
||||
inProcess: config.inProcess
|
||||
paths: left.paths,
|
||||
typescript: left.typescript,
|
||||
js: right.js || left.js,
|
||||
dts: right.dts || left.dts,
|
||||
verbose: right.verbose || left.verbose,
|
||||
force: right.force || left.force,
|
||||
inProcess: right.inProcess || left.inProcess
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProjectOptions} a
|
||||
* @param {ResolvedProjectOptions} b
|
||||
* @param {ResolvedProjectOptions} left
|
||||
* @param {ResolvedProjectOptions} right
|
||||
*/
|
||||
function mergeProjectOptions(a, b) {
|
||||
return {
|
||||
typescript: a.typescript || b.typescript,
|
||||
deps: distinct(concat(a.deps, b.deps)),
|
||||
compilerOptions: Object.assign({}, a.compilerOptions, b.compilerOptions),
|
||||
js: b.js || a.js,
|
||||
dts: b.dts || a.dts,
|
||||
debug: mergeProjectConfigurations(a.debug, b.debug),
|
||||
release: mergeProjectConfigurations(a.release, b.release),
|
||||
verbose: b.verbose || a.verbose,
|
||||
force: b.force || a.force,
|
||||
inProcess: b.inProcess || a.inProcess,
|
||||
defer: a.defer || b.defer
|
||||
};
|
||||
function tryReuseProjectOptions(left, right) {
|
||||
return left === right
|
||||
|| left.js === (right.js || left.js)
|
||||
&& left.dts === (right.dts || left.dts)
|
||||
&& !left.verbose === !(right.verbose || left.verbose)
|
||||
&& !left.force === !(right.force || left.force)
|
||||
&& !left.inProcess === !(right.inProcess || left.inProcess);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProjectConfiguration} a
|
||||
* @param {ResolvedProjectConfiguration} b
|
||||
* @param {ResolvedProjectSpec} projectSpec
|
||||
* @param {ResolvedPathOptions} paths
|
||||
* @returns {UnqualifiedProjectName}
|
||||
*
|
||||
* @typedef {string & {_isUnqualifiedProjectName:never}} UnqualifiedProjectName
|
||||
*/
|
||||
function mergeProjectConfigurations(a, b) {
|
||||
return {
|
||||
compilerOptions: Object.assign({}, a.compilerOptions, b.compilerOptions),
|
||||
deps: concat(a.deps, b.deps),
|
||||
js: b.js || a.js,
|
||||
dts: b.dts || a.dts,
|
||||
force: b.force !== undefined ? b.force : a.force,
|
||||
inProcess: b.inProcess !== undefined ? b.inProcess : a.inProcess
|
||||
};
|
||||
function getUnqualifiedProjectName(projectSpec, paths) {
|
||||
return /**@type {UnqualifiedProjectName}*/(normalizeSlashes(path.relative(paths.base, projectSpec)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProjectOptions} options
|
||||
* @returns {ResolvedTaskConfiguration}
|
||||
* @param {UnqualifiedProjectName} projectName
|
||||
* @param {ResolvedPathOptions} paths
|
||||
* @param {ResolvedTypeScript} typescript
|
||||
* @returns {QualifiedProjectName}
|
||||
*
|
||||
* @typedef {string & {_isQualifiedProjectName:never}} QualifiedProjectName
|
||||
*/
|
||||
function getResolvedTaskConfiguration(options) {
|
||||
const config = debugMode.useDebugMode ? options.debug : options.release
|
||||
return {
|
||||
typescript: options.typescript,
|
||||
compilerOptions: Object.assign({}, options.compilerOptions, config.compilerOptions),
|
||||
deps: concat(options.deps, config.deps),
|
||||
dts: config.dts || options.dts,
|
||||
js: config.js || options.js,
|
||||
verbose: options.verbose,
|
||||
force: config.force !== undefined ? config.force : options.force,
|
||||
inProcess: config.inProcess !== undefined ? config.inProcess : options.inProcess
|
||||
};
|
||||
function getQualifiedProjectName(projectName, paths, typescript) {
|
||||
return /**@type {QualifiedProjectName}*/(projectName + getTaskNameSuffix(typescript, paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T[] | undefined} a
|
||||
* @param {T[] | undefined} b
|
||||
* @returns {T[] | undefined}
|
||||
/**
|
||||
* @typedef {import("../../lib/typescript").ParseConfigFileHost} ParseConfigFileHost
|
||||
* @type {ParseConfigFileHost}
|
||||
*/
|
||||
function concat(a, b) {
|
||||
return a ? b ? a.concat(b) : a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T[] | undefined} ar
|
||||
* @returns {T[] | undefined}
|
||||
*/
|
||||
|
||||
function distinct(ar) {
|
||||
return ar && [...new Set(ar)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} projectSpec
|
||||
* @param {ResolvedProjectOptions} resolvedOptions
|
||||
* @param {ParsedCommandLine} [referer]
|
||||
* @param {Task} [task]
|
||||
*/
|
||||
function prepareProject(projectSpec, resolvedOptions, referer, task) {
|
||||
const resolvedProject = resolveProject(projectSpec, resolvedOptions, referer);
|
||||
if (resolvedProject.resolvedOptions !== resolvedOptions) {
|
||||
resolvedProject.resolvedOptions = mergeProjectOptions(resolvedProject.resolvedOptions, resolvedOptions);
|
||||
}
|
||||
if (task) resolvedProject.task = task;
|
||||
return resolvedProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} projectSpec
|
||||
* @param {ResolvedProjectOptions} resolvedOptions
|
||||
* @param {ParsedCommandLine} [referer]
|
||||
* @param {Task} [task]
|
||||
*/
|
||||
function makeProject(projectSpec, resolvedOptions, referer, task) {
|
||||
const resolvedProject = prepareProject(projectSpec, resolvedOptions, referer, task);
|
||||
if (!resolvedProject.projectTaskCreated || resolvedProject.task) {
|
||||
createProjectTask(resolvedProject);
|
||||
}
|
||||
return resolvedProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} projectSpec
|
||||
* @param {ResolvedCleanOptions} resolvedOptions
|
||||
* @param {ParsedCommandLine} [referer]
|
||||
*/
|
||||
function makeClean(projectSpec, resolvedOptions, referer) {
|
||||
const projects = getProjects(resolvedOptions);
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec, referer, projects);
|
||||
const resolvedProject = projects.get(resolvedProjectSpec);
|
||||
if (!resolvedProject) throw new PluginError("clean", `Project not found: '${projectSpec}'. Add project via 'project()' first.`);
|
||||
if (!resolvedProject.cleanTaskCreated) {
|
||||
createCleanTask(resolvedProject);
|
||||
}
|
||||
return "clean:" + resolvedProject.projectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProjectOptions | ResolvedCleanOptions} resolvedOptions
|
||||
*/
|
||||
function getProjects(resolvedOptions) {
|
||||
let projects = typescriptProjects.get(resolvedOptions.typescript);
|
||||
if (!projects) typescriptProjects.set(resolvedOptions.typescript, projects = new Map());
|
||||
return projects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} resolvedProjectSpec
|
||||
* @param {ResolvedProjectOptions} resolvedOptions
|
||||
*/
|
||||
function getProjectName(resolvedProjectSpec, resolvedOptions) {
|
||||
let projectName = path.relative(process.cwd(), resolvedProjectSpec);
|
||||
if (resolvedOptions.typescript !== resolveTypeScript("default").typescript) {
|
||||
projectName += `@${isPath(resolvedOptions.typescript) ? path.relative(process.cwd(), resolvedOptions.typescript) : resolvedOptions.typescript}`;
|
||||
}
|
||||
return normalizeSlashes(projectName);
|
||||
}
|
||||
|
||||
/** @type {FormatDiagnosticsHost} */
|
||||
const formatDiagnosticsHost = {
|
||||
getCanonicalFileName: fileName => fileName,
|
||||
getCurrentDirectory: () => process.cwd(),
|
||||
getNewLine: () => ts.sys.newLine
|
||||
};
|
||||
|
||||
/** @type {ParseConfigFileHost} */
|
||||
const parseConfigFileHost = {
|
||||
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
|
||||
fileExists: fileName => ts.sys.fileExists(fileName),
|
||||
readFile: fileName => ts.sys.readFile(fileName),
|
||||
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
|
||||
getCurrentDirectory: () => process.cwd(),
|
||||
readDirectory: (rootDir, extensions, exclude, include, depth) => ts.sys.readDirectory(rootDir, extensions, exclude, include, depth),
|
||||
onUnRecoverableConfigFileDiagnostic: diagnostic => {
|
||||
log.warn(ts.formatDiagnosticsWithColorAndContext([diagnostic], formatDiagnosticsHost));
|
||||
}
|
||||
onUnRecoverableConfigFileDiagnostic: diagnostic => reportDiagnostics([diagnostic])
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} projectSpec
|
||||
* @param {ResolvedProjectOptions} resolvedOptions
|
||||
* @param {ParsedCommandLine} [referer]
|
||||
* @param {string} [cwd]
|
||||
* @returns {ParseConfigFileHost}
|
||||
*/
|
||||
function resolveProject(projectSpec, resolvedOptions, referer) {
|
||||
const projects = getProjects(resolvedOptions);
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectSpec, referer, projects);
|
||||
let resolvedProject = projects.get(resolvedProjectSpec);
|
||||
if (!resolvedProject) {
|
||||
const projectName = getProjectName(resolvedProjectSpec, resolvedOptions);
|
||||
resolvedProject = {
|
||||
resolvedProjectSpec,
|
||||
projectName,
|
||||
taskName: "project:" + projectName,
|
||||
parsedProject: undefined,
|
||||
resolvedOptions,
|
||||
destPath: undefined,
|
||||
projectTaskCreated: false,
|
||||
cleanTaskCreated: false,
|
||||
task: undefined,
|
||||
projectTask: undefined
|
||||
function getParseConfigFileHost(cwd) {
|
||||
if (!cwd || cwd === process.cwd()) return parseConfigFileHost;
|
||||
return {
|
||||
useCaseSensitiveFileNames: parseConfigFileHost.useCaseSensitiveFileNames,
|
||||
fileExists: parseConfigFileHost.fileExists,
|
||||
readFile: parseConfigFileHost.readFile,
|
||||
getCurrentDirectory: () => cwd,
|
||||
readDirectory: parseConfigFileHost.readDirectory,
|
||||
onUnRecoverableConfigFileDiagnostic: diagnostic => reportDiagnostics([diagnostic], { cwd })
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProjectSpec} projectSpec
|
||||
* @param {ResolvedPathOptions} paths
|
||||
* @returns {ProjectGraph}
|
||||
*
|
||||
* @typedef ProjectGraph
|
||||
* @property {ResolvedProjectSpec} projectSpec The fully qualified path to the tsconfig.json of the project
|
||||
* @property {UnqualifiedProjectName} projectName The relative project name, excluding any TypeScript suffix.
|
||||
* @property {string} projectDirectory The fully qualified path to the project directory.
|
||||
* @property {ParsedCommandLine} project The parsed tsconfig.json file.
|
||||
* @property {ProjectGraphReference[]} references An array of project references.
|
||||
* @property {Map<ResolvedTypeScriptSpec, ProjectGraphConfiguration>} configurations TypeScript-specific configurations for the project.
|
||||
* @property {boolean} cleanTaskCreated A value indicating whether a `clean:` task has been created for this project (not dependent on TypeScript version).
|
||||
*
|
||||
* @typedef ProjectGraphReference
|
||||
* @property {ProjectGraph} source The referring project.
|
||||
* @property {ProjectGraph} target The referenced project.
|
||||
*/
|
||||
function getOrCreateProjectGraph(projectSpec, paths) {
|
||||
let projectGraph = projectGraphCache.get(projectSpec);
|
||||
if (!projectGraph) {
|
||||
const project = ts.getParsedCommandLineOfConfigFile(projectSpec, {}, getParseConfigFileHost(paths.cwd));
|
||||
projectGraph = {
|
||||
projectSpec,
|
||||
projectName: getUnqualifiedProjectName(projectSpec, paths),
|
||||
projectDirectory: path.dirname(projectSpec),
|
||||
project,
|
||||
references: [],
|
||||
configurations: new Map(),
|
||||
cleanTaskCreated: false
|
||||
};
|
||||
if (!resolvedOptions.defer) {
|
||||
getParsedProject(resolvedProject);
|
||||
getDestPath(resolvedProject);
|
||||
projectGraphCache.set(projectSpec, projectGraph);
|
||||
if (project.projectReferences) {
|
||||
for (const projectReference of project.projectReferences) {
|
||||
const resolvedProjectSpec = resolveProjectSpec(projectReference.path, paths, projectGraph);
|
||||
const referencedProject = getOrCreateProjectGraph(resolvedProjectSpec, paths);
|
||||
const reference = { source: projectGraph, target: referencedProject };
|
||||
projectGraph.references.push(reference);
|
||||
}
|
||||
}
|
||||
projects.set(resolvedProjectSpec, resolvedProject);
|
||||
}
|
||||
return resolvedProject;
|
||||
return projectGraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProject} resolvedProject
|
||||
* @param {ProjectGraph} projectGraph
|
||||
* @param {ResolvedProjectOptions} resolvedOptions
|
||||
* @returns {ProjectGraphConfiguration}
|
||||
*
|
||||
* @typedef ProjectGraphConfiguration
|
||||
* @property {QualifiedProjectName} projectName
|
||||
* @property {ResolvedProjectOptions} resolvedOptions
|
||||
* @property {boolean} compileTaskCreated
|
||||
*/
|
||||
function getParsedProject(resolvedProject) {
|
||||
if (!resolvedProject.parsedProject) {
|
||||
resolvedProject.parsedProject = ts.getParsedCommandLineOfConfigFile(
|
||||
resolvedProject.resolvedProjectSpec,
|
||||
resolvedProject.resolvedOptions.compilerOptions,
|
||||
parseConfigFileHost);
|
||||
function getOrCreateProjectGraphConfiguration(projectGraph, resolvedOptions) {
|
||||
let projectGraphConfig = projectGraph.configurations.get(resolvedOptions.typescript.typescript);
|
||||
if (!projectGraphConfig) {
|
||||
projectGraphConfig = {
|
||||
projectName: getQualifiedProjectName(projectGraph.projectName, resolvedOptions.paths, resolvedOptions.typescript),
|
||||
resolvedOptions,
|
||||
compileTaskCreated: false
|
||||
};
|
||||
projectGraph.configurations.set(resolvedOptions.typescript.typescript, projectGraphConfig);
|
||||
}
|
||||
return resolvedProject.parsedProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProject} resolvedProject
|
||||
*/
|
||||
function getDestPath(resolvedProject) {
|
||||
if (!resolvedProject.destPath) {
|
||||
resolvedProject.destPath = resolveDestPath(getParsedProject(resolvedProject));
|
||||
}
|
||||
return resolvedProject.destPath;
|
||||
return projectGraphConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} projectSpec
|
||||
* @param {ParsedCommandLine} [referer]
|
||||
* @param {Map<string, ResolvedProject>} [projects]
|
||||
* @param {ResolvedPathOptions} paths
|
||||
* @param {ProjectGraph | undefined} referrer
|
||||
* @returns {ResolvedProjectSpec}
|
||||
*
|
||||
* @typedef {string & {_isResolvedProjectSpec: never}} ResolvedProjectSpec
|
||||
*/
|
||||
function resolveProjectSpec(projectSpec, referer, projects) {
|
||||
projectSpec = referer ? path.resolve(path.dirname(referer.options.configFilePath), projectSpec) : path.resolve(projectSpec);
|
||||
projectSpec = normalizeSlashes(projectSpec);
|
||||
|
||||
// quick checks for existing project in cache
|
||||
if (projects && projects.has(projectSpec)) return projectSpec;
|
||||
|
||||
const configSpec = normalizeSlashes(path.join(projectSpec, "tsconfig.json"));
|
||||
if (projects && projects.has(configSpec)) return configSpec;
|
||||
|
||||
// slower checks against file system
|
||||
if (fs.existsSync(projectSpec) && fs.statSync(projectSpec).isDirectory()) {
|
||||
return configSpec;
|
||||
}
|
||||
|
||||
return projectSpec;
|
||||
function resolveProjectSpec(projectSpec, paths, referrer) {
|
||||
projectSpec = path.resolve(paths.cwd, referrer && referrer.projectDirectory || "", projectSpec);
|
||||
if (!ts.sys.fileExists(projectSpec)) projectSpec = path.join(projectSpec, "tsconfig.json");
|
||||
return /**@type {ResolvedProjectSpec}*/(normalizeSlashes(projectSpec));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedCommandLine} parsedProject
|
||||
* @param {ProjectGraph} projectGraph
|
||||
* @param {ResolvedPathOptions} paths
|
||||
*/
|
||||
function resolveDestPath(parsedProject) {
|
||||
function resolveDestPath(projectGraph, paths) {
|
||||
/** @type {string} */
|
||||
let destPath = path.dirname(parsedProject.options.configFilePath);
|
||||
if (parsedProject.options.outDir) {
|
||||
destPath = path.resolve(destPath, parsedProject.options.outDir);
|
||||
let destPath = projectGraph.projectDirectory;
|
||||
if (projectGraph.project.options.outDir) {
|
||||
destPath = path.resolve(paths.cwd, destPath, projectGraph.project.options.outDir);
|
||||
}
|
||||
else if (parsedProject.options.outFile || parsedProject.options.out) {
|
||||
destPath = path.dirname(path.resolve(destPath, parsedProject.options.outFile || parsedProject.options.out));
|
||||
else if (projectGraph.project.options.outFile || projectGraph.project.options.out) {
|
||||
destPath = path.dirname(path.resolve(paths.cwd, destPath, projectGraph.project.options.outFile || projectGraph.project.options.out));
|
||||
}
|
||||
return normalizeSlashes(path.relative(process.cwd(), destPath));
|
||||
return normalizeSlashes(path.relative(paths.base, destPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProject} resolvedProject
|
||||
*/
|
||||
function createProjectTask(resolvedProject) {
|
||||
const { parsedProject, resolvedOptions, taskName } = resolvedProject;
|
||||
const deps = makeProjectDeps(parsedProject, resolvedOptions);
|
||||
gulp.task(taskName, /*help*/ false, (resolvedOptions.deps || []).concat(deps), getProjectTaskFunction(resolvedProject));
|
||||
resolvedProject.projectTaskCreated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProject} resolvedProject
|
||||
*/
|
||||
function getProjectTaskFunction(resolvedProject) {
|
||||
if (!resolvedProject.projectTask) {
|
||||
resolvedProject.projectTask = () => (resolvedProject.task || exports.defaultTask)(
|
||||
getParsedProject(resolvedProject),
|
||||
getDestPath(resolvedProject),
|
||||
getResolvedTaskConfiguration(resolvedProject.resolvedOptions));
|
||||
}
|
||||
return resolvedProject.projectTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedCommandLine | undefined} parsedProject
|
||||
* @param {ProjectGraph} projectGraph
|
||||
* @param {ResolvedProjectOptions} resolvedOptions
|
||||
*/
|
||||
function makeProjectDeps(parsedProject, resolvedOptions) {
|
||||
/** @type {string[]} */
|
||||
const deps = [];
|
||||
if (parsedProject && parsedProject.projectReferences) {
|
||||
for (const projectReference of parsedProject.projectReferences) {
|
||||
const projectReferenceOptions = resolveProjectOptions({
|
||||
typescript: resolvedOptions.typescript,
|
||||
deps: resolvedOptions.deps
|
||||
});
|
||||
deps.push(makeProject(projectReference.path, projectReferenceOptions, parsedProject).taskName);
|
||||
}
|
||||
function ensureCompileTask(projectGraph, resolvedOptions) {
|
||||
const projectGraphConfig = getOrCreateProjectGraphConfiguration(projectGraph, resolvedOptions);
|
||||
projectGraphConfig.resolvedOptions = resolvedOptions = mergeProjectOptions(resolvedOptions, resolvedOptions);
|
||||
if (!projectGraphConfig.compileTaskCreated) {
|
||||
const deps = makeProjectReferenceCompileTasks(projectGraph, resolvedOptions.typescript, resolvedOptions.paths);
|
||||
compilationGulp.task(compileTaskName(projectGraph, resolvedOptions.typescript), deps, () => {
|
||||
const destPath = resolveDestPath(projectGraph, resolvedOptions.paths);
|
||||
const { sourceMap, inlineSourceMap, inlineSources = false, sourceRoot, declarationMap } = projectGraph.project.options;
|
||||
const configFilePath = projectGraph.project.options.configFilePath;
|
||||
const sourceMapPath = inlineSourceMap ? undefined : ".";
|
||||
const sourceMapOptions = { includeContent: inlineSources, sourceRoot, destPath };
|
||||
const project = resolvedOptions.inProcess
|
||||
? tsc.createProject(configFilePath, { typescript: require(resolvedOptions.typescript.typescript) })
|
||||
: tsc_oop.createProject(configFilePath, {}, { typescript: resolvedOptions.typescript.typescript });
|
||||
const stream = project.src()
|
||||
.pipe(gulpif(!resolvedOptions.force, upToDate(projectGraph.project, { verbose: resolvedOptions.verbose })))
|
||||
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.init()))
|
||||
.pipe(project());
|
||||
const js = stream.js
|
||||
.pipe(evaluateHook(resolvedOptions.js))
|
||||
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
|
||||
const dts = stream.dts
|
||||
.pipe(evaluateHook(resolvedOptions.dts))
|
||||
.pipe(gulpif(declarationMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
|
||||
return merge2([js, dts])
|
||||
.pipe(gulp.dest(destPath));
|
||||
});
|
||||
projectGraphConfig.compileTaskCreated = true;
|
||||
}
|
||||
return deps;
|
||||
return projectGraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolvedProject} resolvedProject
|
||||
* @param {ProjectGraph} projectGraph
|
||||
* @param {ResolvedTypeScript} typescript
|
||||
* @param {ResolvedPathOptions} paths
|
||||
*/
|
||||
function createCleanTask(resolvedProject) {
|
||||
const { parsedProject, resolvedOptions, projectName } = resolvedProject;
|
||||
const deps = makeCleanDeps(parsedProject, resolvedOptions);
|
||||
gulp.task("clean:" + projectName, /*help*/ false, deps, () => {
|
||||
let outputs = ts.getAllProjectOutputs(parsedProject);
|
||||
if (!parsedProject.options.inlineSourceMap) {
|
||||
if (parsedProject.options.sourceMap) {
|
||||
outputs = outputs.concat(outputs.filter(file => /\.jsx?$/.test(file)).map(file => file + ".map"));
|
||||
}
|
||||
if (parsedProject.options.declarationMap) {
|
||||
outputs = outputs.concat(outputs.filter(file => /\.d.ts$/.test(file)).map(file => file + ".map"));
|
||||
}
|
||||
}
|
||||
return del(outputs);
|
||||
});
|
||||
resolvedProject.cleanTaskCreated = true;
|
||||
function makeProjectReferenceCompileTasks(projectGraph, typescript, paths) {
|
||||
return projectGraph.references.map(({target}) => compileTaskName(ensureCompileTask(target, { paths, typescript }), typescript));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedCommandLine} parsedProject
|
||||
* @param {ResolvedCleanOptions} resolvedOptions
|
||||
* @param {ProjectGraph} projectGraph
|
||||
*/
|
||||
function makeCleanDeps(parsedProject, resolvedOptions) {
|
||||
/** @type {string[]} */
|
||||
const deps = [];
|
||||
if (parsedProject.projectReferences) {
|
||||
for (const projectReference of parsedProject.projectReferences) {
|
||||
const projectReferenceOptions = resolveCleanOptions({ typescript: resolvedOptions.typescript });
|
||||
deps.push(makeClean(projectReference.path, projectReferenceOptions, parsedProject));
|
||||
}
|
||||
function ensureCleanTask(projectGraph) {
|
||||
if (!projectGraph.cleanTaskCreated) {
|
||||
const deps = makeProjectReferenceCleanTasks(projectGraph);
|
||||
compilationGulp.task(cleanTaskName(projectGraph), deps, () => {
|
||||
let outputs = ts.getAllProjectOutputs(projectGraph.project);
|
||||
if (!projectGraph.project.options.inlineSourceMap) {
|
||||
if (projectGraph.project.options.sourceMap) {
|
||||
outputs = outputs.concat(outputs.filter(file => /\.jsx?$/.test(file)).map(file => file + ".map"));
|
||||
}
|
||||
if (projectGraph.project.options.declarationMap) {
|
||||
outputs = outputs.concat(outputs.filter(file => /\.d.ts$/.test(file)).map(file => file + ".map"));
|
||||
}
|
||||
}
|
||||
return del(outputs);
|
||||
});
|
||||
projectGraph.cleanTaskCreated = true;
|
||||
}
|
||||
return deps;
|
||||
return projectGraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ProjectGraph} projectGraph
|
||||
*/
|
||||
function makeProjectReferenceCleanTasks(projectGraph) {
|
||||
return projectGraph.references.map(({target}) => cleanTaskName(ensureCleanTask(target)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ProjectGraph} projectGraph
|
||||
* @param {ResolvedTypeScript} typescript
|
||||
*/
|
||||
function compileTaskName(projectGraph, typescript) {
|
||||
return `compile:${projectGraph.configurations.get(typescript.typescript).projectName}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ProjectGraph} projectGraph
|
||||
*/
|
||||
function cleanTaskName(projectGraph) {
|
||||
return `clean:${projectGraph.projectName}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,83 +554,5 @@ function isPath(moduleSpec) {
|
||||
/**
|
||||
* @typedef {import("../../lib/typescript").ParsedCommandLine & { options: CompilerOptions }} ParsedCommandLine
|
||||
* @typedef {import("../../lib/typescript").CompilerOptions & { configFilePath?: string }} CompilerOptions
|
||||
* @typedef {import("../../lib/typescript").ParseConfigFileHost} ParseConfigFileHost
|
||||
* @typedef {import("../../lib/typescript").FormatDiagnosticsHost} FormatDiagnosticsHost
|
||||
* @typedef {(project: ParsedCommandLine, destPath: string, options: ResolvedTaskConfiguration) => NodeJS.ReadWriteStream} Task
|
||||
*
|
||||
* @typedef ProjectOptions
|
||||
* @property {string} [typescript] A module specifier or path (relative to gulpfile.js) to the version of TypeScript to use.
|
||||
* @property {string[]} [deps] Gulp task dependencies for all tasks created for a project.
|
||||
* @property {CompilerOptions} [compilerOptions] Default options to pass to the compiler.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream} [js] Pipeline hook for .js file outputs.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream} [dts] Pipeline hook for .d.ts file outputs.
|
||||
* @property {ProjectConfiguration} [debug] Project option overrides when building a "debug" build.
|
||||
* @property {ProjectConfiguration} [release] Project option overrides when building a "release" build.
|
||||
* @property {boolean} [verbose] Indicates whether verbose logging is enabled.
|
||||
* @property {boolean} [force] Force recompilation (no up-to-date check).
|
||||
* @property {boolean} [inProcess] Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
*
|
||||
* @typedef ProjectConfiguration
|
||||
* @property {CompilerOptions} [compilerOptions] Default options to pass to the compiler.
|
||||
* @property {string[]} [deps] Gulp task dependencies for all tasks created for a project.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream} [js] Pipeline hook for .js file outputs.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream} [dts] Pipeline hook for .d.ts file outputs.
|
||||
* @property {boolean} [force] Force recompilation (no up-to-date check).
|
||||
* @property {boolean} [inProcess] Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
*
|
||||
* @typedef ResolvedProjectOptions
|
||||
* @property {string} typescript A module specifier or path (relative to gulpfile.js) to the version of TypeScript to use.
|
||||
* @property {CompilerOptions} compilerOptions Default options to pass to the compiler.
|
||||
* @property {string[] | undefined} deps Gulp task dependencies for all tasks created for a project.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream | undefined} js Pipeline hook for .js file outputs.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream | undefined} dts Pipeline hook for .d.ts file outputs.
|
||||
* @property {ResolvedProjectConfiguration} debug Project option overrides when building a "debug" build.
|
||||
* @property {ResolvedProjectConfiguration} release Project option overrides when building a "release" build.
|
||||
* @property {boolean} verbose Indicates whether verbose logging is enabled.
|
||||
* @property {boolean} force Force recompilation (no up-to-date check).
|
||||
* @property {boolean} inProcess Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
* @property {boolean} defer Defer loading the project until later (not supported for projects with project references).
|
||||
*
|
||||
* @typedef ResolvedProjectConfiguration
|
||||
* @property {CompilerOptions} compilerOptions Project configuration overrides to pass to the compiler.
|
||||
* @property {string[] | undefined} deps Gulp task dependencies for all tasks created for a project.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream | undefined} js Pipeline hook for .js file outputs.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream | undefined} dts Pipeline hook for .d.ts file outputs.
|
||||
* @property {boolean | undefined} force Force recompilation (no up-to-date check).
|
||||
* @property {boolean | undefined} inProcess Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
*
|
||||
* @typedef ResolvedTaskConfiguration
|
||||
* @property {string} typescript
|
||||
* @property {CompilerOptions} compilerOptions Project configuration overrides to pass to the compiler.
|
||||
* @property {string[] | undefined} deps Gulp task dependencies for all tasks created for a project.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream | undefined} js Pipeline hook for .js file outputs.
|
||||
* @property {(stream: NodeJS.ReadWriteStream) => NodeJS.ReadWriteStream | undefined} dts Pipeline hook for .d.ts file outputs.
|
||||
* @property {boolean} verbose Indicates whether verbose logging is enabled.
|
||||
* @property {boolean} force Force recompilation (no up-to-date check).
|
||||
* @property {boolean} inProcess Indicates whether to run gulp-typescript in-process or out-of-process (default).
|
||||
*
|
||||
* @typedef ResolvedProject
|
||||
* @property {string} resolvedProjectSpec
|
||||
* @property {string} projectName
|
||||
* @property {string} taskName
|
||||
* @property {ParsedCommandLine | undefined} parsedProject
|
||||
* @property {string | undefined} destPath
|
||||
* @property {ResolvedProjectOptions} resolvedOptions
|
||||
* @property {Task | undefined} task
|
||||
* @property {(() => NodeJS.ReadWriteStream) | undefined} projectTask
|
||||
* @property {boolean} projectTaskCreated
|
||||
* @property {boolean} cleanTaskCreated
|
||||
*
|
||||
* @typedef CleanOptions
|
||||
* @property {string} [typescript] A module specifier or path (relative to gulpfile.js) to the version of TypeScript to use.
|
||||
*
|
||||
* @typedef ResolvedCleanOptions
|
||||
* @property {string | undefined} typescript A module specifier or path (relative to gulpfile.js) to the version of TypeScript to use.
|
||||
*
|
||||
* @typedef FlattenOptions
|
||||
* @property {CompilerOptions} [compilerOptions]
|
||||
* @property {string} [base]
|
||||
* @property {boolean} [force]
|
||||
*/
|
||||
void 0;
|
||||
|
||||
void 0;
|
||||
@@ -3,7 +3,7 @@ const path = require("path");
|
||||
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
|
||||
const ts = require("../../lib/typescript");
|
||||
const { Duplex } = require("stream");
|
||||
const { addColor, color } = require("./colors");
|
||||
const chalk = require("./chalk");
|
||||
const Vinyl = require("vinyl");
|
||||
|
||||
/**
|
||||
@@ -86,7 +86,7 @@ function normalizeSlashes(file) {
|
||||
* @private
|
||||
*/
|
||||
function fileName(file) {
|
||||
return addColor(normalizeSlashes(path.relative(process.cwd(), path.resolve(file))), color.cyan);
|
||||
return chalk.cyan(normalizeSlashes(path.relative(process.cwd(), path.resolve(file))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user