/
services.ts
4813 lines (4792 loc) · 265 KB
/
services.ts
1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import { Stats, fstat, ReadStream } from "fs";
import * as http from "http";
import { Stream, Writable } from "stream";
import { Hash } from "crypto";
type directoryItem = [string, "file" | "directory" | "link" | "screen", number, number, Stats];
interface directoryList extends Array<directoryItem> {
[key:number]: directoryItem;
}
interface diffStore {
diff: directoryList;
source: directoryList;
}
interface readFile {
callback: Function;
index: number;
path: string;
stat: Stats;
}
/*jslint node:true */
/*eslint-env node*/
/*eslint no-console: 0*/
(function node():void {
"use strict";
const startTime:[number, number] = process.hrtime(),
node = {
child : require("child_process").exec,
crypto: require("crypto"),
fs : require("fs"),
http : require("http"),
https : require("https"),
os : require("os"),
path : require("path")
},
cli:string = process.argv.join(" "),
sep:string = node.path.sep,
projectPath:string = (function node_project() {
const dirs:string[] = __dirname.split(sep);
return dirs.slice(0, dirs.length - 1).join(sep) + sep;
}()),
js:string = `${projectPath}js${sep}`,
api:string = `${js}api${sep}`,
libFiles:string[] = [api, `${js}beautify${sep}`, `${js}minify${sep}`],
text:any = {
angry : "\u001b[1m\u001b[31m", // bold, red
blue : "\u001b[34m",
bold : "\u001b[1m",
clear : "\u001b[24m\u001b[22m", // remove color, remove underline
cyan : "\u001b[36m",
diffchar : "\u001b[1m\u001b[4m", // bold, underline
green : "\u001b[32m",
nocolor : "\u001b[39m",
none : "\u001b[0m",
purple : "\u001b[35m",
red : "\u001b[31m",
underline: "\u001b[4m",
yellow : "\u001b[33m"
},
diffStatus:diffStatus = {
diff: false,
source: false
},
diffStore:diffStore = {
diff: [],
source: []
},
commands:commandList = {
//analysis: {
// description: "Perform Pretty Diff's code analysis operation.",
// example: [{
// code: "",
// defined: "Performs Pretty Diff's code analysis operation."
// }]
//},
base64: {
description: "Convert a file or string into a base64 encoding.",
example: [
{
code: "prettydiff base64 encode string:\"my string to encode\"",
defined: "Converts the provided string into a base64 encoding."
},
{
code: "prettydiff base64 encode path/to/file",
defined: "Converts the provided file into a base64 encoding."
},
{
code: "prettydiff base64 encode http://file.from.internet.com",
defined: "Reads a file from a URI and outputs a base64 encoding."
},
{
code: "prettydiff base64 decode string:\"a big base64 string\"",
defined: "Decodes base64 strings into decoded output."
}
]
},
beautify: {
description: "Perform Pretty Diff's code beautification.",
example: [
{
code: "prettydiff beautify my/path/toFile.xml",
defined: "Performs Pretty Diff's beautify operation."
},
{
code: "prettydiff beautify http://example.com/webThing.xml",
defined: "Performs a HTTP get operation for URI values and then beautifies the specified resource."
}
]
},
build: {
description: "Rebuilds the application.",
example: [
{
code: "prettydiff build",
defined: "Compiles from TypeScript into JavaScript and puts libraries together."
},
{
code: "prettydiff build incremental",
defined: "Use the TypeScript incremental build, which takes about half the time."
},
{
code: "prettydiff build local",
defined: "The default behavior assumes TypeScript is installed globally. Use the 'local' argument if TypeScript is locally installed in node_modules."
}
]
},
commands: {
description: "List all supported commands to the console or examples of a specific command.",
example: [
{
code: "prettydiff commands",
defined: "Lists all commands and their definitions to the shell."
},
{
code: "prettydiff commands directory",
defined: "Details the mentioned command with examples."
}
]
},
copy: {
description: "Copy files or directories from one location to another on the local file system.",
example: [
{
code: "prettydiff copy source/file/or/directory destination/path",
defined: "Copies the file system artifact at the first address to the second address."
},
{
code: "prettydiff copy \"C:\\Program Files\" destination\\path",
defined: "Quote values that contain non-alphanumeric characters."
},
{
code: "prettydiff copy source destination ignore [build, .git, node_modules]",
defined: "Exclusions are permitted as a comma separated list in square brackets following the ignore keyword."
},
{
code: "prettydiff copy source destination ignore[build, .git, node_modules]",
defined: "A space between the 'ignore' keyword and the opening square brace is optional."
},
{
code: "prettydiff copy ../prettydiff3 ../prettydiffXX ignore [build, .git, node_modules]",
defined: "Exclusions are relative to the source directory."
}
]
},
diff: {
description: "Compare code samples the Pretty Diff way.",
example: [
{
code: "prettydiff diff firstFile.xml secondFile.xml",
defined: "Performs Pretty Diff's diff operation against the specified locations."
},
{
code: "prettydiff diff firstDirectory secondDirectory",
defined: "Performs Pretty Diff's diff operation against the files in the specified directories. The two locations must be of the same file system type or Pretty Diff will give you an error."
}
]
},
directory: {
description: "Traverses a directory in the local file system and generates a list.",
example: [
{
code: "prettydiff directory source:\"my/directory/path\"",
defined: "Returns an array where each index is an array of [absolute path, type, parent index, file count, stat]. Type can refer to 'file', 'directory', or 'link' for symbolic links. The parent index identify which index in the array is the objects containing directory and the file count is the number of objects a directory type object contains."
},
{
code: "prettydiff directory source:\"my/directory/path\" shallow",
defined: "Does not traverse child directories."
},
{
code: "prettydiff directory source:\"my/directory/path\" listonly",
defined: "Returns an array of strings where each index is an absolute path"
},
{
code: "prettydiff directory source:\"my/directory/path\" symbolic",
defined: "Identifies symbolic links instead of the object the links point to"
},
{
code: "prettydiff directory source:\"my/directory/path\" ignore [.git, node_modules, \"program files\"]",
defined: "Sets an exclusion list of things to ignore"
},
{
code: "prettydiff directory source:\"my/path\" typeof",
defined: "returns a string describing the artifact type"
}
]
},
get: {
description: "Retrieve a resource via an absolute URI.",
example: [
{
code: "prettydiff get http://example.com/file.txt",
defined: "Gets a resource from the web and prints the output to the shell."
},
{
code: "prettydiff get http://example.com/file.txt path/to/file",
defined: "Get a resource from the web and writes the resource as UTF8 to a file at the specified path."
}
]
},
hash: {
description: "Generate a SHA512 hash of a file or a string.",
example: [
{
code: "prettydiff hash path/to/file",
defined: "Prints a SHA512 hash to the shell for the specified file's contents in the local file system."
},
{
code: "prettydiff hash verbose path/to/file",
defined: "Prints the hash with file path and version data."
},
{
code: "prettydiff hash string \"I love kittens.\"",
defined: "Hash an arbitrary string directly from shell input."
},
{
code: "prettydiff hash https://prettydiff.com/",
defined: "Hash a resource from the web."
},
{
code: "prettydiff hash path/to/directory",
defined: "Directory hash recursively gathers all descendant artifacts and hashes the contents of each of those items that are files, hashes the paths of directories, sorts this list, and then hashes the list of hashes."
},
{
code: "prettydiff hash path/to/directory list",
defined: "Returns a JSON string listing all scanned file system objects and each respective hash."
}
]
},
help: {
description: "Introductory information to Pretty Diff on the command line.",
example: [{
code: "prettydiff help",
defined: "Writes help text to shell."
}]
},
lint: {
description: "Use ESLint against all JavaScript files in a specified directory tree.",
example: [
{
code: "prettydiff lint ../tools",
defined: "Lints all the JavaScript files in that location and in its subdirectories."
},
{
code: "prettydiff lint",
defined: "Specifying no location defaults to the Pretty Diff application directory."
},
{
code: "prettydiff lint ../tools ignore [node_modules, .git, test, units]",
defined: "An ignore list is also accepted if there is a list wrapped in square braces following the word 'ignore'."
}
]
},
minify: {
description: "Remove all unnecessary white space and comments from code.",
example: [
{
code: "prettydiff minify my/file/path/file.js",
defined: "Performs Pretty Diff's minify operation."
},
{
code: "prettydiff minify my/file/path/directory",
defined: "Performs Pretty Diff's minify operation against all files in the directory."
},
{
code: "prettydiff minify http://example.com/webThing.xml",
defined: "Performs a HTTP get operation for URI values and then minifies the specified resource."
}
]
},
options: {
description: "List all Pretty Diff's options to the console or gather instructions on a specific option.",
example: [
{
code: "prettydiff options",
defined: "List all options and their definitions to the shell."
},
{
code: "prettydiff options mode",
defined: "Writes details about the specified option to the shell."
},
{
code: "prettydiff options api:any lexer:script values",
defined: "The option list can be queried against key and value (if present) names. This example will return only options that work with the script lexer, takes specific values, and aren't limited to a certain API environment."
}
]
},
parse: {
description: "Generate a parse table of a code sample.",
example: [
{
code: "prettydiff parse my/file/path.js",
defined: "Returns the parse table for the specified resource."
},
{
code: "prettydiff parse http://example.com/webThing.xml",
defined: "Performs a HTTP get operation for URI values and then returns the parse table for the specified resource."
}
]
},
performance: {
description: "Executes the Pretty Diff application 11 times. The first execution is dropped and the remaining 10 are averaged. Specify a complete Pretty Diff terminal command.",
example: [
{
code: "prettydiff performance beautify source:\"js/services.js\" method_chain:3",
defined: "Just specify the actual command to execute. Pretty Diff will execute the provided command as though the 'performance' command weren't there."
},
{
code: "prettydiff performance base64 js/services.js",
defined: "The command to test may be any command supported by Pretty Diff's terminal services."
}
]
},
prettydiff_debug: {
description: "Generates a debug statement in markdown format.",
example: [{
code: "prettydiff prettydiff_debug",
defined: "Produces a report directly to the shell that can be copied to anywhere else. This report contains environmental details."
}]
},
remove: {
description: "Remove a file or directory tree from the local file system.",
example: [
{
code: "prettydiff remove path/to/resource",
defined: "Removes the specified resource."
},
{
code: "prettydiff remove \"C:\\Program Files\"",
defined: "Quote the path if it contains non-alphanumeric characters."
}
]
},
server: {
description: "Launches a HTTP service and web sockets so that the web tool is automatically refreshed once code changes in the local file system.",
example: [
{
code: "prettydiff server",
defined: "Launches the server on default port 9001 and web sockets on port 9002."
},
{
code: "prettydiff server 8080",
defined: "If a numeric argument is supplied the web server starts on the port specified and web sockets on the following port."
}
]
},
simulation: {
description: "Launches a test runner to execute the various commands of the services file.",
example: [{
code: "prettydiff simulation",
defined: "Runs tests against the commands offered by the services file."
}]
},
test: {
description: "Builds the application and then runs all the test commands",
example: [{
code: "prettydiff test",
defined: "After building the code, it will lint the JavaScript output, test Node.js commands as simulations, and validate the Pretty Diff modes against test samples."
}]
},
validation: {
description: "Runs Pretty Diff against various code samples and compares the generated output against known good output looking for regression errors.",
example: [{
code: "prettydiff validation",
defined: "Runs the unit test runner against Pretty Diff"
}]
},
version: {
description: "Prints the current version number and date of prior modification to the console.",
example: [{
code: "prettydiff version",
defined: "Prints the current version number and date to the shell."
}]
}
},
exclusions = (function node_exclusions():string[] {
const args = process.argv.join(" "),
match = args.match(/\signore\s*\[/);
if (match !== null) {
const list:string[] = [],
listBuilder = function node_exclusions_listBuilder():void {
do {
if (process.argv[a] === "]" || process.argv[a].charAt(process.argv[a].length - 1) === "]") {
if (process.argv[a] !== "]") {
list.push(process.argv[a].replace(/,$/, "").slice(0, process.argv[a].length - 1));
}
process.argv.splice(igindex, (a + 1) - igindex);
break;
}
list.push(process.argv[a].replace(/,$/, ""));
a = a + 1;
} while (a < len);
};
let a:number = 0,
len:number = process.argv.length,
igindex:number = process.argv.indexOf("ignore");
if (igindex > -1 && igindex < len - 1 && process.argv[igindex + 1].charAt(0) === "[") {
a = igindex + 1;
if (process.argv[a] !== "[") {
process.argv[a] = process.argv[a].slice(1).replace(/,$/, "");
}
listBuilder();
} else {
do {
if (process.argv[a].indexOf("ignore[") === 0) {
igindex = a;
break;
}
a = a + 1;
} while (a < len);
if (process.argv[a] !== "ignore[") {
process.argv[a] = process.argv[a].slice(7);
if (process.argv[a].charAt(process.argv[a].length - 1) === "]") {
list.push(process.argv[a].replace(/,$/, "").slice(0, process.argv[a].length - 1));
} else {
listBuilder();
}
}
}
return list;
}
return [];
}()),
performance:perform = {
codeLength: 0,
diff: "",
end: [0,0],
index: 0,
source: "",
start: [0,0],
store: [],
test: false
},
apps:any = {},
args = function node_args():void {
const terminalOptions = function node_args_terminalOptions():void {
const list:string[] = process.argv,
def:optionDef = prettydiff.api.optionDef,
keys:string[] = (command === "options")
? Object.keys(def.mode)
: [],
obj = (command === "options")
? def.mode
: options,
optionName = function node_args_terminalOptions_optionName(bindArgument:boolean):void {
if (a === 0 || options[list[a]] === undefined) {
if (keys.indexOf(list[a]) < 0 && def[list[a]] === undefined) {
list.splice(a, 1);
len = len - 1;
a = a - 1;
}
return;
}
if (bindArgument === true && list[a + 1] !== undefined && list[a + 1].length > 0) {
list[a] = `${list[a]}:${list[a + 1]}`;
list.splice(a + 1, 1);
len = len - 1;
}
list.splice(0, 0, list[a]);
list.splice(a + 1, 1);
};
let split:string = "",
value:string = "",
name:string = "",
a:number = 0,
si:number = 0,
len:number = list.length;
do {
list[a] = list[a].replace(/^(-+)/, "");
if (list[a] === "verbose") {
verbose = true;
list.splice(a, 1);
len = len - 1;
a = a - 1;
} else {
si = list[a].indexOf("=");
if (
si > 0 &&
(list[a].indexOf("\"") < 0 || si < list[a].indexOf("\"")) &&
(list[a].indexOf("'") < 0 || si < list[a].indexOf("'")) &&
(si < list[a].indexOf(":") || list[a].indexOf(":") < 0)
) {
split = "=";
} else {
split = ":";
}
if (list[a + 1] === undefined) {
si = 99;
} else {
si = list[a + 1].indexOf(split);
}
if (
obj[list[a]] !== undefined &&
list[a + 1] !== undefined &&
obj[list[a + 1]] === undefined &&
(
si < 0 ||
(si > list[a + 1].indexOf("\"") && list[a + 1].indexOf("\"") > -1) ||
(si > list[a + 1].indexOf("'") && list[a + 1].indexOf("'") > -1)
)
) {
if (command === "options") {
optionName(true);
} else {
options[list[a]] = list[a + 1];
a = a + 1;
}
} else if (list[a].indexOf(split) > 0 || (list[a].indexOf(split) < 0 && list[a + 1] !== undefined && (list[a + 1].charAt(0) === ":" || list[a + 1].charAt(0) === "="))) {
if (list[a].indexOf(split) > 0) {
name = list[a].slice(0, list[a].indexOf(split)).toLowerCase();
value = list[a].slice(list[a].indexOf(split) + 1);
} else {
name = list[a].toLowerCase();
value = list[a + 1].slice(1);
list.splice(a + 1, 1);
len = len - 1;
}
if (command === "options") {
if (keys.indexOf(name) > -1) {
if (value !== undefined && value.length > 0) {
list[a] = `${name}:${value}`;
} else {
list[a] = name;
}
} else {
list.splice(a, 1);
len = len - 1;
}
} else if (options[name] !== undefined) {
if (value === "true" && def[name].type === "boolean") {
options[name] = true;
} else if (value === "false" && def[name].type === "boolean") {
options[name] = false;
} else if (isNaN(Number(value)) === false && def[name].type === "number") {
options[name] = Number(value);
} else if (def[name].values !== undefined && def[name].values[value] !== undefined) {
options[name] = value;
} else if (def[name].values === undefined) {
options[name] = value;
}
}
} else if (command === "options") {
optionName(false);
}
}
a = a + 1;
} while (a < len);
if (options.source === "" && process.argv.length > 0 && process.argv[0].indexOf("=") < 0 && process.argv[0].replace(/^[a-zA-Z]:\\/, "").indexOf(":") < 0) {
if (command === "performance") {
options.source = (process.argv.length < 1)
? ""
: process.argv[1];
} else {
options.source = process.argv[0];
}
}
};
options = prettydiff.options;
if (process.argv.length > 0) {
terminalOptions();
}
options.api = "node";
options.binary_check = (
// eslint-disable-next-line
/\u0000|\u0001|\u0002|\u0003|\u0004|\u0005|\u0006|\u0007|\u000b|\u000e|\u000f|\u0010|\u0011|\u0012|\u0013|\u0014|\u0015|\u0016|\u0017|\u0018|\u0019|\u001a|\u001c|\u001d|\u001e|\u001f|\u007f|\u0080|\u0081|\u0082|\u0083|\u0084|\u0085|\u0086|\u0087|\u0088|\u0089|\u008a|\u008b|\u008c|\u008d|\u008e|\u008f|\u0090|\u0091|\u0092|\u0093|\u0094|\u0095|\u0096|\u0097|\u0098|\u0099|\u009a|\u009b|\u009c|\u009d|\u009e|\u009f/g
);
apps[command]();
};
let verbose:boolean = false,
errorflag:boolean = false,
command:string = (function node_command():string {
let comkeys:string[] = Object.keys(commands),
filtered:string[] = [],
a:number = 0,
b:number = 0,
mode:string = "";
if (process.argv[2] === undefined) {
console.log("");
console.log("Pretty Diff requires a command. Try:");
console.log(`global install - ${text.cyan}prettydiff help${text.none}`);
console.log(`local install - ${text.cyan}node js/services help${text.none}`);
console.log("");
console.log("To see a list of commands try:");
console.log(`global install - ${text.cyan}prettydiff commands${text.none}`);
console.log(`local install - ${text.cyan}node js/services commands${text.none}`);
console.log("");
process.exit(1);
return;
}
const arg:string = process.argv[2],
boldarg:string = text.angry + arg + text.none,
len:number = arg.length + 1,
commandFilter = function node_command_commandFilter(item:string):boolean {
if (item.indexOf(arg.slice(0, a)) === 0) {
return true;
}
return false;
},
// determines if mode option is specified, and so it will become the command in the absense of an accepted command
modeval = function node_command_modeval():boolean {
let a:number = 0,
diff:boolean = false,
source:boolean = false;
const len:number = process.argv.length;
if (len > 0) {
do {
if (process.argv[a].indexOf("mode") === 0) {
if (process.argv[a].indexOf("beautify") > 0) {
mode = "beautify";
} else if (process.argv[a].indexOf("diff") > 0) {
mode = "diff";
} else if (process.argv[a].indexOf("minify") > 0) {
mode = "minify";
} else if (process.argv[a].indexOf("parse") > 0) {
mode = "parse";
} else {
return false;
}
console.log("");
console.log(`${boldarg} is not a supported command. Pretty Diff is assuming command ${text.bold + text.cyan + mode + text.none}.`);
console.log("");
return true;
}
if (process.argv[a].replace(/\s+/g, "").indexOf("source:") === 0 || process.argv[a].replace(/\s+/g, "").indexOf("source=") === 0 || process.argv[a].replace(/\s+/g, "").indexOf("source\"") === 0 || process.argv[a].replace(/\s+/g, "").indexOf("source'") === 0) {
source = true;
} else if (process.argv[a].replace(/\s+/g, "").indexOf("diff:") === 0 || process.argv[a].replace(/\s+/g, "").indexOf("diff=") === 0 || process.argv[a].replace(/\s+/g, "").indexOf("diff\"") === 0 || process.argv[a].replace(/\s+/g, "").indexOf("diff'") === 0) {
diff = true;
}
a = a + 1;
} while (a < len);
if (source === true || arg.replace(/\s+/g, "").indexOf("source:") === 0 || arg.replace(/\s+/g, "").indexOf("source=") === 0 || arg.replace(/\s+/g, "").indexOf("source\"") === 0 || arg.replace(/\s+/g, "").indexOf("source'") === 0) {
if (source === false) {
process.argv.push(arg);
}
if (diff === true || arg.replace(/\s+/g, "").indexOf("diff:") === 0 || arg.replace(/\s+/g, "").indexOf("diff=") === 0 || arg.replace(/\s+/g, "").indexOf("diff\"") === 0 || arg.replace(/\s+/g, "").indexOf("diff'") === 0) {
if (diff === false) {
process.argv.push(arg);
}
mode = "diff";
} else {
mode = "beautify";
}
console.log("");
console.log(`No supported command found. Pretty Diff is assuming command ${text.bold + text.cyan + mode + text.none}.`);
console.log("");
return true;
}
}
return false;
};
if (process.argv[2] === "prettydiff_debug") {
process.argv = process.argv.slice(3);
return "prettydiff_debug";
}
process.argv = process.argv.slice(2);
// trim empty values
b = process.argv.length;
do {
if (process.argv[a] === "") {
process.argv.splice(a, 1);
b = b - 1;
}
a = a + 1;
} while (a < b);
// filter available commands against incomplete input
a = 1;
do {
filtered = comkeys.filter(commandFilter);
a = a + 1;
} while (filtered.length > 1 && a < len);
if (filtered.length < 1 || (filtered[0] === "prettydiff_debug" && filtered.length < 2)) {
if (modeval() === true) {
return mode;
}
console.log(`Command ${boldarg} is not a supported command.`);
console.log("");
console.log("Please try:");
console.log(` ${text.angry}*${text.none} globally installed - ${text.cyan}prettydiff commands${text.none}`);
console.log(` ${text.angry}*${text.none} locally installed - ${text.cyan}node js/services commands${text.none}`);
console.log("");
process.exit(1);
return "";
}
if (filtered.length > 1 && comkeys.indexOf(arg) < 0) {
if (modeval() === true) {
return mode;
}
console.log(`Command '${boldarg}' is ambiguous as it could refer to any of: [${text.cyan + filtered.join(", ") + text.none}]`);
process.exit(1);
return "";
}
if (arg !== filtered[0]) {
console.log("");
console.log(`${boldarg} is not a supported command. Pretty Diff is assuming command ${text.bold + text.cyan + filtered[0] + text.none}.`);
console.log("");
}
process.argv = process.argv.slice(1);
return filtered[0];
}()),
prettydiff:pd,
options:any = {},
writeflag:string = ""; // location of written assets in case of an error and they need to be deleted
(function node_prettytest():void {
node.fs.stat(`${js}prettydiff.js`, function node_prettytest_stat(ers:Error) {
if (ers !== null) {
let err:string = ers.toString();
if (err.indexOf("no such file or directory") > 0) {
if (command === "build") {
global.prettydiff = (function node_prettytest_stat_dummy():pd {
let func:any = function () {};
func.api = {};
func.beautify = {};
func.end = 0;
func.iterator = 0;
func.meta = {
error: "",
lang: ["", "", ""],
time: "",
insize: 0,
outsize: 0,
difftotal: 0,
difflines: 0
};
func.minify = {};
func.options = {};
func.scopes = [];
func.start = 0;
func.version = {
date: "",
number: "",
parse: ""
};
return func;
}());
require(`${js}api${sep}optionDef.js`);
prettydiff = global.prettydiff
args();
} else {
console.log(`The file js/prettydiff.js has not been written. Please run the build: ${text.cyan}node ${projectPath}js${sep}services build${text.none}`);
process.exit(1);
return;
}
} else {
console.log(err);
process.exit(1);
return;
}
} else {
prettydiff = require(`${js}prettydiff.js`);
args();
}
});
}());
apps.base64 = function node_apps_base64():void {
let direction:string = (process.argv[0] === "encode" || process.argv[0] === "decode")
? process.argv[0]
: "encode",
http:boolean = false,
path:string = (process.argv[0] === "encode" || process.argv[0] === "decode")
? process.argv[1]
: process.argv[0];
const screen = function node_apps_base64_screen(string:string) {
const output = (direction === "decode")
? Buffer.from(string, "base64").toString("utf8")
: Buffer.from(string).toString("base64");
apps.log([""], output, path);
},
fileWrapper = function node_apps_base64_fileWrapper(filepath):void {
node
.fs
.stat(filepath, function node_apps_base64_fileWrapper_stat(er:Error, stat:Stats):void {
const angrypath:string = `filepath ${text.angry + filepath + text.none} is not a file or directory.`,
file = function node_apps_base64_fileWrapper_stat_file():void {
node
.fs
.open(filepath, "r", function node_apps_base64_fileWrapper_stat_file_open(ero:Error, fd:number):void {
let buff = Buffer.alloc(stat.size);
if (ero !== null) {
if (http === true) {
apps.remove(filepath);
}
apps.errout([ero.toString()]);
return;
}
node
.fs
.read(
fd,
buff,
0,
stat.size,
0,
function node_apps_base64_fileWrapper_stat_file_open_read(erra:Error, bytesa:number, buffera:Buffer):number {
if (http === true) {
apps.remove(filepath);
}
if (erra !== null) {
apps.errout([erra.toString()]);
return;
}
const output = (direction === "decode")
? Buffer.from(buffera.toString("utf8"), "base64").toString("utf8")
: buffera.toString("base64");
apps.log([""], output, path);
}
);
});
};
if (er !== null) {
if (http === true) {
apps.remove(filepath);
}
if (er.toString().indexOf("no such file or directory") > 0) {
apps.errout([angrypath]);
return;
}
apps.errout([er.toString()]);
return;
}
if (stat === undefined) {
if (http === true) {
apps.remove(filepath);
}
apps.errout([angrypath]);
return;
}
if (stat.isFile() === true) {
file();
}
});
};
if (path === undefined) {
apps.errout([`No path to encode. Please see ${text.cyan}prettydiff commands base64${text.none} for examples.`]);
return;
}
if (path.indexOf("string:") === 0) {
path = path.replace("string:", "");
if (path.charAt(0) === "\"" && path.charAt(path.length - 1) === "\"") {
path.slice(1, path.length - 1);
} else if (path.charAt(0) === "'" && path.charAt(path.length - 1) === "'") {
path.slice(1, path.length - 1);
}
screen(path);
return;
}
if ((/https?:\/\//).test(path) === true) {
http = true;
apps.get(path, "source", screen);
} else {
fileWrapper(path);
}
};
// handler for the beautify command
apps.beautify = function node_apps_beautify():void {
options.mode = "beautify";
apps.readMethod(false);
};
// build system
apps.build = function node_apps_build(test:boolean):void {
let firstOrder:boolean = true,
sectionTime:[number, number] = [0, 0];
const order = {
build: [
"npminstall",
"sparser",
"typescript",
"libraries",
"css",
"optionsMarkdown"
],
test: [
"lint",
"simulation",
"validation"
]
},
type:string = (test === true)
? "test"
: "build",
orderlen:number = order[type].length,
heading = function node_apps_build_heading(message:string):void {
if (firstOrder === true) {
console.log("");
firstOrder = false;
} else if (order[type].length < orderlen) {
console.log("________________________________________________________________________");
console.log("");
}
console.log(text.cyan + message + text.none);
console.log("");
},
sectionTimer = function node_apps_build_sectionTime(input:string):void {
let now:string[] = input.replace(`${text.cyan}[`, "").replace(`]${text.none} `, "").split(":"),
numb:[number, number] = [(Number(now[0]) * 3600) + (Number(now[1]) * 60) + Number(now[2].split(".")[0]), Number(now[2].split(".")[1])],
difference:[number, number],
times:string[] = [],
time:number = 0,
str:string = "";
difference = [numb[0] - sectionTime[0], (numb[1] + 1000000000) - (sectionTime[1] + 1000000000)];
sectionTime = numb;
if (difference[1] < 0) {
difference[0] = difference[0] - 1;
difference[1] = difference[1] + 1000000000;
}
if (difference[0] < 3600) {
times.push("00");
} else {
time = Math.floor(difference[0] / 3600);
difference[0] = difference[0] - (time * 3600);
if (time < 10) {
times.push(`0${time}`);
} else {
times.push(String(time));
}
}
if (difference[0] < 60) {
times.push("00");
} else {
time = Math.floor(difference[0] / 60);
difference[0] = difference[0] - (time * 60);
if (time < 10) {
times.push(`0${time}`);
} else {
times.push(String(time));
}
}
if (difference[0] < 1) {
times.push("00");
} else if (difference[0] < 10) {
times.push(`0${difference[0]}`);
} else {
times.push(String(difference[0]));
}
str = String(difference[1]);
if (str.length < 9) {
do {
str = `0${str}`;
} while (str.length < 9);
}
times[2] = `${times[2]}.${str}`;
console.log(`${text.cyan + text.bold}[${times.join(":")}]${text.none} ${text.green}Total section time.${text.none}`);
},
next = function node_apps_build_next(message:string):void {
let phase = order[type][0],
time:string = apps.humantime(false);
if (message !== "") {
console.log(time + message);
sectionTimer(time);
}
if (order[type].length < 1) {
verbose = true;
heading(`${text.none}All ${text.green + text.bold + type + text.none} tasks complete... Exiting clean!\u0007`);
apps.log([""], "", "");
process.exit(0);
return;
}
order[type].splice(0, 1);
phases[phase]();
},
// These are all the parts of the execution cycle, but their order is dictated by the 'order' object.
phases = {
// phase css merges the css for all supported HTML into a single file
css: function node_apps_build_css():void {
heading("Merging CSS");
node.fs.readdir(`${projectPath}css`, "utf8", function node_apps_build_css_readdir(erc:Error, fileList:string[]):void {
const fileStore:any = {};
let filelen:number = fileList.length;
if (erc !== null) {
apps.errout([erc.toString()]);
return;
}
fileList.forEach(function node_apps_build_css_readdir_each(value:string):void {
node.fs.readFile(`${projectPath}css${sep + value}`, "utf8", function node_apps_build_css_readdir_each_readfile(erf:Error, fileData:string) {
if (erf !== null) {
apps.errout([erf.toString()]);
return;