This repository has been archived by the owner on Dec 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.ts
120 lines (102 loc) · 3.7 KB
/
index.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
import { Command, flags } from '@oclif/command';
import fs from 'fs';
import glob from 'glob';
import { JSONSchema7 } from 'json-schema';
import outdent from 'outdent';
import { promisify } from 'util';
import compile from './src';
const generatedCodeVersion = '1.0.0';
class Svarog extends Command {
public static description = 'Generates Cloud Firestore helper functions for schema validation using JSON Schema.';
public static flags = {
force: flags.boolean({
char: 'f',
default: false,
description: 'overwrites existing Svarog code unconditionally'
}),
help: flags.help({
char: 'h',
description: 'displays this message'
}),
verbose: flags.boolean({
char: 'v',
default: false,
description: 'enables progress logs during compilation'
})
};
public static args = [
{
description: 'input file containing JSON Schema or a glob pattern',
name: 'input',
required: true
},
{
description: 'target file where Svarog will output security rule helpers',
name: 'output',
required: false
}
];
public async run() {
const timestamp = Date.now();
const command = this.parse(Svarog);
const input = command.args.input as string;
const output = command.args.output;
const isVerbose = command.flags.verbose;
const isOverwriteAllowed = command.flags.force;
const isOutputEmpty = !(await promisify(fs.exists)(output));
if (isVerbose) {
this.log(`Resolving paths for ${input}`);
}
const files = await promisify(glob)(input as string);
if (isVerbose) {
this.log(`Found ${files.length} file${files.length > 1 ? 's' : ''}`);
}
const schemas: JSONSchema7[] = [];
for (const file of files) {
if (isVerbose) this.log(`Reading ${file}`);
const data: string = await promisify(fs.readFile)(file, { encoding: 'utf-8' });
schemas.push(JSON.parse(data));
}
const rules = ([
`// <svarog version="${generatedCodeVersion}">`,
compile(schemas),
'// </svarog>'
]).join('\n');
if (output && isOutputEmpty) {
if (isVerbose) this.log(`Creating ${output}`);
await promisify(fs.writeFile)(output, rules);
} else if (output && !isOutputEmpty) {
const outputContent = await promisify(fs.readFile)(output, {
encoding: 'utf-8'
});
const svarogRegex = /\/\/\s<svarog version="(\d)\.(\d)\.(\d)">\n(.*)\n\/\/\s<\/svarog>/gm;
const svarogInfo = svarogRegex.exec(outputContent);
if (svarogInfo === null) {
if (isVerbose) this.log(`Appending Svarog to ${output}`);
await promisify(fs.writeFile)(output, `${outputContent}\n\n${rules}`);
} else {
const oldVersion = svarogInfo.slice(1, 4).join('.');
const oldMajorVersion = parseInt(svarogInfo[1], 10);
const newMajorVersion = parseInt(generatedCodeVersion.split('.')[0], 10);
const canOverwrite =
oldVersion === generatedCodeVersion ||
(oldMajorVersion === newMajorVersion && oldMajorVersion > 0);
if (canOverwrite || isOverwriteAllowed) {
if (isVerbose) this.log(`Updating Svarog in ${output}`);
const newContent = outputContent.replace(svarogInfo[0], rules);
await promisify(fs.writeFile)(output, newContent);
} else {
this.error(outdent`
Output file contains a different major or pre-release version of Svarog code,
and replacing it might break your configuration. If you know what you're doing,
please use --force flag next time.
`);
}
}
} else {
this.log(rules);
}
if (isVerbose) this.log(`Finished in ${Date.now() - timestamp}ms`);
}
}
export = Svarog;