extensionless-imports 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -176,6 +176,21 @@ The transformer handles statically analyzable module specifiers in:
176
176
  - Named and star re-exports
177
177
  - String-literal dynamic imports
178
178
 
179
+ Relative imports and the conventional `@/` and `~/` project aliases are
180
+ rewritten by default. For example:
181
+
182
+ ```ts
183
+ import Button from "@/components/Button.tsx";
184
+ import type { User } from "~/types/User.ts";
185
+ ```
186
+
187
+ becomes:
188
+
189
+ ```ts
190
+ import Button from "@/components/Button";
191
+ import type { User } from "~/types/User";
192
+ ```
193
+
179
194
  Examples:
180
195
 
181
196
  import value from "./value.ts";
@@ -202,7 +217,8 @@ The package does not modify:
202
217
  - Nonliteral dynamic imports
203
218
  - URL, node:, and package-import-map specifiers
204
219
  - Root-relative browser paths
205
- - Package imports and package subpaths by default
220
+ - Package imports and package subpaths by default (scoped packages such as
221
+ `@scope/package/file.js` are not mistaken for the `@/` alias)
206
222
  - require() calls
207
223
 
208
224
  Package subpaths can be enabled with --include-package-subpaths. This option
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACR,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EACR,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,YAAY,GACf,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EASrD,CAAC;AAsBH;;;GAGG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,YAAiB,GAC3B,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GACjC,OAAO,CAAC,aAAa,CAAC,CAqBxB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBnB;AAyJD;;GAEG;AACH,wBAAgB,aAAa,CACzB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,EACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAsBT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACR,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EACR,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,YAAY,GACf,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EASrD,CAAC;AAsBH;;;GAGG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,YAAiB,GAC3B,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GACjC,OAAO,CAAC,aAAa,CAAC,CAqBxB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBnB;AAmKD;;GAEG;AACH,wBAAgB,aAAa,CACzB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,OAAO,EACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAsBT"}
package/dist/index.js CHANGED
@@ -103,13 +103,18 @@ function transformSource(source, options) {
103
103
  };
104
104
  }
105
105
  function shouldTransformSpecifier(specifier, options) {
106
- if (isRelativeSpecifier(specifier))
106
+ if (isRelativeSpecifier(specifier) ||
107
+ isProjectAliasSpecifier(specifier)) {
107
108
  return true;
109
+ }
108
110
  return (options.includePackageSubpaths === true && isPackageSubpath(specifier));
109
111
  }
110
112
  function isRelativeSpecifier(specifier) {
111
113
  return specifier.startsWith("./") || specifier.startsWith("../");
112
114
  }
