UNPKG

piral-cli

Version:

The standard CLI for creating and building a Piral instance or a Pilet.

258 lines • 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.readImportmap = readImportmap; const path_1 = require("path"); const log_1 = require("./log"); const version_1 = require("./version"); const hash_1 = require("./hash"); const io_1 = require("./io"); const npm_1 = require("./npm"); const shorthandsUrls = ['', '.', '...']; function addLocalDependencies(dependencies, realIdentifier, identifier, version, requireVersion, entry, assetName, isAsync) { const alias = realIdentifier !== identifier ? realIdentifier : undefined; dependencies.push({ id: `${identifier}@${version}`, requireId: `${identifier}@${requireVersion}`, entry, name: identifier, ref: `${assetName}.js`, type: 'local', alias, isAsync, }); } function getAnyPatch(version) { const [major, minor] = version.split('.'); return `~${major}.${minor}.0`; } function getMatchMajor(version) { const [major] = version.split('.'); return `^${major}.0.0`; } function makeAssetName(id) { return (id.startsWith('@') ? id.substring(1) : id).replace(/[\/\.]/g, '-').replace(/(\-)+/, '-'); } function getDependencyDetails(depName, availableSpecs) { const name = depName.replace(/\?+$/, ''); const isAsync = depName.endsWith('?'); const sep = name.indexOf('@', 1); if (sep > 0) { const id = name.substring(0, sep); const version = name.substring(sep + 1); const assetName = makeAssetName(id); return [assetName, id, version, isAsync]; } else { const version = availableSpecs[name] || ''; const assetName = makeAssetName(name); return [assetName, name, version, isAsync]; } } async function getLocalDependencyVersion(packageJson, depName, versionSpec, versionBehavior) { const packageDir = (0, path_1.dirname)(packageJson); const packageFile = (0, path_1.basename)(packageJson); const details = await (0, io_1.readJson)(packageDir, packageFile); if (versionSpec) { if (!(0, version_1.validate)(versionSpec)) { (0, log_1.fail)('importMapVersionSpecInvalid_0026', depName); } if (!(0, version_1.satisfies)(details.version, versionSpec)) { (0, log_1.fail)('importMapVersionSpecNotSatisfied_0025', depName, details.version, versionSpec); } return [details.name, details.version, versionSpec]; } switch (versionBehavior) { case 'all': return [details.name, details.version, '*']; case 'match-major': return [details.name, details.version, getMatchMajor(details.version)]; case 'any-patch': return [details.name, details.version, getAnyPatch(details.version)]; case 'exact': default: return [details.name, details.version, details.version]; } } async function getInheritedDependencies(inheritedImport, dir, excludedDependencies, inheritanceBehavior) { const packageJson = (0, npm_1.tryResolvePackage)(`${inheritedImport}/package.json`, dir); if (packageJson) { const packageDir = (0, path_1.dirname)(packageJson); const packageDetails = await (0, io_1.readJson)(packageDir, 'package.json'); return await consumeImportmap(packageDir, packageDetails, true, 'exact', inheritanceBehavior, excludedDependencies); } else { const directImportmap = (0, npm_1.tryResolvePackage)(inheritedImport, dir); if (directImportmap) { const baseDir = (0, path_1.dirname)(directImportmap); const content = await (0, io_1.readJson)(baseDir, (0, path_1.basename)(directImportmap)); return await resolveImportmap(baseDir, content, { availableSpecs: {}, inheritanceBehavior, excludedDependencies, ignoreFailure: true, versionBehavior: 'exact', }); } } return []; } async function resolveImportmap(dir, importmap, options) { const dependencies = []; const sharedImports = importmap?.imports; const inheritedImports = importmap?.inherit; const excludedImports = importmap?.exclude; const onUnresolved = (name, version) => { if (options.ignoreFailure) { const id = version ? `${name}@${version}` : name; (0, log_1.log)('skipUnresolvedDependency_0054', id); } else { (0, log_1.fail)('importMapReferenceNotFound_0027', dir, name); } }; if (typeof sharedImports === 'object' && sharedImports) { for (const depName of Object.keys(sharedImports)) { const url = sharedImports[depName]; const [assetName, identifier, versionSpec, isAsync] = getDependencyDetails(depName, options.availableSpecs); if (options.excludedDependencies.includes(identifier)) { continue; } else if (typeof url !== 'string') { (0, log_1.log)('generalInfo_0000', `The value of "${depName}" in the importmap is not a string and will be ignored.`); } else if (/^https?:\/\//.test(url)) { const hash = (0, hash_1.computeHash)(url).substring(0, 7); dependencies.push({ id: `${identifier}@${hash}`, requireId: `${identifier}@${hash}`, entry: url, name: identifier, ref: url, type: 'remote', isAsync, }); } else if (url === identifier || shorthandsUrls.includes(url)) { const entry = (0, npm_1.tryResolvePackage)(identifier, dir); if (entry) { const packageJson = await (0, io_1.findFile)((0, path_1.dirname)(entry), 'package.json'); const [realIdentifier, version, requireVersion] = await getLocalDependencyVersion(packageJson, depName, versionSpec, options.versionBehavior); addLocalDependencies(dependencies, realIdentifier, identifier, version, requireVersion, entry, assetName, isAsync); } else { onUnresolved(identifier, versionSpec); } } else if (!url.startsWith('.') && !(0, path_1.isAbsolute)(url)) { const entry = (0, npm_1.tryResolvePackage)(url, dir); if (entry) { const packageJson = await (0, io_1.findFile)((0, path_1.dirname)(entry), 'package.json'); const [realIdentifier, version, requireVersion] = await getLocalDependencyVersion(packageJson, depName, versionSpec, options.versionBehavior); addLocalDependencies(dependencies, realIdentifier, identifier, version, requireVersion, entry, assetName, isAsync); } else { onUnresolved(url, versionSpec); } } else { const entry = (0, path_1.resolve)(dir, url); const exists = await (0, io_1.checkExists)(entry); if (exists) { const isDirectory = await (0, io_1.checkIsDirectory)(entry); const packageJson = isDirectory ? (0, path_1.resolve)(entry, 'package.json') : await (0, io_1.findFile)((0, path_1.dirname)(entry), 'package.json'); const packageJsonExists = await (0, io_1.checkExists)(packageJson); if (packageJsonExists) { const [realIdentifier, version, requireVersion] = await getLocalDependencyVersion(packageJson, depName, versionSpec, options.versionBehavior); addLocalDependencies(dependencies, realIdentifier, identifier, version, requireVersion, isDirectory ? (0, npm_1.tryResolvePackage)(entry, dir) : entry, assetName, isAsync); } else if (isDirectory) { onUnresolved(entry, versionSpec); } else { const hash = await (0, io_1.getHash)(entry); dependencies.push({ id: `${identifier}@${hash}`, requireId: `${identifier}@${hash}`, entry, name: identifier, ref: `${assetName}.js`, type: 'local', isAsync, }); } } else { onUnresolved(url, versionSpec); } } } } if (Array.isArray(inheritedImports)) { const includedImports = [...options.excludedDependencies, ...dependencies.map((m) => m.name)]; const excluded = Array.isArray(excludedImports) ? [...includedImports, ...excludedImports] : includedImports; for (const inheritedImport of inheritedImports) { const otherDependencies = await getInheritedDependencies(inheritedImport, dir, excluded, options.inheritanceBehavior); for (const dependency of otherDependencies) { const entry = dependencies.find((dep) => dep.name === dependency.name); if (!entry) { dependencies.push({ ...dependency, parents: [inheritedImport], }); } else if (Array.isArray(entry.parents)) { entry.parents.push(inheritedImport); } } } } return dependencies; } async function consumeImportmap(dir, packageDetails, inherited, versionBehavior, mode, excludedDependencies) { const importmap = packageDetails.importmap; const appShell = inherited && mode === 'remote'; const availableSpecs = appShell ? packageDetails.devDependencies ?? {} : {}; const inheritanceBehavior = appShell ? 'host' : mode; if (typeof importmap === 'string') { const notFound = {}; const content = await (0, io_1.readJson)(dir, importmap, notFound); if (content === notFound) { (0, log_1.fail)('importMapFileNotFound_0028', dir, importmap); } const baseDir = (0, path_1.dirname)((0, path_1.resolve)(dir, importmap)); return await resolveImportmap(baseDir, content, { availableSpecs, ignoreFailure: inherited, excludedDependencies, versionBehavior, inheritanceBehavior, }); } else if (typeof importmap === 'undefined' && inherited) { // Fall back to sharedDependencies or pilets.external if available const shared = packageDetails.sharedDependencies ?? packageDetails.pilets?.externals; if (Array.isArray(shared)) { return shared.map((dep) => ({ id: dep, name: dep, entry: dep, type: 'local', ref: undefined, requireId: dep, })); } } return await resolveImportmap(dir, importmap, { availableSpecs, excludedDependencies, ignoreFailure: inherited, versionBehavior, inheritanceBehavior, }); } function readImportmap(dir, packageDetails, versionBehavior = 'exact', inheritanceBehavior = 'remote') { return consumeImportmap(dir, packageDetails, false, versionBehavior, inheritanceBehavior, []); } //# sourceMappingURL=importmap.js.map