codify-plugin-lib 1.0.36 → 1.0.38

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,63 +1,54 @@
1
1
  import { Resource } from './resource.js';
2
- import { ParameterOperation, ResourceConfig, ResourceOperation } from 'codify-schemas';
3
- import { ChangeSet, ParameterChange } from './change-set.js';
2
+ import { ResourceOperation, StringIndexedObject } from 'codify-schemas';
3
+ import { ParameterChange } from './change-set.js';
4
4
  import { spy } from 'sinon';
5
5
  import { Plan } from './plan.js';
6
6
  import { StatefulParameter } from './stateful-parameter.js';
7
7
  import { describe, expect, it } from 'vitest'
8
+ import { ResourceConfiguration } from './resource-types.js';
8
9
 
9
- class TestResource extends Resource<TestConfig> {
10
- applyCreate(plan: Plan<TestConfig>): Promise<void> {
11
- return Promise.resolve(undefined);
12
- }
10
+ interface TestConfig extends StringIndexedObject {
11
+ propA: string;
12
+ propB: number;
13
+ propC?: string;
14
+ }
13
15
 
14
- applyDestroy(plan: Plan<TestConfig>): Promise<void> {
15
- return Promise.resolve(undefined);
16
+ class TestResource extends Resource<TestConfig> {
17
+ constructor(options: ResourceConfiguration<TestConfig>) {
18
+ super(options);
16
19
  }
17
20
 
18
- applyModify(plan: Plan<TestConfig>): Promise<void> {
21
+ applyCreate(plan: Plan<TestConfig>): Promise<void> {
19
22
  return Promise.resolve(undefined);
20
23
  }
21
24
 
22
- applyRecreate(plan: Plan<TestConfig>): Promise<void> {
25
+ applyDestroy(plan: Plan<TestConfig>): Promise<void> {
23
26
  return Promise.resolve(undefined);
24
27
  }
25
28
 
26
- calculateOperation(change: ParameterChange): ResourceOperation.RECREATE | ResourceOperation.MODIFY {
27
- return ResourceOperation.MODIFY;
28
- }
29
-
30
- async getCurrentConfig(): Promise<TestConfig | null> {
31
- return null;
29
+ async refresh(): Promise<Partial<TestConfig> | null> {
30
+ return {
31
+ propA: 'a',
32
+ propB: 10,
33
+ propC: 'c',
34
+ };
32
35
  }
33
36
 
34
- async validate(config: ResourceConfig): Promise<string | undefined> {
37
+ async validate(config: unknown): Promise<string[] | undefined> {
35
38
  return undefined;
36
39
  }
37
-
38
- getTypeId(): string {
39
- return '';
40
- }
41
- }
42
-
43
- interface TestConfig extends ResourceConfig {
44
- propA: string;
45
- propB: number;
46
- propC?: string;
47
40
  }
48
41
 
49
42
  describe('Resource tests', () => {
50
43
  it('plans correctly', async () => {
51
44
  const resource = new class extends TestResource {
52
- calculateOperation(change: ParameterChange): ResourceOperation.RECREATE | ResourceOperation.MODIFY {
53
- return ResourceOperation.MODIFY;
45
+ constructor() {
46
+ super({ type: 'type' });
54
47
  }
55
48
 
56
- async getCurrentConfig(): Promise<TestConfig> {
49
+ async refresh(): Promise<TestConfig> {
57
50
  return {
58
- type: 'type',
59
- name: 'name',
60
- propA: "propABefore",
51
+ propA: 'propABefore',
61
52
  propB: 10,
62
53
  };
63
54
  }
@@ -71,20 +62,20 @@ describe('Resource tests', () => {
71
62
  propB: 10,
72
63
  })
73
64
 
74
- expect(result.resourceConfig).to.deep.eq({
65
+ expect(result.desiredConfig).to.deep.eq({
75
66
  type: 'type',
76
67
  name: 'name',
77
68
  propA: 'propA',
78
69
  propB: 10,
79
70
  });
80
- expect(result.changeSet.operation).to.eq(ResourceOperation.MODIFY);
71
+ expect(result.changeSet.operation).to.eq(ResourceOperation.RECREATE);
81
72
  expect(result.changeSet.parameterChanges[0]).to.deep.eq({
82
73
  name: 'propA',
83
74
  previousValue: 'propABefore',
84
75
  newValue: 'propA',
85
76
  operation: 'modify'
86
77
  })
87
- expect(result.changeSet.parameterChanges[1]).to.deep.eq( {
78
+ expect(result.changeSet.parameterChanges[1]).to.deep.eq({
88
79
  name: 'propB',
89
80
  previousValue: 10,
90
81
  newValue: 10,
@@ -92,42 +83,17 @@ describe('Resource tests', () => {
92
83
  })
93
84
  })
94
85
 
95
- it('calls calculateOperation for only modifications and recreates', async () => {
86
+ it('creates the resource if it doesnt exist', async () => {
96
87
  const resource = new class extends TestResource {
97
- calculateOperation(change: ParameterChange): ResourceOperation.RECREATE | ResourceOperation.MODIFY {
98
- return ResourceOperation.MODIFY;
99
- }
100
-
101
- async getCurrentConfig(): Promise<TestConfig> {
102
- return {
103
- type: 'type',
104
- name: 'name',
105
- propA: "propABefore",
106
- propB: 10,
107
- propC: 'somethingBefore'
108
- };
88
+ constructor() {
89
+ super({ type: 'type' });
109
90
  }
110
- }
111
91
 
112
- const resourceSpy = spy(resource);
113
- await resourceSpy.plan({
114
- type: 'type',
115
- name: 'name',
116
- propA: 'propA',
117
- propB: 10,
118
- propC: 'somethingAfter'
119
- })
120
-
121
- expect(resourceSpy.calculateOperation.calledTwice).to.be.true;
122
- })
123
-
124
- it('creates the resource if it doesnt exist', async () => {
125
- const resource = new class extends TestResource {
126
- calculateOperation(change: ParameterChange): ResourceOperation.RECREATE | ResourceOperation.MODIFY {
92
+ calculateOperation(change: ParameterChange<TestConfig>): ResourceOperation.RECREATE | ResourceOperation.MODIFY {
127
93
  return ResourceOperation.MODIFY;
128
94
  }
129
95
 
130
- async getCurrentConfig(): Promise<TestConfig | null> {
96
+ async refresh(): Promise<TestConfig | null> {
131
97
  return null;
132
98
  }
133
99
  }
@@ -147,16 +113,17 @@ describe('Resource tests', () => {
147
113
 
148
114
  it('chooses the create apply properly', async () => {
149
115
  const resource = new class extends TestResource {
150
- getTypeId(): string {
151
- return 'resource'
116
+ constructor() {
117
+ super({ type: 'resource' });
152
118
  }
153
119
  }
154
120
 
155
121
  const resourceSpy = spy(resource);
156
122
  const result = await resourceSpy.apply(
157
- Plan.create(
158
- new ChangeSet(ResourceOperation.CREATE, []),
159
- { type: 'resource', propA: 'a', propB: 0 }
123
+ Plan.create<TestConfig>(
124
+ { type: 'resource', propA: 'a', propB: 0 },
125
+ { type: 'resource' },
126
+ { statefulMode: false },
160
127
  )
161
128
  )
162
129
 
@@ -165,72 +132,88 @@ describe('Resource tests', () => {
165
132
 
166
133
  it('chooses the destroy apply properly', async () => {
167
134
  const resource = new class extends TestResource {
168
- getTypeId(): string {
169
- return 'resource'
135
+ constructor() {
136
+ super({ type: 'resource' });
170
137
  }
171
138
  }
172
139
 
173
140
  const resourceSpy = spy(resource);
174
141
  const result = await resourceSpy.apply(
175
- Plan.create(
176
- new ChangeSet(ResourceOperation.DESTROY, []),
177
- { type: 'resource', propA: 'a', propB: 0 }
142
+ Plan.create<TestConfig>(
143
+ { type: 'resource' },
144
+ { type: 'resource', propA: 'a', propB: 0 },
145
+ { statefulMode: true },
178
146
  )
179
147
  )
180
148
 
181
149
  expect(resourceSpy.applyDestroy.calledOnce).to.be.true;
182
150
  })
183
151
 
184
- it('calls apply modify', async () => {
152
+ it('Defaults parameter changes to recreate', async () => {
185
153
  const resource = new class extends TestResource {
186
- getTypeId(): string {
187
- return 'resource'
154
+ constructor() {
155
+ super({ type: 'resource' });
188
156
  }
189
157
  }
190
158
 
191
159
  const resourceSpy = spy(resource);
192
160
  const result = await resourceSpy.apply(
193
- Plan.create(
194
- new ChangeSet(ResourceOperation.MODIFY, [
195
- {
196
- name: 'propA',
197
- newValue: 'a',
198
- previousValue: 'b',
199
- operation: ParameterOperation.ADD,
200
- },
201
- {
202
- name: 'propB',
203
- newValue: 0,
204
- previousValue: -1,
205
- operation: ParameterOperation.ADD,
206
- },
207
- ]),
208
- { type: 'resource', propA: 'a', propB: 0 }
161
+ Plan.create<TestConfig>(
162
+ { type: 'resource', propA: 'a', propB: 0 },
163
+ { type: 'resource', propA: 'b', propB: -1 },
164
+ { statefulMode: true },
209
165
  )
210
166
  );
211
167
 
212
- expect(resourceSpy.applyModify.calledOnce).to.be.true;
168
+ expect(resourceSpy.applyDestroy.calledOnce).to.be.true;
169
+ expect(resourceSpy.applyCreate.calledOnce).to.be.true;
213
170
  })
214
171
 
215
- it('supports the creation of stateful parameters', async () => {
216
- const statefulParameter = new class implements StatefulParameter<TestConfig, 'propA'> {
217
- get name(): "propA" {
218
- return 'propA';
172
+ it('Allows modification of parameter behavior to allow modify for parameters', async () => {
173
+ const resource = new class extends TestResource {
174
+ constructor() {
175
+ super({
176
+ type: 'resource',
177
+ parameterConfigurations: {
178
+ propA: { planOperation: ResourceOperation.MODIFY },
179
+ propB: { planOperation: ResourceOperation.MODIFY },
180
+ }
181
+ });
219
182
  }
220
183
 
221
- applyAdd(parameterChange: ParameterChange, plan: Plan<TestConfig>): Promise<void> {
222
- return Promise.resolve(undefined);
184
+ async refresh(): Promise<TestConfig | null> {
185
+ return { propA: 'b', propB: -1 };
223
186
  }
187
+ }
224
188
 
225
- applyModify(parameterChange: ParameterChange, plan: Plan<TestConfig>): Promise<void> {
226
- return Promise.resolve(undefined);
227
- }
189
+ const plan = await resource.plan({ type: 'resource', propA: 'a', propB: 0 })
228
190
 
229
- applyRemove(parameterChange: ParameterChange, plan: Plan<TestConfig>): Promise<void> {
230
- return Promise.resolve(undefined);
191
+ const resourceSpy = spy(resource);
192
+ const result = await resourceSpy.apply(
193
+ plan
194
+ );
195
+
196
+ expect(resourceSpy.applyModify.calledTwice).to.be.true;
197
+ })
198
+
199
+ it('supports the creation of stateful parameters', async () => {
200
+ const statefulParameter = new class extends StatefulParameter<TestConfig, string> {
201
+ constructor() {
202
+ super({
203
+ name: 'propA',
204
+ })
231
205
  }
232
206
 
233
- async getCurrent(): Promise<TestConfig["propA"]> {
207
+ applyAdd(valueToAdd: string, plan: Plan<TestConfig>): Promise<void> {
208
+ return Promise.resolve();
209
+ }
210
+ applyModify(newValue: string, previousValue: string, allowDeletes: boolean, plan: Plan<TestConfig>): Promise<void> {
211
+ return Promise.resolve();
212
+ }
213
+ applyRemove(valueToRemove: string, plan: Plan<TestConfig>): Promise<void> {
214
+ return Promise.resolve();
215
+ }
216
+ async refresh(): Promise<string | null> {
234
217
  return '';
235
218
  }
236
219
  }
@@ -240,39 +223,19 @@ describe('Resource tests', () => {
240
223
  const resource = new class extends TestResource {
241
224
 
242
225
  constructor() {
243
- super();
244
- this.registerStatefulParameter(statefulParameterSpy)
245
- }
246
-
247
- getTypeId(): string {
248
- return 'resource'
226
+ super({
227
+ type: 'resource',
228
+ statefulParameters: [statefulParameterSpy],
229
+ });
249
230
  }
250
231
  }
251
232
 
252
233
  const resourceSpy = spy(resource);
253
234
  const result = await resourceSpy.apply(
254
- Plan.create(
255
- new ChangeSet(ResourceOperation.CREATE, [
256
- {
257
- name: 'propA',
258
- newValue: 'a',
259
- previousValue: null,
260
- operation: ParameterOperation.ADD,
261
- },
262
- {
263
- name: 'propB',
264
- newValue: 0,
265
- previousValue: null,
266
- operation: ParameterOperation.ADD,
267
- },
268
- {
269
- name: 'propC',
270
- newValue: 'b',
271
- previousValue: null,
272
- operation: ParameterOperation.ADD,
273
- },
274
- ]),
275
- { type: 'resource', propA: 'a', propB: 0, propC: 'b' }
235
+ Plan.create<TestConfig>(
236
+ { type: 'resource', propA: 'a', propB: 0, propC: 'b' },
237
+ null,
238
+ { statefulMode: false },
276
239
  )
277
240
  );
278
241
 
@@ -281,25 +244,24 @@ describe('Resource tests', () => {
281
244
  })
282
245
 
283
246
  it('supports the modification of stateful parameters', async () => {
284
- const statefulParameter = new class implements StatefulParameter<TestConfig, 'propA'> {
285
- get name(): "propA" {
286
- return 'propA';
247
+ const statefulParameter = new class extends StatefulParameter<TestConfig, string> {
248
+ constructor() {
249
+ super({
250
+ name: 'propA',
251
+ })
287
252
  }
288
253
 
289
- applyAdd(parameterChange: ParameterChange, plan: Plan<TestConfig>): Promise<void> {
290
- return Promise.resolve(undefined);
254
+ applyAdd(valueToAdd: string, plan: Plan<TestConfig>): Promise<void> {
255
+ return Promise.resolve();
291
256
  }
292
-
293
- applyModify(parameterChange: ParameterChange, plan: Plan<TestConfig>): Promise<void> {
294
- return Promise.resolve(undefined);
257
+ applyModify(newValue: string, previousValue: string, allowDeletes: false, plan: Plan<TestConfig>): Promise<void> {
258
+ return Promise.resolve();
295
259
  }
296
-
297
- applyRemove(parameterChange: ParameterChange, plan: Plan<TestConfig>): Promise<void> {
298
- return Promise.resolve(undefined);
260
+ applyRemove(valueToRemove: string, plan: Plan<TestConfig>): Promise<void> {
261
+ return Promise.resolve();
299
262
  }
300
-
301
- async getCurrent(): Promise<TestConfig["propA"]> {
302
- return '';
263
+ async refresh(): Promise<string | null> {
264
+ return 'b';
303
265
  }
304
266
  }
305
267
 
@@ -308,41 +270,24 @@ describe('Resource tests', () => {
308
270
  const resource = new class extends TestResource {
309
271
 
310
272
  constructor() {
311
- super();
312
- this.registerStatefulParameter(statefulParameterSpy)
273
+ super({
274
+ type: 'resource',
275
+ statefulParameters: [statefulParameterSpy],
276
+ parameterConfigurations: {
277
+ propB: { planOperation: ResourceOperation.MODIFY },
278
+ }
279
+ });
313
280
  }
314
281
 
315
- getTypeId(): string {
316
- return 'resource'
282
+ async refresh(): Promise<Partial<TestConfig> | null> {
283
+ return { propB: -1, propC: 'b' }
317
284
  }
318
285
  }
319
286
 
287
+ const plan = await resource.plan({ type: 'resource', propA: 'a', propB: 0, propC: 'b' })
288
+
320
289
  const resourceSpy = spy(resource);
321
- const result = await resourceSpy.apply(
322
- Plan.create(
323
- new ChangeSet(ResourceOperation.MODIFY, [
324
- {
325
- name: 'propA',
326
- newValue: 'a',
327
- previousValue: 'b',
328
- operation: ParameterOperation.MODIFY,
329
- },
330
- {
331
- name: 'propB',
332
- newValue: 0,
333
- previousValue: null,
334
- operation: ParameterOperation.ADD,
335
- },
336
- {
337
- name: 'propC',
338
- newValue: 'b',
339
- previousValue: 'b',
340
- operation: ParameterOperation.NOOP,
341
- },
342
- ]),
343
- { type: 'resource', propA: 'a', propB: 0, propC: 'b' }
344
- )
345
- );
290
+ const result = await resourceSpy.apply(plan);
346
291
 
347
292
  expect(statefulParameterSpy.applyModify.calledOnce).to.be.true;
348
293
  expect(resourceSpy.applyModify.calledOnce).to.be.true;