@znemz/cfn-include 2.1.23 → 2.1.24

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.
Files changed (88) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +196 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.d.ts +19 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +697 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/lib/cache.d.ts +12 -0
  10. package/dist/lib/cache.d.ts.map +1 -0
  11. package/{lib → dist/lib}/cache.js +8 -13
  12. package/dist/lib/cache.js.map +1 -0
  13. package/dist/lib/cfnclient.d.ts +17 -0
  14. package/dist/lib/cfnclient.d.ts.map +1 -0
  15. package/dist/lib/cfnclient.js +69 -0
  16. package/dist/lib/cfnclient.js.map +1 -0
  17. package/dist/lib/include/query.d.ts +4 -0
  18. package/dist/lib/include/query.d.ts.map +1 -0
  19. package/dist/lib/include/query.js +14 -0
  20. package/dist/lib/include/query.js.map +1 -0
  21. package/dist/lib/internals.d.ts +10 -0
  22. package/dist/lib/internals.d.ts.map +1 -0
  23. package/dist/lib/internals.js +145 -0
  24. package/dist/lib/internals.js.map +1 -0
  25. package/dist/lib/parselocation.d.ts +3 -0
  26. package/dist/lib/parselocation.d.ts.map +1 -0
  27. package/dist/lib/parselocation.js +19 -0
  28. package/dist/lib/parselocation.js.map +1 -0
  29. package/dist/lib/promise-utils.d.ts +19 -0
  30. package/dist/lib/promise-utils.d.ts.map +1 -0
  31. package/dist/lib/promise-utils.js +36 -0
  32. package/dist/lib/promise-utils.js.map +1 -0
  33. package/dist/lib/promise.d.ts +6 -0
  34. package/dist/lib/promise.d.ts.map +1 -0
  35. package/dist/lib/promise.js +16 -0
  36. package/dist/lib/promise.js.map +1 -0
  37. package/dist/lib/replaceEnv.d.ts +8 -0
  38. package/dist/lib/replaceEnv.d.ts.map +1 -0
  39. package/dist/lib/replaceEnv.js +48 -0
  40. package/dist/lib/replaceEnv.js.map +1 -0
  41. package/dist/lib/request.d.ts +2 -0
  42. package/dist/lib/request.d.ts.map +1 -0
  43. package/dist/lib/request.js +19 -0
  44. package/dist/lib/request.js.map +1 -0
  45. package/dist/lib/schema.d.ts +9 -0
  46. package/dist/lib/schema.d.ts.map +1 -0
  47. package/dist/lib/schema.js +115 -0
  48. package/dist/lib/schema.js.map +1 -0
  49. package/dist/lib/scope.d.ts +23 -0
  50. package/dist/lib/scope.d.ts.map +1 -0
  51. package/dist/lib/scope.js +36 -0
  52. package/dist/lib/scope.js.map +1 -0
  53. package/dist/lib/utils.d.ts +3 -0
  54. package/dist/lib/utils.d.ts.map +1 -0
  55. package/dist/lib/utils.js +13 -0
  56. package/dist/lib/utils.js.map +1 -0
  57. package/dist/lib/yaml.d.ts +8 -0
  58. package/dist/lib/yaml.d.ts.map +1 -0
  59. package/dist/lib/yaml.js +74 -0
  60. package/dist/lib/yaml.js.map +1 -0
  61. package/dist/types/index.d.ts +6 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +6 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/dist/types/options.d.ts +88 -0
  66. package/dist/types/options.d.ts.map +1 -0
  67. package/dist/types/options.js +5 -0
  68. package/dist/types/options.js.map +1 -0
  69. package/dist/types/template.d.ts +290 -0
  70. package/dist/types/template.d.ts.map +1 -0
  71. package/dist/types/template.js +5 -0
  72. package/dist/types/template.js.map +1 -0
  73. package/package.json +23 -10
  74. package/bin/cli.js +0 -204
  75. package/index.js +0 -899
  76. package/lib/cfnclient.js +0 -84
  77. package/lib/include/api.js +0 -13
  78. package/lib/include/query.js +0 -16
  79. package/lib/internals.js +0 -171
  80. package/lib/parselocation.js +0 -15
  81. package/lib/promise-utils.js +0 -46
  82. package/lib/promise.js +0 -18
  83. package/lib/replaceEnv.js +0 -66
  84. package/lib/request.js +0 -22
  85. package/lib/schema.js +0 -117
  86. package/lib/scope.js +0 -52
  87. package/lib/utils.js +0 -16
  88. package/lib/yaml.js +0 -76
