typescript-transform-paths
Advanced tools
Comparing version 3.1.0 to 3.2.0
@@ -5,2 +5,14 @@ # Changelog | ||
## [3.2.0](https://github.com/LeDDGroup/typescript-transform-paths/compare/v3.1.0...v3.2.0) (2021-08-03) | ||
### Features | ||
* Support transformation via ts-node transpileOnly and compiler API transformNodes (closes [#123](https://github.com/LeDDGroup/typescript-transform-paths/issues/123)) ([dd942fd](https://github.com/LeDDGroup/typescript-transform-paths/commit/dd942fdbf34afcdec8f976a1540746521a758c73)) | ||
### Bug Fixes | ||
* Custom JSDoc tags not working for older TS (fixes [#126](https://github.com/LeDDGroup/typescript-transform-paths/issues/126)) ([d4280c3](https://github.com/LeDDGroup/typescript-transform-paths/commit/d4280c3dec4dc9f3834fc98be2e51109422bd9aa)) | ||
## [3.1.0](https://github.com/LeDDGroup/typescript-transform-paths/compare/v3.0.2...v3.1.0) (2021-07-13) | ||
@@ -7,0 +19,0 @@ |
@@ -12,16 +12,57 @@ "use strict"; | ||
const minimatch_1 = require("minimatch"); | ||
/* ****************************************************************************************************************** * | ||
* Transformer | ||
* ****************************************************************************************************************** */ | ||
function transformer(program, config, { ts: tsInstance }) { | ||
const ts_helpers_1 = require("./utils/ts-helpers"); | ||
/* ****************************************************************************************************************** */ | ||
// region: Helpers | ||
/* ****************************************************************************************************************** */ | ||
function getTsProperties(args) { | ||
var _a; | ||
if (!tsInstance) | ||
tsInstance = typescript_1.default; | ||
const compilerOptions = program.getCompilerOptions(); | ||
const rootDirs = (_a = compilerOptions.rootDirs) === null || _a === void 0 ? void 0 : _a.filter(path_1.default.isAbsolute); | ||
let tsInstance; | ||
let compilerOptions; | ||
let fileNames; | ||
let isTsNode = false; | ||
const { 0: program, 2: extras, 3: manualTransformOptions } = args; | ||
tsInstance = (_a = extras === null || extras === void 0 ? void 0 : extras.ts) !== null && _a !== void 0 ? _a : typescript_1.default; | ||
compilerOptions = manualTransformOptions === null || manualTransformOptions === void 0 ? void 0 : manualTransformOptions.compilerOptions; | ||
if (program) { | ||
compilerOptions !== null && compilerOptions !== void 0 ? compilerOptions : (compilerOptions = program.getCompilerOptions()); | ||
} | ||
else if (manualTransformOptions) { | ||
fileNames = manualTransformOptions.fileNames; | ||
} | ||
else { | ||
const tsNodeProps = ts_helpers_1.getTsNodeRegistrationProperties(tsInstance); | ||
if (!tsNodeProps) | ||
throw new Error(`Cannot transform without a Program, ts-node instance, or manual parameters supplied. ` + | ||
`Make sure you're using ts-patch or ts-node with transpileOnly.`); | ||
isTsNode = true; | ||
compilerOptions = tsNodeProps.compilerOptions; | ||
fileNames = tsNodeProps.fileNames; | ||
} | ||
return { tsInstance, compilerOptions, fileNames, isTsNode }; | ||
} | ||
// endregion | ||
/* ****************************************************************************************************************** */ | ||
// region: Transformer | ||
/* ****************************************************************************************************************** */ | ||
function transformer(program, pluginConfig, transformerExtras, | ||
/** | ||
* Supply if manually transforming with compiler API via 'transformNodes' / 'transformModule' | ||
*/ | ||
manualTransformOptions) { | ||
return (transformationContext) => { | ||
var _a, _b, _c; | ||
const pathsBasePath = (_a = compilerOptions.pathsBasePath) !== null && _a !== void 0 ? _a : compilerOptions.baseUrl; | ||
if (!pathsBasePath || !compilerOptions.paths) | ||
return (sourceFile) => sourceFile; | ||
// prettier-ignore | ||
const { tsInstance, compilerOptions, fileNames, isTsNode } = getTsProperties([program, pluginConfig, transformerExtras, manualTransformOptions]); | ||
const rootDirs = (_a = compilerOptions.rootDirs) === null || _a === void 0 ? void 0 : _a.filter(path_1.default.isAbsolute); | ||
const config = pluginConfig !== null && pluginConfig !== void 0 ? pluginConfig : {}; | ||
const getCanonicalFileName = tsInstance.createGetCanonicalFileName(tsInstance.sys.useCaseSensitiveFileNames); | ||
let emitHost = transformationContext.getEmitHost(); | ||
if (!emitHost) { | ||
if (!fileNames) | ||
throw new Error(`No EmitHost found and could not determine files to be processed. Please file an issue with a reproduction!`); | ||
emitHost = ts_helpers_1.createSyntheticEmitHost(compilerOptions, tsInstance, getCanonicalFileName, fileNames); | ||
} | ||
else if (isTsNode) { | ||
Object.assign(emitHost, { getCompilerOptions: () => compilerOptions }); | ||
} | ||
const { configFile, paths } = compilerOptions; | ||
@@ -39,5 +80,4 @@ // TODO - Remove typecast when tryParsePatterns is recognized (probably after ts v4.4) | ||
tsInstance, | ||
pathsBasePath, | ||
emitHost: transformationContext.getEmitHost(), | ||
getCanonicalFileName: tsInstance.createGetCanonicalFileName(tsInstance.sys.useCaseSensitiveFileNames), | ||
emitHost, | ||
isTsNode, | ||
tsThreeInstance: utils_1.cast(tsInstance), | ||
@@ -47,10 +87,8 @@ excludeMatchers: (_b = config.exclude) === null || _b === void 0 ? void 0 : _b.map((globPattern) => new minimatch_1.Minimatch(globPattern, { matchBase: true })), | ||
// Get paths patterns appropriate for TS compiler version | ||
pathsPatterns: tryParsePatterns | ||
? // TODO - Remove typecast when pathPatterns is recognized (probably after ts v4.4) | ||
((_c = configFile === null || configFile === void 0 ? void 0 : configFile.configFileSpecs) === null || _c === void 0 ? void 0 : _c.pathPatterns) || tryParsePatterns(paths) | ||
: tsInstance.getOwnKeys(paths), | ||
pathsPatterns: paths && | ||
(tryParsePatterns | ||
? // TODO - Remove typecast when pathPatterns is recognized (probably after ts v4.4) | ||
((_c = configFile === null || configFile === void 0 ? void 0 : configFile.configFileSpecs) === null || _c === void 0 ? void 0 : _c.pathPatterns) || tryParsePatterns(paths) | ||
: tsInstance.getOwnKeys(paths)), | ||
}; | ||
if (!tsTransformPathsContext.emitHost) | ||
throw new Error(`typescript-transform-paths >= 3.1.0 requires an EmitHost in the TransformationContext to resolve properly.` + | ||
` Make sure you're using either ts-patch or ttypescript.`); | ||
return (sourceFile) => { | ||
@@ -65,1 +103,2 @@ const visitorContext = Object.assign(Object.assign({}, tsTransformPathsContext), { sourceFile, isDeclarationFile: sourceFile.isDeclarationFile, originalSourceFile: tsInstance.getOriginalSourceFile(sourceFile), getVisitor() { | ||
exports.default = transformer; | ||
// endregion |
@@ -7,2 +7,5 @@ "use strict"; | ||
const resolver = transformationContext.getEmitResolver(); | ||
// Resolver may not be present if run manually (without Program) | ||
if (!resolver) | ||
return tsInstance.isImportDeclaration(node) ? node.importClause : node.exportClause; | ||
const { visitNode, isNamedImportBindings, isImportSpecifier, SyntaxKind, visitNodes, isNamedExportBindings, isExportSpecifier, } = tsInstance; | ||
@@ -9,0 +12,0 @@ if (tsInstance.isImportDeclaration(node)) { |
@@ -85,10 +85,12 @@ "use strict"; | ||
const { program, tsInstance } = context; | ||
/* Attempt to directly pull from Program */ | ||
res = program.getSourceFile(fileName); | ||
if (res) | ||
return res; | ||
/* Attempt to find without extension */ | ||
res = program.getSourceFiles().find((s) => typescript_1.removeFileExtension(s.fileName) === typescript_1.removeFileExtension(fileName)); | ||
if (res) | ||
return res; | ||
if (program) { | ||
/* Attempt to directly pull from Program */ | ||
res = program.getSourceFile(fileName); | ||
if (res) | ||
return res; | ||
/* Attempt to find without extension */ | ||
res = program.getSourceFiles().find((s) => typescript_1.removeFileExtension(s.fileName) === typescript_1.removeFileExtension(fileName)); | ||
if (res) | ||
return res; | ||
} | ||
/* | ||
@@ -123,3 +125,3 @@ * Create basic synthetic SourceFile for use with compiler API - Applies if SourceFile not found in program due to | ||
const resolvedSourceFile = getResolvedSourceFile(context, resolvedModule.resolvedFileName); | ||
const { indexType, resolvedBaseNameNoExtension, resolvedFileName, implicitPackageIndex, extName, resolvedDir, } = getPathDetail(moduleName, resolvedModule); | ||
const { indexType, resolvedBaseNameNoExtension, resolvedFileName, implicitPackageIndex, extName, resolvedDir } = getPathDetail(moduleName, resolvedModule); | ||
/* Determine output filename */ | ||
@@ -126,0 +128,0 @@ let outputBaseName = resolvedBaseNameNoExtension !== null && resolvedBaseNameNoExtension !== void 0 ? resolvedBaseNameNoExtension : ""; |
@@ -46,3 +46,3 @@ "use strict"; | ||
function getStatementTags() { | ||
var _a, _b, _c; | ||
var _a; | ||
let targetNode = tsInstance.isStatement(node) | ||
@@ -56,16 +56,41 @@ ? node | ||
} | ||
catch (_d) { } | ||
catch (_b) { } | ||
const commentTags = new Map(); | ||
try { | ||
const trivia = targetNode.getFullText(sourceFile).slice(0, targetNode.getLeadingTriviaWidth(sourceFile)); | ||
const regex = /^\s*\/\/\/?\s*@(transform-path|no-transform-path)(?:[^\S\r\n](.+?))?$/gm; | ||
const regex = /^\s*\/\/\/?\s*@(transform-path|no-transform-path)(?:[^\S\r\n](.+?))?$/gim; | ||
for (let match = regex.exec(trivia); match; match = regex.exec(trivia)) | ||
commentTags.set(match[1], match[2]); | ||
} | ||
catch (_e) { } | ||
catch (_c) { } | ||
const overridePath = findTag("transform-path"); | ||
const shouldSkip = findTag("no-transform-path"); | ||
return { | ||
overridePath: (_b = commentTags.get("transform-path")) !== null && _b !== void 0 ? _b : (_c = jsDocTags === null || jsDocTags === void 0 ? void 0 : jsDocTags.find((t) => t.tagName.text.toLowerCase() === "transform-path")) === null || _c === void 0 ? void 0 : _c.comment, | ||
shouldSkip: commentTags.has("no-transform-path") || | ||
!!(jsDocTags === null || jsDocTags === void 0 ? void 0 : jsDocTags.find((t) => t.tagName.text.toLowerCase() === "no-transform-path")), | ||
overridePath: typeof overridePath === "string" ? overridePath : void 0, | ||
shouldSkip: !!shouldSkip, | ||
}; | ||
function findTag(expected) { | ||
if (commentTags.has(expected)) | ||
return commentTags.get(expected) || true; | ||
if (!(jsDocTags === null || jsDocTags === void 0 ? void 0 : jsDocTags.length)) | ||
return void 0; | ||
for (const tag of jsDocTags) { | ||
const tagName = tag.tagName.text.toLowerCase(); | ||
if (tagName === expected) | ||
return typeof tag.comment === "string" ? tag.comment : true; | ||
/* The following handles older TS which splits tags at first hyphens */ | ||
if (typeof tag.comment !== "string" || tag.comment[0] !== "-") | ||
continue; | ||
const dashPos = expected.indexOf("-"); | ||
if (dashPos < 0) | ||
return void 0; | ||
if (tagName === expected.slice(0, dashPos)) { | ||
const comment = tag.comment; | ||
const choppedCommentTagName = comment.slice(0, expected.length - dashPos); | ||
return choppedCommentTagName === expected.slice(dashPos) | ||
? comment.slice(choppedCommentTagName.length + 1).trim() || true | ||
: void 0; | ||
} | ||
} | ||
} | ||
} | ||
@@ -72,0 +97,0 @@ } |
@@ -6,4 +6,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isModulePathsMatch = exports.getOutputDirForSourceFile = void 0; | ||
exports.getTsNodeRegistrationProperties = exports.createSyntheticEmitHost = exports.isModulePathsMatch = exports.getOutputDirForSourceFile = void 0; | ||
const path_1 = __importDefault(require("path")); | ||
const ts_node_1 = require("ts-node"); | ||
/* ****************************************************************************************************************** */ | ||
@@ -33,6 +34,41 @@ // region: TS Helpers | ||
const { pathsPatterns, tsInstance: { matchPatternOrExact }, } = context; | ||
// TODO - Remove typecast after ts v4.4 | ||
return !!matchPatternOrExact(pathsPatterns, moduleName); | ||
return !!(pathsPatterns && matchPatternOrExact(pathsPatterns, moduleName)); | ||
} | ||
exports.isModulePathsMatch = isModulePathsMatch; | ||
/** | ||
* Create barebones EmitHost (for no-Program transform) | ||
*/ | ||
function createSyntheticEmitHost(compilerOptions, tsInstance, getCanonicalFileName, fileNames) { | ||
return { | ||
getCompilerOptions: () => compilerOptions, | ||
getCurrentDirectory: tsInstance.sys.getCurrentDirectory, | ||
getCommonSourceDirectory: () => tsInstance.getCommonSourceDirectoryOfConfig({ options: compilerOptions, fileNames: fileNames }, !tsInstance.sys.useCaseSensitiveFileNames), | ||
getCanonicalFileName, | ||
}; | ||
} | ||
exports.createSyntheticEmitHost = createSyntheticEmitHost; | ||
/** | ||
* Get ts-node register info | ||
*/ | ||
function getTsNodeRegistrationProperties(tsInstance) { | ||
var _a; | ||
let tsNodeSymbol; | ||
try { | ||
tsNodeSymbol = (_a = require("ts-node")) === null || _a === void 0 ? void 0 : _a["REGISTER_INSTANCE"]; | ||
} | ||
catch (_b) { | ||
return undefined; | ||
} | ||
if (!global.process[tsNodeSymbol]) | ||
return undefined; | ||
const { config, options } = global.process[ts_node_1.REGISTER_INSTANCE]; | ||
const { configFilePath } = config.options; | ||
const pcl = configFilePath | ||
? tsInstance.getParsedCommandLineOfConfigFile(configFilePath, {}, tsInstance.sys) | ||
: void 0; | ||
const fileNames = (pcl === null || pcl === void 0 ? void 0 : pcl.fileNames) || config.fileNames; | ||
const compilerOptions = Object.assign(config.options, options.compilerOptions, { outDir: pcl === null || pcl === void 0 ? void 0 : pcl.options.outDir }); | ||
return { compilerOptions, fileNames }; | ||
} | ||
exports.getTsNodeRegistrationProperties = getTsNodeRegistrationProperties; | ||
// endregion |
{ | ||
"name": "typescript-transform-paths", | ||
"version": "3.1.0", | ||
"version": "3.2.0", | ||
"description": "Transforms module resolution paths using TypeScript path mapping", | ||
@@ -58,15 +58,14 @@ "keywords": [ | ||
"devDependencies": { | ||
"@types/jest": "^24.0.15", | ||
"@types/minimatch": "^3.0.3", | ||
"@types/node": "^12.0.2", | ||
"jest": "^24.8.0", | ||
"prettier": "^2.1.2", | ||
"@types/jest": "^26.0.24", | ||
"@types/minimatch": "^3.0.5", | ||
"@types/node": "^16.4.10", | ||
"jest": "^27.0.6", | ||
"prettier": "^2.3.2", | ||
"rimraf": "^3.0.2", | ||
"standard-version": "^8.0.1", | ||
"ts-expose-internals": "^4.2.3", | ||
"ts-jest": "^24.0.2", | ||
"ts-node": "^8.10.2", | ||
"ts-patch": "^1.3.1", | ||
"ttypescript": "^1.5.6", | ||
"typescript": "4.2.3" | ||
"standard-version": "^9.3.1", | ||
"ts-expose-internals": "^4.3.2", | ||
"ts-jest": "^27.0.4", | ||
"ts-node": "^10.1.0", | ||
"ts-patch": "^1.4.2", | ||
"typescript": "^4.3.5" | ||
}, | ||
@@ -73,0 +72,0 @@ "peerDependencies": { |
@@ -5,6 +5,5 @@ # typescript-transform-paths | ||
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2FLeDDGroup%2Ftypescript-transform-paths%2Fbadge%3Fref%3Dmaster&style=flat)](https://actions-badge.atrox.dev/LeDDGroup/typescript-transform-paths/goto?ref=master) | ||
[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/4i7egn9rn7iepg31/branch/master?svg=true)](https://ci.appveyor.com/project/danielpza/typescript-transform-paths/branch/master) | ||
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) | ||
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) | ||
[![All Contributors](https://img.shields.io/badge/all_contributors-10-orange.svg?style=flat-square)](#contributors) | ||
![All Contributors](https://img.shields.io/badge/all_contributors-10-orange.svg?style=flat-square) | ||
@@ -16,10 +15,6 @@ Transform module resolution paths in compiled output source to conform with `TypeScript` internal resolution via `tsconfig.json` settings (`paths`, `rootDirs`, `baseUrl`) | ||
```sh | ||
# NPM | ||
npm i -D typescript-transform-paths | ||
# Yarn | ||
yarn add -D typescript-transform-paths | ||
<yarn|npm|pnpm> add -D typescript-transform-paths | ||
``` | ||
## Usage with [ttypescript](https://github.com/cevek/ttypescript/) or [ts-patch](https://github.com/nonara/ts-patch) | ||
## Usage with [ts-patch](https://github.com/nonara/ts-patch) or [ttypescript](https://github.com/cevek/ttypescript/) | ||
@@ -34,6 +29,7 @@ Add it to _plugins_ in your _tsconfig.json_ | ||
"baseUrl": "./", | ||
// Configure your path mapping here | ||
"paths": { | ||
"@utils/*": ["utils/*"] | ||
}, | ||
// Note: In order to transform *both* js and d.ts files, you need to add both of the below lines to plugins | ||
// Note: To transform paths in both .js and .d.ts files, be sure to add both lines to plugins | ||
"plugins": [ | ||
@@ -62,3 +58,3 @@ // Transform paths in output .js files | ||
### Virtual Directories | ||
## Virtual Directories | ||
TS allows defining | ||
@@ -156,2 +152,38 @@ [virtual directories](https://www.typescriptlang.org/docs/handbook/module-resolution.html#virtual-directories-with-rootdirs) | ||
## `ts-node` & TS Compiler API Usage | ||
### Note | ||
Most people using `ts-node` can achieve what they want without the transformer, by using [tsconfig-paths](https://github.com/dividab/tsconfig-paths#readme]) (ie. `ts-node -r tsconfig-paths`) | ||
### Others | ||
If you'd still like to use the transformer, it is now possible to do so programmatically, with or without a `Program` instance. This can be done via `ts-node` or the compiler API using `ts.transform()`. | ||
Here is an example of how to register `ts-node` with the transformer: | ||
```ts | ||
import transformer, { TsTransformPathsConfig } from 'typescript-transform-paths'; | ||
import { register } from 'ts-node'; | ||
import ts from 'typescript'; | ||
const pluginConfig: TsTransformPathsConfig = { | ||
useRootDirs: false | ||
}; | ||
// Use this code if using transpileOnly | ||
register({ | ||
transpileOnly: true, | ||
transformers: { | ||
before: [ transformer(/* Program */ undefined, pluginConfig) ] | ||
} | ||
}); | ||
// Use this if not using transpileOnly | ||
register({ | ||
transformers: (program: ts.Program) => { before: [ transformer(program, pluginConfig) ] } | ||
}); | ||
``` | ||
For TS compiler API usage example, have a look at the logic in [specific.test.ts](https://github.com/LeDDGroup/typescript-transform-paths/blob/master/test/tests/transformer/specific.test.ts) for `manual` mode. | ||
## Articles | ||
@@ -158,0 +190,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
61452
12
748
205