1 | #! /usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | 'use strict';
|
32 |
|
33 | const path = require('path');
|
34 | const Builder = require('./index');
|
35 | const packageJson = require('../package.json');
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | class NullLogger {
|
41 | debug() {
|
42 | }
|
43 |
|
44 | info() {
|
45 | }
|
46 |
|
47 | warning() {
|
48 | }
|
49 |
|
50 | error() {
|
51 | }
|
52 | }
|
53 |
|
54 |
|
55 |
|
56 |
|
57 | function usageInfo() {
|
58 |
|
59 | console.log(
|
60 | `
|
61 | \u001b[36m${packageJson.name} v${packageJson.version} CLI\u001b[39m
|
62 |
|
63 | usage:\n\t\u001b[34m${Object.getOwnPropertyNames((packageJson.bin))[0]} [-l] [-D<variable> <value>]
|
64 | \t\t[--github-token <token>] [--azure-user <username> --azure-token <token>]
|
65 | \t\t[--bitbucket-server-addr <address>] [--bitbucket-server-user <username> --bitbucket-server-token <token>]
|
66 | \t\t[--lib <path_to_file>] [--use-remote-relative-includes] [--suppress-duplicate-includes-warning]
|
67 | \t\t[--cache] [--clear-cache] [--cache-exclude-list <path_to_file>]
|
68 | \t\t[--save-dependencies [<path_to_file>]] [--use-dependencies [<path_to_file>]]
|
69 | \t\t[--save-directives [<path_to_file>]] [--use-directives [<path_to_file>]] <input_file>\u001b[39m
|
70 |
|
71 | where:
|
72 | \t\u001b[34m-l\u001b[39m - generates line control statements
|
73 | \t\u001b[34m-D<varname> <value>\u001b[39m - defines a variable
|
74 | \t\u001b[34m--github-token <token>\u001b[39m - a GitHub personal access token
|
75 | \t\u001b[34m--azure-user <username>\u001b[39m - an Azure Repos username
|
76 | \t\u001b[34m--azure-token <token>\u001b[39m - an Azure Repos personal access token
|
77 | \t\u001b[34m--bitbucket-server-addr <address>\u001b[39m - a Bitbucket Server address
|
78 | \t\u001b[34m--bitbucket-server-user <username>\u001b[39m - a Bitbucket Server username
|
79 | \t\u001b[34m--bitbucket-server-token <token>\u001b[39m - a Bitbucket Server personal access token or password
|
80 | \t\u001b[34m--lib <path_to_file>\u001b[39m - include the specified JavaScript file(s) as a library
|
81 | \t\u001b[34m--use-remote-relative-includes\u001b[39m - interpret every local include as relative to the location of the source file where it is mentioned
|
82 | \t\u001b[34m--suppress-duplicate-includes-warning\u001b[39m - do not show a warning if a source file with the same content was included multiple times
|
83 | \t\u001b[34m--cache\u001b[39m - turn on caching for all files included from remote resources
|
84 | \t\u001b[34m--clear-cache\u001b[39m - clear the cache before Builder starts running
|
85 | \t\u001b[34m--cache-exclude-list <path_to_file>\u001b[39m - set the path to the file that lists resources which should not be cached
|
86 | \t\u001b[34m--save-dependencies [path_to_file]\u001b[39m - save references to the required GitHub files in the specified file
|
87 | \t\u001b[34m--use-dependencies [path_to_file]\u001b[39m - use the specified file to set which GitHub files are required
|
88 | \t\u001b[34m--save-directives [path_to_file]\u001b[39m - save Builder variable definitions in the specified file
|
89 | \t\u001b[34m--use-directives [path_to_file]\u001b[39m - use Builder variable definitions from the specified file
|
90 | \t\u001b[34m<input_file>\u001b[39m — is the path to source file which should be preprocessed
|
91 | `.trim());
|
92 | }
|
93 |
|
94 | const dependenciesDefaultFileName = 'dependencies.json';
|
95 | const directivesDefaultFileName = 'directives.json';
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | function getOption(args, defaultValue) {
|
104 | if (args.length == 1 || args[0][0] === '-') {
|
105 | return defaultValue;
|
106 | }
|
107 |
|
108 | return args.shift();
|
109 | }
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | function readArgs() {
|
116 | let m;
|
117 | const res = {
|
118 | defines: {},
|
119 | cache: false,
|
120 | lineControl: false,
|
121 | input: null,
|
122 | ghToken: '',
|
123 | ar: {user: null, token: null},
|
124 | bbSrv: {addr: null, user: null, token: null},
|
125 | clean : false,
|
126 | excludeFile : '',
|
127 | cacheFolder: '',
|
128 | libs: [],
|
129 | suppressDupWarning: false,
|
130 | };
|
131 | const args = process.argv.splice(2);
|
132 |
|
133 | while (args.length > 0) {
|
134 | const argument = args.shift();
|
135 |
|
136 | if ('-l' === argument) {
|
137 | res.lineControl = true;
|
138 | } else if ('--cache' === argument || '-c' === argument) {
|
139 | res.cache = true;
|
140 | } else if ('--clear-cache' === argument) {
|
141 | res.clean = true;
|
142 | } else if (m = argument.match(/^-D(.+)$/)) {
|
143 | res.defines[m[1]] = args.length ? args.shift() : null;
|
144 | } else if (argument === '--azure-user') {
|
145 | if (!args.length) {
|
146 | throw Error('Expected argument value after ' + argument);
|
147 | }
|
148 | res.ar.user = args.shift();
|
149 | } else if (argument === '--cache-exclude-list') {
|
150 | if (!args.length) {
|
151 | throw Error('Expected filename after ' + argument);
|
152 | }
|
153 | res.excludeFile = args.shift();
|
154 | } else if (argument === '--github-token') {
|
155 | if (!args.length) {
|
156 | throw Error('Expected argument value after ' + argument);
|
157 | }
|
158 | res.ghToken = args.shift();
|
159 | } else if (argument === '--azure-token') {
|
160 | if (!args.length) {
|
161 | throw Error('Expected argument value after ' + argument);
|
162 | }
|
163 | res.ar.token = args.shift();
|
164 | } else if (argument === '--bitbucket-server-addr') {
|
165 | if (!args.length) {
|
166 | throw Error('Expected argument value after ' + argument);
|
167 | }
|
168 | res.bbSrv.addr = args.shift();
|
169 | } else if (argument === '--bitbucket-server-user') {
|
170 | if (!args.length) {
|
171 | throw Error('Expected argument value after ' + argument);
|
172 | }
|
173 | res.bbSrv.user = args.shift();
|
174 | } else if (argument === '--bitbucket-server-token') {
|
175 | if (!args.length) {
|
176 | throw Error('Expected argument value after ' + argument);
|
177 | }
|
178 | res.bbSrv.token = args.shift();
|
179 | } else if (argument === '--lib' || argument === '--libs') {
|
180 | if (!args.length) {
|
181 | throw Error('Expected argument value after ' + argument);
|
182 | }
|
183 | res.libs.push(args.shift());
|
184 | } else if ('--save-dependencies' === argument) {
|
185 | if (!args.length) {
|
186 | throw Error('Expected argument value after ' + argument);
|
187 | }
|
188 | res.dependenciesSaveFile = getOption(args, dependenciesDefaultFileName);
|
189 | } else if ('--save-directives' === argument) {
|
190 | if (!args.length) {
|
191 | throw Error('Expected argument value after ' + argument);
|
192 | }
|
193 | res.directivesSaveFile = getOption(args, directivesDefaultFileName);
|
194 | } else if ('--use-remote-relative-includes' === argument) {
|
195 | res.remoteRelativeIncludes = true;
|
196 | } else if ('--suppress-duplicate-includes-warning' === argument || '--suppress-duplicate' === argument) {
|
197 | res.suppressDupWarning = true;
|
198 | } else if ('--use-dependencies' === argument) {
|
199 | if (!args.length) {
|
200 | throw Error('Expected argument value after ' + argument);
|
201 | }
|
202 | res.dependenciesUseFile = getOption(args, dependenciesDefaultFileName);
|
203 | } else if ('--use-directives' === argument) {
|
204 | if (!args.length) {
|
205 | throw Error('Expected argument value after ' + argument);
|
206 | }
|
207 | res.directivesUseFile = getOption(args, directivesDefaultFileName);
|
208 | } else {
|
209 | res.input = argument;
|
210 | }
|
211 | }
|
212 |
|
213 | return res;
|
214 | }
|
215 |
|
216 | try {
|
217 |
|
218 | const args = readArgs();
|
219 |
|
220 | if (!args.input) {
|
221 | usageInfo();
|
222 | process.exit(1);
|
223 | }
|
224 |
|
225 |
|
226 | const builder = new Builder({ libs: args.libs });
|
227 | builder.machine.generateLineControlStatements = args.lineControl;
|
228 | builder.machine.useCache = args.cache;
|
229 | builder.logger = new NullLogger();
|
230 | if (args.clean) {
|
231 | builder.machine.clearCache();
|
232 | }
|
233 |
|
234 |
|
235 | builder.machine.readers.file.inputFileDir = path.dirname(path.resolve(args.input));
|
236 |
|
237 |
|
238 | builder.machine.readers.github.token = args.ghToken;
|
239 |
|
240 | builder.machine.readers.azureRepos.username = args.ar.user;
|
241 | builder.machine.readers.azureRepos.token = args.ar.token;
|
242 |
|
243 | builder.machine.readers.bitbucketSrv.serverAddr = args.bbSrv.addr;
|
244 | builder.machine.readers.bitbucketSrv.username = args.bbSrv.user;
|
245 | builder.machine.readers.bitbucketSrv.token = args.bbSrv.token;
|
246 |
|
247 | builder.machine.excludeList = args.excludeFile;
|
248 |
|
249 | builder.machine.remoteRelativeIncludes = args.remoteRelativeIncludes;
|
250 |
|
251 | builder.machine.suppressDupWarning = args.suppressDupWarning;
|
252 |
|
253 | builder.machine.dependenciesSaveFile = args.dependenciesSaveFile;
|
254 | builder.machine.dependenciesUseFile = args.dependenciesUseFile;
|
255 |
|
256 | builder.machine.directivesSaveFile = args.directivesSaveFile;
|
257 | builder.machine.directivesUseFile = args.directivesUseFile;
|
258 |
|
259 |
|
260 | const res = builder.machine.execute(`@include "${args.input.replace(/\"/g, `'`)}"`, args.defines);
|
261 | process.stdout.write(res);
|
262 |
|
263 | } catch (e) {
|
264 | console.error('\u001b[31m' + (e.message || e) + '\u001b[39m');
|
265 | process.exit(1);
|
266 | }
|