UNPKG

bidirectional-resolve

Version:

Resolve a package entry point to a file path (like require.resolve/import.meta.resolve) OR a file path to a package entry point

343 lines 12.7 kB
export type ConditionsOption = { /** * Conditions to recursively match against. If none of the listed conditions * can be found and there are no matching `default` conditions, this function * returns an empty array. * * In addition to `default` (which is always implicitly enabled), the * following are standard/well-known conditions: * - `import` * - `require` * - `node` * - `node-addons` * - `types` * - `deno` * - `browser` * - `react-native` * - `electron` * - `development` * - `production` * * Array order does not matter. Priority is determined by the property order * of conditions defined within a `package.json` `imports`/`exports` mapping. * * @see https://nodejs.org/api/packages.html#community-conditions-definitions */ conditions?: string[]; }; export type FlattenedImportsOption = { /** * The `package.json` `imports` object as a flattened array. Such an array is * returned by {@link flattenPackageJsonSubpathMap}. */ flattenedImports: SubpathMappings; }; export type FlattenedExportsOption = { /** * The `package.json` `exports` object as a flattened array. Such an array is * returned by {@link flattenPackageJsonSubpathMap}. */ flattenedExports: SubpathMappings; }; export type UnsafeFallbackOption = { /** * When encountering a fallback array (i.e. targets present at some level * within an array), * [Node.js](https://github.com/nodejs/node/issues/37928#issuecomment-808833604) * will [select the first valid defined non-null target and ignore all the * others](https://github.com/nodejs/node/blob/a9cdeeda880a56de6dad10b24b3bfa45e2cccb5d/lib/internal/modules/esm/resolve.js#L417-L432), * even if that target ends up being unresolvable. However, some build tools * like [Webpack](https://webpack.js.org/guides/package-exports/#alternatives) * will evaluate _all_ targets in the fallback array until it encounters one * that exists on the filesystem. Since this behavior deviates from Node.js * and hence "the spec," it is considered _unsafe_. * * Therefore, by default, this function will ignore all but the very first * defined non-null target in a fallback array regardless of if it exists on * the filesystem or not. If no such target is encountered, the final target * in the fallback array is returned regardless of its value. * * Set `includeUnsafeFallbackTargets` to `true` to exhaustively consider _all_ * non-null fallback targets instead, which is a marked deviation from * Node.js's behavior. * * @default false */ includeUnsafeFallbackTargets?: boolean; }; export type ReplaceSubpathAsterisksOption = { /** * When returning a subpath pattern, i.e. a subpath containing an asterisk * ("*"), the asterisks will be replaced by the matching portions of `target` if * `replaceSubpathAsterisks` is `true`. Otherwise, the literal subpath pattern * will be returned with asterisk included. * * Note that, if `target` contains an asterisk, the literal subpath pattern * will always be returned regardless of the value of this option. * * @default true */ replaceSubpathAsterisks?: boolean; }; /** * A single flattened subpath in a `package.json` `exports`/`imports` map along * with its target, matchable conditions, and other metadata. One or more * subpath mappings together form an imports/exports "entry point" or * "specifier". */ export type SubpathMapping = { /** * The subpath that maps to `target`, e.g.: * * @example * ```json * { * "exports": { * "subpath": "target" * } * } * ``` * * If `isSugared` is `true`, `subpath` is * [sugared](https://nodejs.org/api/packages.html#exports-sugar) and thus does * not exist as a property in the actual `package.json` file. `subpath`, if it * contains at most one asterisk ("*"), becomes a [subpath * pattern](https://nodejs.org/docs/latest-v19.x/api/packages.html#subpath-patterns). */ subpath: string; /** * The path to a target file that maps to `subpath`, e.g.: * * @example * ```json * { * "exports": { * "subpath": "target" * } * } * ``` * * Target may also contain one or more asterisks ("*") only if `subpath` is a * [subpath * pattern](https://nodejs.org/docs/latest-v19.x/api/packages.html#subpath-patterns). */ target: string | null; /** * The combination of resolution conditions that, when matched, result in * `subpath` resolving to `target`. Conditions are listed in the order they * are encountered in the map object. * * Note that the "default" condition, while present in `conditions`, may not * actually exist in the actual `package.json` file. */ conditions: string[]; /** * When the subpath mapping is a "default" mapping that occurs after one or * more sibling conditions, it cannot be selected if one of those siblings is * selected first. This property contains those sibling conditions that, if * present, mean this subpath mapping should not be considered. * * Useful when reverse-mapping targets to subpaths. * * @example * ```jsonc * { * "./strange-subpath": { * "default": { * "import": "./import.js", * "node": "./node.js", * "default": "./default.js" // <- Never chosen if "import" is specified * } * } * } * ``` */ excludedConditions: string[]; /** * If `true`, the value of `subpath` was inferred but no corresponding * property exists in the actual `package.json` file. * * @example * ```json * { * "name": "my-package", * "exports": "./is-sugared.js" * } * ``` * * In the above example, `subpath` would be `"."` even though it does not * exist in the actual `package.json` file. * * @see https://nodejs.org/api/packages.html#exports-sugar */ isSugared: boolean; /** * If `true`, `target` is a so-called "fallback target". This means either (1) * `target` is a member of a fallback array or (2) the parent or ancestor * object containing `target` is a member of a fallback array. For example: * * @example * ```json * { * "name": "my-package", * "exports": [ * "./target-is-fallback-1.js", * { * "require": "./target-is-fallback-2.js", * "default": "./target-is-fallback-3.js" * } * ] * } * ``` * * Note that, due to how fallback arrays work, a fallback `target` may not be * reachable in any environment or under any circumstances ever even if all * the conditions match; multiple fallback `target`s might even overlap in * strange ways that are hard to reason about. [Node.js also ignores all but * the first valid defined non-null fallback * target](https://github.com/nodejs/node/blob/a9cdeeda880a56de6dad10b24b3bfa45e2cccb5d/lib/internal/modules/esm/resolve.js#L417-L432). * * **It is for these reasons that fallback arrays should be avoided entirely * in `package.json` files,** especially any sort of complex nested fallback * configurations. They're really only useful for consumption by build tools * like Webpack or TypeScript, and even then their utility is limited. */ isFallback: boolean; /** * When `isFallback` is true, `isFistNonNullFallback` will be `true` if * `target` is the first non-`null` member in the flattened fallback array. */ isFirstNonNullFallback: boolean; /** * When `isFallback` is true, `isLastFallback` will be `true` if `target` is * the last member in the flattened fallback array regardless of value of * `target`. */ isLastFallback: boolean; /** * If `true`, this condition is guaranteed to be impossible to reach, likely * because it occurs after the "default" condition. */ isDeadCondition: boolean; }; /** * A flat array of subpath-target mappings enumerating all potential * `exports`/`imports` entry points within a `package.json` file. */ export type SubpathMappings = SubpathMapping[]; /** * Given `target` and `conditions`, this function returns an array of zero or * more entry points that are guaranteed to resolve to `target` when the exact * `conditions` are active in the runtime. This is done by reverse-mapping * `target` using `exports` from `package.json`. `exports` is assumed to be * valid. * * Entry points are sorted in the order they're encountered with the caveat that * exact subpaths always come before subpath patterns. Note that, if `target` * contains one or more asterisks, the subpaths returned by this function will * also contain an asterisk. The only other time this function returns a subpath * with an asterisk is if the subpath is a "many-to-one" mapping; that is: the * subpath has an asterisk but its target does not. For instance: * * @example * ```json * { * "exports": { * "many-to-one-subpath-returned-with-asterisk-1/*": "target-with-no-asterisk.js", * "many-to-one-subpath-returned-with-asterisk-2/*": null, * } * } * ``` * * In this case, the asterisk can be replaced with literally anything and it * would still match. Hence, the replacement is left up to the caller. */ export declare function resolveEntryPointsFromExportsTarget({ flattenedExports, target, conditions, includeUnsafeFallbackTargets, replaceSubpathAsterisks }: { /** * The target that will be reverse-mapped to zero or more subpaths from the * `package.json` `exports` object. */ target: string | null; } & FlattenedExportsOption & ConditionsOption & UnsafeFallbackOption & ReplaceSubpathAsterisksOption): string[]; /** * Given `entryPoint` and `conditions`, this function returns an array of zero * or more targets that `entryPoint` is guaranteed to resolve to when the exact * `conditions` are active in the runtime. This is done by mapping `entryPoint` * using `exports` from `package.json`. `exports` is assumed to be valid. */ export declare function resolveExportsTargetsFromEntryPoint({ flattenedExports, entryPoint, conditions, includeUnsafeFallbackTargets }: { /** * The entry point that will be mapped to zero or more targets from the * `package.json` `exports` object. */ entryPoint: string; } & FlattenedExportsOption & ConditionsOption & UnsafeFallbackOption): string[]; /** * Given `target` and `conditions`, this function returns an array of zero or * more entry points that are guaranteed to resolve to `target` when the exact * `conditions` are active in the runtime. This is done by reverse-mapping * `target` using `imports` from `package.json`. `imports` is assumed to be * valid. * * Entry points are sorted in the order they're encountered with the caveat that * exact subpaths always come before subpath patterns. Note that, if `target` * contains one or more asterisks, the subpaths returned by this function will * also contain an asterisk. The only other time this function returns a subpath * with an asterisk is if the subpath is a "many-to-one" mapping; that is: the * subpath has an asterisk but its target does not. For instance: * * @example * ```json * { * "imports": { * "many-to-one-subpath-returned-with-asterisk-1/*": "target-with-no-asterisk.js", * "many-to-one-subpath-returned-with-asterisk-2/*": null, * } * } * ``` * * In this case, the asterisk can be replaced with literally anything and it * would still match. Hence, the replacement is left up to the caller. */ export declare function resolveEntryPointsFromImportsTarget({ flattenedImports, target, conditions, includeUnsafeFallbackTargets, replaceSubpathAsterisks }: { /** * The target that will be reverse-mapped to zero or more subpaths from the * `package.json` `imports` object. */ target: string | null; } & FlattenedImportsOption & ConditionsOption & UnsafeFallbackOption & ReplaceSubpathAsterisksOption): string[]; /** * Given `entryPoint` and `conditions`, this function returns an array of zero * or more targets that `entryPoint` is guaranteed to resolve to when the exact * `conditions` are active in the runtime. This is done by mapping `entryPoint` * using `imports` from `package.json`. `imports` is assumed to be valid. */ export declare function resolveImportsTargetsFromEntryPoint({ flattenedImports, entryPoint, conditions, includeUnsafeFallbackTargets }: { /** * The entry point that will be mapped to zero or more targets from the * `package.json` `imports` object. */ entryPoint: string; } & FlattenedImportsOption & ConditionsOption & UnsafeFallbackOption): string[];