UNPKG

@aem-vite/import-rewriter

Version:

Dynamic imports transformer and CSS path rewriter for Vite when using Adobe Experience Manager

207 lines (202 loc) 9.46 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/bundles.ts var _esmodulelexer = require('es-module-lexer'); var _magicstring = require('magic-string'); var _magicstring2 = _interopRequireDefault(_magicstring); // src/helpers.ts var _debug2 = require('debug'); var _debug3 = _interopRequireDefault(_debug2); var _crypto = require('crypto'); var _fs = require('fs'); var _path = require('path'); var entryPaths = /* @__PURE__ */ new Set(); var debug = _debug3.default.call(void 0, "aem-vite-import-rewriter"); var relativePathPattern = /([.]{1,2}\/)+/; function getEntryPaths() { return entryPaths; } function setEntryPath(path) { entryPaths.add(path); } function generateChecksum(source) { return _crypto.createHash.call(void 0, "md5").update(source, "utf8").digest("hex"); } function getCacheKey(entryPath, keyFormat) { let keyFormatString = ""; switch (keyFormat) { case "cloud": keyFormatString = "lc-%s-lc.%m"; break; case "acs-classic": keyFormatString = "%s.%m"; break; case "acs-modern": keyFormatString = "%m.ACSHASH%s"; break; default: if (typeof keyFormat === "object" && keyFormat.type === "custom" && keyFormat.format) { keyFormatString = keyFormat.format; } else { throw new Error(`Invalid key format provided: ${keyFormat}`); } } const combinedContents = [...entryPaths].map((entry) => { const path = _path.join.call(void 0, entryPath, entry); return _fs.existsSync.call(void 0, path) ? _fs.readFileSync.call(void 0, path).toString() : ""; }); return keyFormatString.replace("%s", generateChecksum(combinedContents.join(""))); } function getAemClientLibPath(options, forImport = false, withChecksum = false, rollupOptions) { let path = options.publicPath; if (forImport) { return `${path}/${options.resourcesPath}/`; } if (withChecksum && options.caching && options.caching.enabled && rollupOptions !== void 0) { const entryPath = rollupOptions.dir; path = `${path}.${getCacheKey(entryPath, options.caching.keyFormat)}`; path = path.replace(".%m", options.minify === true ? ".min" : ""); } return `${path}.js`; } function getReplacementPath(parentPath, path, options, entryAliases) { const isEntryPath = entryPaths.has(parentPath); if (isEntryPath) { return path.replace(new RegExp(`^${relativePathPattern.source}`), getAemClientLibPath(options, true)); } return isInputAnEntryAlias(path, entryAliases) ? path.replace( new RegExp(`${relativePathPattern.source}${path.replace(relativePathPattern, "")}`), getAemClientLibPath(options) ) : path; } function isInputAnEntryAlias(input, entryAliases) { const entryAliasesExpr = new RegExp(`^[./]+(${Object.keys(entryAliases).join("|")})\\.js$`); return !!_optionalChain([RegExp, 'call', _ => _(entryAliasesExpr), 'access', _2 => _2.exec, 'call', _3 => _3(input), 'optionalAccess', _4 => _4[0]]); } // src/bundles.ts function bundlesImportRewriter(options) { const entryAliases = {}; return { apply: "build", enforce: "post", name: "aem-vite:import-rewriter", configResolved(config) { const inputs = config.build.rollupOptions.input; if (!inputs || typeof inputs !== "object" || Array.isArray(inputs)) { throw new Error( "Missing valid input aliases which are required to map to an AEM ClientLib path, see https://www.aemvite.dev/guide/front-end/vite/#source-structure for more information." ); } for (const [key, value] of Object.entries(inputs)) { if (/(ts|js)x?$/.test(value)) { entryAliases[key] = value; } } if (Object.keys(entryAliases).length > 1) { throw new Error( "Invalid number of JavaScript inputs provided. Only a single input is currently supported which is a limitation of AEM ClientLibs. It is recommended to create a second ClientLib and Vite config if you need to meet this need." ); } }, async renderChunk(source, chunk, rollupOptions) { if (rollupOptions.format !== "es") { return null; } if (!_optionalChain([options, 'optionalAccess', _5 => _5.publicPath, 'access', _6 => _6.length])) { this.error( `'publicPath' doesn't appear to be defined, see https://aemvite.dev/guide/faqs/#vite-errors for more information.` ); } if (chunk.isEntry && chunk.facadeModuleId && /(ts|js)x?$/.test(chunk.facadeModuleId)) { debug("setting new entry path: %s\n", chunk.fileName); setEntryPath(chunk.fileName); } await _esmodulelexer.init; let imports = []; try { imports = _esmodulelexer.parse.call(void 0, source)[0]; } catch (e) { this.error({ ...e }); } if (!imports.length) { return null; } let s; const str = () => s || (s = new (0, _magicstring2.default)(source)); for (const element of imports) { const { e: end, d: dynamicIndex, n: importPath, s: start } = element; if (dynamicIndex === -1 && importPath && relativePathPattern.test(importPath)) { const replacementPath = getReplacementPath(chunk.fileName, importPath, options, entryAliases); debug("(render chunk)"); debug("chunk file name: %s", chunk.fileName); debug("import path: %s", importPath); debug("updated import path: %s\n", replacementPath); str().overwrite(start, end, replacementPath); } } if (s) { return { code: s.toString(), map: rollupOptions.sourcemap !== false ? s.generateMap({ hires: true }) : null }; } return null; }, async generateBundle(rollupOptions, output, isWrite) { const aemClientLibPath = getAemClientLibPath(options); debug("(generate bundle)"); debug("aem clientlib path: %s", aemClientLibPath); debug("is write: %s", isWrite); for (const [fileName, chunk] of Object.entries(output)) { if (chunk.type !== "chunk" || !chunk.imports) { continue; } debug("(generate bundle)"); debug("bundle name: %s", fileName); const source = chunk.code; await _esmodulelexer.init; let imports = []; try { imports = _esmodulelexer.parse.call(void 0, source)[0]; } catch (e) { this.error({ ...e }); } if (!imports.length) { continue; } let s; const str = () => s || (s = new (0, _magicstring2.default)(source)); for (const element of imports) { const { e: end, d: dynamicIndex, n: importPath, s: start } = element; if (dynamicIndex === -1 && importPath && relativePathPattern.test(importPath)) { const replacementPath = getReplacementPath(chunk.fileName, importPath, options, entryAliases); debug("chunk file name: %s", chunk.fileName); debug("import type: native"); debug("import path: %s\n", importPath); str().overwrite(start, end, replacementPath); } if (dynamicIndex > -1 && importPath) { debug("chunk file name: %s", chunk.fileName); debug("import type: dynamic"); debug("import path: %s", importPath); const dynamicEnd = source.indexOf(")", end) + 1; const original = source.slice(dynamicIndex + 8, dynamicEnd - 2); debug("updated import path: %s\n", getReplacementPath(chunk.fileName, importPath, options, entryAliases)); if (!original.startsWith("/")) { str().overwrite(start + 1, end - 1, getReplacementPath(chunk.fileName, importPath, options, entryAliases)); } } } let aemImportPath = aemClientLibPath; let newSource = _nullishCoalesce(_optionalChain([s, 'optionalAccess', _7 => _7.toString, 'call', _8 => _8()]), () => ( source)); if (options.caching && options.caching.enabled) { aemImportPath = getAemClientLibPath(options, false, true, rollupOptions); } newSource = newSource.replace(new RegExp(aemClientLibPath, "g"), aemImportPath); const relativeClientLibPath = aemImportPath.substring(aemImportPath.lastIndexOf("/") + 1); getEntryPaths().forEach((path) => { newSource = newSource.replace(new RegExp(path, "g"), relativeClientLibPath); }); chunk.code = newSource; chunk.map = rollupOptions.sourcemap !== false ? s.generateMap({ hires: true }) : null; } } }; } exports.bundlesImportRewriter = bundlesImportRewriter;