codify-plugin-lib 1.0.59 → 1.0.61
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/dist/entities/resource.js +2 -2
- package/dist/entities/stateful-parameter.d.ts +7 -8
- package/dist/entities/stateful-parameter.js +0 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/src/entities/resource-parameters.test.ts +129 -6
- package/src/entities/resource.ts +10 -2
- package/src/entities/stateful-parameter.ts +8 -10
- package/src/index.ts +1 -0
|
@@ -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(resourceParameters, 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<
|
|
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<
|
|
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
|
|
14
|
-
|
|
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<
|
|
23
|
-
constructor(options: ArrayStatefulParameterOptions<
|
|
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>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Plugin } from './entities/plugin.js';
|
|
2
2
|
export * from './entities/resource.js';
|
|
3
3
|
export * from './entities/resource-types.js';
|
|
4
|
+
export * from './entities/resource-options.js';
|
|
4
5
|
export * from './entities/plugin.js';
|
|
5
6
|
export * from './entities/change-set.js';
|
|
6
7
|
export * from './entities/plan.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MessageHandler } from './messages/handlers.js';
|
|
2
2
|
export * from './entities/resource.js';
|
|
3
3
|
export * from './entities/resource-types.js';
|
|
4
|
+
export * from './entities/resource-options.js';
|
|
4
5
|
export * from './entities/plugin.js';
|
|
5
6
|
export * from './entities/change-set.js';
|
|
6
7
|
export * from './entities/plan.js';
|
package/package.json
CHANGED
|
@@ -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<
|
|
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> {
|
|
@@ -28,6 +26,48 @@ class TestParameter extends StatefulParameter<TestConfig, string> {
|
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
describe('Resource parameter tests', () => {
|
|
29
|
+
it ('Generates a resource plan that includes stateful parameters (create)', async () => {
|
|
30
|
+
const statefulParameter = spy(new class extends TestParameter {
|
|
31
|
+
async refresh(): Promise<string | null> {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const resource = new class extends TestResource {
|
|
37
|
+
constructor() {
|
|
38
|
+
super({
|
|
39
|
+
type: 'resource',
|
|
40
|
+
parameterOptions: {
|
|
41
|
+
propA: { statefulParameter }
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async refresh(): Promise<any> {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const plan = await resource.plan({
|
|
52
|
+
type: 'resource',
|
|
53
|
+
propA: 'a',
|
|
54
|
+
propB: 10
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
expect(statefulParameter.refresh.notCalled).to.be.true;
|
|
58
|
+
expect(plan.currentConfig).toMatchObject({
|
|
59
|
+
type: 'resource',
|
|
60
|
+
propA: null,
|
|
61
|
+
propB: null,
|
|
62
|
+
})
|
|
63
|
+
expect(plan.desiredConfig).toMatchObject({
|
|
64
|
+
type: 'resource',
|
|
65
|
+
propA: 'a',
|
|
66
|
+
propB: 10
|
|
67
|
+
})
|
|
68
|
+
expect(plan.changeSet.operation).to.eq(ResourceOperation.CREATE);
|
|
69
|
+
})
|
|
70
|
+
|
|
31
71
|
it('supports the creation of stateful parameters', async () => {
|
|
32
72
|
|
|
33
73
|
const statefulParameter = new class extends TestParameter {
|
|
@@ -39,7 +79,6 @@ describe('Resource parameter tests', () => {
|
|
|
39
79
|
const statefulParameterSpy = spy(statefulParameter);
|
|
40
80
|
|
|
41
81
|
const resource = new class extends TestResource {
|
|
42
|
-
|
|
43
82
|
constructor() {
|
|
44
83
|
super({
|
|
45
84
|
type: 'resource',
|
|
@@ -99,6 +138,51 @@ describe('Resource parameter tests', () => {
|
|
|
99
138
|
expect(resourceSpy.applyModify.calledOnce).to.be.true;
|
|
100
139
|
})
|
|
101
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
|
+
|
|
102
186
|
it('Filters array results in stateless mode to prevent modify from being called', async () => {
|
|
103
187
|
const statefulParameter = new class extends TestParameter {
|
|
104
188
|
async refresh(): Promise<any | null> {
|
|
@@ -169,7 +253,6 @@ describe('Resource parameter tests', () => {
|
|
|
169
253
|
const statefulParameter = new class extends ArrayStatefulParameter<TestConfig, string> {
|
|
170
254
|
constructor() {
|
|
171
255
|
super({
|
|
172
|
-
name: 'propA',
|
|
173
256
|
isElementEqual: (desired, current) => current.includes(desired),
|
|
174
257
|
});
|
|
175
258
|
}
|
|
@@ -490,4 +573,44 @@ describe('Resource parameter tests', () => {
|
|
|
490
573
|
expect(plan.desiredConfig.propE).to.be.lessThan(plan.desiredConfig.propF as any);
|
|
491
574
|
expect(plan.desiredConfig.propF).to.be.lessThan(plan.desiredConfig.propD as any);
|
|
492
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
|
+
})
|
|
493
616
|
})
|
package/src/entities/resource.ts
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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<
|
|
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<
|
|
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
|
|
28
|
-
readonly options: StatefulParameterOptions<T>;
|
|
27
|
+
readonly options: StatefulParameterOptions<V>;
|
|
29
28
|
|
|
30
|
-
protected constructor(options: StatefulParameterOptions<
|
|
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<
|
|
42
|
+
options: ArrayStatefulParameterOptions<V>;
|
|
45
43
|
|
|
46
|
-
constructor(options: ArrayStatefulParameterOptions<
|
|
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<
|
|
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) {
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { MessageHandler } from './messages/handlers.js';
|
|
|
3
3
|
|
|
4
4
|
export * from './entities/resource.js'
|
|
5
5
|
export * from './entities/resource-types.js'
|
|
6
|
+
export * from './entities/resource-options.js'
|
|
6
7
|
export * from './entities/plugin.js'
|
|
7
8
|
export * from './entities/change-set.js'
|
|
8
9
|
export * from './entities/plan.js'
|