1 |
|
2 | (function() {
|
3 | var colors, crypto, crystal, cson, error, extend, findVersions, force, fs, generate, handlebars, imports, inject, loadModules, loadOutputs, loadProcessor, loadSchemaRefs, loaded_modules, merge, mkdirp, mustache, parse, path, processModules, readdir, request, requireFromString, season, semver, skeemas, sortObject, userHome, yaml;
|
4 |
|
5 | crystal = {
|
6 | load: require('./load')
|
7 | };
|
8 |
|
9 | colors = require('colors');
|
10 |
|
11 | crypto = require('crypto');
|
12 |
|
13 | cson = require('cson-parser');
|
14 |
|
15 | extend = require('extend-combine');
|
16 |
|
17 | findVersions = require('find-versions');
|
18 |
|
19 | fs = require('fs');
|
20 |
|
21 | error = require('../error');
|
22 |
|
23 | handlebars = require('handlebars');
|
24 |
|
25 | merge = require('merge');
|
26 |
|
27 | mkdirp = require('mkdirp');
|
28 |
|
29 | mustache = require('mustache');
|
30 |
|
31 | path = require('path');
|
32 |
|
33 | readdir = require('fs-readdir-recursive');
|
34 |
|
35 | request = require('sync-request');
|
36 |
|
37 | season = require('season');
|
38 |
|
39 | semver = require('semver');
|
40 |
|
41 | skeemas = require('skeemas');
|
42 |
|
43 | userHome = require('user-home');
|
44 |
|
45 | yaml = require('js-yaml');
|
46 |
|
47 | force = false;
|
48 |
|
49 | loaded_modules = {};
|
50 |
|
51 | imports = {};
|
52 |
|
53 | requireFromString = function(code, modules_path) {
|
54 | var e, error1, m;
|
55 | try {
|
56 | m = new module.constructor();
|
57 | m.paths = ["" + modules_path];
|
58 | m._compile(code, modules_path);
|
59 | return m.exports;
|
60 | } catch (error1) {
|
61 | e = error1;
|
62 | return code;
|
63 | }
|
64 | };
|
65 |
|
66 | loadModules = function(modules, host) {
|
67 | var engine, export_name, export_path, exported, exported_spec, helper, j, k, len, len1, model_ver, module_alias, module_config, module_name, module_path, module_version, module_version_query, module_versions, module_versions_path, processor, ref, schema, spec, template, transformer;
|
68 | for (module_name in modules) {
|
69 | module_version_query = modules[module_name];
|
70 | if (module_version_query === 'latest') {
|
71 | module_version = 'latest';
|
72 | } else {
|
73 | module_version = null;
|
74 | if (module_version_query.match(/^(\.|\/)/)) {
|
75 | module_versions_path = path.normalize(module_version_query);
|
76 | if (fs.existsSync(module_versions_path)) {
|
77 | module_version = module_version_query;
|
78 | }
|
79 | } else {
|
80 | module_versions_path = path.normalize(userHome + "/.autocode/module/" + host + "/" + module_name);
|
81 | if (fs.existsSync(module_versions_path)) {
|
82 | module_versions = fs.readdirSync(module_versions_path);
|
83 | for (j = 0, len = module_versions.length; j < len; j++) {
|
84 | model_ver = module_versions[j];
|
85 | model_ver = semver.clean(model_ver);
|
86 | if (model_ver && semver.satisfies(model_ver, modules[module_name]) && (!module_version || semver.gt(model_ver, module_version))) {
|
87 | module_version = model_ver;
|
88 | }
|
89 | }
|
90 | }
|
91 | }
|
92 | }
|
93 | if (!module_version) {
|
94 | throw new Error("No matches for Module (" + module_name + ") with version (" + module_version_query + "). Try: autocode update");
|
95 | }
|
96 | module_alias = module_name.substr(module_name.lastIndexOf('/') + 1);
|
97 | if (loaded_modules[module_name] && loaded_modules[module_name][module_version]) {
|
98 | continue;
|
99 | }
|
100 | if (!loaded_modules[module_name]) {
|
101 | loaded_modules[module_name] = {};
|
102 | }
|
103 | if (module_version_query.match(/^(\.|\/)/)) {
|
104 | module_path = module_version_query;
|
105 | } else {
|
106 | module_path = userHome + "/.autocode/module/" + host + "/" + module_name + "/" + module_version;
|
107 | }
|
108 | if (!fs.existsSync(module_path)) {
|
109 | throw new Error("Unknown module (" + module_name + ") at version (" + module_version + "). Try: autocode update");
|
110 | }
|
111 | module_config = crystal.load(module_path);
|
112 | if (!module_config) {
|
113 | throw new Error("Unable to load configuration for module (" + module_name + ")");
|
114 | }
|
115 | if (module_config.exports) {
|
116 | for (export_name in module_config.exports) {
|
117 | exported = module_config.exports[export_name];
|
118 | module_config.exports[export_name].dir = module_path;
|
119 | if (typeof exported.engine === 'string') {
|
120 | export_path = path.normalize(module_path + "/.autocode/engine/" + exported.engine);
|
121 | if (fs.existsSync(export_path)) {
|
122 | engine = require(export_path);
|
123 | } else {
|
124 | engine = requireFromString(exported.engine, module_path + "/node_modules");
|
125 | }
|
126 | module_config.exports[export_name].engine = engine;
|
127 | }
|
128 | if (typeof exported.helper === 'string') {
|
129 | export_path = path.normalize(module_path + "/.autocode/helper/" + exported.helper);
|
130 | if (fs.existsSync(export_path)) {
|
131 | helper = require(export_path);
|
132 | } else {
|
133 | helper = requireFromString(exported.helper, module_path + "/node_modules");
|
134 | }
|
135 | module_config.exports[export_name].helper = helper;
|
136 | }
|
137 | if (typeof exported.processor === 'string') {
|
138 | export_path = path.normalize(module_path + "/.autocode/processor/" + exported.processor);
|
139 | if (fs.existsSync(export_path)) {
|
140 | processor = require(export_path);
|
141 | } else {
|
142 | processor = requireFromString(exported.processor, module_path + "/node_modules");
|
143 | }
|
144 | module_config.exports[export_name].processor = processor;
|
145 | }
|
146 | if (typeof exported.schema === 'string') {
|
147 | if (exported.schema.match(/^https?:/)) {
|
148 | schema = request('get', exported.schema, {
|
149 | allowRedirectHeaders: ['User-Agent']
|
150 | });
|
151 | console.log(schema);
|
152 | schema = yaml.safeLoad(schema.body.toString());
|
153 | } else {
|
154 | export_path = path.normalize(module_path + "/.autocode/schema/" + exported.schema);
|
155 | if (fs.existsSync(export_path)) {
|
156 | schema = yaml.safeLoad(fs.readFileSync(export_path));
|
157 | } else if (module_config.exports[exported.schema]) {
|
158 | schema = module_config.exports[exported.schema].schema;
|
159 | } else {
|
160 | schema = exported.schema;
|
161 | }
|
162 | }
|
163 | module_config.exports[export_name].schema = schema;
|
164 | }
|
165 | if (exported.spec instanceof Array) {
|
166 | spec = {};
|
167 | ref = exported.spec;
|
168 | for (k = 0, len1 = ref.length; k < len1; k++) {
|
169 | exported_spec = ref[k];
|
170 | export_path = module_path + "/.autocode/spec/" + exported_spec;
|
171 | if (fs.existsSync(export_path)) {
|
172 | exported_spec = yaml.safeLoad(fs.readFileSync(export_path));
|
173 | } else {
|
174 | exported_spec = exported_spec;
|
175 | }
|
176 | spec = extend(true, true, spec, exported_spec);
|
177 | }
|
178 | module_config.exports[export_name].spec = spec;
|
179 | } else if (typeof exported.spec === 'string' && exported.spec.match(/\./)) {
|
180 | if (exported.spec.match(/^https?:\/\//)) {
|
181 | spec = request('get', exported.spec, {
|
182 | allowRedirectHeaders: ['User-Agent']
|
183 | });
|
184 | module_config.exports[export_name].spec = yaml.safeLoad(spec.body);
|
185 | } else {
|
186 | export_path = module_path + "/.autocode/spec/" + exported.spec;
|
187 | if (fs.existsSync(export_path)) {
|
188 | spec = yaml.safeLoad(fs.readFileSync(export_path));
|
189 | } else {
|
190 | spec = exported.spec;
|
191 | }
|
192 | module_config.exports[export_name].spec = spec;
|
193 | }
|
194 | }
|
195 | if (typeof exported.template === 'string') {
|
196 | export_path = path.normalize(module_path + "/.autocode/template/" + exported.template);
|
197 | if (fs.existsSync(export_path)) {
|
198 | template = fs.readFileSync(export_path, 'utf8');
|
199 | } else {
|
200 | template = exported.template;
|
201 | }
|
202 | module_config.exports[export_name].template = template;
|
203 | }
|
204 | if (typeof exported.transformer === 'string') {
|
205 | export_path = path.normalize(module_path + "/.autocode/trans/" + exported.transformer);
|
206 | if (fs.existsSync(export_path)) {
|
207 | transformer = require(export_path);
|
208 | } else {
|
209 | transformer = requireFromString(exported.transformer, module_path + "/node_modules");
|
210 | }
|
211 | module_config.exports[export_name].transformer = transformer;
|
212 | }
|
213 | }
|
214 | }
|
215 | loaded_modules[module_name][module_version] = module_config;
|
216 | if (module_config.imports) {
|
217 | loadModules(module_config.imports, module_config.host);
|
218 | } else if (module_config.modules) {
|
219 | loadModules(module_config.modules, module_config.host);
|
220 | }
|
221 | }
|
222 | return loaded_modules = sortObject(loaded_modules);
|
223 | };
|
224 |
|
225 | processModules = function() {
|
226 | var export_name, exported, helper, helper_name, helpers, loaded_module, model_ver, module_name, module_versions, results, submodule_alias, submodule_export, submodule_export_name, submodule_exports, submodule_name, submodule_version, submodule_version_query, submodule_versions, submodule_versions_path, submodules, test, test2, version_name;
|
227 | results = [];
|
228 | for (module_name in loaded_modules) {
|
229 | module_versions = loaded_modules[module_name];
|
230 | results.push((function() {
|
231 | var j, len, results1;
|
232 | results1 = [];
|
233 | for (version_name in module_versions) {
|
234 | loaded_module = module_versions[version_name];
|
235 | submodules = {};
|
236 | if (loaded_module.imports) {
|
237 | loaded_module.modules = loaded_module.imports;
|
238 | }
|
239 | loaded_module.imports = {};
|
240 | for (submodule_name in loaded_module.modules) {
|
241 | submodule_alias = submodule_name.substr(submodule_name.lastIndexOf('/') + 1);
|
242 | submodule_version_query = loaded_module.modules[submodule_name];
|
243 | if (submodule_version_query === 'latest') {
|
244 | submodule_version = 'latest';
|
245 | } else {
|
246 | submodule_version = null;
|
247 | if (submodule_version_query.match(/^(\.|\/)/)) {
|
248 | submodule_versions_path = path.normalize(submodule_version_query);
|
249 | if (fs.existsSync(submodule_versions_path)) {
|
250 | submodule_version = submodule_version_query;
|
251 | }
|
252 | } else {
|
253 | submodule_versions_path = path.normalize(userHome + "/.autocode/module/" + loaded_module.host + "/" + submodule_name);
|
254 | if (fs.existsSync(submodule_versions_path)) {
|
255 | submodule_versions = fs.readdirSync(submodule_versions_path);
|
256 | for (j = 0, len = submodule_versions.length; j < len; j++) {
|
257 | model_ver = submodule_versions[j];
|
258 | model_ver = semver.clean(model_ver);
|
259 | if (model_ver && semver.satisfies(model_ver, submodule_version_query) && (!submodule_version || semver.gt(model_ver, submodule_version))) {
|
260 | submodule_version = model_ver;
|
261 | }
|
262 | }
|
263 | }
|
264 | }
|
265 | }
|
266 | if (!submodule_version) {
|
267 | throw new Error("No matches for submodule (" + submodule_name + ") with version (" + submodule_version_query + "). Try: autocode update");
|
268 | }
|
269 | submodule_exports = loaded_modules[submodule_name][submodule_version].exports;
|
270 | for (submodule_export_name in submodule_exports) {
|
271 | submodule_export = submodule_exports[submodule_export_name];
|
272 | loaded_module.imports[submodule_alias + "." + submodule_export_name] = submodule_name + "." + submodule_export_name;
|
273 | }
|
274 | submodules[submodule_name] = submodule_version;
|
275 | }
|
276 | results1.push((function() {
|
277 | var results2;
|
278 | results2 = [];
|
279 | for (export_name in loaded_module.exports) {
|
280 | exported = loaded_module.exports[export_name];
|
281 | if (exported.copy && typeof exported.copy.engine === 'string') {
|
282 | test = loaded_module.imports[exported.copy.engine].split('.');
|
283 | test2 = test.pop();
|
284 | test = test.join('.');
|
285 | loaded_modules[module_name][version_name].exports[export_name].copy.engine = loaded_modules[test][submodules[test]].exports[test2].engine;
|
286 | }
|
287 | if (exported.copy && exported.copy.dest && exported.copy.dest.engine && typeof exported.copy.dest.engine === 'string') {
|
288 | test = loaded_module.imports[exported.copy.dest.engine].split('.');
|
289 | test2 = test.pop();
|
290 | test = test.join('.');
|
291 | loaded_modules[module_name][version_name].exports[export_name].copy.dest.engine = loaded_modules[test][submodules[test]].exports[test2].engine;
|
292 | }
|
293 | if (typeof exported.engine === 'string' && loaded_module.imports[exported.engine]) {
|
294 | test = loaded_module.imports[exported.engine].split('.');
|
295 | test2 = test.pop();
|
296 | test = test.join('.');
|
297 | loaded_modules[module_name][version_name].exports[export_name].engine = loaded_modules[test][submodules[test]].exports[test2].engine;
|
298 | }
|
299 | if (exported.filename && typeof exported.filename.engine === 'string') {
|
300 | if (!loaded_module.imports[exported.filename.engine]) {
|
301 | throw new Error("Import does not exist for alias (" + exported.filename.engine + ")");
|
302 | }
|
303 | test = loaded_module.imports[exported.filename.engine].split('.');
|
304 | test2 = test.pop();
|
305 | test = test.join('.');
|
306 | loaded_modules[module_name][version_name].exports[export_name].filename.engine = loaded_modules[test][submodules[test]].exports[test2].engine;
|
307 | }
|
308 | if (typeof exported.helper === 'object') {
|
309 | helpers = [];
|
310 | for (helper_name in exported.helper) {
|
311 | helper = exported.helper[helper_name];
|
312 | if (!loaded_module.imports[helper] && !loaded_module.exports[helper]) {
|
313 | throw new Error("Import does not exist for alias (" + helper + ")");
|
314 | }
|
315 | if (loaded_module.exports[helper]) {
|
316 | helpers.push({
|
317 | callback: loaded_module.exports[helper].helper,
|
318 | name: helper_name
|
319 | });
|
320 | } else {
|
321 | test = loaded_module.imports[helper].split('.');
|
322 | test2 = test.pop();
|
323 | test = test.join('.');
|
324 | helpers.push({
|
325 | callback: loaded_modules[test][submodules[test]].exports[test2].helper,
|
326 | name: helper_name
|
327 | });
|
328 | }
|
329 | }
|
330 | loaded_modules[module_name][version_name].exports[export_name].helper = helpers;
|
331 | } else if (typeof exported.helper === 'string' && loaded_module.imports[exported.helper]) {
|
332 | test = loaded_module.imports[exported.helper].split('.');
|
333 | test2 = test.pop();
|
334 | test = test.join('.');
|
335 | if (!loaded_modules[test][submodules[test]].exports[test2]) {
|
336 | throw new Error("Import (" + test2 + ") does not exist for module (" + test + ")");
|
337 | }
|
338 | loaded_modules[module_name][version_name].exports[export_name].helper = [
|
339 | {
|
340 | callback: loaded_modules[test][submodules[test]].exports[test2].helper,
|
341 | name: loaded_modules[test][submodules[test]].exports[test2].name
|
342 | }
|
343 | ];
|
344 | }
|
345 | if (typeof exported.schema === 'string' && loaded_module.imports[exported.schema]) {
|
346 | test = loaded_module.imports[exported.schema].split('.');
|
347 | test2 = test.pop();
|
348 | test = test.join('.');
|
349 | loaded_modules[module_name][version_name].exports[export_name].schema = loaded_modules[test][submodules[test]].exports[test2].schema;
|
350 | }
|
351 | if (typeof exported.transformer === 'string' && loaded_module.imports[exported.transformer]) {
|
352 | test = loaded_module.imports[exported.transformer].split('.');
|
353 | test2 = test.pop();
|
354 | test = test.join('.');
|
355 | results2.push(loaded_modules[module_name][version_name].exports[export_name].transformer = loaded_modules[test][submodules[test]].exports[test2].transformer);
|
356 | } else {
|
357 | results2.push(void 0);
|
358 | }
|
359 | }
|
360 | return results2;
|
361 | })());
|
362 | }
|
363 | return results1;
|
364 | })());
|
365 | }
|
366 | return results;
|
367 | };
|
368 |
|
369 | loadOutputs = function(outputs, imports, config) {
|
370 | var cache, cache_checksum, cache_filename, code_dir, code_file, code_files, content, content_checksum, content_spec, copy_dest, copy_dir, copy_filename, copy_src, engine, file, file_checksum, file_last_path, file_name, filename, filename_checksum, filename_options, files, gen_name, gen_prefix, gen_schema, gen_suffix, generator, generator_filename, generator_processor, helpers, i, injectors, iterator, j, k, l, len, len1, len2, len3, n, name, output, output_i, output_path, output_processor, output_spec, ref, ref1, ref2, results, schema_name, schema_prefix, schema_suffix, spec, spec_filename, template, transformer, validate;
|
371 | if (!imports) {
|
372 | throw new Error('No imports available for output');
|
373 | }
|
374 | if (!(outputs instanceof Array)) {
|
375 | outputs = sortObject(outputs);
|
376 | }
|
377 | results = [];
|
378 | for (output_i in outputs) {
|
379 | output = outputs[output_i];
|
380 | if (!(outputs instanceof Array)) {
|
381 | if (output.filename === true) {
|
382 | delete output.filename;
|
383 | } else if (output.filename && output.filename.engine && imports[output.filename.engine]) {
|
384 | output.filename = {
|
385 | engine: imports[output.filename.engine],
|
386 | value: output_i
|
387 | };
|
388 | } else if (!output.filename) {
|
389 | output.filename = output_i;
|
390 | }
|
391 | }
|
392 | if (output.generator && !imports[output.generator]) {
|
393 | throw new Error("Generator (" + output.generator + ") does not exist for output in config (" + config.name + ")");
|
394 | }
|
395 | generator = imports[output.generator] || {};
|
396 | output_processor = output.processor;
|
397 | generator_processor = generator.processor;
|
398 | output_processor = loadProcessor(output_processor, generator_processor, imports);
|
399 | spec = {};
|
400 | if (output.spec) {
|
401 | if (output.spec instanceof Array) {
|
402 | ref = output.spec;
|
403 | for (j = 0, len = ref.length; j < len; j++) {
|
404 | output_spec = ref[j];
|
405 | if (typeof output_spec === 'string') {
|
406 | if (imports[output_spec]) {
|
407 | output_processor = loadProcessor(imports[output_spec].processor, null, imports);
|
408 | output_spec = imports[output_spec].spec;
|
409 | } else if (output_spec.match(/^https?:\/\//)) {
|
410 | output_spec = request('get', output_spec, {
|
411 | allowRedirectHeaders: ['User-Agent']
|
412 | });
|
413 | output_spec = yaml.safeLoad(spec.body);
|
414 | } else {
|
415 | spec_filename = ".autocode/spec/" + output_spec;
|
416 | if (!fs.existsSync(spec_filename)) {
|
417 | throw new Error("File (" + spec_filename + ") does not exist for spec in output for config (" + config.id + ")");
|
418 | }
|
419 | output_spec = yaml.safeLoad(fs.readFileSync(spec_filename, 'utf8'));
|
420 | }
|
421 | }
|
422 | output_spec = parse(output_spec, config, output_processor);
|
423 | spec = extend(true, true, spec, output_spec);
|
424 | }
|
425 | } else {
|
426 | if (typeof output.spec === 'object') {
|
427 | spec = output.spec;
|
428 | } else if (typeof output.spec === 'string') {
|
429 | if (imports[output.spec]) {
|
430 | output_processor = loadProcessor(imports[output.spec].processor, null, imports);
|
431 | spec = imports[output.spec].spec;
|
432 | } else if (output.spec.match(/^https?:\/\//)) {
|
433 | spec = request('get', output.spec, {
|
434 | allowRedirectHeaders: ['User-Agent']
|
435 | });
|
436 | spec = yaml.safeLoad(spec.body);
|
437 | } else {
|
438 | spec_filename = ".autocode/spec/" + output.spec;
|
439 | if (!fs.existsSync(spec_filename)) {
|
440 | throw new Error("File (" + spec_filename + ") does not exist for spec in output for config (" + config.id + ")");
|
441 | }
|
442 | spec = yaml.safeLoad(fs.readFileSync(spec_filename, 'utf8'));
|
443 | }
|
444 | }
|
445 | spec = parse(spec, config, output_processor);
|
446 | }
|
447 | }
|
448 | if (generator.schema) {
|
449 | gen_schema = generator.schema;
|
450 | if (typeof gen_schema === 'string') {
|
451 | gen_name = output.generator.split('.');
|
452 | if (!gen_name.length) {
|
453 | throw new Error("Invalid generator name: " + gen_name);
|
454 | }
|
455 | if (gen_name.length > 1) {
|
456 | gen_prefix = gen_name[0];
|
457 | gen_suffix = gen_name[1];
|
458 | if (!imports[gen_prefix + "." + gen_suffix] || !imports[gen_prefix + "." + gen_suffix].schema) {
|
459 | throw new Error("Schema does not exist for: " + gen_prefix + "." + gen_suffix);
|
460 | }
|
461 | gen_schema = imports[gen_prefix + "." + gen_suffix].schema;
|
462 | } else {
|
463 | gen_name = gen_name[0];
|
464 | if (!imports["" + gen_name] || !imports["" + gen_name].schema) {
|
465 | throw new Error("Schema does not exist for: " + gen_name);
|
466 | }
|
467 | gen_schema = imports["" + gen_name].schema;
|
468 | if (typeof gen_schema === 'string') {
|
469 | schema_name = gen_schema.split('.');
|
470 | if (!schema_name.length) {
|
471 | throw new Error("Invalid schema: " + schema_name);
|
472 | }
|
473 | if (schema_name.length > 1) {
|
474 | schema_prefix = schema_name[0];
|
475 | schema_suffix = schema_name[1];
|
476 | if (!imports[schema_prefix + "." + schema_suffix] || !imports[schema_prefix + "." + schema_suffix].schema) {
|
477 | throw new Error("Schema does not exist for: " + schema_prefix + "." + schema_suffix);
|
478 | }
|
479 | gen_schema = imports[schema_prefix + "." + schema_suffix].schema;
|
480 | } else {
|
481 | schema_name = schema_name[0];
|
482 | if (!imports["" + schema_name] || !imports["" + schema_name].schema) {
|
483 | throw new Error("Schema does not exist: " + schema_name);
|
484 | }
|
485 | gen_schema = imports["" + schema_name].schema;
|
486 | }
|
487 | }
|
488 | }
|
489 | }
|
490 | gen_schema = loadSchemaRefs(gen_schema);
|
491 | validate = skeemas.validate(spec, gen_schema);
|
492 | if (!validate.valid) {
|
493 | console.log(validate.errors);
|
494 | console.log("ERROR: Specification failed validation.");
|
495 | ref1 = validate.errors;
|
496 | for (k = 0, len1 = ref1.length; k < len1; k++) {
|
497 | error = ref1[k];
|
498 | console.log("- " + error.message + " for specification (" + (error.context.substr(2)) + ") in generator (" + output.generator + ")");
|
499 | }
|
500 | throw new Error("ERROR: Invalid specification.");
|
501 | }
|
502 | }
|
503 | engine = output.engine || generator.engine;
|
504 | if (typeof engine === 'string') {
|
505 | if (!imports[engine] || !imports[engine].engine) {
|
506 | throw new Error("Engine was not imported (" + engine + ") at path " + config.path);
|
507 | }
|
508 | engine = imports[engine].engine;
|
509 | }
|
510 | helpers = generator.helper ? generator.helper : null;
|
511 | injectors = output.injector ? output.injector : null;
|
512 | if (generator.copy) {
|
513 | if (typeof generator.copy === 'object') {
|
514 | if (!generator.copy.src) {
|
515 | throw new Error("Copy requires source");
|
516 | }
|
517 | copy_src = generator.copy.src;
|
518 | } else if (typeof generator.copy === 'string') {
|
519 | copy_src = generator.copy;
|
520 | } else {
|
521 | throw new Error("Invalid value for copy");
|
522 | }
|
523 | if (generator.copy.dest) {
|
524 | if (typeof generator.copy.dest === 'object') {
|
525 | if (!generator.copy.dest.engine) {
|
526 | throw new Error("Destination engine is required for copy");
|
527 | }
|
528 | if (!generator.copy.dest.value) {
|
529 | throw new Error("Destination value is required for copy");
|
530 | }
|
531 | copy_dest = generator.copy.dest.engine(spec, generator.copy.dest.value, helpers);
|
532 | } else if (typeof generator.copy.dest === 'string') {
|
533 | copy_dest = generator.copy.dest;
|
534 | } else {
|
535 | throw new Error("Invalid Destination for copy");
|
536 | }
|
537 | if (copy_dest.substr(copy_dest.length - 1) !== '/') {
|
538 | copy_dest += '/';
|
539 | }
|
540 | } else {
|
541 | copy_dest = '';
|
542 | }
|
543 | copy_dir = generator.dir + "/.autocode/" + copy_src;
|
544 | if (!fs.existsSync(copy_dir)) {
|
545 | throw new Error("Directory (" + copy_dir + ") does not exist in copy");
|
546 | }
|
547 | code_files = readdir(copy_dir, function(x) {
|
548 | return true;
|
549 | });
|
550 | for (l = 0, len2 = code_files.length; l < len2; l++) {
|
551 | code_file = code_files[l];
|
552 | copy_filename = output.path + "/" + copy_dest + code_file;
|
553 | code_dir = copy_filename.substring(0, copy_filename.lastIndexOf('/') + 1);
|
554 | if (!fs.existsSync(code_dir)) {
|
555 | mkdirp.sync(code_dir);
|
556 | }
|
557 | fs.writeFileSync("" + copy_filename, fs.readFileSync(copy_dir + "/" + code_file));
|
558 | console.log(("Generated file: " + copy_filename).green);
|
559 | }
|
560 | }
|
561 | generator_filename = output.filename || generator.filename;
|
562 | if (!generator_filename) {
|
563 | continue;
|
564 | }
|
565 | iterator = output.iterator || generator.iterator;
|
566 | if (iterator) {
|
567 | if (!spec[iterator]) {
|
568 | throw new Error("Iterator (" + iterator + ") not found in spec for generator (" + generator + ") in config (" + config.id + ")");
|
569 | }
|
570 | files = [];
|
571 | if (spec[iterator] instanceof Array) {
|
572 | ref2 = spec[iterator];
|
573 | for (n = 0, len3 = ref2.length; n < len3; n++) {
|
574 | file = ref2[n];
|
575 | files.push(file);
|
576 | }
|
577 | } else if (typeof spec[iterator] === 'object') {
|
578 | for (name in spec[iterator]) {
|
579 | files.push(name);
|
580 | }
|
581 | }
|
582 | } else {
|
583 | files = [generator_filename];
|
584 | }
|
585 | results.push((function() {
|
586 | var results1;
|
587 | results1 = [];
|
588 | for (i in files) {
|
589 | file = files[i];
|
590 | if (file.name) {
|
591 | filename_options = {
|
592 | name: file.name
|
593 | };
|
594 | file = file.name;
|
595 | } else {
|
596 | filename_options = [];
|
597 | filename_options[0] = {};
|
598 | filename_options[0][file] = spec;
|
599 | file_name = null;
|
600 | }
|
601 | if (generator_filename.engine) {
|
602 | filename = generator_filename.engine(filename_options, generator_filename.value, helpers);
|
603 | } else {
|
604 | filename = generator_filename;
|
605 | }
|
606 | if (output.path) {
|
607 | if (!fs.existsSync(output.path)) {
|
608 | mkdirp(output.path);
|
609 | }
|
610 | filename = output.path + "/" + filename;
|
611 | }
|
612 | if (!spec) {
|
613 | throw new Error("Spec is required.");
|
614 | }
|
615 | if (output.template) {
|
616 | output_path = ".autocode/template/" + output.template;
|
617 | if (fs.existsSync(output_path)) {
|
618 | template = fs.readFileSync(output_path, 'utf8');
|
619 | } else {
|
620 | template = output.template;
|
621 | }
|
622 | } else {
|
623 | template = generator.template;
|
624 | }
|
625 | if (engine) {
|
626 | if (iterator) {
|
627 | content_spec = extend(true, true, {}, spec[iterator][i] || spec[iterator][file]);
|
628 | if (content_spec) {
|
629 | content_spec = extend(true, true, content_spec, spec);
|
630 | content_spec.name = file;
|
631 | }
|
632 | if (content_spec && content_spec[iterator] && content_spec[iterator][file] && content_spec[iterator][file]['$injector']) {
|
633 | template = inject(template, injectors, false);
|
634 | template = inject(template, content_spec[iterator][file]['$injector'], false);
|
635 | template = inject(template, null, true);
|
636 | } else {
|
637 | template = inject(template, injectors, true);
|
638 | }
|
639 | content = engine(content_spec, template, helpers, process.cwd());
|
640 | } else {
|
641 | if (template) {
|
642 | template = inject(template, injectors, true);
|
643 | }
|
644 | content = engine(spec, template, helpers, process.cwd());
|
645 | }
|
646 | } else if (template) {
|
647 | template = inject(template, injectors, true);
|
648 | content = template;
|
649 | } else if (spec) {
|
650 | content = spec;
|
651 | } else {
|
652 | content = "";
|
653 | }
|
654 | transformer = output.transformer || generator.transformer;
|
655 | if (transformer) {
|
656 | if (typeof transformer === 'string') {
|
657 | if (!imports[transformer]) {
|
658 | throw new Error("Transformer " + transformer + " does not exist");
|
659 | }
|
660 | transformer = imports[transformer].transformer;
|
661 | }
|
662 | content = transformer(content);
|
663 | } else if (typeof content === 'object') {
|
664 | content = "";
|
665 | }
|
666 | cache_filename = ".autocode/cache.yml";
|
667 | if (fs.existsSync(cache_filename)) {
|
668 | cache = yaml.safeLoad(fs.readFileSync(cache_filename, 'utf8'));
|
669 | if (!cache.checksum) {
|
670 | cache.checksum = {};
|
671 | }
|
672 | } else {
|
673 | cache = {
|
674 | checksum: {}
|
675 | };
|
676 | }
|
677 | filename_checksum = crypto.createHash('md5').update(filename, 'utf8').digest('hex');
|
678 | if (cache.checksum[filename_checksum]) {
|
679 | if (!fs.existsSync(filename)) {
|
680 | if (force !== true) {
|
681 | throw new Error(("ERROR: File (" + filename + ") has been manually deleted outside of Crystal. Use -f to force code generation and overwrite this deletion.").red.bold);
|
682 | }
|
683 | } else {
|
684 | cache_checksum = cache.checksum[filename_checksum];
|
685 | file_checksum = crypto.createHash('md5').update(fs.readFileSync(filename, 'utf8'), 'utf8').digest('hex');
|
686 | if (cache_checksum !== file_checksum && force !== true) {
|
687 | throw new Error(("ERROR: File (" + filename + ") has been manually changed outside of Crystal. Use -f to force code generation and overwrite these changes.").red.bold);
|
688 | }
|
689 | }
|
690 | }
|
691 | content_checksum = crypto.createHash('md5').update(content, 'utf8').digest('hex');
|
692 | cache.checksum[filename_checksum] = content_checksum;
|
693 | if (!fs.existsSync(".autocode")) {
|
694 | mkdirp.sync(".autocode");
|
695 | }
|
696 | fs.writeFileSync(".autocode/cache.yml", yaml.safeDump(cache));
|
697 | file_last_path = filename.lastIndexOf('/');
|
698 | if (file_last_path !== -1) {
|
699 | mkdirp.sync(filename.substr(0, file_last_path));
|
700 | }
|
701 | fs.writeFileSync(filename, content);
|
702 | results1.push(console.log("- " + filename));
|
703 | }
|
704 | return results1;
|
705 | })());
|
706 | }
|
707 | return results;
|
708 | };
|
709 |
|
710 | loadProcessor = function(output_processor, generator_processor, imports) {
|
711 | var j, len, processor, processors;
|
712 | if (generator_processor) {
|
713 | if (typeof output_processor === 'string') {
|
714 | output_processor = [output_processor];
|
715 | }
|
716 | if (typeof generator_processor === 'string') {
|
717 | generator_processor = [generator_processor];
|
718 | }
|
719 | if (output_processor && generator_processor) {
|
720 | output_processor = extend(true, true, output_processor, generator_processor);
|
721 | } else {
|
722 | output_processor = generator_processor;
|
723 | }
|
724 | }
|
725 | if (output_processor instanceof Array) {
|
726 | processors = [];
|
727 | for (j = 0, len = output_processor.length; j < len; j++) {
|
728 | processor = output_processor[j];
|
729 | if (!imports[processor]) {
|
730 | throw new Error("Import does not exist for alias (" + processor + ")");
|
731 | }
|
732 | processors.push({
|
733 | alias: processor,
|
734 | callback: imports[processor].processor
|
735 | });
|
736 | }
|
737 | output_processor = processors;
|
738 | } else if (typeof output_processor === 'string') {
|
739 | if (!imports[output_processor]) {
|
740 | throw new Error("Import does not exist for alias (" + output_processor + ")");
|
741 | }
|
742 | output_processor = [
|
743 | {
|
744 | alias: output_processor,
|
745 | callback: imports[output_processor].processor
|
746 | }
|
747 | ];
|
748 | }
|
749 | return output_processor;
|
750 | };
|
751 |
|
752 | loadSchemaRefs = function(schema) {
|
753 | var property_name, resp, schema_path;
|
754 | if (schema['$ref'] && !!schema['$ref'].match(/^http:\/\//)) {
|
755 | schema_path = path.join(userHome, '.autocode/schema/', schema['$ref'].replace(/(^http:\/\/|#)/g, '') + '.json');
|
756 | if (!fs.existsSync(schema_path)) {
|
757 | console.log("Loading schema for ref: " + schema['$ref']);
|
758 | resp = request('get', schema['$ref'], {
|
759 | allowRedirectHeaders: ['User-Agent']
|
760 | });
|
761 | if (!fs.existsSync(path.dirname(schema_path))) {
|
762 | mkdirp.sync(path.dirname(schema_path));
|
763 | }
|
764 | fs.writeFileSync(schema_path, resp);
|
765 | }
|
766 | schema = yaml.safeLoad(fs.readFileSync(schema_path));
|
767 | return schema;
|
768 | }
|
769 | if (schema.properties) {
|
770 | for (property_name in schema.properties) {
|
771 | if (schema.properties[property_name].properties) {
|
772 | schema.properties[property_name] = loadSchemaRefs(schema.properties[property_name]);
|
773 | } else {
|
774 | schema.properties[property_name] = loadSchemaRefs(schema.properties[property_name]);
|
775 | }
|
776 | }
|
777 | }
|
778 | if (schema.definitions) {
|
779 | for (property_name in schema.definitions) {
|
780 | if (schema.definitions[property_name].definitions) {
|
781 | schema.definitions[property_name] = loadSchemaRefs(schema.definitions[property_name]);
|
782 | } else {
|
783 | schema.definitions[property_name] = loadSchemaRefs(schema.definitions[property_name]);
|
784 | }
|
785 | }
|
786 | }
|
787 | return schema;
|
788 | };
|
789 |
|
790 | generate = function(opts) {
|
791 | var config, export_name, exported, exports, j, len, model_ver, module_alias, module_name, module_version, module_version_query, module_versions, module_versions_path;
|
792 | loaded_modules = {};
|
793 | config = this.config;
|
794 | if (opts && opts.force) {
|
795 | force = true;
|
796 | }
|
797 | if (config.imports) {
|
798 | config.modules = config.imports;
|
799 | if (config.name) {
|
800 | config.modules[config.name] = process.cwd();
|
801 | }
|
802 | delete config.imports;
|
803 | }
|
804 | if (config.modules) {
|
805 | loadModules(config.modules, config.host);
|
806 | processModules();
|
807 | }
|
808 | for (module_name in config.modules) {
|
809 | module_alias = module_name.substr(module_name.lastIndexOf('/') + 1);
|
810 | module_version_query = config.modules[module_name];
|
811 | if (module_version_query === 'latest') {
|
812 | module_version = 'latest';
|
813 | } else {
|
814 | module_version = null;
|
815 | if (module_version_query.match(/^(\.|\/)/)) {
|
816 | module_versions_path = path.normalize(module_version_query);
|
817 | if (!fs.existsSync(module_versions_path)) {
|
818 | throw new Error("Module (" + module_name + ") not found at local path (" + module_version_query + ").");
|
819 | } else {
|
820 | module_version = module_version_query;
|
821 | }
|
822 | } else {
|
823 | module_versions_path = path.normalize(userHome + "/.autocode/module/" + config.host + "/" + module_name);
|
824 | if (fs.existsSync(module_versions_path)) {
|
825 | module_versions = fs.readdirSync(module_versions_path);
|
826 | for (j = 0, len = module_versions.length; j < len; j++) {
|
827 | model_ver = module_versions[j];
|
828 | model_ver = semver.clean(model_ver);
|
829 | if (model_ver && semver.satisfies(model_ver, config.modules[module_name]) && (!module_version || semver.gt(model_ver, module_version))) {
|
830 | module_version = model_ver;
|
831 | }
|
832 | }
|
833 | }
|
834 | }
|
835 | }
|
836 | if (!module_version) {
|
837 | throw new Error("No matches for Module (" + module_name + ") with version (" + module_version_query + "). Try: autocode update");
|
838 | }
|
839 | exports = loaded_modules[module_name][module_version].exports;
|
840 | for (export_name in exports) {
|
841 | exported = exports[export_name];
|
842 | if (module_alias === config.name) {
|
843 | imports["" + export_name] = exported;
|
844 | }
|
845 | imports[module_alias + "." + export_name] = exported;
|
846 | }
|
847 | }
|
848 | if (config.outputs) {
|
849 | console.log("Generating outputs...".bold);
|
850 | loadOutputs(config.outputs, imports, config);
|
851 | }
|
852 | return {
|
853 | imports: imports
|
854 | };
|
855 | };
|
856 |
|
857 | inject = function(template, injectors, remove_injector) {
|
858 | if (remove_injector == null) {
|
859 | remove_injector = true;
|
860 | }
|
861 | return template.replace(/([ |\t]+)?>>>[a-z_]*<<<\n?/ig, function(injector) {
|
862 | var inj, inject_final, injected, injector_tabs, j, len, ref;
|
863 | injector_tabs = injector.match(/^[\s]+>/g);
|
864 | if (injector_tabs) {
|
865 | injector_tabs = injector_tabs[0].substr(0, injector_tabs[0].length - 1);
|
866 | } else {
|
867 | injector_tabs = '';
|
868 | }
|
869 | injector = injector.replace(/[\s]+/g, '');
|
870 | injector = injector.substr(3, injector.length - 6);
|
871 | if (injectors && injectors[injector]) {
|
872 | if (injectors[injector] instanceof Array) {
|
873 | injected = injectors[injector].join("\n");
|
874 | } else if ((injectors[injector].substr(0, 1) === '/' || injectors[injector].substr(0, 2) === './') && fs.existsSync(".autocode/" + injectors[injector])) {
|
875 | injected = fs.readFileSync(".autocode/" + injectors[injector], 'utf8');
|
876 | } else {
|
877 | injected = injectors[injector];
|
878 | }
|
879 | if (remove_injector === true) {
|
880 | inject_final = '';
|
881 | } else {
|
882 | inject_final = injector_tabs + ">>>" + injector + "<<<\n";
|
883 | }
|
884 | ref = injected.split("\n");
|
885 | for (j = 0, len = ref.length; j < len; j++) {
|
886 | inj = ref[j];
|
887 | inject_final += "" + injector_tabs + inj + "\n";
|
888 | }
|
889 | return inject_final += "";
|
890 | } else if (remove_injector === true) {
|
891 | return '';
|
892 | } else {
|
893 | return injector_tabs + ">>>" + injector + "<<<\n";
|
894 | }
|
895 | });
|
896 | };
|
897 |
|
898 | parse = function(spec, config, processors) {
|
899 | var i, j, k, l, len, len1, len2, len3, n, proc, processor, ref, ref1, s;
|
900 | if (spec['$processor']) {
|
901 | if (typeof spec['$processor'] === 'string') {
|
902 | spec['$processor'] = [spec['$processor']];
|
903 | }
|
904 | ref = spec['$processor'];
|
905 | for (j = 0, len = ref.length; j < len; j++) {
|
906 | proc = ref[j];
|
907 | for (k = 0, len1 = processors.length; k < len1; k++) {
|
908 | processor = processors[k];
|
909 | if (processor.alias === proc) {
|
910 | spec['$value'] = processor.callback(spec['$value']);
|
911 | }
|
912 | }
|
913 | }
|
914 | return spec['$value'];
|
915 | }
|
916 | for (i in spec) {
|
917 | s = spec[i];
|
918 | if (s === void 0) {
|
919 | continue;
|
920 | }
|
921 | if (typeof s === 'object' && !s['$processor']) {
|
922 | spec[i] = parse(spec[i], config, processors);
|
923 | } else if (typeof s === 'string' && s.substr(0, 1) === '$' && config[s.substr(1)]) {
|
924 | spec[i] = config[s.substr(1)];
|
925 | }
|
926 | if (spec[i]['$processor']) {
|
927 | if (typeof spec[i]['$processor'] === 'string') {
|
928 | spec[i]['$processor'] = [spec[i]['$processor']];
|
929 | }
|
930 | ref1 = spec[i]['$processor'];
|
931 | for (l = 0, len2 = ref1.length; l < len2; l++) {
|
932 | proc = ref1[l];
|
933 | if (processors) {
|
934 | for (n = 0, len3 = processors.length; n < len3; n++) {
|
935 | processor = processors[n];
|
936 | if (processor.alias === proc) {
|
937 | if (typeof spec[i]['$value'] === 'string') {
|
938 | if (imports[spec[i]['$value']]) {
|
939 | spec[i]['$value'] = imports[spec[i]['$value']].spec;
|
940 | } else if (spec[i]['$value'].match(/^https?:\/\//)) {
|
941 | spec[i]['$value'] = request('get', spec[i]['$value'], {
|
942 | allowRedirectHeaders: ['User-Agent']
|
943 | });
|
944 | spec[i]['$value'] = yaml.safeLoad(spec[i]['$value'].body);
|
945 | }
|
946 | }
|
947 | spec[i]['$value'] = processor.callback(spec[i]['$value']);
|
948 | }
|
949 | }
|
950 | }
|
951 | }
|
952 | spec[i] = spec[i]['$value'];
|
953 | }
|
954 | }
|
955 | return spec;
|
956 | };
|
957 |
|
958 | sortObject = function(object) {
|
959 | return Object.keys(object).sort().reduce((function(result, key) {
|
960 | result[key] = object[key];
|
961 | return result;
|
962 | }), {});
|
963 | };
|
964 |
|
965 | module.exports = generate;
|
966 |
|
967 | }).call(this);
|