├── test ├── fixtures │ ├── type-bad-js │ │ ├── file.js │ │ └── package.json │ ├── type-bad-cjs │ │ ├── file.cjs │ │ └── package.json │ ├── type-bad-mjs │ │ ├── file.mjs │ │ └── package.json │ ├── type-commonjs-js │ │ ├── file.js │ │ └── package.json │ ├── type-module-cjs │ │ ├── file.cjs │ │ └── package.json │ ├── type-module-js │ │ ├── file.js │ │ └── package.json │ ├── type-module-mjs │ │ ├── file.mjs │ │ └── package.json │ ├── type-commonjs-cjs │ │ ├── file.cjs │ │ └── package.json │ ├── type-commonjs-mjs │ │ ├── file.mjs │ │ └── package.json │ ├── type-undefined-cjs │ │ ├── file.cjs │ │ └── package.json │ ├── type-undefined-js │ │ ├── file.js │ │ └── package.json │ └── type-undefined-mjs │ │ ├── file.mjs │ │ └── package.json └── index.js ├── .travis.yml ├── LICENSE ├── package.json ├── .gitignore ├── readme.md └── index.js /test/fixtures/type-bad-js/file.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-bad-cjs/file.cjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-bad-mjs/file.mjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-commonjs-js/file.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-module-cjs/file.cjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-module-js/file.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-module-mjs/file.mjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-commonjs-cjs/file.cjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-commonjs-mjs/file.mjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-undefined-cjs/file.cjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-undefined-js/file.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/type-undefined-mjs/file.mjs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - 12 5 | - 14 6 | - 15 7 | script: 8 | - npm run ci -------------------------------------------------------------------------------- /test/fixtures/type-undefined-cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-undefined-cjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/type-undefined-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-undefined-js", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "file.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/type-undefined-mjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-undefined-mjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/type-commonjs-cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-commonjs-cjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "commonjs", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/type-bad-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-module-js", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "file.js", 6 | "type": "bad", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-bad-cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-module-cjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "bad", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-bad-mjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-module-mjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "bad", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-module-cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-module-cjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-module-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-module-js", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "file.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-module-mjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-module-mjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-commonjs-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-commonjs-js", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "file.js", 6 | "type": "commonjs", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/type-commonjs-mjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-commonjs-mjs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "commonjs", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC" 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License Copyright (c) 2020 David Mark Clements 2 | 3 | Permission is hereby granted, 4 | free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, copy, modify, merge, 7 | publish, distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to the 9 | following conditions: 10 | 11 | The above copyright notice and this permission notice 12 | (including the next paragraph) shall be included in all copies or substantial 13 | portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 18 | EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-file-esm", 3 | "version": "1.0.0", 4 | "description": "Determines whether a Node file is a Module (`import`) or a Script (`require`)", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "tap -R classic --100", 8 | "ci": "npm test" 9 | }, 10 | "keywords": [ 11 | "esm", 12 | "cjs", 13 | "package.json", 14 | "module", 15 | "ecmascript modules", 16 | "native modules", 17 | "native ecmascript modules" 18 | ], 19 | "author": "David Mark Clements (@davidmarkclem)", 20 | "license": "MIT", 21 | "engineStrict": true, 22 | "engine": { 23 | "node": ">= 12.4.0" 24 | }, 25 | "devDependencies": { 26 | "nonsynchronous": "^1.2.0", 27 | "standard": "^14.3.4", 28 | "tap": "^14.10.8" 29 | }, 30 | "dependencies": { 31 | "read-pkg-up": "^7.0.1" 32 | }, 33 | "directories": { 34 | "test": "test" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/davidmarkclements/is-file-esm.git" 39 | }, 40 | "bugs": { 41 | "url": "https://github.com/davidmarkclements/is-file-esm/issues" 42 | }, 43 | "homepage": "https://github.com/davidmarkclements/is-file-esm#readme" 44 | } 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # is-file-esm 2 | 3 | > Determines whether a Node file is a Module (`import`) or a Script (`require`) 4 | 5 | ## Algorithm 6 | 7 | Determining the module system of a file comes from three inputs, the `type` field 8 | of the closest `package.json` to that file, the file extension (`.js`, `.mjs` or `.cjs`) 9 | and the lesser know `--input-type` command-line flag. The latter only applies to 10 | dyamic input (via STDIN, `--eval` or `--print` flags) so is not considered with this library. 11 | 12 | So to determine whether a file is an esm file (e.g. native EcmaScript modules) or not, 13 | we use the following procedure: 14 | 15 | ``` 16 | read package.json for "type" field, 17 | if type is "module" 18 | if answer.mjs -> module 19 | if answer.js -> module 20 | if answer.cjs -> script 21 | if type is "commonjs" 22 | if answer.mjs -> module 23 | if answer.js -> script 24 | if answer.cjs -> script 25 | if type is not set 26 | if answer.mjs -> module 27 | if answer.js -> script 28 | if answer.cjs -> script 29 | ``` 30 | 31 | ## API 32 | 33 | The `is-file-esm` module provides synchronous, awaitable (promise-based) and callback based APIs. 34 | 35 | In each case the Result object has the following shape: 36 | 37 | ```js 38 | { 39 | esm: Boolean, // true if file is a Module, false if it is a Script 40 | type: String, // the determined package.json type, may be undefined, 'module', or 'commonjs' 41 | extType: String, // the file extension type, may be 'c', 'm' or 'j' 42 | path: String, // the input path 43 | pkgPath: String // the path to the package.json from which the type was determined 44 | } 45 | ``` 46 | 47 | ### Awaitable (promise-based) 48 | 49 | #### `await isFileEsm(path) => Result` 50 | 51 | ```js 52 | import isFileEsm from 'is-file-esm' 53 | const { esm, path } = await isFileEsm('/path/to/file.js') 54 | if (esm) console.log(`File ${path} is a Module`) 55 | else console.log(`File ${path} is a Script`) 56 | ``` 57 | 58 | ### Callback-style 59 | 60 | #### `isFileEsm(path, cb(err, Result))` 61 | 62 | ```js 63 | const isFileEsm = require('is-file-esm') 64 | isFileEsm('/path/to/file.js', (err, result) => { 65 | if (err) { 66 | console.error(err) 67 | return 68 | } 69 | if (result.esm) console.log(`File ${result.path} is a Module`) 70 | else console.log(`File ${result.path} is a Script`) 71 | }) 72 | ``` 73 | 74 | ### Synchronous 75 | 76 | #### `isFileEsm.sync(path) => Result` 77 | 78 | ```js 79 | import isFileEsm from 'is-file-esm' 80 | const { esm, path } = isFileEsm.sync('/path/to/file.js') 81 | if (esm) console.log(`File ${path} is a Module`) 82 | else console.log(`File ${path} is a Script`) 83 | ``` 84 | 85 | ### Test 86 | 87 | ```sh 88 | npm test 89 | ``` 90 | 91 | ``` 92 | test/index.js ..................................... 213/213 93 | total ............................................. 213/213 94 | 95 | 213 passing (927.584ms) 96 | 97 | ok 98 | ----------|----------|----------|----------|----------|-------------------| 99 | File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | 100 | ----------|----------|----------|----------|----------|-------------------| 101 | All files | 100 | 100 | 100 | 100 | | 102 | index.js | 100 | 100 | 100 | 100 | | 103 | ----------|----------|----------|----------|----------|-------------------| 104 | ``` 105 | 106 | ### License 107 | 108 | MIT -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const { extname, isAbsolute, dirname } = require('path') 3 | const { access, accessSync, constants: { F_OK } } = require('fs') 4 | const { promisify, callbackify } = require('util') 5 | const readPkgUp = callbackify(require('read-pkg-up')) 6 | 7 | const isFileEsmPromise = promisify(isFileEsm) 8 | 9 | const tick = queueMicrotask 10 | 11 | const ERR_PATH_MUST_BE_STRING = 'is-esm: path must be a string' 12 | const ERR_PATH_MUST_BE_ABSOLUTE = 'is-esm: absolute paths only' 13 | const ERR_PATH_MUST_EXIST = 'is-esm: path does not exist' 14 | const ERR_PATH_MUST_HAVE_VALID_EXT = 'is-esm: path must be to a file with an extension of .js, .mjs or .cjs' 15 | 16 | function isFileEsm (path, cb) { 17 | if (arguments.length <= 1) return isFileEsmPromise(path) 18 | if (typeof path !== 'string') return void tick(() => cb(Error(ERR_PATH_MUST_BE_STRING))) 19 | if (isAbsolute(path) === false) return void tick(() => cb(Error(ERR_PATH_MUST_BE_ABSOLUTE))) 20 | const extMatch = /\.(c|m)?js/.exec(extname(path)) 21 | if (extMatch === null) return void tick(() => cb(Error(ERR_PATH_MUST_HAVE_VALID_EXT))) 22 | access(path, F_OK, (err) => { 23 | if (err) return void cb(Error(ERR_PATH_MUST_EXIST)) 24 | const [, extType = 'j'] = extMatch 25 | const cwd = dirname(path) 26 | readPkgUp({ cwd }, (err, pkg) => { 27 | if (err) return void cb(err) 28 | const { type } = pkg.packageJson 29 | switch (type) { 30 | case undefined: { 31 | if (extType === 'j') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path }) 32 | if (extType === 'm') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path }) 33 | /* istanbul ignore else */ 34 | if (extType === 'c') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path }) 35 | // unreachable 36 | } 37 | case 'commonjs': { 38 | if (extType === 'j') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path }) 39 | if (extType === 'm') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path }) 40 | /* istanbul ignore else */ 41 | if (extType === 'c') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path }) 42 | // unreachable 43 | } 44 | case 'module': { 45 | if (extType === 'j') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path }) 46 | if (extType === 'm') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path }) 47 | /* istanbul ignore else */ 48 | if (extType === 'c') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path }) 49 | // unreachable 50 | } 51 | default: return void cb(Object.assign(Error(`package.json type "${type}" not recognized`), { meta: { type, extType, path, pkgPath: pkg.path } })) 52 | } 53 | }) 54 | }) 55 | } 56 | 57 | isFileEsm.sync = function isFileEsmSync (path) { 58 | if (typeof path !== 'string') throw Error(ERR_PATH_MUST_BE_STRING) 59 | if (isAbsolute(path) === false) throw Error(ERR_PATH_MUST_BE_ABSOLUTE) 60 | const extMatch = /\.(c|m)?js/.exec(extname(path)) 61 | if (extMatch === null) throw Error(ERR_PATH_MUST_HAVE_VALID_EXT) 62 | try { 63 | accessSync(path, F_OK) 64 | } catch (err) { 65 | throw Error(ERR_PATH_MUST_EXIST) 66 | } 67 | const [, extType = 'j'] = extMatch 68 | const cwd = dirname(path) 69 | const pkg = readPkgUp.sync({ cwd }) 70 | const { type } = pkg.packageJson 71 | switch (type) { 72 | case undefined: { 73 | if (extType === 'j') return { esm: false, type, extType, path, pkgPath: pkg.path } 74 | if (extType === 'm') return { esm: true, type, extType, path, pkgPath: pkg.path } 75 | /* istanbul ignore else */ 76 | if (extType === 'c') return { esm: false, type, extType, path, pkgPath: pkg.path } 77 | // unreachable 78 | } 79 | case 'commonjs': { 80 | if (extType === 'j') return { esm: false, type, extType, path, pkgPath: pkg.path } 81 | if (extType === 'm') return { esm: true, type, extType, path, pkgPath: pkg.path } 82 | /* istanbul ignore else */ 83 | if (extType === 'c') return { esm: false, type, extType, path, pkgPath: pkg.path } 84 | // unreachable 85 | } 86 | case 'module': { 87 | if (extType === 'j') return { esm: true, type, extType, path, pkgPath: pkg.path } 88 | if (extType === 'm') return { esm: true, type, extType, path, pkgPath: pkg.path } 89 | /* istanbul ignore else */ 90 | if (extType === 'c') return { esm: false, type, extType, path, pkgPath: pkg.path } 91 | // unreachable 92 | } 93 | default: throw Object.assign(Error(`package.json type "${type}" not recognized`), { meta: { type, extType, path, pkgPath: pkg.path } }) 94 | } 95 | } 96 | 97 | isFileEsm.constants = { 98 | ERR_PATH_MUST_BE_STRING, 99 | ERR_PATH_MUST_BE_ABSOLUTE, 100 | ERR_PATH_MUST_EXIST, 101 | ERR_PATH_MUST_HAVE_VALID_EXT 102 | } 103 | 104 | module.exports = isFileEsm 105 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const { join } = require('path') 3 | const { test } = require('tap') 4 | const { when } = require('nonsynchronous') 5 | const { chmodSync } = require('fs') 6 | const isFileEsm = require('..') 7 | const { 8 | ERR_PATH_MUST_BE_STRING, 9 | ERR_PATH_MUST_BE_ABSOLUTE, 10 | ERR_PATH_MUST_EXIST, 11 | ERR_PATH_MUST_HAVE_VALID_EXT 12 | } = isFileEsm.constants 13 | 14 | const ERR_BAD_TYPE = 'package.json type "bad" not recognized' 15 | const ERR_PERMISSION_DENIED = /EACCES: permission denied/ 16 | 17 | const fixtures = join(__dirname, 'fixtures') 18 | 19 | test('path must be string (promise)', async ({ rejects }) => { 20 | await rejects(() => isFileEsm(), Error(ERR_PATH_MUST_BE_STRING)) 21 | await rejects(() => isFileEsm({}), Error(ERR_PATH_MUST_BE_STRING)) 22 | }) 23 | 24 | test('path must be absolute (promise)', async ({ rejects }) => { 25 | await rejects(() => isFileEsm('../foo.js'), Error(ERR_PATH_MUST_BE_ABSOLUTE)) 26 | await rejects(() => isFileEsm('./bar/foo.mjs'), Error(ERR_PATH_MUST_BE_ABSOLUTE)) 27 | }) 28 | 29 | test('path must have ext (promise)', async ({ rejects }) => { 30 | await rejects(() => isFileEsm('/bar/foo'), Error(ERR_PATH_MUST_HAVE_VALID_EXT)) 31 | }) 32 | 33 | test('path must have valid ext (promise)', async ({ rejects }) => { 34 | await rejects(() => isFileEsm('/bar/foo.ext'), Error(ERR_PATH_MUST_HAVE_VALID_EXT)) 35 | }) 36 | 37 | test('path must exist (promise)', async ({ rejects }) => { 38 | await rejects(() => isFileEsm(join(fixtures, 'bar', 'foo.js')), Error(ERR_PATH_MUST_EXIST)) 39 | }) 40 | 41 | test('type-commonjs-cjs promise', async ({ is }) => { 42 | const inputPath = join(fixtures, 'type-commonjs-cjs', 'file.cjs') 43 | const expectedPkgPath = join(fixtures, 'type-commonjs-cjs', 'package.json') 44 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 45 | is(esm, false) 46 | is(path, inputPath) 47 | is(expectedPkgPath, pkgPath) 48 | is(type, 'commonjs') 49 | is(extType, 'c') 50 | }) 51 | 52 | test('type-commonjs-js promise', async ({ is }) => { 53 | const inputPath = join(fixtures, 'type-commonjs-js', 'file.js') 54 | const expectedPkgPath = join(fixtures, 'type-commonjs-js', 'package.json') 55 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 56 | is(esm, false) 57 | is(path, inputPath) 58 | is(expectedPkgPath, pkgPath) 59 | is(type, 'commonjs') 60 | is(extType, 'j') 61 | }) 62 | 63 | test('type-commonjs-mjs promise', async ({ is }) => { 64 | const inputPath = join(fixtures, 'type-commonjs-mjs', 'file.mjs') 65 | const expectedPkgPath = join(fixtures, 'type-commonjs-mjs', 'package.json') 66 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 67 | is(esm, true) 68 | is(path, inputPath) 69 | is(expectedPkgPath, pkgPath) 70 | is(type, 'commonjs') 71 | is(extType, 'm') 72 | }) 73 | 74 | test('type-module-cjs promise', async ({ is }) => { 75 | const inputPath = join(fixtures, 'type-module-cjs', 'file.cjs') 76 | const expectedPkgPath = join(fixtures, 'type-module-cjs', 'package.json') 77 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 78 | is(esm, false) 79 | is(path, inputPath) 80 | is(expectedPkgPath, pkgPath) 81 | is(type, 'module') 82 | is(extType, 'c') 83 | }) 84 | 85 | test('type-module-js promise', async ({ is }) => { 86 | const inputPath = join(fixtures, 'type-module-js', 'file.js') 87 | const expectedPkgPath = join(fixtures, 'type-module-js', 'package.json') 88 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 89 | is(esm, true) 90 | is(path, inputPath) 91 | is(expectedPkgPath, pkgPath) 92 | is(type, 'module') 93 | is(extType, 'j') 94 | }) 95 | 96 | test('type-module-mjs promise', async ({ is }) => { 97 | const inputPath = join(fixtures, 'type-module-mjs', 'file.mjs') 98 | const expectedPkgPath = join(fixtures, 'type-module-mjs', 'package.json') 99 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 100 | is(esm, true) 101 | is(path, inputPath) 102 | is(expectedPkgPath, pkgPath) 103 | is(type, 'module') 104 | is(extType, 'm') 105 | }) 106 | 107 | test('type-undefined-cjs promise', async ({ is }) => { 108 | const inputPath = join(fixtures, 'type-undefined-cjs', 'file.cjs') 109 | const expectedPkgPath = join(fixtures, 'type-undefined-cjs', 'package.json') 110 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 111 | is(esm, false) 112 | is(path, inputPath) 113 | is(expectedPkgPath, pkgPath) 114 | is(type, undefined) 115 | is(extType, 'c') 116 | }) 117 | 118 | test('type-undefined-js promise', async ({ is }) => { 119 | const inputPath = join(fixtures, 'type-undefined-js', 'file.js') 120 | const expectedPkgPath = join(fixtures, 'type-undefined-js', 'package.json') 121 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 122 | is(esm, false) 123 | is(path, inputPath) 124 | is(expectedPkgPath, pkgPath) 125 | is(type, undefined) 126 | is(extType, 'j') 127 | }) 128 | 129 | test('type-undefined-mjs promise', async ({ is }) => { 130 | const inputPath = join(fixtures, 'type-undefined-mjs', 'file.mjs') 131 | const expectedPkgPath = join(fixtures, 'type-undefined-mjs', 'package.json') 132 | const { esm, path, type, extType, pkgPath } = await isFileEsm(inputPath) 133 | is(esm, true) 134 | is(path, inputPath) 135 | is(expectedPkgPath, pkgPath) 136 | is(type, undefined) 137 | is(extType, 'm') 138 | }) 139 | 140 | test('type-bad-cjs promise', async ({ is, rejects }) => { 141 | const inputPath = join(fixtures, 'type-bad-cjs', 'file.cjs') 142 | const expectedPkgPath = join(fixtures, 'type-bad-cjs', 'package.json') 143 | let error = null 144 | await rejects(async () => { 145 | try { 146 | await isFileEsm(inputPath) 147 | } catch (err) { 148 | error = err 149 | throw err 150 | } 151 | }, ERR_BAD_TYPE) 152 | const { path, type, extType, pkgPath } = error.meta 153 | is(path, inputPath) 154 | is(expectedPkgPath, pkgPath) 155 | is(type, 'bad') 156 | is(extType, 'c') 157 | }) 158 | 159 | test('type-bad-js promise', async ({ is, rejects }) => { 160 | const inputPath = join(fixtures, 'type-bad-js', 'file.js') 161 | const expectedPkgPath = join(fixtures, 'type-bad-js', 'package.json') 162 | let error = null 163 | await rejects(async () => { 164 | try { 165 | await isFileEsm(inputPath) 166 | } catch (err) { 167 | error = err 168 | throw err 169 | } 170 | }, ERR_BAD_TYPE) 171 | const { path, type, extType, pkgPath } = error.meta 172 | is(path, inputPath) 173 | is(expectedPkgPath, pkgPath) 174 | is(type, 'bad') 175 | is(extType, 'j') 176 | }) 177 | 178 | test('type-bad-mjs promise', async ({ is, rejects }) => { 179 | const inputPath = join(fixtures, 'type-bad-mjs', 'file.mjs') 180 | const expectedPkgPath = join(fixtures, 'type-bad-mjs', 'package.json') 181 | let error = null 182 | await rejects(async () => { 183 | try { 184 | await isFileEsm(inputPath) 185 | } catch (err) { 186 | error = err 187 | throw err 188 | } 189 | }, ERR_BAD_TYPE) 190 | const { path, type, extType, pkgPath } = error.meta 191 | is(path, inputPath) 192 | is(expectedPkgPath, pkgPath) 193 | is(type, 'bad') 194 | is(extType, 'm') 195 | }) 196 | 197 | test('package.json read error propagation (promise)', async ({ rejects, tearDown }) => { 198 | const inputPath = join(fixtures, 'type-bad-js', 'file.js') 199 | const expectedPkgPath = join(fixtures, 'type-bad-js', 'package.json') 200 | tearDown(() => chmodSync(expectedPkgPath, 0o644)) 201 | chmodSync(expectedPkgPath, 0o000) 202 | await rejects(() => isFileEsm(inputPath), ERR_PERMISSION_DENIED) 203 | }) 204 | 205 | test('type-commonjs-cjs sync', async ({ is }) => { 206 | const inputPath = join(fixtures, 'type-commonjs-cjs', 'file.cjs') 207 | const expectedPkgPath = join(fixtures, 'type-commonjs-cjs', 'package.json') 208 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 209 | is(esm, false) 210 | is(path, inputPath) 211 | is(expectedPkgPath, pkgPath) 212 | is(type, 'commonjs') 213 | is(extType, 'c') 214 | }) 215 | 216 | test('type-commonjs-js sync', async ({ is }) => { 217 | const inputPath = join(fixtures, 'type-commonjs-js', 'file.js') 218 | const expectedPkgPath = join(fixtures, 'type-commonjs-js', 'package.json') 219 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 220 | is(esm, false) 221 | is(path, inputPath) 222 | is(expectedPkgPath, pkgPath) 223 | is(type, 'commonjs') 224 | is(extType, 'j') 225 | }) 226 | 227 | test('type-commonjs-mjs sync', async ({ is }) => { 228 | const inputPath = join(fixtures, 'type-commonjs-mjs', 'file.mjs') 229 | const expectedPkgPath = join(fixtures, 'type-commonjs-mjs', 'package.json') 230 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 231 | is(esm, true) 232 | is(path, inputPath) 233 | is(expectedPkgPath, pkgPath) 234 | is(type, 'commonjs') 235 | is(extType, 'm') 236 | }) 237 | 238 | test('type-module-cjs sync', async ({ is }) => { 239 | const inputPath = join(fixtures, 'type-module-cjs', 'file.cjs') 240 | const expectedPkgPath = join(fixtures, 'type-module-cjs', 'package.json') 241 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 242 | is(esm, false) 243 | is(path, inputPath) 244 | is(expectedPkgPath, pkgPath) 245 | is(type, 'module') 246 | is(extType, 'c') 247 | }) 248 | 249 | test('type-module-js sync', async ({ is }) => { 250 | const inputPath = join(fixtures, 'type-module-js', 'file.js') 251 | const expectedPkgPath = join(fixtures, 'type-module-js', 'package.json') 252 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 253 | is(esm, true) 254 | is(path, inputPath) 255 | is(expectedPkgPath, pkgPath) 256 | is(type, 'module') 257 | is(extType, 'j') 258 | }) 259 | 260 | test('type-module-mjs sync', async ({ is }) => { 261 | const inputPath = join(fixtures, 'type-module-mjs', 'file.mjs') 262 | const expectedPkgPath = join(fixtures, 'type-module-mjs', 'package.json') 263 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 264 | is(esm, true) 265 | is(path, inputPath) 266 | is(expectedPkgPath, pkgPath) 267 | is(type, 'module') 268 | is(extType, 'm') 269 | }) 270 | 271 | test('type-undefined-cjs sync', async ({ is }) => { 272 | const inputPath = join(fixtures, 'type-undefined-cjs', 'file.cjs') 273 | const expectedPkgPath = join(fixtures, 'type-undefined-cjs', 'package.json') 274 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 275 | is(esm, false) 276 | is(path, inputPath) 277 | is(expectedPkgPath, pkgPath) 278 | is(type, undefined) 279 | is(extType, 'c') 280 | }) 281 | 282 | test('type-undefined-js sync', async ({ is }) => { 283 | const inputPath = join(fixtures, 'type-undefined-js', 'file.js') 284 | const expectedPkgPath = join(fixtures, 'type-undefined-js', 'package.json') 285 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 286 | is(esm, false) 287 | is(path, inputPath) 288 | is(expectedPkgPath, pkgPath) 289 | is(type, undefined) 290 | is(extType, 'j') 291 | }) 292 | 293 | test('type-undefined-mjs sync', async ({ is }) => { 294 | const inputPath = join(fixtures, 'type-undefined-mjs', 'file.mjs') 295 | const expectedPkgPath = join(fixtures, 'type-undefined-mjs', 'package.json') 296 | const { esm, path, type, extType, pkgPath } = isFileEsm.sync(inputPath) 297 | is(esm, true) 298 | is(path, inputPath) 299 | is(expectedPkgPath, pkgPath) 300 | is(type, undefined) 301 | is(extType, 'm') 302 | }) 303 | 304 | test('path must be string (sync)', async ({ throws }) => { 305 | throws(() => isFileEsm.sync(), Error(ERR_PATH_MUST_BE_STRING)) 306 | throws(() => isFileEsm.sync({}), Error(ERR_PATH_MUST_BE_STRING)) 307 | }) 308 | 309 | test('path must be absolute (sync)', async ({ throws }) => { 310 | throws(() => isFileEsm.sync('../foo.js'), Error(ERR_PATH_MUST_BE_ABSOLUTE)) 311 | throws(() => isFileEsm.sync('./bar/foo.mjs'), Error(ERR_PATH_MUST_BE_ABSOLUTE)) 312 | }) 313 | 314 | test('path must have ext (sync)', async ({ throws }) => { 315 | throws(() => isFileEsm.sync('/bar/foo'), Error(ERR_PATH_MUST_HAVE_VALID_EXT)) 316 | }) 317 | 318 | test('path must have valid ext (sync)', async ({ throws }) => { 319 | throws(() => isFileEsm.sync('/bar/foo.ext'), Error(ERR_PATH_MUST_HAVE_VALID_EXT)) 320 | }) 321 | 322 | test('path must exist (promise)', async ({ throws }) => { 323 | throws(() => isFileEsm.sync(join(fixtures, 'bar', 'foo.js')), Error(ERR_PATH_MUST_EXIST)) 324 | }) 325 | 326 | test('type-bad-cjs sync', async ({ is, throws }) => { 327 | const inputPath = join(fixtures, 'type-bad-cjs', 'file.cjs') 328 | const expectedPkgPath = join(fixtures, 'type-bad-cjs', 'package.json') 329 | let error = null 330 | throws(() => { 331 | try { 332 | isFileEsm.sync(inputPath) 333 | } catch (err) { 334 | error = err 335 | throw err 336 | } 337 | }, ERR_BAD_TYPE) 338 | const { path, type, extType, pkgPath } = error.meta 339 | is(path, inputPath) 340 | is(expectedPkgPath, pkgPath) 341 | is(type, 'bad') 342 | is(extType, 'c') 343 | }) 344 | 345 | test('type-bad-js sync', async ({ is, throws }) => { 346 | const inputPath = join(fixtures, 'type-bad-js', 'file.js') 347 | const expectedPkgPath = join(fixtures, 'type-bad-js', 'package.json') 348 | let error = null 349 | throws(() => { 350 | try { 351 | isFileEsm.sync(inputPath) 352 | } catch (err) { 353 | error = err 354 | throw err 355 | } 356 | }, ERR_BAD_TYPE) 357 | const { path, type, extType, pkgPath } = error.meta 358 | is(path, inputPath) 359 | is(expectedPkgPath, pkgPath) 360 | is(type, 'bad') 361 | is(extType, 'j') 362 | }) 363 | 364 | test('type-bad-mjs sync', async ({ is, throws }) => { 365 | const inputPath = join(fixtures, 'type-bad-mjs', 'file.mjs') 366 | const expectedPkgPath = join(fixtures, 'type-bad-mjs', 'package.json') 367 | let error = null 368 | throws(() => { 369 | try { 370 | isFileEsm.sync(inputPath) 371 | } catch (err) { 372 | error = err 373 | throw err 374 | } 375 | }, ERR_BAD_TYPE) 376 | const { path, type, extType, pkgPath } = error.meta 377 | is(path, inputPath) 378 | is(expectedPkgPath, pkgPath) 379 | is(type, 'bad') 380 | is(extType, 'm') 381 | }) 382 | 383 | test('package.json read error propagation (sync)', async ({ throws, tearDown }) => { 384 | const inputPath = join(fixtures, 'type-bad-js', 'file.js') 385 | const expectedPkgPath = join(fixtures, 'type-bad-js', 'package.json') 386 | tearDown(() => chmodSync(expectedPkgPath, 0o644)) 387 | chmodSync(expectedPkgPath, 0o000) 388 | throws(() => isFileEsm.sync(inputPath), ERR_PERMISSION_DENIED) 389 | }) 390 | 391 | test('type-commonjs-cjs callback', async ({ is, error }) => { 392 | const inputPath = join(fixtures, 'type-commonjs-cjs', 'file.cjs') 393 | const expectedPkgPath = join(fixtures, 'type-commonjs-cjs', 'package.json') 394 | const until = when() 395 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 396 | error(err) 397 | is(esm, false) 398 | is(path, inputPath) 399 | is(expectedPkgPath, pkgPath) 400 | is(type, 'commonjs') 401 | is(extType, 'c') 402 | until() 403 | }) 404 | await until.done() 405 | }) 406 | 407 | test('type-commonjs-js callback', async ({ is, error }) => { 408 | const inputPath = join(fixtures, 'type-commonjs-js', 'file.js') 409 | const expectedPkgPath = join(fixtures, 'type-commonjs-js', 'package.json') 410 | const until = when() 411 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 412 | error(err) 413 | is(esm, false) 414 | is(path, inputPath) 415 | is(expectedPkgPath, pkgPath) 416 | is(type, 'commonjs') 417 | is(extType, 'j') 418 | until() 419 | }) 420 | await until.done() 421 | }) 422 | 423 | test('type-commonjs-mjs callback', async ({ is, error }) => { 424 | const inputPath = join(fixtures, 'type-commonjs-mjs', 'file.mjs') 425 | const expectedPkgPath = join(fixtures, 'type-commonjs-mjs', 'package.json') 426 | const until = when() 427 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 428 | error(err) 429 | is(esm, true) 430 | is(path, inputPath) 431 | is(expectedPkgPath, pkgPath) 432 | is(type, 'commonjs') 433 | is(extType, 'm') 434 | until() 435 | }) 436 | await until.done() 437 | }) 438 | 439 | test('type-module-cjs callback', async ({ is, error }) => { 440 | const inputPath = join(fixtures, 'type-module-cjs', 'file.cjs') 441 | const expectedPkgPath = join(fixtures, 'type-module-cjs', 'package.json') 442 | const until = when() 443 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 444 | error(err) 445 | is(esm, false) 446 | is(path, inputPath) 447 | is(expectedPkgPath, pkgPath) 448 | is(type, 'module') 449 | is(extType, 'c') 450 | until() 451 | }) 452 | await until.done() 453 | }) 454 | 455 | test('type-module-js callback', async ({ is, error }) => { 456 | const inputPath = join(fixtures, 'type-module-js', 'file.js') 457 | const expectedPkgPath = join(fixtures, 'type-module-js', 'package.json') 458 | const until = when() 459 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 460 | error(err) 461 | is(esm, true) 462 | is(path, inputPath) 463 | is(expectedPkgPath, pkgPath) 464 | is(type, 'module') 465 | is(extType, 'j') 466 | until() 467 | }) 468 | await until.done() 469 | }) 470 | 471 | test('type-module-mjs callback', async ({ is, error }) => { 472 | const inputPath = join(fixtures, 'type-module-mjs', 'file.mjs') 473 | const expectedPkgPath = join(fixtures, 'type-module-mjs', 'package.json') 474 | const until = when() 475 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 476 | error(err) 477 | is(esm, true) 478 | is(path, inputPath) 479 | is(expectedPkgPath, pkgPath) 480 | is(type, 'module') 481 | is(extType, 'm') 482 | until() 483 | }) 484 | await until.done() 485 | }) 486 | 487 | test('type-undefined-cjs callback', async ({ is, error }) => { 488 | const inputPath = join(fixtures, 'type-undefined-cjs', 'file.cjs') 489 | const expectedPkgPath = join(fixtures, 'type-undefined-cjs', 'package.json') 490 | const until = when() 491 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 492 | error(err) 493 | is(esm, false) 494 | is(path, inputPath) 495 | is(expectedPkgPath, pkgPath) 496 | is(type, undefined) 497 | is(extType, 'c') 498 | until() 499 | }) 500 | await until.done() 501 | }) 502 | 503 | test('type-undefined-js callback', async ({ is, error }) => { 504 | const inputPath = join(fixtures, 'type-undefined-js', 'file.js') 505 | const expectedPkgPath = join(fixtures, 'type-undefined-js', 'package.json') 506 | const until = when() 507 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 508 | error(err) 509 | is(esm, false) 510 | is(path, inputPath) 511 | is(expectedPkgPath, pkgPath) 512 | is(type, undefined) 513 | is(extType, 'j') 514 | until() 515 | }) 516 | await until.done() 517 | }) 518 | 519 | test('type-undefined-mjs callback', async ({ is, error }) => { 520 | const inputPath = join(fixtures, 'type-undefined-mjs', 'file.mjs') 521 | const expectedPkgPath = join(fixtures, 'type-undefined-mjs', 'package.json') 522 | const until = when() 523 | isFileEsm(inputPath, (err, { esm, path, type, extType, pkgPath }) => { 524 | error(err) 525 | is(esm, true) 526 | is(path, inputPath) 527 | is(expectedPkgPath, pkgPath) 528 | is(type, undefined) 529 | is(extType, 'm') 530 | until() 531 | }) 532 | await until.done() 533 | }) 534 | 535 | test('path must be string (callback)', async ({ match }) => { 536 | const until1 = when() 537 | isFileEsm(undefined, (err) => { 538 | match(err, Error(ERR_PATH_MUST_BE_STRING)) 539 | until1() 540 | }) 541 | const until2 = when() 542 | isFileEsm({}, (err) => { 543 | match(err, Error(ERR_PATH_MUST_BE_STRING)) 544 | until2() 545 | }) 546 | await Promise.all([until1.done(), until2.done()]) 547 | }) 548 | 549 | test('path must be absolute (callback)', async ({ match }) => { 550 | const until1 = when() 551 | isFileEsm('../foo.js', (err) => { 552 | match(err, Error(ERR_PATH_MUST_BE_ABSOLUTE)) 553 | until1() 554 | }) 555 | const until2 = when() 556 | isFileEsm('./bar/foo.mjs', (err) => { 557 | match(err, Error(ERR_PATH_MUST_BE_ABSOLUTE)) 558 | until2() 559 | }) 560 | await Promise.all([until1.done(), until2.done()]) 561 | }) 562 | 563 | test('path must have ext (callback)', async ({ match }) => { 564 | const until = when() 565 | isFileEsm('/bar/foo', (err) => { 566 | match(err, Error(ERR_PATH_MUST_HAVE_VALID_EXT)) 567 | until() 568 | }) 569 | await until.done() 570 | }) 571 | 572 | test('path must have valid ext (callback)', async ({ match }) => { 573 | const until = when() 574 | isFileEsm('/bar/foo.ext', (err) => { 575 | match(err, Error(ERR_PATH_MUST_HAVE_VALID_EXT)) 576 | until() 577 | }) 578 | await until.done() 579 | }) 580 | 581 | test('path must exist (callback)', async ({ match }) => { 582 | const until = when() 583 | isFileEsm(join(fixtures, 'bar', 'foo.js'), (err) => { 584 | match(err, Error(ERR_PATH_MUST_EXIST)) 585 | until() 586 | }) 587 | await until.done() 588 | }) 589 | 590 | test('type-bad-cjs callback', async ({ is }) => { 591 | const inputPath = join(fixtures, 'type-bad-cjs', 'file.cjs') 592 | const expectedPkgPath = join(fixtures, 'type-bad-cjs', 'package.json') 593 | const until = when() 594 | isFileEsm(inputPath, (err) => { 595 | is(err.message, ERR_BAD_TYPE) 596 | const { path, type, extType, pkgPath } = err.meta 597 | is(path, inputPath) 598 | is(expectedPkgPath, pkgPath) 599 | is(type, 'bad') 600 | is(extType, 'c') 601 | until() 602 | }) 603 | await until.done() 604 | }) 605 | 606 | test('type-bad-js callback', async ({ is }) => { 607 | const inputPath = join(fixtures, 'type-bad-js', 'file.js') 608 | const expectedPkgPath = join(fixtures, 'type-bad-js', 'package.json') 609 | const until = when() 610 | isFileEsm(inputPath, (err) => { 611 | is(err.message, ERR_BAD_TYPE) 612 | const { path, type, extType, pkgPath } = err.meta 613 | is(path, inputPath) 614 | is(expectedPkgPath, pkgPath) 615 | is(type, 'bad') 616 | is(extType, 'j') 617 | until() 618 | }) 619 | await until.done() 620 | }) 621 | 622 | test('type-bad-mjs callback', async ({ is }) => { 623 | const inputPath = join(fixtures, 'type-bad-mjs', 'file.mjs') 624 | const expectedPkgPath = join(fixtures, 'type-bad-mjs', 'package.json') 625 | const until = when() 626 | isFileEsm(inputPath, (err) => { 627 | is(err.message, ERR_BAD_TYPE) 628 | const { path, type, extType, pkgPath } = err.meta 629 | is(path, inputPath) 630 | is(expectedPkgPath, pkgPath) 631 | is(type, 'bad') 632 | is(extType, 'm') 633 | until() 634 | }) 635 | await until.done() 636 | }) 637 | 638 | test('package.json read error propagation (callback)', async ({ match, tearDown }) => { 639 | const inputPath = join(fixtures, 'type-bad-js', 'file.js') 640 | const expectedPkgPath = join(fixtures, 'type-bad-js', 'package.json') 641 | tearDown(() => chmodSync(expectedPkgPath, 0o644)) 642 | chmodSync(expectedPkgPath, 0o000) 643 | const until = when() 644 | isFileEsm(inputPath, (err) => { 645 | match(err, ERR_PERMISSION_DENIED) 646 | until() 647 | }) 648 | await until.done() 649 | }) 650 | --------------------------------------------------------------------------------