UNPKG

@jspm/generator

Version:

Package Import Map Generation Tool

363 lines (361 loc) 15.7 kB
function _check_private_redeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } } function _class_apply_descriptor_set(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } } function _class_extract_field_descriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); } function _class_private_field_init(obj, privateMap, value) { _check_private_redeclaration(obj, privateMap); privateMap.set(obj, value); } function _class_private_field_set(receiver, privateMap, value) { var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set"); _class_apply_descriptor_set(receiver, descriptor, value); return value; } function _class_private_method_get(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; } function _class_private_method_init(obj, privateSet) { _check_private_redeclaration(obj, privateSet); privateSet.add(obj); } function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import * as deno from './deno.js'; import * as jspm from './jspm.js'; import * as skypack from './skypack.js'; import * as jsdelivr from './jsdelivr.js'; import * as unpkg from './unpkg.js'; import * as node from './node.js'; import * as esmsh from './esmsh.js'; import { JspmError } from '../common/err.js'; import { isNode } from '../common/env.js'; import { fetch } from '../common/fetch.js'; var _pm = /*#__PURE__*/ new WeakMap(); /** * Context provided to all provider methods * Contains necessary services and configuration */ export class ProviderContext { constructor(pm, log, fetchOpts){ /** * Logger instance for provider operations */ _define_property(this, "log", void 0); /** * Fetch options for provider operations */ _define_property(this, "fetchOpts", void 0); /** * Custom context object for providers */ _define_property(this, "context", void 0); _class_private_field_init(this, _pm, { writable: true, value: void 0 }); _class_private_field_set(this, _pm, pm); this.log = log; this.fetchOpts = fetchOpts; this.context = {}; } } var _getProviderContext = /*#__PURE__*/ new WeakSet(), /** * Get a provider by name * * @param name Name of the provider * @returns The provider instance */ _getProvider = /*#__PURE__*/ new WeakSet(), /** * Configure all providers with the given configuration * * @param providerConfig Configuration for providers */ _configure = /*#__PURE__*/ new WeakSet(); /** * Provider manager to handle provider registration, lookup and operations */ export class ProviderManager { /** * Add a custom provider to this provider manager * * @param name Name of the provider * @param provider Provider implementation */ addProvider(name, provider) { if (!provider.pkgToUrl) throw new Error(`Custom provider "${name}" must define a "pkgToUrl" method.`); if (!provider.parseUrlPkg) throw new Error(`Custom provider "${name}" must define a "parseUrlPkg" method.`); if (!provider.resolveLatestTarget) throw new Error(`Custom provider "${name}" must define a "resolveLatestTarget" method.`); this.providers[name] = provider; } /** * Find the provider name for a given URL * * @param url URL to find the provider for * @returns The name of the provider, or null if no provider handles this URL */ providerNameForUrl(url) { for (const name of Object.keys(this.providers).reverse()){ const provider = this.providers[name]; const context = _class_private_method_get(this, _getProviderContext, getProviderContext).call(this, name); if (provider.ownsUrl && provider.ownsUrl.call(context, url) || provider.parseUrlPkg.call(context, url)) { return name; } } return null; } /** * Parse a URL to get package information * * @param url URL to parse * @returns Package information or null if URL can't be parsed */ parseUrlPkg(url) { for (const provider of Object.keys(this.providers).reverse()){ const providerInstance = this.providers[provider]; const context = _class_private_method_get(this, _getProviderContext, getProviderContext).call(this, provider); const result = providerInstance.parseUrlPkg.call(context, url); if (result) return { pkg: 'pkg' in result ? result.pkg : result, source: { provider, layer: 'layer' in result ? result.layer : 'default' }, subpath: 'subpath' in result ? result.subpath : null }; } return null; } /** * Convert a package to a URL * * @param pkg Package to convert * @param provider Provider name * @param layer Layer to use * @returns URL for the package */ pkgToUrl(pkg, provider, layer = 'default') { return _class_private_method_get(this, _getProvider, getProvider).call(this, provider).pkgToUrl.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, provider), pkg, layer); } /** * Get the package config corresponding to a package URL * * @param pkgUrl URL to the package * @returns */ async getPackageConfig(pkgUrl) { const name = this.providerNameForUrl(pkgUrl); if (name) { var _class_private_method_get_call_getPackageConfig; const pcfg = await ((_class_private_method_get_call_getPackageConfig = _class_private_method_get(this, _getProvider, getProvider).call(this, name).getPackageConfig) === null || _class_private_method_get_call_getPackageConfig === void 0 ? void 0 : _class_private_method_get_call_getPackageConfig.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, name), pkgUrl)); return pcfg || null; } } /** * Obtain a file listing of a package boundary if available */ async getFileList(pkgUrl) { if (!pkgUrl.endsWith('/')) pkgUrl += '/'; const name = this.providerNameForUrl(pkgUrl); if (name) { var _class_private_method_get_call_getFileList; const fileList = await ((_class_private_method_get_call_getFileList = _class_private_method_get(this, _getProvider, getProvider).call(this, name).getFileList) === null || _class_private_method_get_call_getFileList === void 0 ? void 0 : _class_private_method_get_call_getFileList.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, name), pkgUrl)); return fileList || undefined; } // if we don't have a provider, and we are on the local filesystem, verify there // is a package.json and do a glob excluding node_modules if (isNode && pkgUrl.startsWith('file:') || pkgUrl.startsWith('https:')) { const fileList = new Set(); async function walk(path, basePath) { try { const res = await fetch(path); if (res.status === 200) { fileList.add(path.slice(basePath.length)); } else if (res.status === 204) { if (!path.endsWith('/')) path += '/'; const dirListing = await res.json(); for (const entry of dirListing){ if (entry === 'node_modules' || entry === '.git') continue; await walk(path + entry, basePath); } } } catch (e) { throw new JspmError(`Unable to read package ${path} - ${e.toString()}`); } } await walk(pkgUrl, pkgUrl); return fileList; } } /** * Resolve a builtin module * * @param specifier Module specifier * @returns Resolved string, install object, or undefined if not resolvable */ resolveBuiltin(specifier, env) { for (const [name, provider] of Object.entries(this.providers).reverse()){ if (!provider.resolveBuiltin) continue; const context = _class_private_method_get(this, _getProviderContext, getProviderContext).call(this, name); const builtin = provider.resolveBuiltin.call(context, specifier, env); if (builtin) return builtin; } return undefined; } async resolveLatestTarget(target, { provider, layer }, parentUrl, resolver) { // find the range to resolve latest let range; for (const possibleRange of target.ranges.sort(target.ranges[0].constructor.compare)){ if (!range) { range = possibleRange; } else if (possibleRange.gt(range) && !range.contains(possibleRange)) { range = possibleRange; } } const latestTarget = { registry: target.registry, name: target.name, range, unstable: target.unstable }; const resolveLatestTarget = _class_private_method_get(this, _getProvider, getProvider).call(this, provider).resolveLatestTarget; const pkg = await resolveLatestTarget.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, provider), latestTarget, layer, parentUrl, resolver); if (pkg) return pkg; if (provider === 'nodemodules') { throw new JspmError(`Cannot find package ${target.name} in node_modules from parent ${parentUrl}. Try installing "${target.name}" with npm first adding it to package.json "dependencies" or running "npm install --save ${target.name}".`); } else { throw new JspmError(`Unable to resolve package ${latestTarget.registry}:${latestTarget.name} in range "${latestTarget.range}" from parent ${parentUrl}.`); } } /** * Get the supported provider strings for all providers * * @returns List of provider string identifiers */ getProviderStrings() { let res = []; for (const [name, provider] of Object.entries(this.providers)){ var _provider_supportedLayers; for (const layer of (_provider_supportedLayers = provider.supportedLayers) !== null && _provider_supportedLayers !== void 0 ? _provider_supportedLayers : [ 'default' ])res.push(`${name}${layer === 'default' ? '' : `#${layer}`}`); } return res; } /** * Downloads the given package files into the local folder path outDir * Does not include the import map, which must be merged separately. */ download(pkg, providerName) { const provider = _class_private_method_get(this, _getProvider, getProvider).call(this, providerName); if (!provider.download) { throw new JspmError(`Provider "${providerName}" does not currently support publishing from JSPM`); } return provider.download.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, providerName), pkg); } async publish(pkg, providerName, imports, files, importMap) { const provider = _class_private_method_get(this, _getProvider, getProvider).call(this, providerName); if (!provider.publish) { throw new JspmError(`Provider "${providerName}" does not support publishing on JSPM`); } return provider.publish.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, providerName), pkg, files, importMap, imports); } /** * Authenticate with a provider to obtain an authentication token * * @param providerName Name of the provider to authenticate with * @param options Authentication options * @returns Promise resolving to the authentication token */ async auth(providerName, options = {}) { const provider = _class_private_method_get(this, _getProvider, getProvider).call(this, providerName); if (!provider.auth) { throw new JspmError(`Provider "${providerName}" does not support authentication`); } return provider.auth.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, providerName), options); } /** * Create a new ProviderManager with the given providers * * @param customProviders Custom provider definitions to add */ constructor(log, fetchOpts, providerConfig = {}, customProviders = {}){ _class_private_method_init(this, _getProviderContext); _class_private_method_init(this, _getProvider); _class_private_method_init(this, _configure); _define_property(this, "log", void 0); _define_property(this, "fetchOpts", void 0); _define_property(this, "providers", void 0); _define_property(this, "contexts", void 0); this.log = log; this.fetchOpts = fetchOpts; this.contexts = {}; this.providers = { ...defaultProviders }; for (const [name, provider] of Object.entries(customProviders)){ this.addProvider(name, provider); } _class_private_method_get(this, _configure, configure).call(this, providerConfig); } } function getProviderContext(name) { return this.contexts[name] || (this.contexts[name] = new ProviderContext(this, this.log, this.fetchOpts)); } function getProvider(name) { const provider = this.providers[name]; if (provider) return provider; throw new JspmError(`No provider named "${name}" has been defined.`); } function configure(providerConfig) { for (const [providerName, provider] of Object.entries(this.providers)){ if (provider.configure) { provider.configure.call(_class_private_method_get(this, _getProviderContext, getProviderContext).call(this, providerName), providerConfig[providerName] || {}); } } } export const defaultProviders = { deno, jsdelivr, node, skypack, unpkg, 'esm.sh': esmsh, 'jspm.io': jspm }; export function getDefaultProviderStrings() { let res = []; for (const [name, provider] of Object.entries(defaultProviders)){ var _provider_supportedLayers; for (const layer of (_provider_supportedLayers = provider.supportedLayers) !== null && _provider_supportedLayers !== void 0 ? _provider_supportedLayers : [ 'default' ])res.push(`${name}${layer === 'default' ? '' : `#${layer}`}`); } return res; } export const registryProviders = { 'denoland:': 'deno', 'deno:': 'deno' }; export const mappableSchemes = new Set([ 'npm', 'deno', 'node' ]); export const builtinSchemes = new Set([ 'node', 'deno' ]); //# sourceMappingURL=index.js.map