@aws/cloudformation-validate 1.8.0-beta → 1.10.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/bindings_wasm.js CHANGED
@@ -48,18 +48,92 @@ class WasmCelEngine {
48
48
  WasmCelEngineFinalization.register(this, this.__wbg_ptr, this);
49
49
  return this;
50
50
  }
51
+ /**
52
+ * @param {any} request
53
+ * @returns {any}
54
+ */
55
+ validateAwsCliCommand(request) {
56
+ const ret = wasm.wasmcelengine_validateAwsCliCommand(this.__wbg_ptr, request);
57
+ if (ret[2]) {
58
+ throw takeFromExternrefTable0(ret[1]);
59
+ }
60
+ return takeFromExternrefTable0(ret[0]);
61
+ }
51
62
  /**
52
63
  * @param {Uint8Array} template
53
64
  * @param {ValidateConfig} options
54
65
  * @param {string} file_path
55
66
  * @returns {any}
56
67
  */
57
- validateDetailed(template, options, file_path) {
68
+ validateTemplate(template, options, file_path) {
58
69
  const ptr0 = passArray8ToWasm0(template, wasm.__wbindgen_malloc);
59
70
  const len0 = WASM_VECTOR_LEN;
60
71
  const ptr1 = passStringToWasm0(file_path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
61
72
  const len1 = WASM_VECTOR_LEN;
62
- const ret = wasm.wasmcelengine_validateDetailed(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
73
+ const ret = wasm.wasmcelengine_validateTemplate(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
74
+ if (ret[2]) {
75
+ throw takeFromExternrefTable0(ret[1]);
76
+ }
77
+ return takeFromExternrefTable0(ret[0]);
78
+ }
79
+ }
80
+ if (Symbol.dispose) WasmCelEngine.prototype[Symbol.dispose] = WasmCelEngine.prototype.free;
81
+ exports.WasmCelEngine = WasmCelEngine;
82
+
83
+ class WasmCompositeEngine {
84
+ __destroy_into_raw() {
85
+ const ptr = this.__wbg_ptr;
86
+ this.__wbg_ptr = 0;
87
+ WasmCompositeEngineFinalization.unregister(this);
88
+ return ptr;
89
+ }
90
+ free() {
91
+ const ptr = this.__destroy_into_raw();
92
+ wasm.__wbg_wasmcompositeengine_free(ptr, 0);
93
+ }
94
+ /**
95
+ * @returns {string}
96
+ */
97
+ engineName() {
98
+ let deferred1_0;
99
+ let deferred1_1;
100
+ try {
101
+ const ret = wasm.wasmcompositeengine_engineName(this.__wbg_ptr);
102
+ deferred1_0 = ret[0];
103
+ deferred1_1 = ret[1];
104
+ return getStringFromWasm0(ret[0], ret[1]);
105
+ } finally {
106
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
107
+ }
108
+ }
109
+ /**
110
+ * @returns {any}
111
+ */
112
+ listRules() {
113
+ const ret = wasm.wasmcompositeengine_listRules(this.__wbg_ptr);
114
+ if (ret[2]) {
115
+ throw takeFromExternrefTable0(ret[1]);
116
+ }
117
+ return takeFromExternrefTable0(ret[0]);
118
+ }
119
+ /**
120
+ * @param {CompositeEngineConfig} config
121
+ */
122
+ constructor(config) {
123
+ const ret = wasm.wasmcompositeengine_new(config);
124
+ if (ret[2]) {
125
+ throw takeFromExternrefTable0(ret[1]);
126
+ }
127
+ this.__wbg_ptr = ret[0];
128
+ WasmCompositeEngineFinalization.register(this, this.__wbg_ptr, this);
129
+ return this;
130
+ }
131
+ /**
132
+ * @param {any} request
133
+ * @returns {any}
134
+ */
135
+ validateAwsCliCommand(request) {
136
+ const ret = wasm.wasmcompositeengine_validateAwsCliCommand(this.__wbg_ptr, request);
63
137
  if (ret[2]) {
64
138
  throw takeFromExternrefTable0(ret[1]);
65
139
  }
@@ -71,20 +145,20 @@ class WasmCelEngine {
71
145
  * @param {string} file_path
72
146
  * @returns {any}
73
147
  */
74
- validateStandard(template, options, file_path) {
148
+ validateTemplate(template, options, file_path) {
75
149
  const ptr0 = passArray8ToWasm0(template, wasm.__wbindgen_malloc);
76
150
  const len0 = WASM_VECTOR_LEN;
77
151
  const ptr1 = passStringToWasm0(file_path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
78
152
  const len1 = WASM_VECTOR_LEN;
79
- const ret = wasm.wasmcelengine_validateStandard(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
153
+ const ret = wasm.wasmcompositeengine_validateTemplate(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
80
154
  if (ret[2]) {
81
155
  throw takeFromExternrefTable0(ret[1]);
82
156
  }
83
157
  return takeFromExternrefTable0(ret[0]);
84
158
  }
85
159
  }
86
- if (Symbol.dispose) WasmCelEngine.prototype[Symbol.dispose] = WasmCelEngine.prototype.free;
87
- exports.WasmCelEngine = WasmCelEngine;
160
+ if (Symbol.dispose) WasmCompositeEngine.prototype[Symbol.dispose] = WasmCompositeEngine.prototype.free;
161
+ exports.WasmCompositeEngine = WasmCompositeEngine;
88
162
 
89
163
  class WasmRegoEngine {
90
164
  __destroy_into_raw() {
@@ -135,17 +209,11 @@ class WasmRegoEngine {
135
209
  return this;
136
210
  }
137
211
  /**
138
- * @param {Uint8Array} template
139
- * @param {ValidateConfig} options
140
- * @param {string} file_path
212
+ * @param {any} request
141
213
  * @returns {any}
142
214
  */
143
- validateDetailed(template, options, file_path) {
144
- const ptr0 = passArray8ToWasm0(template, wasm.__wbindgen_malloc);
145
- const len0 = WASM_VECTOR_LEN;
146
- const ptr1 = passStringToWasm0(file_path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
147
- const len1 = WASM_VECTOR_LEN;
148
- const ret = wasm.wasmregoengine_validateDetailed(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
215
+ validateAwsCliCommand(request) {
216
+ const ret = wasm.wasmregoengine_validateAwsCliCommand(this.__wbg_ptr, request);
149
217
  if (ret[2]) {
150
218
  throw takeFromExternrefTable0(ret[1]);
151
219
  }
@@ -157,12 +225,12 @@ class WasmRegoEngine {
157
225
  * @param {string} file_path
158
226
  * @returns {any}
159
227
  */
160
- validateStandard(template, options, file_path) {
228
+ validateTemplate(template, options, file_path) {
161
229
  const ptr0 = passArray8ToWasm0(template, wasm.__wbindgen_malloc);
162
230
  const len0 = WASM_VECTOR_LEN;
163
231
  const ptr1 = passStringToWasm0(file_path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
164
232
  const len1 = WASM_VECTOR_LEN;
165
- const ret = wasm.wasmregoengine_validateStandard(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
233
+ const ret = wasm.wasmregoengine_validateTemplate(this.__wbg_ptr, ptr0, len0, options, ptr1, len1);
166
234
  if (ret[2]) {
167
235
  throw takeFromExternrefTable0(ret[1]);
168
236
  }
@@ -401,6 +469,12 @@ function __wbg_get_imports() {
401
469
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
402
470
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
403
471
  },
472
+ __wbg___wbindgen_bigint_get_as_i64_d968e41184ae354f: function (arg0, arg1) {
473
+ const v = arg1;
474
+ const ret = typeof v === 'bigint' ? v : undefined;
475
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
476
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
477
+ },
404
478
  __wbg___wbindgen_boolean_get_fa956cfa2d1bd751: function (arg0) {
405
479
  const v = arg0;
406
480
  const ret = typeof v === 'boolean' ? v : undefined;
@@ -417,6 +491,10 @@ function __wbg_get_imports() {
417
491
  const ret = arg0 in arg1;
418
492
  return ret;
419
493
  },
494
+ __wbg___wbindgen_is_bigint_2f76dc55065b4273: function (arg0) {
495
+ const ret = typeof arg0 === 'bigint';
496
+ return ret;
497
+ },
420
498
  __wbg___wbindgen_is_function_1ff95bcc5517c252: function (arg0) {
421
499
  const ret = typeof arg0 === 'function';
422
500
  return ret;
@@ -434,6 +512,10 @@ function __wbg_get_imports() {
434
512
  const ret = arg0 === undefined;
435
513
  return ret;
436
514
  },
515
+ __wbg___wbindgen_jsval_eq_e659fcf7b0e32763: function (arg0, arg1) {
516
+ const ret = arg0 === arg1;
517
+ return ret;
518
+ },
437
519
  __wbg___wbindgen_jsval_loose_eq_db4c3b15f63fc170: function (arg0, arg1) {
438
520
  const ret = arg0 == arg1;
439
521
  return ret;
@@ -485,6 +567,10 @@ function __wbg_get_imports() {
485
567
  globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
486
568
  }, arguments);
487
569
  },
570
+ __wbg_getTime_d6f070c088c9b5ed: function (arg0) {
571
+ const ret = arg0.getTime();
572
+ return ret;
573
+ },
488
574
  __wbg_get_507a50627bffa49b: function (arg0, arg1) {
489
575
  const ret = arg0[arg1 >>> 0];
490
576
  return ret;
@@ -513,6 +599,16 @@ function __wbg_get_imports() {
513
599
  const ret = result;
514
600
  return ret;
515
601
  },
602
+ __wbg_instanceof_Map_e5b5e3db98422fcc: function (arg0) {
603
+ let result;
604
+ try {
605
+ result = arg0 instanceof Map;
606
+ } catch (_) {
607
+ result = false;
608
+ }
609
+ const ret = result;
610
+ return ret;
611
+ },
516
612
  __wbg_instanceof_Uint8Array_309b927aaf7a3fc7: function (arg0) {
517
613
  let result;
518
614
  try {
@@ -543,6 +639,10 @@ function __wbg_get_imports() {
543
639
  const ret = arg0.length;
544
640
  return ret;
545
641
  },
642
+ __wbg_new_0_3da9e97f24fc69be: function () {
643
+ const ret = new Date();
644
+ return ret;
645
+ },
546
646
  __wbg_new_227d7c05414eb861: function () {
547
647
  const ret = new Error();
548
648
  return ret;
@@ -661,6 +761,10 @@ const WasmCelEngineFinalization =
661
761
  typeof FinalizationRegistry === 'undefined'
662
762
  ? { register: () => {}, unregister: () => {} }
663
763
  : new FinalizationRegistry((ptr) => wasm.__wbg_wasmcelengine_free(ptr, 1));
764
+ const WasmCompositeEngineFinalization =
765
+ typeof FinalizationRegistry === 'undefined'
766
+ ? { register: () => {}, unregister: () => {} }
767
+ : new FinalizationRegistry((ptr) => wasm.__wbg_wasmcompositeengine_free(ptr, 1));
664
768
  const WasmRegoEngineFinalization =
665
769
  typeof FinalizationRegistry === 'undefined'
666
770
  ? { register: () => {}, unregister: () => {} }
Binary file
@@ -2,6 +2,7 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const __wbg_wasmcelengine_free: (a: number, b: number) => void;
5
+ export const __wbg_wasmcompositeengine_free: (a: number, b: number) => void;
5
6
  export const __wbg_wasmregoengine_free: (a: number, b: number) => void;
6
7
  export const __wbg_wasmschemavalidator_free: (a: number, b: number) => void;
7
8
  export const __wbg_wasmsemanticmodel_free: (a: number, b: number) => void;
@@ -10,7 +11,8 @@ export const version: () => [number, number];
10
11
  export const wasmcelengine_engineName: (a: number) => [number, number];
11
12
  export const wasmcelengine_listRules: (a: number) => [number, number, number];
12
13
  export const wasmcelengine_new: (a: any) => [number, number, number];
13
- export const wasmcelengine_validateDetailed: (
14
+ export const wasmcelengine_validateAwsCliCommand: (a: number, b: any) => [number, number, number];
15
+ export const wasmcelengine_validateTemplate: (
14
16
  a: number,
15
17
  b: number,
16
18
  c: number,
@@ -18,7 +20,11 @@ export const wasmcelengine_validateDetailed: (
18
20
  e: number,
19
21
  f: number,
20
22
  ) => [number, number, number];
21
- export const wasmcelengine_validateStandard: (
23
+ export const wasmcompositeengine_engineName: (a: number) => [number, number];
24
+ export const wasmcompositeengine_listRules: (a: number) => [number, number, number];
25
+ export const wasmcompositeengine_new: (a: any) => [number, number, number];
26
+ export const wasmcompositeengine_validateAwsCliCommand: (a: number, b: any) => [number, number, number];
27
+ export const wasmcompositeengine_validateTemplate: (
22
28
  a: number,
23
29
  b: number,
24
30
  c: number,
@@ -29,15 +35,8 @@ export const wasmcelengine_validateStandard: (
29
35
  export const wasmregoengine_engineName: (a: number) => [number, number];
30
36
  export const wasmregoengine_listRules: (a: number) => [number, number, number];
31
37
  export const wasmregoengine_new: (a: any) => [number, number, number];
32
- export const wasmregoengine_validateDetailed: (
33
- a: number,
34
- b: number,
35
- c: number,
36
- d: any,
37
- e: number,
38
- f: number,
39
- ) => [number, number, number];
40
- export const wasmregoengine_validateStandard: (
38
+ export const wasmregoengine_validateAwsCliCommand: (a: number, b: any) => [number, number, number];
39
+ export const wasmregoengine_validateTemplate: (
41
40
  a: number,
42
41
  b: number,
43
42
  c: number,
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type {
2
- DetailedReport,
2
+ Diagnostic,
3
+ ValidationReport,
3
4
  DiagnosticModel,
4
5
  AdditionalSchemaSource,
5
6
  ExternalRuleSource,
@@ -8,8 +9,6 @@ import type {
8
9
  ResolvedResource,
9
10
  RuleInfo,
10
11
  SourceSpan,
11
- StandardDiagnostic,
12
- StandardReport,
13
12
  ValidateConfig,
14
13
  } from './bindings_wasm';
15
14
  export type {
@@ -29,14 +28,12 @@ export type {
29
28
  ResourceRef,
30
29
  RelatedResource,
31
30
  ViolationContext,
32
- StandardDiagnostic,
33
- DetailedDiagnostic,
31
+ Diagnostic,
34
32
  PhaseMetric,
35
33
  PerformanceMetrics,
36
34
  Summary,
37
35
  ReportMetadata,
38
- StandardReport,
39
- DetailedReport,
36
+ ValidationReport,
40
37
  PseudoParameterOverrides,
41
38
  ValidateConfig,
42
39
  ExternalRuleSource,
@@ -79,9 +76,55 @@ export type JsonValue =
79
76
  | {
80
77
  [key: string]: JsonValue;
81
78
  };
79
+ export type AwsCliOperationKind =
80
+ | 'READ_ONLY'
81
+ | 'CLOUD_FORMATION_CREATE'
82
+ | 'CLOUD_FORMATION_UPDATE'
83
+ | 'CLOUD_FORMATION_DELETE'
84
+ | 'DATA_PLANE_MUTATION'
85
+ | 'UNMAPPED_MUTATION';
86
+ export type AwsCliCommandValidationStatus = 'VALIDATED' | 'SKIPPED';
87
+ export type AwsCliTemplateSource =
88
+ 'TEMPLATE_BODY' | 'CLOUD_CONTROL_DESIRED_STATE' | 'SYNTHESIZED_CREATE' | 'SYNTHESIZED_UPDATE';
89
+ export interface AwsCliCommandOptions {
90
+ servicePrefix?: string;
91
+ httpMethod?: string;
92
+ isReadOnly?: boolean;
93
+ }
94
+ /**
95
+ * Service, operation, and input values for one AWS CLI command.
96
+ *
97
+ * `serviceName` is the canonical botocore service name and is normalized only
98
+ * for ASCII case. Callers adapting an SDK request must translate its native
99
+ * service identity before constructing this request; endpoint and signing-name
100
+ * aliases are never guessed by the validation core.
101
+ */
102
+ export declare class AwsCliCommand {
103
+ readonly serviceName: string;
104
+ readonly operationName: string;
105
+ readonly parameters: Record<string, unknown>;
106
+ readonly servicePrefix?: string;
107
+ readonly httpMethod?: string;
108
+ readonly isReadOnly?: boolean;
109
+ constructor(
110
+ serviceName: string,
111
+ operationName: string,
112
+ parameters: Record<string, unknown>,
113
+ options?: AwsCliCommandOptions,
114
+ );
115
+ }
116
+ export interface AwsCliCommandValidation {
117
+ operationKind: AwsCliOperationKind;
118
+ status: AwsCliCommandValidationStatus;
119
+ templateSource: AwsCliTemplateSource | null;
120
+ resourceTypes: string[];
121
+ reason: string;
122
+ report: ValidationReport | null;
123
+ template: Uint8Array | null;
124
+ }
82
125
  export interface Engine {
83
- validateStandard(template: TemplateFile, config?: ValidateConfig): StandardReport;
84
- validateDetailed(template: TemplateFile, config?: ValidateConfig): DetailedReport;
126
+ validateTemplate(template: TemplateFile, config?: ValidateConfig): ValidationReport;
127
+ validateAwsCliCommand(request: AwsCliCommand): AwsCliCommandValidation;
85
128
  listRules(): RuleInfo[];
86
129
  engineName(): string;
87
130
  free(): void;
@@ -119,6 +162,24 @@ export interface EngineConfig {
119
162
  */
120
163
  schemaValidatorConfig?: SchemaValidatorConfig;
121
164
  }
165
+ /**
166
+ * Configuration for the {@link CompositeEngine}. The built-in rules are always
167
+ * evaluated by the engine's fixed built-in evaluator, so these fields only layer
168
+ * external rules on top - there is no engine-native custom-rule field.
169
+ */
170
+ export interface CompositeEngineConfig {
171
+ /** Custom Rego rules layered on top of the built-in rules. */
172
+ regoRules?: RuleSource[];
173
+ /** Custom CEL rules layered on top of the built-in rules. */
174
+ celRules?: RuleSource[];
175
+ /** CloudFormation Guard DSL rules layered on top of the built-in rules. */
176
+ guardRules?: RuleSource[];
177
+ /**
178
+ * Optional schema validator configuration, observed by both the built-in and
179
+ * external rule evaluation.
180
+ */
181
+ schemaValidatorConfig?: SchemaValidatorConfig;
182
+ }
122
183
  /**
123
184
  * Configuration for the schema validator. Additional schemas are merged on top
124
185
  * of the bundled CloudFormation provider schemas before schema validation.
@@ -150,9 +211,10 @@ export declare class SchemaValidator {
150
211
  constructor(config?: SchemaValidatorConfig);
151
212
  listRules(): RuleInfo[];
152
213
  schemaCount(): number;
153
- validate(template: TemplateFile, region?: string): StandardDiagnostic[];
214
+ validate(template: TemplateFile, region?: string): Diagnostic[];
154
215
  free(): void;
155
216
  }
156
217
  export declare const RegoEngine: new (config?: EngineConfig) => Engine;
157
218
  export declare const CelEngine: new (config?: EngineConfig) => Engine;
219
+ export declare const CompositeEngine: new (config?: CompositeEngineConfig) => Engine;
158
220
  export declare function version(): string;
package/index.js CHANGED
@@ -1,15 +1,203 @@
1
1
  'use strict';
2
2
  Object.defineProperty(exports, '__esModule', { value: true });
3
- exports.CelEngine =
3
+ exports.CompositeEngine =
4
+ exports.CelEngine =
4
5
  exports.RegoEngine =
5
6
  exports.SchemaValidator =
6
7
  exports.TemplateModel =
7
8
  exports.SchemaFile =
8
9
  exports.RuleFile =
9
10
  exports.TemplateFile =
11
+ exports.AwsCliCommand =
10
12
  void 0;
11
13
  exports.version = version;
12
14
  const fs_1 = require('fs');
15
+ /**
16
+ * Service, operation, and input values for one AWS CLI command.
17
+ *
18
+ * `serviceName` is the canonical botocore service name and is normalized only
19
+ * for ASCII case. Callers adapting an SDK request must translate its native
20
+ * service identity before constructing this request; endpoint and signing-name
21
+ * aliases are never guessed by the validation core.
22
+ */
23
+ class AwsCliCommand {
24
+ constructor(serviceName, operationName, parameters, options = {}) {
25
+ this.serviceName = serviceName;
26
+ this.operationName = operationName;
27
+ if (!isPlainRecord(parameters)) {
28
+ throw new TypeError('parameters must be a plain object with string keys');
29
+ }
30
+ const copiedParameters = Object.create(null);
31
+ for (const key of Reflect.ownKeys(parameters)) {
32
+ if (typeof key !== 'string') {
33
+ throw new TypeError('request parameter names must be strings');
34
+ }
35
+ const descriptor = Object.getOwnPropertyDescriptor(parameters, key);
36
+ if (descriptor === undefined || !('value' in descriptor)) {
37
+ throw new TypeError(`request parameter ${JSON.stringify(key)} must be a value property`);
38
+ }
39
+ copiedParameters[key] = descriptor.value;
40
+ }
41
+ this.parameters = copiedParameters;
42
+ this.servicePrefix = options.servicePrefix;
43
+ this.httpMethod = options.httpMethod;
44
+ this.isReadOnly = options.isReadOnly;
45
+ }
46
+ }
47
+ exports.AwsCliCommand = AwsCliCommand;
48
+ const MIN_SIGNED_64 = -(1n << 63n);
49
+ const MAX_SIGNED_64 = (1n << 63n) - 1n;
50
+ const MAX_UNSIGNED_64 = (1n << 64n) - 1n;
51
+ const MAX_REQUEST_VALUE_DEPTH = 64;
52
+ const DATE_GET_TIME = Date.prototype.getTime;
53
+ const DATE_TO_ISO_STRING = Date.prototype.toISOString;
54
+ const UINT8_ARRAY_FOR_EACH = Uint8Array.prototype.forEach;
55
+ function isPlainRecord(value) {
56
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
57
+ return false;
58
+ }
59
+ const prototype = Object.getPrototypeOf(value);
60
+ return prototype === Object.prototype || prototype === null;
61
+ }
62
+ function unsupportedValue(typeName) {
63
+ return { type: 'UNSUPPORTED', type_name: typeName };
64
+ }
65
+ function encodeAwsCliValue(value, depth = 0, ancestors = new Set()) {
66
+ if (depth > MAX_REQUEST_VALUE_DEPTH) {
67
+ return unsupportedValue('recursion depth exceeded');
68
+ }
69
+ if (value === null) {
70
+ return { type: 'NULL' };
71
+ }
72
+ if (typeof value === 'boolean') {
73
+ return { type: 'BOOLEAN', value };
74
+ }
75
+ if (typeof value === 'number') {
76
+ if (!Number.isFinite(value)) {
77
+ return unsupportedValue('non-finite floating-point number');
78
+ }
79
+ if (Number.isInteger(value)) {
80
+ return Number.isSafeInteger(value)
81
+ ? { type: 'INTEGER', value }
82
+ : unsupportedValue('integer outside the JavaScript safe range');
83
+ }
84
+ return { type: 'NUMBER', value };
85
+ }
86
+ if (typeof value === 'bigint') {
87
+ if (value >= MIN_SIGNED_64 && value <= MAX_SIGNED_64) {
88
+ return { type: 'INTEGER', value };
89
+ }
90
+ if (value >= 0n && value <= MAX_UNSIGNED_64) {
91
+ return { type: 'UNSIGNED_INTEGER', value };
92
+ }
93
+ return unsupportedValue('integer outside the 64-bit request range');
94
+ }
95
+ if (typeof value === 'string') {
96
+ return { type: 'STRING', value };
97
+ }
98
+ if (value instanceof Uint8Array) {
99
+ const bytes = [];
100
+ try {
101
+ UINT8_ARRAY_FOR_EACH.call(value, (byte) => {
102
+ bytes.push(byte);
103
+ });
104
+ } catch {
105
+ return unsupportedValue('invalid Uint8Array');
106
+ }
107
+ return { type: 'BYTES', value: bytes };
108
+ }
109
+ if (value instanceof Date) {
110
+ try {
111
+ const timestamp = DATE_GET_TIME.call(value);
112
+ return Number.isFinite(timestamp)
113
+ ? { type: 'STRING', value: DATE_TO_ISO_STRING.call(value) }
114
+ : unsupportedValue('invalid Date');
115
+ } catch {
116
+ return unsupportedValue('invalid Date');
117
+ }
118
+ }
119
+ if (Array.isArray(value)) {
120
+ if (ancestors.has(value)) {
121
+ return unsupportedValue('cyclic array');
122
+ }
123
+ ancestors.add(value);
124
+ try {
125
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, 'length');
126
+ if (
127
+ lengthDescriptor === undefined ||
128
+ !('value' in lengthDescriptor) ||
129
+ !Number.isSafeInteger(lengthDescriptor.value) ||
130
+ lengthDescriptor.value < 0
131
+ ) {
132
+ return unsupportedValue('array with invalid length');
133
+ }
134
+ const items = [];
135
+ for (let index = 0; index < lengthDescriptor.value; index += 1) {
136
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
137
+ if (descriptor === undefined) {
138
+ return unsupportedValue('sparse array');
139
+ }
140
+ if (!('value' in descriptor)) {
141
+ return unsupportedValue('array with accessor elements');
142
+ }
143
+ items.push(encodeAwsCliValue(descriptor.value, depth + 1, ancestors));
144
+ }
145
+ return { type: 'ARRAY', items };
146
+ } finally {
147
+ ancestors.delete(value);
148
+ }
149
+ }
150
+ if (isPlainRecord(value)) {
151
+ if (ancestors.has(value)) {
152
+ return unsupportedValue('cyclic object');
153
+ }
154
+ ancestors.add(value);
155
+ try {
156
+ const entries = Object.create(null);
157
+ for (const key of Reflect.ownKeys(value)) {
158
+ if (typeof key !== 'string') {
159
+ return unsupportedValue('mapping with non-string keys');
160
+ }
161
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
162
+ if (descriptor === undefined || !('value' in descriptor)) {
163
+ return unsupportedValue('mapping with accessor properties');
164
+ }
165
+ entries[key] = encodeAwsCliValue(descriptor.value, depth + 1, ancestors);
166
+ }
167
+ return { type: 'OBJECT', entries };
168
+ } finally {
169
+ ancestors.delete(value);
170
+ }
171
+ }
172
+ return unsupportedValue(typeof value);
173
+ }
174
+ function toWireAwsCliCommand(request) {
175
+ const parameters = Object.create(null);
176
+ for (const [name, value] of Object.entries(request.parameters)) {
177
+ try {
178
+ parameters[name] = encodeAwsCliValue(value);
179
+ } catch {
180
+ parameters[name] = unsupportedValue('request value inspection failed');
181
+ }
182
+ }
183
+ return {
184
+ serviceName: request.serviceName,
185
+ operationName: request.operationName,
186
+ parameters,
187
+ ...(request.servicePrefix === undefined ? {} : { servicePrefix: request.servicePrefix }),
188
+ ...(request.httpMethod === undefined ? {} : { httpMethod: request.httpMethod }),
189
+ ...(request.isReadOnly === undefined ? {} : { isReadOnly: request.isReadOnly }),
190
+ };
191
+ }
192
+ function fromWireAwsCliCommandValidation(validation) {
193
+ const template = validation.template;
194
+ return {
195
+ ...validation,
196
+ templateSource: validation.templateSource ?? null,
197
+ report: validation.report ?? null,
198
+ template: template == null ? null : Uint8Array.from(template),
199
+ };
200
+ }
13
201
  const bridge = require('./bindings_wasm');
14
202
  class TemplateFile {
15
203
  constructor(path) {
@@ -62,6 +250,16 @@ function toWasmEngineConfig(config) {
62
250
  : undefined,
63
251
  };
64
252
  }
253
+ function toWasmCompositeEngineConfig(config) {
254
+ return {
255
+ regoRules: toExternalRuleSources(config?.regoRules),
256
+ celRules: toExternalRuleSources(config?.celRules),
257
+ guardRules: toExternalRuleSources(config?.guardRules),
258
+ schemaValidatorConfig: config?.schemaValidatorConfig
259
+ ? toWasmSchemaValidatorConfig(config.schemaValidatorConfig)
260
+ : undefined,
261
+ };
262
+ }
65
263
  function toWasmSchemaValidatorConfig(config) {
66
264
  return {
67
265
  additionalSchemas: toAdditionalSchemas(config?.additionalSchemas),
@@ -126,16 +324,19 @@ class SchemaValidator {
126
324
  }
127
325
  }
128
326
  exports.SchemaValidator = SchemaValidator;
129
- function createEngineClass(WasmClass) {
327
+ function createEngineClass(WasmClass, toWasmConfig) {
130
328
  return class {
131
329
  constructor(config) {
132
- this.inner = new WasmClass(toWasmEngineConfig(config));
330
+ this.inner = new WasmClass(toWasmConfig(config));
133
331
  }
134
- validateStandard(template, config) {
135
- return this.inner.validateStandard(template.readBytes(), config ?? {}, template.path);
332
+ validateTemplate(template, config) {
333
+ return this.inner.validateTemplate(template.readBytes(), config ?? {}, template.path);
136
334
  }
137
- validateDetailed(template, config) {
138
- return this.inner.validateDetailed(template.readBytes(), config ?? {}, template.path);
335
+ validateAwsCliCommand(request) {
336
+ if (!(request instanceof AwsCliCommand)) {
337
+ throw new TypeError('request must be an AwsCliCommand');
338
+ }
339
+ return fromWireAwsCliCommandValidation(this.inner.validateAwsCliCommand(toWireAwsCliCommand(request)));
139
340
  }
140
341
  listRules() {
141
342
  return this.inner.listRules();
@@ -148,8 +349,9 @@ function createEngineClass(WasmClass) {
148
349
  }
149
350
  };
150
351
  }
151
- exports.RegoEngine = createEngineClass(bridge.WasmRegoEngine);
152
- exports.CelEngine = createEngineClass(bridge.WasmCelEngine);
352
+ exports.RegoEngine = createEngineClass(bridge.WasmRegoEngine, toWasmEngineConfig);
353
+ exports.CelEngine = createEngineClass(bridge.WasmCelEngine, toWasmEngineConfig);
354
+ exports.CompositeEngine = createEngineClass(bridge.WasmCompositeEngine, toWasmCompositeEngineConfig);
153
355
  function version() {
154
356
  return bridge.version();
155
357
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/cloudformation-validate",
3
- "version": "1.8.0-beta",
3
+ "version": "1.10.0",
4
4
  "description": "Fast, offline, embeddable validation for AWS CloudFormation templates",
5
5
  "keywords": [
6
6
  "aws",