UNPKG

41.6 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.10.0
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);