diff --git a/.vscode/launch.json b/.vscode/launch.json index 1e677261..3de984ea 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,6 +9,7 @@ "program": "${file}", // "runtimeVersion": "14.5.0", "runtimeArgs": [ + "--conditions=development", "--unhandled-rejections=strict", "--experimental-json-modules", "--experimental-top-level-await" diff --git a/package.json b/package.json index 583351ff..27f70c7d 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/readme.md b/readme.md index b6daa347..15916a5c 100644 --- a/readme.md +++ b/readme.md @@ -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.
@@ -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)
@@ -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. diff --git a/src/getImportMapFromProjectFiles.js b/src/getImportMapFromProjectFiles.js index a5989120..4d03b30e 100644 --- a/src/getImportMapFromProjectFiles.js +++ b/src/getImportMapFromProjectFiles.js @@ -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 }) @@ -35,7 +35,7 @@ export const getImportMapFromProjectFiles = async ({ logger, warn, projectDirectoryUrl, - packagesExportsPreference, + packageConditions, projectPackageDevDependenciesIncluded: dev, ...rest, }) @@ -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"], } diff --git a/src/internal/from-package/getImportMapFromPackageFiles.js b/src/internal/from-package/getImportMapFromPackageFiles.js index f9031958..c1e9793b 100644 --- a/src/internal/from-package/getImportMapFromPackageFiles.js +++ b/src/internal/from-package/getImportMapFromPackageFiles.js @@ -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" @@ -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, }) => { @@ -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, @@ -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) } @@ -303,7 +327,7 @@ export const getImportMapFromPackageFiles = async ({ }) => { const mainFileUrl = await resolvePackageMain({ warn, - packagesExportsPreference, + packageConditions, packageFileUrl, packageJsonObject, }) diff --git a/src/internal/from-package/resolvePackageMain.js b/src/internal/from-package/resolvePackageMain.js index 23f9c539..873a77fb 100644 --- a/src/internal/from-package/resolvePackageMain.js +++ b/src/internal/from-package/resolvePackageMain.js @@ -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, @@ -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, @@ -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 diff --git a/src/internal/from-package/visitPackageExports.js b/src/internal/from-package/visitPackageExports.js index 7ef8bda1..42f6a868 100644 --- a/src/internal/from-package/visitPackageExports.js +++ b/src/internal/from-package/visitPackageExports.js @@ -1,159 +1,157 @@ -// https://nodejs.org/dist/latest-v13.x/docs/api/esm.html#esm_package_exports +/* + +https://nodejs.org/docs/latest-v15.x/api/packages.html#packages_node_js_package_json_field_definitions + +*/ import { urlToFileSystemPath, urlToRelativeUrl, resolveUrl } from "@jsenv/util" import { specifierIsRelative } from "./specifierIsRelative.js" export const visitPackageExports = ({ - warn, packageFileUrl, packageJsonObject, packageExports = packageJsonObject.exports, packageName = packageJsonObject.name, projectDirectoryUrl, - packagesExportsPreference, - onExport, + packageConditions, + warn, }) => { + const exportsSubpaths = {} const packageDirectoryUrl = resolveUrl("./", packageFileUrl) const packageDirectoryRelativeUrl = urlToRelativeUrl(packageDirectoryUrl, projectDirectoryUrl) - - visitExportsSubpath(packageExports, packagesExportsPreference, { - onUnexpectedPackageExports: ({ packageExportsValue, packageExportsValuePath }) => { + const onExportsSubpath = ({ key, value, trace }) => { + if (!specifierIsRelative(value)) { warn( - createExportsValueWarning({ - packageExportsValue, - packageExportsValuePath, + createSubpathValueMustBeRelativeWarning({ + value, + valueTrace: trace, packageFileUrl, }), ) - }, - onMixedPackageExports: ({ packageExportsValue, packageExportsValuePath }) => { - // see https://nodejs.org/dist/latest-v13.x/docs/api/esm.html#esm_exports_sugar - warn( - createExportsMixedWarning({ - packageExportsValue, - packageExportsValuePath, - packageFileUrl, - }), - ) - }, - onSubpathPackageExport: ({ key, value, valuePath }) => { - if (!specifierIsRelative(key)) { - warn( - createExportsMappingKeyMustBeRelativeWarning({ - key, - keyPath: valuePath.slice(0, -1), - packageFileUrl, - }), - ) - return - } - if (typeof value !== "string") { - warn( - createExportsMappingValueMustBeAStringWarning({ - value, - valuePath, - packageFileUrl, - }), - ) - return - } - if (!specifierIsRelative(value)) { - warn( - createExportsMappingValueMustBeRelativeWarning({ - value, - valuePath, - packageFileUrl, - }), - ) - return - } + return + } - onExport({ - key: specifierToSource(key, packageName), - value: addressToDestination(value, packageDirectoryRelativeUrl), - }) - }, - }) -} + const keyNormalized = specifierToSource(key, packageName) + const valueNormalized = addressToDestination(value, packageDirectoryRelativeUrl) + exportsSubpaths[keyNormalized] = valueNormalized + } -const visitExportsSubpath = ( - packageExports, - packageExportsConditions, - { onUnexpectedPackageExports, onMixedPackageExports, onSubpathPackageExport }, -) => { - const visitValue = (packageExportsValue, { valuePath }) => { + const conditions = [...packageConditions, "default"] + + const visitSubpathValue = (subpathValue, subpathValueTrace) => { // false is allowed as alternative to exports: {} - if (packageExportsValue === false) { - return + if (subpathValue === false) { + return handleFalse() } - if (typeof packageExportsValue === "string") { - const firstNonConditionKey = valuePath - .slice() - .reverse() - .find((key) => key.startsWith(".")) - const key = firstNonConditionKey || "." - onSubpathPackageExport({ - value: packageExportsValue, - valuePath, - key, - }) - return + if (typeof subpathValue === "string") { + return handleString(subpathValue, subpathValueTrace) } - if (typeof packageExportsValue !== "object" && packageExportsValue !== null) { - onUnexpectedPackageExports({ - packageExportsValue, - packageExportsValuePath: valuePath, - }) - return + if (typeof subpathValue === "object" && subpathValue !== null) { + return handleObject(subpathValue, subpathValueTrace) } - const keys = Object.keys(packageExportsValue) - const everyKeyDoesNotStartsWithDot = keys.every((key) => !key.startsWith(".")) - if (everyKeyDoesNotStartsWithDot) { - const bestConditionKey = findBestConditionKey(keys, packageExportsConditions) - if (!bestConditionKey) { - return - } - const bestExports = packageExportsValue[bestConditionKey] - visitValue(bestExports, { - valuePath: [...valuePath, bestConditionKey], + return handleRemaining(subpathValue, subpathValueTrace) + } + + const handleFalse = () => { + // nothing to do + return true + } + + const handleString = (subpathValue, subpathValueTrace) => { + const firstRelativeKey = subpathValueTrace + .slice() + .reverse() + .find((key) => key.startsWith(".")) + const key = firstRelativeKey || "." + onExportsSubpath({ + key, + value: subpathValue, + trace: subpathValueTrace, + }) + return true + } + + const handleObject = (subpathValue, subpathValueTrace) => { + // From Node.js documentation: + // "If a nested conditional does not have any mapping it will continue + // checking the remaining conditions of the parent condition" + // https://nodejs.org/docs/latest-v14.x/api/packages.html#packages_nested_conditions + // + // So it seems what we do here is not sufficient + // -> if the condition finally does not lead to something + // it should be ignored and an other branch be taken until + // something resolves + const followConditionBranch = (subpathValue, conditionTrace) => { + const relativeKeys = [] + const conditionalKeys = [] + Object.keys(subpathValue).forEach((availableKey) => { + if (availableKey.startsWith(".")) { + relativeKeys.push(availableKey) + } else { + conditionalKeys.push(availableKey) + } }) - return - } - const everyKeyStartsWithDot = keys.every((key) => key.startsWith(".")) - if (everyKeyStartsWithDot) { - keys.forEach((key) => { - visitValue(packageExportsValue[key], { - valuePath: [...valuePath, key], + if (relativeKeys.length > 0 && conditionalKeys.length > 0) { + warn( + createSubpathKeysAreMixedWarning({ + subpathValue, + subpathValueTrace: [...subpathValueTrace, ...conditionTrace], + packageFileUrl, + relativeKeys, + conditionalKeys, + }), + ) + return false + } + + // there is no condition, visit all relative keys + if (conditionalKeys.length === 0) { + let leadsToSomething = false + relativeKeys.forEach((key) => { + leadsToSomething = visitSubpathValue(subpathValue[key], [ + ...subpathValueTrace, + ...conditionTrace, + key, + ]) }) + return leadsToSomething + } + + // there is a condition, keep the first one leading to something + return conditions.some((keyCandidate) => { + if (!conditionalKeys.includes(keyCandidate)) { + return false + } + const valueCandidate = subpathValue[keyCandidate] + return visitSubpathValue(valueCandidate, [ + ...subpathValueTrace, + ...conditionTrace, + keyCandidate, + ]) }) - return } - onMixedPackageExports({ - packageExportsValue, - packageExportsValuePath: valuePath, - }) + return followConditionBranch(subpathValue, []) } - visitValue(packageExports, { - valuePath: ["exports"], - }) -} -const findBestConditionKey = (availableKeys, exportsConditions) => { - const conditionKey = exportsConditions.find((key) => availableKeys.includes(key)) - if (conditionKey) { - return conditionKey + const handleRemaining = (subpathValue, subpathValueTrace) => { + warn( + createSubpathIsUnexpectedWarning({ + subpathValue, + subpathValueTrace, + packageFileUrl, + }), + ) + return false } - if (availableKeys.includes("default")) { - return "default" - } + visitSubpathValue(packageExports, ["exports"]) - return undefined + return exportsSubpaths } const specifierToSource = (specifier, packageName) => { @@ -184,74 +182,40 @@ const addressToDestination = (address, packageDirectoryRelativeUrl) => { return `./${packageDirectoryRelativeUrl}${address}` } -const createExportsValueWarning = ({ - packageExportsValue, - packageExportsValuePath, - packageFileUrl, -}) => { +const createSubpathIsUnexpectedWarning = ({ subpathValue, subpathValueTrace, packageFileUrl }) => { return { - code: "EXPORTS_VALUE", - message: `unexpected value in package.json exports field: value must be an object or a string. + code: "EXPORTS_SUBPATH_UNEXPECTED", + message: `unexpected subpath in package.json exports: value must be an object or a string. --- value --- -${packageExportsValue} ---- value path --- -${packageExportsValuePath.join(".")} +${subpathValue} +--- value at --- +${subpathValueTrace.join(".")} --- package.json path --- ${urlToFileSystemPath(packageFileUrl)}`, } } -const createExportsMixedWarning = ({ - packageExportsValue, - packageExportsValuePath, - packageFileUrl, -}) => { +const createSubpathKeysAreMixedWarning = ({ subpathValue, subpathValueTrace, packageFileUrl }) => { return { - code: "EXPORTS_MIXED", - message: `unexpected package.json exports field: cannot mix conditional and subpath exports. + code: "EXPORTS_SUBPATH_MIXED_KEYS", + message: `unexpected subpath keys in package.json exports: cannot mix relative and conditional keys. --- value --- -${JSON.stringify(packageExportsValue, null, " ")} ---- value path --- -${packageExportsValuePath.join(".")} ---- package.json path --- -${urlToFileSystemPath(packageFileUrl)}`, - } -} - -const createExportsMappingKeyMustBeRelativeWarning = ({ key, keyPath, packageFileUrl }) => { - return { - code: "EXPORTS_MAPPING_KEY_MUST_BE_RELATIVE", - message: `unexpected key in package.json exports field: key must be relative. ---- key --- -${key} ---- key path --- -${keyPath.join(".")} ---- package.json path --- -${urlToFileSystemPath(packageFileUrl)}`, - } -} - -const createExportsMappingValueMustBeAStringWarning = ({ value, valuePath, packageFileUrl }) => { - return { - code: "EXPORTS_MAPPING_VALUE_MUST_BE_A_STRING", - message: `unexpected value in package.json exports field: value must be a string. ---- value --- -${value} ---- value path --- -${valuePath.join(".")} +${JSON.stringify(subpathValue, null, " ")} +--- value at --- +${subpathValueTrace.join(".")} --- package.json path --- ${urlToFileSystemPath(packageFileUrl)}`, } } -const createExportsMappingValueMustBeRelativeWarning = ({ value, valuePath, packageFileUrl }) => { +const createSubpathValueMustBeRelativeWarning = ({ value, valueTrace, packageFileUrl }) => { return { - code: "EXPORTS_MAPPING_VALUE_MUST_BE_RELATIVE", - message: `unexpected value in package.json exports field: value must be relative. + code: "EXPORTS_SUBPATH_VALUE_MUST_BE_RELATIVE", + message: `unexpected subpath value in package.json exports: value must be a relative to the package. --- value --- ${value} ---- value path --- -${valuePath.join(".")} +--- value at --- +${valueTrace.join(".")} --- package.json path --- ${urlToFileSystemPath(packageFileUrl)}`, } diff --git a/src/internal/from-package/visitPackageImports.js b/src/internal/from-package/visitPackageImports.js new file mode 100644 index 00000000..713ec6b2 --- /dev/null +++ b/src/internal/from-package/visitPackageImports.js @@ -0,0 +1,179 @@ +/* + +https://nodejs.org/docs/latest-v15.x/api/packages.html#packages_node_js_package_json_field_definitions + +*/ + +import { urlToFileSystemPath } from "@jsenv/util" +import { specifierIsRelative } from "./specifierIsRelative.js" + +export const visitPackageImports = ({ + packageFileUrl, + packageJsonObject, + packageImports = packageJsonObject.imports, + packageConditions, + warn, +}) => { + const importsSubpaths = {} + const onImportsSubpath = ({ key, value, trace }) => { + if (!specifierIsRelative(value)) { + warn( + createSubpathValueMustBeRelativeWarning({ + value, + valueTrace: trace, + packageFileUrl, + }), + ) + return + } + + const keyNormalized = key + const valueNormalized = value + importsSubpaths[keyNormalized] = valueNormalized + } + + const conditions = [...packageConditions, "default"] + + const visitSubpathValue = (subpathValue, subpathValueTrace) => { + if (typeof subpathValue === "string") { + return handleString(subpathValue, subpathValueTrace) + } + + if (typeof subpathValue === "object" && subpathValue !== null) { + return handleObject(subpathValue, subpathValueTrace) + } + + return handleRemaining(subpathValue, subpathValueTrace) + } + + const handleString = (subpathValue, subpathValueTrace) => { + const firstBareKey = subpathValueTrace + .slice() + .reverse() + .find((key) => key.startsWith("#")) + onImportsSubpath({ + key: firstBareKey, + value: subpathValue, + trace: subpathValueTrace, + }) + return true + } + + const handleObject = (subpathValue, subpathValueTrace) => { + // From Node.js documentation: + // "If a nested conditional does not have any mapping it will continue + // checking the remaining conditions of the parent condition" + // https://nodejs.org/docs/latest-v14.x/api/packages.html#packages_nested_conditions + // + // So it seems what we do here is not sufficient + // -> if the condition finally does not lead to something + // it should be ignored and an other branch be taken until + // something resolves + const followConditionBranch = (subpathValue, conditionTrace) => { + const bareKeys = [] + const conditionalKeys = [] + Object.keys(subpathValue).forEach((availableKey) => { + if (availableKey.startsWith("#")) { + bareKeys.push(availableKey) + } else { + conditionalKeys.push(availableKey) + } + }) + + if (bareKeys.length > 0 && conditionalKeys.length > 0) { + warn( + createSubpathKeysAreMixedWarning({ + subpathValue, + subpathValueTrace: [...subpathValueTrace, ...conditionTrace], + packageFileUrl, + bareKeys, + conditionalKeys, + }), + ) + return false + } + + // there is no condition, visit all bare keys (starting with #) + if (conditionalKeys.length === 0) { + let leadsToSomething = false + bareKeys.forEach((key) => { + leadsToSomething = visitSubpathValue(subpathValue[key], [ + ...subpathValueTrace, + ...conditionTrace, + key, + ]) + }) + return leadsToSomething + } + + // there is a condition, keep the first one leading to something + return conditions.some((keyCandidate) => { + if (!conditionalKeys.includes(keyCandidate)) { + return false + } + const valueCandidate = subpathValue[keyCandidate] + return visitSubpathValue(valueCandidate, [ + ...subpathValueTrace, + ...conditionTrace, + keyCandidate, + ]) + }) + } + + return followConditionBranch(subpathValue, []) + } + + const handleRemaining = (subpathValue, subpathValueTrace) => { + warn( + createSubpathIsUnexpectedWarning({ + subpathValue, + subpathValueTrace, + packageFileUrl, + }), + ) + return false + } + + visitSubpathValue(packageImports, ["imports"]) + + return importsSubpaths +} + +const createSubpathIsUnexpectedWarning = ({ subpathValue, subpathValueTrace, packageFileUrl }) => { + return { + code: "IMPORTS_SUBPATH_UNEXPECTED", + message: `unexpected subpath in package.json imports: value must be an object or a string. +--- value --- +${subpathValue} +--- value at --- +${subpathValueTrace.join(".")} +--- package.json path --- +${urlToFileSystemPath(packageFileUrl)}`, + } +} + +const createSubpathKeysAreMixedWarning = ({ subpathValue, subpathValueTrace, packageFileUrl }) => { + return { + code: "IMPORTS_SUBPATH_MIXED_KEYS", + message: `unexpected subpath keys in package.json imports: cannot mix bare and conditional keys. +--- value --- +${JSON.stringify(subpathValue, null, " ")} +--- value at --- +${subpathValueTrace.join(".")} +--- package.json path --- +${urlToFileSystemPath(packageFileUrl)}`, + } +} + +const createSubpathValueMustBeRelativeWarning = ({ value, valueTrace, packageFileUrl }) => { + return { + code: "IMPORTS_SUBPATH_VALUE_UNEXPECTED", + message: `unexpected subpath value in package.json imports: value must be relative to package +--- value --- +${value} +--- value at --- +${valueTrace.join(".")} +--- package.json path --- +${urlToFileSystemPath(packageFileUrl)}`, + } +} diff --git a/test/getImportMapFromProjectFiles/core/circular/circular.test.js b/test/getImportMapFromProjectFiles/core/circular/circular.test.js index 45056061..a976f09f 100644 --- a/test/getImportMapFromProjectFiles/core/circular/circular.test.js +++ b/test/getImportMapFromProjectFiles/core/circular/circular.test.js @@ -10,10 +10,18 @@ const actual = await getImportMapFromProjectFiles({ }) const expected = { imports: { - whatever: "./index", - bar: "./node_modules/bar/bar.js", - foo: "./node_modules/foo/foo.js", + "whatever/": "./", + "whatever": "./index", + "bar": "./node_modules/bar/bar.js", + "foo": "./node_modules/foo/foo.js", + }, + scopes: { + "./node_modules/bar/": { + "bar/": "./node_modules/bar/", + }, + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/core/inside/inside.test.js b/test/getImportMapFromProjectFiles/core/inside/inside.test.js index a6c60cb7..cb867111 100644 --- a/test/getImportMapFromProjectFiles/core/inside/inside.test.js +++ b/test/getImportMapFromProjectFiles/core/inside/inside.test.js @@ -12,13 +12,21 @@ const importMap = await getImportMapFromProjectFiles({ const actual = importMap const expected = { imports: { - root: "./index", - bar: "./node_modules/bar/bar.js", - foo: "./node_modules/foo/foo.js", + "root/": "./", + "root": "./index", + "bar": "./node_modules/bar/bar.js", + "foo": "./node_modules/foo/foo.js", }, scopes: { + "./node_modules/foo/node_modules/bar/": { + "bar/": "./node_modules/foo/node_modules/bar/", + }, + "./node_modules/bar/": { + "bar/": "./node_modules/bar/", + }, "./node_modules/foo/": { - bar: "./node_modules/foo/node_modules/bar/bar.js", + "foo/": "./node_modules/foo/", + "bar": "./node_modules/foo/node_modules/bar/bar.js", }, }, } @@ -48,18 +56,12 @@ const importMapNormalized = normalizeImportMap(importMap, "http://example.com") } // import 'bar/file.js' inside 'bar' -try { - resolveImport({ +{ + const actual = resolveImport({ specifier: `bar/file.js`, importer: `http://example.com/node_modules/foo/node_modules/bar/bar.js`, importMap: importMapNormalized, }) - throw new Error("should throw") -} catch (actual) { - const expected = new Error(`Unmapped bare specifier. ---- specifier --- -bar/file.js ---- importer --- -http://example.com/node_modules/foo/node_modules/bar/bar.js`) + const expected = `http://example.com/node_modules/foo/node_modules/bar/file.js` assert({ actual, expected }) } diff --git a/test/getImportMapFromProjectFiles/core/missing-dependency-package/missing-dependency-package.test.js b/test/getImportMapFromProjectFiles/core/missing-dependency-package/missing-dependency-package.test.js index 013453ae..4877cd6e 100644 --- a/test/getImportMapFromProjectFiles/core/missing-dependency-package/missing-dependency-package.test.js +++ b/test/getImportMapFromProjectFiles/core/missing-dependency-package/missing-dependency-package.test.js @@ -11,7 +11,8 @@ const actual = await getImportMapFromProjectFiles({ }) const expected = { imports: { - root: "./index", + "root/": "./", + "root": "./index", }, scopes: {}, } diff --git a/test/getImportMapFromProjectFiles/core/scoped-inside-scoped/scoped-inside-scoped.test.js b/test/getImportMapFromProjectFiles/core/scoped-inside-scoped/scoped-inside-scoped.test.js index 88410219..c2bbad00 100644 --- a/test/getImportMapFromProjectFiles/core/scoped-inside-scoped/scoped-inside-scoped.test.js +++ b/test/getImportMapFromProjectFiles/core/scoped-inside-scoped/scoped-inside-scoped.test.js @@ -12,14 +12,21 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "@jsenv/bundling": "./node_modules/@jsenv/bundling/whatever.js", + "root/": "./", "root": "./index", }, scopes: { + "./node_modules/@jsenv/bundling/node_modules/@jsenv/core/node_modules/@dmail/project-structure/": { + "@dmail/project-structure/": + "./node_modules/@jsenv/bundling/node_modules/@jsenv/core/node_modules/@dmail/project-structure/", + }, "./node_modules/@jsenv/bundling/node_modules/@jsenv/core/": { "@dmail/project-structure": "./node_modules/@jsenv/bundling/node_modules/@jsenv/core/node_modules/@dmail/project-structure/whatever.js", + "@jsenv/core/": "./node_modules/@jsenv/bundling/node_modules/@jsenv/core/", }, "./node_modules/@jsenv/bundling/": { + "@jsenv/bundling/": "./node_modules/@jsenv/bundling/", "@jsenv/core": "./node_modules/@jsenv/bundling/node_modules/@jsenv/core/whatever.js", }, }, diff --git a/test/getImportMapFromProjectFiles/manual-override/manual-override.test.js b/test/getImportMapFromProjectFiles/manual-override/manual-override.test.js index 8d56be4c..8b754b8a 100644 --- a/test/getImportMapFromProjectFiles/manual-override/manual-override.test.js +++ b/test/getImportMapFromProjectFiles/manual-override/manual-override.test.js @@ -18,6 +18,7 @@ const actual = await getImportMapFromProjectFiles({ }) const expected = { imports: { + "root/": "./", "bar/": "./node_modules/bar/", "root": "./index", "bar": "./node_modules/bar/bar.js", diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-and-main/exports-and-main.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-and-main/exports-and-main.test.js index fbb32029..caeca14d 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-and-main/exports-and-main.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-and-main/exports-and-main.test.js @@ -10,9 +10,14 @@ const actual = await getImportMapFromProjectFiles({ }) const expected = { imports: { - whatever: "./index", - foo: "./node_modules/foo/file.js", + "whatever/": "./", + "whatever": "./index", + "foo": "./node_modules/foo/file.js", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/exports-branch.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/exports-branch.test.js new file mode 100644 index 00000000..48529bba --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/exports-branch.test.js @@ -0,0 +1,54 @@ +import { assert } from "@jsenv/assert" +import { resolveUrl } from "@jsenv/util" +import { getImportMapFromProjectFiles } from "@jsenv/node-module-import-map" + +const testDirectoryUrl = resolveUrl("./root/", import.meta.url) + +const getImportMap = async ({ runtime, moduleFormat } = {}) => { + return getImportMapFromProjectFiles({ + projectDirectoryUrl: testDirectoryUrl, + jsFiles: false, + moduleFormat, + runtime, + dev: true, + }) +} + +{ + const actual = await getImportMap({ + runtime: "node", + }) + const expected = { + imports: { + "whatever/": "./", + "whatever": "./index", + "foo": "./node_modules/foo/main.js", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, + }, + } + assert({ actual, expected }) +} + +{ + const actual = await getImportMap({ + runtime: "node", + moduleFormat: "cjs", + }) + const expected = { + imports: { + "whatever/": "./", + "whatever": "./index", + "foo": "./node_modules/foo/main.cjs", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, + }, + } + assert({ actual, expected }) +} diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/main.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/main.js new file mode 100644 index 00000000..05eed085 --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/main.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-unresolved +import "foo" diff --git a/test/getImportMapFromProjectFiles/self-import/self-import-1/index.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/main.cjs similarity index 100% rename from test/getImportMapFromProjectFiles/self-import/self-import-1/index.js rename to test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/main.cjs diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/main.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/main.js new file mode 100644 index 00000000..e69de29b diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/package.json b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/package.json new file mode 100644 index 00000000..87c7e890 --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/node_modules/foo/package.json @@ -0,0 +1,14 @@ +{ + "name": "foo", + "type": "module", + "exports": { + ".": { + "development": { + "require": "./main.cjs" + }, + "import": { + "development": "./main.js" + } + } + } +} diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/package.json b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/package.json new file mode 100644 index 00000000..62dd616a --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-branch/root/package.json @@ -0,0 +1,7 @@ +{ + "name": "whatever", + "type": "module", + "dependencies": { + "foo": "*" + } +} diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/exports-complex.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/exports-complex.test.js index 9659769e..3b40f292 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/exports-complex.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/exports-complex.test.js @@ -20,10 +20,15 @@ const getImportMap = async ({ runtime, moduleFormat } = {}) => { const expected = { imports: { "foo/dist/": "./node_modules/foo/dist/", + "whatever/": "./", "whatever": "./index", - "foo": "./node_modules/foo/dist/es/rollup.js", + "foo": "./node_modules/foo/dist/rollup.mjs", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) } @@ -36,10 +41,15 @@ const getImportMap = async ({ runtime, moduleFormat } = {}) => { const expected = { imports: { "foo/dist/": "./node_modules/foo/dist/", + "whatever/": "./", "whatever": "./index", "foo": "./node_modules/foo/dist/rollup.js", }, - scopes: {}, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, + }, } assert({ actual, expected }) } @@ -52,10 +62,15 @@ const getImportMap = async ({ runtime, moduleFormat } = {}) => { const expected = { imports: { "foo/dist/": "./node_modules/foo/dist/", + "whatever/": "./", "whatever": "./index", - "foo": "./node_modules/foo/file.cjs", + "foo": "./node_modules/foo/dist/rollup.browser.mjs", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) } @@ -65,10 +80,15 @@ const getImportMap = async ({ runtime, moduleFormat } = {}) => { const expected = { imports: { "foo/dist/": "./node_modules/foo/dist/", + "whatever/": "./", "whatever": "./index", - "foo": "./node_modules/foo/dist/es/rollup.browser.js", + "foo": "./node_modules/foo/dist/rollup.browser.mjs", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) } diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/root/node_modules/foo/package.json b/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/root/node_modules/foo/package.json index 9c3a8c64..39feb289 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/root/node_modules/foo/package.json +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-complex/root/node_modules/foo/package.json @@ -4,9 +4,9 @@ ".": { "node": { "require": "./dist/rollup.js", - "import": "./dist/es/rollup.js" + "import": "./dist/rollup.mjs" }, - "default": "./dist/es/rollup.browser.js" + "default": "./dist/rollup.browser.mjs" }, "./dist/": "./dist/" } diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-condition-nested/exports-condition-nested.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-condition-nested/exports-condition-nested.test.js index 9e3ca3d6..5e24d5b5 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-condition-nested/exports-condition-nested.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-condition-nested/exports-condition-nested.test.js @@ -13,10 +13,15 @@ const testDirectoryUrl = resolveUrl("./root/", import.meta.url) const actual = importMap const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/feature-node.mjs", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/feature-node.mjs", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) } @@ -30,10 +35,15 @@ const testDirectoryUrl = resolveUrl("./root/", import.meta.url) const actual = importMap const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/feature.mjs", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/feature.mjs", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) } diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-directory-scoped/exports-directory-scoped.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-directory-scoped/exports-directory-scoped.test.js index a320b779..87d7a150 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-directory-scoped/exports-directory-scoped.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-directory-scoped/exports-directory-scoped.test.js @@ -11,6 +11,7 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "foo/ding": "./node_modules/foo/dong", + "root/": "./", "root": "./index", "foo": "./node_modules/foo/index.js", }, @@ -21,6 +22,7 @@ const expected = { "./node_modules/foo/": { "exporting-folder/": "./node_modules/foo/node_modules/exporting-folder/", "exporting-folder": "./node_modules/foo/node_modules/exporting-folder/index.js", + "foo/": "./node_modules/foo/", }, }, } diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-directory/exports-directory.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-directory/exports-directory.test.js index 39cd3a18..d4a6b0f5 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-directory/exports-directory.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-directory/exports-directory.test.js @@ -12,6 +12,7 @@ const expected = { imports: { "@jsenv/whatever/": "./node_modules/@jsenv/whatever/", "@jsenv/whatever": "./node_modules/@jsenv/whatever/index.js", + "root/": "./", "root": "./index", }, scopes: {}, diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-file-conditional/exports-file-conditional.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-file-conditional/exports-file-conditional.test.js index b064d002..b71e4552 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-file-conditional/exports-file-conditional.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-file-conditional/exports-file-conditional.test.js @@ -14,10 +14,15 @@ const testDirectoryUrl = resolveUrl("./root/", import.meta.url) const expected = { imports: { "foo/file.js": "./node_modules/foo/file.browser.js", + "root/": "./", "root": "./index", "foo": "./node_modules/foo/index", }, - scopes: {}, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, + }, } assert({ actual, expected }) } @@ -32,10 +37,15 @@ const testDirectoryUrl = resolveUrl("./root/", import.meta.url) const expected = { imports: { "foo/file.js": "./node_modules/foo/file.default.js", + "root/": "./", "root": "./index", "foo": "./node_modules/foo/index", }, - scopes: {}, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, + }, } assert({ actual, expected }) } diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep-2/exports-file-deep-2.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep-2/exports-file-deep-2.test.js index 042c724a..76ec840d 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep-2/exports-file-deep-2.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep-2/exports-file-deep-2.test.js @@ -11,15 +11,18 @@ const importMap = await getImportMapFromProjectFiles({ const actual = importMap const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/index", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/index", }, scopes: { "./node_modules/foo/node_modules/bar/": { "bar/file.js": "./node_modules/foo/node_modules/bar/src/file.js", + "bar/": "./node_modules/foo/node_modules/bar/", }, "./node_modules/foo/": { "bar/file.js": "./node_modules/foo/node_modules/bar/src/file.js", + "foo/": "./node_modules/foo/", "bar": "./node_modules/foo/node_modules/bar/index", }, }, diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep/exports-file-deep.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep/exports-file-deep.test.js index cead984c..80382c55 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep/exports-file-deep.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-file-deep/exports-file-deep.test.js @@ -11,15 +11,18 @@ const importMap = await getImportMapFromProjectFiles({ const actual = importMap const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/index", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/index", }, scopes: { "./node_modules/bar/": { "bar/file.js": "./node_modules/bar/src/file.js", + "bar/": "./node_modules/bar/", }, "./node_modules/foo/": { "bar/file.js": "./node_modules/bar/src/file.js", + "foo/": "./node_modules/foo/", "bar": "./node_modules/bar/index", }, }, diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-file/exports-file.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-file/exports-file.test.js index df8b572f..9af08707 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-file/exports-file.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-file/exports-file.test.js @@ -12,9 +12,14 @@ const actual = importMap const expected = { imports: { "foo/file.js": "./node_modules/foo/src/file.js", + "root/": "./", "root": "./index", "foo": "./node_modules/foo/index.js", }, - scopes: {}, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, + }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-string/exports-string.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-string/exports-string.test.js index 9263362a..40482dac 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-string/exports-string.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-string/exports-string.test.js @@ -11,9 +11,14 @@ const importMap = await getImportMapFromProjectFiles({ const actual = importMap const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/foo.js", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/foo.js", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-exports-field/exports-sugar/exports-sugar.test.js b/test/getImportMapFromProjectFiles/package-exports-field/exports-sugar/exports-sugar.test.js index 9263362a..40482dac 100644 --- a/test/getImportMapFromProjectFiles/package-exports-field/exports-sugar/exports-sugar.test.js +++ b/test/getImportMapFromProjectFiles/package-exports-field/exports-sugar/exports-sugar.test.js @@ -11,9 +11,14 @@ const importMap = await getImportMapFromProjectFiles({ const actual = importMap const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/foo.js", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/foo.js", + }, + scopes: { + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, - scopes: {}, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-importmap-field/importmap-scope/importmap-scope.test.js b/test/getImportMapFromProjectFiles/package-importmap-field/importmap-scope/importmap-scope.test.js index 40eabf72..fd9fd163 100644 --- a/test/getImportMapFromProjectFiles/package-importmap-field/importmap-scope/importmap-scope.test.js +++ b/test/getImportMapFromProjectFiles/package-importmap-field/importmap-scope/importmap-scope.test.js @@ -10,13 +10,17 @@ const actual = await getImportMapFromProjectFiles({ }) const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/index", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/index", }, scopes: { "./node_modules/foo/src/": { "./a.js": "./node_modules/foo/src/b.js", }, + "./node_modules/foo/": { + "foo/": "./node_modules/foo/", + }, }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-importmap-field/importmap-top-level/importmap-top-level.test.js b/test/getImportMapFromProjectFiles/package-importmap-field/importmap-top-level/importmap-top-level.test.js index dd16f5da..9d538912 100644 --- a/test/getImportMapFromProjectFiles/package-importmap-field/importmap-top-level/importmap-top-level.test.js +++ b/test/getImportMapFromProjectFiles/package-importmap-field/importmap-top-level/importmap-top-level.test.js @@ -10,12 +10,14 @@ const actual = await getImportMapFromProjectFiles({ }) const expected = { imports: { - root: "./index", - foo: "./node_modules/foo/index", + "root/": "./", + "root": "./index", + "foo": "./node_modules/foo/index", }, scopes: { "./node_modules/foo/": { "./a.js": "./node_modules/foo/b.js", + "foo/": "./node_modules/foo/", }, }, } diff --git a/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/imports-basic.test.js b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/imports-basic.test.js new file mode 100644 index 00000000..1b332af6 --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/imports-basic.test.js @@ -0,0 +1,21 @@ +import { assert } from "@jsenv/assert" +import { resolveUrl } from "@jsenv/util" +import { getImportMapFromProjectFiles } from "@jsenv/node-module-import-map" + +const testDirectoryUrl = resolveUrl("./root/", import.meta.url) + +const actual = await getImportMapFromProjectFiles({ + projectDirectoryUrl: testDirectoryUrl, +}) +const expected = { + imports: { + root: "./index.js", + foo: "./node_modules/foo/index.js", + }, + scopes: { + "./node_modules/foo/": { + "#env": "./node_modules/foo/env.prod.js", + }, + }, +} +assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/index.js b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/index.js new file mode 100644 index 00000000..05eed085 --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/index.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-unresolved +import "foo" diff --git a/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/env.prod.js b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/env.prod.js new file mode 100644 index 00000000..e69de29b diff --git a/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/index.js b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/index.js new file mode 100644 index 00000000..77673f5f --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/index.js @@ -0,0 +1 @@ +import "#env" \ No newline at end of file diff --git a/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/package.json b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/package.json new file mode 100644 index 00000000..34f0967b --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/node_modules/foo/package.json @@ -0,0 +1,9 @@ +{ + "name": "foo", + "imports": { + "#env": { + "development": "./env.dev.js", + "import": "./env.prod.js" + } + } +} diff --git a/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/package.json b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/package.json new file mode 100644 index 00000000..399e6ef7 --- /dev/null +++ b/test/getImportMapFromProjectFiles/package-imports-field/imports-basic/root/package.json @@ -0,0 +1,6 @@ +{ + "name": "root", + "dependencies": { + "foo": "*" + } +} diff --git a/test/getImportMapFromProjectFiles/package-main-field/main-directory-trailing/main-directory-trailing.test.js b/test/getImportMapFromProjectFiles/package-main-field/main-directory-trailing/main-directory-trailing.test.js index e36c29fb..019d61fb 100644 --- a/test/getImportMapFromProjectFiles/package-main-field/main-directory-trailing/main-directory-trailing.test.js +++ b/test/getImportMapFromProjectFiles/package-main-field/main-directory-trailing/main-directory-trailing.test.js @@ -11,8 +11,13 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "main-folder-trailing": "./node_modules/main-folder-trailing/lib/index.js", + "root/": "./", "root": "./index", }, - scopes: {}, + scopes: { + "./node_modules/main-folder-trailing/": { + "main-folder-trailing/": "./node_modules/main-folder-trailing/", + }, + }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-main-field/main-jsnext/main-jsnext.test.js b/test/getImportMapFromProjectFiles/package-main-field/main-jsnext/main-jsnext.test.js index a36f5068..ab84155e 100644 --- a/test/getImportMapFromProjectFiles/package-main-field/main-jsnext/main-jsnext.test.js +++ b/test/getImportMapFromProjectFiles/package-main-field/main-jsnext/main-jsnext.test.js @@ -11,8 +11,13 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "main-jsnext": "./node_modules/main-jsnext/jsnext.js", + "root/": "./", "root": "./index", }, - scopes: {}, + scopes: { + "./node_modules/main-jsnext/": { + "main-jsnext/": "./node_modules/main-jsnext/", + }, + }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-main-field/main-relative/main-relative.test.js b/test/getImportMapFromProjectFiles/package-main-field/main-relative/main-relative.test.js index f0b83b7a..70aac6b4 100644 --- a/test/getImportMapFromProjectFiles/package-main-field/main-relative/main-relative.test.js +++ b/test/getImportMapFromProjectFiles/package-main-field/main-relative/main-relative.test.js @@ -11,8 +11,13 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "main-relative": "./node_modules/main-relative/lib/index.js", + "root/": "./", "root": "./index", }, - scopes: {}, + scopes: { + "./node_modules/main-relative/": { + "main-relative/": "./node_modules/main-relative/", + }, + }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-main-field/main-undefined/main-undefined.test.js b/test/getImportMapFromProjectFiles/package-main-field/main-undefined/main-undefined.test.js index 7fac4da8..4d7c8920 100644 --- a/test/getImportMapFromProjectFiles/package-main-field/main-undefined/main-undefined.test.js +++ b/test/getImportMapFromProjectFiles/package-main-field/main-undefined/main-undefined.test.js @@ -11,8 +11,13 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "main-undefined": "./node_modules/main-undefined/index.js", + "root/": "./", "root": "./index", }, - scopes: {}, + scopes: { + "./node_modules/main-undefined/": { + "main-undefined/": "./node_modules/main-undefined/", + }, + }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/package-main-field/main-without-extension/main-without-extension.test.js b/test/getImportMapFromProjectFiles/package-main-field/main-without-extension/main-without-extension.test.js index 76569743..a2407d9f 100644 --- a/test/getImportMapFromProjectFiles/package-main-field/main-without-extension/main-without-extension.test.js +++ b/test/getImportMapFromProjectFiles/package-main-field/main-without-extension/main-without-extension.test.js @@ -11,8 +11,13 @@ const actual = await getImportMapFromProjectFiles({ const expected = { imports: { "main-without-extension": "./node_modules/main-without-extension/file.js", + "root/": "./", "root": "./index", }, - scopes: {}, + scopes: { + "./node_modules/main-without-extension/": { + "main-without-extension/": "./node_modules/main-without-extension/", + }, + }, } assert({ actual, expected }) diff --git a/test/getImportMapFromProjectFiles/self-import/self-import-1/root/file.js b/test/getImportMapFromProjectFiles/self-import/self-import-1/root/file.js new file mode 100644 index 00000000..e69de29b diff --git a/test/getImportMapFromProjectFiles/self-import/self-import-1/root/index.js b/test/getImportMapFromProjectFiles/self-import/self-import-1/root/index.js new file mode 100644 index 00000000..bdecdff1 --- /dev/null +++ b/test/getImportMapFromProjectFiles/self-import/self-import-1/root/index.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/no-unresolved +import "root/file.js" diff --git a/test/getImportMapFromProjectFiles/self-import/self-import-1/package.json b/test/getImportMapFromProjectFiles/self-import/self-import-1/root/package.json similarity index 100% rename from test/getImportMapFromProjectFiles/self-import/self-import-1/package.json rename to test/getImportMapFromProjectFiles/self-import/self-import-1/root/package.json diff --git a/test/getImportMapFromProjectFiles/self-import/self-import-1/self-import.test.js b/test/getImportMapFromProjectFiles/self-import/self-import-1/self-import.test.js index dbe0aa61..588a3f78 100644 --- a/test/getImportMapFromProjectFiles/self-import/self-import-1/self-import.test.js +++ b/test/getImportMapFromProjectFiles/self-import/self-import-1/self-import.test.js @@ -2,14 +2,15 @@ import { assert } from "@jsenv/assert" import { resolveUrl } from "@jsenv/util" import { getImportMapFromProjectFiles } from "@jsenv/node-module-import-map" -const testDirectoryUrl = resolveUrl("./", import.meta.url) +const testDirectoryUrl = resolveUrl("./root/", import.meta.url) const actual = await getImportMapFromProjectFiles({ projectDirectoryUrl: testDirectoryUrl, }) const expected = { imports: { - root: "./index.js", + "root/": "./", + "root": "./index.js", }, scopes: {}, } diff --git a/test/getImportMapFromProjectFiles/self-import/self-import-6/self-import-6.test.js b/test/getImportMapFromProjectFiles/self-import/self-import-6/self-import-6.test.js index 4abef5a8..af707254 100644 --- a/test/getImportMapFromProjectFiles/self-import/self-import-6/self-import-6.test.js +++ b/test/getImportMapFromProjectFiles/self-import/self-import-6/self-import-6.test.js @@ -13,11 +13,13 @@ const expected = { "@jsenv/core/conflict": "./root.js", "@jsenv/core/rootonly": "./rootonly.js", "@jsenv/core/deponly": "./node_modules/@jsenv/core/deponly.js", + "@jsenv/core/": "./", "@jsenv/core": "./index.js", }, scopes: { "./node_modules/@jsenv/core/": { "@jsenv/core/conflict": "./node_modules/@jsenv/core/dep.js", + "@jsenv/core/": "./node_modules/@jsenv/core/", "@jsenv/core": "./node_modules/@jsenv/core/maindep.js", }, },