@tamagui/babel-plugin-fully-specified 2.7.4 → 2.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/babel-plugin-fully-specified",
3
- "version": "2.7.4",
3
+ "version": "2.7.6",
4
4
  "gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14",
5
5
  "license": "MIT",
6
6
  "source": "src/index.ts",
@@ -0,0 +1,11 @@
1
+ {
2
+ "mappings": "AAGA,eAAe,SAAS,qBACtB,UACA,SAAS;CACP;IAED,MAAM",
3
+ "names": [],
4
+ "sources": [
5
+ "src/commonjs.ts"
6
+ ],
7
+ "version": 3,
8
+ "sourcesContent": [
9
+ "import { existsSync, lstatSync } from 'node:fs'\nimport { dirname, extname, resolve } from 'node:path'\n\nexport default function fullySpecifyCommonJS(\n api: any,\n options: {\n esExtensionDefault: string\n }\n): babel.PluginObj {\n api.assertVersion(7)\n\n return {\n name: 'babel-plugin-fully-specified-cjs',\n visitor: {\n CallExpression(path, state) {\n const callee = path.get('callee')\n\n if (\n callee.isIdentifier({ name: 'require' }) &&\n path.node.arguments.length === 1\n ) {\n const arg = path.node.arguments[0]\n if (arg.type === 'StringLiteral') {\n let moduleSpecifier = arg.value\n\n // Skip built-in modules and node_modules\n if (moduleSpecifier.startsWith('.') || moduleSpecifier.startsWith('/')) {\n const filePath = state.file.opts.filename\n if (!filePath) return // Cannot determine file path\n\n const fileDir = dirname(filePath)\n const cjsExtension = options.esExtensionDefault || '.cjs'\n const jsExtension = '.js'\n\n // Check if moduleSpecifier already has a module extension. extname alone\n // is wrong here: dotted basenames like ./foo.generated have no extension.\n const specifierExtension = extname(moduleSpecifier)\n const hasModuleExtension = [\n '.js',\n '.cjs',\n '.mjs',\n '.json',\n '.node',\n ].includes(specifierExtension)\n if (!hasModuleExtension) {\n const resolvedPath = resolve(fileDir, moduleSpecifier)\n let newModuleSpecifier = moduleSpecifier\n\n // Check if the moduleSpecifier is a directory with an index.cjs file\n if (isLocalDirectory(resolvedPath)) {\n const indexPath = resolve(resolvedPath, 'index' + jsExtension)\n if (existsSync(indexPath)) {\n // Append '/' if not present\n if (!newModuleSpecifier.endsWith('/')) {\n newModuleSpecifier += '/'\n }\n newModuleSpecifier += 'index' + cjsExtension\n arg.value = newModuleSpecifier\n return\n }\n }\n\n // Check if source file exists (try .js first, then target extension)\n if (\n existsSync(resolvedPath + jsExtension) ||\n existsSync(resolvedPath + cjsExtension)\n ) {\n newModuleSpecifier += cjsExtension\n arg.value = newModuleSpecifier\n return\n }\n }\n }\n }\n }\n },\n },\n } satisfies babel.PluginObj\n}\n\nfunction isLocalDirectory(absolutePath: string): boolean {\n return existsSync(absolutePath) && lstatSync(absolutePath).isDirectory()\n}\n"
10
+ ]
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "mappings": "AAGA,cAAc,WAAqB,iBAA6B;AAUhE,iBAAiB,sBAAsB;CACrC;CACA;;CAEA,eAAe;;CAEf,cAAc;;CAEd;;AAWF,eAAe,SAAS,eACtB,KAAK,WACL,aAAY,QAAQ,yBACnB",
3
+ "names": [],
4
+ "sources": [
5
+ "src/index.ts"
6
+ ],
7
+ "version": 3,
8
+ "sourcesContent": [
9
+ "import { existsSync, lstatSync } from 'node:fs'\nimport { dirname, extname, resolve } from 'node:path'\n\nimport type { ConfigAPI, NodePath, PluginObj, PluginPass } from '@babel/core'\nimport * as t from '@babel/types'\nimport type {\n ExportAllDeclaration,\n ExportNamedDeclaration,\n Import,\n ImportDeclaration,\n MemberExpression,\n} from '@babel/types'\n\nexport interface FullySpecifiedOptions {\n ensureFileExists: boolean\n esExtensionDefault: string\n /** List of all extensions which we try to find. */\n tryExtensions: Array<string>\n /** List of extensions that can run in Node.js or in the Browser. */\n esExtensions: Array<string>\n /** Convert process.env.XYZ to import.meta.env.XYZ */\n convertProcessEnvToImportMetaEnv?: boolean\n}\n\nconst DEFAULT_OPTIONS = {\n ensureFileExists: true,\n esExtensionDefault: '.mjs',\n tryExtensions: ['.js'],\n esExtensions: ['.mjs'],\n convertProcessEnvToImportMetaEnv: false,\n} satisfies FullySpecifiedOptions\n\nexport default function FullySpecified(\n api: ConfigAPI,\n rawOptions: Partial<FullySpecifiedOptions> = {}\n): PluginObj {\n api.assertVersion(7)\n\n const options = normalizeOptions(rawOptions)\n\n /** For `import ... from '...'`. */\n const importDeclarationVisitor = (\n path: NodePath<ImportDeclaration>,\n state: PluginPass\n ) => {\n const filePath = state.file.opts.filename\n if (!filePath) return // cannot determine file path therefore cannot proceed\n\n const { node } = path\n if (node.importKind === 'type') return // is a type-only import, skip\n\n const originalModuleSpecifier = node.source.value\n const fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(\n originalModuleSpecifier,\n {\n filePath,\n options,\n }\n )\n\n if (fullySpecifiedModuleSpecifier) {\n node.source.value = fullySpecifiedModuleSpecifier\n }\n }\n\n /** For `export ... from '...'`. */\n const exportDeclarationVisitor = (\n path: NodePath<ExportNamedDeclaration> | NodePath<ExportAllDeclaration>,\n state: PluginPass\n ) => {\n const filePath = state.file.opts.filename\n if (!filePath) return // cannot determine file path therefore cannot proceed\n\n const { node } = path\n if (node.exportKind === 'type') return // is a type-only export, skip\n\n const source = node.source\n if (!source) return // is not a re-export, skip\n\n const originalModuleSpecifier = source.value\n const fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(\n originalModuleSpecifier,\n {\n filePath,\n options,\n }\n )\n\n if (fullySpecifiedModuleSpecifier) {\n source.value = fullySpecifiedModuleSpecifier\n }\n }\n\n /** For dynamic `import()`s. */\n const importVisitor = (path: NodePath<Import>, state) => {\n const filePath = state.file.opts.filename\n if (!filePath) return // cannot determine file path therefore cannot proceed\n\n const parent = path.parent\n if (parent.type !== 'CallExpression') {\n return // we expect the usage of `import` is a call to it, e.g.: `import('...')`, other usages are not supported\n }\n\n const firstArgOfImportCall = parent.arguments[0]\n if (firstArgOfImportCall.type !== 'StringLiteral') {\n return // we expect the first argument of `import` to be a string, e.g.: `import('./myModule')`, other types are not supported\n }\n\n const originalModuleSpecifier = firstArgOfImportCall.value\n const fullySpecifiedModuleSpecifier = getFullySpecifiedModuleSpecifier(\n originalModuleSpecifier,\n {\n filePath,\n options,\n }\n )\n\n if (fullySpecifiedModuleSpecifier) {\n firstArgOfImportCall.value = fullySpecifiedModuleSpecifier\n }\n }\n\n /** For converting process.env to import.meta.env */\n const memberExpressionVisitor = (path: NodePath<MemberExpression>) => {\n if (!options.convertProcessEnvToImportMetaEnv) return\n\n const { node } = path\n\n // Check if this is process.env.SOMETHING\n if (\n node.object.type === 'MemberExpression' &&\n node.object.object.type === 'Identifier' &&\n node.object.object.name === 'process' &&\n node.object.property.type === 'Identifier' &&\n node.object.property.name === 'env'\n ) {\n // Skip process.env.NODE_ENV - leave it as is\n if (node.property.type === 'Identifier' && node.property.name === 'NODE_ENV') {\n return\n }\n\n // Replace process.env with import.meta.env\n node.object = t.memberExpression(\n t.metaProperty(t.identifier('import'), t.identifier('meta')),\n t.identifier('env')\n )\n }\n }\n\n return {\n name: 'babel-plugin-fully-specified',\n visitor: {\n ImportDeclaration: importDeclarationVisitor,\n ExportNamedDeclaration: exportDeclarationVisitor,\n ExportAllDeclaration: exportDeclarationVisitor,\n Import: importVisitor,\n MemberExpression: memberExpressionVisitor,\n },\n }\n}\n\nfunction normalizeOptions(\n rawOptions: Partial<FullySpecifiedOptions>\n): FullySpecifiedOptions {\n const options = { ...DEFAULT_OPTIONS, ...rawOptions }\n\n if (\n rawOptions.esExtensionDefault &&\n !rawOptions.tryExtensions &&\n rawOptions.esExtensionDefault !== DEFAULT_OPTIONS.esExtensionDefault\n ) {\n options.tryExtensions = [\n rawOptions.esExtensionDefault,\n ...DEFAULT_OPTIONS.tryExtensions.filter(\n (extension) => extension !== rawOptions.esExtensionDefault\n ),\n ]\n }\n\n return options\n}\n\n/**\n * 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).\n */\nfunction getFullySpecifiedModuleSpecifier(\n /**\n * The original module specifier in the code.\n *\n * For example, `'./foo'` for `import { foo } from './foo'`.\n */\n originalModuleSpecifier: string,\n {\n filePath,\n options,\n }: {\n /**\n * The absolute file path of the file being transformed.\n *\n * Normally this can be obtained from the 2nd parameter in a visitor function (often named as `state`): `state.file.opts.filename`.\n */\n filePath: string\n /** Options that users pass to babel-plugin-fully-specified. */\n options: FullySpecifiedOptions\n }\n): string | null {\n const fileExt = extname(filePath)\n const fileDir = dirname(filePath)\n\n const isDirectory = isLocalDirectory(resolve(fileDir, originalModuleSpecifier))\n\n const currentModuleExtension = extname(originalModuleSpecifier)\n\n const { tryExtensions, esExtensions, esExtensionDefault, ensureFileExists } = options\n\n const targetModule = evaluateTargetModule({\n moduleSpecifier: originalModuleSpecifier,\n filenameDirectory: fileDir,\n filenameExtension: fileExt,\n currentModuleExtension,\n isDirectory,\n tryExtensions,\n esExtensions,\n esExtensionDefault,\n ensureFileExists,\n })\n\n if (targetModule === false) {\n return null\n }\n\n return targetModule\n}\n\nfunction isLocalDirectory(absoluteDirectory: string) {\n return existsSync(absoluteDirectory) && lstatSync(absoluteDirectory).isDirectory()\n}\n\nfunction evaluateTargetModule({\n moduleSpecifier,\n currentModuleExtension,\n isDirectory,\n filenameDirectory,\n filenameExtension,\n tryExtensions,\n esExtensions,\n esExtensionDefault,\n ensureFileExists,\n}: any): string | false {\n const targetFile = resolve(filenameDirectory, moduleSpecifier)\n\n if (ensureFileExists) {\n for (const extension of tryExtensions) {\n if (existsSync(targetFile + extension)) {\n return moduleSpecifier + esExtensionDefault\n }\n }\n\n if (currentModuleExtension && !esExtensions.includes(currentModuleExtension)) {\n return false\n }\n\n if (isDirectory) {\n const indexModuleSpecifier = `${moduleSpecifier.replace(/\\/$/, '')}/index`\n const indexTargetFile = resolve(filenameDirectory, indexModuleSpecifier)\n\n for (const extension of tryExtensions) {\n if (existsSync(indexTargetFile + extension)) {\n return indexModuleSpecifier + esExtensionDefault\n }\n }\n }\n } else if (esExtensions.includes(filenameExtension)) {\n return moduleSpecifier + esExtensionDefault\n } else {\n return moduleSpecifier + esExtensionDefault\n }\n\n return false\n}\n"
10
+ ]
11
+ }