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