@cdk8s/awscdk-resolver 0.0.535 → 0.0.537

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 (108) hide show
  1. package/.jsii +3 -3
  2. package/lib/resolve.js +1 -1
  3. package/node_modules/@aws-sdk/client-cloudformation/package.json +34 -34
  4. package/node_modules/@aws-sdk/core/dist-cjs/index.js +6 -6
  5. package/node_modules/@aws-sdk/core/dist-cjs/submodules/protocols/index.js +6 -6
  6. package/node_modules/@aws-sdk/core/dist-es/submodules/protocols/json/JsonShapeSerializer.js +6 -6
  7. package/node_modules/@aws-sdk/core/dist-types/submodules/protocols/json/JsonShapeSerializer.d.ts +2 -2
  8. package/node_modules/@aws-sdk/core/dist-types/ts3.4/submodules/protocols/json/JsonShapeSerializer.d.ts +1 -1
  9. package/node_modules/@aws-sdk/core/package.json +11 -11
  10. package/node_modules/@aws-sdk/credential-provider-env/package.json +5 -5
  11. package/node_modules/@aws-sdk/credential-provider-http/package.json +10 -10
  12. package/node_modules/@aws-sdk/credential-provider-ini/package.json +14 -14
  13. package/node_modules/@aws-sdk/credential-provider-login/package.json +8 -8
  14. package/node_modules/@aws-sdk/credential-provider-node/package.json +12 -12
  15. package/node_modules/@aws-sdk/credential-provider-process/package.json +6 -6
  16. package/node_modules/@aws-sdk/credential-provider-sso/package.json +8 -8
  17. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +7 -7
  18. package/node_modules/@aws-sdk/middleware-host-header/package.json +4 -4
  19. package/node_modules/@aws-sdk/middleware-logger/package.json +3 -3
  20. package/node_modules/@aws-sdk/middleware-recursion-detection/package.json +4 -4
  21. package/node_modules/@aws-sdk/middleware-user-agent/package.json +8 -8
  22. package/node_modules/@aws-sdk/nested-clients/package.json +32 -32
  23. package/node_modules/@aws-sdk/region-config-resolver/package.json +5 -5
  24. package/node_modules/@aws-sdk/token-providers/package.json +7 -7
  25. package/node_modules/@aws-sdk/types/package.json +2 -2
  26. package/node_modules/@aws-sdk/util-endpoints/package.json +5 -5
  27. package/node_modules/@aws-sdk/util-user-agent-browser/package.json +3 -3
  28. package/node_modules/@aws-sdk/util-user-agent-node/package.json +5 -5
  29. package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
  30. package/node_modules/@smithy/config-resolver/package.json +5 -5
  31. package/node_modules/@smithy/core/package.json +7 -7
  32. package/node_modules/@smithy/credential-provider-imds/package.json +5 -5
  33. package/node_modules/@smithy/fetch-http-handler/package.json +5 -5
  34. package/node_modules/@smithy/hash-node/package.json +2 -2
  35. package/node_modules/@smithy/invalid-dependency/package.json +2 -2
  36. package/node_modules/@smithy/middleware-content-length/package.json +3 -3
  37. package/node_modules/@smithy/middleware-endpoint/package.json +8 -8
  38. package/node_modules/@smithy/middleware-retry/package.json +9 -9
  39. package/node_modules/@smithy/middleware-serde/package.json +4 -4
  40. package/node_modules/@smithy/middleware-stack/package.json +2 -2
  41. package/node_modules/@smithy/node-config-provider/package.json +4 -4
  42. package/node_modules/@smithy/node-http-handler/dist-cjs/index.js +6 -6
  43. package/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js +1 -1
  44. package/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +5 -5
  45. package/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +14 -1
  46. package/node_modules/@smithy/node-http-handler/package.json +5 -5
  47. package/node_modules/@smithy/property-provider/package.json +2 -2
  48. package/node_modules/@smithy/protocol-http/package.json +2 -2
  49. package/node_modules/@smithy/querystring-builder/package.json +2 -2
  50. package/node_modules/@smithy/querystring-parser/package.json +2 -2
  51. package/node_modules/@smithy/service-error-classification/package.json +2 -2
  52. package/node_modules/@smithy/shared-ini-file-loader/package.json +2 -2
  53. package/node_modules/@smithy/signature-v4/dist-cjs/index.js +11 -5
  54. package/node_modules/@smithy/signature-v4/dist-es/SignatureV4.js +11 -5
  55. package/node_modules/@smithy/signature-v4/dist-types/SignatureV4.d.ts +3 -3
  56. package/node_modules/@smithy/signature-v4/package.json +4 -4
  57. package/node_modules/@smithy/smithy-client/dist-cjs/index.js +8 -1
  58. package/node_modules/@smithy/smithy-client/dist-es/command.js +8 -1
  59. package/node_modules/@smithy/smithy-client/package.json +7 -7
  60. package/node_modules/@smithy/types/dist-types/connection/config.d.ts +5 -0
  61. package/node_modules/@smithy/types/dist-types/signature.d.ts +20 -3
  62. package/node_modules/@smithy/types/package.json +1 -1
  63. package/node_modules/@smithy/url-parser/package.json +3 -3
  64. package/node_modules/@smithy/util-defaults-mode-browser/package.json +4 -4
  65. package/node_modules/@smithy/util-defaults-mode-node/package.json +7 -7
  66. package/node_modules/@smithy/util-endpoints/dist-cjs/index.js +165 -76
  67. package/node_modules/@smithy/util-endpoints/dist-es/bdd/BinaryDecisionDiagram.js +15 -0
  68. package/node_modules/@smithy/util-endpoints/dist-es/decideEndpoint.js +42 -0
  69. package/node_modules/@smithy/util-endpoints/dist-es/index.js +2 -0
  70. package/node_modules/@smithy/util-endpoints/dist-es/lib/coalesce.js +8 -0
  71. package/node_modules/@smithy/util-endpoints/dist-es/lib/getAttr.js +2 -1
  72. package/node_modules/@smithy/util-endpoints/dist-es/lib/index.js +3 -0
  73. package/node_modules/@smithy/util-endpoints/dist-es/lib/ite.js +3 -0
  74. package/node_modules/@smithy/util-endpoints/dist-es/lib/split.js +13 -0
  75. package/node_modules/@smithy/util-endpoints/dist-es/lib/substring.js +1 -1
  76. package/node_modules/@smithy/util-endpoints/dist-es/resolveEndpoint.js +8 -13
  77. package/node_modules/@smithy/util-endpoints/dist-es/utils/endpointFunctions.js +4 -1
  78. package/node_modules/@smithy/util-endpoints/dist-es/utils/evaluateExpression.js +20 -5
  79. package/node_modules/@smithy/util-endpoints/dist-es/utils/evaluateTemplate.js +3 -6
  80. package/node_modules/@smithy/util-endpoints/dist-es/utils/getEndpointHeaders.js +1 -1
  81. package/node_modules/@smithy/util-endpoints/dist-es/utils/getReferenceValue.js +1 -5
  82. package/node_modules/@smithy/util-endpoints/dist-types/bdd/BinaryDecisionDiagram.d.ts +22 -0
  83. package/node_modules/@smithy/util-endpoints/dist-types/decideEndpoint.d.ts +7 -0
  84. package/node_modules/@smithy/util-endpoints/dist-types/index.d.ts +2 -0
  85. package/node_modules/@smithy/util-endpoints/dist-types/lib/coalesce.d.ts +7 -0
  86. package/node_modules/@smithy/util-endpoints/dist-types/lib/index.d.ts +3 -0
  87. package/node_modules/@smithy/util-endpoints/dist-types/lib/ite.d.ts +6 -0
  88. package/node_modules/@smithy/util-endpoints/dist-types/lib/split.d.ts +11 -0
  89. package/node_modules/@smithy/util-endpoints/dist-types/utils/endpointFunctions.d.ts +4 -0
  90. package/node_modules/@smithy/util-endpoints/dist-types/utils/getReferenceValue.d.ts +3 -1
  91. package/node_modules/@smithy/util-endpoints/package.json +3 -3
  92. package/node_modules/@smithy/util-middleware/package.json +2 -2
  93. package/node_modules/@smithy/util-retry/dist-cjs/index.js +6 -0
  94. package/node_modules/@smithy/util-retry/dist-es/AdaptiveRetryStrategy.js +3 -0
  95. package/node_modules/@smithy/util-retry/dist-es/StandardRetryStrategy.js +3 -0
  96. package/node_modules/@smithy/util-retry/dist-types/AdaptiveRetryStrategy.d.ts +5 -0
  97. package/node_modules/@smithy/util-retry/dist-types/StandardRetryStrategy.d.ts +5 -0
  98. package/node_modules/@smithy/util-retry/package.json +3 -3
  99. package/node_modules/@smithy/util-stream/package.json +4 -4
  100. package/node_modules/@smithy/util-waiter/package.json +3 -3
  101. package/node_modules/path-expression-matcher/README.md +41 -54
  102. package/node_modules/path-expression-matcher/lib/pem.cjs +1 -1
  103. package/node_modules/path-expression-matcher/lib/pem.min.js +1 -1
  104. package/node_modules/path-expression-matcher/lib/pem.min.js.map +1 -1
  105. package/node_modules/path-expression-matcher/package.json +1 -1
  106. package/node_modules/path-expression-matcher/src/Matcher.js +223 -195
  107. package/node_modules/path-expression-matcher/src/index.d.ts +64 -247
  108. package/package.json +7 -7
