codify-plugin-lib 1.0.60 → 1.0.62

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.
@@ -54,13 +54,13 @@ export class Resource {
54
54
  statefulMode: false,
55
55
  parameterOptions: this.parameterOptions,
56
56
  };
57
+ this.addDefaultValues(desiredConfig);
57
58
  const parsedConfig = new ConfigParser(desiredConfig, this.statefulParameters, this.transformParameters);
58
59
  const { parameters: desiredParameters, resourceMetadata, resourceParameters, statefulParameters, transformParameters, } = parsedConfig;
59
- this.addDefaultValues(resourceParameters);
60
60
  await this.applyTransformParameters(transformParameters, resourceParameters);
61
61
  const currentParameters = await this.refreshResourceParameters(resourceParameters);
62
62
  if (currentParameters == null) {
63
- return Plan.create(desiredParameters, null, resourceMetadata, planOptions);
63
+ return Plan.create({ ...resourceParameters, ...statefulParameters }, null, resourceMetadata, planOptions);
64
64
  }
65
65
  const statefulCurrentParameters = await this.refreshStatefulParameters(statefulParameters, planOptions.statefulMode);
66
66
  return Plan.create({ ...resourceParameters, ...statefulParameters }, { ...currentParameters, ...statefulCurrentParameters }, resourceMetadata, planOptions);
@@ -1,26 +1,25 @@
1
1
  import { Plan } from './plan.js';
2
2
  import { StringIndexedObject } from 'codify-schemas';
