UNPKG

jsii-pacmak

Version:

A code generation framework for jsii backend languages

152 lines 6.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pacmak = exports.configureLogging = exports.TargetName = void 0; const jsii_reflect_1 = require("jsii-reflect"); const jsii_rosetta_1 = require("jsii-rosetta"); const path_1 = require("path"); const process_1 = require("process"); const logging = require("./logging"); const npm_modules_1 = require("./npm-modules"); const targets_1 = require("./targets"); Object.defineProperty(exports, "TargetName", { enumerable: true, get: function () { return targets_1.TargetName; } }); const timer_1 = require("./timer"); const util_1 = require("./util"); var logging_1 = require("./logging"); Object.defineProperty(exports, "configureLogging", { enumerable: true, get: function () { return logging_1.configure; } }); /** * Generates code in the desired targets. */ async function pacmak({ argv = {}, clean = true, codeOnly = false, fingerprint = true, force = false, forceSubdirectory = true, forceTarget = false, inputDirectories, outputDirectory, parallel = true, recurse = false, rosettaTablet, rosettaUnknownSnippets = undefined, runtimeTypeChecking = true, targets = Object.values(targets_1.TargetName), timers = new timer_1.Timers(), updateNpmIgnoreFiles = false, validateAssemblies = false, }) { const rosetta = new jsii_rosetta_1.RosettaTabletReader({ unknownSnippets: rosettaUnknownSnippets, prefixDisclaimer: true, }); if (rosettaTablet) { await rosetta.loadTabletFromFile(rosettaTablet); } const modulesToPackageSorted = await (0, npm_modules_1.findJsiiModules)(inputDirectories, recurse); const modulesToPackageFlat = (0, util_1.flatten)(modulesToPackageSorted); logging.info(`Found ${modulesToPackageFlat.length} modules to package`); if (modulesToPackageFlat.length === 0) { logging.warn('Nothing to do'); return; } if (outputDirectory) { // Ensure this is consistently interpreted as relative to cwd(). This is transparent for absolute // paths, as those would be returned unmodified. const absoluteOutputDirectory = (0, path_1.resolve)((0, process_1.cwd)(), outputDirectory); for (const mod of modulesToPackageFlat) { mod.outputDirectory = absoluteOutputDirectory; } } else if (updateNpmIgnoreFiles) { // if outdir is coming from package.json, verify it is excluded by .npmignore. if it is explicitly // defined via --out, don't perform this verification. await (0, npm_modules_1.updateAllNpmIgnores)(modulesToPackageFlat); } const packCommand = argv['pack-command']; await timers.recordAsync(packCommand, () => { logging.info('Packaging NPM bundles'); return Promise.all(modulesToPackageFlat.map((m) => m.npmPack(packCommand))); }); await timers.recordAsync('load jsii', () => { logging.info('Loading jsii assemblies and translations'); const system = new jsii_reflect_1.TypeSystem(); return Promise.all(modulesToPackageFlat.map(async (m) => { await m.load(system, validateAssemblies); return rosetta.addAssembly(m.assembly.spec, m.moduleDirectory); })); }); try { const targetSets = sliceTargets(modulesToPackageSorted, targets, forceTarget); if (targetSets.every((s) => s.modulesSorted.length === 0)) { throw new Error(`None of the requested packages had any targets to build for '${targets.join(', ')}' (use --force-target to force)`); } const perLanguageDirectory = targetSets.length > 1 || forceSubdirectory; // We run all target sets in parallel for minimal wall clock time await Promise.all(mapParallelOrSerial(targetSets, async (targetSet) => { logging.info(`Packaging '${targetSet.targetType}' for ${describePackages(targetSet)}`); return timers .recordAsync(targetSet.targetType, () => buildTargetsForLanguage(targetSet.targetType, targetSet.modulesSorted, { argv, clean, codeOnly, fingerprint, force, perLanguageDirectory, rosetta, runtimeTypeChecking, })) .then(() => logging.info(`${targetSet.targetType} finished`), (err) => { logging.warn(`${targetSet.targetType} failed`); return Promise.reject(err); }); }, { parallel })); } finally { if (clean) { logging.debug('Cleaning up'); await timers.recordAsync('cleanup', () => Promise.all(modulesToPackageFlat.map((m) => m.cleanup()))); } else { logging.info('Temporary directories retained (--no-clean)'); } } logging.info(`Packaged. ${timers.display()}`); } exports.pacmak = pacmak; //#endregion //#region Building async function buildTargetsForLanguage(targetLanguage, modules, { argv, clean, codeOnly, fingerprint, force, perLanguageDirectory, rosetta, runtimeTypeChecking, }) { // ``argv.target`` is guaranteed valid by ``yargs`` through the ``choices`` directive. const factory = targets_1.ALL_BUILDERS[targetLanguage]; if (!factory) { throw new Error(`Unsupported target: '${targetLanguage}'`); } return factory(modules, { arguments: argv, clean: clean, codeOnly: codeOnly, fingerprint: fingerprint, force: force, languageSubdirectory: perLanguageDirectory, rosetta, runtimeTypeChecking, }).buildModules(); } function sliceTargets(modulesSorted, requestedTargets, force) { const ret = new Array(); for (const target of requestedTargets) { ret.push({ targetType: target, modulesSorted: modulesSorted .map((modules) => modules.filter((m) => force || m.availableTargets.includes(target))) .filter((ms) => ms.length > 0), }); } return ret; } //#endregion //#region Parallelization function mapParallelOrSerial(collection, mapper, { parallel }) { const result = new Array(); for (const item of collection) { result.push(result.length === 0 || parallel ? // Running parallel, or first element mapper(item) : // Wait for the previous promise, then make the next one result[result.length - 1].then(() => mapper(item), (error) => Promise.reject(error))); } return result; } //#endregion //#region Misc. Utilities function describePackages(target) { const modules = (0, util_1.flatten)(target.modulesSorted); if (modules.length > 0 && modules.length < 5) { return modules.map((m) => m.name).join(', '); } return `${modules.length} modules`; } //#endregion //# sourceMappingURL=index.js.map