codify-plugin-lib 1.0.81 → 1.0.82

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.
@@ -1,5 +1,4 @@
1
1
  import { ParameterOperation, ResourceOperation } from 'codify-schemas';
2
- import { areArraysEqual } from '../utils/utils.js';
3
2
  // Change set will coerce undefined values to null because undefined is not valid JSON
4
3
  export class ChangeSet {
5
4
  operation;
@@ -139,14 +138,6 @@ export class ChangeSet {
139
138
  return orderOfOperations[Math.max(indexPrev, indexNext)];
140
139
  }
141
140
  static isSame(desired, current, setting) {
142
- switch (setting?.type) {
143
- case 'array': {
144
- const arrayParameter = setting;
145
- return areArraysEqual(arrayParameter, desired, current);
146
- }
147
- default: {
148
- return (setting?.isEqual ?? ((a, b) => a === b))(desired, current);
149
- }
150
- }
141
+ return (setting?.isEqual ?? ((a, b) => a === b))(desired, current);
151
142
  }
152
143
  }
package/dist/plan/plan.js CHANGED
@@ -148,13 +148,26 @@ export class Plan {
148
148
  && settings.parameterSettings[k].definition.getSettings().type === 'array'
149
149
  && Array.isArray(v);
150
150
  }
151
+ // For stateless mode, we must filter the current array so that the diff algorithm will not detect any deletes
151
152
  function filterArrayStatefulParameter(k, v) {
152
153
  const desiredArray = desired[k];
153
154
  const matcher = settings.parameterSettings[k]
154
155
  .definition
155
156
  .getSettings()
156
- .isElementEqual;
157
- return v.filter((cv) => desiredArray.find((dv) => (matcher ?? ((a, b) => a === b))(dv, cv)));
157
+ .isElementEqual ?? ((a, b) => a === b);
158
+ const desiredCopy = [...desiredArray];
159
+ const currentCopy = [...v];
160
+ const result = [];
161
+ for (let counter = desiredCopy.length - 1; counter >= 0; counter--) {
162
+ const idx = currentCopy.findIndex((e2) => matcher(desiredCopy[counter], e2));
163
+ if (idx === -1) {
164
+ continue;
165
+ }
166
+ desiredCopy.splice(counter, 1);
167
+ const [element] = currentCopy.splice(idx, 1);
168
+ result.push(element);
169
+ }
170
+ return result;
158
171
  }
159
172
  }
160
173
  // TODO: This needs to be revisited. I don't think this is valid anymore.
@@ -21,6 +21,5 @@ export declare class ParsedResourceSettings<T extends StringIndexedObject> imple
21
21
  get statefulParameterOrder(): Map<keyof T, number>;
22
22
  private validateSettings;
23
23
  private validateParameterEqualsFn;
24
- private resolveEqualsFn;
25
24
  private getFromCacheOrCreate;
26
25
  }
