1 | #!/usr/bin/env node
|
2 |
|
3 | const program = require('commander'),
|
4 | Gateway = require('./lib/proxy'),
|
5 | fs = require('fs'),
|
6 | path = require('path'),
|
7 | watch = require('node-watch'),
|
8 | Queue = require('async/queue'),
|
9 | logger = require('./lib/logger'),
|
10 | validate = require('./lib/validators'),
|
11 | watchFilesExtensions = require('./lib/watch-files-extensions'),
|
12 | templates = require('./lib/templates'),
|
13 | settings = require('./lib/settings'),
|
14 | version = require('./package.json').version;
|
15 |
|
16 | const WATCH_DIRECTORIES = ['marketplace_builder', 'modules'];
|
17 | const getWatchDirectories = () => WATCH_DIRECTORIES.filter(fs.existsSync);
|
18 | const ext = filePath => filePath.split('.').pop();
|
19 | const filename = filePath => filePath.split(path.sep).pop();
|
20 | const filePathUnixified = filePath => filePath.replace(/\\/g, '/').replace('marketplace_builder/', '');
|
21 | const isEmpty = filePath => fs.readFileSync(filePath).toString().trim().length === 0;
|
22 | const shouldBeSynced = (filePath, event) => {
|
23 | return fileUpdated(event) && extensionAllowed(filePath) && isNotHidden(filePath) && isNotEmptyYML(filePath) && isModuleFile(filePath);
|
24 | };
|
25 |
|
26 | const fileUpdated = event => event === 'update';
|
27 |
|
28 | const extensionAllowed = filePath => {
|
29 | const allowed = watchFilesExtensions.includes(ext(filePath));
|
30 | if (!allowed) {
|
31 | logger.Debug(`[Sync] Not syncing, not allowed file extension: ${filePath}`);
|
32 | }
|
33 | return allowed;
|
34 | };
|
35 |
|
36 | const isNotHidden = filePath => {
|
37 | const isHidden = filename(filePath).startsWith('.');
|
38 |
|
39 | if (isHidden) {
|
40 | logger.Warn(`[Sync] Not syncing hidden file: ${filePath}`);
|
41 | }
|
42 | return !isHidden;
|
43 | };
|
44 |
|
45 | const isNotEmptyYML = filePath => {
|
46 | if (ext(filePath) === 'yml' && isEmpty(filePath)) {
|
47 | logger.Warn(`[Sync] Not syncing empty YML file: ${filePath}`);
|
48 | return false;
|
49 | }
|
50 |
|
51 | return true;
|
52 | };
|
53 |
|
54 |
|
55 | const isModuleFile = f => {
|
56 | let pathArray = f.split(path.sep);
|
57 | if ('modules' != pathArray[0]) {
|
58 | return true;
|
59 | }
|
60 | return ['private', 'public'].includes(pathArray[2]);
|
61 | };
|
62 |
|
63 | CONCURRENCY = 3;
|
64 |
|
65 | const queue = Queue((task, callback) => {
|
66 | pushFile(task.path).then(callback);
|
67 | }, CONCURRENCY);
|
68 |
|
69 | const enqueue = filePath => {
|
70 | queue.push({ path: filePath }, () => {});
|
71 | };
|
72 |
|
73 | const getBody = (filePath, processTemplate) => {
|
74 | if (processTemplate) {
|
75 | const templatePath = `modules/${filePath.split(path.sep)[1]}/template-values.json`;
|
76 | const moduleTemplateData = templateData(templatePath);
|
77 | return templates.fillInTemplateValues(filePath, moduleTemplateData);
|
78 | } else {
|
79 | return fs.createReadStream(filePath);
|
80 | }
|
81 | };
|
82 |
|
83 | const templateData = (path) => {
|
84 | return settings.loadSettingsFile(path);
|
85 | };
|
86 |
|
87 | const pushFile = syncedFilePath => {
|
88 | let filePath = filePathUnixified(syncedFilePath);
|
89 |
|
90 | const formData = {
|
91 | path: filePath,
|
92 | marketplace_builder_file_body: getBody(syncedFilePath, filePath.startsWith('modules'))
|
93 | };
|
94 |
|
95 | return gateway.sync(formData).then(body => {
|
96 | if (body && body.refresh_index) {
|
97 | logger.Warn('WARNING: Data schema was updated. It will take a while for the change to be applied.');
|
98 | }
|
99 |
|
100 | logger.Success(`[Sync] ${filePath} - done`);
|
101 | });
|
102 | };
|
103 |
|
104 | const checkParams = params => {
|
105 | validate.existence({ argumentValue: params.token, argumentName: 'token', fail: program.help.bind(program) });
|
106 | validate.existence({ argumentValue: params.url, argumentName: 'URL', fail: program.help.bind(program) });
|
107 | };
|
108 |
|
109 | program
|
110 | .version(version)
|
111 | .option('--email <email>', 'authentication token', process.env.MARKETPLACE_EMAIL)
|
112 | .option('--token <token>', 'authentication token', process.env.MARKETPLACE_TOKEN)
|
113 | .option('--url <url>', 'marketplace url', process.env.MARKETPLACE_URL)
|
114 |
|
115 | .parse(process.argv);
|
116 |
|
117 | checkParams(program);
|
118 |
|
119 | const gateway = new Gateway(program);
|
120 |
|
121 | gateway.ping().then(() => {
|
122 | const directories = getWatchDirectories();
|
123 |
|
124 | if (directories.length === 0) {
|
125 | logger.Error('marketplace_builder or modules directory has to exist!');
|
126 | }
|
127 |
|
128 | logger.Info(`Enabling sync mode to: ${program.url}`);
|
129 |
|
130 | watch(directories, { recursive: true }, (event, filePath) => {
|
131 | shouldBeSynced(filePath, event) && enqueue(filePath);
|
132 | });
|
133 | });
|