@jsenv/import-map
Version:
Helpers to implement importmaps.
140 lines (117 loc) • 3.3 kB
JavaScript
import { assertImportMap } from "./internal/assertImportMap.js"
import { tryUrlResolution } from "./internal/tryUrlResolution.js"
import { resolveSpecifier } from "./resolveSpecifier.js"
import { sortImports, sortScopes } from "./sortImportMap.js"
export const normalizeImportMap = (importMap, baseUrl) => {
assertImportMap(importMap)
if (!isStringOrUrl(baseUrl)) {
throw new TypeError(formulateBaseUrlMustBeStringOrUrl({ baseUrl }))
}
const { imports, scopes } = importMap
return {
imports: imports ? normalizeMappings(imports, baseUrl) : undefined,
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined,
}
}
const isStringOrUrl = (value) => {
if (typeof value === "string") {
return true
}
if (typeof URL === "function" && value instanceof URL) {
return true
}
return false
}
const normalizeMappings = (mappings, baseUrl) => {
const mappingsNormalized = {}
Object.keys(mappings).forEach((specifier) => {
const address = mappings[specifier]
if (typeof address !== "string") {
console.warn(
formulateAddressMustBeAString({
address,
specifier,
}),
)
return
}
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier
const addressUrl = tryUrlResolution(address, baseUrl)
if (addressUrl === null) {
console.warn(
formulateAdressResolutionFailed({
address,
baseUrl,
specifier,
}),
)
return
}
if (specifier.endsWith("/") && !addressUrl.endsWith("/")) {
console.warn(
formulateAddressUrlRequiresTrailingSlash({
addressUrl,
address,
specifier,
}),
)
return
}
mappingsNormalized[specifierResolved] = addressUrl
})
return sortImports(mappingsNormalized)
}
const normalizeScopes = (scopes, baseUrl) => {
const scopesNormalized = {}
Object.keys(scopes).forEach((scopeSpecifier) => {
const scopeMappings = scopes[scopeSpecifier]
const scopeUrl = tryUrlResolution(scopeSpecifier, baseUrl)
if (scopeUrl === null) {
console.warn(
formulateScopeResolutionFailed({
scope: scopeSpecifier,
baseUrl,
}),
)
return
}
const scopeValueNormalized = normalizeMappings(scopeMappings, baseUrl)
scopesNormalized[scopeUrl] = scopeValueNormalized
})
return sortScopes(scopesNormalized)
}
const formulateBaseUrlMustBeStringOrUrl = ({ baseUrl }) => `baseUrl must be a string or an url.
--- base url ---
${baseUrl}`
const formulateAddressMustBeAString = ({ specifier, address }) => `Address must be a string.
--- address ---
${address}
--- specifier ---
${specifier}`
const formulateAdressResolutionFailed = ({
address,
baseUrl,
specifier,
}) => `Address url resolution failed.
--- address ---
${address}
--- base url ---
${baseUrl}
--- specifier ---
${specifier}`
const formulateAddressUrlRequiresTrailingSlash = ({
addressURL,
address,
specifier,
}) => `Address must end with /.
--- address url ---
${addressURL}
--- address ---
${address}
--- specifier ---
${specifier}`
const formulateScopeResolutionFailed = ({ scope, baseUrl }) => `Scope url resolution failed.
--- scope ---
${scope}
--- base url ---
${baseUrl}`