@@ -1,5 +1,4 @@
1
- import { areArraysEqual } from '../utils/utils.js';
2
- import { ParameterEqualsDefaults } from './resource-settings.js';
1
+ import { resolveEqualsFn } from './resource-settings.js';
3
2
  export class ParsedResourceSettings {
4
3
  cache = new Map();
5
4
  id;
@@ -35,7 +34,7 @@ export class ParsedResourceSettings {
35
34
  const settings = Object.entries(this.settings.parameterSettings ?? {})
36
35
  .map(([k, v]) => [k, v])
37
36
  .map(([k, v]) => {
38
- v.isEqual = this.resolveEqualsFn(v, k);
37
+ v.isEqual = resolveEqualsFn(v, k);
39
38
  return [k, v];
40
39
  });
41
40
  return Object.fromEntries(settings);
@@ -106,15 +105,6 @@ export class ParsedResourceSettings {
106
105
  }
107
106
  // The rest of the types have defaults set already
108
107
  }
109
- resolveEqualsFn(parameter, key) {
110
- if (parameter.type === 'array') {
111
- return parameter.isEqual ?? areArraysEqual.bind(areArraysEqual, parameter);
112
- }
113
- if (parameter.type === 'stateful') {
114
- return this.resolveEqualsFn(parameter.definition.getSettings(), key);
115
- }
116
- return parameter.isEqual ?? ParameterEqualsDefaults[parameter.type] ?? (((a, b) => a === b));
117
- }
118
108
  getFromCacheOrCreate(key, create) {
119
109
  if (this.cache.has(key)) {
120
110
  return this.cache.get(key);
@@ -146,4 +146,4 @@ export interface StatefulParameterSetting extends DefaultParameterSetting {
146
146
  */
147
147
  order?: number;
148
148
  }
149
- export declare const ParameterEqualsDefaults: Partial<Record<ParameterSettingType, (a: unknown, b: unknown) => boolean>>;
149
+ export declare function resolveEqualsFn(parameter: ParameterSetting, key: string): (desired: unknown, current: unknown) => boolean;
@@ -1,9 +1,18 @@
1
1
  import path from 'node:path';
2
- import { untildify } from '../utils/utils.js';
3
- export const ParameterEqualsDefaults = {
2
+ import { areArraysEqual, untildify } from '../utils/utils.js';
3
+ const ParameterEqualsDefaults = {
4
4
  'boolean': (a, b) => Boolean(a) === Boolean(b),
5
5
  'directory': (a, b) => path.resolve(untildify(String(a))) === path.resolve(untildify(String(b))),
6
6
  'number': (a, b) => Number(a) === Number(b),
7
7
  'string': (a, b) => String(a) === String(b),
8
8
  'version': (desired, current) => String(current).includes(String(desired))
9
9
  };
10
+ export function resolveEqualsFn(parameter, key) {
11
+ if (parameter.type === 'array') {
12
+ return parameter.isEqual ?? areArraysEqual.bind(areArraysEqual, parameter);
13
+ }
14
+ if (parameter.type === 'stateful') {
15
+ return resolveEqualsFn(parameter.definition.getSettings(), key);
16
+ }
17
+ return parameter.isEqual ?? ParameterEqualsDefaults[parameter.type] ?? (((a, b) => a === b));
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-lib",
3
- "version": "1.0.81",
3
+ "version": "1.0.82",
4
4
  "description": "Library plugin library",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "@oclif/prettier-config": "^0.2.1",
23
23
  "@oclif/test": "^3",
24
24
  "@types/npmcli__promise-spawn": "^6.0.3",
25
- "@types/node": "^18",
25
+ "@types/node": "^20",
26
26
  "@types/semver": "^7.5.4",
27
27
  "@types/sinon": "^17.0.3",
28
28
  "@types/uuid": "^10.0.0",
@@ -1,6 +1,7 @@
1
1
  import { ChangeSet } from './change-set.js';
2
2
  import { ParameterOperation, ResourceOperation } from 'codify-schemas';
3
3
  import { describe, expect, it } from 'vitest';
4
+ import { ParsedResourceSettings } from '../resource/parsed-resource-settings.js';
4
5
 
5
6
  describe('Change set tests', () => {
6
7
  it ('Correctly diffs two resource configs (modify)', () => {
@@ -31,7 +32,7 @@ describe('Change set tests', () => {
31
32
  propA: 'after',
32
33
  }
33
34
 
34
- const cs = ChangeSet.calculateModification(after, before,);
35
+ const cs = ChangeSet.calculateModification(after, before);
35
36
  expect(cs.parameterChanges.length).to.eq(2);
36
37
  expect(cs.parameterChanges[0].operation).to.eq(ParameterOperation.MODIFY);
37
38
  expect(cs.parameterChanges[1].operation).to.eq(ParameterOperation.ADD);
@@ -104,7 +105,14 @@ describe('Change set tests', () => {
104
105
  propA: ['b', 'a', 'c'],
105
106
  }
106
107
 
107
- const cs = ChangeSet.calculateModification(after, before, { propA: { type: 'array' } });
108
+ const parameterSettings = new ParsedResourceSettings({
109
+ id: 'type',
110
+ parameterSettings: {
111
+ propA: { type: 'array' }
112
+ }
113
+ }).parameterSettings
114
+
115
+ const cs = ChangeSet.calculateModification(after, before, parameterSettings);
108
116
  expect(cs.parameterChanges.length).to.eq(1);
109
117
  expect(cs.parameterChanges[0].operation).to.eq(ParameterOperation.NOOP);
110
118
  expect(cs.operation).to.eq(ResourceOperation.NOOP)
@@ -119,7 +127,14 @@ describe('Change set tests', () => {
119
127
  propA: ['b', 'a'],
120
128
  }
121
129
 
122
- const cs = ChangeSet.calculateModification(after, before, { propA: { type: 'array' } });
130
+ const parameterSettings = new ParsedResourceSettings({
131
+ id: 'type',
132
+ parameterSettings: {
133
+ propA: { type: 'array' }
134
+ }
135
+ }).parameterSettings
136
+
137
+ const cs = ChangeSet.calculateModification(after, before, parameterSettings);
123
138
  expect(cs.parameterChanges.length).to.eq(1);
124
139
  expect(cs.parameterChanges[0].operation).to.eq(ParameterOperation.MODIFY);
125
140
  expect(cs.operation).to.eq(ResourceOperation.RECREATE)
@@ -135,7 +150,14 @@ describe('Change set tests', () => {
135
150
  propB: 'before'
136
151
  }
137
152
 
138
- const cs = ChangeSet.calculateModification(after, before, { propA: { canModify: true } });
153
+ const parameterSettings = new ParsedResourceSettings({
154
+ id: 'type',
155
+ parameterSettings: {
156
+ propA: { canModify: true }
157
+ }
158
+ }).parameterSettings
159
+
160
+ const cs = ChangeSet.calculateModification(after, before, parameterSettings);
139
161
  expect(cs.parameterChanges.length).to.eq(2);
140
162
  expect(cs.parameterChanges[0].operation).to.eq(ParameterOperation.MODIFY);
141
163
  expect(cs.parameterChanges[1].operation).to.eq(ParameterOperation.REMOVE);
@@ -152,10 +174,15 @@ describe('Change set tests', () => {
152
174
  propB: 'before'
153
175
  }
154
176
 
155
- const cs = ChangeSet.calculateModification<any>(after, before, {
156
- propA: { canModify: true },
157
- propB: { canModify: true }
158
- });
177
+ const parameterSettings = new ParsedResourceSettings({
178
+ id: 'type',
179
+ parameterSettings: {
180
+ propA: { canModify: true },
181
+ propB: { canModify: true }
182
+ },
183
+ }).parameterSettings
184
+
185
+ const cs = ChangeSet.calculateModification<any>(after, before, parameterSettings);
159
186
  expect(cs.parameterChanges.length).to.eq(2);
160
187
  expect(cs.parameterChanges[0].operation).to.eq(ParameterOperation.MODIFY);
161
188
  expect(cs.parameterChanges[1].operation).to.eq(ParameterOperation.REMOVE);
@@ -167,7 +194,15 @@ describe('Change set tests', () => {
167
194
  const arrA = ['a', 'b', 'd'];
168
195
  const arrB = ['a', 'b', 'd'];
169
196
 
170
- const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, { propA: { type: 'array' } })
197
+ const parameterSettings = new ParsedResourceSettings({
198
+ id: 'type',
199
+ parameterSettings: {
200
+ propA: { type: 'array' }
201
+ },
202
+ }).parameterSettings
203
+
204
+
205
+ const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, parameterSettings)
171
206
 
172
207
  expect(result.operation).to.eq(ResourceOperation.NOOP);
173
208
  })
@@ -176,7 +211,14 @@ describe('Change set tests', () => {
176
211
  const arrA = ['a', 'b'];
177
212
  const arrB = ['a', 'b', 'd'];
178
213
 
179
- const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, { propA: { type: 'array' } })
214
+ const parameterSettings = new ParsedResourceSettings({
215
+ id: 'type',
216
+ parameterSettings: {
217
+ propA: { type: 'array' }
218
+ },
219
+ }).parameterSettings
220
+
221
+ const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, parameterSettings)
180
222
 
181
223
  expect(result.parameterChanges[0].operation).to.eq(ParameterOperation.MODIFY);
182
224
  })
@@ -185,7 +227,14 @@ describe('Change set tests', () => {
185
227
  const arrA = ['b', 'a', 'd'];
186
228
  const arrB = ['a', 'b', 'd'];
187
229
 
188
- const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, { propA: { type: 'array' } })
230
+ const parameterSettings = new ParsedResourceSettings({
231
+ id: 'type',
232
+ parameterSettings: {
233
+ propA: { type: 'array' }
234
+ },
235
+ }).parameterSettings
236
+
237
+ const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, parameterSettings)
189
238
 
190
239
  expect(result.parameterChanges[0].operation).to.eq(ParameterOperation.NOOP);
191
240
  })
@@ -194,12 +243,18 @@ describe('Change set tests', () => {
194
243
  const arrA = [{ key1: 'a' }, { key1: 'a' }, { key1: 'a' }];
195
244
  const arrB = [{ key1: 'a' }, { key1: 'a' }, { key1: 'b' }];
196
245
 
197
- const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, {
198
- propA: {
199
- type: 'array',
200
- isElementEqual: (a, b) => a.key1 === b.key1
201
- }
202
- })
246
+ const parameterSettings = new ParsedResourceSettings({
247
+ id: 'type',
248
+ parameterSettings: {
249
+ propA: {
250
+ type: 'array',
251
+ isElementEqual: (a, b) => a.key1 === b.key1
252
+ }
253
+ },
254
+ }).parameterSettings
255
+
256
+
257
+ const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, parameterSettings)
203
258
 
204
259
  expect(result.parameterChanges[0].operation).to.eq(ParameterOperation.MODIFY);
205
260
  })
@@ -208,12 +263,17 @@ describe('Change set tests', () => {
208
263
  const arrA = [{ key1: 'b' }, { key1: 'a' }, { key1: 'a' }];
209
264
  const arrB = [{ key1: 'a' }, { key1: 'a' }, { key1: 'b' }];
210
265
 
211
- const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, {
212
- propA: {
213
- type: 'array',
214
- isElementEqual: (a, b) => a.key1 === b.key1
215
- }
216
- })
266
+ const parameterSettings = new ParsedResourceSettings({
267
+ id: 'type',
268
+ parameterSettings: {
269
+ propA: {
270
+ type: 'array',
271
+ isElementEqual: (a, b) => a.key1 === b.key1
272
+ }
273
+ },
274
+ }).parameterSettings
275
+
276
+ const result = ChangeSet.calculateModification({ propA: arrA }, { propA: arrB }, parameterSettings)
217
277
 
218
278
  expect(result.parameterChanges[0].operation).to.eq(ParameterOperation.NOOP);
219
279
  })
@@ -1,7 +1,6 @@
1
1
  import { ParameterOperation, ResourceOperation, StringIndexedObject } from 'codify-schemas';
2
2
 
3
- import { ArrayParameterSetting, ParameterSetting, StatefulParameterSetting } from '../resource/resource-settings.js';
4
- import { areArraysEqual } from '../utils/utils.js';
3
+ import { ParameterSetting } from '../resource/resource-settings.js';
5
4
 
6
5
  /**
7
6
  * A parameter change describes a parameter level change to a resource.
@@ -215,15 +214,6 @@ export class ChangeSet<T extends StringIndexedObject> {
215
214
  current: unknown,
216
215
  setting?: ParameterSetting,
217
216
  ): boolean {
218
- switch (setting?.type) {
219
- case 'array': {
220
- const arrayParameter = setting as ArrayParameterSetting;
221
- return areArraysEqual(arrayParameter, desired, current)
222
- }
223
-
224
- default: {
225
- return (setting?.isEqual ?? ((a, b) => a === b))(desired, current)
226
- }
227
- }
217
+ return (setting?.isEqual ?? ((a, b) => a === b))(desired, current)
228
218
  }
229
219
  }
package/src/plan/plan.ts CHANGED
@@ -253,16 +253,31 @@ export class Plan<T extends StringIndexedObject> {
253
253
  && Array.isArray(v)
254
254
  }
255
255
 
256
+ // For stateless mode, we must filter the current array so that the diff algorithm will not detect any deletes
256
257
  function filterArrayStatefulParameter(k: string, v: unknown[]): unknown[] {
257
258
  const desiredArray = desired![k] as unknown[];
258
259
  const matcher = ((settings.parameterSettings![k] as StatefulParameterSetting)
259
260
  .definition
260
261
  .getSettings() as ArrayParameterSetting)
261
- .isElementEqual;
262
+ .isElementEqual ?? ((a, b) => a === b);
262
263
 
263
- return v.filter((cv) =>
264
- desiredArray.find((dv) => (matcher ?? ((a: any, b: any) => a === b))(dv, cv))
265
- )
264
+ const desiredCopy = [...desiredArray];
265
+ const currentCopy = [...v];
266
+ const result = [];
267
+
268
+ for (let counter = desiredCopy.length - 1; counter >= 0; counter--) {
269
+ const idx = currentCopy.findIndex((e2) => matcher(desiredCopy[counter], e2))
270
+
271
+ if (idx === -1) {
272
+ continue;
273
+ }
274
+
275
+ desiredCopy.splice(counter, 1)
276
+ const [element] = currentCopy.splice(idx, 1)
277
+ result.push(element)
278
+ }
279
+
280
+ return result;
266
281
  }
267
282
  }
268
283
 
@@ -1,14 +1,6 @@
1
1
  import { StringIndexedObject } from 'codify-schemas';
2
2
 
3
- import { areArraysEqual } from '../utils/utils.js';
4
- import {
5
- ArrayParameterSetting,
6
- ParameterEqualsDefaults,
7
- ParameterSetting,
8
- ParameterSettingType,
9
- ResourceSettings,
10
- StatefulParameterSetting
11
- } from './resource-settings.js';
3
+ import { ParameterSetting, resolveEqualsFn, ResourceSettings, StatefulParameterSetting } from './resource-settings.js';
12
4
  import { StatefulParameter as StatefulParameterImpl } from './stateful-parameter.js'
13
5
 
14
6
  export class ParsedResourceSettings<T extends StringIndexedObject> implements ResourceSettings<T> {
@@ -54,7 +46,7 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
54
46
  const settings = Object.entries(this.settings.parameterSettings ?? {})
55
47
  .map(([k, v]) => [k, v!] as const)
56
48
  .map(([k, v]) => {
57
- v.isEqual = this.resolveEqualsFn(v, k);
49
+ v.isEqual = resolveEqualsFn(v, k);
58
50
 
59
51
  return [k, v];
60
52
  })
@@ -154,18 +146,6 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
154
146
  // The rest of the types have defaults set already
155
147
  }
156
148
 
157
- private resolveEqualsFn(parameter: ParameterSetting, key: string): (desired: unknown, current: unknown) => boolean {
158
- if (parameter.type === 'array') {
159
- return parameter.isEqual ?? areArraysEqual.bind(areArraysEqual, parameter as ArrayParameterSetting)
160
- }
161
-
162
- if (parameter.type === 'stateful') {
163
- return this.resolveEqualsFn((parameter as StatefulParameterSetting).definition.getSettings(), key)
164
- }
165
-
166
- return parameter.isEqual ?? ParameterEqualsDefaults[parameter.type as ParameterSettingType] ?? (((a, b) => a === b));
167
- }
168
-
169
149
  private getFromCacheOrCreate<T2>(key: string, create: () => T2): T2 {
170
150
  if (this.cache.has(key)) {
171
151
  return this.cache.get(key) as T2
@@ -1,7 +1,7 @@
1
1
  import { StringIndexedObject } from 'codify-schemas';
2
2
  import path from 'node:path';
3
3
 
4
- import { untildify } from '../utils/utils.js';
4
+ import { areArraysEqual, untildify } from '../utils/utils.js';
5
5
  import { StatefulParameter } from './stateful-parameter.js';
6
6
 
7
7
  /**
@@ -183,10 +183,23 @@ export interface StatefulParameterSetting extends DefaultParameterSetting {
183
183
  order?: number,
184
184
  }
185
185
 
186
- export const ParameterEqualsDefaults: Partial<Record<ParameterSettingType, (a: unknown, b: unknown) => boolean>> = {
186
+ const ParameterEqualsDefaults: Partial<Record<ParameterSettingType, (a: unknown, b: unknown) => boolean>> = {
187
187
  'boolean': (a: unknown, b: unknown) => Boolean(a) === Boolean(b),
188
188
  'directory': (a: unknown, b: unknown) => path.resolve(untildify(String(a))) === path.resolve(untildify(String(b))),
189
189
  'number': (a: unknown, b: unknown) => Number(a) === Number(b),
190
190
  'string': (a: unknown, b: unknown) => String(a) === String(b),
191
191
  'version': (desired: unknown, current: unknown) => String(current).includes(String(desired))
192
192
  }
193
+
194
+
195
+ export function resolveEqualsFn(parameter: ParameterSetting, key: string): (desired: unknown, current: unknown) => boolean {
196
+ if (parameter.type === 'array') {
197
+ return parameter.isEqual ?? areArraysEqual.bind(areArraysEqual, parameter as ArrayParameterSetting)
198
+ }
199
+
200
+ if (parameter.type === 'stateful') {
201
+ return resolveEqualsFn((parameter as StatefulParameterSetting).definition.getSettings(), key)
202
+ }
203
+
204
+ return parameter.isEqual ?? ParameterEqualsDefaults[parameter.type as ParameterSettingType] ?? (((a, b) => a === b));
205
+ }
@@ -1,8 +1,15 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import { spy } from 'sinon';
3
3
  import { ParameterOperation, ResourceOperation } from 'codify-schemas';
4
- import { TestArrayStatefulParameter, TestConfig, testPlan, TestStatefulParameter } from '../utils/test-utils.test.js';
5
- import { ArrayParameterSetting, ParameterSetting } from './resource-settings.js';
4
+ import {
5
+ TestArrayStatefulParameter,
6
+ TestConfig,
7
+ testPlan,
8
+ TestResource,
9
+ TestStatefulParameter
10
+ } from '../utils/test-utils.test.js';
11
+ import { ArrayParameterSetting, ParameterSetting, ResourceSettings } from './resource-settings.js';
12
+ import { ResourceController } from './resource-controller.js';
6
13
 
7
14
  describe('Stateful parameter tests', () => {
8
15
  it('addItem is called the correct number of times', async () => {
@@ -49,7 +56,7 @@ describe('Stateful parameter tests', () => {
49
56
  expect(plan.changeSet.operation).to.eq(ResourceOperation.MODIFY);
50
57
  expect(plan.changeSet.parameterChanges[0]).toMatchObject({
51
58
  name: 'propZ',
52
- previousValue: ['a', 'c'], // In stateless mode the previous value gets filtered to prevent deletes
59
+ previousValue: ['c', 'a'], // In stateless mode the previous value gets filtered to prevent deletes
53
60
  newValue: ['a', 'c', 'd', 'e', 'f'],
54
61
  operation: ParameterOperation.MODIFY,
55
62
  })
@@ -108,4 +115,44 @@ describe('Stateful parameter tests', () => {
108
115
 
109
116
  expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
110
117
  })
118
+
119
+ it('isElementEquals test', async () => {
120
+ const testParameter = spy(new class extends TestArrayStatefulParameter {
121
+ getSettings(): ArrayParameterSetting {
122
+ return {
123
+ type: 'array',
124
+ isElementEqual: (desired, current) => current.includes(desired),
125
+ }
126
+ }
127
+
128
+ async refresh(): Promise<any> {
129
+ return [
130
+ '20.15.0',
131
+ '20.15.1'
132
+ ]
133
+ }
134
+ });
135
+
136
+ const resource = new class extends TestResource {
137
+ getSettings(): ResourceSettings<any> {
138
+ return {
139
+ id: 'type',
140
+ parameterSettings: { nodeVersions: { type: 'stateful', definition: testParameter } }
141
+ }
142
+ }
143
+
144
+ async refresh(): Promise<Partial<any> | null> {
145
+ return {};
146
+ }
147
+ }
148
+
149
+ const controller = new ResourceController(resource);
150
+ const plan = await controller.plan({
151
+ nodeVersions: ['20.15'],
152
+ } as any)
153
+
154
+ console.log(JSON.stringify(plan, null, 2))
155
+
156
+ expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
157
+ })
111
158
  })