Repository: oclif/core
Pull request #853 (2023-11-06 16:03:24)

fix: dont drop ts-node options if there are no extends


Patch:
diff --git a/src/config/ts-node.ts b/src/config/ts-node.ts
index 15c5267..fea0af2 100644
--- a/src/config/ts-node.ts
+++ b/src/config/ts-node.ts
@@ -211,16 +211,11 @@ export async function tsPath(root: string, orig: string | undefined, plugin?: Pl
       memoizedWarn(
         `${plugin?.name} is a linked ESM module and cannot be auto-transpiled. Existing compiled source will be used instead.`,
       )
-
-    if (plugin?.options.url)
-      memoizedWarn(
-        `${plugin?.name} is an ESM module installed from github and cannot be auto-transpiled. Existing compiled source will be used instead.`,
-      )
     return orig
   }
 
-  // Do not skip ts-node registration if the plugin is linked or installed from github
-  if (settings.tsnodeEnabled === undefined && isProduction && plugin?.type !== 'link' && !plugin?.options.url) {
+  // Do not skip ts-node registration if the plugin is linked
+  if (settings.tsnodeEnabled === undefined && isProduction && plugin?.type !== 'link') {
     debug(`Skipping ts-node registration for ${root} because NODE_ENV is NOT "test" or "development"`)
     return orig
   }
diff --git a/src/util/fs.ts b/src/util/fs.ts
index 2afc495..0e09e7c 100644
--- a/src/util/fs.ts
+++ b/src/util/fs.ts
@@ -2,6 +2,8 @@ import {Stats, existsSync as fsExistsSync, readFileSync} from 'node:fs'
 import {readFile, stat} from 'node:fs/promises'
 import {join} from 'node:path'
 
+import {mergeNestedObjects} from './util'
+
 export function requireJson<T>(...pathParts: string[]): T {
   return JSON.parse(readFileSync(join(...pathParts), 'utf8'))
 }
@@ -73,8 +75,6 @@ export function existsSync(path: string): boolean {
 export async function readTSConfig(path: string) {
   const {parse} = await import('tsconfck')
   const result = await parse(path)
-  const tsNodeOpts = Object.fromEntries(
-    (result.extended ?? []).flatMap((e) => Object.entries(e.tsconfig['ts-node'] ?? {})).reverse(),
-  )
+  const tsNodeOpts = mergeNestedObjects(result.extended ?? [result], 'tsconfig.ts-node')
   return {...result.tsconfig, 'ts-node': tsNodeOpts}
 }
diff --git a/src/util/util.ts b/src/util/util.ts
index 03022a8..6b3048a 100644
--- a/src/util/util.ts
+++ b/src/util/util.ts
@@ -97,3 +97,11 @@ export function mapValues<T extends Record<string, any>, TResult>(
     return o
   }, {} as any)
 }
+
+function get(obj: Record<string, any>, path: string): unknown {
+  return path.split('.').reduce((o, p) => o?.[p], obj)
+}
+
+export function mergeNestedObjects(objs: Record<string, any>[], path: string): Record<string, any> {
+  return Object.fromEntries(objs.flatMap((o) => Object.entries(get(o, path) ?? {})).reverse())
+}


Test patch:
diff --git a/test/util/util.test.ts b/test/util/util.test.ts
index 1507bf7..d2c00b5 100644
--- a/test/util/util.test.ts
+++ b/test/util/util.test.ts
@@ -1,6 +1,6 @@
 import {expect} from 'chai'
 
-import {capitalize, castArray, isNotFalsy, isTruthy, last, maxBy, sumBy} from '../../src/util/util'
+import {capitalize, castArray, isNotFalsy, isTruthy, last, maxBy, mergeNestedObjects, sumBy} from '../../src/util/util'
 
 describe('capitalize', () => {
   it('capitalizes the string', () => {
@@ -96,3 +96,35 @@ describe('castArray', () => {
     expect(castArray()).to.deep.equal([])
   })
 })
+
+describe('mergeNestedObjects', () => {
+  it('should merge nested objects', () => {
+    const a = {
+      tsconfig: {
+        compilerOptions: {
+          outDir: 'dist',
+          rootDir: 'src',
+        },
+        'ts-node': {
+          transpileOnly: true,
+        },
+      },
+    }
+
+    const b = {
+      tsconfig: {
+        compilerOptions: {
+          outDir: 'dist',
+          rootDir: 'src',
+        },
+        'ts-node': {
+          transpileOnly: false,
+        },
+      },
+    }
+
+    expect(mergeNestedObjects([a, b], 'tsconfig.ts-node')).to.deep.equal({
+      transpileOnly: true,
+    })
+  })
+})