@znemz/cfn-include 1.6.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +602 -21
- package/bin/cli.js +163 -110
- package/index.js +597 -190
- package/lib/cfnclient.js +42 -19
- package/lib/include/api.js +2 -3
- package/lib/parselocation.js +6 -2
- package/lib/promise.js +19 -24
- package/lib/replaceEnv.js +17 -11
- package/lib/schema.js +58 -9
- package/lib/yaml.js +11 -15
- package/package.json +62 -38
package/lib/cfnclient.js
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const {
|
|
2
|
+
CloudFormationClient,
|
|
3
|
+
ValidateTemplateCommand,
|
|
4
|
+
} = require('@aws-sdk/client-cloudformation');
|
|
5
|
+
const { S3Client, PutObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3');
|
|
6
|
+
const { addProxyToClient } = require('aws-sdk-v3-proxy');
|
|
7
|
+
|
|
2
8
|
const { posix: path } = require('path');
|
|
3
9
|
const crypto = require('crypto');
|
|
4
10
|
|
|
11
|
+
const S3 = (opts = {}) => addProxyToClient(new S3Client(opts));
|
|
12
|
+
const CloudFormation = (opts = {}) => addProxyToClient(new CloudFormationClient(opts));
|
|
13
|
+
|
|
5
14
|
class Client {
|
|
6
15
|
constructor({ region = 'us-east-1', bucket, prefix }) {
|
|
7
|
-
this.client =
|
|
16
|
+
this.client = CloudFormation({
|
|
8
17
|
region,
|
|
9
18
|
});
|
|
10
|
-
this.s3 =
|
|
19
|
+
this.s3 = S3();
|
|
11
20
|
this.bucket = bucket;
|
|
12
21
|
this.prefix = prefix;
|
|
13
22
|
this.region = region;
|
|
@@ -21,22 +30,28 @@ class Client {
|
|
|
21
30
|
|
|
22
31
|
async uploadTemplate(tpl, callback) {
|
|
23
32
|
const key = path.join(this.prefix, `${this.digest(tpl)}.json`);
|
|
24
|
-
await this.s3.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
await this.s3.Send(
|
|
34
|
+
new PutObjectCommand({
|
|
35
|
+
Body: tpl,
|
|
36
|
+
Bucket: this.bucket,
|
|
37
|
+
Key: key,
|
|
38
|
+
})
|
|
39
|
+
);
|
|
29
40
|
|
|
30
41
|
let res, err;
|
|
31
42
|
try {
|
|
32
43
|
res = await callback(key);
|
|
33
|
-
} catch(e) {
|
|
44
|
+
} catch (e) {
|
|
34
45
|
err = e;
|
|
35
46
|
}
|
|
36
|
-
await this.s3
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
await this.s3
|
|
48
|
+
.send(
|
|
49
|
+
new DeleteObjectCommand({
|
|
50
|
+
Bucket: this.bucket,
|
|
51
|
+
Key: key,
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
.catch(() => {});
|
|
40
55
|
if (err) throw err;
|
|
41
56
|
return res;
|
|
42
57
|
}
|
|
@@ -50,14 +65,22 @@ class Client {
|
|
|
50
65
|
throw 'Template exceeds maximum size of 450k';
|
|
51
66
|
}
|
|
52
67
|
if (needsUpload) {
|
|
53
|
-
return this.uploadTemplate(tpl, (key) =>
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
return this.uploadTemplate(tpl, (key) =>
|
|
69
|
+
this.client
|
|
70
|
+
.send(
|
|
71
|
+
new ValidateTemplateCommand({
|
|
72
|
+
TemplateURL: `https://s3.${this.region}.amazonaws.com/${this.bucket}/${key}`,
|
|
73
|
+
})
|
|
74
|
+
)
|
|
75
|
+
.promise()
|
|
76
|
+
);
|
|
56
77
|
}
|
|
57
78
|
|
|
58
|
-
return this.client.
|
|
59
|
-
|
|
60
|
-
|
|
79
|
+
return this.client.send(
|
|
80
|
+
new ValidateTemplateCommand({
|
|
81
|
+
TemplateBody: tpl,
|
|
82
|
+
})
|
|
83
|
+
);
|
|
61
84
|
}
|
|
62
85
|
}
|
|
63
86
|
|
package/lib/include/api.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
var _ = require('lodash'),
|
|
2
2
|
AWS = require('aws-sdk-proxy'),
|
|
3
|
-
jmespath = require('jmespath')
|
|
4
|
-
{ getParser } = require('./query');
|
|
3
|
+
jmespath = require('jmespath');
|
|
5
4
|
|
|
6
5
|
module.exports = function(args) {
|
|
7
6
|
var service = new AWS[args.service](args.region ? { region: args.region } : null);
|
|
8
7
|
return service[args.action](args.parameters ? args.parameters : {}).promise().then(function(res) {
|
|
9
|
-
return args.query ?
|
|
8
|
+
return args.query ? jmespath.search(res, args.query) : res;
|
|
10
9
|
});
|
|
11
10
|
}
|
package/lib/parselocation.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
var
|
|
1
|
+
var { isUndefined } = require('lodash');
|
|
2
2
|
|
|
3
3
|
module.exports = function parseLocation(location) {
|
|
4
4
|
if(!location) return {};
|
|
5
|
+
if (!location.match) {
|
|
6
|
+
console.error('location.match is not a function', location);
|
|
7
|
+
}
|
|
5
8
|
var parsed = location.match(/^(((\w+):)?\/\/)?(.*?)([\\\/](.*))?$/);
|
|
9
|
+
|
|
6
10
|
return {
|
|
7
11
|
protocol: parsed[3],
|
|
8
12
|
host: parsed[4],
|
|
9
13
|
path: parsed[5],
|
|
10
|
-
relative:
|
|
14
|
+
relative: isUndefined(parsed[1]),
|
|
11
15
|
raw: location,
|
|
12
16
|
};
|
|
13
17
|
}
|
package/lib/promise.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
+
const Promise = require('bluebird');
|
|
2
|
+
const _ = require('lodash');
|
|
1
3
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var awaitables = [];
|
|
11
|
-
var keys = Object.keys(obj);
|
|
12
|
-
for (var i = 0; i < keys.length; i++) {
|
|
13
|
-
var key = keys[i];
|
|
14
|
-
var a$ = obj[key];
|
|
15
|
-
awaitables.push(a$);
|
|
16
|
-
}
|
|
17
|
-
return Promise.all(awaitables).then(function (results) {
|
|
18
|
-
var byName = {};
|
|
19
|
-
for (var i = 0; i < keys.length; i++) {
|
|
20
|
-
var key = keys[i];
|
|
21
|
-
byName[key] = results[i];
|
|
4
|
+
/*
|
|
5
|
+
Maps over objects or iterables just like lodash.
|
|
6
|
+
*/
|
|
7
|
+
const mapWhatever = (promises, cb) =>
|
|
8
|
+
Promise.try(() =>
|
|
9
|
+
Promise.resolve(promises).then((arrayOrObject) => {
|
|
10
|
+
if (_.isArray(arrayOrObject)) {
|
|
11
|
+
return Promise.map(arrayOrObject, cb);
|
|
22
12
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
const size = Object.values(arrayOrObject).length;
|
|
14
|
+
return Promise.all(_.map(arrayOrObject, (value, key) => cb(value, key, size)));
|
|
15
|
+
})
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
mapWhatever,
|
|
20
|
+
mapX: mapWhatever,
|
|
21
|
+
};
|
package/lib/replaceEnv.js
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const passThrough = (template) => template
|
|
2
|
+
const replaceProcessEnv = (template) => replaceEnv(template, process.env, false)
|
|
3
|
+
|
|
4
|
+
const replaceEnv = (template, inject = {}, doEnv) => {
|
|
5
|
+
processTemplate = doEnv ? replaceProcessEnv : passThrough;
|
|
6
|
+
|
|
7
|
+
if (!template || typeof template !== "string") {
|
|
8
|
+
// return template;
|
|
9
|
+
return processTemplate(template)
|
|
4
10
|
};
|
|
5
11
|
|
|
6
|
-
const keys = Object.keys(
|
|
12
|
+
const keys = Object.keys(inject);
|
|
7
13
|
|
|
8
14
|
for (let i = 0; i < keys.length; i++) {
|
|
9
15
|
const key = keys[i];
|
|
10
|
-
let val =
|
|
11
|
-
|
|
12
|
-
if (!val) {
|
|
13
|
-
// we have an empty key fill it w/ an empty value
|
|
14
|
-
val = `""`;
|
|
15
|
-
}
|
|
16
|
+
let val = inject[key];
|
|
16
17
|
|
|
17
18
|
template = template
|
|
18
19
|
.replace(new RegExp(`\\$${key}`, "g"), val)
|
|
19
20
|
.replace(new RegExp(`\\$\{${key}}`, "g"), val);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
return template;
|
|
23
|
+
// return template;
|
|
24
|
+
return processTemplate(template);
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
const IsRegExVar = (str) => /\$\w+/.test(str) || /\$\{\w+\}/.test(str)
|
|
28
|
+
|
|
29
|
+
replaceEnv.IsRegExVar = IsRegExVar; // hack to be backward compat
|
|
30
|
+
|
|
25
31
|
module.exports = replaceEnv;
|
package/lib/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var yaml = require('js-yaml'),
|
|
2
|
-
_ = require('lodash');
|
|
2
|
+
_ = require('lodash');
|
|
3
3
|
|
|
4
4
|
var tags = [
|
|
5
5
|
{ short: 'Include', full: 'Fn::Include', type: 'scalar' },
|
|
@@ -9,6 +9,8 @@ var tags = [
|
|
|
9
9
|
{ short: 'Map', full: 'Fn::Map', type: 'sequence' },
|
|
10
10
|
{ short: 'Length', full: 'Fn::Length', type: 'sequence' },
|
|
11
11
|
{ short: 'Flatten', full: 'Fn::Flatten', type: 'sequence' },
|
|
12
|
+
{ short: 'FlattenDeep', full: 'Fn::FlattenDeep', type: 'sequence' },
|
|
13
|
+
{ short: 'Uniq', full: 'Fn::Uniq', type: 'sequence' },
|
|
12
14
|
{ short: 'GetEnv', full: 'Fn::GetEnv', type: 'sequence' },
|
|
13
15
|
{ short: 'GetEnv', full: 'Fn::GetEnv', type: 'scalar' },
|
|
14
16
|
{ short: 'Merge', full: 'Fn::Merge', type: 'sequence' },
|
|
@@ -16,6 +18,24 @@ var tags = [
|
|
|
16
18
|
{ short: 'LowerCamelCase', full: 'Fn::LowerCamelCase', type: 'scalar' },
|
|
17
19
|
{ short: 'UpperCamelCase', full: 'Fn::UpperCamelCase', type: 'scalar' },
|
|
18
20
|
{ short: 'Sequence', full: 'Fn::Sequence', type: 'sequence' },
|
|
21
|
+
{ short: 'DeepMerge', full: 'Fn::DeepMerge', type: 'sequence' },
|
|
22
|
+
{ short: 'Compact', full: 'Fn::Compact', type: 'sequence' },
|
|
23
|
+
{ short: 'Concat', full: 'Fn::Concat', type: 'sequence' },
|
|
24
|
+
{ short: 'Sort', full: 'Fn::Sort', type: 'sequence' },
|
|
25
|
+
{ short: 'SortedUniq', full: 'Fn::SortedUniq', type: 'sequence' },
|
|
26
|
+
{ short: 'SortBy', full: 'Fn::SortBy', type: 'mapping' },
|
|
27
|
+
{ short: 'SortObject', full: 'Fn::SortObject', type: 'mapping' },
|
|
28
|
+
{ short: 'ObjectKeys', full: 'Fn::ObjectKeys', type: 'sequence' },
|
|
29
|
+
{ short: 'ObjectValues', full: 'Fn::ObjectValues', type: 'sequence' },
|
|
30
|
+
{ short: 'Filenames', full: 'Fn::Filenames', type: 'sequence' },
|
|
31
|
+
{ short: 'Without', full: 'Fn::Without', type: 'sequence' },
|
|
32
|
+
{ short: 'Omit', full: 'Fn::Omit', type: 'sequence' },
|
|
33
|
+
{ short: 'Omit', full: 'Fn::Omit', type: 'mapping' },
|
|
34
|
+
{ short: 'OmitEmpty', full: 'Fn::OmitEmpty', type: 'mapping' },
|
|
35
|
+
{ short: 'Eval', full: 'Fn::Eval', type: 'sequence' },
|
|
36
|
+
{ short: 'IfEval', full: 'Fn::IfEval', type: 'mapping' },
|
|
37
|
+
{ short: 'JoinNow', full: 'Fn::JoinNow', type: 'scalar' },
|
|
38
|
+
{ short: 'ApplyTags', full: 'Fn::ApplyTags', type: 'mapping' },
|
|
19
39
|
|
|
20
40
|
// http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
|
|
21
41
|
{ short: 'Base64', full: 'Fn::Base64', type: 'scalar' },
|
|
@@ -45,21 +65,50 @@ var tags = [
|
|
|
45
65
|
{ short: 'Not', full: 'Fn::Not', type: 'sequence' },
|
|
46
66
|
{ short: 'Or', full: 'Fn::Or', type: 'sequence' },
|
|
47
67
|
{ short: 'Condition', full: 'Condition', type: 'scalar' },
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
].map(function(fn) {
|
|
68
|
+
].map(function (fn) {
|
|
51
69
|
return new yaml.Type('!' + fn.short, {
|
|
52
70
|
kind: fn.type,
|
|
53
|
-
construct: function(obj) {
|
|
54
|
-
if(fn.dotSyntax && _.isString(obj)) {
|
|
71
|
+
construct: function (obj) {
|
|
72
|
+
if (fn.dotSyntax && _.isString(obj)) {
|
|
55
73
|
var indexOfDot = obj.indexOf('.');
|
|
56
|
-
if(indexOfDot != -1)
|
|
57
|
-
obj = [obj.substr(0, indexOfDot), obj.substr(indexOfDot + 1)];
|
|
74
|
+
if (indexOfDot != -1) obj = [obj.substr(0, indexOfDot), obj.substr(indexOfDot + 1)];
|
|
58
75
|
else obj = [obj];
|
|
59
76
|
}
|
|
60
77
|
return _.fromPairs([[fn.full, obj]]);
|
|
61
|
-
}
|
|
78
|
+
},
|
|
62
79
|
});
|
|
63
80
|
});
|
|
64
81
|
|
|
82
|
+
// build array of strings of all Amazon Intrinsic functions
|
|
83
|
+
const BANG_AMAZON_FUNCS = [
|
|
84
|
+
'Base64',
|
|
85
|
+
'FindInMap',
|
|
86
|
+
'GetAtt',
|
|
87
|
+
'GetAZs',
|
|
88
|
+
'ImportValue',
|
|
89
|
+
'Join',
|
|
90
|
+
'Select',
|
|
91
|
+
'Split',
|
|
92
|
+
'Sub',
|
|
93
|
+
'Ref',
|
|
94
|
+
'Cidr',
|
|
95
|
+
'GetParam',
|
|
96
|
+
'And',
|
|
97
|
+
'Equals',
|
|
98
|
+
'If',
|
|
99
|
+
'Not',
|
|
100
|
+
'Or',
|
|
101
|
+
'Condition',
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const EXPLICIT_AMAZON_FUNCS = BANG_AMAZON_FUNCS.map((f) => `Fn::${f}`);
|
|
105
|
+
|
|
65
106
|
module.exports = yaml.Schema.create(tags);
|
|
107
|
+
|
|
108
|
+
module.exports.EXPLICIT_AMAZON_FUNCS = EXPLICIT_AMAZON_FUNCS;
|
|
109
|
+
module.exports.BANG_AMAZON_FUNCS = BANG_AMAZON_FUNCS;
|
|
110
|
+
|
|
111
|
+
// Test the function key to make sure it's something
|
|
112
|
+
// we should process.
|
|
113
|
+
module.exports.isOurExplicitFunction = (testKeyForFunc) =>
|
|
114
|
+
/Fn::.*/.test(testKeyForFunc) && EXPLICIT_AMAZON_FUNCS.indexOf(testKeyForFunc) === -1;
|
package/lib/yaml.js
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const minify = require('jsonminify');
|
|
2
|
+
const yaml = require('js-yaml');
|
|
3
|
+
const yamlSchema = require('./schema');
|
|
4
4
|
|
|
5
5
|
module.exports = {
|
|
6
|
-
load:
|
|
7
|
-
|
|
6
|
+
load: (res) => {
|
|
7
|
+
let json;
|
|
8
8
|
try {
|
|
9
9
|
json = yaml.safeLoad(res, { schema: yamlSchema });
|
|
10
|
-
} catch(yamlErr) {
|
|
10
|
+
} catch (yamlErr) {
|
|
11
11
|
try {
|
|
12
|
-
json = JSON.parse(
|
|
13
|
-
} catch(jsonErr) {
|
|
14
|
-
|
|
12
|
+
json = JSON.parse(minify(res));
|
|
13
|
+
} catch (jsonErr) {
|
|
14
|
+
const err = new Error([yamlErr, jsonErr]);
|
|
15
15
|
err.name = 'SyntaxError';
|
|
16
16
|
throw err;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
return json;
|
|
20
20
|
},
|
|
21
|
-
dump:
|
|
22
|
-
|
|
23
|
-
sortKeys: true,
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
}
|
|
21
|
+
dump: (obj, opts) => yaml.safeDump(obj, { sortKeys: true, ...opts }),
|
|
22
|
+
};
|
package/package.json
CHANGED
|
@@ -1,60 +1,84 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@znemz/cfn-include",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Preprocessor for CloudFormation templates with support for loops and flexible include statements",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "mocha --timeout 20000 --bail t/include.js t/cli.js t/replaceEnv.js"
|
|
8
|
-
},
|
|
9
|
-
"bin": {
|
|
10
|
-
"cfn-include": "bin/cli.js"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"index.js",
|
|
14
|
-
"bin/",
|
|
15
|
-
"lib/"
|
|
16
|
-
],
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/nmccready/cfn-include.git"
|
|
20
|
-
},
|
|
21
5
|
"keywords": [
|
|
22
6
|
"aws",
|
|
23
7
|
"cfn",
|
|
24
8
|
"cloudformation",
|
|
25
9
|
"include"
|
|
26
10
|
],
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
"
|
|
11
|
+
"homepage": "https://github.com/nmccready/cfn-include#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/nmccready/cfn-include/issues"
|
|
30
14
|
},
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/nmccready/cfn-include.git"
|
|
34
18
|
},
|
|
35
19
|
"license": "MIT",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Nicholas McCready",
|
|
22
|
+
"email": "nemtcan@gmail.com"
|
|
38
23
|
},
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
24
|
+
"main": "index.js",
|
|
25
|
+
"bin": {
|
|
26
|
+
"cfn-include": "bin/cli.js"
|
|
42
27
|
},
|
|
43
|
-
"
|
|
44
|
-
"
|
|
28
|
+
"files": [
|
|
29
|
+
"index.js",
|
|
30
|
+
"bin/",
|
|
31
|
+
"lib/"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"better-audit": "better-npm-audit audit",
|
|
35
|
+
"lint": "eslint .",
|
|
36
|
+
"lint:fix": "eslint . --fix",
|
|
37
|
+
"prepare": "sort-package-json",
|
|
38
|
+
"serve": "serve ./t/fixtures -l 9999",
|
|
39
|
+
"test": "npm run test:this",
|
|
40
|
+
"test:this": "run-p -r serve test:run",
|
|
41
|
+
"test:run": "sleep 1 && mocha --timeout 20000 --bail t/include.js t/cli.js t/replaceEnv.js"
|
|
45
42
|
},
|
|
46
43
|
"dependencies": {
|
|
47
|
-
"aws-sdk-
|
|
44
|
+
"@aws-sdk/client-cloudformation": "^3.637.0",
|
|
45
|
+
"@aws-sdk/client-s3": "^3.637.0",
|
|
46
|
+
"@znemz/cft-utils": "0.1.1",
|
|
47
|
+
"@znemz/sort-object": "^3.0.4",
|
|
48
|
+
"aws-sdk-v3-proxy": "2.1.2",
|
|
49
|
+
"bluebird": "^3.7.2",
|
|
48
50
|
"deepmerge": "^4.2.2",
|
|
49
|
-
"
|
|
51
|
+
"glob": "^11.0.0",
|
|
52
|
+
"jmespath": "^0.16.0",
|
|
50
53
|
"js-yaml": "^3.14.0",
|
|
51
|
-
"
|
|
52
|
-
"lodash": "^4.17.
|
|
53
|
-
"path-parse": "
|
|
54
|
-
"
|
|
54
|
+
"jsonminify": "^0.4.1",
|
|
55
|
+
"lodash": "^4.17.21",
|
|
56
|
+
"path-parse": "~1.0.7",
|
|
57
|
+
"proxy-agent": "6.3.1",
|
|
58
|
+
"yargs": "17"
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
57
|
-
"
|
|
58
|
-
"
|
|
61
|
+
"@commitlint/cli": "^19",
|
|
62
|
+
"@commitlint/config-conventional": "^19",
|
|
63
|
+
"better-npm-audit": "3.7.3",
|
|
64
|
+
"commit-and-tag-version": "12",
|
|
65
|
+
"commitlint": "19",
|
|
66
|
+
"eslint": "8",
|
|
67
|
+
"eslint-config-prettier": "9",
|
|
68
|
+
"eslint-config-standard": "17",
|
|
69
|
+
"eslint-plugin-mocha": "10",
|
|
70
|
+
"eslint-plugin-prettier": "5",
|
|
71
|
+
"mocha": "10.2.0",
|
|
72
|
+
"npm-run-all": "4.1.5",
|
|
73
|
+
"prettier": "3",
|
|
74
|
+
"serve": "14.2.1",
|
|
75
|
+
"sort-package-json": "2.10.1"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=8"
|
|
79
|
+
},
|
|
80
|
+
"originalAuthor": {
|
|
81
|
+
"name": "Moritz Onken",
|
|
82
|
+
"email": "onken@netcubed.de"
|
|
59
83
|
}
|
|
60
84
|
}
|