@@ -2,6 +2,22 @@
2
2
 
3
3
  var types = require('@smithy/types');
4
4
 
5
+ class BinaryDecisionDiagram {
6
+ nodes;
7
+ root;
8
+ conditions;
9
+ results;
10
+ constructor(bdd, root, conditions, results) {
11
+ this.nodes = bdd;
12
+ this.root = root;
13
+ this.conditions = conditions;
14
+ this.results = results;
15
+ }
16
+ static from(bdd, root, conditions, results) {
17
+ return new BinaryDecisionDiagram(bdd, root, conditions, results);
18
+ }
19
+ }
20
+
5
21
  class EndpointCache {
6
22
  capacity;
7
23
  data = new Map();
@@ -53,24 +69,12 @@ class EndpointCache {
53
69
  }
54
70
  }
55
71
 
56
- const IP_V4_REGEX = new RegExp(`^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$`);
57
- const isIpAddress = (value) => IP_V4_REGEX.test(value) || (value.startsWith("[") && value.endsWith("]"));
58
-
59
- const VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`);
60
- const isValidHostLabel = (value, allowSubDomains = false) => {
61
- if (!allowSubDomains) {
62
- return VALID_HOST_LABEL_REGEX.test(value);
63
- }
64
- const labels = value.split(".");
65
- for (const label of labels) {
66
- if (!isValidHostLabel(label)) {
67
- return false;
68
- }
72
+ class EndpointError extends Error {
73
+ constructor(message) {
74
+ super(message);
75
+ this.name = "EndpointError";
69
76
  }
70
- return true;
71
- };
72
-
73
- const customEndpointFunctions = {};
77
+ }
74
78
 
75
79
  const debugId = "endpoints";
76
80
 
@@ -87,15 +91,19 @@ function toDebugString(input) {
87
91
  return JSON.stringify(input, null, 2);
88
92
  }
89
93
 
90
- class EndpointError extends Error {
91
- constructor(message) {
92
- super(message);
93
- this.name = "EndpointError";
94
- }
95
- }
94
+ const customEndpointFunctions = {};
96
95
 
97
96
  const booleanEquals = (value1, value2) => value1 === value2;
98
97
 
98
+ function coalesce(...args) {
99
+ for (const arg of args) {
100
+ if (arg != null) {
101
+ return arg;
102
+ }
103
+ }
104
+ return undefined;
105
+ }
106
+
99
107
  const getAttrPathList = (path) => {
100
108
  const parts = path.split(".");
101
109
  const pathList = [];
@@ -126,15 +134,37 @@ const getAttr = (value, path) => getAttrPathList(path).reduce((acc, index) => {
126
134
  throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`);