115
+ function isProjectAliasSpecifier(specifier) {
116
+ return specifier.startsWith("@/") || specifier.startsWith("~/");
117
+ }
113
118
  function isPackageSubpath(specifier) {
114
119
  if (specifier.startsWith("/") ||
115
120
  specifier.charCodeAt(0) === 92 ||
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {randomUUID} from \"node:crypto\";\nimport {\n chmod,\n lstat,\n readFile,\n readdir,\n rename,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport {\n basename,\n dirname,\n extname,\n join,\n relative,\n resolve,\n} from \"node:path\";\nimport {init, parse} from \"es-module-lexer\";\nimport {minimatch} from \"minimatch\";\n\nimport type {\n FindFilesOptions,\n ProcessFileOptions,\n ProcessResult,\n StripOptions,\n} from \"./types.js\";\n\nexport type {\n FindFilesOptions,\n ProcessFileOptions,\n ProcessResult,\n StripOptions,\n} from \"./types.js\";\n\nconst REMOVABLE_EXTENSION = /\\.(?:tsx?|jsx?)(?=[?#]|$)/i;\nexport const DEFAULT_SOURCE_EXTENSIONS: readonly string[] = Object.freeze([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".mts\",\n \".cts\",\n \".mjs\",\n \".cjs\",\n]);\nconst DEFAULT_IGNORED_DIRECTORIES = new Set([\n \".git\",\n \"node_modules\",\n \"dist\",\n \"coverage\",\n]);\nconst URI_SCHEME = /^[a-zA-Z][a-zA-Z\\d+.-]*:/;\n\nawait init();\n\ninterface TextEdit {\n start: number;\n end: number;\n value: string;\n}\n\ninterface TransformResult {\n code: string;\n replacements: number;\n}\n\n/**\n * Remove .ts, .tsx, .js, and .jsx suffixes from eligible module specifiers\n * while preserving every other part of the source text.\n */\nexport function stripImportExtensions(\n source: string,\n options: StripOptions = {},\n): string {\n return transformSource(source, options).code;\n}\n\n/**\n * Inspect or rewrite one source file.\n *\n * Preview is the default. Pass write: true to persist changes. The check and\n * write options are mutually exclusive.\n */\nexport async function processFile(\n filePath: string,\n options: ProcessFileOptions = {},\n): Promise<ProcessResult> {\n if (options.check && options.write) {\n throw new TypeError(\"check and write cannot both be enabled\");\n }\n\n const absolutePath = resolve(filePath);\n const source = await readFile(absolutePath, \"utf8\");\n const transformed = transformSource(source, options);\n const changed = transformed.code !== source;\n const written = changed && options.write === true;\n\n if (written) {\n await atomicWrite(absolutePath, transformed.code);\n }\n\n return {\n path: absolutePath,\n changed,\n replacements: transformed.replacements,\n written,\n };\n}\n\n/**\n * Find supported JavaScript and TypeScript source files below a file or\n * directory. Directory symlinks are intentionally not followed.\n */\nexport async function findSourceFiles(\n inputPath: string,\n options: FindFilesOptions = {},\n): Promise<string[]> {\n const absolutePath = resolve(inputPath);\n const baseDirectory = resolve(options.baseDirectory ?? process.cwd());\n const ignoredDirectories = new Set(\n [\n ...DEFAULT_IGNORED_DIRECTORIES,\n ...(options.ignoredDirectories ?? []),\n ].map((name) => name.toLowerCase()),\n );\n const ignorePatterns = options.ignorePatterns ?? [];\n const sourceExtensions = normalizeExtensions(\n options.extensions ?? DEFAULT_SOURCE_EXTENSIONS,\n );\n const files: string[] = [];\n\n await collectSourceFiles(\n absolutePath,\n baseDirectory,\n ignoredDirectories,\n ignorePatterns,\n sourceExtensions,\n files,\n );\n return files.sort((left, right) => left.localeCompare(right));\n}\n\nfunction transformSource(\n source: string,\n options: StripOptions,\n): TransformResult {\n if (typeof source !== \"string\")\n throw new TypeError(\"source must be a string\");\n\n const [imports] = parse(source);\n const edits: TextEdit[] = [];\n\n for (const imported of imports) {\n const specifier = imported.specifier;\n if (typeof specifier !== \"string\" || specifier.length === 0) continue;\n if (imported.type === \"dynamic\" && imported.glob) continue;\n if (!REMOVABLE_EXTENSION.test(specifier)) continue;\n if (!shouldTransformSpecifier(specifier, options)) continue;\n\n const rawRange = source.slice(imported.start, imported.end);\n const offset = rawRange.indexOf(specifier);\n if (offset < 0) continue;\n\n const start = imported.start + offset;\n edits.push({\n start,\n end: start + specifier.length,\n value: specifier.replace(REMOVABLE_EXTENSION, \"\"),\n });\n }\n\n return {\n code: applyEdits(source, edits),\n replacements: edits.length,\n };\n}\n\nfunction shouldTransformSpecifier(\n specifier: string,\n options: StripOptions,\n): boolean {\n if (isRelativeSpecifier(specifier)) return true;\n return (\n options.includePackageSubpaths === true && isPackageSubpath(specifier)\n );\n}\n\nfunction isRelativeSpecifier(specifier: string): boolean {\n return specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n}\n\nfunction isPackageSubpath(specifier: string): boolean {\n if (\n specifier.startsWith(\"/\") ||\n specifier.charCodeAt(0) === 92 ||\n specifier.startsWith(\"#\") ||\n URI_SCHEME.test(specifier)\n ) {\n return false;\n }\n\n const path = specifier.split(/[?#]/, 1)[0];\n if (!path) return false;\n\n const segments = path.split(\"/\");\n return path.startsWith(\"@\") ? segments.length >= 3 : segments.length >= 2;\n}\n\nfunction applyEdits(source: string, edits: TextEdit[]): string {\n let output = source;\n\n for (const edit of edits.sort((left, right) => right.start - left.start)) {\n output =\n output.slice(0, edit.start) + edit.value + output.slice(edit.end);\n }\n\n return output;\n}\n\nasync function collectSourceFiles(\n currentPath: string,\n baseDirectory: string,\n ignoredDirectories: ReadonlySet<string>,\n ignorePatterns: readonly string[],\n sourceExtensions: ReadonlySet<string>,\n files: string[],\n): Promise<void> {\n const metadata = await lstat(currentPath);\n if (metadata.isSymbolicLink()) return;\n if (\n isPathIgnored(\n currentPath,\n metadata.isDirectory(),\n baseDirectory,\n ignorePatterns,\n )\n ) {\n return;\n }\n\n if (metadata.isFile()) {\n if (sourceExtensions.has(extname(currentPath).toLowerCase())) {\n files.push(currentPath);\n }\n return;\n }\n\n if (!metadata.isDirectory()) return;\n\n const entries = await readdir(currentPath, {withFileTypes: true});\n entries.sort((left, right) => left.name.localeCompare(right.name));\n\n for (const entry of entries) {\n if (\n entry.isDirectory() &&\n ignoredDirectories.has(entry.name.toLowerCase())\n ) {\n continue;\n }\n\n if (entry.isSymbolicLink()) continue;\n await collectSourceFiles(\n join(currentPath, entry.name),\n baseDirectory,\n ignoredDirectories,\n ignorePatterns,\n sourceExtensions,\n files,\n );\n }\n}\n\nfunction normalizeExtensions(extensions: readonly string[]): Set<string> {\n if (extensions.length === 0) {\n throw new TypeError(\"at least one source extension is required\");\n }\n\n const normalized = new Set<string>();\n\n for (const extension of extensions) {\n const value = extension.trim().toLowerCase();\n const withoutDot = value.startsWith(\".\") ? value.slice(1) : value;\n\n if (!/^[a-z0-9]+$/i.test(withoutDot)) {\n throw new TypeError(\"invalid source extension: \" + extension);\n }\n\n normalized.add(\".\" + withoutDot);\n }\n\n return normalized;\n}\n\n/**\n * Test a path against the same cwd-relative glob rules used by file discovery.\n */\nexport function isPathIgnored(\n filePath: string,\n isDirectory: boolean,\n baseDirectory: string,\n patterns: readonly string[],\n): boolean {\n if (patterns.length === 0) return false;\n\n const relativePath = relative(baseDirectory, filePath)\n .split(\"\\\\\")\n .join(\"/\");\n const candidate = relativePath.length === 0 ? \".\" : relativePath;\n const candidates = isDirectory ? [candidate, candidate + \"/\"] : [candidate];\n\n return patterns.some((pattern) => {\n if (pattern.length === 0) {\n throw new TypeError(\"ignore patterns cannot be empty\");\n }\n\n return candidates.some((path) =>\n minimatch(path, pattern, {\n dot: true,\n nocase: process.platform === \"win32\",\n nonegate: true,\n }),\n );\n });\n}\n\nasync function atomicWrite(filePath: string, contents: string): Promise<void> {\n const metadata = await lstat(filePath);\n const temporaryPath = join(\n dirname(filePath),\n \".\" +\n basename(filePath) +\n \".\" +\n process.pid +\n \".\" +\n randomUUID() +\n \".tmp\",\n );\n\n try {\n await writeFile(temporaryPath, contents, {\n encoding: \"utf8\",\n mode: metadata.mode,\n });\n await chmod(temporaryPath, metadata.mode);\n await rename(temporaryPath, filePath);\n } catch (error) {\n await unlink(temporaryPath).catch(() => undefined);\n throw error;\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {randomUUID} from \"node:crypto\";\nimport {\n chmod,\n lstat,\n readFile,\n readdir,\n rename,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport {\n basename,\n dirname,\n extname,\n join,\n relative,\n resolve,\n} from \"node:path\";\nimport {init, parse} from \"es-module-lexer\";\nimport {minimatch} from \"minimatch\";\n\nimport type {\n FindFilesOptions,\n ProcessFileOptions,\n ProcessResult,\n StripOptions,\n} from \"./types.js\";\n\nexport type {\n FindFilesOptions,\n ProcessFileOptions,\n ProcessResult,\n StripOptions,\n} from \"./types.js\";\n\nconst REMOVABLE_EXTENSION = /\\.(?:tsx?|jsx?)(?=[?#]|$)/i;\nexport const DEFAULT_SOURCE_EXTENSIONS: readonly string[] = Object.freeze([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".mts\",\n \".cts\",\n \".mjs\",\n \".cjs\",\n]);\nconst DEFAULT_IGNORED_DIRECTORIES = new Set([\n \".git\",\n \"node_modules\",\n \"dist\",\n \"coverage\",\n]);\nconst URI_SCHEME = /^[a-zA-Z][a-zA-Z\\d+.-]*:/;\n\nawait init();\n\ninterface TextEdit {\n start: number;\n end: number;\n value: string;\n}\n\ninterface TransformResult {\n code: string;\n replacements: number;\n}\n\n/**\n * Remove .ts, .tsx, .js, and .jsx suffixes from eligible module specifiers\n * while preserving every other part of the source text.\n */\nexport function stripImportExtensions(\n source: string,\n options: StripOptions = {},\n): string {\n return transformSource(source, options).code;\n}\n\n/**\n * Inspect or rewrite one source file.\n *\n * Preview is the default. Pass write: true to persist changes. The check and\n * write options are mutually exclusive.\n */\nexport async function processFile(\n filePath: string,\n options: ProcessFileOptions = {},\n): Promise<ProcessResult> {\n if (options.check && options.write) {\n throw new TypeError(\"check and write cannot both be enabled\");\n }\n\n const absolutePath = resolve(filePath);\n const source = await readFile(absolutePath, \"utf8\");\n const transformed = transformSource(source, options);\n const changed = transformed.code !== source;\n const written = changed && options.write === true;\n\n if (written) {\n await atomicWrite(absolutePath, transformed.code);\n }\n\n return {\n path: absolutePath,\n changed,\n replacements: transformed.replacements,\n written,\n };\n}\n\n/**\n * Find supported JavaScript and TypeScript source files below a file or\n * directory. Directory symlinks are intentionally not followed.\n */\nexport async function findSourceFiles(\n inputPath: string,\n options: FindFilesOptions = {},\n): Promise<string[]> {\n const absolutePath = resolve(inputPath);\n const baseDirectory = resolve(options.baseDirectory ?? process.cwd());\n const ignoredDirectories = new Set(\n [\n ...DEFAULT_IGNORED_DIRECTORIES,\n ...(options.ignoredDirectories ?? []),\n ].map((name) => name.toLowerCase()),\n );\n const ignorePatterns = options.ignorePatterns ?? [];\n const sourceExtensions = normalizeExtensions(\n options.extensions ?? DEFAULT_SOURCE_EXTENSIONS,\n );\n const files: string[] = [];\n\n await collectSourceFiles(\n absolutePath,\n baseDirectory,\n ignoredDirectories,\n ignorePatterns,\n sourceExtensions,\n files,\n );\n return files.sort((left, right) => left.localeCompare(right));\n}\n\nfunction transformSource(\n source: string,\n options: StripOptions,\n): TransformResult {\n if (typeof source !== \"string\")\n throw new TypeError(\"source must be a string\");\n\n const [imports] = parse(source);\n const edits: TextEdit[] = [];\n\n for (const imported of imports) {\n const specifier = imported.specifier;\n if (typeof specifier !== \"string\" || specifier.length === 0) continue;\n if (imported.type === \"dynamic\" && imported.glob) continue;\n if (!REMOVABLE_EXTENSION.test(specifier)) continue;\n if (!shouldTransformSpecifier(specifier, options)) continue;\n\n const rawRange = source.slice(imported.start, imported.end);\n const offset = rawRange.indexOf(specifier);\n if (offset < 0) continue;\n\n const start = imported.start + offset;\n edits.push({\n start,\n end: start + specifier.length,\n value: specifier.replace(REMOVABLE_EXTENSION, \"\"),\n });\n }\n\n return {\n code: applyEdits(source, edits),\n replacements: edits.length,\n };\n}\n\nfunction shouldTransformSpecifier(\n specifier: string,\n options: StripOptions,\n): boolean {\n if (\n isRelativeSpecifier(specifier) ||\n isProjectAliasSpecifier(specifier)\n ) {\n return true;\n }\n\n return (\n options.includePackageSubpaths === true && isPackageSubpath(specifier)\n );\n}\n\nfunction isRelativeSpecifier(specifier: string): boolean {\n return specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n}\n\nfunction isProjectAliasSpecifier(specifier: string): boolean {\n return specifier.startsWith(\"@/\") || specifier.startsWith(\"~/\");\n}\n\nfunction isPackageSubpath(specifier: string): boolean {\n if (\n specifier.startsWith(\"/\") ||\n specifier.charCodeAt(0) === 92 ||\n specifier.startsWith(\"#\") ||\n URI_SCHEME.test(specifier)\n ) {\n return false;\n }\n\n const path = specifier.split(/[?#]/, 1)[0];\n if (!path) return false;\n\n const segments = path.split(\"/\");\n return path.startsWith(\"@\") ? segments.length >= 3 : segments.length >= 2;\n}\n\nfunction applyEdits(source: string, edits: TextEdit[]): string {\n let output = source;\n\n for (const edit of edits.sort((left, right) => right.start - left.start)) {\n output =\n output.slice(0, edit.start) + edit.value + output.slice(edit.end);\n }\n\n return output;\n}\n\nasync function collectSourceFiles(\n currentPath: string,\n baseDirectory: string,\n ignoredDirectories: ReadonlySet<string>,\n ignorePatterns: readonly string[],\n sourceExtensions: ReadonlySet<string>,\n files: string[],\n): Promise<void> {\n const metadata = await lstat(currentPath);\n if (metadata.isSymbolicLink()) return;\n if (\n isPathIgnored(\n currentPath,\n metadata.isDirectory(),\n baseDirectory,\n ignorePatterns,\n )\n ) {\n return;\n }\n\n if (metadata.isFile()) {\n if (sourceExtensions.has(extname(currentPath).toLowerCase())) {\n files.push(currentPath);\n }\n return;\n }\n\n if (!metadata.isDirectory()) return;\n\n const entries = await readdir(currentPath, {withFileTypes: true});\n entries.sort((left, right) => left.name.localeCompare(right.name));\n\n for (const entry of entries) {\n if (\n entry.isDirectory() &&\n ignoredDirectories.has(entry.name.toLowerCase())\n ) {\n continue;\n }\n\n if (entry.isSymbolicLink()) continue;\n await collectSourceFiles(\n join(currentPath, entry.name),\n baseDirectory,\n ignoredDirectories,\n ignorePatterns,\n sourceExtensions,\n files,\n );\n }\n}\n\nfunction normalizeExtensions(extensions: readonly string[]): Set<string> {\n if (extensions.length === 0) {\n throw new TypeError(\"at least one source extension is required\");\n }\n\n const normalized = new Set<string>();\n\n for (const extension of extensions) {\n const value = extension.trim().toLowerCase();\n const withoutDot = value.startsWith(\".\") ? value.slice(1) : value;\n\n if (!/^[a-z0-9]+$/i.test(withoutDot)) {\n throw new TypeError(\"invalid source extension: \" + extension);\n }\n\n normalized.add(\".\" + withoutDot);\n }\n\n return normalized;\n}\n\n/**\n * Test a path against the same cwd-relative glob rules used by file discovery.\n */\nexport function isPathIgnored(\n filePath: string,\n isDirectory: boolean,\n baseDirectory: string,\n patterns: readonly string[],\n): boolean {\n if (patterns.length === 0) return false;\n\n const relativePath = relative(baseDirectory, filePath)\n .split(\"\\\\\")\n .join(\"/\");\n const candidate = relativePath.length === 0 ? \".\" : relativePath;\n const candidates = isDirectory ? [candidate, candidate + \"/\"] : [candidate];\n\n return patterns.some((pattern) => {\n if (pattern.length === 0) {\n throw new TypeError(\"ignore patterns cannot be empty\");\n }\n\n return candidates.some((path) =>\n minimatch(path, pattern, {\n dot: true,\n nocase: process.platform === \"win32\",\n nonegate: true,\n }),\n );\n });\n}\n\nasync function atomicWrite(filePath: string, contents: string): Promise<void> {\n const metadata = await lstat(filePath);\n const temporaryPath = join(\n dirname(filePath),\n \".\" +\n basename(filePath) +\n \".\" +\n process.pid +\n \".\" +\n randomUUID() +\n \".tmp\",\n );\n\n try {\n await writeFile(temporaryPath, contents, {\n encoding: \"utf8\",\n mode: metadata.mode,\n });\n await chmod(temporaryPath, metadata.mode);\n await rename(temporaryPath, filePath);\n } catch (error) {\n await unlink(temporaryPath).catch(() => undefined);\n throw error;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "extensionless-imports",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Remove JavaScript and TypeScript extensions from module specifiers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",