index.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. const isFileEsmPromise = promisify(isFileEsm)
  7. const tick = queueMicrotask
  8. const ERR_PATH_MUST_BE_STRING = 'is-esm: path must be a string'
  9. const ERR_PATH_MUST_BE_ABSOLUTE = 'is-esm: absolute paths only'
  10. const ERR_PATH_MUST_EXIST = 'is-esm: path does not exist'
  11. const ERR_PATH_MUST_HAVE_VALID_EXT = 'is-esm: path must be to a file with an extension of .js, .mjs or .cjs'
  12. function isFileEsm (path, cb) {
  13. if (arguments.length <= 1) return isFileEsmPromise(path)
  14. if (typeof path !== 'string') return void tick(() => cb(Error(ERR_PATH_MUST_BE_STRING)))
  15. if (isAbsolute(path) === false) return void tick(() => cb(Error(ERR_PATH_MUST_BE_ABSOLUTE)))
  16. const extMatch = /\.(c|m)?js/.exec(extname(path))
  17. if (extMatch === null) return void tick(() => cb(Error(ERR_PATH_MUST_HAVE_VALID_EXT)))
  18. access(path, F_OK, (err) => {
  19. if (err) return void cb(Error(ERR_PATH_MUST_EXIST))
  20. const [, extType = 'j'] = extMatch
  21. const cwd = dirname(path)
  22. readPkgUp({ cwd }, (err, pkg) => {
  23. if (err) return void cb(err)
  24. const { type } = pkg.packageJson
  25. switch (type) {
  26. case undefined: {
  27. if (extType === 'j') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path })
  28. if (extType === 'm') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path })
  29. /* istanbul ignore else */
  30. if (extType === 'c') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path })
  31. // unreachable
  32. }
  33. case 'commonjs': {
  34. if (extType === 'j') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path })
  35. if (extType === 'm') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path })
  36. /* istanbul ignore else */
  37. if (extType === 'c') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path })
  38. // unreachable
  39. }
  40. case 'module': {
  41. if (extType === 'j') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path })
  42. if (extType === 'm') return void cb(null, { esm: true, type, extType, path, pkgPath: pkg.path })
  43. /* istanbul ignore else */
  44. if (extType === 'c') return void cb(null, { esm: false, type, extType, path, pkgPath: pkg.path })
  45. // unreachable
  46. }
  47. default: return void cb(Object.assign(Error(`package.json type "${type}" not recognized`), { meta: { type, extType, path, pkgPath: pkg.path } }))
  48. }
  49. })
  50. })
  51. }
  52. isFileEsm.sync = function isFileEsmSync (path) {
  53. if (typeof path !== 'string') throw Error(ERR_PATH_MUST_BE_STRING)
  54. if (isAbsolute(path) === false) throw Error(ERR_PATH_MUST_BE_ABSOLUTE)
  55. const extMatch = /\.(c|m)?js/.exec(extname(path))
  56. if (extMatch === null) throw Error(ERR_PATH_MUST_HAVE_VALID_EXT)
  57. try {
  58. accessSync(path, F_OK)
  59. } catch (err) {
  60. throw Error(ERR_PATH_MUST_EXIST)
  61. }
  62. const [, extType = 'j'] = extMatch
  63. const cwd = dirname(path)
  64. const pkg = readPkgUp.sync({ cwd })
  65. const { type } = pkg.packageJson
  66. switch (type) {
  67. case undefined: {
  68. if (extType === 'j') return { esm: false, type, extType, path, pkgPath: pkg.path }
  69. if (extType === 'm') return { esm: true, type, extType, path, pkgPath: pkg.path }
  70. /* istanbul ignore else */
  71. if (extType === 'c') return { esm: false, type, extType, path, pkgPath: pkg.path }
  72. // unreachable
  73. }
  74. case 'commonjs': {
  75. if (extType === 'j') return { esm: false, type, extType, path, pkgPath: pkg.path }
  76. if (extType === 'm') return { esm: true, type, extType, path, pkgPath: pkg.path }
  77. /* istanbul ignore else */
  78. if (extType === 'c') return { esm: false, type, extType, path, pkgPath: pkg.path }
  79. // unreachable
  80. }
  81. case 'module': {
  82. if (extType === 'j') return { esm: true, type, extType, path, pkgPath: pkg.path }
  83. if (extType === 'm') return { esm: true, type, extType, path, pkgPath: pkg.path }
  84. /* istanbul ignore else */
  85. if (extType === 'c') return { esm: false, type, extType, path, pkgPath: pkg.path }
  86. // unreachable
  87. }
  88. default: throw Object.assign(Error(`package.json type "${type}" not recognized`), { meta: { type, extType, path, pkgPath: pkg.path } })
  89. }
  90. }
  91. isFileEsm.constants = {
  92. ERR_PATH_MUST_BE_STRING,
  93. ERR_PATH_MUST_BE_ABSOLUTE,
  94. ERR_PATH_MUST_EXIST,
  95. ERR_PATH_MUST_HAVE_VALID_EXT
  96. }
  97. module.exports = isFileEsm