127
135
  }
128
136
  else if (Array.isArray(acc)) {
129
- return acc[parseInt(index)];
137
+ const i = parseInt(index);
138
+ return acc[i < 0 ? acc.length + i : i];
130
139
  }
131
140
  return acc[index];
132
141
  }, value);
133
142
 
134
143
  const isSet = (value) => value != null;
135
144
 
145
+ const VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`);
146
+ const isValidHostLabel = (value, allowSubDomains = false) => {
147
+ if (!allowSubDomains) {
148
+ return VALID_HOST_LABEL_REGEX.test(value);
149
+ }
150
+ const labels = value.split(".");
151
+ for (const label of labels) {
152
+ if (!isValidHostLabel(label)) {
153
+ return false;
154
+ }
155
+ }
156
+ return true;
157
+ };
158
+
159
+ function ite(condition, trueValue, falseValue) {
160
+ return condition ? trueValue : falseValue;
161
+ }
162
+
136
163
  const not = (value) => !value;
137
164
 
165
+ const IP_V4_REGEX = new RegExp(`^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$`);
166
+ const isIpAddress = (value) => IP_V4_REGEX.test(value) || (value.startsWith("[") && value.endsWith("]"));
167
+
138
168
  const DEFAULT_PORTS = {
139
169
  [types.EndpointURLScheme.HTTP]: 80,
140
170
  [types.EndpointURLScheme.HTTPS]: 443,
@@ -185,10 +215,24 @@ const parseURL = (value) => {
185
215
  };
186
216
  };
187
217
 
218
+ function split(value, delimiter, limit) {
219
+ if (limit === 1) {
220
+ return [value];
221
+ }
222
+ if (value === "") {
223
+ return [""];
224
+ }
225
+ const parts = value.split(delimiter);
226
+ if (limit === 0) {
227
+ return parts;
228
+ }
229
+ return parts.slice(0, limit - 1).concat(parts.slice(1).join(delimiter));
230
+ }
231
+
188
232
  const stringEquals = (value1, value2) => value1 === value2;
189
233
 
190
234
  const substring = (input, start, stop, reverse) => {
191
- if (start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
235
+ if (input == null || start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
192
236
  return null;
193
237
  }
194
238
  if (!reverse) {
@@ -201,11 +245,14 @@ const uriEncode = (value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) =
201
245
 
202
246
  const endpointFunctions = {
203
247
  booleanEquals,
248
+ coalesce,
204
249
  getAttr,
205
250
  isSet,
206
251
  isValidHostLabel,
252
+ ite,
207
253
  not,
208
254
  parseURL,
255
+ split,
209
256
  stringEquals,
210
257
  substring,
211
258
  uriEncode,
@@ -213,10 +260,7 @@ const endpointFunctions = {
213
260
 
214
261
  const evaluateTemplate = (template, options) => {
215
262
  const evaluatedTemplateArr = [];
216
- const templateContext = {
217
- ...options.endpointParams,
218
- ...options.referenceRecord,
219
- };
263
+ const { referenceRecord, endpointParams } = options;
220
264
  let currentIndex = 0;
221
265
  while (currentIndex < template.length) {
222
266
  const openingBraceIndex = template.indexOf("{", currentIndex);
@@ -237,10 +281,10 @@ const evaluateTemplate = (template, options) => {
237
281
  const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex);
238
282
  if (parameterName.includes("#")) {
239
283
  const [refName, attrName] = parameterName.split("#");
240
- evaluatedTemplateArr.push(getAttr(templateContext[refName], attrName));
284
+ evaluatedTemplateArr.push(getAttr((referenceRecord[refName] ?? endpointParams[refName]), attrName));
241
285
  }
242
286
  else {
243
- evaluatedTemplateArr.push(templateContext[parameterName]);
287
+ evaluatedTemplateArr.push((referenceRecord[parameterName] ?? endpointParams[parameterName]));
244
288
  }
245
289
  currentIndex = closingBraceIndex + 1;
246
290
  }
@@ -248,11 +292,7 @@ const evaluateTemplate = (template, options) => {
248
292
  };
249
293
 
250
294
  const getReferenceValue = ({ ref }, options) => {
251
- const referenceRecord = {
252
- ...options.endpointParams,
253
- ...options.referenceRecord,
254
- };
255
- return referenceRecord[ref];
295
+ return options.referenceRecord[ref] ?? options.endpointParams[ref];
256
296
  };
257
297
 
258
298
  const evaluateExpression = (obj, keyName, options) => {
@@ -268,12 +308,27 @@ const evaluateExpression = (obj, keyName, options) => {
268
308
  throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`);
