@jcoreio/toolchain-esnext 5.6.0 → 5.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcoreio/toolchain-esnext",
3
- "version": "5.6.0",
3
+ "version": "5.8.0",
4
4
  "description": "ESNext JS build toolchain",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,7 +32,8 @@
32
32
  "globals": "^16.0.0",
33
33
  "resolve": "^1.22.2",
34
34
  "resolve-bin": "^1.0.0",
35
- "@jcoreio/toolchain": "5.6.0"
35
+ "semver": "^7.5.3",
36
+ "@jcoreio/toolchain": "5.8.0"
36
37
  },
37
38
  "toolchainManaged": {
38
39
  "dependencies": {
@@ -1,3 +1,5 @@
1
+ const { packageJson } = require('@jcoreio/toolchain/util/findUps.cjs')
2
+
1
3
  module.exports = [
2
4
  (api) => {
3
5
  const {
@@ -8,18 +10,22 @@ module.exports = [
8
10
  api.cache.using(() => JCOREIO_TOOLCHAIN_CJS)
9
11
  api.cache.using(() => JCOREIO_TOOLCHAIN_ESM)
10
12
  api.cache.using(() => JCOREIO_TOOLCHAIN_TEST)
13
+ api.cache.using(() => packageJson.type)
14
+
15
+ const cjsExtension = packageJson.type === 'module' ? '.cjs' : '.js'
16
+ const esmExtension = packageJson.type === 'module' ? '.js' : '.mjs'
17
+
11
18
  return [
12
19
  require.resolve('@babel/plugin-transform-runtime'),
13
- // for CJS tests, we leave off import extensions, since @babel/register resolves them.
14
- // for ESM tests, we resolve to .js for babel-register-esm.
15
- // for CJS build, we resolve to .js.
16
- // for ESM build, we resolve to .mjs.
17
- ((JCOREIO_TOOLCHAIN_CJS && !JCOREIO_TOOLCHAIN_TEST) ||
18
- JCOREIO_TOOLCHAIN_ESM) && [
20
+ (JCOREIO_TOOLCHAIN_CJS || JCOREIO_TOOLCHAIN_ESM) && [
19
21
  require.resolve('../util/babelPluginResolveImports.cjs'),
20
22
  {
21
23
  outputExtension:
22
- JCOREIO_TOOLCHAIN_ESM && !JCOREIO_TOOLCHAIN_TEST ? '.mjs' : '.js',
24
+ JCOREIO_TOOLCHAIN_TEST ? undefined
25
+ : JCOREIO_TOOLCHAIN_ESM ? esmExtension
26
+ : JCOREIO_TOOLCHAIN_CJS ? cjsExtension
27
+ : packageJson.type === 'module' ? esmExtension
28
+ : cjsExtension,
23
29
  },
24
30
  ],
25
31
  !JCOREIO_TOOLCHAIN_ESM &&
@@ -1,42 +1,67 @@
1
1
  const execa = require('@jcoreio/toolchain/util/execa.cjs')
2
2
  const fs = require('@jcoreio/toolchain/util/projectFs.cjs')
3
- const { glob } = require('@jcoreio/toolchain/util/glob.cjs')
3
+ const { glob, globIterate } = require('@jcoreio/toolchain/util/glob.cjs')
4
4
  const buildGlobOpts = require('@jcoreio/toolchain/util/buildGlobOpts.cjs')
5
5
  const path = require('path')
6
6
  const dedent = require('dedent-js')
7
7
  const {
8
+ packageJson,
8
9
  toolchainConfig,
9
10
  projectDir,
10
11
  } = require('@jcoreio/toolchain/util/findUps.cjs')
11
12
  const getPluginsArraySync = require('@jcoreio/toolchain/util/getPluginsArraySync.cjs')
12
13
  const fixSourceMaps = require('../util/fixSourceMaps.cjs')
13
14
 
15
+ async function hasSourceFilesForExtension(extension) {
16
+ const ignore = [
17
+ ...(toolchainConfig.buildIgnore || []),
18
+ ...(/\.[cm]?ts$/i.test(extension) ? [`**/*.d${extension}`] : []),
19
+ ]
20
+ for await (const file of globIterate(`src/**/*${extension}`, {
21
+ ignore: ignore.length ? ignore : undefined,
22
+ })) {
23
+ return true
24
+ }
25
+ return false
26
+ }
27
+
14
28
  module.exports = [
15
29
  [
16
30
  async function compile(args = []) {
17
- const extensions = getPluginsArraySync('babelExtensions')
18
-
19
- await execa(
20
- 'babel',
21
- [
22
- 'src',
23
- ...(extensions.length ? ['--extensions', extensions.join(',')] : []),
24
- ...(extensions.includes('.ts') ? ['--ignore', '**/*.d.ts'] : []),
25
- ...(toolchainConfig.buildIgnore || []).flatMap((pattern) => [
26
- '--ignore',
27
- pattern,
28
- ]),
29
- '--out-dir',
30
- 'dist',
31
- '--out-file-extension',
32
- '.js',
33
- ...(toolchainConfig.sourceMaps ?
34
- ['--source-maps', toolchainConfig.sourceMaps]
35
- : []),
36
- ],
37
- { env: { ...process.env, JCOREIO_TOOLCHAIN_CJS: '1' } }
31
+ const extensions = getPluginsArraySync('sourceExtensions').map(
32
+ (ext) => `.${ext}`
38
33
  )
39
34
 
35
+ for (const extension of extensions) {
36
+ if (extension.startsWith('.m')) continue
37
+ if (!(await hasSourceFilesForExtension(extension))) continue
38
+ await execa(
39
+ 'babel',
40
+ [
41
+ 'src',
42
+ '--extensions',
43
+ extension,
44
+ ...(/\.[cm]?ts$/i.test(extension) ?
45
+ ['--ignore', '**/*.d' + extension]
46
+ : []),
47
+ ...(toolchainConfig.buildIgnore || []).flatMap((pattern) => [
48
+ '--ignore',
49
+ pattern,
50
+ ]),
51
+ '--out-dir',
52
+ 'dist',
53
+ '--out-file-extension',
54
+ /\.c[tj]sx?$/i.test(extension) || packageJson.type === 'module' ?
55
+ '.cjs'
56
+ : '.js',
57
+ ...(toolchainConfig.sourceMaps ?
58
+ ['--source-maps', toolchainConfig.sourceMaps]
59
+ : []),
60
+ ],
61
+ { env: { ...process.env, JCOREIO_TOOLCHAIN_CJS: '1' } }
62
+ )
63
+ }
64
+
40
65
  const jsFiles = await glob(path.join('dist', '**', '*.js'))
41
66
  if (toolchainConfig.outputEsm !== false) {
42
67
  if (toolchainConfig.esWrapper) {
@@ -55,32 +80,40 @@ module.exports = [
55
80
  )
56
81
  )
57
82
  } else {
58
- await execa(
59
- 'babel',
60
- [
61
- 'src',
62
- ...(extensions.length ?
63
- ['--extensions', extensions.join(',')]
64
- : []),
65
- ...(toolchainConfig.buildIgnore || []).flatMap((pattern) => [
66
- '--ignore',
67
- pattern,
68
- ]),
69
- '--out-dir',
70
- 'dist',
71
- '--out-file-extension',
72
- '.mjs',
73
- ...(toolchainConfig.sourceMaps ?
74
- ['--source-maps', toolchainConfig.sourceMaps]
75
- : []),
76
- ],
77
- { env: { ...process.env, JCOREIO_TOOLCHAIN_ESM: '1' } }
78
- )
83
+ for (const extension of extensions) {
84
+ if (extension.startsWith('.c')) continue
85
+ if (!(await hasSourceFilesForExtension(extension))) continue
86
+ await execa(
87
+ 'babel',
88
+ [
89
+ 'src',
90
+ '--extensions',
91
+ extension,
92
+ ...(/\.[cm]?ts$/i.test(extension) ?
93
+ ['--ignore', '**/*.d' + extension]
94
+ : []),
95
+ ...(toolchainConfig.buildIgnore || []).flatMap((pattern) => [
96
+ '--ignore',
97
+ pattern,
98
+ ]),
99
+ '--out-dir',
100
+ 'dist',
101
+ '--out-file-extension',
102
+ /\.m[tj]sx?$/.test(extension) || packageJson.type !== 'module' ?
103
+ '.mjs'
104
+ : '.js',
105
+ ...(toolchainConfig.sourceMaps ?
106
+ ['--source-maps', toolchainConfig.sourceMaps]
107
+ : []),
108
+ ],
109
+ { env: { ...process.env, JCOREIO_TOOLCHAIN_ESM: '1' } }
110
+ )
111
+ }
79
112
  }
80
113
  }
81
114
 
82
115
  if (extensions.length) {
83
- for (const ext of ['.js', '.mjs']) {
116
+ for (const ext of ['.js', '.cjs', '.mjs']) {
84
117
  if (!extensions.includes(ext)) {
85
118
  const srcFiles = await glob(path.join('**', '*' + ext), {
86
119
  ...buildGlobOpts,
@@ -1,31 +1,51 @@
1
1
  import path from 'path'
2
- import { fileURLToPath } from 'url'
3
- import { resolve, load as wrappedLoad } from 'babel-register-esm'
2
+ import { fileURLToPath, pathToFileURL } from 'url'
3
+ import { resolve as baseResolve, load as wrappedLoad } from 'babel-register-esm'
4
+ import { projectDir } from '@jcoreio/toolchain/util/findUps.cjs'
5
+ import resolveAltType from './resolveAltType.cjs'
4
6
 
5
- export { resolve }
7
+ const projectDirPrefix = pathToFileURL(projectDir) + '/'
6
8
 
7
- export async function load(url, context, nextLoad) {
8
- // some versions of node support --experimental-default-type, but it was removed in Node 23.
9
- // Since we allow the project to omit `type` in `package.json` and transpile the same source
10
- // code to CJS and ESM, we need to set the module type based upon the mode the toolchain is
11
- // running in here for Node >=23.
12
- if (context.format == null && !url.includes('/node_modules/')) {
13
- const extension = path.extname(fileURLToPath(url))
14
- if (
15
- extension === '.js' ||
16
- extension === '.jsx' ||
17
- extension === '.ts' ||
18
- extension === '.tsx'
19
- ) {
20
- return await wrappedLoad(
21
- url,
22
- {
23
- ...context,
24
- format: process.env.JCOREIO_TOOLCHAIN_ESM ? 'module' : 'commonjs',
25
- },
26
- nextLoad
27
- )
9
+ export async function resolve(specifier, context, nextResolve) {
10
+ if (
11
+ specifier.startsWith('.') &&
12
+ context.parentURL.startsWith('file:') &&
13
+ !context.parentURL.includes('/node_modules/')
14
+ ) {
15
+ const basedir = path.dirname(fileURLToPath(context.parentURL))
16
+ const altTypeResolved = resolveAltType(specifier, basedir)
17
+ if (altTypeResolved) {
18
+ return {
19
+ url: new URL(altTypeResolved, context.parentURL).toString(),
20
+ shortCircuit: true,
21
+ format:
22
+ process.env.JCOREIO_TOOLCHAIN_CJS ? 'commonjs'
23
+ : process.env.JCOREIO_TOOLCHAIN_ESM ? 'module'
24
+ : context.format,
25
+ }
28
26
  }
29
27
  }
28
+ return await baseResolve(specifier, context, nextResolve)
29
+ }
30
+
31
+ export async function load(url, context, nextLoad) {
32
+ if (!url.startsWith('file:') || url.includes('/node_modules/')) {
33
+ return await nextLoad(url, context)
34
+ }
35
+ const extension = path.extname(url)
36
+ if (
37
+ process.env.JCOREIO_TOOLCHAIN_ESM &&
38
+ url.startsWith(projectDirPrefix) &&
39
+ (!extension || /\.m?[jt]sx?$/i.test(extension))
40
+ ) {
41
+ context = { ...context, format: 'module' }
42
+ }
43
+ if (
44
+ process.env.JCOREIO_TOOLCHAIN_CJS &&
45
+ url.startsWith(projectDirPrefix) &&
46
+ (!extension || /\.c?[jt]sx?$/i.test(extension))
47
+ ) {
48
+ context = { ...context, format: 'commonjs' }
49
+ }
30
50
  return await wrappedLoad(url, context, nextLoad)
31
51
  }
@@ -0,0 +1,41 @@
1
+ const path = require('path')
2
+ const fs = require('fs-extra')
3
+ const { packageJson } = require('@jcoreio/toolchain/util/findUps.cjs')
4
+ const hasTSSourcesSync = require('@jcoreio/toolchain/util/hasTSSourcesSync.cjs')
5
+
6
+ const isActive =
7
+ (packageJson.type === 'module' && process.env.JCOREIO_TOOLCHAIN_CJS) ||
8
+ (packageJson.type !== 'module' && process.env.JCOREIO_TOOLCHAIN_ESM)
9
+
10
+ module.exports = function resolveAltType(specifier, basedir) {
11
+ if (
12
+ !isActive ||
13
+ !specifier.startsWith('.') ||
14
+ !/\.[tj]sx?$/i.test(specifier)
15
+ ) {
16
+ return undefined
17
+ }
18
+ // if .js/.ts, project is CJS and output mode is ESM, see if there's a .mjs/.mts file.
19
+ // if .js/.ts, project is ESM and output mode is CJS, see if there's a .cjs/.cts file.
20
+ // same for tsx/jsx
21
+ const otherTypeSpecifier = specifier.replace(
22
+ /\.([^.]+)$/,
23
+ packageJson.type === 'module' ? '.c$1' : '.m$1'
24
+ )
25
+ if (fs.pathExistsSync(path.resolve(basedir, otherTypeSpecifier))) {
26
+ return otherTypeSpecifier
27
+ }
28
+ if (hasTSSourcesSync() && /\.tsx?$/i.test(specifier)) {
29
+ // if .ts, project is CJS and output mode is ESM, see if there's a .mjs file.
30
+ // if .ts, project is ESM and output mode is CJS, see if there's a .cjs file.
31
+ // same for tsx/jsx
32
+ const otherTypeSpecifier = specifier.replace(
33
+ /\.t([^.]+)$/,
34
+ packageJson.type === 'module' ? '.cj$1' : '.mj$1'
35
+ )
36
+ if (fs.pathExistsSync(path.resolve(basedir, otherTypeSpecifier))) {
37
+ return otherTypeSpecifier
38
+ }
39
+ }
40
+ return undefined
41
+ }
@@ -2,12 +2,18 @@ const resolve = require('resolve/sync')
2
2
  const path = require('path')
3
3
  const fs = require('fs-extra')
4
4
  const builtinModules = new Set(require('module').builtinModules)
5
+ const resolveAltType = require('./resolveAltType.cjs')
5
6
 
6
7
  module.exports = function resolveImportSource({
7
8
  file,
8
9
  source,
9
10
  outputExtension,
10
11
  }) {
12
+ const basedir = path.dirname(file)
13
+
14
+ const altTypeResolved = resolveAltType(source, basedir)
15
+ if (altTypeResolved) return altTypeResolved
16
+
11
17
  if (
12
18
  /(\.d\.ts|\.[cm]?jsx?)$/i.test(source) ||
13
19
  source.startsWith('node:') ||
@@ -16,7 +22,6 @@ module.exports = function resolveImportSource({
16
22
  return source
17
23
  }
18
24
 
19
- const basedir = path.dirname(file)
20
25
  if (source.startsWith('.')) {
21
26
  if (/\.[cm]?tsx?$/i.test(source) && /\.d\.[cm]?ts$/i.test(file)) {
22
27
  source = source.replace(/\.[^.]+$/, '')