@tamagui/babel-plugin-fully-specified
Advanced tools
Comparing version 1.101.7 to 1.102.0
@@ -20,33 +20,80 @@ var __defProp = Object.defineProperty; | ||
module.exports = __toCommonJS(src_exports); | ||
var import_node_fs = require("node:fs"), import_node_path = require("node:path"), import_types = require("@babel/types"); | ||
const makeDeclaration = ({ | ||
declaration, | ||
makeNodes, | ||
ensureFileExists = !1, | ||
esExtensionDefault = ".js", | ||
// List of all extensions which we try to find | ||
tryExtensions = [".js", ".mjs", ".cjs"], | ||
// List of extensions that can run in Node.js or in the Browser | ||
esExtensions = [".js", ".mjs", ".cjs"], | ||
// List of packages that also should be transformed with this plugin | ||
includePackages = [] | ||
}) => (path, { | ||
file: { | ||
opts: { filename } | ||
} | ||
}) => { | ||
const { source } = path.node; | ||
if (!source || !filename) | ||
return; | ||
const { exportKind, importKind } = path.node; | ||
if (exportKind === "type" || importKind === "type") | ||
return; | ||
const { value } = source, module2 = value; | ||
var import_node_fs = require("node:fs"), import_node_path = require("node:path"); | ||
const DEFAULT_OPTIONS = { | ||
ensureFileExists: !1, | ||
esExtensionDefault: ".js", | ||
tryExtensions: [".js", ".mjs", ".cjs"], | ||
esExtensions: [".js", ".mjs", ".cjs"], | ||
includePackages: [] | ||
}; | ||
function FullySpecified(api, rawOptions) { | ||
api.assertVersion(7); | ||
const options = { ...DEFAULT_OPTIONS, ...rawOptions }, importDeclarationVisitor = (path, state) => { | ||
const filePath = state.file.opts.filename; | ||
if (!filePath) return; | ||
const { node } = path; | ||
if (node.importKind === "type") return; | ||
const originalModuleSpecifier = node.source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options | ||
} | ||
); | ||
fullySpecifiedModuleSpecifier && (node.source.value = fullySpecifiedModuleSpecifier); | ||
}, exportDeclarationVisitor = (path, state) => { | ||
const filePath = state.file.opts.filename; | ||
if (!filePath) return; | ||
const { node } = path; | ||
if (node.exportKind === "type") return; | ||
const source = node.source; | ||
if (!source) return; | ||
const originalModuleSpecifier = source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options | ||
} | ||
); | ||
fullySpecifiedModuleSpecifier && (source.value = fullySpecifiedModuleSpecifier); | ||
}; | ||
return { | ||
name: "babel-plugin-fully-specified", | ||
visitor: { | ||
ImportDeclaration: importDeclarationVisitor, | ||
ExportNamedDeclaration: exportDeclarationVisitor, | ||
ExportAllDeclaration: exportDeclarationVisitor, | ||
Import: (path, state) => { | ||
const filePath = state.file.opts.filename; | ||
if (!filePath) return; | ||
const parent = path.parent; | ||
if (parent.type !== "CallExpression") | ||
return; | ||
const firstArgOfImportCall = parent.arguments[0]; | ||
if (firstArgOfImportCall.type !== "StringLiteral") | ||
return; | ||
const originalModuleSpecifier = firstArgOfImportCall.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options | ||
} | ||
); | ||
fullySpecifiedModuleSpecifier && (firstArgOfImportCall.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
}; | ||
} | ||
function getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}) { | ||
const fileExt = (0, import_node_path.extname)(filePath), fileDir = (0, import_node_path.dirname)(filePath), { includePackages } = options; | ||
let packageData = null; | ||
if (!isLocalFile(module2) && (includePackages.some((name) => module2.startsWith(name)) && (packageData = getPackageData(module2)), !(packageData && packageData.hasPath))) | ||
return; | ||
const filenameExtension = (0, import_node_path.extname)(filename), filenameDirectory = (0, import_node_path.dirname)(filename), isDirectory = isLocalDirectory((0, import_node_path.resolve)(filenameDirectory, module2)), currentModuleExtension = (0, import_node_path.extname)(module2), targetModule = evaluateTargetModule({ | ||
module: module2, | ||
filenameDirectory, | ||
filenameExtension, | ||
if (!isLocalFile(originalModuleSpecifier) && (includePackages.some((name) => originalModuleSpecifier.startsWith(name)) && (packageData = getPackageData(originalModuleSpecifier, filePath)), !(packageData && packageData.isDeepImport))) | ||
return null; | ||
const isDirectory = isLocalDirectory((0, import_node_path.resolve)(fileDir, originalModuleSpecifier)), currentModuleExtension = (0, import_node_path.extname)(originalModuleSpecifier), { tryExtensions, esExtensions, esExtensionDefault, ensureFileExists } = options, targetModule = evaluateTargetModule({ | ||
moduleSpecifier: originalModuleSpecifier, | ||
filenameDirectory: fileDir, | ||
filenameExtension: fileExt, | ||
packageData, | ||
@@ -60,35 +107,9 @@ currentModuleExtension, | ||
}); | ||
if (targetModule === !1 || currentModuleExtension === targetModule.extension) | ||
return; | ||
const nodes = makeNodes(path); | ||
path.replaceWith( | ||
// @ts-ignore | ||
declaration.apply(null, [...nodes, (0, import_types.stringLiteral)(targetModule.module)]) | ||
); | ||
}; | ||
function FullySpecified(api, options) { | ||
return api.assertVersion(7), { | ||
name: "babel-plugin-fully-specified", | ||
visitor: { | ||
ImportDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: import_types.importDeclaration, | ||
makeNodes: ({ node: { specifiers } }) => [specifiers] | ||
}), | ||
ExportNamedDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: import_types.exportNamedDeclaration, | ||
makeNodes: ({ node: { declaration, specifiers } }) => [declaration, specifiers] | ||
}), | ||
ExportAllDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: import_types.exportAllDeclaration, | ||
makeNodes: () => [] | ||
}) | ||
} | ||
}; | ||
return targetModule === !1 || currentModuleExtension === targetModule.extension ? null : targetModule.module; | ||
} | ||
function getPackageData(module2) { | ||
function getPackageData(moduleSpecifier, filePath) { | ||
try { | ||
const packagePath = require.resolve(module2), parts = packagePath.split("/"); | ||
const modulePath = require.resolve(moduleSpecifier, { | ||
paths: filePath ? [filePath] : [] | ||
}), parts = modulePath.split("/"); | ||
let packageDir = ""; | ||
@@ -105,3 +126,3 @@ for (let i = parts.length; i >= 0; i--) { | ||
const packageJson = JSON.parse((0, import_node_fs.readFileSync)(`${packageDir}/package.json`).toString()); | ||
return { hasPath: !module2.endsWith(packageJson.name), packagePath }; | ||
return { isDeepImport: !moduleSpecifier.endsWith(packageJson.name), modulePath }; | ||
} catch { | ||
@@ -111,4 +132,4 @@ } | ||
} | ||
function isLocalFile(module2) { | ||
return module2.startsWith(".") || module2.startsWith("/"); | ||
function isLocalFile(moduleSpecifier) { | ||
return moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("/"); | ||
} | ||
@@ -119,3 +140,3 @@ function isLocalDirectory(absoluteDirectory) { | ||
function evaluateTargetModule({ | ||
module: module2, | ||
moduleSpecifier, | ||
currentModuleExtension, | ||
@@ -132,4 +153,4 @@ packageData, | ||
if (packageData) | ||
return packageData.packagePath.endsWith("index.js") && !module2.endsWith("index.js") && (module2 = `${module2}/index`), { | ||
module: module2 + esExtensionDefault, | ||
return packageData.modulePath.endsWith("index.js") && !moduleSpecifier.endsWith("index.js") && (moduleSpecifier = `${moduleSpecifier}/index`), { | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -142,10 +163,10 @@ }; | ||
filenameDirectory, | ||
currentModuleExtension ? module2 : module2 + esExtensionDefault | ||
currentModuleExtension ? moduleSpecifier : moduleSpecifier + esExtensionDefault | ||
) | ||
) && (module2 = `${module2}/index`); | ||
const targetFile = (0, import_node_path.resolve)(filenameDirectory, module2); | ||
) && (moduleSpecifier = `${moduleSpecifier}/index`); | ||
const targetFile = (0, import_node_path.resolve)(filenameDirectory, moduleSpecifier); | ||
if (ensureFileExists) { | ||
if (esExtensions.includes(filenameExtension) && (0, import_node_fs.existsSync)(targetFile + filenameExtension)) | ||
return { | ||
module: module2 + filenameExtension, | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || filenameExtension), | ||
extension: filenameExtension | ||
@@ -155,8 +176,11 @@ }; | ||
if ((0, import_node_fs.existsSync)(targetFile + extension)) | ||
return { module: module2 + ".mjs", extension }; | ||
return { | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || extension), | ||
extension | ||
}; | ||
} else return esExtensions.includes(filenameExtension) ? { | ||
module: module2 + filenameExtension, | ||
module: moduleSpecifier + filenameExtension, | ||
extension: filenameExtension | ||
} : { | ||
module: module2 + esExtensionDefault, | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -163,0 +187,0 @@ }; |
@@ -21,11 +21,3 @@ "use strict"; | ||
module.exports = __toCommonJS(src_exports); | ||
var import_node_fs = require("node:fs"), import_node_path = require("node:path"), import_types = require("@babel/types"); | ||
function _array_like_to_array(arr, len) { | ||
(len == null || len > arr.length) && (len = arr.length); | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; | ||
return arr2; | ||
} | ||
function _array_without_holes(arr) { | ||
if (Array.isArray(arr)) return _array_like_to_array(arr); | ||
} | ||
var import_node_fs = require("node:fs"), import_node_path = require("node:path"); | ||
function _define_property(obj, key, value) { | ||
@@ -39,14 +31,8 @@ return key in obj ? Object.defineProperty(obj, key, { | ||
} | ||
function _iterable_to_array(iter) { | ||
if (typeof Symbol < "u" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); | ||
} | ||
function _non_iterable_spread() { | ||
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
} | ||
function _object_spread(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}, ownKeys2 = Object.keys(source); | ||
typeof Object.getOwnPropertySymbols == "function" && (ownKeys2 = ownKeys2.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { | ||
var source = arguments[i] != null ? arguments[i] : {}, ownKeys = Object.keys(source); | ||
typeof Object.getOwnPropertySymbols == "function" && (ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { | ||
return Object.getOwnPropertyDescriptor(source, sym).enumerable; | ||
}))), ownKeys2.forEach(function(key) { | ||
}))), ownKeys.forEach(function(key) { | ||
_define_property(target, key, source[key]); | ||
@@ -57,108 +43,99 @@ }); | ||
} | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
enumerableOnly && (symbols = symbols.filter(function(sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
})), keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _object_spread_props(target, source) { | ||
return source = source ?? {}, Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function(key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}), target; | ||
} | ||
function _to_consumable_array(arr) { | ||
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread(); | ||
} | ||
function _unsupported_iterable_to_array(o, minLen) { | ||
if (o) { | ||
if (typeof o == "string") return _array_like_to_array(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor && (n = o.constructor.name), n === "Map" || n === "Set") return Array.from(n); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); | ||
} | ||
} | ||
var makeDeclaration = function(param) { | ||
var declaration = param.declaration, makeNodes = param.makeNodes, _param_ensureFileExists = param.ensureFileExists, ensureFileExists = _param_ensureFileExists === void 0 ? !1 : _param_ensureFileExists, _param_esExtensionDefault = param.esExtensionDefault, esExtensionDefault = _param_esExtensionDefault === void 0 ? ".js" : _param_esExtensionDefault, _param_tryExtensions = param.tryExtensions, tryExtensions = _param_tryExtensions === void 0 ? [ | ||
var DEFAULT_OPTIONS = { | ||
ensureFileExists: !1, | ||
esExtensionDefault: ".js", | ||
tryExtensions: [ | ||
".js", | ||
".mjs", | ||
".cjs" | ||
] : _param_tryExtensions, _param_esExtensions = param.esExtensions, esExtensions = _param_esExtensions === void 0 ? [ | ||
], | ||
esExtensions: [ | ||
".js", | ||
".mjs", | ||
".cjs" | ||
] : _param_esExtensions, _param_includePackages = param.includePackages, includePackages = _param_includePackages === void 0 ? [] : _param_includePackages; | ||
return function(path, param2) { | ||
var _param_file = param2.file, filename = _param_file.opts.filename, source = path.node.source; | ||
if (!(!source || !filename)) { | ||
var _path_node = path.node, exportKind = _path_node.exportKind, importKind = _path_node.importKind, isTypeOnly = exportKind === "type" || importKind === "type"; | ||
if (!isTypeOnly) { | ||
var value = source.value, module2 = value, packageData = null; | ||
if (!(!isLocalFile(module2) && (includePackages.some(function(name) { | ||
return module2.startsWith(name); | ||
}) && (packageData = getPackageData(module2)), !(packageData && packageData.hasPath)))) { | ||
var filenameExtension = (0, import_node_path.extname)(filename), filenameDirectory = (0, import_node_path.dirname)(filename), isDirectory = isLocalDirectory((0, import_node_path.resolve)(filenameDirectory, module2)), currentModuleExtension = (0, import_node_path.extname)(module2), targetModule = evaluateTargetModule({ | ||
module: module2, | ||
filenameDirectory, | ||
filenameExtension, | ||
packageData, | ||
currentModuleExtension, | ||
isDirectory, | ||
tryExtensions, | ||
esExtensions, | ||
esExtensionDefault, | ||
ensureFileExists | ||
], | ||
includePackages: [] | ||
}; | ||
function FullySpecified(api, rawOptions) { | ||
api.assertVersion(7); | ||
var options = _object_spread({}, DEFAULT_OPTIONS, rawOptions), importDeclarationVisitor = function(path, state) { | ||
var filePath = state.file.opts.filename; | ||
if (filePath) { | ||
var node = path.node; | ||
if (node.importKind !== "type") { | ||
var originalModuleSpecifier = node.source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}); | ||
fullySpecifiedModuleSpecifier && (node.source.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
}, exportDeclarationVisitor = function(path, state) { | ||
var filePath = state.file.opts.filename; | ||
if (filePath) { | ||
var node = path.node; | ||
if (node.exportKind !== "type") { | ||
var source = node.source; | ||
if (source) { | ||
var originalModuleSpecifier = source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}); | ||
if (!(targetModule === !1 || currentModuleExtension === targetModule.extension)) { | ||
var nodes = makeNodes(path); | ||
path.replaceWith( | ||
// @ts-ignore | ||
declaration.apply(null, _to_consumable_array(nodes).concat([ | ||
(0, import_types.stringLiteral)(targetModule.module) | ||
])) | ||
); | ||
} | ||
fullySpecifiedModuleSpecifier && (source.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
} | ||
}, importVisitor = function(path, state) { | ||
var filePath = state.file.opts.filename; | ||
if (filePath) { | ||
var parent = path.parent; | ||
if (parent.type === "CallExpression") { | ||
var firstArgOfImportCall = parent.arguments[0]; | ||
if (firstArgOfImportCall.type === "StringLiteral") { | ||
var originalModuleSpecifier = firstArgOfImportCall.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}); | ||
fullySpecifiedModuleSpecifier && (firstArgOfImportCall.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
function FullySpecified(api, options) { | ||
return api.assertVersion(7), { | ||
return { | ||
name: "babel-plugin-fully-specified", | ||
visitor: { | ||
ImportDeclaration: makeDeclaration(_object_spread_props(_object_spread({}, options), { | ||
declaration: import_types.importDeclaration, | ||
makeNodes: function(param) { | ||
var specifiers = param.node.specifiers; | ||
return [ | ||
specifiers | ||
]; | ||
} | ||
})), | ||
ExportNamedDeclaration: makeDeclaration(_object_spread_props(_object_spread({}, options), { | ||
declaration: import_types.exportNamedDeclaration, | ||
makeNodes: function(param) { | ||
var _param_node = param.node, declaration = _param_node.declaration, specifiers = _param_node.specifiers; | ||
return [ | ||
declaration, | ||
specifiers | ||
]; | ||
} | ||
})), | ||
ExportAllDeclaration: makeDeclaration(_object_spread_props(_object_spread({}, options), { | ||
declaration: import_types.exportAllDeclaration, | ||
makeNodes: function() { | ||
return []; | ||
} | ||
})) | ||
ImportDeclaration: importDeclarationVisitor, | ||
ExportNamedDeclaration: exportDeclarationVisitor, | ||
ExportAllDeclaration: exportDeclarationVisitor, | ||
Import: importVisitor | ||
} | ||
}; | ||
} | ||
function getPackageData(module2) { | ||
function getFullySpecifiedModuleSpecifier(originalModuleSpecifier, param) { | ||
var filePath = param.filePath, options = param.options, fileExt = (0, import_node_path.extname)(filePath), fileDir = (0, import_node_path.dirname)(filePath), includePackages = options.includePackages, packageData = null; | ||
if (!isLocalFile(originalModuleSpecifier) && (includePackages.some(function(name) { | ||
return originalModuleSpecifier.startsWith(name); | ||
}) && (packageData = getPackageData(originalModuleSpecifier, filePath)), !(packageData && packageData.isDeepImport))) | ||
return null; | ||
var isDirectory = isLocalDirectory((0, import_node_path.resolve)(fileDir, originalModuleSpecifier)), currentModuleExtension = (0, import_node_path.extname)(originalModuleSpecifier), tryExtensions = options.tryExtensions, esExtensions = options.esExtensions, esExtensionDefault = options.esExtensionDefault, ensureFileExists = options.ensureFileExists, targetModule = evaluateTargetModule({ | ||
moduleSpecifier: originalModuleSpecifier, | ||
filenameDirectory: fileDir, | ||
filenameExtension: fileExt, | ||
packageData, | ||
currentModuleExtension, | ||
isDirectory, | ||
tryExtensions, | ||
esExtensions, | ||
esExtensionDefault, | ||
ensureFileExists | ||
}); | ||
return targetModule === !1 || currentModuleExtension === targetModule.extension ? null : targetModule.module; | ||
} | ||
function getPackageData(moduleSpecifier, filePath) { | ||
try { | ||
for (var packagePath = require.resolve(module2), parts = packagePath.split("/"), packageDir = "", i = parts.length; i >= 0; i--) { | ||
for (var modulePath = require.resolve(moduleSpecifier, { | ||
paths: filePath ? [ | ||
filePath | ||
] : [] | ||
}), parts = modulePath.split("/"), packageDir = "", i = parts.length; i >= 0; i--) { | ||
var dir = (0, import_node_path.dirname)(parts.slice(0, i).join("/")); | ||
@@ -172,6 +149,6 @@ if ((0, import_node_fs.existsSync)("".concat(dir, "/package.json"))) { | ||
throw new Error("no package dir"); | ||
var packageJson = JSON.parse((0, import_node_fs.readFileSync)("".concat(packageDir, "/package.json")).toString()), hasPath = !module2.endsWith(packageJson.name); | ||
var packageJson = JSON.parse((0, import_node_fs.readFileSync)("".concat(packageDir, "/package.json")).toString()), isDeepImport = !moduleSpecifier.endsWith(packageJson.name); | ||
return { | ||
hasPath, | ||
packagePath | ||
isDeepImport, | ||
modulePath | ||
}; | ||
@@ -182,4 +159,4 @@ } catch { | ||
} | ||
function isLocalFile(module2) { | ||
return module2.startsWith(".") || module2.startsWith("/"); | ||
function isLocalFile(moduleSpecifier) { | ||
return moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("/"); | ||
} | ||
@@ -190,6 +167,6 @@ function isLocalDirectory(absoluteDirectory) { | ||
function evaluateTargetModule(param) { | ||
var module2 = param.module, currentModuleExtension = param.currentModuleExtension, packageData = param.packageData, isDirectory = param.isDirectory, filenameDirectory = param.filenameDirectory, filenameExtension = param.filenameExtension, tryExtensions = param.tryExtensions, esExtensions = param.esExtensions, esExtensionDefault = param.esExtensionDefault, ensureFileExists = param.ensureFileExists; | ||
var moduleSpecifier = param.moduleSpecifier, currentModuleExtension = param.currentModuleExtension, packageData = param.packageData, isDirectory = param.isDirectory, filenameDirectory = param.filenameDirectory, filenameExtension = param.filenameExtension, tryExtensions = param.tryExtensions, esExtensions = param.esExtensions, esExtensionDefault = param.esExtensionDefault, ensureFileExists = param.ensureFileExists; | ||
if (packageData) | ||
return packageData.packagePath.endsWith("index.js") && !module2.endsWith("index.js") && (module2 = "".concat(module2, "/index")), { | ||
module: module2 + esExtensionDefault, | ||
return packageData.modulePath.endsWith("index.js") && !moduleSpecifier.endsWith("index.js") && (moduleSpecifier = "".concat(moduleSpecifier, "/index")), { | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -199,8 +176,8 @@ }; | ||
return !1; | ||
isDirectory && !(0, import_node_fs.existsSync)((0, import_node_path.resolve)(filenameDirectory, currentModuleExtension ? module2 : module2 + esExtensionDefault)) && (module2 = "".concat(module2, "/index")); | ||
var targetFile = (0, import_node_path.resolve)(filenameDirectory, module2); | ||
isDirectory && !(0, import_node_fs.existsSync)((0, import_node_path.resolve)(filenameDirectory, currentModuleExtension ? moduleSpecifier : moduleSpecifier + esExtensionDefault)) && (moduleSpecifier = "".concat(moduleSpecifier, "/index")); | ||
var targetFile = (0, import_node_path.resolve)(filenameDirectory, moduleSpecifier); | ||
if (ensureFileExists) { | ||
if (esExtensions.includes(filenameExtension) && (0, import_node_fs.existsSync)(targetFile + filenameExtension)) | ||
return { | ||
module: module2 + filenameExtension, | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || filenameExtension), | ||
extension: filenameExtension | ||
@@ -214,3 +191,3 @@ }; | ||
return { | ||
module: module2 + ".mjs", | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || extension), | ||
extension | ||
@@ -230,6 +207,6 @@ }; | ||
} else return esExtensions.includes(filenameExtension) ? { | ||
module: module2 + filenameExtension, | ||
module: moduleSpecifier + filenameExtension, | ||
extension: filenameExtension | ||
} : { | ||
module: module2 + esExtensionDefault, | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -236,0 +213,0 @@ }; |
import { existsSync, readFileSync, lstatSync } from "node:fs"; | ||
import { resolve, extname, dirname } from "node:path"; | ||
import { | ||
importDeclaration, | ||
exportNamedDeclaration, | ||
exportAllDeclaration, | ||
stringLiteral | ||
} from "@babel/types"; | ||
const makeDeclaration = ({ | ||
declaration, | ||
makeNodes, | ||
ensureFileExists = !1, | ||
esExtensionDefault = ".js", | ||
// List of all extensions which we try to find | ||
tryExtensions = [".js", ".mjs", ".cjs"], | ||
// List of extensions that can run in Node.js or in the Browser | ||
esExtensions = [".js", ".mjs", ".cjs"], | ||
// List of packages that also should be transformed with this plugin | ||
includePackages = [] | ||
}) => (path, { | ||
file: { | ||
opts: { filename } | ||
} | ||
}) => { | ||
const { source } = path.node; | ||
if (!source || !filename) | ||
return; | ||
const { exportKind, importKind } = path.node; | ||
if (exportKind === "type" || importKind === "type") | ||
return; | ||
const { value } = source, module = value; | ||
const DEFAULT_OPTIONS = { | ||
ensureFileExists: !1, | ||
esExtensionDefault: ".js", | ||
tryExtensions: [".js", ".mjs", ".cjs"], | ||
esExtensions: [".js", ".mjs", ".cjs"], | ||
includePackages: [] | ||
}; | ||
function FullySpecified(api, rawOptions) { | ||
api.assertVersion(7); | ||
const options = { ...DEFAULT_OPTIONS, ...rawOptions }, importDeclarationVisitor = (path, state) => { | ||
const filePath = state.file.opts.filename; | ||
if (!filePath) return; | ||
const { node } = path; | ||
if (node.importKind === "type") return; | ||
const originalModuleSpecifier = node.source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options | ||
} | ||
); | ||
fullySpecifiedModuleSpecifier && (node.source.value = fullySpecifiedModuleSpecifier); | ||
}, exportDeclarationVisitor = (path, state) => { | ||
const filePath = state.file.opts.filename; | ||
if (!filePath) return; | ||
const { node } = path; | ||
if (node.exportKind === "type") return; | ||
const source = node.source; | ||
if (!source) return; | ||
const originalModuleSpecifier = source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options | ||
} | ||
); | ||
fullySpecifiedModuleSpecifier && (source.value = fullySpecifiedModuleSpecifier); | ||
}; | ||
return { | ||
name: "babel-plugin-fully-specified", | ||
visitor: { | ||
ImportDeclaration: importDeclarationVisitor, | ||
ExportNamedDeclaration: exportDeclarationVisitor, | ||
ExportAllDeclaration: exportDeclarationVisitor, | ||
Import: (path, state) => { | ||
const filePath = state.file.opts.filename; | ||
if (!filePath) return; | ||
const parent = path.parent; | ||
if (parent.type !== "CallExpression") | ||
return; | ||
const firstArgOfImportCall = parent.arguments[0]; | ||
if (firstArgOfImportCall.type !== "StringLiteral") | ||
return; | ||
const originalModuleSpecifier = firstArgOfImportCall.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options | ||
} | ||
); | ||
fullySpecifiedModuleSpecifier && (firstArgOfImportCall.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
}; | ||
} | ||
function getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}) { | ||
const fileExt = extname(filePath), fileDir = dirname(filePath), { includePackages } = options; | ||
let packageData = null; | ||
if (!isLocalFile(module) && (includePackages.some((name) => module.startsWith(name)) && (packageData = getPackageData(module)), !(packageData && packageData.hasPath))) | ||
return; | ||
const filenameExtension = extname(filename), filenameDirectory = dirname(filename), isDirectory = isLocalDirectory(resolve(filenameDirectory, module)), currentModuleExtension = extname(module), targetModule = evaluateTargetModule({ | ||
module, | ||
filenameDirectory, | ||
filenameExtension, | ||
if (!isLocalFile(originalModuleSpecifier) && (includePackages.some((name) => originalModuleSpecifier.startsWith(name)) && (packageData = getPackageData(originalModuleSpecifier, filePath)), !(packageData && packageData.isDeepImport))) | ||
return null; | ||
const isDirectory = isLocalDirectory(resolve(fileDir, originalModuleSpecifier)), currentModuleExtension = extname(originalModuleSpecifier), { tryExtensions, esExtensions, esExtensionDefault, ensureFileExists } = options, targetModule = evaluateTargetModule({ | ||
moduleSpecifier: originalModuleSpecifier, | ||
filenameDirectory: fileDir, | ||
filenameExtension: fileExt, | ||
packageData, | ||
@@ -47,35 +88,9 @@ currentModuleExtension, | ||
}); | ||
if (targetModule === !1 || currentModuleExtension === targetModule.extension) | ||
return; | ||
const nodes = makeNodes(path); | ||
path.replaceWith( | ||
// @ts-ignore | ||
declaration.apply(null, [...nodes, stringLiteral(targetModule.module)]) | ||
); | ||
}; | ||
function FullySpecified(api, options) { | ||
return api.assertVersion(7), { | ||
name: "babel-plugin-fully-specified", | ||
visitor: { | ||
ImportDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: importDeclaration, | ||
makeNodes: ({ node: { specifiers } }) => [specifiers] | ||
}), | ||
ExportNamedDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: exportNamedDeclaration, | ||
makeNodes: ({ node: { declaration, specifiers } }) => [declaration, specifiers] | ||
}), | ||
ExportAllDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: exportAllDeclaration, | ||
makeNodes: () => [] | ||
}) | ||
} | ||
}; | ||
return targetModule === !1 || currentModuleExtension === targetModule.extension ? null : targetModule.module; | ||
} | ||
function getPackageData(module) { | ||
function getPackageData(moduleSpecifier, filePath) { | ||
try { | ||
const packagePath = require.resolve(module), parts = packagePath.split("/"); | ||
const modulePath = require.resolve(moduleSpecifier, { | ||
paths: filePath ? [filePath] : [] | ||
}), parts = modulePath.split("/"); | ||
let packageDir = ""; | ||
@@ -92,3 +107,3 @@ for (let i = parts.length; i >= 0; i--) { | ||
const packageJson = JSON.parse(readFileSync(`${packageDir}/package.json`).toString()); | ||
return { hasPath: !module.endsWith(packageJson.name), packagePath }; | ||
return { isDeepImport: !moduleSpecifier.endsWith(packageJson.name), modulePath }; | ||
} catch { | ||
@@ -98,4 +113,4 @@ } | ||
} | ||
function isLocalFile(module) { | ||
return module.startsWith(".") || module.startsWith("/"); | ||
function isLocalFile(moduleSpecifier) { | ||
return moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("/"); | ||
} | ||
@@ -106,3 +121,3 @@ function isLocalDirectory(absoluteDirectory) { | ||
function evaluateTargetModule({ | ||
module, | ||
moduleSpecifier, | ||
currentModuleExtension, | ||
@@ -119,4 +134,4 @@ packageData, | ||
if (packageData) | ||
return packageData.packagePath.endsWith("index.js") && !module.endsWith("index.js") && (module = `${module}/index`), { | ||
module: module + esExtensionDefault, | ||
return packageData.modulePath.endsWith("index.js") && !moduleSpecifier.endsWith("index.js") && (moduleSpecifier = `${moduleSpecifier}/index`), { | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -129,10 +144,10 @@ }; | ||
filenameDirectory, | ||
currentModuleExtension ? module : module + esExtensionDefault | ||
currentModuleExtension ? moduleSpecifier : moduleSpecifier + esExtensionDefault | ||
) | ||
) && (module = `${module}/index`); | ||
const targetFile = resolve(filenameDirectory, module); | ||
) && (moduleSpecifier = `${moduleSpecifier}/index`); | ||
const targetFile = resolve(filenameDirectory, moduleSpecifier); | ||
if (ensureFileExists) { | ||
if (esExtensions.includes(filenameExtension) && existsSync(targetFile + filenameExtension)) | ||
return { | ||
module: module + filenameExtension, | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || filenameExtension), | ||
extension: filenameExtension | ||
@@ -142,8 +157,11 @@ }; | ||
if (existsSync(targetFile + extension)) | ||
return { module: module + ".mjs", extension }; | ||
return { | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || extension), | ||
extension | ||
}; | ||
} else return esExtensions.includes(filenameExtension) ? { | ||
module: module + filenameExtension, | ||
module: moduleSpecifier + filenameExtension, | ||
extension: filenameExtension | ||
} : { | ||
module: module + esExtensionDefault, | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -150,0 +168,0 @@ }; |
import { existsSync, readFileSync, lstatSync } from "node:fs"; | ||
import { resolve, extname, dirname } from "node:path"; | ||
import { importDeclaration, exportNamedDeclaration, exportAllDeclaration, stringLiteral } from "@babel/types"; | ||
function _array_like_to_array(arr, len) { | ||
(len == null || len > arr.length) && (len = arr.length); | ||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; | ||
return arr2; | ||
} | ||
function _array_without_holes(arr) { | ||
if (Array.isArray(arr)) return _array_like_to_array(arr); | ||
} | ||
function _define_property(obj, key, value) { | ||
@@ -20,14 +11,8 @@ return key in obj ? Object.defineProperty(obj, key, { | ||
} | ||
function _iterable_to_array(iter) { | ||
if (typeof Symbol < "u" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); | ||
} | ||
function _non_iterable_spread() { | ||
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); | ||
} | ||
function _object_spread(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}, ownKeys2 = Object.keys(source); | ||
typeof Object.getOwnPropertySymbols == "function" && (ownKeys2 = ownKeys2.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { | ||
var source = arguments[i] != null ? arguments[i] : {}, ownKeys = Object.keys(source); | ||
typeof Object.getOwnPropertySymbols == "function" && (ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { | ||
return Object.getOwnPropertyDescriptor(source, sym).enumerable; | ||
}))), ownKeys2.forEach(function(key) { | ||
}))), ownKeys.forEach(function(key) { | ||
_define_property(target, key, source[key]); | ||
@@ -38,108 +23,99 @@ }); | ||
} | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
enumerableOnly && (symbols = symbols.filter(function(sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
})), keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _object_spread_props(target, source) { | ||
return source = source ?? {}, Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function(key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}), target; | ||
} | ||
function _to_consumable_array(arr) { | ||
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread(); | ||
} | ||
function _unsupported_iterable_to_array(o, minLen) { | ||
if (o) { | ||
if (typeof o == "string") return _array_like_to_array(o, minLen); | ||
var n = Object.prototype.toString.call(o).slice(8, -1); | ||
if (n === "Object" && o.constructor && (n = o.constructor.name), n === "Map" || n === "Set") return Array.from(n); | ||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); | ||
} | ||
} | ||
var makeDeclaration = function(param) { | ||
var declaration = param.declaration, makeNodes = param.makeNodes, _param_ensureFileExists = param.ensureFileExists, ensureFileExists = _param_ensureFileExists === void 0 ? !1 : _param_ensureFileExists, _param_esExtensionDefault = param.esExtensionDefault, esExtensionDefault = _param_esExtensionDefault === void 0 ? ".js" : _param_esExtensionDefault, _param_tryExtensions = param.tryExtensions, tryExtensions = _param_tryExtensions === void 0 ? [ | ||
var DEFAULT_OPTIONS = { | ||
ensureFileExists: !1, | ||
esExtensionDefault: ".js", | ||
tryExtensions: [ | ||
".js", | ||
".mjs", | ||
".cjs" | ||
] : _param_tryExtensions, _param_esExtensions = param.esExtensions, esExtensions = _param_esExtensions === void 0 ? [ | ||
], | ||
esExtensions: [ | ||
".js", | ||
".mjs", | ||
".cjs" | ||
] : _param_esExtensions, _param_includePackages = param.includePackages, includePackages = _param_includePackages === void 0 ? [] : _param_includePackages; | ||
return function(path, param2) { | ||
var _param_file = param2.file, filename = _param_file.opts.filename, source = path.node.source; | ||
if (!(!source || !filename)) { | ||
var _path_node = path.node, exportKind = _path_node.exportKind, importKind = _path_node.importKind, isTypeOnly = exportKind === "type" || importKind === "type"; | ||
if (!isTypeOnly) { | ||
var value = source.value, module = value, packageData = null; | ||
if (!(!isLocalFile(module) && (includePackages.some(function(name) { | ||
return module.startsWith(name); | ||
}) && (packageData = getPackageData(module)), !(packageData && packageData.hasPath)))) { | ||
var filenameExtension = extname(filename), filenameDirectory = dirname(filename), isDirectory = isLocalDirectory(resolve(filenameDirectory, module)), currentModuleExtension = extname(module), targetModule = evaluateTargetModule({ | ||
module, | ||
filenameDirectory, | ||
filenameExtension, | ||
packageData, | ||
currentModuleExtension, | ||
isDirectory, | ||
tryExtensions, | ||
esExtensions, | ||
esExtensionDefault, | ||
ensureFileExists | ||
], | ||
includePackages: [] | ||
}; | ||
function FullySpecified(api, rawOptions) { | ||
api.assertVersion(7); | ||
var options = _object_spread({}, DEFAULT_OPTIONS, rawOptions), importDeclarationVisitor = function(path, state) { | ||
var filePath = state.file.opts.filename; | ||
if (filePath) { | ||
var node = path.node; | ||
if (node.importKind !== "type") { | ||
var originalModuleSpecifier = node.source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}); | ||
fullySpecifiedModuleSpecifier && (node.source.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
}, exportDeclarationVisitor = function(path, state) { | ||
var filePath = state.file.opts.filename; | ||
if (filePath) { | ||
var node = path.node; | ||
if (node.exportKind !== "type") { | ||
var source = node.source; | ||
if (source) { | ||
var originalModuleSpecifier = source.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}); | ||
if (!(targetModule === !1 || currentModuleExtension === targetModule.extension)) { | ||
var nodes = makeNodes(path); | ||
path.replaceWith( | ||
// @ts-ignore | ||
declaration.apply(null, _to_consumable_array(nodes).concat([ | ||
stringLiteral(targetModule.module) | ||
])) | ||
); | ||
} | ||
fullySpecifiedModuleSpecifier && (source.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
} | ||
}, importVisitor = function(path, state) { | ||
var filePath = state.file.opts.filename; | ||
if (filePath) { | ||
var parent = path.parent; | ||
if (parent.type === "CallExpression") { | ||
var firstArgOfImportCall = parent.arguments[0]; | ||
if (firstArgOfImportCall.type === "StringLiteral") { | ||
var originalModuleSpecifier = firstArgOfImportCall.value, fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(originalModuleSpecifier, { | ||
filePath, | ||
options | ||
}); | ||
fullySpecifiedModuleSpecifier && (firstArgOfImportCall.value = fullySpecifiedModuleSpecifier); | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
function FullySpecified(api, options) { | ||
return api.assertVersion(7), { | ||
return { | ||
name: "babel-plugin-fully-specified", | ||
visitor: { | ||
ImportDeclaration: makeDeclaration(_object_spread_props(_object_spread({}, options), { | ||
declaration: importDeclaration, | ||
makeNodes: function(param) { | ||
var specifiers = param.node.specifiers; | ||
return [ | ||
specifiers | ||
]; | ||
} | ||
})), | ||
ExportNamedDeclaration: makeDeclaration(_object_spread_props(_object_spread({}, options), { | ||
declaration: exportNamedDeclaration, | ||
makeNodes: function(param) { | ||
var _param_node = param.node, declaration = _param_node.declaration, specifiers = _param_node.specifiers; | ||
return [ | ||
declaration, | ||
specifiers | ||
]; | ||
} | ||
})), | ||
ExportAllDeclaration: makeDeclaration(_object_spread_props(_object_spread({}, options), { | ||
declaration: exportAllDeclaration, | ||
makeNodes: function() { | ||
return []; | ||
} | ||
})) | ||
ImportDeclaration: importDeclarationVisitor, | ||
ExportNamedDeclaration: exportDeclarationVisitor, | ||
ExportAllDeclaration: exportDeclarationVisitor, | ||
Import: importVisitor | ||
} | ||
}; | ||
} | ||
function getPackageData(module) { | ||
function getFullySpecifiedModuleSpecifier(originalModuleSpecifier, param) { | ||
var filePath = param.filePath, options = param.options, fileExt = extname(filePath), fileDir = dirname(filePath), includePackages = options.includePackages, packageData = null; | ||
if (!isLocalFile(originalModuleSpecifier) && (includePackages.some(function(name) { | ||
return originalModuleSpecifier.startsWith(name); | ||
}) && (packageData = getPackageData(originalModuleSpecifier, filePath)), !(packageData && packageData.isDeepImport))) | ||
return null; | ||
var isDirectory = isLocalDirectory(resolve(fileDir, originalModuleSpecifier)), currentModuleExtension = extname(originalModuleSpecifier), tryExtensions = options.tryExtensions, esExtensions = options.esExtensions, esExtensionDefault = options.esExtensionDefault, ensureFileExists = options.ensureFileExists, targetModule = evaluateTargetModule({ | ||
moduleSpecifier: originalModuleSpecifier, | ||
filenameDirectory: fileDir, | ||
filenameExtension: fileExt, | ||
packageData, | ||
currentModuleExtension, | ||
isDirectory, | ||
tryExtensions, | ||
esExtensions, | ||
esExtensionDefault, | ||
ensureFileExists | ||
}); | ||
return targetModule === !1 || currentModuleExtension === targetModule.extension ? null : targetModule.module; | ||
} | ||
function getPackageData(moduleSpecifier, filePath) { | ||
try { | ||
for (var packagePath = require.resolve(module), parts = packagePath.split("/"), packageDir = "", i = parts.length; i >= 0; i--) { | ||
for (var modulePath = require.resolve(moduleSpecifier, { | ||
paths: filePath ? [ | ||
filePath | ||
] : [] | ||
}), parts = modulePath.split("/"), packageDir = "", i = parts.length; i >= 0; i--) { | ||
var dir = dirname(parts.slice(0, i).join("/")); | ||
@@ -153,6 +129,6 @@ if (existsSync("".concat(dir, "/package.json"))) { | ||
throw new Error("no package dir"); | ||
var packageJson = JSON.parse(readFileSync("".concat(packageDir, "/package.json")).toString()), hasPath = !module.endsWith(packageJson.name); | ||
var packageJson = JSON.parse(readFileSync("".concat(packageDir, "/package.json")).toString()), isDeepImport = !moduleSpecifier.endsWith(packageJson.name); | ||
return { | ||
hasPath, | ||
packagePath | ||
isDeepImport, | ||
modulePath | ||
}; | ||
@@ -163,4 +139,4 @@ } catch { | ||
} | ||
function isLocalFile(module) { | ||
return module.startsWith(".") || module.startsWith("/"); | ||
function isLocalFile(moduleSpecifier) { | ||
return moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("/"); | ||
} | ||
@@ -171,6 +147,6 @@ function isLocalDirectory(absoluteDirectory) { | ||
function evaluateTargetModule(param) { | ||
var module = param.module, currentModuleExtension = param.currentModuleExtension, packageData = param.packageData, isDirectory = param.isDirectory, filenameDirectory = param.filenameDirectory, filenameExtension = param.filenameExtension, tryExtensions = param.tryExtensions, esExtensions = param.esExtensions, esExtensionDefault = param.esExtensionDefault, ensureFileExists = param.ensureFileExists; | ||
var moduleSpecifier = param.moduleSpecifier, currentModuleExtension = param.currentModuleExtension, packageData = param.packageData, isDirectory = param.isDirectory, filenameDirectory = param.filenameDirectory, filenameExtension = param.filenameExtension, tryExtensions = param.tryExtensions, esExtensions = param.esExtensions, esExtensionDefault = param.esExtensionDefault, ensureFileExists = param.ensureFileExists; | ||
if (packageData) | ||
return packageData.packagePath.endsWith("index.js") && !module.endsWith("index.js") && (module = "".concat(module, "/index")), { | ||
module: module + esExtensionDefault, | ||
return packageData.modulePath.endsWith("index.js") && !moduleSpecifier.endsWith("index.js") && (moduleSpecifier = "".concat(moduleSpecifier, "/index")), { | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -180,8 +156,8 @@ }; | ||
return !1; | ||
isDirectory && !existsSync(resolve(filenameDirectory, currentModuleExtension ? module : module + esExtensionDefault)) && (module = "".concat(module, "/index")); | ||
var targetFile = resolve(filenameDirectory, module); | ||
isDirectory && !existsSync(resolve(filenameDirectory, currentModuleExtension ? moduleSpecifier : moduleSpecifier + esExtensionDefault)) && (moduleSpecifier = "".concat(moduleSpecifier, "/index")); | ||
var targetFile = resolve(filenameDirectory, moduleSpecifier); | ||
if (ensureFileExists) { | ||
if (esExtensions.includes(filenameExtension) && existsSync(targetFile + filenameExtension)) | ||
return { | ||
module: module + filenameExtension, | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || filenameExtension), | ||
extension: filenameExtension | ||
@@ -195,3 +171,3 @@ }; | ||
return { | ||
module: module + ".mjs", | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || extension), | ||
extension | ||
@@ -211,6 +187,6 @@ }; | ||
} else return esExtensions.includes(filenameExtension) ? { | ||
module: module + filenameExtension, | ||
module: moduleSpecifier + filenameExtension, | ||
extension: filenameExtension | ||
} : { | ||
module: module + esExtensionDefault, | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault | ||
@@ -217,0 +193,0 @@ }; |
{ | ||
"name": "@tamagui/babel-plugin-fully-specified", | ||
"version": "1.101.7", | ||
"version": "1.102.0", | ||
"source": "src/index.ts", | ||
@@ -18,6 +18,7 @@ "types": "./types/index.d.ts", | ||
"scripts": { | ||
"build": "node ../../../node_modules/.bin/tamagui-build", | ||
"watch": "node ../../../node_modules/.bin/tamagui-build --watch", | ||
"build": "node ../../../node_modules/.bin/tamagui-build --exclude __tests__", | ||
"watch": "node ../../../node_modules/.bin/tamagui-build --exclude __tests__ --watch", | ||
"lint": "npx biome check src", | ||
"lint:fix": "npx biome check --apply-unsafe src", | ||
"test": "vitest --run", | ||
"clean": "node ../../../node_modules/.bin/tamagui-build clean", | ||
@@ -30,5 +31,6 @@ "clean:build": "node ../../../node_modules/.bin/tamagui-build clean:build" | ||
"devDependencies": { | ||
"@babel/types": "^7.23.3" | ||
"@babel/types": "^7.23.3", | ||
"vitest": "^0.34.3" | ||
}, | ||
"gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14" | ||
} |
354
src/index.ts
import { existsSync, readFileSync, lstatSync } from 'node:fs' | ||
import { resolve, extname, dirname } from 'node:path' | ||
import { | ||
importDeclaration, | ||
exportNamedDeclaration, | ||
exportAllDeclaration, | ||
stringLiteral, | ||
} from '@babel/types' | ||
import type { ConfigAPI, NodePath, PluginPass } from '@babel/core' | ||
import type { ConfigAPI, NodePath, PluginObj, PluginPass } from '@babel/core' | ||
import type { | ||
ImportSpecifier, | ||
ImportDeclaration, | ||
ExportAllDeclaration, | ||
StringLiteral, | ||
ExportSpecifier, | ||
ExportDeclaration, | ||
ExportNamedDeclaration, | ||
Import, | ||
ImportDeclaration, | ||
} from '@babel/types' | ||
type ImportDeclarationFunc = ( | ||
specifiers: Array<ImportSpecifier>, | ||
source: StringLiteral | ||
) => ImportDeclaration | ||
type ExportNamedDeclarationFunc = ( | ||
declaration?: ExportDeclaration, | ||
specifiers?: Array<ExportSpecifier>, | ||
source?: StringLiteral | ||
) => ExportNamedDeclaration | ||
type ExportAllDeclarationFunc = (source: StringLiteral) => ExportAllDeclaration | ||
type PathDeclaration = NodePath & { | ||
node: ImportDeclaration & ExportNamedDeclaration & ExportAllDeclaration | ||
} | ||
type PackageData = { | ||
hasPath: boolean | ||
packagePath: string | ||
} | ||
interface FullySpecifiedOptions { | ||
declaration: | ||
| ImportDeclarationFunc | ||
| ExportNamedDeclarationFunc | ||
| ExportAllDeclarationFunc | ||
makeNodes: (path: PathDeclaration) => Array<PathDeclaration> | ||
ensureFileExists: boolean | ||
export interface FullySpecifiedOptions { | ||
ensureFileExists: | ||
| boolean | ||
| { | ||
/** | ||
* If you're doing a non-in-place transformation (for example, outputting `.mjs` from `.js`) with `ensureFileExists` enabled, it's possible that the transform will be incorrect due to the imported file is not transformed and written into place yet (for example, we have `foo.js` and `bar.js` and we're transforming them into `foo.mjs` and `bar.mjs` respectively, in `bar.js` we have `import { ... } from './foo.js'` which we expect to be transformed into `import { ... } from './foo.mjs'`, but if `foo.mjs` is not transformed and written yet, it will be transformed into `import { ... } from './foo.js'` because `foo.mjs` can't be found at that time). | ||
* | ||
* To solve this, you can set this option to `'.mjs'` to force the extension to be transformed into that specified extension. | ||
*/ | ||
forceExtension?: string | ||
} | ||
esExtensionDefault: string | ||
/** List of all extensions which we try to find. */ | ||
tryExtensions: Array<string> | ||
/** List of extensions that can run in Node.js or in the Browser. */ | ||
esExtensions: Array<string> | ||
/** List of packages that also should be transformed with this plugin. */ | ||
includePackages: Array<string> | ||
} | ||
const makeDeclaration = ({ | ||
declaration, | ||
makeNodes, | ||
ensureFileExists = false, | ||
esExtensionDefault = '.js', | ||
const DEFAULT_OPTIONS = { | ||
ensureFileExists: false, | ||
esExtensionDefault: '.js', | ||
tryExtensions: ['.js', '.mjs', '.cjs'], | ||
esExtensions: ['.js', '.mjs', '.cjs'], | ||
includePackages: [], | ||
} | ||
// List of all extensions which we try to find | ||
tryExtensions = ['.js', '.mjs', '.cjs'], | ||
export default function FullySpecified( | ||
api: ConfigAPI, | ||
rawOptions: FullySpecifiedOptions | ||
): PluginObj { | ||
api.assertVersion(7) | ||
// List of extensions that can run in Node.js or in the Browser | ||
esExtensions = ['.js', '.mjs', '.cjs'], | ||
const options = { ...DEFAULT_OPTIONS, ...rawOptions } | ||
// List of packages that also should be transformed with this plugin | ||
includePackages = [], | ||
}: FullySpecifiedOptions) => { | ||
return ( | ||
path: PathDeclaration, | ||
{ | ||
file: { | ||
opts: { filename }, | ||
}, | ||
}: PluginPass | ||
/** For `import ... from '...'`. */ | ||
const importDeclarationVisitor = ( | ||
path: NodePath<ImportDeclaration>, | ||
state: PluginPass | ||
) => { | ||
const { source } = path.node | ||
const filePath = state.file.opts.filename | ||
if (!filePath) return // cannot determine file path therefore cannot proceed | ||
if (!source || !filename) { | ||
return // stop here | ||
} | ||
const { node } = path | ||
if (node.importKind === 'type') return // is a type-only import, skip | ||
const { exportKind, importKind } = path.node | ||
const isTypeOnly = exportKind === 'type' || importKind === 'type' | ||
if (isTypeOnly) { | ||
return // stop here | ||
const originalModuleSpecifier = node.source.value | ||
const fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options, | ||
} | ||
) | ||
if (fullySpecifiedModuleSpecifier) { | ||
node.source.value = fullySpecifiedModuleSpecifier | ||
} | ||
} | ||
const { value } = source | ||
const module = value as string | ||
/** For `export ... from '...'`. */ | ||
const exportDeclarationVisitor = ( | ||
path: NodePath<ExportNamedDeclaration> | NodePath<ExportAllDeclaration>, | ||
state: PluginPass | ||
) => { | ||
const filePath = state.file.opts.filename | ||
if (!filePath) return // cannot determine file path therefore cannot proceed | ||
let packageData: PackageData | null = null | ||
const { node } = path | ||
if (node.exportKind === 'type') return // is a type-only export, skip | ||
if (!isLocalFile(module)) { | ||
if (includePackages.some((name) => module.startsWith(name))) { | ||
packageData = getPackageData(module) | ||
const source = node.source | ||
if (!source) return // is not a re-export, skip | ||
const originalModuleSpecifier = source.value | ||
const fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options, | ||
} | ||
) | ||
if (!(packageData && packageData.hasPath)) { | ||
return // stop here | ||
} | ||
if (fullySpecifiedModuleSpecifier) { | ||
source.value = fullySpecifiedModuleSpecifier | ||
} | ||
} | ||
const filenameExtension = extname(filename) | ||
const filenameDirectory = dirname(filename) | ||
const isDirectory = isLocalDirectory(resolve(filenameDirectory, module)) | ||
/** For dynamic `import()`s. */ | ||
const importVisitor = (path: NodePath<Import>, state) => { | ||
const filePath = state.file.opts.filename | ||
if (!filePath) return // cannot determine file path therefore cannot proceed | ||
const currentModuleExtension = extname(module) | ||
const targetModule = evaluateTargetModule({ | ||
module, | ||
filenameDirectory, | ||
filenameExtension, | ||
packageData, | ||
currentModuleExtension, | ||
isDirectory, | ||
tryExtensions, | ||
esExtensions, | ||
esExtensionDefault, | ||
ensureFileExists, | ||
}) | ||
const parent = path.parent | ||
if (parent.type !== 'CallExpression') { | ||
return // we expect the usage of `import` is a call to it, e.g.: `import('...')`, other usages are not supported | ||
} | ||
if (targetModule === false || currentModuleExtension === targetModule.extension) { | ||
return // stop here | ||
const firstArgOfImportCall = parent.arguments[0] | ||
if (firstArgOfImportCall.type !== 'StringLiteral') { | ||
return // we expect the first argument of `import` to be a string, e.g.: `import('./myModule')`, other types are not supported | ||
} | ||
const nodes = makeNodes(path) | ||
const originalModuleSpecifier = firstArgOfImportCall.value | ||
const fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier( | ||
originalModuleSpecifier, | ||
{ | ||
filePath, | ||
options, | ||
} | ||
) | ||
path.replaceWith( | ||
// @ts-ignore | ||
declaration.apply(null, [...nodes, stringLiteral(targetModule.module)]) | ||
) | ||
if (fullySpecifiedModuleSpecifier) { | ||
firstArgOfImportCall.value = fullySpecifiedModuleSpecifier | ||
} | ||
} | ||
} | ||
export default function FullySpecified(api: ConfigAPI, options: FullySpecifiedOptions) { | ||
api.assertVersion(7) | ||
return { | ||
name: 'babel-plugin-fully-specified', | ||
visitor: { | ||
ImportDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: importDeclaration, | ||
makeNodes: ({ node: { specifiers } }) => [specifiers], | ||
}), | ||
ExportNamedDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: exportNamedDeclaration, | ||
makeNodes: ({ node: { declaration, specifiers } }) => [declaration, specifiers], | ||
}), | ||
ExportAllDeclaration: makeDeclaration({ | ||
...options, | ||
declaration: exportAllDeclaration, | ||
makeNodes: () => [], | ||
}), | ||
ImportDeclaration: importDeclarationVisitor, | ||
ExportNamedDeclaration: exportDeclarationVisitor, | ||
ExportAllDeclaration: exportDeclarationVisitor, | ||
Import: importVisitor, | ||
}, | ||
@@ -162,6 +141,101 @@ } | ||
function getPackageData<PackageData>(module: string) { | ||
/** | ||
* Returns a fully specified [module specifier](https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#prod-ModuleSpecifier) (or `null` if it can't be determined or shouldn't be transformed). | ||
*/ | ||
function getFullySpecifiedModuleSpecifier( | ||
/** | ||
* The original module specifier in the code. | ||
* | ||
* For example, `'./foo'` for `import { foo } from './foo'`. | ||
*/ | ||
originalModuleSpecifier: string, | ||
{ | ||
filePath, | ||
options, | ||
}: { | ||
/** | ||
* The absolute file path of the file being transformed. | ||
* | ||
* Normally this can be obtained from the 2nd parameter in a visitor function (often named as `state`): `state.file.opts.filename`. | ||
*/ | ||
filePath: string | ||
/** Options that users pass to babel-plugin-fully-specified. */ | ||
options: FullySpecifiedOptions | ||
} | ||
): string | null { | ||
const fileExt = extname(filePath) | ||
const fileDir = dirname(filePath) | ||
const { includePackages } = options | ||
let packageData: PackageImportData | null = null | ||
if (!isLocalFile(originalModuleSpecifier)) { | ||
if (includePackages.some((name) => originalModuleSpecifier.startsWith(name))) { | ||
packageData = getPackageData(originalModuleSpecifier, filePath) | ||
} | ||
if (!(packageData && packageData.isDeepImport)) { | ||
return null | ||
} | ||
} | ||
const isDirectory = isLocalDirectory(resolve(fileDir, originalModuleSpecifier)) | ||
const currentModuleExtension = extname(originalModuleSpecifier) | ||
const { tryExtensions, esExtensions, esExtensionDefault, ensureFileExists } = options | ||
const targetModule = evaluateTargetModule({ | ||
moduleSpecifier: originalModuleSpecifier, | ||
filenameDirectory: fileDir, | ||
filenameExtension: fileExt, | ||
packageData, | ||
currentModuleExtension, | ||
isDirectory, | ||
tryExtensions, | ||
esExtensions, | ||
esExtensionDefault, | ||
ensureFileExists, | ||
}) | ||
if (targetModule === false || currentModuleExtension === targetModule.extension) { | ||
return null | ||
} | ||
return targetModule.module | ||
} | ||
/** | ||
* Data about how a package is being imported. | ||
*/ | ||
type PackageImportData = { | ||
/** | ||
* Indicates whether the import from the package is a deep import. | ||
* | ||
* Example: | ||
* | ||
* * `import { foo } from '@org/package'` -> `isDeepImport: false` | ||
* * `import { foo } from '@org/package/lib/foo'` -> `isDeepImport: true` | ||
*/ | ||
isDeepImport: boolean | ||
/** | ||
* The resolved absolute path of the exact file being imported. This will always be a file path (such as `<project>/node_modules/my-pkg/dist/index.js`), not just a directory path. | ||
*/ | ||
modulePath: string | ||
} | ||
/** | ||
* Given a module specifier and the file path of the source file which imports that module, returns the package data of that module if it can be found. | ||
*/ | ||
function getPackageData( | ||
/** The module specifier, e.g.: `@org/package/lib/someTool`. */ | ||
moduleSpecifier: string, | ||
/** The file path of the source file which imports that module. */ | ||
filePath?: string | ||
): PackageImportData | null { | ||
try { | ||
const packagePath = require.resolve(module) | ||
const parts = packagePath.split('/') | ||
const modulePath = require.resolve(moduleSpecifier, { | ||
paths: filePath ? [filePath] : [], | ||
}) | ||
const parts = modulePath.split('/') | ||
@@ -182,4 +256,4 @@ let packageDir = '' | ||
const hasPath = !module.endsWith(packageJson.name) | ||
return { hasPath, packagePath } | ||
const isDeepImport = !moduleSpecifier.endsWith(packageJson.name) | ||
return { isDeepImport, modulePath } | ||
} catch (e) {} | ||
@@ -190,4 +264,4 @@ | ||
function isLocalFile(module: string) { | ||
return module.startsWith('.') || module.startsWith('/') | ||
function isLocalFile(moduleSpecifier: string) { | ||
return moduleSpecifier.startsWith('.') || moduleSpecifier.startsWith('/') | ||
} | ||
@@ -200,3 +274,3 @@ | ||
function evaluateTargetModule({ | ||
module, | ||
moduleSpecifier, | ||
currentModuleExtension, | ||
@@ -213,8 +287,11 @@ packageData, | ||
if (packageData) { | ||
if (packageData.packagePath.endsWith('index.js') && !module.endsWith('index.js')) { | ||
module = `${module}/index` | ||
if ( | ||
packageData.modulePath.endsWith('index.js') && | ||
!moduleSpecifier.endsWith('index.js') | ||
) { | ||
moduleSpecifier = `${moduleSpecifier}/index` | ||
} | ||
return { | ||
module: module + esExtensionDefault, | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault, | ||
@@ -233,10 +310,10 @@ } | ||
filenameDirectory, | ||
currentModuleExtension ? module : module + esExtensionDefault | ||
currentModuleExtension ? moduleSpecifier : moduleSpecifier + esExtensionDefault | ||
) | ||
) | ||
) { | ||
module = `${module}/index` | ||
moduleSpecifier = `${moduleSpecifier}/index` | ||
} | ||
const targetFile = resolve(filenameDirectory, module) | ||
const targetFile = resolve(filenameDirectory, moduleSpecifier) | ||
@@ -250,3 +327,3 @@ if (ensureFileExists) { | ||
return { | ||
module: module + filenameExtension, | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || filenameExtension), | ||
extension: filenameExtension, | ||
@@ -259,3 +336,6 @@ } | ||
if (existsSync(targetFile + extension)) { | ||
return { module: module + '.mjs', extension } | ||
return { | ||
module: moduleSpecifier + (ensureFileExists.forceExtension || extension), | ||
extension, | ||
} | ||
} | ||
@@ -265,3 +345,3 @@ } | ||
return { | ||
module: module + filenameExtension, | ||
module: moduleSpecifier + filenameExtension, | ||
extension: filenameExtension, | ||
@@ -271,3 +351,3 @@ } | ||
return { | ||
module: module + esExtensionDefault, | ||
module: moduleSpecifier + esExtensionDefault, | ||
extension: esExtensionDefault, | ||
@@ -274,0 +354,0 @@ } |
@@ -1,27 +0,20 @@ | ||
import type { ConfigAPI, NodePath, PluginPass } from '@babel/core'; | ||
import type { ImportSpecifier, ImportDeclaration, ExportAllDeclaration, StringLiteral, ExportSpecifier, ExportDeclaration, ExportNamedDeclaration } from '@babel/types'; | ||
type ImportDeclarationFunc = (specifiers: Array<ImportSpecifier>, source: StringLiteral) => ImportDeclaration; | ||
type ExportNamedDeclarationFunc = (declaration?: ExportDeclaration, specifiers?: Array<ExportSpecifier>, source?: StringLiteral) => ExportNamedDeclaration; | ||
type ExportAllDeclarationFunc = (source: StringLiteral) => ExportAllDeclaration; | ||
type PathDeclaration = NodePath & { | ||
node: ImportDeclaration & ExportNamedDeclaration & ExportAllDeclaration; | ||
}; | ||
interface FullySpecifiedOptions { | ||
declaration: ImportDeclarationFunc | ExportNamedDeclarationFunc | ExportAllDeclarationFunc; | ||
makeNodes: (path: PathDeclaration) => Array<PathDeclaration>; | ||
ensureFileExists: boolean; | ||
import type { ConfigAPI, PluginObj } from '@babel/core'; | ||
export interface FullySpecifiedOptions { | ||
ensureFileExists: boolean | { | ||
/** | ||
* If you're doing a non-in-place transformation (for example, outputting `.mjs` from `.js`) with `ensureFileExists` enabled, it's possible that the transform will be incorrect due to the imported file is not transformed and written into place yet (for example, we have `foo.js` and `bar.js` and we're transforming them into `foo.mjs` and `bar.mjs` respectively, in `bar.js` we have `import { ... } from './foo.js'` which we expect to be transformed into `import { ... } from './foo.mjs'`, but if `foo.mjs` is not transformed and written yet, it will be transformed into `import { ... } from './foo.js'` because `foo.mjs` can't be found at that time). | ||
* | ||
* To solve this, you can set this option to `'.mjs'` to force the extension to be transformed into that specified extension. | ||
*/ | ||
forceExtension?: string; | ||
}; | ||
esExtensionDefault: string; | ||
/** List of all extensions which we try to find. */ | ||
tryExtensions: Array<string>; | ||
/** List of extensions that can run in Node.js or in the Browser. */ | ||
esExtensions: Array<string>; | ||
/** List of packages that also should be transformed with this plugin. */ | ||
includePackages: Array<string>; | ||
} | ||
export default function FullySpecified(api: ConfigAPI, options: FullySpecifiedOptions): { | ||
name: string; | ||
visitor: { | ||
ImportDeclaration: (path: PathDeclaration, { file: { opts: { filename }, }, }: PluginPass) => void; | ||
ExportNamedDeclaration: (path: PathDeclaration, { file: { opts: { filename }, }, }: PluginPass) => void; | ||
ExportAllDeclaration: (path: PathDeclaration, { file: { opts: { filename }, }, }: PluginPass) => void; | ||
}; | ||
}; | ||
export {}; | ||
export default function FullySpecified(api: ConfigAPI, rawOptions: FullySpecifiedOptions): PluginObj; | ||
//# sourceMappingURL=index.d.ts.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
75371
29
1392
0
2
33
2
1