UNPKG

8.29 kBJavaScriptView Raw
1// @ts-check
2'use strict';
3
4const fs = require('fs');
5const path = require('path');
6const util = require('util');
7
8const mkdirp = require('mkdirp');
9const rimraf = require('rimraf');
10const Hogan = require('hogan.js');
11const clone = require('reftools/lib/clone.js').circularClone; // must preserve functions
12
13const adaptor = require('./adaptor.js');
14const lambdas = require('./lambdas.js');
15
16// allows other backends, such as a stream writer for .tar.gz files
17let ff = {
18 readFileSync: fs.readFileSync,
19 createFile: fs.writeFileSync,
20 rimraf: rimraf,
21 mkdirp: mkdirp
22};
23
24function tpl(config, ...segments) {
25 if (config.templateDir) {
26 segments.splice(0,1);
27 return path.join(config.templateDir, ...segments);
28 }
29 return path.join(__dirname, 'templates', ...segments)
30}
31
32function main(o, config, configName, callback) {
33 let outputDir = config.outputDir || './out/';
34 let verbose = config.defaults.verbose;
35 config.defaults.configName = configName;
36
37 adaptor.transform(o, config.defaults, function(err, model) {
38 if (config.generator) {
39 model.generator = config.generator;
40 }
41 if (verbose) console.log('Processing lambdas '+Object.keys(lambdas));
42 Object.keys(lambdas).forEach(key => model[key] = lambdas[key]);
43
44 if (config.generator && config.generator.lambdas) {
45 for (let lambda in config.generator.lambdas) {
46 if (verbose) console.log('Processing lambda '+lambda);
47 model[lambda] = config.generator.lambdas[lambda];
48 }
49 }
50 for (let p in config.partials) {
51 let partial = config.partials[p];
52 if (verbose) console.log('Processing partial '+partial);
53 config.partials[p] = ff.readFileSync(tpl(config, configName, partial),'utf8');
54 }
55
56 let actions = [];
57 for (let t in config.transformations) {
58 let tx = config.transformations[t];
59 if (tx.input) {
60 if (verbose) console.log('Processing template ' + tx.input);
61 tx.template = ff.readFileSync(tpl(config, configName, tx.input),'utf8');
62 }
63 actions.push(tx);
64 }
65
66 const subDir = (config.defaults.flat ? '' : configName);
67
68 if (verbose) console.log('Making/cleaning output directories');
69 ff.mkdirp(path.join(outputDir,subDir),function(){
70 ff.rimraf(path.join(outputDir,subDir)+'/*',function(){
71 if (config.directories) {
72 for (let directory of config.directories) {
73 ff.mkdirp.sync(path.join(outputDir,subDir,directory));
74 }
75 }
76 for (let action of actions) {
77 if (verbose) console.log('Rendering '+action.output);
78 let template = Hogan.compile(action.template);
79 let content = template.render(model,config.partials);
80 ff.createFile(path.join(outputDir,subDir,action.output),content,'utf8');
81 }
82 if (config.touch) { // may not now be necessary
83 let touchTmp = Hogan.compile(config.touch);
84 let touchList = touchTmp.render(model,config.partials);
85 let files = touchList.split('\r').join('').split('\n');
86 for (let file of files) {
87 file = file.trim();
88 if (file) {
89 if (!fs.existsSync(path.join(outputDir,subDir,file))) {
90 ff.createFile(path.join(outputDir,subDir,file),'','utf8');
91 }
92 }
93 }
94 }
95 if (config.apache) {
96 ff.createFile(path.join(outputDir,subDir,'LICENSE'),ff.readFileSync(tpl({}, '_common', 'LICENSE'),'utf8'),'utf8');
97 }
98 else {
99 ff.createFile(path.join(outputDir,subDir,'LICENSE'),ff.readFileSync(tpl({}, '_common', 'UNLICENSE'),'utf8'),'utf8');
100 }
101 let outer = model;
102
103 if (config.perApi) {
104 let toplevel = clone(model);
105 delete toplevel.apiInfo;
106 for (let pa of config.perApi) {
107 let fnTemplate = Hogan.compile(pa.output);
108 let template = Hogan.compile(ff.readFileSync(tpl(config, configName, pa.input), 'utf8'));
109 for (let api of model.apiInfo.apis) {
110 let cApi = Object.assign({},config.defaults,pa.defaults||{},toplevel,api);
111 let filename = fnTemplate.render(cApi,config.partials);
112 if (verbose) console.log('Rendering '+filename+' (dynamic:'+pa.input+')');
113 ff.createFile(path.join(outputDir,subDir,filename),template.render(cApi,config.partials),'utf8');
114 }
115 }
116 }
117
118 if (config.perPath) {
119 let toplevel = clone(model);
120 delete toplevel.apiInfo;
121 for (let pa of config.perPath) {
122 let fnTemplate = Hogan.compile(pa.output);
123 let template = Hogan.compile(ff.readFileSync(tpl(config, configName, pa.input), 'utf8'));
124 for (let pat of model.apiInfo.paths) {
125 let cPath = Object.assign({},config.defaults,pa.defaults||{},toplevel,pat);
126 let filename = fnTemplate.render(cPath,config.partials);
127 let dirname = path.dirname(filename);
128 if (verbose) console.log('Rendering '+filename+' (dynamic:'+pa.input+')');
129 ff.mkdirp.sync(path.join(outputDir,subDir,dirname));
130 ff.createFile(path.join(outputDir,subDir,filename),template.render(cPath,config.partials),'utf8');
131 }
132 }
133 }
134
135 if (config.perModel) {
136 let cModels = clone(model.models);
137 for (let pm of config.perModel) {
138 let fnTemplate = Hogan.compile(pm.output);
139 let template = Hogan.compile(ff.readFileSync(tpl(config, configName, pm.input), 'utf8'));
140 for (let model of cModels) {
141 outer.models = [];
142 let effModel = Object.assign({},model,pm.defaults||{});
143 outer.models.push(effModel);
144 let filename = fnTemplate.render(outer,config.partials);
145 if (verbose) console.log('Rendering '+filename+' (dynamic:'+pm.input+')');
146 ff.createFile(path.join(outputDir,subDir,filename),template.render(outer,config.partials),'utf8');
147 }
148 }
149 }
150
151 if (config.perOperation) { // now may not be necessary
152 for (let po of config.perOperation) {
153 for (let api of outer.apiInfo.apis) {
154 let cOperations = clone(api.operations);
155 let fnTemplate = Hogan.compile(po.output);
156 let template = Hogan.compile(ff.readFileSync(tpl(config, configName, po.input), 'utf8'));
157 for (let operation of cOperations.operation) {
158 model.operations = [];
159 model.operations.push(operation);
160 let filename = fnTemplate.render(outer,config.partials);
161 if (verbose) console.log('Rendering '+filename+' (dynamic:'+po.input+')');
162 ff.createFile(path.join(outputDir,subDir,filename),template.render(outer,config.partials),'utf8');
163 }
164 }
165 }
166 }
167
168 if (callback) callback(null,true);
169 });
170 });
171 });
172}
173
174module.exports = {
175 fileFunctions: ff,
176 main : main
177};
178