269
309
  };
270
310
  const callFunction = ({ fn, argv }, options) => {
271
- const evaluatedArgs = argv.map((arg) => ["boolean", "number"].includes(typeof arg) ? arg : group$2.evaluateExpression(arg, "arg", options));
272
- const fnSegments = fn.split(".");
273
- if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) {
274
- return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs);
311
+ const evaluatedArgs = Array(argv.length);
312
+ for (let i = 0; i < evaluatedArgs.length; ++i) {
313
+ const arg = argv[i];
314
+ if (typeof arg === "boolean" || typeof arg === "number") {
315
+ evaluatedArgs[i] = arg;
316
+ }
317
+ else {
318
+ evaluatedArgs[i] = group$2.evaluateExpression(arg, "arg", options);
319
+ }
320
+ }
321
+ if (fn.includes(".")) {
322
+ const fnSegments = fn.split(".");
323
+ if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) {
324
+ return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs);
325
+ }
275
326
  }
276
- return endpointFunctions[fn](...evaluatedArgs);
327
+ if (typeof endpointFunctions[fn] !== "function") {
328
+ throw new Error(`function ${fn} not loaded in endpointFunctions.`);
329
+ }
330
+ const callable = endpointFunctions[fn];
331
+ return callable(...evaluatedArgs);
277
332
  };
278
333
  const group$2 = {
279
334
  evaluateExpression,
@@ -292,28 +347,7 @@ const evaluateCondition = ({ assign, ...fnArgs }, options) => {
292
347
  };
293
348
  };
294
349
 
