resolve a path_alias to its absolutely referenced path from an import map entries. if the input path_alias is not a part of the provided import_map_entries, then undefined will be returned.

for further reading on the specifics of what constitutes an import-map, see the documentation of ImportMap.

Tip

why use this function when resolvePathFromImportMap exists?

this function has the potential to be faster if you provide pre-sorted import_map_entries, in addition to also providing configuration options for relative paths.

to understand how configure the behavior of the resolver differently, using the optional config parameter, check out the documentation comments of ResolvePathFromImportMapEntriesConfig. but for a summary, here is the breakdown:

  • config.baseAliasDir: if defined (non-empty string), then the given base directory path will be prepended to all relative path-aliases of your import map entries. however, this will not affect any path-aliases that do not begin with a "./" (i.e. non-relative path-aliases).
  • config.basePathDir: if defined (non-empty string), then the given base directory path will be prepended to the resolved matching path-value if it is a relative path (which is checked via isAbsolutePath).
  • config.sort: specify true (default behavior) if your input import_map_entries is not already sorted alias-length-wise. it is necessary for the import_map_entries to be sorted for the import-map specification-compliant match to be selected. so, if your import map entries are pre-sorted, you can save time by setting this option to false.
  • config.errorCheck: if a path-value match is found for some path_alias, however the alias-path of the entry is directory, but the corresponding path-value is not a directory (i.e. does not end in "/"), then an error will be thrown.
import { assertEquals, assertThrows } from "jsr:@std/assert"

// out export map's entries
const my_export_map_entries = [
[".", "./src/mod.ts"],
["./", "./src/dir/"],
["./hello/abc/", "./src/hello-abc/xyz/"],
["./hello/world/", "./src/hello-world/"],
["./hello", "./src/js/script.ts"],
["./hello/", "./src/hello-greetings/"],
["./alias/dir/", "./incorrect/non-dir/path"],
["postcss", "./node_modules/postcss/main.js"],
["esbuild", "https://registry.npmjs.org/esbuild"],
["kitchensink/", "https://jsr.io/@oazmi/kitchensink/0.9.6/src/"],
] as Array<[alias: string, path: string]>

// aliasing our functions, types, and objects for brevity
type Config = Partial<ResolvePathFromImportMapEntriesConfig>
const
eq = assertEquals,
err = assertThrows,
fn = (path_alias: string, config?: Config) => resolvePathFromImportMapEntries(path_alias, my_export_map_entries, config),
config_1: Config = { baseAliasDir: "jsr:@my-scope/my-lib" },
config_2: Config = { baseAliasDir: "jsr:@my-other/library" },
config_3: Config = { baseAliasDir: "jsr:@my-scope/my-lib/", basePathDir: "http://example.com" },
config_4: Config = { basePathDir: "@scope/lib" }

eq(fn("jsr:@my-scope/my-lib", config_1), "./src/mod.ts")
eq(fn("jsr:@my-scope/my-lib/", config_1), "./src/dir/")
eq(fn("jsr:@my-scope/my-lib/www/robot.txt", config_1), "./src/dir/www/robot.txt")
eq(fn("jsr:@my-scope/my-lib/hello", config_1), "./src/js/script.ts")
eq(fn("jsr:@my-scope/my-lib/hello/js/script.ts", config_1), "./src/hello-greetings/js/script.ts")
eq(fn("jsr:@my-scope/my-lib/hello/world/", config_1), "./src/hello-world/")
eq(fn("jsr:@my-scope/my-lib/hello/world/mod.ts", config_1), "./src/hello-world/mod.ts")
eq(fn("jsr:@my-scope/my-lib/hello/abc/", config_1), "./src/hello-abc/xyz/")
eq(fn("jsr:@my-scope/my-lib/hello/abc/mod.ts", config_1), "./src/hello-abc/xyz/mod.ts")
eq(fn("jsr:@my-scope/my-lib/postcss", config_1), "./src/dir/postcss") // captured by the `"./"` alias
eq(fn("postcss", config_1), "./node_modules/postcss/main.js")
eq(fn("esbuild", config_1), "https://registry.npmjs.org/esbuild")
eq(fn("kitchensink/pathman.ts", config_1), "https://jsr.io/@oazmi/kitchensink/0.9.6/src/pathman.ts")

