codify-plugin-lib 1.0.50 → 1.0.51

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,14 +1,14 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { ArrayStatefulParameter, StatefulParameter, StatefulParameterConfiguration } from './stateful-parameter.js';
2
+ import { ArrayStatefulParameter, StatefulParameter, StatefulParameterOptions } from './stateful-parameter.js';
3
3
  import { Plan } from './plan.js';
4
4
  import { spy } from 'sinon';
5
- import { ResourceOperation } from 'codify-schemas';
5
+ import { ParameterOperation, ResourceOperation } from 'codify-schemas';
6
6
  import { TestConfig, TestResource } from './resource.test.js';
7
7
  import { TransformParameter } from './transform-parameter.js';
8
8
 
9
9
  class TestParameter extends StatefulParameter<TestConfig, string> {
10
- constructor(configuration?: StatefulParameterConfiguration<TestConfig>) {
11
- super(configuration ?? {
10
+ constructor(options?: StatefulParameterOptions<TestConfig>) {
11
+ super(options ?? {
12
12
  name: 'propA'
13
13
  })
14
14
  }
@@ -43,7 +43,9 @@ describe('Resource parameters tests', () => {
43
43
  constructor() {
44
44
  super({
45
45
  type: 'resource',
46
- statefulParameters: [statefulParameterSpy],
46
+ parameterOptions: {
47
+ propA: { statefulParameter: statefulParameterSpy }
48
+ },
47
49
  });
48
50
  }
49
51
  }
@@ -76,8 +78,8 @@ describe('Resource parameters tests', () => {
76
78
  constructor() {
77
79
  super({
78
80
  type: 'resource',
79
- statefulParameters: [statefulParameterSpy],
80
- parameterConfigurations: {
81
+ parameterOptions: {
82
+ propA: { statefulParameter: statefulParameterSpy },
81
83
  propB: { planOperation: ResourceOperation.MODIFY },
82
84
  }
83
85
  });
@@ -110,7 +112,9 @@ describe('Resource parameters tests', () => {
110
112
  constructor() {
111
113
  super({
112
114
  type: 'resource',
113
- statefulParameters: [statefulParameterSpy],
115
+ parameterOptions: {
116
+ propA: { statefulParameter: statefulParameterSpy },
117
+ },
114
118
  });
115
119
  }
116
120
 
@@ -141,7 +145,9 @@ describe('Resource parameters tests', () => {
141
145
  constructor() {
142
146
  super({
143
147
  type: 'resource',
144
- statefulParameters: [statefulParameterSpy],
148
+ parameterOptions: {
149
+ propA: { statefulParameter: statefulParameterSpy }
150
+ },
145
151
  });
146
152
  }
147
153
 
@@ -182,7 +188,9 @@ describe('Resource parameters tests', () => {
182
188
  constructor() {
183
189
  super({
184
190
  type: 'resource',
185
- statefulParameters: [statefulParameterSpy],
191
+ parameterOptions: {
192
+ propA: { statefulParameter: statefulParameterSpy }
193
+ },
186
194
  });
187
195
  }
188
196
 
@@ -200,6 +208,163 @@ describe('Resource parameters tests', () => {
200
208
  })
201
209
  })
202
210
 
211
+ it('Plans stateful parameters in the order specified', async () => {
212
+ const statefulParameterA = spy(new class extends TestParameter {
213
+ async refresh(): Promise<any | null> {
214
+ return performance.now()
215
+ }
216
+ });
217
+
218
+ const statefulParameterB = spy(new class extends TestParameter {
219
+ async refresh(): Promise<any | null> {
220
+ return performance.now()
221
+ }
222
+ });
223
+
224
+ const statefulParameterC = spy(new class extends TestParameter {
225
+ async refresh(): Promise<any | null> {
226
+ return performance.now()
227
+ }
228
+ });
229
+
230
+ const statefulParameterD = spy(new class extends TestParameter {
231
+ async refresh(): Promise<any | null> {
232
+ return performance.now()
233
+ }
234
+ });
235
+
236
+ const statefulParameterE = spy(new class extends TestParameter {
237
+ async refresh(): Promise<any | null> {
238
+ return performance.now()
239
+ }
240
+ });
241
+
242
+ const resource = spy(new class extends TestResource {
243
+ constructor() {
244
+ super({
245
+ type: 'resourceType',
246
+ parameterOptions: {
247
+ propA: { statefulParameter: statefulParameterA, order: 3},
248
+ propB: { statefulParameter: statefulParameterB, order: 1 },
249
+ propC: { statefulParameter: statefulParameterC, order: 2 },
250
+ propD: { statefulParameter: statefulParameterD },
251
+ propE: { statefulParameter: statefulParameterE }
252
+ },
253
+ });
254
+ }
255
+
256
+ async refresh(): Promise<Partial<TestConfig> | null> {
257
+ return {};
258
+ }
259
+ });
260
+
261
+ const plan = await resource.plan({
262
+ type: 'resourceType',
263
+ propA: 'propA',
264
+ propB: 10,
265
+ propC: 'propC',
266
+ propD: 'propD',
267
+ propE: 'propE',
268
+ });
269
+
270
+ expect(plan.currentConfig.propB).to.be.lessThan(plan.currentConfig.propC as any);
271
+ expect(plan.currentConfig.propC).to.be.lessThan(plan.currentConfig.propA as any);
272
+ expect(plan.currentConfig.propA).to.be.lessThan(plan.currentConfig.propD as any);
273
+ expect(plan.currentConfig.propD).to.be.lessThan(plan.currentConfig.propE as any);
274
+ })
275
+
276
+ it('Applies stateful parameters in the order specified', async () => {
277
+ let timestampA;
278
+ const statefulParameterA = spy(new class extends TestParameter {
279
+ applyAdd = async (): Promise<void> => { timestampA = performance.now(); }
280
+ applyModify = async (): Promise<void> => { timestampA = performance.now(); }
281
+ applyRemove = async (): Promise<void> => { timestampA = performance.now(); }
282
+ });
283
+
284
+ let timestampB
285
+ const statefulParameterB = spy(new class extends TestParameter {
286
+ applyAdd = async (): Promise<void> => { timestampB = performance.now(); }
287
+ applyModify = async (): Promise<void> => { timestampB = performance.now(); }
288
+ applyRemove = async (): Promise<void> => { timestampB = performance.now(); }
289
+ });
290
+
291
+ let timestampC
292
+ const statefulParameterC = spy(new class extends TestParameter {
293
+ applyAdd = async (): Promise<void> => { timestampC = performance.now(); }
294
+ applyModify = async (): Promise<void> => { timestampC = performance.now(); }
295
+ applyRemove = async (): Promise<void> => { timestampC = performance.now(); }
296
+ });
297
+
298
+ const resource = spy(new class extends TestResource {
299
+ constructor() {
300
+ super({
301
+ type: 'resourceType',
302
+ parameterOptions: {
303
+ propA: { statefulParameter: statefulParameterA, order: 3},
304
+ propB: { statefulParameter: statefulParameterB, order: 1 },
305
+ propC: { statefulParameter: statefulParameterC, order: 2 },
306
+ },
307
+ callStatefulParameterRemoveOnDestroy: true,
308
+ });
309
+ }
310
+ });
311
+
312
+ await resource.apply(
313
+ Plan.fromResponse({
314
+ resourceType: 'resourceType',
315
+ operation: ResourceOperation.CREATE,
316
+ parameters: [
317
+ { name: 'propA', operation: ParameterOperation.ADD, previousValue: null, newValue: null },
318
+ { name: 'propB', operation: ParameterOperation.ADD, previousValue: null, newValue: null },
319
+ { name: 'propC', operation: ParameterOperation.ADD, previousValue: null, newValue: null },
320
+ ]
321
+ }, {}) as any
322
+ );
323
+
324
+ expect(timestampB).to.be.lessThan(timestampC as any);
325
+ expect(timestampC).to.be.lessThan(timestampA as any);
326
+ timestampA = 0;
327
+ timestampB = 0;
328
+ timestampC = 0;
329
+
330
+ await resource.apply(
331
+ Plan.fromResponse({
332
+ resourceType: 'resourceType',
333
+ operation: ResourceOperation.MODIFY,
334
+ parameters: [
335
+ { name: 'propA', operation: ParameterOperation.MODIFY, previousValue: null, newValue: null },
336
+ { name: 'propB', operation: ParameterOperation.MODIFY, previousValue: null, newValue: null },
337
+ { name: 'propC', operation: ParameterOperation.MODIFY, previousValue: null, newValue: null },
338
+ ]
339
+ }, {}) as any
340
+ );
341
+
342
+ expect(timestampB).to.be.lessThan(timestampC as any);
343
+ expect(timestampC).to.be.lessThan(timestampA as any);
344
+ timestampA = 0;
345
+ timestampB = 0;
346
+ timestampC = 0;
347
+
348
+ await resource.apply(
349
+ Plan.fromResponse({
350
+ resourceType: 'resourceType',
351
+ operation: ResourceOperation.DESTROY,
352
+ parameters: [
353
+ { name: 'propA', operation: ParameterOperation.REMOVE, previousValue: null, newValue: null },
354
+ { name: 'propB', operation: ParameterOperation.REMOVE, previousValue: null, newValue: null },
355
+ { name: 'propC', operation: ParameterOperation.REMOVE, previousValue: null, newValue: null },
356
+ ]
357
+ }, {}) as any
358
+ );
359
+
360
+ expect(timestampB).to.be.lessThan(timestampC as any);
361
+ expect(timestampC).to.be.lessThan(timestampA as any);
362
+ timestampA = 0;
363
+ timestampB = 0;
364
+ timestampC = 0;
365
+
366
+ })
367
+
203
368
  it('Supports transform parameters', async () => {
204
369
  const transformParameter = new class extends TransformParameter<TestConfig> {
205
370
  async transform(value: any): Promise<Partial<TestConfig>> {
@@ -214,8 +379,8 @@ describe('Resource parameters tests', () => {
214
379
  constructor() {
215
380
  super({
216
381
  type: 'resourceType',
217
- transformParameters: {
218
- propC: transformParameter
382
+ parameterOptions: {
383
+ propC: { transformParameter }
219
384
  },
220
385
  });
221
386
  }
@@ -241,4 +406,51 @@ describe('Resource parameters tests', () => {
241
406
 
242
407
  expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
243
408
  })
409
+
410
+ it('Plans transform parameters in the order specified', async () => {
411
+ const transformParameterA = spy(new class extends TransformParameter<TestConfig> {
412
+ async transform(value: any): Promise<Partial<TestConfig>> {
413
+ return { propD: performance.now() as any }
414
+ }
415
+ });
416
+
417
+ const transformParameterB = spy(new class extends TransformParameter<TestConfig> {
418
+ async transform(value: any): Promise<Partial<TestConfig>> {
419
+ return { propE: performance.now() }
420
+ }
421
+ });
422
+
423
+ const transformParameterC = spy(new class extends TransformParameter<TestConfig> {
424
+ async transform(value: any): Promise<Partial<TestConfig>> {
425
+ return { propF: performance.now() as any }
426
+ }
427
+ });
428
+
429
+ const resource = spy(new class extends TestResource {
430
+ constructor() {
431
+ super({
432
+ type: 'resourceType',
433
+ parameterOptions: {
434
+ propA: { transformParameter: transformParameterA, order: 3},
435
+ propB: { transformParameter: transformParameterB, order: 1 },
436
+ propC: { transformParameter: transformParameterC, order: 2 },
437
+ },
438
+ });
439
+ }
440
+
441
+ async refresh(): Promise<Partial<TestConfig> | null> {
442
+ return { propD: 'propD', propE: 10, propF: 'propF' };
443
+ }
444
+ });
445
+
446
+ const plan = await resource.plan({
447
+ type: 'resourceType',
448
+ propA: 'propA',
449
+ propB: 10,
450
+ propC: 'propC',
451
+ });
452
+
453
+ expect(plan.desiredConfig.propE).to.be.lessThan(plan.desiredConfig.propF as any);
454
+ expect(plan.desiredConfig.propF).to.be.lessThan(plan.desiredConfig.propD as any);
455
+ })
244
456
  })
@@ -1,13 +1,11 @@
1
- import { StatefulParameter } from './stateful-parameter.js';
2
- import { ResourceOperation, StringIndexedObject } from 'codify-schemas';
3
- import { TransformParameter } from './transform-parameter.js';
1
+ import { ResourceOperation } from 'codify-schemas';
4
2
 
5
3
  export type ErrorMessage = string;
6
4
 
7
5
  /**
8
6
  * Customize properties for specific parameters. This will alter the way the library process changes to the parameter.
9
7
  */
10
- export interface ResourceParameterConfiguration {
8
+ export interface ResourceParameterOptions {
11
9
  /**
12
10
  * Chose if the resource should be re-created or modified if this parameter is changed. Defaults to re-create.
13
11
  */
@@ -27,18 +25,6 @@ export interface ResourceParameterConfiguration {
27
25
  /**
28
26
  * @param
29
27
  */
30
- export interface ResourceConfiguration<T extends StringIndexedObject> {
31
- type: string;
32
- /**
33
- * If true, statefulParameter.applyRemove() will be called before resource destruction.
34
- * Defaults to false.
35
- */
36
- callStatefulParameterRemoveOnDestroy?: boolean,
37
- dependencies?: string[];
38
- statefulParameters?: Array<StatefulParameter<T, T[keyof T]>>;
39
- transformParameters?: Partial<Record<keyof T, TransformParameter<T>>>
40
- parameterConfigurations?: Partial<Record<keyof T, ResourceParameterConfiguration>>
41
- }
42
28
 
43
29
  export interface ResourceDefinition {
44
30
  [x: string]: {
@@ -3,8 +3,9 @@ import { ResourceOperation, StringIndexedObject } from 'codify-schemas';
3
3
  import { spy } from 'sinon';
4
4
  import { Plan } from './plan.js';
5
5
  import { describe, expect, it } from 'vitest'
6
- import { ResourceConfiguration, ValidationResult } from './resource-types.js';
6
+ import { ValidationResult } from './resource-types.js';
7
7
  import { StatefulParameter } from './stateful-parameter.js';
8
+ import { ResourceOptions } from './resource-options.js';
8
9
 
9
10
  export interface TestConfig extends StringIndexedObject {
10
11
  propA: string;
@@ -13,7 +14,7 @@ export interface TestConfig extends StringIndexedObject {
13
14
  }
14
15
 
15
16
  export class TestResource extends Resource<TestConfig> {
16
- constructor(options: ResourceConfiguration<TestConfig>) {
17
+ constructor(options: ResourceOptions<TestConfig>) {
17
18
  super(options);
18
19
  }
19
20
 
@@ -33,7 +34,7 @@ export class TestResource extends Resource<TestConfig> {
33
34
  };
34
35
  }
35
36
 
36
- async validate(config: unknown): Promise<ValidationResult> {
37
+ async validateResource(config: unknown): Promise<ValidationResult> {
37
38
  return {
38
39
  isValid: true
39
40
  }
@@ -193,7 +194,7 @@ describe('Resource tests', () => {
193
194
  constructor() {
194
195
  super({
195
196
  type: 'resource',
196
- parameterConfigurations: {
197
+ parameterOptions: {
197
198
  propA: { planOperation: ResourceOperation.MODIFY },
198
199
  propB: { planOperation: ResourceOperation.MODIFY },
199
200
  }
@@ -215,8 +216,8 @@ describe('Resource tests', () => {
215
216
  expect(resourceSpy.applyModify.calledTwice).to.be.true;
216
217
  })
217
218
 
218
- it('Validates the resource configuration correct (pass)', () => {
219
- const parameter = new class extends StatefulParameter<TestConfig, string> {
219
+ it('Validates the resource options correct (pass)', () => {
220
+ const statefulParameter = new class extends StatefulParameter<TestConfig, string> {
220
221
  constructor() {
221
222
  super({
222
223
  name: 'propC',
@@ -242,11 +243,9 @@ describe('Resource tests', () => {
242
243
  super({
243
244
  type: 'type',
244
245
  dependencies: ['homebrew', 'python'],
245
- statefulParameters: [
246
- parameter
247
- ],
248
- parameterConfigurations: {
246
+ parameterOptions: {
249
247
  propA: { planOperation: ResourceOperation.MODIFY },
248
+ propB: { statefulParameter },
250
249
  propC: { isEqual: (a, b) => true },
251
250
  }
252
251
  });
@@ -254,8 +253,8 @@ describe('Resource tests', () => {
254
253
  }).to.not.throw;
255
254
  })
256
255
 
257
- it('Validates the resource configuration correct (fail)', () => {
258
- const parameter = new class extends StatefulParameter<TestConfig, string> {
256
+ it('Validates the resource options correct (fail)', () => {
257
+ const statefulParameter = new class extends StatefulParameter<TestConfig, string> {
259
258
  constructor() {
260
259
  super({
261
260
  name: 'propC',
@@ -281,11 +280,9 @@ describe('Resource tests', () => {
281
280
  super({
282
281
  type: 'type',
283
282
  dependencies: ['homebrew', 'python'],
284
- statefulParameters: [
285
- parameter
286
- ],
287
- parameterConfigurations: {
283
+ parameterOptions: {
288
284
  propA: { planOperation: ResourceOperation.MODIFY },
285
+ propB: { statefulParameter },
289
286
  propC: { isEqual: (a, b) => true },
290
287
  }
291
288
  });
@@ -298,7 +295,7 @@ describe('Resource tests', () => {
298
295
  constructor() {
299
296
  super({
300
297
  type: 'type',
301
- parameterConfigurations: {
298
+ parameterOptions: {
302
299
  propA: { defaultValue: 'propADefault' }
303
300
  }
304
301
  });
@@ -327,7 +324,7 @@ describe('Resource tests', () => {
327
324
  constructor() {
328
325
  super({
329
326
  type: 'type',
330
- parameterConfigurations: {
327
+ parameterOptions: {
331
328
  propA: { defaultValue: 'propADefault' }
332
329
  }
333
330
  });
@@ -348,6 +345,5 @@ describe('Resource tests', () => {
348
345
  expect(plan.currentConfig.propA).to.eq('propAAfter');
349
346
  expect(plan.desiredConfig.propA).to.eq('propA');
350
347
  expect(plan.changeSet.operation).to.eq(ResourceOperation.RECREATE);
351
-
352
- })
348
+ });
353
349
  });