295
- const evaluateConditions = (conditions = [], options) => {
296
- const conditionsReferenceRecord = {};
297
- for (const condition of conditions) {
298
- const { result, toAssign } = evaluateCondition(condition, {
299
- ...options,
300
- referenceRecord: {
301
- ...options.referenceRecord,
302
- ...conditionsReferenceRecord,
303
- },
304
- });
305
- if (!result) {
306
- return { result };
307
- }
308
- if (toAssign) {
309
- conditionsReferenceRecord[toAssign.name] = toAssign.value;
310
- options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`);
311
- }
312
- }
313
- return { result: true, referenceRecord: conditionsReferenceRecord };
314
- };
315
-
316
- const getEndpointHeaders = (headers, options) => Object.entries(headers).reduce((acc, [headerKey, headerVal]) => ({
350
+ const getEndpointHeaders = (headers, options) => Object.entries(headers ?? {}).reduce((acc, [headerKey, headerVal]) => ({
317
351
  ...acc,
318
352
  [headerKey]: headerVal.map((headerValEntry) => {
319
353
  const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options);
@@ -365,6 +399,64 @@ const getEndpointUrl = (endpointUrl, options) => {
365
399
  throw new EndpointError(`Endpoint URL must be a string, got ${typeof expression}`);
366
400
  };
367
401
 
402
+ const RESULT = 100_000_000;
403
+ const decideEndpoint = (bdd, options) => {
404
+ const { nodes, root, results, conditions } = bdd;
405
+ let ref = root;
406
+ const referenceRecord = {};
407
+ const closure = {
408
+ referenceRecord,
409
+ endpointParams: options.endpointParams,
410
+ logger: options.logger,
411
+ };
412
+ while (ref !== 1 && ref !== -1 && ref < RESULT) {
413
+ const node_i = 3 * (Math.abs(ref) - 1);
414
+ const [condition_i, highRef, lowRef] = [nodes[node_i], nodes[node_i + 1], nodes[node_i + 2]];
415
+ const [fn, argv, assign] = conditions[condition_i];
416
+ const evaluation = evaluateCondition({ fn, assign, argv }, closure);
417
+ if (evaluation.toAssign) {
418
+ const { name, value } = evaluation.toAssign;
419
+ referenceRecord[name] = value;
420
+ }
421
+ ref = ref >= 0 === evaluation.result ? highRef : lowRef;
422
+ }
423
+ if (ref >= RESULT) {
424
+ const result = results[ref - RESULT];
425
+ if (result[0] === -1) {
426
+ const [, errorExpression] = result;
427
+ throw new EndpointError(evaluateExpression(errorExpression, "Error", closure));
428
+ }
429
+ const [url, properties, headers] = result;
430
+ return {
431
+ url: getEndpointUrl(url, closure),
432
+ properties: getEndpointProperties(properties, closure),
433
+ headers: getEndpointHeaders(headers ?? {}, closure),
434
+ };
435
+ }
436
+ throw new EndpointError(`No matching endpoint.`);
437
+ };
438
+
439
+ const evaluateConditions = (conditions = [], options) => {
440
+ const conditionsReferenceRecord = {};
441
+ for (const condition of conditions) {
442
+ const { result, toAssign } = evaluateCondition(condition, {
443
+ ...options,
444
+ referenceRecord: {
445
+ ...options.referenceRecord,
446
+ ...conditionsReferenceRecord,
447
+ },
448
+ });
449
+ if (!result) {
450
+ return { result };
451
+ }
452
+ if (toAssign) {
453
+ conditionsReferenceRecord[toAssign.name] = toAssign.value;
454
+ options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`);
455
+ }
456
+ }
457
+ return { result: true, referenceRecord: conditionsReferenceRecord };
458
+ };
459
+
368
460
  const evaluateEndpointRule = (endpointRule, options) => {
369
461
  const { conditions, endpoint } = endpointRule;
370
462
  const { result, referenceRecord } = evaluateConditions(conditions, options);
@@ -443,20 +535,15 @@ const resolveEndpoint = (ruleSetObject, options) => {
443
535
  const { endpointParams, logger } = options;
444
536
  const { parameters, rules } = ruleSetObject;
445
537
  options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`);
446
- const paramsWithDefault = Object.entries(parameters)
447
- .filter(([, v]) => v.default != null)
448
- .map(([k, v]) => [k, v.default]);
449
- if (paramsWithDefault.length > 0) {
450
- for (const [paramKey, paramDefaultValue] of paramsWithDefault) {
451
- endpointParams[paramKey] = endpointParams[paramKey] ?? paramDefaultValue;
538
+ for (const paramKey in parameters) {
539
+ const parameter = parameters[paramKey];
540
+ const endpointParam = endpointParams[paramKey];
541
+ if (endpointParam == null && parameter.default != null) {
542
+ endpointParams[paramKey] = parameter.default;
543
+ continue;
452
544
  }
453
- }
454
- const requiredParams = Object.entries(parameters)
455
- .filter(([, v]) => v.required)
456
- .map(([k]) => k);
457
- for (const requiredParam of requiredParams) {
458
- if (endpointParams[requiredParam] == null) {
459
- throw new EndpointError(`Missing required parameter: '${requiredParam}'`);
545
+ if (parameter.required && endpointParam == null) {
546
+ throw new EndpointError(`Missing required parameter: '${paramKey}'`);
460
547
  }
461
548
  }
462
549
  const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} });
@@ -464,9 +551,11 @@ const resolveEndpoint = (ruleSetObject, options) => {
464
551
  return endpoint;
465
552
  };
466
553
 
554
+ exports.BinaryDecisionDiagram = BinaryDecisionDiagram;
467
555
  exports.EndpointCache = EndpointCache;
468
556
  exports.EndpointError = EndpointError;
469
557
  exports.customEndpointFunctions = customEndpointFunctions;
558
+ exports.decideEndpoint = decideEndpoint;
470
559
  exports.isIpAddress = isIpAddress;
471
560
  exports.isValidHostLabel = isValidHostLabel;
472
561
  exports.resolveEndpoint = resolveEndpoint;
@@ -0,0 +1,15 @@
1
+ export class BinaryDecisionDiagram {
2
+ nodes;
3
+ root;
4
+ conditions;
5
+ results;
6
+ constructor(bdd, root, conditions, results) {
7
+ this.nodes = bdd;
8
+ this.root = root;
9
+ this.conditions = conditions;
10
+ this.results = results;
11
+ }
12
+ static from(bdd, root, conditions, results) {
13
+ return new BinaryDecisionDiagram(bdd, root, conditions, results);
14
+ }
15
+ }
@@ -0,0 +1,42 @@
1
+ import { EndpointError } from "./types";
2
+ import { evaluateCondition } from "./utils/evaluateCondition";
3
+ import { evaluateExpression } from "./utils/evaluateExpression";
4
+ import { getEndpointHeaders } from "./utils/getEndpointHeaders";
5
+ import { getEndpointProperties } from "./utils/getEndpointProperties";
6
+ import { getEndpointUrl } from "./utils/getEndpointUrl";
7
+ const RESULT = 100_000_000;
8
+ export const decideEndpoint = (bdd, options) => {
9
+ const { nodes, root, results, conditions } = bdd;
10
+ let ref = root;
11
+ const referenceRecord = {};
12
+ const closure = {
13
+ referenceRecord,
14
+ endpointParams: options.endpointParams,
15
+ logger: options.logger,
16
+ };
17
+ while (ref !== 1 && ref !== -1 && ref < RESULT) {
18
+ const node_i = 3 * (Math.abs(ref) - 1);
19
+ const [condition_i, highRef, lowRef] = [nodes[node_i], nodes[node_i + 1], nodes[node_i + 2]];
20
+ const [fn, argv, assign] = conditions[condition_i];
21
+ const evaluation = evaluateCondition({ fn, assign, argv }, closure);
22
+ if (evaluation.toAssign) {
23
+ const { name, value } = evaluation.toAssign;
24
+ referenceRecord[name] = value;
25
+ }
26
+ ref = ref >= 0 === evaluation.result ? highRef : lowRef;
27
+ }
28
+ if (ref >= RESULT) {
29
+ const result = results[ref - RESULT];
30
+ if (result[0] === -1) {
31
+ const [, errorExpression] = result;
32
+ throw new EndpointError(evaluateExpression(errorExpression, "Error", closure));
33
+ }
34
+ const [url, properties, headers] = result;
35
+ return {
36
+ url: getEndpointUrl(url, closure),
37
+ properties: getEndpointProperties(properties, closure),
38
+ headers: getEndpointHeaders(headers ?? {}, closure),
39
+ };
40
+ }
41
+ throw new EndpointError(`No matching endpoint.`);
42
+ };
@@ -1,4 +1,6 @@
1
+ export { BinaryDecisionDiagram } from "./bdd/BinaryDecisionDiagram";
1
2
  export * from "./cache/EndpointCache";
3
+ export { decideEndpoint } from "./decideEndpoint";
2
4
  export * from "./lib/isIpAddress";
3
5
  export * from "./lib/isValidHostLabel";
4
6
  export * from "./utils/customEndpointFunctions";
@@ -0,0 +1,8 @@
1
+ export function coalesce(...args) {
2
+ for (const arg of args) {
3
+ if (arg != null) {
4
+ return arg;
5
+ }
6
+ }
7
+ return undefined;
8
+ }
@@ -5,7 +5,8 @@ export const getAttr = (value, path) => getAttrPathList(path).reduce((acc, index
5
5
  throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`);
6
6
  }
