Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@tamagui/babel-plugin-fully-specified

Package Overview
Dependencies
Maintainers
1
Versions
155
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tamagui/babel-plugin-fully-specified - npm Package Compare versions

Comparing version 1.101.7 to 1.102.0

src/__tests__/__snapshots__/index.test.ts.snap

172

dist/cjs/index.js

@@ -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"
}
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

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc