Socket
Socket
Sign inDemoInstall

@rollup/plugin-typescript

Package Overview
Dependencies
Maintainers
4
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rollup/plugin-typescript - npm Package Compare versions

Comparing version 3.1.1 to 4.0.0

27

CHANGELOG.md
# @rollup/plugin-typescript ChangeLog
## v4.0.0
### Bugfixes
- fix: Use builtin extends resolution (#199)
### Features
- feat: Move to BuilderProgram API (#217)
### Breaking Changes
Please see https://github.com/rollup/plugins/pull/217 for more information.
## v3.1.0
_2020-03-05_
_Note: This was a bad release due to breaking changes. v3.1.1 has been published to revert the latest 3.x.x version to a non-breaking state. For the changes in this erroneous version, please use v4.0.0._
### Updates
- test: Add preserveModules test (#234)
- chore: refactor compiler host (#214)
- test: Add test for optional chaining (#207)
- chore: Use typechecking (4bb8753)
## v3.0.0

@@ -4,0 +31,0 @@

630

dist/index.es.js

@@ -1,87 +0,40 @@

import { resolve, win32, posix } from 'path';
import { readFile, readFileSync } from 'fs';
import { resolve, dirname, relative, win32, posix } from 'path';
import { createFilter } from '@rollup/pluginutils';
import * as defaultTs from 'typescript';
import resolveId from 'resolve';
import { readFileSync } from 'fs';
// `Cannot compile modules into 'es6' when targeting 'ES5' or lower.`
const CANNOT_COMPILE_ESM = 1204;
/**
* For each type error reported by Typescript, emit a Rollup warning or error.
* Create a format diagnostics host to use with the Typescript type checking APIs.
* Typescript hosts are used to represent the user's system,
* with an API for checking case sensitivity etc.
* @param compilerOptions Typescript compiler options. Affects functions such as `getNewLine`.
* @see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
*/
function emitDiagnostics(ts, context, host, diagnostics) {
if (!diagnostics)
return;
const { noEmitOnError } = host.getCompilationSettings();
diagnostics
.filter((diagnostic) => diagnostic.code !== CANNOT_COMPILE_ESM)
.forEach((diagnostic) => {
// Build a Rollup warning object from the diagnostics object.
const warning = diagnosticToWarning(ts, host, diagnostic);
// Errors are fatal. Otherwise emit warnings.
if (noEmitOnError && diagnostic.category === ts.DiagnosticCategory.Error) {
context.error(warning);
}
else {
context.warn(warning);
}
});
}
/**
* Converts a Typescript type error into an equivalent Rollup warning object.
*/
function diagnosticToWarning(ts, host, diagnostic) {
const pluginCode = `TS${diagnostic.code}`;
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
// Build a Rollup warning object from the diagnostics object.
const warning = {
pluginCode,
message: `@rollup/plugin-typescript ${pluginCode}: ${message}`
function createFormattingHost(ts, compilerOptions) {
return {
/** Returns the compiler options for the project. */
getCompilationSettings: () => compilerOptions,
/** Returns the current working directory. */
getCurrentDirectory: () => process.cwd(),
/** Returns the string that corresponds with the selected `NewLineKind`. */
getNewLine() {
switch (compilerOptions.newLine) {
case ts.NewLineKind.CarriageReturnLineFeed:
return '\r\n';
case ts.NewLineKind.LineFeed:
return '\n';
default:
return ts.sys.newLine;
}
},
/** Returns a lower case name on case insensitive systems, otherwise the original name. */
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase()
};
if (diagnostic.file) {
// Add information about the file location
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
warning.loc = {
column: character + 1,
line: line + 1,
file: diagnostic.file.fileName
};
if (host) {
// Extract a code frame from Typescript
const formatted = ts.formatDiagnosticsWithColorAndContext([diagnostic], host);
// Typescript only exposes this formatter as a string prefixed with the flattened message.
// We need to remove it here since Rollup treats the properties as separate parts.
let frame = formatted.slice(formatted.indexOf(message) + message.length);
const newLine = host.getNewLine();
if (frame.startsWith(newLine)) {
frame = frame.slice(frame.indexOf(newLine) + newLine.length);
}
warning.frame = frame;
}
}
return warning;
}
/**
* Map of Typescript instances to paths to DocumentRegistries.
*/
const globalRegistryCache = new Map();
/**
* Return a `DocumentRegistry` instance that matches the given Typescript instance
* and working directory. If there is no a pre-existing instance, one will be
* created and set in the map.
*/
function getDocumentRegistry(ts, cwd) {
if (!globalRegistryCache.has(ts)) {
globalRegistryCache.set(ts, new Map());
}
const instanceRegistryCache = globalRegistryCache.get(ts);
if (!instanceRegistryCache.has(cwd)) {
instanceRegistryCache.set(cwd, ts.createDocumentRegistry(ts.sys.useCaseSensitiveFileNames, cwd));
}
return instanceRegistryCache.get(cwd);
}
/**
* Create a helper for resolving modules using Typescript.
* @param host Typescript host that extends `ModuleResolutionHost`
* with methods for sanitizing filenames and getting compiler options.
*/

@@ -91,4 +44,5 @@ function createModuleResolver(ts, host) {

const cache = ts.createModuleResolutionCache(process.cwd(), host.getCanonicalFileName, compilerOptions);
const moduleHost = Object.assign(Object.assign({}, ts.sys), host);
return (moduleName, containingFile) => {
const resolved = ts.nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache);
const resolved = ts.nodeModuleNameResolver(moduleName, containingFile, compilerOptions, moduleHost, cache);
return resolved.resolvedModule;

@@ -98,83 +52,2 @@ };

/**
* Create a language service host to use with the Typescript compiler & type checking APIs.
* @param parsedOptions Parsed options for Typescript.
* @param parsedOptions.options Typescript compiler options. Affects functions such as `getNewLine`.
* @param parsedOptions.fileNames Declaration files to include for typechecking.
* @see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
*/
function createHost(ts, parsedOptions) {
const files = new Map();
/** Get the code stored in a File snapshot. */
function getCode({ file }) {
return file.getText(0, file.getLength());
}
/** @see TypescriptHost.addFile */
function addFile(id, code) {
const existing = files.get(id);
// Don't need to update if nothing changed
if (existing && getCode(existing) === code)
return;
files.set(id, {
file: ts.ScriptSnapshot.fromString(code),
version: existing ? existing.version + 1 : 0
});
}
/** Helper that tries to read the file if it hasn't been stored yet */
function getFile(id) {
if (!files.has(id)) {
const code = ts.sys.readFile(id);
if (code == null) {
throw new Error(`@rollup/plugin-typescript: Could not find ${id}`);
}
addFile(id, code);
}
return files.get(id);
}
parsedOptions.fileNames.forEach((id) => getFile(id));
let resolver;
const host = {
getCompilationSettings: () => parsedOptions.options,
getCurrentDirectory: () => process.cwd(),
getNewLine: () => getNewLine(ts, parsedOptions.options.newLine),
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
getDefaultLibFileName: ts.getDefaultLibFilePath,
getDirectories: ts.sys.getDirectories,
directoryExists: ts.sys.directoryExists,
realpath: ts.sys.realpath,
readDirectory: ts.sys.readDirectory,
readFile(fileName, encoding) {
const file = files.get(fileName);
if (file != null)
return getCode(file);
return ts.sys.readFile(fileName, encoding);
},
fileExists: (fileName) => files.has(fileName) || ts.sys.fileExists(fileName),
getScriptFileNames: () => Array.from(files.keys()),
getScriptSnapshot: (fileName) => getFile(fileName).file,
getScriptVersion: (fileName) => getFile(fileName).version.toString(),
resolveModuleNames(moduleNames, containingFile) {
return moduleNames.map((moduleName) => resolver(moduleName, containingFile));
},
addFile
};
// Declared here because this has a circular reference
resolver = createModuleResolver(ts, host);
return host;
}
/**
* Returns the string that corresponds with the selected `NewLineKind`.
*/
function getNewLine(ts, kind) {
switch (kind) {
case ts.NewLineKind.CarriageReturnLineFeed:
return '\r\n';
case ts.NewLineKind.LineFeed:
return '\n';
default:
return ts.sys.newLine;
}
}
/*! *****************************************************************************

@@ -207,40 +80,10 @@ Copyright (c) Microsoft Corporation. All rights reserved.

const TSLIB_ID = '\0tslib';
const readFileAsync = (file) => new Promise((fulfil, reject) => readFile(file, 'utf-8', (err, contents) => (err ? reject(err) : fulfil(contents))));
const resolveIdAsync = (file, opts) => new Promise((fulfil, reject) => resolveId(file, opts, (err, contents) => (err ? reject(err) : fulfil(contents))));
/**
* Returns code asynchronously for the tslib helper library.
* @param customHelperCode Overrides the injected helpers with a custom version.
*/
async function getTsLibCode(customHelperCode) {
if (customHelperCode)
return customHelperCode;
const defaultPath = await resolveIdAsync('tslib/tslib.es6.js', { basedir: __dirname });
return readFileAsync(defaultPath);
function getTsLibPath() {
return resolveIdAsync('tslib/tslib.es6.js', { basedir: __dirname });
}
const DEFAULT_COMPILER_OPTIONS = {
module: 'esnext',
sourceMap: true,
noEmitOnError: true
};
const FORCED_COMPILER_OPTIONS = {
// See: https://github.com/rollup/rollup-plugin-typescript/issues/45
// See: https://github.com/rollup/rollup-plugin-typescript/issues/142
declaration: false,
// Delete the `declarationMap` option, as it will cause an error, because we have
// deleted the `declaration` option.
declarationMap: false,
incremental: false,
// eslint-disable-next-line no-undefined
tsBuildInfoFile: undefined,
// Always use tslib
noEmitHelpers: true,
importHelpers: true,
// Typescript needs to emit the code for us to work with
noEmit: false,
emitDeclarationOnly: false,
// Preventing Typescript from resolving code may break compilation
noResolve: false
};
/**

@@ -254,7 +97,7 @@ * Separate the Rollup plugin options from the Typescript compiler options,

* - `typescript`: Instance of Typescript library (possibly custom).
* - `tslib`: ESM code from the tslib helper library (possibly)
* - `tslib`: ESM code from the tslib helper library (possibly custom).
*/
function getPluginOptions(options) {
const { include, exclude, tsconfig, typescript, tslib } = options, compilerOptions = __rest(options, ["include", "exclude", "tsconfig", "typescript", "tslib"]);
const filter = createFilter(include || ['*.ts+(|x)', '**/*.ts+(|x)'], exclude || ['*.d.ts', '**/*.d.ts']);
const filter = createFilter(include || ['*.ts+(|x)', '**/*.ts+(|x)'], exclude);
return {

@@ -265,6 +108,113 @@ filter,

typescript: typescript || defaultTs,
tslib: getTsLibCode(tslib)
tslib: tslib || getTsLibPath()
};
}
/**
* Converts a Typescript type error into an equivalent Rollup warning object.
*/
function diagnosticToWarning(ts, host, diagnostic) {
const pluginCode = `TS${diagnostic.code}`;
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
// Build a Rollup warning object from the diagnostics object.
const warning = {
pluginCode,
message: `@rollup/plugin-typescript ${pluginCode}: ${message}`
};
if (diagnostic.file) {
// Add information about the file location
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
warning.loc = {
column: character + 1,
line: line + 1,
file: diagnostic.file.fileName
};
if (host) {
// Extract a code frame from Typescript
const formatted = ts.formatDiagnosticsWithColorAndContext([diagnostic], host);
// Typescript only exposes this formatter as a string prefixed with the flattened message.
// We need to remove it here since Rollup treats the properties as separate parts.
let frame = formatted.slice(formatted.indexOf(message) + message.length);
const newLine = host.getNewLine();
if (frame.startsWith(newLine)) {
frame = frame.slice(frame.indexOf(newLine) + newLine.length);
}
warning.frame = frame;
}
}
return warning;
}
const DEFAULT_COMPILER_OPTIONS = {
module: 'esnext',
noEmitOnError: true,
skipLibCheck: true
};
const FORCED_COMPILER_OPTIONS = {
// Always use tslib
noEmitHelpers: true,
importHelpers: true,
// Typescript needs to emit the code for us to work with
noEmit: false,
emitDeclarationOnly: false,
// Preventing Typescript from resolving code may break compilation
noResolve: false
};
/* eslint-disable no-param-reassign */
const DIRECTORY_PROPS = ['outDir', 'declarationDir'];
/**
* Mutates the compiler options to convert paths from relative to absolute.
* This should be used with compiler options passed through the Rollup plugin options,
* not those found from loading a tsconfig.json file.
* @param compilerOptions Compiler options to _mutate_.
* @param relativeTo Paths are resolved relative to this path.
*/
function makePathsAbsolute(compilerOptions, relativeTo) {
for (const pathProp of DIRECTORY_PROPS) {
if (compilerOptions[pathProp]) {
compilerOptions[pathProp] = resolve(relativeTo, compilerOptions[pathProp]);
}
}
}
/**
* Mutates the compiler options to normalize some values for Rollup.
* @param compilerOptions Compiler options to _mutate_.
* @returns True if the source map compiler option was not initially set.
*/
function normalizeCompilerOptions(ts, compilerOptions) {
let autoSetSourceMap = false;
if (compilerOptions.inlineSourceMap) {
// Force separate source map files for Rollup to work with.
compilerOptions.sourceMap = true;
compilerOptions.inlineSourceMap = false;
}
else if (typeof compilerOptions.sourceMap !== 'boolean') {
// Default to using source maps.
// If the plugin user sets sourceMap to false we keep that option.
compilerOptions.sourceMap = true;
autoSetSourceMap = true;
}
switch (compilerOptions.module) {
case ts.ModuleKind.ES2015:
case ts.ModuleKind.ESNext:
case ts.ModuleKind.CommonJS:
// OK module type
return autoSetSourceMap;
case ts.ModuleKind.None:
case ts.ModuleKind.AMD:
case ts.ModuleKind.UMD:
case ts.ModuleKind.System: {
// Invalid module type
const moduleType = ts.ModuleKind[compilerOptions.module];
throw new Error(`@rollup/plugin-typescript: The module kind should be 'ES2015' or 'ESNext, found: '${moduleType}'`);
}
default:
// Unknown or unspecified module type, force ESNext
compilerOptions.module = ts.ModuleKind.ESNext;
}
return autoSetSourceMap;
}
/**
* Finds the path to the tsconfig file relative to the current working directory.

@@ -298,3 +248,2 @@ * @param relativePath Relative tsconfig path given by the user.

function readTsConfigFile(ts, tsConfigPath) {
var _a;
const { config, error } = ts.readConfigFile(tsConfigPath, (path) => readFileSync(path, 'utf8'));

@@ -304,7 +253,2 @@ if (error) {

}
const extendedTsConfig = (_a = config) === null || _a === void 0 ? void 0 : _a.extends;
if (extendedTsConfig) {
// Get absolute path of `extends`, starting at basedir of the tsconfig file.
config.extends = resolve(process.cwd(), tsConfigPath, '..', extendedTsConfig);
}
return config || {};

@@ -326,38 +270,4 @@ }

}
const configCache = new Map();
/**
* Mutates the compiler options to normalize some values for Rollup.
* @param compilerOptions Compiler options to _mutate_.
*/
function normalizeCompilerOptions(ts, compilerOptions) {
/* eslint-disable no-param-reassign */
if (compilerOptions.inlineSourceMap) {
// Force separate source map files for Rollup to work with.
compilerOptions.sourceMap = true;
compilerOptions.inlineSourceMap = false;
}
else if (typeof compilerOptions.sourceMap !== 'boolean') {
// Default to using source maps.
// If the plugin user sets sourceMap to false we keep that option.
compilerOptions.sourceMap = true;
}
switch (compilerOptions.module) {
case ts.ModuleKind.ES2015:
case ts.ModuleKind.ESNext:
case ts.ModuleKind.CommonJS:
// OK module type
return;
case ts.ModuleKind.None:
case ts.ModuleKind.AMD:
case ts.ModuleKind.UMD:
case ts.ModuleKind.System: {
// Invalid module type
const moduleType = ts.ModuleKind[compilerOptions.module];
throw new Error(`@rollup/plugin-typescript: The module kind should be 'ES2015' or 'ESNext, found: '${moduleType}'`);
}
default:
// Unknown or unspecified module type, force ESNext
compilerOptions.module = ts.ModuleKind.ESNext;
}
}
/**
* Parse the Typescript config to use with the plugin.

@@ -374,3 +284,5 @@ * @param ts Typescript library instance.

function parseTypescriptConfig(ts, tsconfig, compilerOptions) {
/* eslint-disable no-undefined */
const cwd = process.cwd();
makePathsAbsolute(compilerOptions, cwd);
let parsedConfig;

@@ -381,22 +293,89 @@ // Resolve path to file. If file is not found, pass undefined path to `parseJsonConfigFileContent`.

const tsConfigFile = tsConfigPath ? readTsConfigFile(ts, tsConfigPath) : {};
const basePath = tsConfigPath ? dirname(tsConfigPath) : cwd;
// If compilerOptions has enums, it represents an CompilerOptions object instead of parsed JSON.
// This determines where the data is passed to the parser.
if (containsEnumOptions(compilerOptions)) {
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions) }), ts.sys, cwd, Object.assign(Object.assign({}, compilerOptions), FORCED_COMPILER_OPTIONS), tsConfigPath);
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions) }), ts.sys, basePath, Object.assign(Object.assign({}, compilerOptions), FORCED_COMPILER_OPTIONS), tsConfigPath, undefined, undefined, configCache);
}
else {
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions), compilerOptions) }), ts.sys, cwd, FORCED_COMPILER_OPTIONS, tsConfigPath);
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions), compilerOptions) }), ts.sys, basePath, FORCED_COMPILER_OPTIONS, tsConfigPath, undefined, undefined, configCache);
}
// We only want to automatically add ambient declaration files.
// Normal script files are handled by Rollup.
parsedConfig.fileNames = parsedConfig.fileNames.filter((file) => file.endsWith('.d.ts'));
normalizeCompilerOptions(ts, parsedConfig.options);
return parsedConfig;
const autoSetSourceMap = normalizeCompilerOptions(ts, parsedConfig.options);
return Object.assign(Object.assign({}, parsedConfig), { autoSetSourceMap });
}
/**
* If errors are detected in the parsed options,
* display all of them as warnings then emit an error.
*/
function emitParsedOptionsErrors(ts, context, parsedOptions) {
if (parsedOptions.errors.length > 0) {
parsedOptions.errors.forEach((error) => context.warn(diagnosticToWarning(ts, null, error)));
context.error(`@rollup/plugin-typescript: Couldn't process compiler options`);
}
}
/**
* Validate that the `compilerOptions.sourceMap` option matches `outputOptions.sourcemap`.
* @param context Rollup plugin context used to emit warnings.
* @param compilerOptions Typescript compiler options.
* @param outputOptions Rollup output options.
* @param autoSetSourceMap True if the `compilerOptions.sourceMap` property was set to `true`
* by the plugin, not the user.
*/
function validateSourceMap(context, compilerOptions, outputOptions, autoSetSourceMap) {
if (compilerOptions.sourceMap && !outputOptions.sourcemap && !autoSetSourceMap) {
context.warn(`@rollup/plugin-typescript: Rollup 'sourcemap' option must be set to generate source maps.`);
}
else if (!compilerOptions.sourceMap && outputOptions.sourcemap) {
context.warn(`@rollup/plugin-typescript: Typescript 'sourceMap' compiler option must be set to generate source maps.`);
}
}
/**
* Validate that the out directory used by Typescript can be controlled by Rollup.
* @param context Rollup plugin context used to emit errors.
* @param compilerOptions Typescript compiler options.
* @param outputOptions Rollup output options.
*/
function validatePaths(ts, context, compilerOptions, outputOptions) {
if (compilerOptions.out) {
context.error(`@rollup/plugin-typescript: Deprecated 'out' option is not supported. Use 'outDir' instead.`);
}
else if (compilerOptions.outFile) {
context.error(`@rollup/plugin-typescript: 'outFile' option is not supported. Use 'outDir' instead.`);
}
for (const dirProperty of DIRECTORY_PROPS) {
if (compilerOptions[dirProperty]) {
if (!outputOptions.dir) {
context.error(`@rollup/plugin-typescript: 'dir' must be used when '${dirProperty}' is specified.`);
}
// Checks if the given path lies within Rollup output dir
const fromRollupDirToTs = relative(outputOptions.dir, compilerOptions[dirProperty]);
if (fromRollupDirToTs.startsWith('..')) {
context.error(`@rollup/plugin-typescript: '${dirProperty}' must be located inside 'dir'.`);
}
}
}
const tsBuildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(compilerOptions);
if (tsBuildInfoPath && compilerOptions.incremental) {
if (!outputOptions.dir) {
context.error(`@rollup/plugin-typescript: 'dir' must be used when 'tsBuildInfoFile' or 'incremental' are specified.`);
}
// Checks if the given path lies within Rollup output dir
const fromRollupDirToTs = relative(outputOptions.dir, tsBuildInfoPath);
if (fromRollupDirToTs.startsWith('..')) {
context.error(`@rollup/plugin-typescript: 'tsBuildInfoFile' must be located inside 'dir'.`);
}
}
if (compilerOptions.declaration || compilerOptions.declarationMap) {
if (DIRECTORY_PROPS.every((dirProperty) => !compilerOptions[dirProperty])) {
context.error(`@rollup/plugin-typescript: 'outDir' or 'declarationDir' must be specified to generate declaration files.`);
}
}
}
/**
* Checks if the given OutputFile represents some code
*/
function isCodeOutputFile(file) {
return !isMapOutputFile(file) && !file.name.endsWith('.d.ts');
function isCodeOutputFile(name) {
return !isMapOutputFile(name) && !name.endsWith('.d.ts');
}

@@ -406,37 +385,115 @@ /**

*/
function isMapOutputFile({ name }) {
function isMapOutputFile(name) {
return name.endsWith('.map');
}
/**
* Transforms a Typescript EmitOutput into a Rollup SourceDescription.
* Finds the corresponding emitted Javascript files for a given Typescript file.
* @param id Path to the Typescript file.
* @param emittedFiles Map of file names to source code,
* containing files emitted by the Typescript compiler.
*/
function typescriptOutputToRollupTransformation(outputFiles) {
var _a;
const code = outputFiles.find(isCodeOutputFile);
if (code == null)
return null;
const map = outputFiles.find(isMapOutputFile);
function findTypescriptOutput(ts, parsedOptions, id, emittedFiles) {
const emittedFileNames = ts.getOutputFileNames(parsedOptions, id, !ts.sys.useCaseSensitiveFileNames);
const codeFile = emittedFileNames.find(isCodeOutputFile);
const mapFile = emittedFileNames.find(isMapOutputFile);
return {
code: code.text,
map: (_a = map) === null || _a === void 0 ? void 0 : _a.text
code: emittedFiles.get(codeFile),
map: emittedFiles.get(mapFile),
declarations: emittedFileNames.filter((name) => name !== codeFile && name !== mapFile)
};
}
// `Cannot compile modules into 'es6' when targeting 'ES5' or lower.`
const CANNOT_COMPILE_ESM = 1204;
/**
* Emit a Rollup warning or error for a Typescript type error.
*/
function emitDiagnostic(ts, context, host, diagnostic) {
if (diagnostic.code === CANNOT_COMPILE_ESM)
return;
const { noEmitOnError } = host.getCompilationSettings();
// Build a Rollup warning object from the diagnostics object.
const warning = diagnosticToWarning(ts, host, diagnostic);
// Errors are fatal. Otherwise emit warnings.
if (noEmitOnError && diagnostic.category === ts.DiagnosticCategory.Error) {
context.error(warning);
}
else {
context.warn(warning);
}
}
function buildDiagnosticReporter(ts, context, host) {
return function reportDiagnostics(diagnostic) {
emitDiagnostic(ts, context, host, diagnostic);
};
}
/**
* Create a language service host to use with the Typescript compiler & type checking APIs.
* Typescript hosts are used to represent the user's system,
* with an API for reading files, checking directories and case sensitivity etc.
* @see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
*/
function createWatchHost(ts, context, { formatHost, parsedOptions, writeFile, resolveModule }) {
const createProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram;
const baseHost = ts.createWatchCompilerHost(parsedOptions.fileNames, parsedOptions.options, ts.sys, createProgram, buildDiagnosticReporter(ts, context, formatHost),
// Ignore watch status changes
() => { }, parsedOptions.projectReferences);
return Object.assign(Object.assign({}, baseHost), {
/** Override the created program so an in-memory emit is used */
afterProgramCreate(program) {
const origEmit = program.emit;
// eslint-disable-next-line no-param-reassign
program.emit = (targetSourceFile, _, ...args) => origEmit(targetSourceFile, writeFile, ...args);
return baseHost.afterProgramCreate(program);
},
/** Add helper to deal with module resolution */
resolveModuleNames(moduleNames, containingFile) {
return moduleNames.map((moduleName) => resolveModule(moduleName, containingFile));
} });
}
function createWatchProgram(ts, context, options) {
return ts.createWatchProgram(createWatchHost(ts, context, options));
}
function typescript(options = {}) {
const { filter, tsconfig, compilerOptions, tslib, typescript: ts } = getPluginOptions(options);
const emittedFiles = new Map();
const declarationFiles = new Set();
const parsedOptions = parseTypescriptConfig(ts, tsconfig, compilerOptions);
const host = createHost(ts, parsedOptions);
const services = ts.createLanguageService(host, getDocumentRegistry(ts, process.cwd()));
parsedOptions.fileNames = parsedOptions.fileNames.filter(filter);
const formatHost = createFormattingHost(ts, parsedOptions.options);
const resolveModule = createModuleResolver(ts, formatHost);
let program = null;
function normalizePath(fileName) {
return fileName.split(win32.sep).join(posix.sep);
}
return {
name: 'typescript',
buildStart() {
if (parsedOptions.errors.length > 0) {
parsedOptions.errors.forEach((error) => this.warn(diagnosticToWarning(ts, host, error)));
this.error(`@rollup/plugin-typescript: Couldn't process compiler options`);
emitParsedOptionsErrors(ts, this, parsedOptions);
program = createWatchProgram(ts, this, {
formatHost,
resolveModule,
parsedOptions,
writeFile(fileName, data) {
emittedFiles.set(fileName, data);
}
});
},
buildEnd() {
var _a;
if (process.env.ROLLUP_WATCH !== 'true') {
// ESLint doesn't understand optional chaining
// eslint-disable-next-line
(_a = program) === null || _a === void 0 ? void 0 : _a.close();
}
},
renderStart(outputOptions) {
validateSourceMap(this, parsedOptions.options, outputOptions, parsedOptions.autoSetSourceMap);
validatePaths(ts, this, parsedOptions.options, outputOptions);
},
resolveId(importee, importer) {
var _a;
if (importee === 'tslib') {
return TSLIB_ID;
return tslib;
}

@@ -446,9 +503,8 @@ if (!importer)

// Convert path from windows separators to posix separators
const containingFile = importer.split(win32.sep).join(posix.sep);
const resolved = host.resolveModuleNames([importee], containingFile);
const resolvedFile = (_a = resolved[0]) === null || _a === void 0 ? void 0 : _a.resolvedFileName;
if (resolvedFile) {
if (resolvedFile.endsWith('.d.ts'))
const containingFile = normalizePath(importer);
const resolved = resolveModule(importee, containingFile);
if (resolved) {
if (resolved.extension === '.d.ts')
return null;
return resolvedFile;
return resolved.resolvedFileName;
}

@@ -458,27 +514,27 @@ return null;

load(id) {
if (id === TSLIB_ID) {
return tslib;
}
return null;
},
transform(code, id) {
if (!filter(id))
return null;
host.addFile(id, code);
const output = services.getEmitOutput(id);
if (output.emitSkipped) {
// Emit failed, print all diagnostics for this file
const allDiagnostics = []
.concat(services.getSyntacticDiagnostics(id))
.concat(services.getSemanticDiagnostics(id));
emitDiagnostics(ts, this, host, allDiagnostics);
throw new Error(`Couldn't compile ${id}`);
const output = findTypescriptOutput(ts, parsedOptions, id, emittedFiles);
output.declarations.forEach((declaration) => declarationFiles.add(declaration));
return output.code ? output : null;
},
generateBundle(outputOptions) {
for (const id of declarationFiles) {
const code = emittedFiles.get(id);
if (code) {
this.emitFile({
type: 'asset',
fileName: normalizePath(relative(outputOptions.dir, id)),
source: code
});
}
}
return typescriptOutputToRollupTransformation(output.outputFiles);
},
generateBundle() {
const program = services.getProgram();
if (program == null)
return;
emitDiagnostics(ts, this, host, ts.getPreEmitDiagnostics(program));
const tsBuildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(parsedOptions.options);
if (tsBuildInfoPath) {
this.emitFile({
type: 'asset',
fileName: normalizePath(relative(outputOptions.dir, tsBuildInfoPath)),
source: emittedFiles.get(tsBuildInfoPath)
});
}
}

@@ -485,0 +541,0 @@ };

@@ -6,87 +6,40 @@ 'use strict';

var path = require('path');
var fs = require('fs');
var pluginutils = require('@rollup/pluginutils');
var defaultTs = require('typescript');
var resolveId = _interopDefault(require('resolve'));
var fs = require('fs');
// `Cannot compile modules into 'es6' when targeting 'ES5' or lower.`
const CANNOT_COMPILE_ESM = 1204;
/**
* For each type error reported by Typescript, emit a Rollup warning or error.
* Create a format diagnostics host to use with the Typescript type checking APIs.
* Typescript hosts are used to represent the user's system,
* with an API for checking case sensitivity etc.
* @param compilerOptions Typescript compiler options. Affects functions such as `getNewLine`.
* @see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
*/
function emitDiagnostics(ts, context, host, diagnostics) {
if (!diagnostics)
return;
const { noEmitOnError } = host.getCompilationSettings();
diagnostics
.filter((diagnostic) => diagnostic.code !== CANNOT_COMPILE_ESM)
.forEach((diagnostic) => {
// Build a Rollup warning object from the diagnostics object.
const warning = diagnosticToWarning(ts, host, diagnostic);
// Errors are fatal. Otherwise emit warnings.
if (noEmitOnError && diagnostic.category === ts.DiagnosticCategory.Error) {
context.error(warning);
}
else {
context.warn(warning);
}
});
}
/**
* Converts a Typescript type error into an equivalent Rollup warning object.
*/
function diagnosticToWarning(ts, host, diagnostic) {
const pluginCode = `TS${diagnostic.code}`;
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
// Build a Rollup warning object from the diagnostics object.
const warning = {
pluginCode,
message: `@rollup/plugin-typescript ${pluginCode}: ${message}`
function createFormattingHost(ts, compilerOptions) {
return {
/** Returns the compiler options for the project. */
getCompilationSettings: () => compilerOptions,
/** Returns the current working directory. */
getCurrentDirectory: () => process.cwd(),
/** Returns the string that corresponds with the selected `NewLineKind`. */
getNewLine() {
switch (compilerOptions.newLine) {
case ts.NewLineKind.CarriageReturnLineFeed:
return '\r\n';
case ts.NewLineKind.LineFeed:
return '\n';
default:
return ts.sys.newLine;
}
},
/** Returns a lower case name on case insensitive systems, otherwise the original name. */
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase()
};
if (diagnostic.file) {
// Add information about the file location
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
warning.loc = {
column: character + 1,
line: line + 1,
file: diagnostic.file.fileName
};
if (host) {
// Extract a code frame from Typescript
const formatted = ts.formatDiagnosticsWithColorAndContext([diagnostic], host);
// Typescript only exposes this formatter as a string prefixed with the flattened message.
// We need to remove it here since Rollup treats the properties as separate parts.
let frame = formatted.slice(formatted.indexOf(message) + message.length);
const newLine = host.getNewLine();
if (frame.startsWith(newLine)) {
frame = frame.slice(frame.indexOf(newLine) + newLine.length);
}
warning.frame = frame;
}
}
return warning;
}
/**
* Map of Typescript instances to paths to DocumentRegistries.
*/
const globalRegistryCache = new Map();
/**
* Return a `DocumentRegistry` instance that matches the given Typescript instance
* and working directory. If there is no a pre-existing instance, one will be
* created and set in the map.
*/
function getDocumentRegistry(ts, cwd) {
if (!globalRegistryCache.has(ts)) {
globalRegistryCache.set(ts, new Map());
}
const instanceRegistryCache = globalRegistryCache.get(ts);
if (!instanceRegistryCache.has(cwd)) {
instanceRegistryCache.set(cwd, ts.createDocumentRegistry(ts.sys.useCaseSensitiveFileNames, cwd));
}
return instanceRegistryCache.get(cwd);
}
/**
* Create a helper for resolving modules using Typescript.
* @param host Typescript host that extends `ModuleResolutionHost`
* with methods for sanitizing filenames and getting compiler options.
*/

@@ -96,4 +49,5 @@ function createModuleResolver(ts, host) {

const cache = ts.createModuleResolutionCache(process.cwd(), host.getCanonicalFileName, compilerOptions);
const moduleHost = Object.assign(Object.assign({}, ts.sys), host);
return (moduleName, containingFile) => {
const resolved = ts.nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache);
const resolved = ts.nodeModuleNameResolver(moduleName, containingFile, compilerOptions, moduleHost, cache);
return resolved.resolvedModule;

@@ -103,83 +57,2 @@ };

/**
* Create a language service host to use with the Typescript compiler & type checking APIs.
* @param parsedOptions Parsed options for Typescript.
* @param parsedOptions.options Typescript compiler options. Affects functions such as `getNewLine`.
* @param parsedOptions.fileNames Declaration files to include for typechecking.
* @see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
*/
function createHost(ts, parsedOptions) {
const files = new Map();
/** Get the code stored in a File snapshot. */
function getCode({ file }) {
return file.getText(0, file.getLength());
}
/** @see TypescriptHost.addFile */
function addFile(id, code) {
const existing = files.get(id);
// Don't need to update if nothing changed
if (existing && getCode(existing) === code)
return;
files.set(id, {
file: ts.ScriptSnapshot.fromString(code),
version: existing ? existing.version + 1 : 0
});
}
/** Helper that tries to read the file if it hasn't been stored yet */
function getFile(id) {
if (!files.has(id)) {
const code = ts.sys.readFile(id);
if (code == null) {
throw new Error(`@rollup/plugin-typescript: Could not find ${id}`);
}
addFile(id, code);
}
return files.get(id);
}
parsedOptions.fileNames.forEach((id) => getFile(id));
let resolver;
const host = {
getCompilationSettings: () => parsedOptions.options,
getCurrentDirectory: () => process.cwd(),
getNewLine: () => getNewLine(ts, parsedOptions.options.newLine),
getCanonicalFileName: (fileName) => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
getDefaultLibFileName: ts.getDefaultLibFilePath,
getDirectories: ts.sys.getDirectories,
directoryExists: ts.sys.directoryExists,
realpath: ts.sys.realpath,
readDirectory: ts.sys.readDirectory,
readFile(fileName, encoding) {
const file = files.get(fileName);
if (file != null)
return getCode(file);
return ts.sys.readFile(fileName, encoding);
},
fileExists: (fileName) => files.has(fileName) || ts.sys.fileExists(fileName),
getScriptFileNames: () => Array.from(files.keys()),
getScriptSnapshot: (fileName) => getFile(fileName).file,
getScriptVersion: (fileName) => getFile(fileName).version.toString(),
resolveModuleNames(moduleNames, containingFile) {
return moduleNames.map((moduleName) => resolver(moduleName, containingFile));
},
addFile
};
// Declared here because this has a circular reference
resolver = createModuleResolver(ts, host);
return host;
}
/**
* Returns the string that corresponds with the selected `NewLineKind`.
*/
function getNewLine(ts, kind) {
switch (kind) {
case ts.NewLineKind.CarriageReturnLineFeed:
return '\r\n';
case ts.NewLineKind.LineFeed:
return '\n';
default:
return ts.sys.newLine;
}
}
/*! *****************************************************************************

@@ -212,40 +85,10 @@ Copyright (c) Microsoft Corporation. All rights reserved.

const TSLIB_ID = '\0tslib';
const readFileAsync = (file) => new Promise((fulfil, reject) => fs.readFile(file, 'utf-8', (err, contents) => (err ? reject(err) : fulfil(contents))));
const resolveIdAsync = (file, opts) => new Promise((fulfil, reject) => resolveId(file, opts, (err, contents) => (err ? reject(err) : fulfil(contents))));
/**
* Returns code asynchronously for the tslib helper library.
* @param customHelperCode Overrides the injected helpers with a custom version.
*/
async function getTsLibCode(customHelperCode) {
if (customHelperCode)
return customHelperCode;
const defaultPath = await resolveIdAsync('tslib/tslib.es6.js', { basedir: __dirname });
return readFileAsync(defaultPath);
function getTsLibPath() {
return resolveIdAsync('tslib/tslib.es6.js', { basedir: __dirname });
}
const DEFAULT_COMPILER_OPTIONS = {
module: 'esnext',
sourceMap: true,
noEmitOnError: true
};
const FORCED_COMPILER_OPTIONS = {
// See: https://github.com/rollup/rollup-plugin-typescript/issues/45
// See: https://github.com/rollup/rollup-plugin-typescript/issues/142
declaration: false,
// Delete the `declarationMap` option, as it will cause an error, because we have
// deleted the `declaration` option.
declarationMap: false,
incremental: false,
// eslint-disable-next-line no-undefined
tsBuildInfoFile: undefined,
// Always use tslib
noEmitHelpers: true,
importHelpers: true,
// Typescript needs to emit the code for us to work with
noEmit: false,
emitDeclarationOnly: false,
// Preventing Typescript from resolving code may break compilation
noResolve: false
};
/**

@@ -259,7 +102,7 @@ * Separate the Rollup plugin options from the Typescript compiler options,

* - `typescript`: Instance of Typescript library (possibly custom).
* - `tslib`: ESM code from the tslib helper library (possibly)
* - `tslib`: ESM code from the tslib helper library (possibly custom).
*/
function getPluginOptions(options) {
const { include, exclude, tsconfig, typescript, tslib } = options, compilerOptions = __rest(options, ["include", "exclude", "tsconfig", "typescript", "tslib"]);
const filter = pluginutils.createFilter(include || ['*.ts+(|x)', '**/*.ts+(|x)'], exclude || ['*.d.ts', '**/*.d.ts']);
const filter = pluginutils.createFilter(include || ['*.ts+(|x)', '**/*.ts+(|x)'], exclude);
return {

@@ -270,6 +113,113 @@ filter,

typescript: typescript || defaultTs,
tslib: getTsLibCode(tslib)
tslib: tslib || getTsLibPath()
};
}
/**
* Converts a Typescript type error into an equivalent Rollup warning object.
*/
function diagnosticToWarning(ts, host, diagnostic) {
const pluginCode = `TS${diagnostic.code}`;
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
// Build a Rollup warning object from the diagnostics object.
const warning = {
pluginCode,
message: `@rollup/plugin-typescript ${pluginCode}: ${message}`
};
if (diagnostic.file) {
// Add information about the file location
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
warning.loc = {
column: character + 1,
line: line + 1,
file: diagnostic.file.fileName
};
if (host) {
// Extract a code frame from Typescript
const formatted = ts.formatDiagnosticsWithColorAndContext([diagnostic], host);
// Typescript only exposes this formatter as a string prefixed with the flattened message.
// We need to remove it here since Rollup treats the properties as separate parts.
let frame = formatted.slice(formatted.indexOf(message) + message.length);
const newLine = host.getNewLine();
if (frame.startsWith(newLine)) {
frame = frame.slice(frame.indexOf(newLine) + newLine.length);
}
warning.frame = frame;
}
}
return warning;
}
const DEFAULT_COMPILER_OPTIONS = {
module: 'esnext',
noEmitOnError: true,
skipLibCheck: true
};
const FORCED_COMPILER_OPTIONS = {
// Always use tslib
noEmitHelpers: true,
importHelpers: true,
// Typescript needs to emit the code for us to work with
noEmit: false,
emitDeclarationOnly: false,
// Preventing Typescript from resolving code may break compilation
noResolve: false
};
/* eslint-disable no-param-reassign */
const DIRECTORY_PROPS = ['outDir', 'declarationDir'];
/**
* Mutates the compiler options to convert paths from relative to absolute.
* This should be used with compiler options passed through the Rollup plugin options,
* not those found from loading a tsconfig.json file.
* @param compilerOptions Compiler options to _mutate_.
* @param relativeTo Paths are resolved relative to this path.
*/
function makePathsAbsolute(compilerOptions, relativeTo) {
for (const pathProp of DIRECTORY_PROPS) {
if (compilerOptions[pathProp]) {
compilerOptions[pathProp] = path.resolve(relativeTo, compilerOptions[pathProp]);
}
}
}
/**
* Mutates the compiler options to normalize some values for Rollup.
* @param compilerOptions Compiler options to _mutate_.
* @returns True if the source map compiler option was not initially set.
*/
function normalizeCompilerOptions(ts, compilerOptions) {
let autoSetSourceMap = false;
if (compilerOptions.inlineSourceMap) {
// Force separate source map files for Rollup to work with.
compilerOptions.sourceMap = true;
compilerOptions.inlineSourceMap = false;
}
else if (typeof compilerOptions.sourceMap !== 'boolean') {
// Default to using source maps.
// If the plugin user sets sourceMap to false we keep that option.
compilerOptions.sourceMap = true;
autoSetSourceMap = true;
}
switch (compilerOptions.module) {
case ts.ModuleKind.ES2015:
case ts.ModuleKind.ESNext:
case ts.ModuleKind.CommonJS:
// OK module type
return autoSetSourceMap;
case ts.ModuleKind.None:
case ts.ModuleKind.AMD:
case ts.ModuleKind.UMD:
case ts.ModuleKind.System: {
// Invalid module type
const moduleType = ts.ModuleKind[compilerOptions.module];
throw new Error(`@rollup/plugin-typescript: The module kind should be 'ES2015' or 'ESNext, found: '${moduleType}'`);
}
default:
// Unknown or unspecified module type, force ESNext
compilerOptions.module = ts.ModuleKind.ESNext;
}
return autoSetSourceMap;
}
/**
* Finds the path to the tsconfig file relative to the current working directory.

@@ -303,3 +253,2 @@ * @param relativePath Relative tsconfig path given by the user.

function readTsConfigFile(ts, tsConfigPath) {
var _a;
const { config, error } = ts.readConfigFile(tsConfigPath, (path) => fs.readFileSync(path, 'utf8'));

@@ -309,7 +258,2 @@ if (error) {

}
const extendedTsConfig = (_a = config) === null || _a === void 0 ? void 0 : _a.extends;
if (extendedTsConfig) {
// Get absolute path of `extends`, starting at basedir of the tsconfig file.
config.extends = path.resolve(process.cwd(), tsConfigPath, '..', extendedTsConfig);
}
return config || {};

@@ -331,38 +275,4 @@ }

}
const configCache = new Map();
/**
* Mutates the compiler options to normalize some values for Rollup.
* @param compilerOptions Compiler options to _mutate_.
*/
function normalizeCompilerOptions(ts, compilerOptions) {
/* eslint-disable no-param-reassign */
if (compilerOptions.inlineSourceMap) {
// Force separate source map files for Rollup to work with.
compilerOptions.sourceMap = true;
compilerOptions.inlineSourceMap = false;
}
else if (typeof compilerOptions.sourceMap !== 'boolean') {
// Default to using source maps.
// If the plugin user sets sourceMap to false we keep that option.
compilerOptions.sourceMap = true;
}
switch (compilerOptions.module) {
case ts.ModuleKind.ES2015:
case ts.ModuleKind.ESNext:
case ts.ModuleKind.CommonJS:
// OK module type
return;
case ts.ModuleKind.None:
case ts.ModuleKind.AMD:
case ts.ModuleKind.UMD:
case ts.ModuleKind.System: {
// Invalid module type
const moduleType = ts.ModuleKind[compilerOptions.module];
throw new Error(`@rollup/plugin-typescript: The module kind should be 'ES2015' or 'ESNext, found: '${moduleType}'`);
}
default:
// Unknown or unspecified module type, force ESNext
compilerOptions.module = ts.ModuleKind.ESNext;
}
}
/**
* Parse the Typescript config to use with the plugin.

@@ -379,3 +289,5 @@ * @param ts Typescript library instance.

function parseTypescriptConfig(ts, tsconfig, compilerOptions) {
/* eslint-disable no-undefined */
const cwd = process.cwd();
makePathsAbsolute(compilerOptions, cwd);
let parsedConfig;

@@ -386,22 +298,89 @@ // Resolve path to file. If file is not found, pass undefined path to `parseJsonConfigFileContent`.

const tsConfigFile = tsConfigPath ? readTsConfigFile(ts, tsConfigPath) : {};
const basePath = tsConfigPath ? path.dirname(tsConfigPath) : cwd;
// If compilerOptions has enums, it represents an CompilerOptions object instead of parsed JSON.
// This determines where the data is passed to the parser.
if (containsEnumOptions(compilerOptions)) {
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions) }), ts.sys, cwd, Object.assign(Object.assign({}, compilerOptions), FORCED_COMPILER_OPTIONS), tsConfigPath);
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions) }), ts.sys, basePath, Object.assign(Object.assign({}, compilerOptions), FORCED_COMPILER_OPTIONS), tsConfigPath, undefined, undefined, configCache);
}
else {
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions), compilerOptions) }), ts.sys, cwd, FORCED_COMPILER_OPTIONS, tsConfigPath);
parsedConfig = ts.parseJsonConfigFileContent(Object.assign(Object.assign({}, tsConfigFile), { compilerOptions: Object.assign(Object.assign(Object.assign({}, DEFAULT_COMPILER_OPTIONS), tsConfigFile.compilerOptions), compilerOptions) }), ts.sys, basePath, FORCED_COMPILER_OPTIONS, tsConfigPath, undefined, undefined, configCache);
}
// We only want to automatically add ambient declaration files.
// Normal script files are handled by Rollup.
parsedConfig.fileNames = parsedConfig.fileNames.filter((file) => file.endsWith('.d.ts'));
normalizeCompilerOptions(ts, parsedConfig.options);
return parsedConfig;
const autoSetSourceMap = normalizeCompilerOptions(ts, parsedConfig.options);
return Object.assign(Object.assign({}, parsedConfig), { autoSetSourceMap });
}
/**
* If errors are detected in the parsed options,
* display all of them as warnings then emit an error.
*/
function emitParsedOptionsErrors(ts, context, parsedOptions) {
if (parsedOptions.errors.length > 0) {
parsedOptions.errors.forEach((error) => context.warn(diagnosticToWarning(ts, null, error)));
context.error(`@rollup/plugin-typescript: Couldn't process compiler options`);
}
}
/**
* Validate that the `compilerOptions.sourceMap` option matches `outputOptions.sourcemap`.
* @param context Rollup plugin context used to emit warnings.
* @param compilerOptions Typescript compiler options.
* @param outputOptions Rollup output options.
* @param autoSetSourceMap True if the `compilerOptions.sourceMap` property was set to `true`
* by the plugin, not the user.
*/
function validateSourceMap(context, compilerOptions, outputOptions, autoSetSourceMap) {
if (compilerOptions.sourceMap && !outputOptions.sourcemap && !autoSetSourceMap) {
context.warn(`@rollup/plugin-typescript: Rollup 'sourcemap' option must be set to generate source maps.`);
}
else if (!compilerOptions.sourceMap && outputOptions.sourcemap) {
context.warn(`@rollup/plugin-typescript: Typescript 'sourceMap' compiler option must be set to generate source maps.`);
}
}
/**
* Validate that the out directory used by Typescript can be controlled by Rollup.
* @param context Rollup plugin context used to emit errors.
* @param compilerOptions Typescript compiler options.
* @param outputOptions Rollup output options.
*/
function validatePaths(ts, context, compilerOptions, outputOptions) {
if (compilerOptions.out) {
context.error(`@rollup/plugin-typescript: Deprecated 'out' option is not supported. Use 'outDir' instead.`);
}
else if (compilerOptions.outFile) {
context.error(`@rollup/plugin-typescript: 'outFile' option is not supported. Use 'outDir' instead.`);
}
for (const dirProperty of DIRECTORY_PROPS) {
if (compilerOptions[dirProperty]) {
if (!outputOptions.dir) {
context.error(`@rollup/plugin-typescript: 'dir' must be used when '${dirProperty}' is specified.`);
}
// Checks if the given path lies within Rollup output dir
const fromRollupDirToTs = path.relative(outputOptions.dir, compilerOptions[dirProperty]);
if (fromRollupDirToTs.startsWith('..')) {
context.error(`@rollup/plugin-typescript: '${dirProperty}' must be located inside 'dir'.`);
}
}
}
const tsBuildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(compilerOptions);
if (tsBuildInfoPath && compilerOptions.incremental) {
if (!outputOptions.dir) {
context.error(`@rollup/plugin-typescript: 'dir' must be used when 'tsBuildInfoFile' or 'incremental' are specified.`);
}
// Checks if the given path lies within Rollup output dir
const fromRollupDirToTs = path.relative(outputOptions.dir, tsBuildInfoPath);
if (fromRollupDirToTs.startsWith('..')) {
context.error(`@rollup/plugin-typescript: 'tsBuildInfoFile' must be located inside 'dir'.`);
}
}
if (compilerOptions.declaration || compilerOptions.declarationMap) {
if (DIRECTORY_PROPS.every((dirProperty) => !compilerOptions[dirProperty])) {
context.error(`@rollup/plugin-typescript: 'outDir' or 'declarationDir' must be specified to generate declaration files.`);
}
}
}
/**
* Checks if the given OutputFile represents some code
*/
function isCodeOutputFile(file) {
return !isMapOutputFile(file) && !file.name.endsWith('.d.ts');
function isCodeOutputFile(name) {
return !isMapOutputFile(name) && !name.endsWith('.d.ts');
}

@@ -411,37 +390,115 @@ /**

*/
function isMapOutputFile({ name }) {
function isMapOutputFile(name) {
return name.endsWith('.map');
}
/**
* Transforms a Typescript EmitOutput into a Rollup SourceDescription.
* Finds the corresponding emitted Javascript files for a given Typescript file.
* @param id Path to the Typescript file.
* @param emittedFiles Map of file names to source code,
* containing files emitted by the Typescript compiler.
*/
function typescriptOutputToRollupTransformation(outputFiles) {
var _a;
const code = outputFiles.find(isCodeOutputFile);
if (code == null)
return null;
const map = outputFiles.find(isMapOutputFile);
function findTypescriptOutput(ts, parsedOptions, id, emittedFiles) {
const emittedFileNames = ts.getOutputFileNames(parsedOptions, id, !ts.sys.useCaseSensitiveFileNames);
const codeFile = emittedFileNames.find(isCodeOutputFile);
const mapFile = emittedFileNames.find(isMapOutputFile);
return {
code: code.text,
map: (_a = map) === null || _a === void 0 ? void 0 : _a.text
code: emittedFiles.get(codeFile),
map: emittedFiles.get(mapFile),
declarations: emittedFileNames.filter((name) => name !== codeFile && name !== mapFile)
};
}
// `Cannot compile modules into 'es6' when targeting 'ES5' or lower.`
const CANNOT_COMPILE_ESM = 1204;
/**
* Emit a Rollup warning or error for a Typescript type error.
*/
function emitDiagnostic(ts, context, host, diagnostic) {
if (diagnostic.code === CANNOT_COMPILE_ESM)
return;
const { noEmitOnError } = host.getCompilationSettings();
// Build a Rollup warning object from the diagnostics object.
const warning = diagnosticToWarning(ts, host, diagnostic);
// Errors are fatal. Otherwise emit warnings.
if (noEmitOnError && diagnostic.category === ts.DiagnosticCategory.Error) {
context.error(warning);
}
else {
context.warn(warning);
}
}
function buildDiagnosticReporter(ts, context, host) {
return function reportDiagnostics(diagnostic) {
emitDiagnostic(ts, context, host, diagnostic);
};
}
/**
* Create a language service host to use with the Typescript compiler & type checking APIs.
* Typescript hosts are used to represent the user's system,
* with an API for reading files, checking directories and case sensitivity etc.
* @see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
*/
function createWatchHost(ts, context, { formatHost, parsedOptions, writeFile, resolveModule }) {
const createProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram;
const baseHost = ts.createWatchCompilerHost(parsedOptions.fileNames, parsedOptions.options, ts.sys, createProgram, buildDiagnosticReporter(ts, context, formatHost),
// Ignore watch status changes
() => { }, parsedOptions.projectReferences);
return Object.assign(Object.assign({}, baseHost), {
/** Override the created program so an in-memory emit is used */
afterProgramCreate(program) {
const origEmit = program.emit;
// eslint-disable-next-line no-param-reassign
program.emit = (targetSourceFile, _, ...args) => origEmit(targetSourceFile, writeFile, ...args);
return baseHost.afterProgramCreate(program);
},
/** Add helper to deal with module resolution */
resolveModuleNames(moduleNames, containingFile) {
return moduleNames.map((moduleName) => resolveModule(moduleName, containingFile));
} });
}
function createWatchProgram(ts, context, options) {
return ts.createWatchProgram(createWatchHost(ts, context, options));
}
function typescript(options = {}) {
const { filter, tsconfig, compilerOptions, tslib, typescript: ts } = getPluginOptions(options);
const emittedFiles = new Map();
const declarationFiles = new Set();
const parsedOptions = parseTypescriptConfig(ts, tsconfig, compilerOptions);
const host = createHost(ts, parsedOptions);
const services = ts.createLanguageService(host, getDocumentRegistry(ts, process.cwd()));
parsedOptions.fileNames = parsedOptions.fileNames.filter(filter);
const formatHost = createFormattingHost(ts, parsedOptions.options);
const resolveModule = createModuleResolver(ts, formatHost);
let program = null;
function normalizePath(fileName) {
return fileName.split(path.win32.sep).join(path.posix.sep);
}
return {
name: 'typescript',
buildStart() {
if (parsedOptions.errors.length > 0) {
parsedOptions.errors.forEach((error) => this.warn(diagnosticToWarning(ts, host, error)));
this.error(`@rollup/plugin-typescript: Couldn't process compiler options`);
emitParsedOptionsErrors(ts, this, parsedOptions);
program = createWatchProgram(ts, this, {
formatHost,
resolveModule,
parsedOptions,
writeFile(fileName, data) {
emittedFiles.set(fileName, data);
}
});
},
buildEnd() {
var _a;
if (process.env.ROLLUP_WATCH !== 'true') {
// ESLint doesn't understand optional chaining
// eslint-disable-next-line
(_a = program) === null || _a === void 0 ? void 0 : _a.close();
}
},
renderStart(outputOptions) {
validateSourceMap(this, parsedOptions.options, outputOptions, parsedOptions.autoSetSourceMap);
validatePaths(ts, this, parsedOptions.options, outputOptions);
},
resolveId(importee, importer) {
var _a;
if (importee === 'tslib') {
return TSLIB_ID;
return tslib;
}

@@ -451,9 +508,8 @@ if (!importer)

// Convert path from windows separators to posix separators
const containingFile = importer.split(path.win32.sep).join(path.posix.sep);
const resolved = host.resolveModuleNames([importee], containingFile);
const resolvedFile = (_a = resolved[0]) === null || _a === void 0 ? void 0 : _a.resolvedFileName;
if (resolvedFile) {
if (resolvedFile.endsWith('.d.ts'))
const containingFile = normalizePath(importer);
const resolved = resolveModule(importee, containingFile);
if (resolved) {
if (resolved.extension === '.d.ts')
return null;
return resolvedFile;
return resolved.resolvedFileName;
}

@@ -463,27 +519,27 @@ return null;

load(id) {
if (id === TSLIB_ID) {
return tslib;
}
return null;
},
transform(code, id) {
if (!filter(id))
return null;
host.addFile(id, code);
const output = services.getEmitOutput(id);
if (output.emitSkipped) {
// Emit failed, print all diagnostics for this file
const allDiagnostics = []
.concat(services.getSyntacticDiagnostics(id))
.concat(services.getSemanticDiagnostics(id));
emitDiagnostics(ts, this, host, allDiagnostics);
throw new Error(`Couldn't compile ${id}`);
const output = findTypescriptOutput(ts, parsedOptions, id, emittedFiles);
output.declarations.forEach((declaration) => declarationFiles.add(declaration));
return output.code ? output : null;
},
generateBundle(outputOptions) {
for (const id of declarationFiles) {
const code = emittedFiles.get(id);
if (code) {
this.emitFile({
type: 'asset',
fileName: normalizePath(path.relative(outputOptions.dir, id)),
source: code
});
}
}
return typescriptOutputToRollupTransformation(output.outputFiles);
},
generateBundle() {
const program = services.getProgram();
if (program == null)
return;
emitDiagnostics(ts, this, host, ts.getPreEmitDiagnostics(program));
const tsBuildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(parsedOptions.options);
if (tsBuildInfoPath) {
this.emitFile({
type: 'asset',
fileName: normalizePath(path.relative(outputOptions.dir, tsBuildInfoPath)),
source: emittedFiles.get(tsBuildInfoPath)
});
}
}

@@ -490,0 +546,0 @@ };

{
"name": "@rollup/plugin-typescript",
"version": "3.1.1",
"version": "4.0.0",
"publishConfig": {

@@ -22,6 +22,7 @@ "access": "public"

"ci:lint:commits": "commitlint --from=${CIRCLE_BRANCH} --to=${CIRCLE_SHA1}",
"ci:test": "pnpm run test -- --verbose",
"lint": "pnpm run lint:js && pnpm run lint:docs && pnpm run lint:package",
"ci:test": "pnpm run test -- --verbose --serial",
"lint": "pnpm run lint:js && pnpm run lint:docs && pnpm run lint:json && pnpm run lint:package",
"lint:docs": "prettier --single-quote --write README.md",
"lint:js": "eslint --fix --cache src test --ext .js,.ts",
"lint:json": "prettier --write **/tsconfig.json",
"lint:package": "prettier --write package.json --plugin=prettier-plugin-package",

@@ -58,3 +59,3 @@ "prebuild": "del-cli dist",

"@rollup/plugin-commonjs": "^11.0.1",
"@rollup/plugin-typescript": "^2.0.1",
"@rollup/plugin-typescript": "^3.0.0",
"buble": "^0.19.8",

@@ -61,0 +62,0 @@ "rollup": "^1.27.14",

@@ -111,3 +111,3 @@ [npm]: https://img.shields.io/npm/v/@rollup/plugin-typescript

typescript({
tslib: fs.readFileSync(require.resolve('some-fork-of-tslib'))
tslib: require.resolve('some-fork-of-tslib')
});

@@ -138,4 +138,2 @@ ```

- `declaration`, `declarationMap`: This plugin currently cannot emit declaration files.
- `incremental`, `tsBuildInfoFile`: This plugin currently does not support incremental compilation using Typescript.
- `noEmitHelpers`, `importHelpers`: The `tslib` helper module always must be used.

@@ -142,0 +140,0 @@ - `noEmit`, `emitDeclarationOnly`: Typescript needs to emit code for the plugin to work with.

@@ -0,5 +1,6 @@

import { FilterPattern } from '@rollup/pluginutils';
import { Plugin } from 'rollup';
import { CompilerOptionsValue, TsConfigSourceFile } from 'typescript';
interface RollupTypescriptOptions {
export interface RollupTypescriptOptions {
/**

@@ -20,3 +21,3 @@ * Other Typescript compiler options.

*/
include?: string | RegExp | Array<string | RegExp> | null;
include?: FilterPattern;
/**

@@ -26,3 +27,3 @@ * Determine which files are transpiled by Typescript (all `.ts` and

*/
exclude?: string | RegExp | Array<string | RegExp> | null;
exclude?: FilterPattern;
/**

@@ -29,0 +30,0 @@ * When set to false, ignores any options specified in the config file.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc