UNPKG

@omnia/tooling-vue

Version:

Used to bundle and serve manifests web component that build on Vue framework.

340 lines (339 loc) • 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildFileGraph = exports.buildFileGraphs = exports.toModuleId = exports.toFileGraphId = exports.getFileGraph = void 0; const tslib_1 = require("tslib"); const fs_1 = tslib_1.__importDefault(require("fs")); const path_1 = tslib_1.__importDefault(require("path")); const vite_1 = require("vite"); const fx_models_1 = require("@omnia/fx-models"); const utils_1 = require("./utils"); const manifest_1 = require("./manifest"); const vueJsx_1 = require("./vueJsx"); const $ = tslib_1.__importStar(require("../../variables")); let fileGraphs = {}; let manifests = {}; const initialManifests = [ fx_models_1.OmniaResourceManifests.Vendor.toString(), fx_models_1.OmniaResourceManifests.FxCore.toString(), fx_models_1.OmniaResourceManifests.FxWorkers.toString() ]; const esbuildTransformOptions = { target: 'es2022', jsx: 'preserve', sourcemap: false, legalComments: 'inline' }; function getFileGraph(unknownId) { const id = toFileGraphId(unknownId); return fileGraphs[id]; } exports.getFileGraph = getFileGraph; function toFileGraphId(unknownId) { let id = unknownId; if (utils_1.pathUtils.isTsPath(id)) { id = utils_1.pathUtils.resolveTsPath(id); } if (path_1.default.isAbsolute(id)) { return '.' + (0, vite_1.normalizePath)(id.replace((0, vite_1.normalizePath)(utils_1.envUtils.getRootDirPath()), '')); } if (id.startsWith('/')) { return '.' + id; } return id; } exports.toFileGraphId = toFileGraphId; function toModuleId(unknownId) { let id = unknownId; if (utils_1.pathUtils.isTsPath(id)) { id = utils_1.pathUtils.resolveTsPath(id); } if (path_1.default.isAbsolute(id)) { return (0, vite_1.normalizePath)(id.replace((0, vite_1.normalizePath)(utils_1.envUtils.getRootDirPath()), '')); } if (id.startsWith('./')) { return id.substring(1); } return id; } exports.toModuleId = toModuleId; async function buildFileGraphs(entries) { fileGraphs = {}; manifests = {}; const graph = {}; // external manifests const omniaPackageDependencies = utils_1.manifestUtils.getExternalManifestReferences().slice() .filter(packageManifest => packageManifest.isVendor == false) .map(packageManifest => { const exportModules = Object.keys(packageManifest.content) .filter(filePath => utils_1.pathUtils.isNodeModulePath(filePath)) .map(filePath => filePath.endsWith('index.js') ? filePath.substr(0, filePath.lastIndexOf('/')).replace('./node_modules/', '') : filePath.replace('./node_modules/', '').replace('.js', '')); // fix @omnia/fx/models if (exportModules.indexOf('@omnia/fx-models') > -1) { exportModules.push('@omnia/fx/models'); } return { serviceId: packageManifest.serviceId, resourceId: packageManifest.resourceId, exportModules: exportModules }; }); // pre-bundle manifests await buildPreBundledGraphs(); // local manifests await Object.keys(entries).reduce(async (prevPromise, entryName) => { await prevPromise; const parts = entryName.split('_'); const resourceId = parts.length > 1 ? parts[1] : parts[0]; const entryPaths = entries[entryName].filter(entryFile => utils_1.pathUtils.isSourceCodePath(entryFile)); const dependencies = entries[entryName].slice(); const buildDependencyGraphPromises = entryPaths.reduce(async (prevSubPromise, entryFile) => { await prevSubPromise; return await buildFileGraphRecursive(entryFile, dependencies, true, resourceId); }, Promise.resolve()); await buildDependencyGraphPromises; graph[entryName] = dependencies; manifests[resourceId] = { entryName: entryName, entryPaths: entryPaths, dependingOnManifests: [], }; }, Promise.resolve()); const runtimeCodeGraph = graph; // skip empty files Object.keys(runtimeCodeGraph).forEach(entryName => { runtimeCodeGraph[entryName] = runtimeCodeGraph[entryName].filter(fileGraphId => { const sourceFile = fileGraphs[fileGraphId]; if (sourceFile) { return !sourceFile.js || !sourceFile.js.empty; } return true; }); }); // add manifest dependency with each others Object.keys(manifests).forEach((resourceId, _, allResourceIds) => { const manifest = manifests[resourceId]; const depFilePaths = runtimeCodeGraph[manifest.entryName]; if (initialManifests.indexOf(resourceId) > -1) { return; } const internalManifests = allResourceIds.filter(depResourceId => { const depedingOnManifest = manifests[depResourceId]; return resourceId != depResourceId && depedingOnManifest.entryPaths.some(entryPath => depFilePaths.indexOf(entryPath) > -1); }).map(depResourceId => ({ resourceId: depResourceId, serviceId: $.tooling.composer.getServiceId() })); const externalManifests = omniaPackageDependencies.filter(omniaPackageDependency => { return resourceId != omniaPackageDependency.resourceId && omniaPackageDependency.exportModules.some(modulePath => depFilePaths.indexOf(modulePath) > -1); }).map(omniaPackageDependency => ({ resourceId: omniaPackageDependency.resourceId, serviceId: omniaPackageDependency.serviceId })); manifest.dependingOnManifests = [ ...internalManifests, ...externalManifests ]; }); // set resource id for each files Object.keys(fileGraphs).forEach(fileGraphId => { const fileGraph = fileGraphs[fileGraphId]; setResourceIdForFileGraph(fileGraph); }); return manifests; } exports.buildFileGraphs = buildFileGraphs; async function buildFileGraph(unknownId, code) { const id = toFileGraphId(unknownId); const fileGraph = ensureFileGraph(id, false, undefined); if (!fileGraph.js) { return { fileGraph, code }; } fileGraph.js.scanned = true; const esbuildTransformResult = await (0, vite_1.transformWithEsbuild)(code, id, esbuildTransformOptions); code = esbuildTransformResult.code; // d.ts or interface only if (!esbuildTransformResult.code) { fileGraph.js.empty = true; return { fileGraph, code, esbuildTransformResult }; } if (id.endsWith('.tsx')) { code = await (0, vueJsx_1.transformVueJsx)(code, id); } fileGraph.js.metadata = utils_1.moduleAnalysis.analyze(code, id); ensureDependencies(id, fileGraph.js.metadata); return { fileGraph, code, esbuildTransformResult }; } exports.buildFileGraph = buildFileGraph; async function buildFileGraphRecursive(id, manifestDependencies, entry, resourceId) { const fileGraph = ensureFileGraph(id, entry, resourceId); if (!fileGraph.js) { return; } if (fileGraph.js.scanned) { if (fileGraph.js.empty) { return; } return addManifestDependencies(fileGraph, manifestDependencies, resourceId).reduce(async (prevPromise, depFileGraphId) => { await prevPromise; return await buildFileGraphRecursive(depFileGraphId, manifestDependencies, false, resourceId); }, Promise.resolve()); } const content = fs_1.default.readFileSync(id, 'utf8'); const esbuildTransformResult = await (0, vite_1.transformWithEsbuild)(content, id, esbuildTransformOptions); fileGraph.js.scanned = true; // d.ts or interface only if (!esbuildTransformResult.code) { fileGraph.js.empty = true; return; } fileGraph.js.metadata = utils_1.moduleAnalysis.analyze(esbuildTransformResult.code, id); ensureDependencies(id, fileGraph.js.metadata); return addManifestDependencies(fileGraph, manifestDependencies, resourceId).reduce(async (prevPromise, depFileGraphId) => { await prevPromise; return await buildFileGraphRecursive(depFileGraphId, manifestDependencies, false, resourceId); }, Promise.resolve()); } async function buildPreBundledGraphs() { const preBundleEntries = await manifest_1.entriesResolver.getPreBundleEntries(); Object.keys(preBundleEntries).forEach(key => { const [resourceName, resourceId] = key.split('_'); preBundleEntries[key].forEach(id => { if (fileGraphs[id] && fileGraphs[id].preBundled) { return; } fileGraphs[id] = initFileGraph(id, true, true); fileGraphs[id].resourceId = resourceId; fileGraphs[id].preBundled = true; }); }); } function setResourceIdForFileGraph(fileGraph) { // resource Id already set, this is entry file if (!!fileGraph.resourceId) { return; } // only one manifest connected to this file => the file belongs to this manifest if (fileGraph.connectedResourceIds.length == 1) { fileGraph.resourceId = fileGraph.connectedResourceIds[0]; fileGraph.connectedResourceIds = []; return; } fileGraph.connectedResourceIds = []; // vendor file so skip it if (fileGraph.bareImport) { return; } // more than one manifest connencted to this file => priority exporters if (fileGraph.exporters.length > 0) { fileGraph.resourceId = resolveResourceIdFromDependency(fileGraph.exporters[0]); } // if exporters has no value then check importers if (fileGraph.importers.length > 0) { fileGraph.resourceId = resolveResourceIdFromDependency(fileGraph.importers[0]); } } function resolveResourceIdFromDependency(id) { const fileGraph = fileGraphs[id]; if (!!fileGraph.resourceId) { return fileGraph.resourceId; } setResourceIdForFileGraph(fileGraph); return fileGraph.resourceId; } function addManifestDependencies(fileGraph, manifestDependencies, resourceId) { const fileDependencies = [...fileGraph.js.metadata.importPaths, ...fileGraph.js.metadata.exportPaths]; const newManifestDependencies = fileDependencies.filter(filePath => manifestDependencies.indexOf(filePath) == -1); if (newManifestDependencies.length > 0) { manifestDependencies.push(...newManifestDependencies); } const unscannedFiles = []; newManifestDependencies.forEach(filePath => { const depFileGraph = ensureFileGraph(filePath, false, resourceId); if (depFileGraph.bareImport || !depFileGraph.js || (depFileGraph.js.scanned && depFileGraph.js.empty)) { return; } if (depFileGraph.js.scanned) { unscannedFiles.push(...addManifestDependencies(depFileGraph, manifestDependencies, resourceId)); } else { unscannedFiles.push(filePath); } }); return unscannedFiles; } function ensureDependencies(id, metadata) { metadata.importPaths.forEach(importId => { const fileGraph = ensureFileGraph(importId, false, undefined); if (fileGraph.importers.includes(id) == false) { fileGraph.importers.push(id); } }); metadata.exportPaths.forEach(exportId => { const fileGraph = ensureFileGraph(exportId, false, undefined); if (fileGraph.exporters.includes(id) == false) { fileGraph.exporters.push(id); } }); } function ensureFileGraph(id, entry, resourceId) { if (!fileGraphs[id]) { if (utils_1.pathUtils.isSourceCodePath(id)) { if (utils_1.pathUtils.isJavaScriptSuperset(id)) { fileGraphs[id] = initFileGraphJavaScript(id, {}, entry, false); } else { fileGraphs[id] = initFileGraph(id, entry, false); } } else { if (id.endsWith('.css') || id.endsWith('.svg')) { fileGraphs[id] = initFileGraph(id, entry, true); } else { fileGraphs[id] = initFileGraphJavaScript(id, {}, entry, true); } } } if (entry && !!resourceId) { fileGraphs[id].entry = true; fileGraphs[id].resourceId = resourceId; } else if (resourceId && fileGraphs[id].connectedResourceIds.includes(resourceId) == false) { fileGraphs[id].connectedResourceIds.push(resourceId); } return fileGraphs[id]; } function initFileGraph(id, entry, bareImport) { return { id: id, entry: entry, preBundled: false, extension: path_1.default.extname(id), resourceId: undefined, connectedResourceIds: [], importers: [], exporters: [], js: undefined, bareImport: bareImport }; } function initFileGraphJavaScript(id, graph, entry, bareImport) { return { id: id, entry: entry, preBundled: false, extension: path_1.default.extname(id), resourceId: undefined, connectedResourceIds: [], importers: [], exporters: [], js: { scanned: graph.scanned ? graph.scanned : false, empty: graph.empty ? graph.empty : false, metadata: graph.metadata ? graph.metadata : undefined }, bareImport: bareImport }; }