Initial commit

This commit is contained in:
2026-01-18 21:01:43 +03:00
commit 455b6df2ba
3329 changed files with 1143638 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
export namespace codes {
let ERR_INVALID_ARG_TYPE: new (...args: any[]) => Error;
let ERR_INVALID_MODULE_SPECIFIER: new (...args: any[]) => Error;
let ERR_INVALID_PACKAGE_CONFIG: new (...args: any[]) => Error;
let ERR_INVALID_PACKAGE_TARGET: new (...args: any[]) => Error;
let ERR_MODULE_NOT_FOUND: new (...args: any[]) => Error;
let ERR_NETWORK_IMPORT_DISALLOWED: new (...args: any[]) => Error;
let ERR_PACKAGE_IMPORT_NOT_DEFINED: new (...args: any[]) => Error;
let ERR_PACKAGE_PATH_NOT_EXPORTED: new (...args: any[]) => Error;
let ERR_UNSUPPORTED_DIR_IMPORT: new (...args: any[]) => Error;
let ERR_UNKNOWN_FILE_EXTENSION: new (...args: any[]) => Error;
let ERR_INVALID_ARG_VALUE: new (...args: any[]) => Error;
let ERR_UNSUPPORTED_ESM_URL_SCHEME: new (...args: any[]) => Error;
}
export type ErrnoExceptionFields = {
errnode?: number | undefined;
code?: string | undefined;
path?: string | undefined;
syscall?: string | undefined;
url?: string | undefined;
};
export type ErrnoException = Error & ErrnoExceptionFields;
export type MessageFunction = (...args: Array<any>) => string;
+524
View File
@@ -0,0 +1,524 @@
/**
* @typedef ErrnoExceptionFields
* @property {number | undefined} [errnode]
* @property {string | undefined} [code]
* @property {string | undefined} [path]
* @property {string | undefined} [syscall]
* @property {string | undefined} [url]
*
* @typedef {Error & ErrnoExceptionFields} ErrnoException
*/
/**
* @typedef {(...args: Array<any>) => string} MessageFunction
*/
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/6668c4d/lib/internal/errors.js>
// Last checked on: Jan 6, 2023.
import v8 from 'node:v8'
import process from 'node:process'
import assert from 'node:assert'
// Needed for types.
// eslint-disable-next-line no-unused-vars
import {URL} from 'node:url'
import {format, inspect} from 'node:util'
const isWindows = process.platform === 'win32'
const own = {}.hasOwnProperty
const classRegExp = /^([A-Z][a-z\d]*)+$/
// Sorted by a rough estimate on most frequently used entries.
const kTypes = new Set([
'string',
'function',
'number',
'object',
// Accept 'Function' and 'Object' as alternative to the lower cased version.
'Function',
'Object',
'boolean',
'bigint',
'symbol'
])
export const codes = {}
/**
* Create a list string in the form like 'A and B' or 'A, B, ..., and Z'.
* We cannot use Intl.ListFormat because it's not available in
* --without-intl builds.
*
* @param {Array<string>} array
* An array of strings.
* @param {string} [type]
* The list type to be inserted before the last element.
* @returns {string}
*/
function formatList(array, type = 'and') {
return array.length < 3
? array.join(` ${type} `)
: `${array.slice(0, -1).join(', ')}, ${type} ${array[array.length - 1]}`
}
/** @type {Map<string, MessageFunction | string>} */
const messages = new Map()
const nodeInternalPrefix = '__node_internal_'
/** @type {number} */
let userStackTraceLimit
codes.ERR_INVALID_ARG_TYPE = createError(
'ERR_INVALID_ARG_TYPE',
/**
* @param {string} name
* @param {Array<string> | string} expected
* @param {unknown} actual
*/
(name, expected, actual) => {
assert(typeof name === 'string', "'name' must be a string")
if (!Array.isArray(expected)) {
expected = [expected]
}
let message = 'The '
if (name.endsWith(' argument')) {
// For cases like 'first argument'
message += `${name} `
} else {
const type = name.includes('.') ? 'property' : 'argument'
message += `"${name}" ${type} `
}
message += 'must be '
/** @type {Array<string>} */
const types = []
/** @type {Array<string>} */
const instances = []
/** @type {Array<string>} */
const other = []
for (const value of expected) {
assert(
typeof value === 'string',
'All expected entries have to be of type string'
)
if (kTypes.has(value)) {
types.push(value.toLowerCase())
} else if (classRegExp.exec(value) === null) {
assert(
value !== 'object',
'The value "object" should be written as "Object"'
)
other.push(value)
} else {
instances.push(value)
}
}
// Special handle `object` in case other instances are allowed to outline
// the differences between each other.
if (instances.length > 0) {
const pos = types.indexOf('object')
if (pos !== -1) {
types.slice(pos, 1)
instances.push('Object')
}
}
if (types.length > 0) {
message += `${types.length > 1 ? 'one of type' : 'of type'} ${formatList(
types,
'or'
)}`
if (instances.length > 0 || other.length > 0) message += ' or '
}
if (instances.length > 0) {
message += `an instance of ${formatList(instances, 'or')}`
if (other.length > 0) message += ' or '
}
if (other.length > 0) {
if (other.length > 1) {
message += `one of ${formatList(other, 'or')}`
} else {
if (other[0].toLowerCase() !== other[0]) message += 'an '
message += `${other[0]}`
}
}
message += `. Received ${determineSpecificType(actual)}`
return message
},
TypeError
)
codes.ERR_INVALID_MODULE_SPECIFIER = createError(
'ERR_INVALID_MODULE_SPECIFIER',
/**
* @param {string} request
* @param {string} reason
* @param {string} [base]
*/
(request, reason, base = undefined) => {
return `Invalid module "${request}" ${reason}${
base ? ` imported from ${base}` : ''
}`
},
TypeError
)
codes.ERR_INVALID_PACKAGE_CONFIG = createError(
'ERR_INVALID_PACKAGE_CONFIG',
/**
* @param {string} path
* @param {string} [base]
* @param {string} [message]
*/
(path, base, message) => {
return `Invalid package config ${path}${
base ? ` while importing ${base}` : ''
}${message ? `. ${message}` : ''}`
},
Error
)
codes.ERR_INVALID_PACKAGE_TARGET = createError(
'ERR_INVALID_PACKAGE_TARGET',
/**
* @param {string} pkgPath
* @param {string} key
* @param {unknown} target
* @param {boolean} [isImport=false]
* @param {string} [base]
*/
(pkgPath, key, target, isImport = false, base = undefined) => {
const relError =
typeof target === 'string' &&
!isImport &&
target.length > 0 &&
!target.startsWith('./')
if (key === '.') {
assert(isImport === false)
return (
`Invalid "exports" main target ${JSON.stringify(target)} defined ` +
`in the package config ${pkgPath}package.json${
base ? ` imported from ${base}` : ''
}${relError ? '; targets must start with "./"' : ''}`
)
}
return `Invalid "${
isImport ? 'imports' : 'exports'
}" target ${JSON.stringify(
target
)} defined for '${key}' in the package config ${pkgPath}package.json${
base ? ` imported from ${base}` : ''
}${relError ? '; targets must start with "./"' : ''}`
},
Error
)
codes.ERR_MODULE_NOT_FOUND = createError(
'ERR_MODULE_NOT_FOUND',
/**
* @param {string} path
* @param {string} base
* @param {string} [type]
*/
(path, base, type = 'package') => {
return `Cannot find ${type} '${path}' imported from ${base}`
},
Error
)
codes.ERR_NETWORK_IMPORT_DISALLOWED = createError(
'ERR_NETWORK_IMPORT_DISALLOWED',
"import of '%s' by %s is not supported: %s",
Error
)
codes.ERR_PACKAGE_IMPORT_NOT_DEFINED = createError(
'ERR_PACKAGE_IMPORT_NOT_DEFINED',
/**
* @param {string} specifier
* @param {string} packagePath
* @param {string} base
*/
(specifier, packagePath, base) => {
return `Package import specifier "${specifier}" is not defined${
packagePath ? ` in package ${packagePath}package.json` : ''
} imported from ${base}`
},
TypeError
)
codes.ERR_PACKAGE_PATH_NOT_EXPORTED = createError(
'ERR_PACKAGE_PATH_NOT_EXPORTED',
/**
* @param {string} pkgPath
* @param {string} subpath
* @param {string} [base]
*/
(pkgPath, subpath, base = undefined) => {
if (subpath === '.')
return `No "exports" main defined in ${pkgPath}package.json${
base ? ` imported from ${base}` : ''
}`
return `Package subpath '${subpath}' is not defined by "exports" in ${pkgPath}package.json${
base ? ` imported from ${base}` : ''
}`
},
Error
)
codes.ERR_UNSUPPORTED_DIR_IMPORT = createError(
'ERR_UNSUPPORTED_DIR_IMPORT',
"Directory import '%s' is not supported " +
'resolving ES modules imported from %s',
Error
)
codes.ERR_UNKNOWN_FILE_EXTENSION = createError(
'ERR_UNKNOWN_FILE_EXTENSION',
/**
* @param {string} ext
* @param {string} path
*/
(ext, path) => {
return `Unknown file extension "${ext}" for ${path}`
},
TypeError
)
codes.ERR_INVALID_ARG_VALUE = createError(
'ERR_INVALID_ARG_VALUE',
/**
* @param {string} name
* @param {unknown} value
* @param {string} [reason='is invalid']
*/
(name, value, reason = 'is invalid') => {
let inspected = inspect(value)
if (inspected.length > 128) {
inspected = `${inspected.slice(0, 128)}...`
}
const type = name.includes('.') ? 'property' : 'argument'
return `The ${type} '${name}' ${reason}. Received ${inspected}`
},
TypeError
// Note: extra classes have been shaken out.
// , RangeError
)
codes.ERR_UNSUPPORTED_ESM_URL_SCHEME = createError(
'ERR_UNSUPPORTED_ESM_URL_SCHEME',
/**
* @param {URL} url
* @param {Array<string>} supported
*/
(url, supported) => {
let message = `Only URLs with a scheme in: ${formatList(
supported
)} are supported by the default ESM loader`
if (isWindows && url.protocol.length === 2) {
message += '. On Windows, absolute paths must be valid file:// URLs'
}
message += `. Received protocol '${url.protocol}'`
return message
},
Error
)
/**
* Utility function for registering the error codes. Only used here. Exported
* *only* to allow for testing.
* @param {string} sym
* @param {MessageFunction | string} value
* @param {ErrorConstructor} def
* @returns {new (...args: Array<any>) => Error}
*/
function createError(sym, value, def) {
// Special case for SystemError that formats the error message differently
// The SystemErrors only have SystemError as their base classes.
messages.set(sym, value)
return makeNodeErrorWithCode(def, sym)
}
/**
* @param {ErrorConstructor} Base
* @param {string} key
* @returns {ErrorConstructor}
*/
function makeNodeErrorWithCode(Base, key) {
// @ts-expect-error It’s a Node error.
return NodeError
/**
* @param {Array<unknown>} args
*/
function NodeError(...args) {
const limit = Error.stackTraceLimit
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = 0
const error = new Base()
// Reset the limit and setting the name property.
if (isErrorStackTraceLimitWritable()) Error.stackTraceLimit = limit
const message = getMessage(key, args, error)
Object.defineProperties(error, {
// Note: no need to implement `kIsNodeError` symbol, would be hard,
// probably.
message: {
value: message,
enumerable: false,
writable: true,
configurable: true
},
toString: {
/** @this {Error} */
value() {
return `${this.name} [${key}]: ${this.message}`
},
enumerable: false,
writable: true,
configurable: true
}
})
captureLargerStackTrace(error)
// @ts-expect-error It’s a Node error.
error.code = key
return error
}
}
/**
* @returns {boolean}
*/
function isErrorStackTraceLimitWritable() {
// Do no touch Error.stackTraceLimit as V8 would attempt to install
// it again during deserialization.
try {
// @ts-expect-error: not in types?
if (v8.startupSnapshot.isBuildingSnapshot()) {
return false
}
} catch {}
const desc = Object.getOwnPropertyDescriptor(Error, 'stackTraceLimit')
if (desc === undefined) {
return Object.isExtensible(Error)
}
return own.call(desc, 'writable') && desc.writable !== undefined
? desc.writable
: desc.set !== undefined
}
/**
* This function removes unnecessary frames from Node.js core errors.
* @template {(...args: unknown[]) => unknown} T
* @param {T} fn
* @returns {T}
*/
function hideStackFrames(fn) {
// We rename the functions that will be hidden to cut off the stacktrace
// at the outermost one
const hidden = nodeInternalPrefix + fn.name
Object.defineProperty(fn, 'name', {value: hidden})
return fn
}
const captureLargerStackTrace = hideStackFrames(
/**
* @param {Error} error
* @returns {Error}
*/
// @ts-expect-error: fine
function (error) {
const stackTraceLimitIsWritable = isErrorStackTraceLimitWritable()
if (stackTraceLimitIsWritable) {
userStackTraceLimit = Error.stackTraceLimit
Error.stackTraceLimit = Number.POSITIVE_INFINITY
}
Error.captureStackTrace(error)
// Reset the limit
if (stackTraceLimitIsWritable) Error.stackTraceLimit = userStackTraceLimit
return error
}
)
/**
* @param {string} key
* @param {Array<unknown>} args
* @param {Error} self
* @returns {string}
*/
function getMessage(key, args, self) {
const message = messages.get(key)
assert(message !== undefined, 'expected `message` to be found')
if (typeof message === 'function') {
assert(
message.length <= args.length, // Default options do not count.
`Code: ${key}; The provided arguments length (${args.length}) does not ` +
`match the required ones (${message.length}).`
)
return Reflect.apply(message, self, args)
}
const regex = /%[dfijoOs]/g
let expectedLength = 0
while (regex.exec(message) !== null) expectedLength++
assert(
expectedLength === args.length,
`Code: ${key}; The provided arguments length (${args.length}) does not ` +
`match the required ones (${expectedLength}).`
)
if (args.length === 0) return message
args.unshift(message)
return Reflect.apply(format, null, args)
}
/**
* Determine the specific type of a value for type-mismatch errors.
* @param {unknown} value
* @returns {string}
*/
function determineSpecificType(value) {
if (value === null || value === undefined) {
return String(value)
}
if (typeof value === 'function' && value.name) {
return `function ${value.name}`
}
if (typeof value === 'object') {
if (value.constructor && value.constructor.name) {
return `an instance of ${value.constructor.name}`
}
return `${inspect(value, {depth: -1})}`
}
let inspected = inspect(value, {colors: false})
if (inspected.length > 28) {
inspected = `${inspected.slice(0, 25)}...`
}
return `type ${typeof value} (${inspected})`
}
+21
View File
@@ -0,0 +1,21 @@
/// <reference types="node" resolution-mode="require"/>
/**
* @param {URL} url
* @param {{parentURL: string}} context
* @returns {string | null}
*/
export function defaultGetFormatWithoutErrors(url: URL, context: {
parentURL: string;
}): string | null;
/**
* @param {string} url
* @param {{parentURL: string}} context
* @returns {null | string | void}
*/
export function defaultGetFormat(url: string, context: {
parentURL: string;
}): null | string | void;
export type ProtocolHandler = (parsed: URL, context: {
parentURL: string;
}, ignoreErrors: boolean) => string | null | void;
import { URL } from 'node:url';
+151
View File
@@ -0,0 +1,151 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/get_format.js>
// Last checked on: Apr 24, 2023.
import {URL, fileURLToPath} from 'node:url'
import {getPackageType} from './resolve-get-package-type.js'
import {codes} from './errors.js'
const {ERR_UNKNOWN_FILE_EXTENSION} = codes
const hasOwnProperty = {}.hasOwnProperty
/** @type {Record<string, string>} */
const extensionFormatMap = {
// @ts-expect-error: hush.
__proto__: null,
'.cjs': 'commonjs',
'.js': 'module',
'.json': 'json',
'.mjs': 'module'
}
/**
* @param {string | null} mime
* @returns {string | null}
*/
function mimeToFormat(mime) {
if (
mime &&
/\s*(text|application)\/javascript\s*(;\s*charset=utf-?8\s*)?/i.test(mime)
)
return 'module'
if (mime === 'application/json') return 'json'
return null
}
/**
* @callback ProtocolHandler
* @param {URL} parsed
* @param {{parentURL: string}} context
* @param {boolean} ignoreErrors
* @returns {string | null | void}
*/
/**
* @type {Record<string, ProtocolHandler>}
*/
const protocolHandlers = {
// @ts-expect-error: hush.
__proto__: null,
'data:': getDataProtocolModuleFormat,
'file:': getFileProtocolModuleFormat,
'http:': getHttpProtocolModuleFormat,
'https:': getHttpProtocolModuleFormat,
'node:'() {
return 'builtin'
}
}
/**
* @param {URL} parsed
*/
function getDataProtocolModuleFormat(parsed) {
const {1: mime} = /^([^/]+\/[^;,]+)[^,]*?(;base64)?,/.exec(
parsed.pathname
) || [null, null, null]
return mimeToFormat(mime)
}
/**
* Returns the file extension from a URL.
*
* Should give similar result to
* `require('node:path').extname(require('node:url').fileURLToPath(url))`
* when used with a `file:` URL.
*
* @param {URL} url
* @returns {string}
*/
function extname(url) {
const pathname = url.pathname
let index = pathname.length
while (index--) {
const code = pathname.codePointAt(index)
if (code === 47 /* `/` */) {
return ''
}
if (code === 46 /* `.` */) {
return pathname.codePointAt(index - 1) === 47 /* `/` */
? ''
: pathname.slice(index)
}
}
return ''
}
/**
* @type {ProtocolHandler}
*/
function getFileProtocolModuleFormat(url, _context, ignoreErrors) {
const ext = extname(url)
if (ext === '.js') {
return getPackageType(url) === 'module' ? 'module' : 'commonjs'
}
const format = extensionFormatMap[ext]
if (format) return format
// Explicit undefined return indicates load hook should rerun format check
if (ignoreErrors) {
return undefined
}
const filepath = fileURLToPath(url)
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath)
}
function getHttpProtocolModuleFormat() {
// To do: HTTPS imports.
}
/**
* @param {URL} url
* @param {{parentURL: string}} context
* @returns {string | null}
*/
export function defaultGetFormatWithoutErrors(url, context) {
if (!hasOwnProperty.call(protocolHandlers, url.protocol)) {
return null
}
return protocolHandlers[url.protocol](url, context, true) || null
}
/**
* @param {string} url
* @param {{parentURL: string}} context
* @returns {null | string | void}
*/
export function defaultGetFormat(url, context) {
const parsed = new URL(url)
return hasOwnProperty.call(protocolHandlers, parsed.protocol)
? protocolHandlers[parsed.protocol](parsed, context, false)
: null
}
+25
View File
@@ -0,0 +1,25 @@
/// <reference types="node" resolution-mode="require"/>
/**
* @param {string} path
* @param {URL | string} specifier Note: `specifier` is actually optional, not base.
* @param {URL} [base]
* @returns {PackageConfig}
*/
export function getPackageConfig(path: string, specifier: URL | string, base?: URL | undefined): PackageConfig;
/**
* @param {URL} resolved
* @returns {PackageConfig}
*/
export function getPackageScopeConfig(resolved: URL): PackageConfig;
export type ErrnoException = import('./errors.js').ErrnoException;
export type PackageType = 'commonjs' | 'module' | 'none';
export type PackageConfig = {
pjsonPath: string;
exists: boolean;
main: string | undefined;
name: string | undefined;
type: PackageType;
exports: Record<string, unknown> | undefined;
imports: Record<string, unknown> | undefined;
};
import { URL } from 'node:url';
+129
View File
@@ -0,0 +1,129 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/package_config.js>
// Last checked on: Apr 24, 2023.
/**
* @typedef {import('./errors.js').ErrnoException} ErrnoException
*
* @typedef {'commonjs' | 'module' | 'none'} PackageType
*
* @typedef PackageConfig
* @property {string} pjsonPath
* @property {boolean} exists
* @property {string | undefined} main
* @property {string | undefined} name
* @property {PackageType} type
* @property {Record<string, unknown> | undefined} exports
* @property {Record<string, unknown> | undefined} imports
*/
import {URL, fileURLToPath} from 'node:url'
import {codes} from './errors.js'
import packageJsonReader from './package-json-reader.js'
const {ERR_INVALID_PACKAGE_CONFIG} = codes
/** @type {Map<string, PackageConfig>} */
const packageJsonCache = new Map()
/**
* @param {string} path
* @param {URL | string} specifier Note: `specifier` is actually optional, not base.
* @param {URL} [base]
* @returns {PackageConfig}
*/
export function getPackageConfig(path, specifier, base) {
const existing = packageJsonCache.get(path)
if (existing !== undefined) {
return existing
}
const source = packageJsonReader.read(path).string
if (source === undefined) {
/** @type {PackageConfig} */
const packageConfig = {
pjsonPath: path,
exists: false,
main: undefined,
name: undefined,
type: 'none',
exports: undefined,
imports: undefined
}
packageJsonCache.set(path, packageConfig)
return packageConfig
}
/** @type {Record<string, unknown>} */
let packageJson
try {
packageJson = JSON.parse(source)
} catch (error) {
const exception = /** @type {ErrnoException} */ (error)
throw new ERR_INVALID_PACKAGE_CONFIG(
path,
(base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier),
exception.message
)
}
const {exports, imports, main, name, type} = packageJson
/** @type {PackageConfig} */
const packageConfig = {
pjsonPath: path,
exists: true,
main: typeof main === 'string' ? main : undefined,
name: typeof name === 'string' ? name : undefined,
type: type === 'module' || type === 'commonjs' ? type : 'none',
// @ts-expect-error Assume `Record<string, unknown>`.
exports,
// @ts-expect-error Assume `Record<string, unknown>`.
imports: imports && typeof imports === 'object' ? imports : undefined
}
packageJsonCache.set(path, packageConfig)
return packageConfig
}
/**
* @param {URL} resolved
* @returns {PackageConfig}
*/
export function getPackageScopeConfig(resolved) {
let packageJsonUrl = new URL('package.json', resolved)
while (true) {
const packageJsonPath = packageJsonUrl.pathname
if (packageJsonPath.endsWith('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)
/** @type {PackageConfig} */
const packageConfig = {
pjsonPath: packageJsonPath,
exists: false,
main: undefined,
name: undefined,
type: 'none',
exports: undefined,
imports: undefined
}
packageJsonCache.set(packageJsonPath, packageConfig)
return packageConfig
}
+12
View File
@@ -0,0 +1,12 @@
export default reader;
export type ErrnoException = import('./errors.js').ErrnoException;
declare namespace reader {
export { read };
}
/**
* @param {string} jsonPath
* @returns {{string: string | undefined}}
*/
declare function read(jsonPath: string): {
string: string | undefined;
};
+39
View File
@@ -0,0 +1,39 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/package_json_reader.js>
// Last checked on: Apr 24, 2023.
// Removed the native dependency.
// Also: no need to cache, we do that in resolve already.
/**
* @typedef {import('./errors.js').ErrnoException} ErrnoException
*/
import fs from 'node:fs'
import path from 'node:path'
const reader = {read}
export default reader
/**
* @param {string} jsonPath
* @returns {{string: string | undefined}}
*/
function read(jsonPath) {
try {
const string = fs.readFileSync(
path.toNamespacedPath(path.join(path.dirname(jsonPath), 'package.json')),
'utf8'
)
return {string}
} catch (error) {
const exception = /** @type {ErrnoException} */ (error)
if (exception.code === 'ENOENT') {
return {string: undefined}
// Throw all other errors.
/* c8 ignore next 4 */
}
throw exception
}
}
@@ -0,0 +1,6 @@
/**
* @param {URL} url
* @returns {PackageType}
*/
export function getPackageType(url: URL): PackageType;
export type PackageType = import('./package-config.js').PackageType;
@@ -0,0 +1,23 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/resolve.js>
// Last checked on: Apr 24, 2023.
//
// This file solves a circular dependency.
// In Node.js, `getPackageType` is in `resolve.js`.
// `resolve.js` imports `get-format.js`, which needs `getPackageType`.
// We split that up so that bundlers don’t fail.
/**
* @typedef {import('./package-config.js').PackageType} PackageType
*/
import {getPackageScopeConfig} from './package-config.js'
/**
* @param {URL} url
* @returns {PackageType}
*/
export function getPackageType(url) {
const packageConfig = getPackageScopeConfig(url)
return packageConfig.type
}
+32
View File
@@ -0,0 +1,32 @@
/// <reference types="node" resolution-mode="require"/>
/**
* The “Resolver Algorithm Specification” as detailed in the Node docs (which is
* sync and slightly lower-level than `resolve`).
*
* @param {string} specifier
* `/example.js`, `./example.js`, `../example.js`, `some-package`, `fs`, etc.
* @param {URL} base
* Full URL (to a file) that `specifier` is resolved relative from.
* @param {Set<string>} [conditions]
* Conditions.
* @param {boolean} [preserveSymlinks]
* Keep symlinks instead of resolving them.
* @returns {URL}
* A URL object to the found thing.
*/
export function moduleResolve(specifier: string, base: URL, conditions?: Set<string> | undefined, preserveSymlinks?: boolean | undefined): URL;
/**
* @param {string} specifier
* @param {{parentURL?: string, conditions?: Array<string>}} context
* @returns {{url: string, format?: string | null}}
*/
export function defaultResolve(specifier: string, context?: {
parentURL?: string;
conditions?: Array<string>;
}): {
url: string;
format?: string | null;
};
export type ErrnoException = import('./errors.js').ErrnoException;
export type PackageConfig = import('./package-config.js').PackageConfig;
import { URL } from 'node:url';
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
/**
* @param {Array<string>} [conditions]
* @returns {Set<string>}
*/
export function getConditionsSet(conditions?: string[] | undefined): Set<string>;
+41
View File
@@ -0,0 +1,41 @@
// Manually “tree shaken” from:
// <https://github.com/nodejs/node/blob/3e74590/lib/internal/modules/esm/utils.js>
// Last checked on: Apr 24, 2023.
import {codes} from './errors.js'
const {ERR_INVALID_ARG_VALUE} = codes
// In Node itself these values are populated from CLI arguments, before any
// user code runs.
// Here we just define the defaults.
const DEFAULT_CONDITIONS = Object.freeze(['node', 'import'])
const DEFAULT_CONDITIONS_SET = new Set(DEFAULT_CONDITIONS)
function getDefaultConditions() {
return DEFAULT_CONDITIONS
}
function getDefaultConditionsSet() {
return DEFAULT_CONDITIONS_SET
}
/**
* @param {Array<string>} [conditions]
* @returns {Set<string>}
*/
export function getConditionsSet(conditions) {
if (conditions !== undefined && conditions !== getDefaultConditions()) {
if (!Array.isArray(conditions)) {
throw new ERR_INVALID_ARG_VALUE(
'conditions',
conditions,
'expected an array'
)
}
return new Set(conditions)
}
return getDefaultConditionsSet()
}