@znemz/cfn-include 1.6.4 → 2.0.1

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/lib/cfnclient.js CHANGED
@@ -1,13 +1,22 @@
1
- const { CloudFormation, S3 } = require('aws-sdk-proxy');
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 = new CloudFormation({
16
+ this.client = CloudFormation({
8
17
  region,
9
18
  });
10
- this.s3 = new 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.putObject({
25
- Body: tpl,
26
- Bucket: this.bucket,
27
- Key: key,
28
- }).promise();
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.deleteObject({
37
- Bucket: this.bucket,
38
- Key: key,
39
- }).promise().catch(() => {});
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) => this.client.validateTemplate({
54
- TemplateURL: `https://s3.${this.region}.amazonaws.com/${this.bucket}/${key}`,
55
- }).promise());
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.validateTemplate({
59
- TemplateBody: tpl,
60
- }).promise();
79
+ return this.client.send(
80
+ new ValidateTemplateCommand({
81
+ TemplateBody: tpl,
82
+ })
83
+ );
61
84
  }
62
85
  }
63
86
 
@@ -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 ? getParser(args.parser)(res, args.query) : res;
8
+ return args.query ? jmespath.search(res, args.query) : res;
10
9
  });
11
10
  }
@@ -1,13 +1,17 @@
1
- var _ = require('lodash');
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: _.isUndefined(parsed[1]) ? true : false,
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
- module.exports = {
3
- map: (arr, fn) => {
4
- return arr.then(res => {
5
- return Promise.all(res.map(fn));
6
- });
7
- },
8
- // https://github.com/expo/promise-props
9
- props: obj => {
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
- return byName;
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
- function replaceEnv(template, env = process.env) {
2
- if (!template || typeof template != "string") {
3
- return template
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(env);
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 = env[key];
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
- var jsmin = require('jsmin').jsmin,
2
- yaml = require('js-yaml'),
3
- yamlSchema = require('./schema');
1
+ const minify = require('jsonminify');
2
+ const yaml = require('js-yaml');
3
+ const yamlSchema = require('./schema');
4
4
 
5
5
  module.exports = {
6
- load: function (res) {
7
- var json;
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(jsmin(res));
13
- } catch(jsonErr) {
14
- var err = new Error([yamlErr, jsonErr]);
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: function(obj) {
22
- return yaml.safeDump(obj, {
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": "1.6.4",
3
+ "version": "2.0.1",
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
- "author": {
28
- "name": "Nicholas McCready",
29
- "email": "nemtcan@gmail.com"
11
+ "homepage": "https://github.com/nmccready/cfn-include#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/nmccready/cfn-include/issues"
30
14
  },
31
- "originalAuthor": {
32
- "name": "Moritz Onken",
33
- "email": "onken@netcubed.de"
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/nmccready/cfn-include.git"
34
18
  },
35
19
  "license": "MIT",
36
- "bugs": {
37
- "url": "https://github.com/nmccready/cfn-include/issues"
20
+ "author": {
21
+ "name": "Nicholas McCready",
22
+ "email": "nemtcan@gmail.com"
38
23
  },
39
- "homepage": "https://github.com/nmccready/cfn-include#readme",
40
- "engines": {
41
- "node": ">=8"
24
+ "main": "index.js",
25
+ "bin": {
26
+ "cfn-include": "bin/cli.js"
42
27
  },
43
- "peerDependencies": {
44
- "aws-sdk": "^2.205.0"
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-proxy": "^1.0.0",
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
- "jmespath": "^0.15.0",
51
+ "glob": "^11.0.0",
52
+ "jmespath": "^0.16.0",
50
53
  "js-yaml": "^3.14.0",
51
- "jsmin": "1.0.1",
52
- "lodash": "^4.17.20",
53
- "path-parse": "^1.0.5",
54
- "yargs": "^15.4.1"
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
- "mocha": "^7.2.0",
58
- "proxy-agent": "^3.1.1"
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.4",
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
  }