UNPKG

5.87 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.generate = void 0;
4const tslib_1 = require("tslib");
5const hooks_js_1 = require("./hooks.js");
6const codegen_js_1 = require("./codegen.js");
7const watcher_js_1 = require("./utils/watcher.js");
8const file_system_js_1 = require("./utils/file-system.js");
9const mkdirp_1 = tslib_1.__importDefault(require("mkdirp"));
10const path_1 = require("path");
11const debugging_js_1 = require("./utils/debugging.js");
12const config_js_1 = require("./config.js");
13const crypto_1 = require("crypto");
14const hash = (content) => (0, crypto_1.createHash)('sha1').update(content).digest('base64');
15async function generate(input, saveToFile = true) {
16 const context = (0, config_js_1.ensureContext)(input);
17 const config = context.getConfig();
18 await context.profiler.run(() => (0, hooks_js_1.lifecycleHooks)(config.hooks).afterStart(), 'Lifecycle: afterStart');
19 let previouslyGeneratedFilenames = [];
20 function removeStaleFiles(config, generationResult) {
21 const filenames = generationResult.map(o => o.filename);
22 // find stale files from previous build which are not present in current build
23 const staleFilenames = previouslyGeneratedFilenames.filter(f => !filenames.includes(f));
24 staleFilenames.forEach(filename => {
25 if (shouldOverwrite(config, filename)) {
26 return (0, file_system_js_1.unlinkFile)(filename, err => {
27 const prettyFilename = filename.replace(`${input.cwd || process.cwd()}/`, '');
28 if (err) {
29 (0, debugging_js_1.debugLog)(`Cannot remove stale file: ${prettyFilename}\n${err}`);
30 }
31 else {
32 (0, debugging_js_1.debugLog)(`Removed stale file: ${prettyFilename}`);
33 }
34 });
35 }
36 });
37 previouslyGeneratedFilenames = filenames;
38 }
39 const recentOutputHash = new Map();
40 async function writeOutput(generationResult) {
41 if (!saveToFile) {
42 return generationResult;
43 }
44 if (config.watch) {
45 removeStaleFiles(config, generationResult);
46 }
47 await context.profiler.run(async () => {
48 await (0, hooks_js_1.lifecycleHooks)(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
49 }, 'Lifecycle: beforeAllFileWrite');
50 await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
51 const exists = await (0, file_system_js_1.fileExists)(result.filename);
52 if (!shouldOverwrite(config, result.filename) && exists) {
53 return;
54 }
55 const content = result.content || '';
56 const currentHash = hash(content);
57 let previousHash = recentOutputHash.get(result.filename);
58 if (!previousHash && exists) {
59 previousHash = hash(await (0, file_system_js_1.readFile)(result.filename));
60 }
61 if (previousHash && currentHash === previousHash) {
62 (0, debugging_js_1.debugLog)(`Skipping file (${result.filename}) writing due to indentical hash...`);
63 return;
64 }
65 else if (context.checkMode) {
66 context.checkModeStaleFiles.push(result.filename);
67 return; // skip updating file in dry mode
68 }
69 if (content.length === 0) {
70 return;
71 }
72 recentOutputHash.set(result.filename, currentHash);
73 const basedir = (0, path_1.dirname)(result.filename);
74 await (0, hooks_js_1.lifecycleHooks)(result.hooks).beforeOneFileWrite(result.filename);
75 await (0, hooks_js_1.lifecycleHooks)(config.hooks).beforeOneFileWrite(result.filename);
76 await (0, mkdirp_1.default)(basedir);
77 const absolutePath = (0, path_1.isAbsolute)(result.filename)
78 ? result.filename
79 : (0, path_1.join)(input.cwd || process.cwd(), result.filename);
80 await (0, file_system_js_1.writeFile)(absolutePath, result.content);
81 await (0, hooks_js_1.lifecycleHooks)(result.hooks).afterOneFileWrite(result.filename);
82 await (0, hooks_js_1.lifecycleHooks)(config.hooks).afterOneFileWrite(result.filename);
83 })), 'Write files');
84 await context.profiler.run(() => (0, hooks_js_1.lifecycleHooks)(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: afterAllFileWrite');
85 return generationResult;
86 }
87 // watch mode
88 if (config.watch) {
89 return (0, watcher_js_1.createWatcher)(context, writeOutput);
90 }
91 const outputFiles = await context.profiler.run(() => (0, codegen_js_1.executeCodegen)(context), 'executeCodegen');
92 await context.profiler.run(() => writeOutput(outputFiles), 'writeOutput');
93 await context.profiler.run(() => (0, hooks_js_1.lifecycleHooks)(config.hooks).beforeDone(), 'Lifecycle: beforeDone');
94 if (context.profilerOutput) {
95 await (0, file_system_js_1.writeFile)((0, path_1.join)(context.cwd, context.profilerOutput), JSON.stringify(context.profiler.collect()));
96 }
97 return outputFiles;
98}
99exports.generate = generate;
100function shouldOverwrite(config, outputPath) {
101 const globalValue = config.overwrite === undefined ? true : !!config.overwrite;
102 const outputConfig = config.generates[outputPath];
103 if (!outputConfig) {
104 (0, debugging_js_1.debugLog)(`Couldn't find a config of ${outputPath}`);
105 return globalValue;
106 }
107 if (isConfiguredOutput(outputConfig) && typeof outputConfig.overwrite === 'boolean') {
108 return outputConfig.overwrite;
109 }
110 return globalValue;
111}
112function isConfiguredOutput(output) {
113 return typeof output.plugins !== 'undefined';
114}