package/lib/cfnclient.js DELETED
@@ -1,84 +0,0 @@
1
- import { CloudFormationClient, ValidateTemplateCommand } from '@aws-sdk/client-cloudformation';
2
- import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
3
- import { addProxyToClient } from 'aws-sdk-v3-proxy';
4
-
5
- import path from 'node:path';
6
- import crypto from 'node:crypto';
7
-
8
- const S3 = (opts = {}) => addProxyToClient(new S3Client(opts));
9
- const CloudFormation = (opts = {}) => addProxyToClient(new CloudFormationClient(opts));
10
-
11
- class Client {
12
- constructor({ region = 'us-east-1', bucket, prefix }) {
13
- this.client = CloudFormation({
14
- region,
15
- });
16
- this.s3 = S3();
17
- this.bucket = bucket;
18
- this.prefix = prefix;
19
- this.region = region;
20
- }
21
-
22
- digest(input) {
23
- const hash = crypto.createHash('md5');
24
- hash.update(input);
25
- return hash.digest('hex');
26
- }
27
-
28
- async uploadTemplate(tpl, callback) {
29
- const key = path.posix.join(this.prefix, `${this.digest(tpl)}.json`);
30
- await this.s3.Send(
31
- new PutObjectCommand({
32
- Body: tpl,
33
- Bucket: this.bucket,
34
- Key: key,
35
- }),
36
- );
37
-
38
- let res, err;
39
- try {
40
- res = await callback(key);
41
- } catch (e) {
42
- err = e;
43
- }
44
- await this.s3
45
- .send(
46
- new DeleteObjectCommand({
47
- Bucket: this.bucket,
48
- Key: key,
49
- }),
50
- )
51
- .catch(() => {});
52
- if (err) throw err;
53
- return res;
54
- }
55
-
56
- async validateTemplate(tpl = '') {
57
- const needsUpload = tpl.length > 51200;
58
- if (needsUpload && !this.bucket) {
59
- throw 'Cannot validate template larger than 50k without a bucket. Please provide a bucket name.';
60
- }
61
- if (needsUpload && tpl.length > 460800) {
62
- throw 'Template exceeds maximum size of 450k';
63
- }
64
- if (needsUpload) {
65
- return this.uploadTemplate(tpl, (key) =>
66
- this.client
67
- .send(
68
- new ValidateTemplateCommand({
69
- TemplateURL: `https://s3.${this.region}.amazonaws.com/${this.bucket}/${key}`,
70
- }),
71
- )
72
- .promise(),
73
- );
74
- }
75
-
76
- return this.client.send(
77
- new ValidateTemplateCommand({
78
- TemplateBody: tpl,
79
- }),
80
- );
81
- }
82
- }
83
-
84
- export default Client;
@@ -1,13 +0,0 @@
1
- // NOTE: This module uses the legacy AWS SDK v2 via aws-sdk-proxy
2
- // It may be unused and could be removed or rewritten for SDK v3
3
- import AWS from 'aws-sdk-proxy';
4
- import jmespath from 'jmespath';
5
-
6
- export default function (args) {
7
- const service = new AWS[args.service](args.region ? { region: args.region } : null);
8
- return service[args.action](args.parameters ? args.parameters : {})
9
- .promise()
10
- .then(function (res) {
11
- return args.query ? jmespath.search(res, args.query) : res;
12
- });
13
- }
@@ -1,16 +0,0 @@
1
- import _ from 'lodash';
2
- import jmespath from 'jmespath';
3
-
4
- // this exists cause in most cases lodash get is plenty sufficient
5
- // also this bug / error in jmespath is ridiculous https://github.com/jmespath/jmespath.js/issues/35
6
- const queryParsers = {
7
- lodash: (obj, path) => _.get(obj, path) || '',
8
- jmespath: jmespath.search,
9
- default: jmespath.search,
10
- };
11
-
12
- queryParsers['default'] = queryParsers[process.env.CFN_INCLUDE_QUERY_PARSER] || queryParsers.default;
13
-
14
- export function getParser(type) {
15
- return queryParsers[type] || queryParsers.default;
16
- }
package/lib/internals.js DELETED
@@ -1,171 +0,0 @@
1
- function getAwsPseudoParameters() {
2
- return {
3
- 'AWS::AccountId': process.env.AWS_ACCOUNT_ID || process.env.AWS_ACCOUNT_NUM || '${AWS::AccountId}',
4
- 'AWS::Partition': process.env.AWS_PARTITION || 'aws',
5
- 'AWS::Region': process.env.AWS_REGION || '${AWS::Region}',
6
- 'AWS::StackId': process.env.AWS_STACK_ID || '${AWS::StackId}',
7
- 'AWS::StackName': process.env.AWS_STACK_NAME || '${AWS::StackName}',
8
- 'AWS::URLSuffix': process.env.AWS_URL_SUFFIX || 'amazonaws.com',
9
- 'AWS::NotificationARNs': process.env.AWS_NOTIFICATION_ARNS || '${AWS::NotificationARNs}',
10
- };
11
- }
12
-
13
- /**
14
- * Build an ARN for a CloudFormation resource based on its Type and Properties
15
- * Supports both ARN construction and property name resolution
16
- * @param {string} resourceType - The CloudFormation resource type (e.g., 'AWS::IAM::ManagedPolicy')
17
- * @param {object} properties - The resource properties
18
- * @param {object} pseudoParams - AWS pseudo-parameters including AccountId, Region
19
- * @param {object} options - Optional configuration
20
- * @param {string} options.returnType - 'arn' (default) or 'name' to return the resource name/identifier
21
- * @returns {string|null} - The ARN, name, or null if not applicable
22
- */
23
- function buildResourceArn(resourceType, properties = {}, pseudoParams = {}, options = {}) {
24
- const accountId = pseudoParams['AWS::AccountId'] || '${AWS::AccountId}';
25
- const region = pseudoParams['AWS::Region'] || '${AWS::Region}';
26
- const partition = pseudoParams['AWS::Partition'] || 'aws';
27
- const returnType = options.returnType || 'arn';
28
-
29
- // Handle AWS::IAM::ManagedPolicy
30
- if (resourceType === 'AWS::IAM::ManagedPolicy') {
31
- const { ManagedPolicyName, Path } = properties;
32
- if (ManagedPolicyName) {
33
- if (returnType === 'name') {
34
- return ManagedPolicyName;
35
- }
36
- const path = Path || '/';
37
- return `arn:${partition}:iam::${accountId}:policy${path}${ManagedPolicyName}`;
38
- }
39
- }
40
-
41
- // Handle AWS::IAM::Role
42
- if (resourceType === 'AWS::IAM::Role') {
43
- const { RoleName, Path } = properties;
44
- if (RoleName) {
45
- if (returnType === 'name') {
46
- return RoleName;
47
- }
48
- const path = Path || '/';
49
- return `arn:${partition}:iam::${accountId}:role${path}${RoleName}`;
50
- }
51
- }
52
-
53
- // Handle AWS::S3::Bucket
54
- if (resourceType === 'AWS::S3::Bucket') {
55
- const { BucketName } = properties;
56
- if (BucketName) {
57
- if (returnType === 'name') {
58
- return BucketName;
59
- }
60
- return `arn:${partition}:s3:::${BucketName}`;
61
- }
62
- }
63
-
64
- // Handle AWS::Lambda::Function
65
- if (resourceType === 'AWS::Lambda::Function') {
66
- const { FunctionName } = properties;
67
- if (FunctionName) {
68
- if (returnType === 'name') {
69
- return FunctionName;
70
- }
71
- return `arn:${partition}:lambda:${region}:${accountId}:function:${FunctionName}`;
72
- }
73
- }
74
-
75
- // Handle AWS::SQS::Queue
76
- if (resourceType === 'AWS::SQS::Queue') {
77
- const { QueueName } = properties;
78
- if (QueueName) {
79
- if (returnType === 'name') {
80
- return QueueName;
81
- }
82
- return `arn:${partition}:sqs:${region}:${accountId}:${QueueName}`;
83
- }
84
- }
85
-
86
- // Handle AWS::SNS::Topic
87
- if (resourceType === 'AWS::SNS::Topic') {
88
- const { TopicName } = properties;
89
- if (TopicName) {
90
- if (returnType === 'name') {
91
- return TopicName;
92
- }
93
- return `arn:${partition}:sns:${region}:${accountId}:${TopicName}`;
94
- }
95
- }
96
-
97
- // Handle AWS::DynamoDB::Table
98
- if (resourceType === 'AWS::DynamoDB::Table') {
99
- const { TableName } = properties;
100
- if (TableName) {
101
- if (returnType === 'name') {
102
- return TableName;
103
- }
104
- return `arn:${partition}:dynamodb:${region}:${accountId}:table/${TableName}`;
105
- }
106
- }
107
-
108
- // Handle AWS::RDS::DBInstance
109
- if (resourceType === 'AWS::RDS::DBInstance') {
110
- const { DBInstanceIdentifier } = properties;
111
- if (DBInstanceIdentifier) {
112
- if (returnType === 'name') {
113
- return DBInstanceIdentifier;
114
- }
115
- return `arn:${partition}:rds:${region}:${accountId}:db:${DBInstanceIdentifier}`;
116
- }
117
- }
118
-
119
- // Handle AWS::EC2::SecurityGroup
120
- if (resourceType === 'AWS::EC2::SecurityGroup') {
121
- const { GroupName } = properties;
122
- if (GroupName) {
123
- if (returnType === 'name') {
124
- return GroupName;
125
- }
126
- // Security groups need to be referenced by ID in most cases, not ARN
127
- // This returns the name for reference purposes
128
- return GroupName;
129
- }
130
- }
131
-
132
- // Handle AWS::IAM::InstanceProfile
133
- if (resourceType === 'AWS::IAM::InstanceProfile') {
134
- const { InstanceProfileName, Path } = properties;
135
- if (InstanceProfileName) {
136
- if (returnType === 'name') {
137
- return InstanceProfileName;
138
- }
139
- const path = Path || '/';
140
- return `arn:${partition}:iam::${accountId}:instance-profile${path}${InstanceProfileName}`;
141
- }
142
- }
143
-
144
- // Handle AWS::KMS::Key
145
- if (resourceType === 'AWS::KMS::Key') {
146
- // KMS keys are referenced by KeyId or KeyArn in properties
147
- const { KeyId } = properties;
148
- if (KeyId) {
149
- if (returnType === 'name') {
150
- return KeyId;
151
- }
152
- return `arn:${partition}:kms:${region}:${accountId}:key/${KeyId}`;
153
- }
154
- }
155
-
156
- // Handle AWS::SecretsManager::Secret
157
- if (resourceType === 'AWS::SecretsManager::Secret') {
158
- const { Name } = properties;
159
- if (Name) {
160
- if (returnType === 'name') {
161
- return Name;
162
- }
163
- return `arn:${partition}:secretsmanager:${region}:${accountId}:secret:${Name}`;
164
- }
165
- }
166
-
167
- // Add more resource types as needed
168
- return null;
169
- }
170
-
171
- export { getAwsPseudoParameters, buildResourceArn };
@@ -1,15 +0,0 @@
1
- export default function parseLocation(location) {
2
- if (!location) return {};
3
- if (!location.match) {
4
- console.error('location.match is not a function', location);
5
- }
6
- const parsed = location.match(/^(((\w+):)?\/\/)?(.*?)([\\\/](.*))?$/);
7
-
8
- return {
9
- protocol: parsed[3],
10
- host: parsed[4],
11
- path: parsed[5],
12
- relative: parsed[1] === undefined,
13
- raw: location,
14
- };
15
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Native Promise utilities to replace bluebird.
3
- * These are drop-in replacements for the bluebird methods we use.
4
- */
5
-
6
- /**
7
- * Promise.props replacement - resolves an object of promises.
8
- * @param {Object} obj - Object with promise values
9
- * @returns {Promise<Object>} Object with resolved values
10
- */
11
- async function promiseProps(obj) {
12
- const keys = Object.keys(obj);
13
- const values = await Promise.all(keys.map((key) => obj[key]));
14
- const result = {};
15
- for (let i = 0; i < keys.length; i++) {
16
- result[keys[i]] = values[i];
17
- }
18
- return result;
19
- }
20
-
21
- /**
22
- * Promise.try replacement - wraps a function to catch sync errors.
23
- * @param {Function} fn - Function to execute
24
- * @returns {Promise} Promise that resolves to fn result or rejects on error
25
- */
26
- function promiseTry(fn) {
27
- return new Promise((resolve, reject) => {
28
- try {
29
- resolve(fn());
30
- } catch (err) {
31
- reject(err);
32
- }
33
- });
34
- }
35
-
36
- /**
37
- * Promise.map replacement - maps over array with concurrency.
38
- * @param {Array} arr - Array to map over
39
- * @param {Function} fn - Async function to apply
40
- * @returns {Promise<Array>} Array of resolved values
41
- */
42
- function promiseMap(arr, fn) {
43
- return Promise.all(arr.map(fn));
44
- }
45
-
46
- export { promiseProps, promiseTry, promiseMap };
package/lib/promise.js DELETED
@@ -1,18 +0,0 @@
1
- import { promiseTry, promiseMap } from './promise-utils.js';
2
-
3
- /*
4
- Maps over objects or iterables just like lodash.
5
- */
6
- const mapWhatever = (promises, cb) =>
7
- promiseTry(() =>
8
- Promise.resolve(promises).then((arrayOrObject) => {
9
- if (Array.isArray(arrayOrObject)) {
10
- return promiseMap(arrayOrObject, cb);
11
- }
12
- const size = Object.values(arrayOrObject).length;
13
- const entries = Object.entries(arrayOrObject);
14
- return Promise.all(entries.map(([key, value]) => cb(value, key, size)));
15
- }),
16
- );
17
-
18
- export { mapWhatever, mapWhatever as mapX };
package/lib/replaceEnv.js DELETED
@@ -1,66 +0,0 @@
1
- const passThrough = (template) => template;
2
- const replaceProcessEnv = (template) => replaceEnv(template, process.env, false);
3
-
4
- // Cache for compiled regex patterns to avoid re-creating them
5
- const regexCache = new Map();
6
-
7
- /**
8
- * Escape special regex characters in a string
9
- * @param {string} str - String to escape
10
- * @returns {string} Escaped string safe for regex
11
- */
12
- function escapeRegExp(str) {
13
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
14
- }
15
-
16
- /**
17
- * Get a cached regex for variable substitution
18
- * @param {string} key - Variable name
19
- * @param {boolean} withBraces - Whether to match ${key} format (true) or $key format (false)
20
- * @returns {RegExp} Cached regex pattern
21
- */
22
- function getVarRegex(key, withBraces) {
23
- const cacheKey = `${key}:${withBraces}`;
24
- if (!regexCache.has(cacheKey)) {
25
- const escaped = escapeRegExp(key);
26
- const pattern = withBraces ? `\\$\\{${escaped}\\}` : `\\$${escaped}`;
27
- regexCache.set(cacheKey, new RegExp(pattern, 'g'));
28
- }
29
- return regexCache.get(cacheKey);
30
- }
31
-
32
- let processTemplate;
33
-
34
- function replaceEnv(template, inject = {}, doEnv) {
35
- processTemplate = doEnv ? replaceProcessEnv : passThrough;
36
-
37
- if (!template || typeof template !== 'string') {
38
- return processTemplate(template);
39
- }
40
-
41
- const keys = Object.keys(inject);
42
-
43
- for (let i = 0; i < keys.length; i++) {
44
- const key = keys[i];
45
- const val = inject[key];
46
-
47
- // Use cached regex patterns instead of creating new ones each time
48
- const bareRegex = getVarRegex(key, false);
49
- const bracedRegex = getVarRegex(key, true);
50
-
51
- // Reset lastIndex for global regex reuse
52
- bareRegex.lastIndex = 0;
53
- bracedRegex.lastIndex = 0;
54
-
55
- template = template.replace(bareRegex, val).replace(bracedRegex, val);
56
- }
57
-
58
- return processTemplate(template);
59
- }
60
-
61
- const IsRegExVar = (str) => /\$\w+/.test(str) || /\$\{\w+\}/.test(str);
62
-
63
- replaceEnv.IsRegExVar = IsRegExVar; // hack to be backward compat
64
-
65
- export default replaceEnv;
66
- export { IsRegExVar };
package/lib/request.js DELETED
@@ -1,22 +0,0 @@
1
- import { parse as urlParse } from 'node:url';
2
- import https from 'node:https';
3
- import http from 'node:http';
4
-
5
- export default function request(location) {
6
- const parsed = urlParse(location);
7
- const proto = parsed.protocol === 'https:' ? https : http;
8
-
9
- return new Promise((resolve, reject) =>
10
- proto
11
- .get(location, (res) => {
12
- if (res.statusCode > 299) {
13
- return reject(new Error('HTTP request failed with status code ' + res.statusCode));
14
- }
15
- const rawData = [];
16
- res.setEncoding('utf8');
17
- res.on('data', (chunk) => rawData.push(chunk));
18
- res.on('end', () => resolve(rawData.join('')));
19
- })
20
- .on('error', reject),
21
- );
22
- }
package/lib/schema.js DELETED
@@ -1,117 +0,0 @@
1
- import yaml from 'js-yaml';
2
- import _ from 'lodash';
3
-
4
- const tags = [
5
- { short: 'Include', full: 'Fn::Include', type: 'scalar' },
6
- { short: 'Include', full: 'Fn::Include', type: 'mapping' },
7
- { short: 'Stringify', full: 'Fn::Stringify', type: 'sequence' },
8
- { short: 'Stringify', full: 'Fn::Stringify', type: 'mapping' },
9
- { short: 'Map', full: 'Fn::Map', type: 'sequence' },
10
- { short: 'Length', full: 'Fn::Length', type: 'sequence' },
11
- { short: 'Flatten', full: 'Fn::Flatten', type: 'sequence' },
12
- { short: 'FlattenDeep', full: 'Fn::FlattenDeep', type: 'sequence' },
13
- { short: 'Uniq', full: 'Fn::Uniq', type: 'sequence' },
14
- { short: 'GetEnv', full: 'Fn::GetEnv', type: 'sequence' },
15
- { short: 'GetEnv', full: 'Fn::GetEnv', type: 'scalar' },
16
- { short: 'Merge', full: 'Fn::Merge', type: 'sequence' },
17
- { short: 'Outputs', full: 'Fn::Outputs', type: 'mapping' },
18
- { short: 'LowerCamelCase', full: 'Fn::LowerCamelCase', type: 'scalar' },
19
- { short: 'UpperCamelCase', full: 'Fn::UpperCamelCase', type: 'scalar' },
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: 'SubNow', full: 'Fn::SubNow', type: 'scalar' },
39
- { short: 'SubNow', full: 'Fn::SubNow', type: 'sequence' },
40
- { short: 'RefNow', full: 'Fn::RefNow', type: 'scalar' },
41
- { short: 'ApplyTags', full: 'Fn::ApplyTags', type: 'mapping' },
42
-
43
- // http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
44
- { short: 'Base64', full: 'Fn::Base64', type: 'scalar' },
45
- { short: 'Base64', full: 'Fn::Base64', type: 'mapping' },
46
- { short: 'FindInMap', full: 'Fn::FindInMap', type: 'sequence' },
47
- { short: 'GetAtt', full: 'Fn::GetAtt', type: 'sequence' },
48
- { short: 'GetAtt', full: 'Fn::GetAtt', type: 'scalar', dotSyntax: true },
49
- { short: 'GetAZs', full: 'Fn::GetAZs', type: 'sequence' },
50
- { short: 'GetAZs', full: 'Fn::GetAZs', type: 'scalar' },
51
- { short: 'ImportValue', full: 'Fn::ImportValue', type: 'scalar' },
52
- { short: 'ImportValue', full: 'Fn::ImportValue', type: 'mapping' },
53
- { short: 'Join', full: 'Fn::Join', type: 'sequence' },
54
- { short: 'Select', full: 'Fn::Select', type: 'sequence' },
55
- { short: 'Sub', full: 'Fn::Sub', type: 'sequence' },
56
- { short: 'Sub', full: 'Fn::Sub', type: 'mapping' },
57
- { short: 'Sub', full: 'Fn::Sub', type: 'scalar' },
58
- { short: 'Split', full: 'Fn::Split', type: 'sequence' },
59
- { short: 'Ref', full: 'Ref', type: 'scalar' },
60
- { short: 'Cidr', full: 'Fn::Cidr', type: 'sequence' },
61
- { short: 'Cidr', full: 'Fn::Cidr', type: 'mapping' },
62
- // http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-action-reference.html
63
- { short: 'GetParam', full: 'Fn::GetParam', type: 'sequence' },
64
- // http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html
65
- { short: 'And', full: 'Fn::And', type: 'sequence' },
66
- { short: 'Equals', full: 'Fn::Equals', type: 'sequence' },
67
- { short: 'If', full: 'Fn::If', type: 'sequence' },
68
- { short: 'Not', full: 'Fn::Not', type: 'sequence' },
69
- { short: 'Or', full: 'Fn::Or', type: 'sequence' },
70
- { short: 'Condition', full: 'Condition', type: 'scalar' },
71
- ].map(function (fn) {
72
- return new yaml.Type('!' + fn.short, {
73
- kind: fn.type,
74
- construct: function (obj) {
75
- if (fn.dotSyntax && _.isString(obj)) {
76
- const indexOfDot = obj.indexOf('.');
77
- if (indexOfDot !== -1) obj = [obj.substr(0, indexOfDot), obj.substr(indexOfDot + 1)];
78
- else obj = [obj];
79
- }
80
- return _.fromPairs([[fn.full, obj]]);
81
- },
82
- });
83
- });
84
-
85
- // build array of strings of all Amazon Intrinsic functions
86
- const BANG_AMAZON_FUNCS = [
87
- 'Base64',
88
- 'FindInMap',
89
- 'GetAtt',
90
- 'GetAZs',
91
- 'ImportValue',
92
- 'Join',
93
- 'Select',
94
- 'Split',
95
- 'Sub',
96
- 'Ref',
97
- 'Cidr',
98
- 'GetParam',
99
- 'And',
100
- 'Equals',
101
- 'If',
102
- 'Not',
103
- 'Or',
104
- 'Condition',
105
- ];
106
-
107
- const EXPLICIT_AMAZON_FUNCS = BANG_AMAZON_FUNCS.map((f) => `Fn::${f}`);
108
-
109
- const yamlSchema = yaml.DEFAULT_SCHEMA.extend(tags);
110
-
111
- // Test the function key to make sure it's something
112
- // we should process.
113
- const isOurExplicitFunction = (testKeyForFunc) =>
114
- /Fn::.*/.test(testKeyForFunc) && !EXPLICIT_AMAZON_FUNCS.includes(testKeyForFunc);
115
-
116
- export default yamlSchema;
117
- export { EXPLICIT_AMAZON_FUNCS, BANG_AMAZON_FUNCS, isOurExplicitFunction };
package/lib/scope.js DELETED
@@ -1,52 +0,0 @@
1
- /**
2
- * Scope helper functions for lazy prototype-chain based scope management.
3
- *
4
- * Instead of _.clone(scope) which copies O(n) properties each time,
5
- * we use Object.create(scope) which creates a child scope in O(1) time
6
- * that inherits from the parent via the prototype chain.
7
- */
8
-
9
- /**
10
- * Create a child scope that inherits from the parent.
11
- * Uses Object.create() for O(1) creation instead of cloning.
12
- *
13
- * @param {Object} parent - The parent scope to inherit from
14
- * @param {Object} [additions={}] - Properties to add to the child scope
15
- * @returns {Object} A new child scope with prototype chain to parent
16
- */
17
- export function createChildScope(parent, additions = {}) {
18
- const child = Object.create(parent);
19
- Object.assign(child, additions);
20
- return child;
21
- }
22
-
23
- /**
24
- * Convert a prototype-chain scope to a plain object.
25
- * Uses for...in to walk the entire prototype chain.
26
- *
27
- * Useful when we need to pass scope to functions that don't
28
- * walk the prototype chain (e.g., Object.keys, _.forEach).
29
- *
30
- * @param {Object} scope - The scope to flatten
31
- * @returns {Object} A plain object with all inherited properties
32
- */
33
- export function scopeToObject(scope) {
34
- const result = {};
35
- for (const key in scope) {
36
- result[key] = scope[key];
37
- }
38
- return result;
39
- }
40
-
41
- /**
42
- * Iterate over all properties in a scope, including inherited ones.
43
- * This is a replacement for _.forEach that walks the prototype chain.
44
- *
45
- * @param {Object} scope - The scope to iterate over
46
- * @param {Function} callback - Function to call with (value, key)
47
- */
48
- export function forEachInScope(scope, callback) {
49
- for (const key in scope) {
50
- callback(scope[key], key);
51
- }
52
- }
package/lib/utils.js DELETED
@@ -1,16 +0,0 @@
1
- import assert from 'node:assert/strict';
2
-
3
- function upperCamelCase(str) {
4
- assert(typeof str === 'string', 'argument to upper/lowerCamelCase must be a string');
5
- return str
6
- .split(/[\._-\s]+/)
7
- .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())
8
- .join('');
9
- }
10
-
11
- function lowerCamelCase(str) {
12
- const upper = upperCamelCase(str);
13
- return upper.charAt(0).toLowerCase() + upper.slice(1);
14
- }
15
-
16
- export { lowerCamelCase, upperCamelCase };