mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
esm: move package config helpers
PR-URL: https://github.com/nodejs/node/pull/43967 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
da2764bda3
commit
7ef40322b7
142
lib/internal/modules/esm/package_config.js
Normal file
142
lib/internal/modules/esm/package_config.js
Normal file
@ -0,0 +1,142 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
JSONParse,
|
||||
SafeMap,
|
||||
StringPrototypeEndsWith,
|
||||
} = primordials;
|
||||
const { URL, fileURLToPath } = require('internal/url');
|
||||
const {
|
||||
ERR_INVALID_PACKAGE_CONFIG,
|
||||
} = require('internal/errors').codes;
|
||||
|
||||
const packageJsonReader = require('internal/modules/package_json_reader');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {string | string[] | Record<string, unknown>} Exports
|
||||
* @typedef {'module' | 'commonjs'} PackageType
|
||||
* @typedef {{
|
||||
* pjsonPath: string,
|
||||
* exports?: ExportConfig,
|
||||
* name?: string,
|
||||
* main?: string,
|
||||
* type?: PackageType,
|
||||
* }} PackageConfig
|
||||
*/
|
||||
|
||||
/** @type {Map<string, PackageConfig>} */
|
||||
const packageJSONCache = new SafeMap();
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {string} specifier
|
||||
* @param {string | URL | undefined} base
|
||||
* @returns {PackageConfig}
|
||||
*/
|
||||
function getPackageConfig(path, specifier, base) {
|
||||
const existing = packageJSONCache.get(path);
|
||||
if (existing !== undefined) {
|
||||
return existing;
|
||||
}
|
||||
const source = packageJsonReader.read(path).string;
|
||||
if (source === undefined) {
|
||||
const packageConfig = {
|
||||
pjsonPath: path,
|
||||
exists: false,
|
||||
main: undefined,
|
||||
name: undefined,
|
||||
type: 'none',
|
||||
exports: undefined,
|
||||
imports: undefined,
|
||||
};
|
||||
packageJSONCache.set(path, packageConfig);
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
let packageJSON;
|
||||
try {
|
||||
packageJSON = JSONParse(source);
|
||||
} catch (error) {
|
||||
throw new ERR_INVALID_PACKAGE_CONFIG(
|
||||
path,
|
||||
(base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier),
|
||||
error.message
|
||||
);
|
||||
}
|
||||
|
||||
let { imports, main, name, type } = packageJSON;
|
||||
const { exports } = packageJSON;
|
||||
if (typeof imports !== 'object' || imports === null) {
|
||||
imports = undefined;
|
||||
}
|
||||
if (typeof main !== 'string') {
|
||||
main = undefined;
|
||||
}
|
||||
if (typeof name !== 'string') {
|
||||
name = undefined;
|
||||
}
|
||||
// Ignore unknown types for forwards compatibility
|
||||
if (type !== 'module' && type !== 'commonjs') {
|
||||
type = 'none';
|
||||
}
|
||||
|
||||
const packageConfig = {
|
||||
pjsonPath: path,
|
||||
exists: true,
|
||||
main,
|
||||
name,
|
||||
type,
|
||||
exports,
|
||||
imports,
|
||||
};
|
||||
packageJSONCache.set(path, packageConfig);
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {URL | string} resolved
|
||||
* @returns {PackageConfig}
|
||||
*/
|
||||
function getPackageScopeConfig(resolved) {
|
||||
let packageJSONUrl = new URL('./package.json', resolved);
|
||||
while (true) {
|
||||
const packageJSONPath = packageJSONUrl.pathname;
|
||||
if (StringPrototypeEndsWith(packageJSONPath, 'node_modules/package.json')) {
|
||||
break;
|
||||
}
|
||||
const packageConfig = getPackageConfig(fileURLToPath(packageJSONUrl), resolved);
|
||||
if (packageConfig.exists) {
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
const lastPackageJSONUrl = packageJSONUrl;
|
||||
packageJSONUrl = new URL('../package.json', packageJSONUrl);
|
||||
|
||||
// Terminates at root where ../package.json equals ../../package.json
|
||||
// (can't just check "/package.json" for Windows support).
|
||||
if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const packageJSONPath = fileURLToPath(packageJSONUrl);
|
||||
const packageConfig = {
|
||||
pjsonPath: packageJSONPath,
|
||||
exists: false,
|
||||
main: undefined,
|
||||
name: undefined,
|
||||
type: 'none',
|
||||
exports: undefined,
|
||||
imports: undefined,
|
||||
};
|
||||
packageJSONCache.set(packageJSONPath, packageConfig);
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
getPackageConfig,
|
||||
getPackageScopeConfig,
|
||||
};
|
@ -58,9 +58,16 @@ const {
|
||||
ERR_NETWORK_IMPORT_DISALLOWED,
|
||||
ERR_UNSUPPORTED_ESM_URL_SCHEME,
|
||||
} = require('internal/errors').codes;
|
||||
const { Module: CJSModule } = require('internal/modules/cjs/loader');
|
||||
|
||||
const { Module: CJSModule } = require('internal/modules/cjs/loader');
|
||||
const packageJsonReader = require('internal/modules/package_json_reader');
|
||||
const { getPackageConfig, getPackageScopeConfig } = require('internal/modules/esm/package_config');
|
||||
|
||||
/**
|
||||
* @typedef {import('internal/modules/esm/package_config.js').PackageConfig} PackageConfig
|
||||
*/
|
||||
|
||||
|
||||
const userConditions = getOptionValue('--conditions');
|
||||
const noAddons = getOptionValue('--no-addons');
|
||||
const addonConditions = noAddons ? [] : ['node-addons'];
|
||||
@ -74,18 +81,6 @@ const DEFAULT_CONDITIONS = ObjectFreeze([
|
||||
|
||||
const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS);
|
||||
|
||||
/**
|
||||
* @typedef {string | string[] | Record<string, unknown>} Exports
|
||||
* @typedef {'module' | 'commonjs'} PackageType
|
||||
* @typedef {{
|
||||
* pjsonPath: string,
|
||||
* exports?: ExportConfig,
|
||||
* name?: string,
|
||||
* main?: string,
|
||||
* type?: PackageType,
|
||||
* }} PackageConfig
|
||||
*/
|
||||
|
||||
const emittedPackageWarnings = new SafeSet();
|
||||
|
||||
function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) {
|
||||
@ -154,7 +149,6 @@ function getConditionsSet(conditions) {
|
||||
}
|
||||
|
||||
const realpathCache = new SafeMap();
|
||||
const packageJSONCache = new SafeMap(); /* string -> PackageConfig */
|
||||
|
||||
/**
|
||||
* @param {string | URL} path
|
||||
@ -163,99 +157,6 @@ const packageJSONCache = new SafeMap(); /* string -> PackageConfig */
|
||||
const tryStatSync =
|
||||
(path) => statSync(path, { throwIfNoEntry: false }) ?? new Stats();
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {string} specifier
|
||||
* @param {string | URL | undefined} base
|
||||
* @returns {PackageConfig}
|
||||
*/
|
||||
function getPackageConfig(path, specifier, base) {
|
||||
const existing = packageJSONCache.get(path);
|
||||
if (existing !== undefined) {
|
||||
return existing;
|
||||
}
|
||||
const source = packageJsonReader.read(path).string;
|
||||
if (source === undefined) {
|
||||
const packageConfig = {
|
||||
pjsonPath: path,
|
||||
exists: false,
|
||||
main: undefined,
|
||||
name: undefined,
|
||||
type: 'none',
|
||||
exports: undefined,
|
||||
imports: undefined,
|
||||
};
|
||||
packageJSONCache.set(path, packageConfig);
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
let packageJSON;
|
||||
try {
|
||||
packageJSON = JSONParse(source);
|
||||
} catch (error) {
|
||||
throw new ERR_INVALID_PACKAGE_CONFIG(
|
||||
path,
|
||||
(base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier),
|
||||
error.message
|
||||
);
|
||||
}
|
||||
|
||||
let { imports, main, name, type } = packageJSON;
|
||||
const { exports } = packageJSON;
|
||||
if (typeof imports !== 'object' || imports === null) imports = undefined;
|
||||
if (typeof main !== 'string') main = undefined;
|
||||
if (typeof name !== 'string') name = undefined;
|
||||
// Ignore unknown types for forwards compatibility
|
||||
if (type !== 'module' && type !== 'commonjs') type = 'none';
|
||||
|
||||
const packageConfig = {
|
||||
pjsonPath: path,
|
||||
exists: true,
|
||||
main,
|
||||
name,
|
||||
type,
|
||||
exports,
|
||||
imports,
|
||||
};
|
||||
packageJSONCache.set(path, packageConfig);
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {URL | string} resolved
|
||||
* @returns {PackageConfig}
|
||||
*/
|
||||
function getPackageScopeConfig(resolved) {
|
||||
let packageJSONUrl = new URL('./package.json', resolved);
|
||||
while (true) {
|
||||
const packageJSONPath = packageJSONUrl.pathname;
|
||||
if (StringPrototypeEndsWith(packageJSONPath, 'node_modules/package.json'))
|
||||
break;
|
||||
const packageConfig = getPackageConfig(fileURLToPath(packageJSONUrl),
|
||||
resolved);
|
||||
if (packageConfig.exists) return packageConfig;
|
||||
|
||||
const lastPackageJSONUrl = packageJSONUrl;
|
||||
packageJSONUrl = new URL('../package.json', packageJSONUrl);
|
||||
|
||||
// Terminates at root where ../package.json equals ../../package.json
|
||||
// (can't just check "/package.json" for Windows support).
|
||||
if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) break;
|
||||
}
|
||||
const packageJSONPath = fileURLToPath(packageJSONUrl);
|
||||
const packageConfig = {
|
||||
pjsonPath: packageJSONPath,
|
||||
exists: false,
|
||||
main: undefined,
|
||||
name: undefined,
|
||||
type: 'none',
|
||||
exports: undefined,
|
||||
imports: undefined,
|
||||
};
|
||||
packageJSONCache.set(packageJSONPath, packageConfig);
|
||||
return packageConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | URL} url
|
||||
* @returns {boolean}
|
||||
@ -609,7 +510,7 @@ function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath,
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Exports} exports
|
||||
* @param {import('internal/modules/esm/package_config.js').Exports} exports
|
||||
* @param {URL} packageJSONUrl
|
||||
* @param {string | URL | undefined} base
|
||||
* @returns {boolean}
|
||||
@ -799,7 +700,7 @@ function packageImportsResolve(name, base, conditions) {
|
||||
|
||||
/**
|
||||
* @param {URL} url
|
||||
* @returns {PackageType}
|
||||
* @returns {import('internal/modules/esm/package_config.js').PackageType}
|
||||
*/
|
||||
function getPackageType(url) {
|
||||
const packageConfig = getPackageScopeConfig(url);
|
||||
|
@ -84,6 +84,7 @@ const expectedModules = new Set([
|
||||
'NativeModule internal/modules/esm/loader',
|
||||
'NativeModule internal/modules/esm/module_job',
|
||||
'NativeModule internal/modules/esm/module_map',
|
||||
'NativeModule internal/modules/esm/package_config',
|
||||
'NativeModule internal/modules/esm/resolve',
|
||||
'NativeModule internal/modules/esm/translators',
|
||||
'NativeModule internal/modules/package_json_reader',
|
||||
|
Loading…
Reference in New Issue
Block a user