ts-add-js-extension
Version:
Add .js extension to each relative ESM import and export statement in JavaScript file
235 lines • 8.85 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var fs_1 = __importDefault(require("fs"));
var path_1 = __importDefault(require("path"));
var typescript_1 = __importDefault(require("typescript"));
var const_1 = require("./const");
var type_1 = require("./type");
var formProperFilePath = function (props) {
return props.filePath.split(const_1.separator).filter(Boolean).join(const_1.separator);
};
var checkJavaScriptFileExistByAppend = function (props) {
var result = const_1.extensions.javaScript
.map(function (extension) {
return {
extension: extension,
filePath: "".concat(props.filePath).concat(extension),
};
})
.find(function (filePath) {
return fs_1.default.existsSync(filePath.filePath);
});
return result !== null && result !== void 0 ? result : false;
};
var checkTypeDefinitionFileExistByAppend = function (props) {
var _a = const_1.extensions.javaScript, js = _a[0], mjs = _a[1];
var _b = const_1.extensions.typeDefinition, dts = _b[0], mdts = _b[1];
var dtsFilePath = "".concat(props.filePath).concat(dts);
if (fs_1.default.existsSync(dtsFilePath)) {
return { extension: js, filePath: dtsFilePath };
}
var mdtsFilePath = "".concat(props.filePath).concat(mdts);
if (fs_1.default.existsSync(mdtsFilePath)) {
return { extension: mjs, filePath: mdtsFilePath };
}
return false;
};
var isDirectory = function (path) {
return fs_1.default.existsSync(path) && fs_1.default.lstatSync(path).isDirectory();
};
var addJSExtensionConditionally = function (props) {
var check = props.checkType === 'js'
? checkJavaScriptFileExistByAppend
: checkTypeDefinitionFileExistByAppend;
var skip = {
procedure: 'skip',
};
if (isDirectory(props.filePath)) {
var result_1 = check({
filePath: path_1.default.posix.join(props.filePath, 'index'),
});
if (!result_1) {
return skip;
}
var file = "index".concat(result_1.extension);
return {
procedure: 'proceed',
absolutePath: result_1.filePath,
importPath: formProperFilePath({
filePath: "".concat(props.importPath).concat(const_1.separator).concat(file),
}),
};
}
var result = check({
filePath: props.filePath,
});
if (!result) {
return skip;
}
return {
procedure: 'proceed',
absolutePath: result.filePath,
importPath: formProperFilePath({
filePath: "".concat(props.importPath).concat(result.extension),
}),
};
};
var addJSExtension = function (props) {
if ((0, const_1.matchJs)(props.filePath)) {
return {
procedure: 'skip',
};
}
var result = addJSExtensionConditionally(__assign(__assign({}, props), { checkType: 'js' }));
switch (result.procedure) {
case 'proceed': {
return result;
}
case 'skip': {
return addJSExtensionConditionally(__assign(__assign({}, props), { checkType: 'dts' }));
}
}
};
var generateModuleSpecifier = function (props) {
if (!props.moduleSpecifier.startsWith('.')) {
return undefined;
}
var result = addJSExtension({
importPath: props.moduleSpecifier,
filePath: path_1.default.posix.join(props.file, '..', props.moduleSpecifier),
});
switch (result.procedure) {
case 'proceed': {
if (props.files.find(function (file) {
return file.endsWith(result.absolutePath);
})) {
return result.importPath;
}
}
}
return undefined;
};
var nodeIsStringLiteral = function (node) {
return (typescript_1.default.isStringLiteral(node) || typescript_1.default.isNoSubstitutionTemplateLiteral(node));
};
var dynamicJsImport = function (props) {
var node = props.node;
if (node.expression.kind === typescript_1.default.SyntaxKind.ImportKeyword) {
var argument = (0, type_1.guard)({
value: node.arguments[0],
error: new Error("Dynamic import must have a path"),
});
if (nodeIsStringLiteral(argument)) {
var text = generateModuleSpecifier(__assign(__assign({}, props.fileInfo), { moduleSpecifier: argument.text }));
if (!text) {
return node;
}
props.fileInfo.updateFile();
return props.factory.updateCallExpression(node, node.expression, node.typeArguments, [props.factory.createStringLiteral(text)]);
}
}
return node;
};
var dynamicDtsImport = function (props) {
var node = props.node;
var argument = node.argument;
if (typescript_1.default.isLiteralTypeNode(argument)) {
var literal = argument.literal;
if (nodeIsStringLiteral(literal)) {
var text = generateModuleSpecifier(__assign(__assign({}, props.fileInfo), { moduleSpecifier: literal.text }));
if (!text) {
return node;
}
props.fileInfo.updateFile();
return props.factory.updateImportTypeNode(node, props.factory.updateLiteralTypeNode(argument, props.factory.createStringLiteral(text)), node.attributes, node.qualifier, node.typeArguments, node.isTypeOf);
}
}
return node;
};
var staticImportExport = function (props) {
var node = props.node;
var moduleSpecifier = node.moduleSpecifier;
if (!moduleSpecifier || !typescript_1.default.isStringLiteral(moduleSpecifier)) {
return node;
}
var text = generateModuleSpecifier(__assign(__assign({}, props.fileInfo), { moduleSpecifier: moduleSpecifier.text }));
if (!text) {
return node;
}
props.fileInfo.updateFile();
if (typescript_1.default.isImportDeclaration(node)) {
return props.factory.updateImportDeclaration(node, node.modifiers, node.importClause, props.factory.createStringLiteral(text), node.attributes);
}
return props.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, props.factory.createStringLiteral(text), node.attributes);
};
var updateImportExport = function (props) {
return function (parent) {
var node = typescript_1.default.visitEachChild(parent, updateImportExport(props), props.context);
var parameters = {
fileInfo: props.fileInfo,
factory: props.context.factory,
};
if (typescript_1.default.isImportDeclaration(node) || typescript_1.default.isExportDeclaration(node)) {
return staticImportExport(__assign(__assign({}, parameters), { node: node }));
}
else if (typescript_1.default.isCallExpression(node)) {
return dynamicJsImport(__assign(__assign({}, parameters), { node: node }));
}
else if (typescript_1.default.isImportTypeNode(node)) {
return dynamicDtsImport(__assign(__assign({}, parameters), { node: node }));
}
return node;
};
};
var traverse = function (props) {
return function (context) {
return function (rootNode) {
return typescript_1.default.visitNode(rootNode, updateImportExport(__assign(__assign({}, props), { context: context })));
};
};
};
var traverseAndUpdateFile = function (metainfo) {
var printer = typescript_1.default.createPrinter();
var fileUpdated = false;
var file = metainfo.sourceFile.fileName;
var transformer = traverse({
fileInfo: {
files: metainfo.files,
file: file,
updateFile: function () {
fileUpdated = true;
},
},
});
var code = printer.printNode(typescript_1.default.EmitHint.Unspecified, (0, type_1.guard)({
value: typescript_1.default
.transform(metainfo.sourceFile, [transformer])
.transformed.at(0),
error: new Error('Transformer should have a transformed value'),
}), metainfo.sourceFile);
if (!fileUpdated) {
return [];
}
return [
{
file: file,
code: code,
},
];
};
exports.default = traverseAndUpdateFile;
//# sourceMappingURL=traverse-and-update.js.map