diff --git a/README.md b/README.md index baab588..8fae06b 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ Module name or relative path similar to CommonJS [require](https://nodejs.org/ap - `'./dogs.mjs'` - `'./minimal'` - `importSync` will look for `'./minimal.js'` before `'./minimal.mjs'` + - `importSync` will look for matching extensions in the order `[.js, .mjs, .cjs]` - `'node-fetch'` - `importSync` can import pure-esm [node-fetch](https://github.com/node-fetch/node-fetch) (v3) in your cjs project diff --git a/package-lock.json b/package-lock.json index 56f72f5..6cea309 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "import-sync", - "version": "2.0.5", + "version": "2.0.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "import-sync", - "version": "2.0.5", + "version": "2.0.6", "license": "MIT", "dependencies": { "esm": "^3.2.25" @@ -17,8 +17,8 @@ "@types/node": "^20.8.7", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", - "eslint": "^8.51.0", - "eslint-plugin-jest": "^27.4.2", + "eslint": "^8.52.0", + "eslint-plugin-jest": "^27.4.3", "jest": "^29.7.0", "node-fetch": "^3.3.2", "ts-jest": "^29.1.1", @@ -767,21 +767,21 @@ } }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -803,9 +803,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1649,6 +1649,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -2329,18 +2335,19 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2383,9 +2390,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.2.tgz", - "integrity": "sha512-3Nfvv3wbq2+PZlRTf2oaAWXWwbdBejFRBR2O8tAO67o+P8zno+QGbcDYaAXODlreXVg+9gvWhKKmG2rgfb8GEg==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", + "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" diff --git a/package.json b/package.json index cb3a981..2a4b985 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "git", "url": "https://github.com/nktnet1/import-sync" }, - "version": "2.0.5", + "version": "2.0.6", "files": [ "dist" ], @@ -47,8 +47,8 @@ "@types/node": "^20.8.7", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", - "eslint": "^8.51.0", - "eslint-plugin-jest": "^27.4.2", + "eslint": "^8.52.0", + "eslint-plugin-jest": "^27.4.3", "jest": "^29.7.0", "node-fetch": "^3.3.2", "ts-jest": "^29.1.1", diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..2c16766 --- /dev/null +++ b/src/config.ts @@ -0,0 +1 @@ +export const VALID_FILE_EXTENSIONS = Object.freeze(['.js', '.mjs', '.cjs']); diff --git a/src/files.ts b/src/files.ts index 00493fb..c2eda93 100644 --- a/src/files.ts +++ b/src/files.ts @@ -1,3 +1,7 @@ +import fs from 'fs'; +import path from 'path'; +import { VALID_FILE_EXTENSIONS } from './config'; + /** * Get the file path of the caller function. * @@ -15,3 +19,30 @@ export const getCallerFilePath = (): string => { Error.prepareStackTrace = orig; return stack[1].getFileName(); }; + +/** + * Find the module file path by checking for available extensions + * as defined by VALID_FILE_EXTENSIONS + * + * @param {string} modulePath - The path to the module + * @param {string} basePath - The base path for the module + * @returns {string} The resolved file path + * @throws {Error} If the file is not found + */ +export const findModuleFile = (modulePath: string, basePath: string): string => { + const filePath = path.join(basePath, modulePath); + if (fs.existsSync(filePath)) { + return filePath; + } + if (!path.extname(filePath)) { + for (const ext of VALID_FILE_EXTENSIONS) { + const extFilePath = path.join(basePath, `${modulePath}${ext}`); + if (fs.existsSync(extFilePath)) { + return extFilePath; + } + } + } + throw new Error( + `No such file '${filePath}' with matching extensions [${VALID_FILE_EXTENSIONS}]` + ); +}; diff --git a/src/import.ts b/src/import.ts index 89880cf..5580986 100644 --- a/src/import.ts +++ b/src/import.ts @@ -2,7 +2,7 @@ import esm from 'esm'; import path from 'path'; import fs from 'fs'; import { ESMOptions, Options } from './types'; -import { getCallerFilePath } from './files'; +import { findModuleFile, getCallerFilePath } from './files'; /** * Creates an esm-compatible require function that can import ES Modules @@ -48,10 +48,7 @@ const importSync = (id: string, options: Options = {}) => { esmOptions: {}, }; const opts = { ...defaultOptions, ...options }; - let modulePath = id; - if (/^\.\.?\//.test(id)) { - modulePath = path.join(opts.basePath, id); - } + const modulePath = /^\.\.?\//.test(id) ? findModuleFile(id, opts.basePath) : id; const es6Require = createEs6Require(opts.esmOptions); try { return es6Require(modulePath);