Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
fix: infer TS module format from package.json (#1580)
Browse files Browse the repository at this point in the history
* fix: infer TS module format from `package.json`

* chore: typo

* chore: update comments
  • Loading branch information
eduardoboucas authored Oct 2, 2023
1 parent 7aeed4d commit 028da38
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
34 changes: 31 additions & 3 deletions src/runtimes/node/bundlers/nft/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import { cachedReadFile, getPathWithExtension } from '../../../../utils/fs.js'
import { minimatch } from '../../../../utils/matching.js'
import { getBasePath } from '../../utils/base_path.js'
import { filterExcludedPaths, getPathsOfIncludedFiles } from '../../utils/included_files.js'
import { MODULE_FORMAT, MODULE_FILE_EXTENSION, tsExtensions } from '../../utils/module_format.js'
import { MODULE_FORMAT, MODULE_FILE_EXTENSION, tsExtensions, ModuleFormat } from '../../utils/module_format.js'
import { getNodeSupportMatrix } from '../../utils/node_version.js'
import { getModuleFormat as getTSModuleFormat } from '../../utils/tsconfig.js'
import { getClosestPackageJson } from '../../utils/package_json.js'
import { getModuleFormat as getModuleFormatFromTsConfig } from '../../utils/tsconfig.js'
import type { GetSrcFilesFunction, BundleFunction } from '../types.js'

import { processESM } from './es_modules.js'
Expand Down Expand Up @@ -85,6 +86,33 @@ const getIgnoreFunction = (config: FunctionConfig) => {
}
}

/**
* Returns the module format that should be used when transpiling a TypeScript
* file.
*/
const getTSModuleFormat = async (mainFile: string, repositoryRoot?: string): Promise<ModuleFormat> => {
const fromTsConfig = getModuleFormatFromTsConfig(mainFile, repositoryRoot)

// If we can infer the module type from a `tsconfig.json` file, use that.
if (fromTsConfig !== undefined) {
return fromTsConfig
}

// At this point, we need to infer the module type from the `type` field in
// the closest `package.json`.
try {
const packageJSON = await getClosestPackageJson(dirname(mainFile), repositoryRoot)

if (packageJSON?.contents.type === 'module') {
return MODULE_FORMAT.ESM
}
} catch {
// no-op
}

return MODULE_FORMAT.COMMONJS
}

const traceFilesAndTranspile = async function ({
basePath,
cache,
Expand All @@ -107,7 +135,7 @@ const traceFilesAndTranspile = async function ({
runtimeAPIVersion: number
}) {
const isTypeScript = tsExtensions.has(extname(mainFile))
const tsFormat = isTypeScript ? getTSModuleFormat(mainFile, repositoryRoot) : MODULE_FORMAT.COMMONJS
const tsFormat = isTypeScript ? await getTSModuleFormat(mainFile, repositoryRoot) : MODULE_FORMAT.COMMONJS
const tsAliases = new Map<string, string>()
const tsRewrites = new Map<string, string>()

Expand Down
17 changes: 12 additions & 5 deletions src/runtimes/node/utils/tsconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,29 @@ import { MODULE_FORMAT } from './module_format.js'

const esmModuleValues = new Set(['es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node16', 'nodenext'])

// Returns the module format that should be used for a TypeScript file at a
// given path, by reading the associated `tsconfig.json` file if it exists.
/**
* Looks for a `tsconfig.json` file on a given path and, if one exists, returns
* the module format inferred from the `module` property. If no file is found
* or if no `module` property is defined, the function returns `undefined`.
*/
export const getModuleFormat = (path: string, boundary?: string) => {
const file = getTsconfig(path)

if (!file) {
return MODULE_FORMAT.COMMONJS
return
}

// If there is a boundary defined and the file we found is outside of it,
// discard the file.
if (boundary !== undefined && relative(boundary, dirname(file.path)).startsWith('..')) {
return MODULE_FORMAT.COMMONJS
return
}

const moduleProp = file.config.compilerOptions?.module?.toLowerCase() ?? ''
const moduleProp = file.config.compilerOptions?.module

if (!moduleProp) {
return
}

return esmModuleValues.has(moduleProp) ? MODULE_FORMAT.ESM : MODULE_FORMAT.COMMONJS
}

1 comment on commit 028da38

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱ Benchmark results

  • largeDepsEsbuild: 2.6s
  • largeDepsNft: 8.7s
  • largeDepsZisi: 15.8s

Please sign in to comment.