3
- export interface StatefulParameterOptions<T> {
4
- name: keyof T;
3
+ export interface StatefulParameterOptions<V> {
5
4
  isEqual?: (desired: any, current: any) => boolean;
6
5
  disableStatelessModeArrayFiltering?: boolean;
6
+ default?: V;
7
7
  }
8
- export interface ArrayStatefulParameterOptions<T> extends StatefulParameterOptions<T> {
8
+ export interface ArrayStatefulParameterOptions<V> extends StatefulParameterOptions<V> {
9
9
  isEqual?: (desired: any[], current: any[]) => boolean;
10
10
  isElementEqual?: (desired: any, current: any) => boolean;
11
11
  }
12
12
  export declare abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
13
- readonly name: keyof T;
14
- readonly options: StatefulParameterOptions<T>;
15
- protected constructor(options: StatefulParameterOptions<T>);
13
+ readonly options: StatefulParameterOptions<V>;
14
+ protected constructor(options?: StatefulParameterOptions<V>);
16
15
  abstract refresh(desired: V | null): Promise<V | null>;
17
16
  abstract applyAdd(valueToAdd: V, plan: Plan<T>): Promise<void>;
18
17
  abstract applyModify(newValue: V, previousValue: V, allowDeletes: boolean, plan: Plan<T>): Promise<void>;
19
18
  abstract applyRemove(valueToRemove: V, plan: Plan<T>): Promise<void>;
20
19
  }
21
20
  export declare abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any> {
22
- options: ArrayStatefulParameterOptions<T>;
23
- constructor(options: ArrayStatefulParameterOptions<T>);
21
+ options: ArrayStatefulParameterOptions<V>;
22
+ constructor(options: ArrayStatefulParameterOptions<V>);
24
23
  applyAdd(valuesToAdd: V[], plan: Plan<T>): Promise<void>;
25
24
  applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void>;
26
25
  applyRemove(valuesToRemove: V[], plan: Plan<T>): Promise<void>;
@@ -1,8 +1,6 @@
1
1
  export class StatefulParameter {
2
- name;
3
2
  options;
4
- constructor(options) {
5
- this.name = options.name;
3
+ constructor(options = {}) {
6
4
  this.options = options;
7
5
  }
8
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-lib",
3
- "version": "1.0.60",
3
+ "version": "1.0.62",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -7,10 +7,8 @@ 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(options?: StatefulParameterOptions<TestConfig>) {
11
- super(options ?? {
12
- name: 'propA'
13
- })
10
+ constructor(options?: StatefulParameterOptions<string>) {
11
+ super(options ?? {})
14
12
  }
15
13
 
16
14
  applyAdd(valueToAdd: string, plan: Plan<TestConfig>): Promise<void> {
@@ -140,6 +138,51 @@ describe('Resource parameter tests', () => {
140
138
  expect(resourceSpy.applyModify.calledOnce).to.be.true;
141
139
  })
142
140
 
141
+ it('Allows stateful parameters to have default values', async () => {
142
+ const statefulParameter = spy(new class extends TestParameter {
143
+ constructor() {
144
+ super({
145
+ default: 'abc'
146
+ });
147
+ }
148
+
149
+ async refresh(): Promise<string | null> {
150
+ return null;
151
+ }
152
+ });
153
+
154
+ const resource = new class extends TestResource {
155
+ constructor() {
156
+ super({
157
+ type: 'resource',
158
+ parameterOptions: {
159
+ propA: { statefulParameter }
160
+ },
161
+ });
162
+ }
163
+
164
+ async refresh(): Promise<any> {
165
+ return null;
166
+ }
167
+ }
168
+
169
+ const plan = await resource.plan({
170
+ type: 'resource',
171
+ })
172
+
173
+ expect(statefulParameter.refresh.notCalled).to.be.true;
174
+ expect(plan.currentConfig).toMatchObject({
175
+ type: 'resource',
176
+ propA: null,
177
+ })
178
+ expect(plan.desiredConfig).toMatchObject({
179
+ type: 'resource',
180
+ propA: 'abc',
181
+ })
182
+ expect(plan.changeSet.operation).to.eq(ResourceOperation.CREATE);
183
+ })
184
+
185
+
143
186
  it('Filters array results in stateless mode to prevent modify from being called', async () => {
144
187
  const statefulParameter = new class extends TestParameter {
145
188
  async refresh(): Promise<any | null> {
@@ -210,7 +253,6 @@ describe('Resource parameter tests', () => {
210
253
  const statefulParameter = new class extends ArrayStatefulParameter<TestConfig, string> {
211
254
  constructor() {
212
255
  super({
213
- name: 'propA',
214
256
  isElementEqual: (desired, current) => current.includes(desired),
215
257
  });
216
258
  }
@@ -531,4 +573,44 @@ describe('Resource parameter tests', () => {
531
573
  expect(plan.desiredConfig.propE).to.be.lessThan(plan.desiredConfig.propF as any);
532
574
  expect(plan.desiredConfig.propF).to.be.lessThan(plan.desiredConfig.propD as any);
533
575
  })
576
+
577
+ it('Plans transform even for creating new resources', async () => {
578
+ const transformParameterA = spy(new class extends TransformParameter<TestConfig> {
579
+ async transform(value: any): Promise<Partial<TestConfig>> {
580
+ return { propD: 'abc', propE: 10 }
581
+ }
582
+ });
583
+
584
+ const resource = spy(new class extends TestResource {
585
+ constructor() {
586
+ super({
587
+ type: 'resourceType',
588
+ parameterOptions: {
589
+ propA: { transformParameter: transformParameterA },
590
+ },
591
+ });
592
+ }
593
+
594
+ async refresh(): Promise<Partial<TestConfig> | null> {
595
+ return null;
596
+ }
597
+ });
598
+
599
+ const plan = await resource.plan({
600
+ type: 'resourceType',
601
+ propA: 'propA',
602
+ propB: 10,
603
+ propC: 'propC',
604
+ });
605
+ expect(plan.currentConfig).toMatchObject({
606
+ type: 'resourceType',
607
+ propD: null,
608
+ propE: null,
609
+ })
610
+ expect(plan.desiredConfig).toMatchObject({
611
+ type: 'resourceType',
612
+ propD: 'abc',
613
+ propE: 10,
614
+ })
615
+ })
534
616
  })
@@ -83,6 +83,8 @@ export abstract class Resource<T extends StringIndexedObject> {
83
83
  parameterOptions: this.parameterOptions,
84
84
  }
85
85
 
86
+ this.addDefaultValues(desiredConfig);
87
+
86
88
  // Parse data from the user supplied config
87
89
  const parsedConfig = new ConfigParser(desiredConfig, this.statefulParameters, this.transformParameters)
88
90
  const {
@@ -93,7 +95,8 @@ export abstract class Resource<T extends StringIndexedObject> {
93
95
  transformParameters,
94
96
  } = parsedConfig;
95
97
 
96
- this.addDefaultValues(resourceParameters);
98
+ // Apply transform parameters. Transform parameters turn into other parameters.
99
+ // Ex: csvFile: './location' => { password: 'pass', 'username': 'user' }
97
100
  await this.applyTransformParameters(transformParameters, resourceParameters);
98
101
 
99
102
  // Refresh resource parameters. This refreshes the parameters that configure the resource itself
@@ -101,7 +104,12 @@ export abstract class Resource<T extends StringIndexedObject> {
101
104
 
102
105
  // Short circuit here. If the resource is non-existent, there's no point checking stateful parameters
103
106
  if (currentParameters == null) {
104
- return Plan.create(desiredParameters, null, resourceMetadata, planOptions);
107
+ return Plan.create(
108
+ { ...resourceParameters, ...statefulParameters },
109
+ null,
110
+ resourceMetadata,
111
+ planOptions,
112
+ );
105
113
  }
106
114
 
107
115
  // Refresh stateful parameters. These parameters have state external to the resource
@@ -1,8 +1,7 @@
1
1
  import { Plan } from './plan.js';
2
2
  import { StringIndexedObject } from 'codify-schemas';
3
3
 
4
- export interface StatefulParameterOptions<T> {
5
- name: keyof T;
4
+ export interface StatefulParameterOptions<V> {
6
5
  isEqual?: (desired: any, current: any) => boolean;
7
6
 
8
7
  /**
@@ -15,20 +14,19 @@ export interface StatefulParameterOptions<T> {
15
14
  * Set this flag to true to disable this behaviour
16
15
  */
17
16
  disableStatelessModeArrayFiltering?: boolean;
17
+ default?: V;
18
18
  }
19
19
 
20
- export interface ArrayStatefulParameterOptions<T> extends StatefulParameterOptions<T> {
20
+ export interface ArrayStatefulParameterOptions<V> extends StatefulParameterOptions<V> {
21
21
  isEqual?: (desired: any[], current: any[]) => boolean;
22
22
  isElementEqual?: (desired: any, current: any) => boolean;
23
23
  }
24
24
 
25
25
 
26
26
  export abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
27
- readonly name: keyof T;
28
- readonly options: StatefulParameterOptions<T>;
27
+ readonly options: StatefulParameterOptions<V>;
29
28
 
30
- protected constructor(options: StatefulParameterOptions<T>) {
31
- this.name = options.name;
29
+ protected constructor(options: StatefulParameterOptions<V> = {}) {
32
30
  this.options = options
33
31
  }
34
32
 
@@ -41,9 +39,9 @@ export abstract class StatefulParameter<T extends StringIndexedObject, V extends
41
39
  }
42
40
 
43
41
  export abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any>{
44
- options: ArrayStatefulParameterOptions<T>;
42
+ options: ArrayStatefulParameterOptions<V>;
45
43
 
46
- constructor(options: ArrayStatefulParameterOptions<T>) {
44
+ constructor(options: ArrayStatefulParameterOptions<V>) {
47
45
  super(options);
48
46
  this.options = options;
49
47
  }
@@ -55,7 +53,7 @@ export abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> e
55
53
  }
56
54
 
57
55
  async applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void> {
58
- const options = this.options as ArrayStatefulParameterOptions<T>;
56
+ const options = this.options as ArrayStatefulParameterOptions<V>;
59
57
 
60
58
  const valuesToAdd = newValues.filter((n) => !previousValues.some((p) => {
61
59
  if (options.isElementEqual) {