err(() => fn("jsr:@my-scope/my-lib/alias/dir/", config_1))
err(() => fn("jsr:@my-scope/my-lib/alias/dir/xyz.txt", config_1))

eq(fn("jsr:@my-scope/my-lib", config_2), undefined)

eq(fn("jsr:@my-scope/my-lib", config_3), "http://example.com/src/mod.ts")
eq(fn("jsr:@my-scope/my-lib/", config_3), "http://example.com/src/dir/")
eq(fn("jsr:@my-scope/my-lib/www/robot.txt", config_3), "http://example.com/src/dir/www/robot.txt")
eq(fn("jsr:@my-scope/my-lib/hello", config_3), "http://example.com/src/js/script.ts")
eq(fn("jsr:@my-scope/my-lib/hello/js/script.ts", config_3), "http://example.com/src/hello-greetings/js/script.ts")
eq(fn("jsr:@my-scope/my-lib/hello/world/", config_3), "http://example.com/src/hello-world/")
eq(fn("jsr:@my-scope/my-lib/hello/world/mod.ts", config_3), "http://example.com/src/hello-world/mod.ts")
eq(fn("jsr:@my-scope/my-lib/hello/abc/", config_3), "http://example.com/src/hello-abc/xyz/")
eq(fn("jsr:@my-scope/my-lib/hello/abc/mod.ts", config_3), "http://example.com/src/hello-abc/xyz/mod.ts")
eq(fn("jsr:@my-scope/my-lib/postcss", config_3), "http://example.com/src/dir/postcss")
eq(fn("postcss", config_3), "http://example.com/node_modules/postcss/main.js")
eq(fn("esbuild", config_3), "https://registry.npmjs.org/esbuild")
eq(fn("kitchensink/pathman.ts", config_3), "https://jsr.io/@oazmi/kitchensink/0.9.6/src/pathman.ts")

eq(fn(".", config_4), "@scope/lib/src/mod.ts")
eq(fn("./", config_4), "@scope/lib/src/dir/")
eq(fn("./www/robot.txt", config_4), "@scope/lib/src/dir/www/robot.txt")
eq(fn("./hello", config_4), "@scope/lib/src/js/script.ts")
eq(fn("./hello/js/script.ts", config_4), "@scope/lib/src/hello-greetings/js/script.ts")
eq(fn("./hello/world/", config_4), "@scope/lib/src/hello-world/")
eq(fn("./hello/world/mod.ts", config_4), "@scope/lib/src/hello-world/mod.ts")
eq(fn("./hello/abc/", config_4), "@scope/lib/src/hello-abc/xyz/")
eq(fn("./hello/abc/mod.ts", config_4), "@scope/lib/src/hello-abc/xyz/mod.ts")
eq(fn("./postcss", config_4), "@scope/lib/src/dir/postcss")
eq(fn("postcss", config_4), "@scope/lib/node_modules/postcss/main.js")
eq(fn("esbuild", config_4), "https://registry.npmjs.org/esbuild")
eq(fn("kitchensink/pathman.ts", config_4), "https://jsr.io/@oazmi/kitchensink/0.9.6/src/pathman.ts")

eq(fn("", config_4), "@scope/lib/src/mod.ts")
eq(fn("/", config_4), undefined)
eq(fn("www/robot.txt", config_4), undefined)
eq(fn("hello", config_4), undefined)
eq(fn("hello/js/script.ts", config_4), undefined)
eq(fn("hello/world/", config_4), undefined)
eq(fn("hello/world/mod.ts", config_4), undefined)
eq(fn("hello/abc/", config_4), undefined)
eq(fn("hello/abc/mod.ts", config_4), undefined)
eq(fn("postcss", config_4), "@scope/lib/node_modules/postcss/main.js")
eq(fn("esbuild", config_4), "https://registry.npmjs.org/esbuild")
eq(fn("kitchensink/pathman.ts", config_4), "https://jsr.io/@oazmi/kitchensink/0.9.6/src/pathman.ts")