'use strict'; var rollupPluginImportMap = require('rollup-plugin-import-map'); var common = require('@eik/common'); var undici = require('undici'); /** * @typedef {object} ImportMap * @property {Record} imports */ /** * @param {string[]} urls * @returns {Promise} */ const fetchImportMaps = async (urls = []) => { try { const maps = urls.map(async (map) => { const { statusCode, body } = await undici.request(map, { maxRedirections: 2, }); if (statusCode === 404) { throw new Error("Import map could not be found on server"); } else if (statusCode >= 400 && statusCode < 500) { throw new Error("Server rejected client request"); } else if (statusCode >= 500) { throw new Error("Server error"); } return /** @type {Promise} */ (body.json()); }); return await Promise.all(maps); } catch (err) { throw new Error( `Unable to load import map file from server: ${err.message}`, ); } }; /** * @typedef {object} PluginOptions * @property {string} [path=process.cwd()] Path to `eik.json`. * @property {string[]} [urls=[]] URLs to import maps hosted on an Eik server. Takes precedence over `eik.json`. * @property {ImportMap[]} [maps=[]] Inline import maps that should be used. Takes precedence over `urls` and `eik.json`. */ /** * @typedef {object} Plugin * @property {string} name * @property {(options?: unknown) => Promise} buildStart * @property {(importee?: string) => string} resolveId */ /** * @param {PluginOptions} options * @returns {Plugin} */ function esmImportToUrl({ path = process.cwd(), maps = [], urls = [], } = {}) { const pMaps = Array.isArray(maps) ? maps : [maps]; const pUrls = Array.isArray(urls) ? urls : [urls]; let plugin; return { name: "eik-rollup-plugin", /** * @this {import('rollup').PluginContext} * @param {unknown} [options] */ async buildStart(options) { // Load eik config from eik.json or package.json const config = await common.helpers.getDefaults(path); this.debug(`Loaded eik config ${JSON.stringify(config, null, 2)}`); // Fetch import maps from the server try { const fetched = await fetchImportMaps([...config.map, ...pUrls]); for (const map of fetched) { this.debug(`Fetched import map ${JSON.stringify(map, null, 2)}`); } plugin = rollupPluginImportMap.rollupImportMapPlugin([...fetched, ...pMaps]); await plugin.buildStart(options); } catch (err) { this.error(err.message); } }, /** * @this {import('rollup').PluginContext} * @param {string} [importee] */ resolveId(importee) { const resolved = plugin.resolveId(importee); if (resolved) { this.debug(`Resolved ${importee} to ${resolved.id}`); } return resolved; }, }; } module.exports = esmImportToUrl;