7
7
  else if (Array.isArray(acc)) {
8
- return acc[parseInt(index)];
8
+ const i = parseInt(index);
9
+ return acc[i < 0 ? acc.length + i : i];
9
10
  }
10
11
  return acc[index];
11
12
  }, value);
@@ -1,9 +1,12 @@
1
1
  export * from "./booleanEquals";
2
+ export * from "./coalesce";
2
3
  export * from "./getAttr";
3
4
  export * from "./isSet";
4
5
  export * from "./isValidHostLabel";
6
+ export * from "./ite";
5
7
  export * from "./not";
6
8
  export * from "./parseURL";
9
+ export * from "./split";
7
10
  export * from "./stringEquals";
8
11
  export * from "./substring";
9
12
  export * from "./uriEncode";
@@ -0,0 +1,3 @@
1
+ export function ite(condition, trueValue, falseValue) {
2
+ return condition ? trueValue : falseValue;
3
+ }
@@ -0,0 +1,13 @@
1
+ export function split(value, delimiter, limit) {
2
+ if (limit === 1) {
3
+ return [value];
4
+ }
5
+ if (value === "") {
6
+ return [""];
7
+ }
8
+ const parts = value.split(delimiter);
9
+ if (limit === 0) {
10
+ return parts;
11
+ }
12
+ return parts.slice(0, limit - 1).concat(parts.slice(1).join(delimiter));
13
+ }
@@ -1,5 +1,5 @@
1
1
  export const substring = (input, start, stop, reverse) => {
2
- if (start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
2
+ if (input == null || start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
3
3
  return null;
4
4
  }
5
5
  if (!reverse) {
@@ -5,20 +5,15 @@ export const resolveEndpoint = (ruleSetObject, options) => {
5
5
  const { endpointParams, logger } = options;
6
6
  const { parameters, rules } = ruleSetObject;
7
7
  options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`);
8
- const paramsWithDefault = Object.entries(parameters)
9
- .filter(([, v]) => v.default != null)
10
- .map(([k, v]) => [k, v.default]);
11
- if (paramsWithDefault.length > 0) {
12
- for (const [paramKey, paramDefaultValue] of paramsWithDefault) {
13
- endpointParams[paramKey] = endpointParams[paramKey] ?? paramDefaultValue;
8
+ for (const paramKey in parameters) {
9
+ const parameter = parameters[paramKey];
10
+ const endpointParam = endpointParams[paramKey];
11
+ if (endpointParam == null && parameter.default != null) {
12
+ endpointParams[paramKey] = parameter.default;
13
+ continue;
14
14
  }
15
- }
16
- const requiredParams = Object.entries(parameters)
17
- .filter(([, v]) => v.required)
18
- .map(([k]) => k);
19
- for (const requiredParam of requiredParams) {
20
- if (endpointParams[requiredParam] == null) {
21
- throw new EndpointError(`Missing required parameter: '${requiredParam}'`);
15
+ if (parameter.required && endpointParam == null) {
16
+ throw new EndpointError(`Missing required parameter: '${paramKey}'`);
22
17
  }
23
18
  }
24
19
  const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} });
@@ -1,11 +1,14 @@
1
- import { booleanEquals, getAttr, isSet, isValidHostLabel, not, parseURL, stringEquals, substring, uriEncode, } from "../lib";
1
+ import { booleanEquals, coalesce, getAttr, isSet, isValidHostLabel, ite, not, parseURL, split, stringEquals, substring, uriEncode, } from "../lib";
2
2
  export const endpointFunctions = {
3
3
  booleanEquals,
4
+ coalesce,
4
5
  getAttr,
5
6
  isSet,
6
7
  isValidHostLabel,
8
+ ite,
7
9
  not,
8
10
  parseURL,
11
+ split,
9
12
  stringEquals,
10
13
  substring,
11
14
  uriEncode,
@@ -16,12 +16,27 @@ export const evaluateExpression = (obj, keyName, options) => {
16
16
  throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`);
17
17
  };
18
18
  export const callFunction = ({ fn, argv }, options) => {
19
- const evaluatedArgs = argv.map((arg) => ["boolean", "number"].includes(typeof arg) ? arg : group.evaluateExpression(arg, "arg", options));
20
- const fnSegments = fn.split(".");
21
- if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) {
22
- return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs);
19
+ const evaluatedArgs = Array(argv.length);
20
+ for (let i = 0; i < evaluatedArgs.length; ++i) {
21
+ const arg = argv[i];
22
+ if (typeof arg === "boolean" || typeof arg === "number") {
23
+ evaluatedArgs[i] = arg;
24
+ }
25
+ else {
26
+ evaluatedArgs[i] = group.evaluateExpression(arg, "arg", options);
27
+ }
23
28
  }
24
- return endpointFunctions[fn](...evaluatedArgs);
29
+ if (fn.includes(".")) {
30
+ const fnSegments = fn.split(".");
31
+ if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) {
32
+ return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs);
33
+ }
34
+ }
35
+ if (typeof endpointFunctions[fn] !== "function") {
36
+ throw new Error(`function ${fn} not loaded in endpointFunctions.`);
37
+ }
38
+ const callable = endpointFunctions[fn];
39
+ return callable(...evaluatedArgs);
25
40
  };
