Skip to content

Commit

Permalink
Merge pull request #31 from jsenv/package-imports
Browse files Browse the repository at this point in the history
Package imports
  • Loading branch information
dmail authored Apr 20, 2021
2 parents 490bc4f + bb06e19 commit 36e8f9c
Show file tree
Hide file tree
Showing 49 changed files with 688 additions and 280 deletions.
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"program": "${file}",
// "runtimeVersion": "14.5.0",
"runtimeArgs": [
"--conditions=development",
"--unhandled-rejections=strict",
"--experimental-json-modules",
"--experimental-top-level-await"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jsenv/node-module-import-map",
"version": "13.2.1",
"version": "13.3.0",
"description": "Generate importmap for node_modules.",
"license": "MIT",
"repository": {
Expand Down
6 changes: 3 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ The following source of information are used to create complete and coherent map
- Your `package.json`
- All `dependencies` declared in `package.json` are searched into `node_modules`, recursively.
- The main file declared in your `package.json`
- In every `package.json`, "main", "exports" and "imports" field.
- All static and dynamic import found in files, recursively.
<details>
Expand Down Expand Up @@ -232,7 +232,7 @@ const importMap = await getImportMapFromProjectFiles({
When enabled the following happens:
1. `devDependencies` declared in your `package.json` are included in the generated importMap.
2. `"development"` is favored over `"production"` in [package.json exports conditions](https://nodejs.org/dist/latest-v15.x/docs/api/packages.html#packages_conditions_definitions).
2. `"development"` is favored over `"production"` in [package.json conditions](https://nodejs.org/dist/latest-v15.x/docs/api/packages.html#packages_conditions_definitions)
</details>
Expand All @@ -241,7 +241,7 @@ When enabled the following happens:
`runtime` parameter is a string indicating where the importmap will be used. This parameter is optional with a default of `"browser"`.
When `runtime` is `"browser"`, `"browser"` is favored over `"node"` in [package.json exports conditions](https://nodejs.org/dist/latest-v15.x/docs/api/packages.html#packages_conditions_definitions).
When `runtime` is `"browser"`, `"browser"` is favored over `"node"` in [package.json conditions](https://nodejs.org/dist/latest-v15.x/docs/api/packages.html#packages_conditions_definitions).
When it is `"node"`, `"node"` is favored.
Expand Down
14 changes: 7 additions & 7 deletions src/getImportMapFromProjectFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export const getImportMapFromProjectFiles = async ({
},
...rest
}) => {
const packagesExportsPreference = [
...(moduleFormatPreferences[moduleFormat] || [moduleFormat]),
...(runtimeExportsPreferences[runtime] || [runtime]),
...(dev ? "development" : "production"),
const packageConditions = [
...(packageConditionsFromModuleFormat[moduleFormat] || [moduleFormat]),
...(packageConditionsFromRuntime[runtime] || [runtime]),
...(dev ? ["development"] : ["production"]),
]

const logger = createLogger({ logLevel })
Expand All @@ -35,7 +35,7 @@ export const getImportMapFromProjectFiles = async ({
logger,
warn,
projectDirectoryUrl,
packagesExportsPreference,
packageConditions,
projectPackageDevDependenciesIncluded: dev,
...rest,
})
Expand All @@ -56,12 +56,12 @@ export const getImportMapFromProjectFiles = async ({
return importMapFromJsFiles
}

const runtimeExportsPreferences = {
const packageConditionsFromRuntime = {
browser: ["browser"],
node: ["node"],
}

const moduleFormatPreferences = {
const packageConditionsFromModuleFormat = {
esm: ["import"],
cjs: ["require"],
}
94 changes: 59 additions & 35 deletions src/internal/from-package/getImportMapFromPackageFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { optimizeImportMap } from "../optimizeImportMap.js"
import { resolvePackageMain } from "./resolvePackageMain.js"
import { visitPackageImportMap } from "./visitPackageImportMap.js"
import { visitPackageImports } from "./visitPackageImports.js"
import { visitPackageExports } from "./visitPackageExports.js"
import { createFindNodeModulePackage } from "./node-module-resolution.js"

Expand All @@ -21,8 +22,7 @@ export const getImportMapFromPackageFiles = async ({
warn,
projectDirectoryUrl,
projectPackageDevDependenciesIncluded = process.env.NODE_ENV !== "production",
packagesExportsPreference = ["import", "browser"],
packagesExportsIncluded = true,
packageConditions = ["import", "browser"],
packagesManualOverrides = {},
packageIncludedPredicate = () => true,
}) => {
Expand Down Expand Up @@ -239,6 +239,13 @@ export const getImportMapFromPackageFiles = async ({
})
}

// https://nodejs.org/docs/latest-v15.x/api/packages.html#packages_name
addImportMapForPackage({
imports: {
[`${packageName}/`]: `./`,
},
})

const importsFromPackageField = await visitPackageImportMap({
warn,
packageFileUrl,
Expand All @@ -247,44 +254,61 @@ export const getImportMapFromPackageFiles = async ({
})
addImportMapForPackage(importsFromPackageField)

if (packagesExportsIncluded && "exports" in packageJsonObject) {
if ("imports" in packageJsonObject) {
const mappingsFromPackageExports = {}
visitPackageExports({
const packageImports = visitPackageImports({
warn,
packageFileUrl,
packageJsonObject,
packageName,
projectDirectoryUrl,
packagesExportsPreference,
onExport: ({ key, value }) => {
const from = key
const to = value

if (from.indexOf("*") === -1) {
mappingsFromPackageExports[from] = to
return
}

if (
from.endsWith("/*") &&
to.endsWith("/*") &&
// ensure ends with '*' AND there is only one '*' occurence
to.indexOf("*") === to.length - 1
) {
const fromWithouTrailingStar = from.slice(0, -1)
const toWithoutTrailingStar = to.slice(0, -1)
mappingsFromPackageExports[fromWithouTrailingStar] = toWithoutTrailingStar
return
}

warn(
createExportsWildcardIgnoredWarning({
key,
value,
packageFileUrl,
}),
)
},
packageConditions,
})
Object.keys(packageImports).forEach((from) => {
const to = packageImports[from]
mappingsFromPackageExports[from] = to
})
addImportMapForPackage({
imports: mappingsFromPackageExports,
})
}

if ("exports" in packageJsonObject) {
const mappingsFromPackageExports = {}
const packageExports = visitPackageExports({
warn,
packageFileUrl,
packageJsonObject,
packageName,
projectDirectoryUrl,
packageConditions,
})
Object.keys(packageExports).forEach((from) => {
const to = packageExports[from]
if (from.indexOf("*") === -1) {
mappingsFromPackageExports[from] = to
return
}

if (
from.endsWith("/*") &&
to.endsWith("/*") &&
// ensure ends with '*' AND there is only one '*' occurence
to.indexOf("*") === to.length - 1
) {
const fromWithouTrailingStar = from.slice(0, -1)
const toWithoutTrailingStar = to.slice(0, -1)
mappingsFromPackageExports[fromWithouTrailingStar] = toWithoutTrailingStar
return
}

warn(
createExportsWildcardIgnoredWarning({
key: from,
value: to,
packageFileUrl,
}),
)
})
addMappingsForPackageAndImporter(mappingsFromPackageExports)
}
Expand All @@ -303,7 +327,7 @@ export const getImportMapFromPackageFiles = async ({
}) => {
const mainFileUrl = await resolvePackageMain({
warn,
packagesExportsPreference,
packageConditions,
packageFileUrl,
packageJsonObject,
})
Expand Down
8 changes: 4 additions & 4 deletions src/internal/from-package/resolvePackageMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ const magicExtensions = [".js", ".json", ".node"]

export const resolvePackageMain = ({
warn,
packagesExportsPreference,
packageConditions,
packageFileUrl,
packageJsonObject,
}) => {
if (packagesExportsPreference.includes("import") && "module" in packageJsonObject) {
if (packageConditions.includes("import") && "module" in packageJsonObject) {
return resolveMainFile({
warn,
packageFileUrl,
Expand All @@ -19,7 +19,7 @@ export const resolvePackageMain = ({
})
}

if (packagesExportsPreference.includes("import") && "jsnext:main" in packageJsonObject) {
if (packageConditions.includes("import") && "jsnext:main" in packageJsonObject) {
return resolveMainFile({
warn,
packageFileUrl,
Expand All @@ -29,7 +29,7 @@ export const resolvePackageMain = ({
}

if (
packagesExportsPreference.includes("browser") &&
packageConditions.includes("browser") &&
"browser" in packageJsonObject &&
// when it's an object it means some files
// should be replaced with an other, let's ignore this when we are searching
Expand Down
Loading

0 comments on commit 36e8f9c

Please sign in to comment.