codify-plugin-lib 1.0.37 → 1.0.39
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/change-set.d.ts +17 -9
- package/dist/entities/change-set.js +91 -36
- package/dist/entities/plan-types.d.ts +11 -0
- package/dist/entities/plan-types.js +1 -0
- package/dist/entities/plan.d.ts +10 -7
- package/dist/entities/plan.js +53 -8
- package/dist/entities/plugin.js +9 -8
- package/dist/entities/resource-types.d.ts +24 -0
- package/dist/entities/resource-types.js +1 -0
- package/dist/entities/resource.d.ts +20 -15
- package/dist/entities/resource.js +137 -62
- package/dist/entities/stateful-parameter.d.ts +22 -8
- package/dist/entities/stateful-parameter.js +33 -0
- package/dist/entities/test.d.ts +1 -0
- package/dist/entities/test.js +22 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/utils/common-types.d.ts +3 -0
- package/dist/utils/common-types.js +1 -0
- package/dist/utils/utils.d.ts +6 -0
- package/dist/utils/utils.js +15 -0
- package/package.json +2 -2
- package/src/entities/change-set.test.ts +24 -36
- package/src/entities/change-set.ts +138 -47
- package/src/entities/plan-types.ts +26 -0
- package/src/entities/plan.ts +87 -16
- package/src/entities/plugin.ts +11 -9
- package/src/entities/resource-parameters.test.ts +159 -0
- package/src/entities/resource-types.ts +47 -0
- package/src/entities/resource.test.ts +77 -215
- package/src/entities/resource.ts +203 -91
- package/src/entities/stateful-parameter.ts +56 -8
- package/src/index.ts +3 -0
- package/src/utils/utils.ts +21 -0
package/src/entities/resource.ts
CHANGED
|
@@ -1,134 +1,246 @@
|
|
|
1
|
-
import { ParameterOperation, ResourceConfig, ResourceOperation } from 'codify-schemas';
|
|
2
|
-
import {
|
|
1
|
+
import { ParameterOperation, ResourceConfig, ResourceOperation, StringIndexedObject, } from 'codify-schemas';
|
|
2
|
+
import { ParameterChange } from './change-set.js';
|
|
3
3
|
import { Plan } from './plan.js';
|
|
4
4
|
import { StatefulParameter } from './stateful-parameter.js';
|
|
5
|
+
import { ResourceConfiguration, ValidationResult } from './resource-types.js';
|
|
6
|
+
import { setsEqual, splitUserConfig } from '../utils/utils.js';
|
|
7
|
+
import { ParameterConfiguration, PlanConfiguration } from './plan-types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Description of resource here
|
|
11
|
+
* Two main functions:
|
|
12
|
+
* - Plan
|
|
13
|
+
* - Apply
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export abstract class Resource<T extends StringIndexedObject> {
|
|
17
|
+
|
|
18
|
+
readonly typeId: string;
|
|
19
|
+
readonly statefulParameters: Map<keyof T, StatefulParameter<T, T[keyof T]>>;
|
|
20
|
+
readonly dependencies: Resource<any>[]; // TODO: Change this to a string
|
|
21
|
+
readonly parameterConfigurations: Record<keyof T, ParameterConfiguration>
|
|
22
|
+
|
|
23
|
+
private readonly options: ResourceConfiguration<T>;
|
|
24
|
+
|
|
25
|
+
protected constructor(configuration: ResourceConfiguration<T>) {
|
|
26
|
+
this.validateResourceConfiguration(configuration);
|
|
27
|
+
|
|
28
|
+
this.typeId = configuration.type;
|
|
29
|
+
this.statefulParameters = new Map(configuration.statefulParameters?.map((sp) => [sp.name, sp]));
|
|
30
|
+
this.parameterConfigurations = this.generateParameterConfigurations(configuration);
|
|
31
|
+
|
|
32
|
+
this.dependencies = configuration.dependencies ?? [];
|
|
33
|
+
this.options = configuration;
|
|
34
|
+
}
|
|
5
35
|
|
|
6
|
-
|
|
36
|
+
getDependencyTypeIds(): string[] {
|
|
37
|
+
return this.dependencies.map((d) => d.typeId)
|
|
38
|
+
}
|
|
7
39
|
|
|
8
|
-
|
|
40
|
+
async onInitialize(): Promise<void> {}
|
|
9
41
|
|
|
10
|
-
|
|
42
|
+
// TODO: Add state in later.
|
|
43
|
+
// Currently only calculating how to add things to reach desired state. Can't delete resources.
|
|
44
|
+
// Add previousConfig as a parameter for plan(desired, previous);
|
|
45
|
+
async plan(desiredConfig: Partial<T> & ResourceConfig): Promise<Plan<T>> {
|
|
46
|
+
|
|
47
|
+
// Explanation: these are settings for how the plan will be generated
|
|
48
|
+
const planConfiguration: PlanConfiguration<T> = {
|
|
49
|
+
statefulMode: false,
|
|
50
|
+
parameterConfigurations: this.parameterConfigurations,
|
|
51
|
+
}
|
|
11
52
|
|
|
12
|
-
|
|
13
|
-
private dependencies: Resource<any>[] = [],
|
|
14
|
-
) {}
|
|
53
|
+
const { resourceMetadata, parameters: desiredParameters } = splitUserConfig(desiredConfig);
|
|
15
54
|
|
|
16
|
-
|
|
55
|
+
const resourceParameters = Object.fromEntries([
|
|
56
|
+
...Object.entries(desiredParameters).filter(([key]) => !this.statefulParameters.has(key)),
|
|
57
|
+
]) as Partial<T>;
|
|
17
58
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
59
|
+
const statefulParameters = [...this.statefulParameters.values()]
|
|
60
|
+
.filter((sp) => desiredParameters[sp.name] !== undefined) // Checking for undefined is fine here because JSONs can only have null.
|
|
21
61
|
|
|
22
|
-
|
|
62
|
+
// Refresh resource parameters
|
|
63
|
+
// This refreshes the parameters that configure the resource itself
|
|
64
|
+
const keysToRefresh = new Set(Object.keys(resourceParameters));
|
|
65
|
+
const currentParameters = await this.refresh(keysToRefresh);
|
|
23
66
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
async plan(desiredConfig: T): Promise<Plan<T>> {
|
|
27
|
-
const currentConfig = await this.getCurrentConfig(desiredConfig);
|
|
28
|
-
if (!currentConfig) {
|
|
29
|
-
return Plan.create(ChangeSet.createForNullCurrentConfig(desiredConfig), desiredConfig);
|
|
67
|
+
if (currentParameters == null && statefulParameters.length === 0) {
|
|
68
|
+
return Plan.create(desiredConfig, null, planConfiguration);
|
|
30
69
|
}
|
|
31
70
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
71
|
+
this.validateRefreshResults(currentParameters, keysToRefresh);
|
|
72
|
+
|
|
73
|
+
// Refresh stateful parameters
|
|
74
|
+
// This refreshes parameters that are stateful (they can be added, deleted separately from the resource)
|
|
75
|
+
const currentStatefulParameters = {} as Partial<T>;
|
|
76
|
+
|
|
77
|
+
for(const statefulParameter of statefulParameters) {
|
|
78
|
+
const desiredValue = desiredParameters[statefulParameter.name];
|
|
79
|
+
|
|
80
|
+
let currentValue = await statefulParameter.refresh(desiredValue ?? null) ?? undefined;
|
|
81
|
+
|
|
82
|
+
// In stateless mode, filter the refreshed parameters by the desired to ensure that no deletes happen
|
|
83
|
+
if (Array.isArray(currentValue) && Array.isArray(desiredValue) && !planConfiguration.statefulMode) {
|
|
84
|
+
currentValue = currentValue.filter((p) => desiredValue?.includes(p)) as any;
|
|
39
85
|
}
|
|
40
|
-
}
|
|
41
86
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Explanation: This calculates the change set of the parameters between the
|
|
46
|
-
// two configs and then passes it to the subclass to calculate the overall
|
|
47
|
-
// operation for the resource
|
|
48
|
-
const parameterChangeSet = ChangeSet.calculateParameterChangeSet(currentConfig, desiredConfig);
|
|
49
|
-
const resourceOperation = parameterChangeSet
|
|
50
|
-
.filter((change) => change.operation !== ParameterOperation.NOOP)
|
|
51
|
-
.reduce((operation: ResourceOperation, curr: ParameterChange) => {
|
|
52
|
-
const newOperation = !this.statefulParameters.has(curr.name)
|
|
53
|
-
? this.calculateOperation(curr)
|
|
54
|
-
: ResourceOperation.MODIFY; // All stateful parameters are modify only
|
|
55
|
-
return ChangeSet.combineResourceOperations(operation, newOperation);
|
|
56
|
-
}, ResourceOperation.NOOP);
|
|
87
|
+
currentStatefulParameters[statefulParameter.name] = currentValue;
|
|
88
|
+
}
|
|
57
89
|
|
|
58
90
|
return Plan.create(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
91
|
+
desiredConfig,
|
|
92
|
+
{ ...currentParameters, ...currentStatefulParameters, ...resourceMetadata } as Partial<T> & ResourceConfig,
|
|
93
|
+
planConfiguration,
|
|
94
|
+
)
|
|
62
95
|
}
|
|
63
96
|
|
|
64
97
|
async apply(plan: Plan<T>): Promise<void> {
|
|
65
|
-
if (plan.getResourceType() !== this.
|
|
66
|
-
throw new Error(`Internal error: Plan set to wrong resource during apply. Expected ${this.
|
|
98
|
+
if (plan.getResourceType() !== this.typeId) {
|
|
99
|
+
throw new Error(`Internal error: Plan set to wrong resource during apply. Expected ${this.typeId} but got: ${plan.getResourceType()}`);
|
|
67
100
|
}
|
|
68
101
|
|
|
69
102
|
switch (plan.changeSet.operation) {
|
|
103
|
+
case ResourceOperation.CREATE: {
|
|
104
|
+
return this._applyCreate(plan); // TODO: Add new parameters value so that apply
|
|
105
|
+
}
|
|
70
106
|
case ResourceOperation.MODIFY: {
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
return this._applyModify(plan);
|
|
108
|
+
}
|
|
109
|
+
case ResourceOperation.RECREATE: {
|
|
110
|
+
await this._applyDestroy(plan);
|
|
111
|
+
return this._applyCreate(plan);
|
|
112
|
+
}
|
|
113
|
+
case ResourceOperation.DESTROY: {
|
|
114
|
+
return this._applyDestroy(plan);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
73
118
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
await this.applyModify(plan);
|
|
77
|
-
}
|
|
119
|
+
private async _applyCreate(plan: Plan<T>): Promise<void> {
|
|
120
|
+
await this.applyCreate(plan);
|
|
78
121
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
122
|
+
const statefulParameterChanges = plan.changeSet.parameterChanges
|
|
123
|
+
.filter((pc: ParameterChange<T>) => this.statefulParameters.has(pc.name))
|
|
124
|
+
for (const parameterChange of statefulParameterChanges) {
|
|
125
|
+
const statefulParameter = this.statefulParameters.get(parameterChange.name)!;
|
|
126
|
+
await statefulParameter.applyAdd(parameterChange.newValue, plan);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private async _applyModify(plan: Plan<T>): Promise<void> {
|
|
131
|
+
const parameterChanges = plan
|
|
132
|
+
.changeSet
|
|
133
|
+
.parameterChanges
|
|
134
|
+
.filter((c: ParameterChange<T>) => c.operation !== ParameterOperation.NOOP);
|
|
135
|
+
|
|
136
|
+
const statelessParameterChanges = parameterChanges
|
|
137
|
+
.filter((pc: ParameterChange<T>) => !this.statefulParameters.has(pc.name))
|
|
138
|
+
for (const pc of statelessParameterChanges) {
|
|
139
|
+
// TODO: When stateful mode is added in the future. Dynamically choose if deletes are allowed
|
|
140
|
+
await this.applyModify(pc.name, pc.newValue, pc.previousValue, false, plan);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const statefulParameterChanges = parameterChanges
|
|
144
|
+
.filter((pc: ParameterChange<T>) => this.statefulParameters.has(pc.name))
|
|
145
|
+
for (const parameterChange of statefulParameterChanges) {
|
|
146
|
+
const statefulParameter = this.statefulParameters.get(parameterChange.name)!;
|
|
147
|
+
|
|
148
|
+
switch (parameterChange.operation) {
|
|
149
|
+
case ParameterOperation.ADD: {
|
|
150
|
+
await statefulParameter.applyAdd(parameterChange.newValue, plan);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case ParameterOperation.MODIFY: {
|
|
154
|
+
// TODO: When stateful mode is added in the future. Dynamically choose if deletes are allowed
|
|
155
|
+
await statefulParameter.applyModify(parameterChange.newValue, parameterChange.previousValue, false, plan);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case ParameterOperation.REMOVE: {
|
|
159
|
+
await statefulParameter.applyRemove(parameterChange.previousValue, plan);
|
|
160
|
+
break;
|
|
96
161
|
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
97
165
|
|
|
98
|
-
|
|
166
|
+
private async _applyDestroy(plan: Plan<T>): Promise<void> {
|
|
167
|
+
// If this option is set (defaults to false), then stateful parameters need to be destroyed
|
|
168
|
+
// as well. This means that the stateful parameter wouldn't have been normally destroyed with applyDestroy()
|
|
169
|
+
if (this.options.callStatefulParameterRemoveOnDestroy) {
|
|
170
|
+
const statefulParameterChanges = plan.changeSet.parameterChanges
|
|
171
|
+
.filter((pc: ParameterChange<T>) => this.statefulParameters.has(pc.name))
|
|
172
|
+
for (const parameterChange of statefulParameterChanges) {
|
|
173
|
+
const statefulParameter = this.statefulParameters.get(parameterChange.name)!;
|
|
174
|
+
await statefulParameter.applyRemove(parameterChange.previousValue, plan);
|
|
99
175
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await this.applyDestroy(plan);
|
|
179
|
+
}
|
|
104
180
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
181
|
+
private generateParameterConfigurations(
|
|
182
|
+
resourceConfiguration: ResourceConfiguration<T>
|
|
183
|
+
): Record<keyof T, ParameterConfiguration> {
|
|
184
|
+
const resourceParameters = Object.fromEntries(
|
|
185
|
+
Object.entries(resourceConfiguration.parameterConfigurations ?? {})
|
|
186
|
+
?.map(([name, value]) => ([name, { ...value, isStatefulParameter: false }]))
|
|
187
|
+
) as Record<keyof T, ParameterConfiguration>
|
|
188
|
+
|
|
189
|
+
const statefulParameters = resourceConfiguration.statefulParameters
|
|
190
|
+
?.reduce((obj, sp) => {
|
|
191
|
+
return {
|
|
192
|
+
...obj,
|
|
193
|
+
[sp.name]: {
|
|
194
|
+
...sp.configuration,
|
|
195
|
+
isStatefulParameter: true,
|
|
196
|
+
}
|
|
108
197
|
}
|
|
198
|
+
}, {}) ?? {}
|
|
109
199
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
case ResourceOperation.DESTROY: return this.applyDestroy(plan);
|
|
200
|
+
return {
|
|
201
|
+
...resourceParameters,
|
|
202
|
+
...statefulParameters,
|
|
114
203
|
}
|
|
204
|
+
|
|
115
205
|
}
|
|
116
206
|
|
|
117
|
-
|
|
118
|
-
|
|
207
|
+
private validateResourceConfiguration(data: ResourceConfiguration<T>) {
|
|
208
|
+
// A parameter cannot be both stateful and stateless
|
|
209
|
+
if (data.parameterConfigurations && data.statefulParameters) {
|
|
210
|
+
const parameters = [...Object.keys(data.parameterConfigurations)];
|
|
211
|
+
const statefulParameterSet = new Set(Object.keys(data.statefulParameters));
|
|
212
|
+
|
|
213
|
+
const intersection = parameters.some((p) => statefulParameterSet.has(p));
|
|
214
|
+
if (intersection) {
|
|
215
|
+
throw new Error(`Resource ${this.typeId} cannot declare a parameter as both stateful and non-stateful`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
119
218
|
}
|
|
120
219
|
|
|
121
|
-
|
|
220
|
+
private validateRefreshResults(refresh: Partial<T> | null, desiredKeys: Set<keyof T>) {
|
|
221
|
+
if (!refresh) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const refreshKeys = new Set(Object.keys(refresh)) as Set<keyof T>;
|
|
226
|
+
|
|
227
|
+
if (!setsEqual(desiredKeys, refreshKeys)) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
`Resource ${this.options.type}
|
|
230
|
+
refresh() must return back exactly the keys that were provided
|
|
231
|
+
Missing: ${[...desiredKeys].filter((k) => !refreshKeys.has(k))};
|
|
232
|
+
Additional: ${[...refreshKeys].filter(k => !desiredKeys.has(k))};`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
122
236
|
|
|
123
|
-
abstract
|
|
237
|
+
abstract validate(config: unknown): Promise<ValidationResult>;
|
|
124
238
|
|
|
125
|
-
abstract
|
|
239
|
+
abstract refresh(keys: Set<keyof T>): Promise<Partial<T> | null>;
|
|
126
240
|
|
|
127
241
|
abstract applyCreate(plan: Plan<T>): Promise<void>;
|
|
128
242
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
abstract applyRecreate(plan: Plan<T>): Promise<void>;
|
|
243
|
+
async applyModify(parameterName: keyof T, newValue: unknown, previousValue: unknown, allowDeletes: boolean, plan: Plan<T>): Promise<void> {};
|
|
132
244
|
|
|
133
|
-
abstract applyDestroy(plan:Plan<T>): Promise<void>;
|
|
245
|
+
abstract applyDestroy(plan: Plan<T>): Promise<void>;
|
|
134
246
|
}
|
|
@@ -1,13 +1,61 @@
|
|
|
1
|
-
import { ParameterChange } from './change-set.js';
|
|
2
1
|
import { Plan } from './plan.js';
|
|
3
|
-
import {
|
|
2
|
+
import { StringIndexedObject } from 'codify-schemas';
|
|
4
3
|
|
|
5
|
-
export
|
|
6
|
-
|
|
4
|
+
export interface StatefulParameterConfiguration<T> {
|
|
5
|
+
name: keyof T;
|
|
6
|
+
isEqual?: (a: any, b: any) => boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
|
|
10
|
+
readonly name: keyof T;
|
|
11
|
+
readonly configuration: StatefulParameterConfiguration<T>;
|
|
12
|
+
|
|
13
|
+
protected constructor(configuration: StatefulParameterConfiguration<T>) {
|
|
14
|
+
this.name = configuration.name;
|
|
15
|
+
this.configuration = configuration
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
abstract refresh(previousValue: V | null): Promise<V | null>;
|
|
19
|
+
|
|
20
|
+
// TODO: Add an additional parameter here for what has actually changed.
|
|
21
|
+
abstract applyAdd(valueToAdd: V, plan: Plan<T>): Promise<void>;
|
|
22
|
+
abstract applyModify(newValue: V, previousValue: V, allowDeletes: boolean, plan: Plan<T>): Promise<void>;
|
|
23
|
+
abstract applyRemove(valueToRemove: V, plan: Plan<T>): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any>{
|
|
27
|
+
protected constructor(configuration: StatefulParameterConfiguration<T>) {
|
|
28
|
+
super(configuration);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async applyAdd(valuesToAdd: V[], plan: Plan<T>): Promise<void> {
|
|
32
|
+
for (const value of valuesToAdd) {
|
|
33
|
+
await this.applyAddItem(value, plan);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void> {
|
|
38
|
+
const valuesToAdd = newValues.filter((n) => !previousValues.includes(n));
|
|
39
|
+
const valuesToRemove = previousValues.filter((n) => !newValues.includes(n));
|
|
40
|
+
|
|
41
|
+
for (const value of valuesToAdd) {
|
|
42
|
+
await this.applyAddItem(value, plan)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (allowDeletes) {
|
|
46
|
+
for (const value of valuesToRemove) {
|
|
47
|
+
await this.applyRemoveItem(value, plan)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
7
51
|
|
|
8
|
-
|
|
52
|
+
async applyRemove(valuesToRemove: V[], plan: Plan<T>): Promise<void> {
|
|
53
|
+
for (const value of valuesToRemove) {
|
|
54
|
+
await this.applyRemoveItem(value as V, plan);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
9
57
|
|
|
10
|
-
abstract
|
|
11
|
-
abstract
|
|
12
|
-
abstract
|
|
58
|
+
abstract refresh(previousValue: V[] | null): Promise<V[] | null>;
|
|
59
|
+
abstract applyAddItem(item: V, plan: Plan<T>): Promise<void>;
|
|
60
|
+
abstract applyRemoveItem(item: V, plan: Plan<T>): Promise<void>;
|
|
13
61
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { Plugin } from './entities/plugin.js';
|
|
|
2
2
|
import { MessageHandler } from './messages/handlers.js';
|
|
3
3
|
|
|
4
4
|
export * from './entities/resource.js'
|
|
5
|
+
export * from './entities/resource-types.js'
|
|
5
6
|
export * from './entities/plugin.js'
|
|
6
7
|
export * from './entities/change-set.js'
|
|
7
8
|
export * from './entities/plan.js'
|
|
9
|
+
export * from './entities/plan-types.js'
|
|
8
10
|
export * from './entities/stateful-parameter.js'
|
|
9
11
|
|
|
10
12
|
export * from './utils/test-utils.js'
|
|
@@ -14,3 +16,4 @@ export async function runPlugin(plugin: Plugin) {
|
|
|
14
16
|
const messageHandler = new MessageHandler(plugin);
|
|
15
17
|
process.on('message', (message) => messageHandler.onMessage(message))
|
|
16
18
|
}
|
|
19
|
+
export { ErrorMessage } from './entities/resource-types.js';
|
package/src/utils/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import promiseSpawn from '@npmcli/promise-spawn';
|
|
2
2
|
import { SpawnOptions } from 'child_process';
|
|
3
|
+
import { ResourceConfig, StringIndexedObject } from 'codify-schemas';
|
|
3
4
|
|
|
4
5
|
export enum SpawnStatus {
|
|
5
6
|
SUCCESS = 'success',
|
|
@@ -78,3 +79,23 @@ export async function codifySpawn(
|
|
|
78
79
|
export function isDebug(): boolean {
|
|
79
80
|
return process.env.DEBUG != null && process.env.DEBUG.includes('codify'); // TODO: replace with debug library
|
|
80
81
|
}
|
|
82
|
+
|
|
83
|
+
export function splitUserConfig<T extends StringIndexedObject>(
|
|
84
|
+
config: T & ResourceConfig
|
|
85
|
+
): { parameters: T; resourceMetadata: ResourceConfig} {
|
|
86
|
+
const resourceMetadata = {
|
|
87
|
+
type: config.type,
|
|
88
|
+
...(config.name && { name: config.name }),
|
|
89
|
+
...(config.dependsOn && { dependsOn: config.dependsOn }),
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const { type, name, dependsOn, ...parameters } = config;
|
|
93
|
+
return {
|
|
94
|
+
parameters: parameters as T,
|
|
95
|
+
resourceMetadata,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function setsEqual(set1: Set<unknown>, set2: Set<unknown>): boolean {
|
|
100
|
+
return set1.size === set2.size && [...set1].every((v) => set2.has(v));
|
|
101
|
+
}
|