26
41
  export const group = {
27
42
  evaluateExpression,
@@ -1,10 +1,7 @@
1
1
  import { getAttr } from "../lib";
2
2
  export const evaluateTemplate = (template, options) => {
3
3
  const evaluatedTemplateArr = [];
4
- const templateContext = {
5
- ...options.endpointParams,
6
- ...options.referenceRecord,
7
- };
4
+ const { referenceRecord, endpointParams } = options;
8
5
  let currentIndex = 0;
9
6
  while (currentIndex < template.length) {
10
7
  const openingBraceIndex = template.indexOf("{", currentIndex);
@@ -25,10 +22,10 @@ export const evaluateTemplate = (template, options) => {
25
22
  const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex);
26
23
  if (parameterName.includes("#")) {
27
24
  const [refName, attrName] = parameterName.split("#");
28
- evaluatedTemplateArr.push(getAttr(templateContext[refName], attrName));
25
+ evaluatedTemplateArr.push(getAttr((referenceRecord[refName] ?? endpointParams[refName]), attrName));
29
26
  }
30
27
  else {
31
- evaluatedTemplateArr.push(templateContext[parameterName]);
28
+ evaluatedTemplateArr.push((referenceRecord[parameterName] ?? endpointParams[parameterName]));
32
29
  }
33
30
  currentIndex = closingBraceIndex + 1;
34
31
  }
@@ -1,6 +1,6 @@
1
1
  import { EndpointError } from "../types";
2
2
  import { evaluateExpression } from "./evaluateExpression";
3
- export const getEndpointHeaders = (headers, options) => Object.entries(headers).reduce((acc, [headerKey, headerVal]) => ({
3
+ export const getEndpointHeaders = (headers, options) => Object.entries(headers ?? {}).reduce((acc, [headerKey, headerVal]) => ({
4
4
  ...acc,
5
5
  [headerKey]: headerVal.map((headerValEntry) => {
6
6
  const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options);
@@ -1,7 +1,3 @@
1
1
  export const getReferenceValue = ({ ref }, options) => {
2
- const referenceRecord = {
3
- ...options.endpointParams,
4
- ...options.referenceRecord,
5
- };
6
- return referenceRecord[ref];
2
+ return options.referenceRecord[ref] ?? options.endpointParams[ref];
7
3
  };
@@ -0,0 +1,22 @@
1
+ import type { EndpointObjectHeaders, ParameterObject } from "@smithy/types";
2
+ import type { Expression, FunctionArgv } from "../types/shared";
3
+ /**
4
+ * @internal
5
+ */
6
+ type BddCondition = [string, FunctionArgv] | [string, FunctionArgv, string];
7
+ /**
8
+ * @internal
9
+ */
10
+ type BddResult = [-1] | [-1, Expression] | [string, Record<string, ParameterObject>, EndpointObjectHeaders] | [string, Record<string, ParameterObject>];
11
+ /**
12
+ * @internal
13
+ */
14
+ export declare class BinaryDecisionDiagram {
15
+ nodes: Int32Array;
16
+ root: number;
17
+ conditions: BddCondition[];
18
+ results: BddResult[];
19
+ private constructor();
20
+ static from(bdd: Int32Array, root: number, conditions: BddCondition[] | any[], results: BddResult[] | any[]): BinaryDecisionDiagram;
21
+ }
22
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { EndpointV2 } from "@smithy/types";
2
+ import type { BinaryDecisionDiagram } from "./bdd/BinaryDecisionDiagram";
3
+ import type { EndpointResolverOptions } from "./types";
4
+ /**
5
+ * Resolves an endpoint URL by processing the endpoints bdd and options.
6
+ */
7
+ export declare const decideEndpoint: (bdd: BinaryDecisionDiagram, options: EndpointResolverOptions) => EndpointV2;
@@ -1,4 +1,6 @@
1
+ export { BinaryDecisionDiagram } from "./bdd/BinaryDecisionDiagram";
1
2
  export * from "./cache/EndpointCache";
3
+ export { decideEndpoint } from "./decideEndpoint";
2
4
  export * from "./lib/isIpAddress";
3
5
  export * from "./lib/isValidHostLabel";
4
6
  export * from "./utils/customEndpointFunctions";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Evaluates arguments in order and returns the first non-empty result,
3
+ * otherwise returns the result of the last argument.
4
+ *
5
+ * @internal
6
+ */
7
+ export declare function coalesce<T>(...args: (T | undefined)[]): T | undefined;