codify-plugin-lib 1.0.176 → 1.0.178

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.
Files changed (39) hide show
  1. package/dist/messages/sender.d.ts +1 -0
  2. package/dist/messages/sender.js +10 -0
  3. package/dist/plugin/plugin.js +1 -1
  4. package/dist/resource/resource-controller.d.ts +2 -2
  5. package/dist/resource/resource-controller.js +20 -13
  6. package/dist/resource/resource.d.ts +1 -1
  7. package/package.json +2 -2
  8. package/src/messages/sender.ts +13 -0
  9. package/src/plugin/plugin.ts +2 -1
  10. package/src/resource/resource-controller.ts +21 -13
  11. package/src/resource/resource.ts +1 -1
  12. package/dist/entities/change-set.d.ts +0 -24
  13. package/dist/entities/change-set.js +0 -152
  14. package/dist/entities/errors.d.ts +0 -4
  15. package/dist/entities/errors.js +0 -7
  16. package/dist/entities/plan-types.d.ts +0 -25
  17. package/dist/entities/plan-types.js +0 -1
  18. package/dist/entities/plan.d.ts +0 -15
  19. package/dist/entities/plan.js +0 -127
  20. package/dist/entities/plugin.d.ts +0 -16
  21. package/dist/entities/plugin.js +0 -80
  22. package/dist/entities/resource-options.d.ts +0 -31
  23. package/dist/entities/resource-options.js +0 -76
  24. package/dist/entities/resource-types.d.ts +0 -11
  25. package/dist/entities/resource-types.js +0 -1
  26. package/dist/entities/resource.d.ts +0 -42
  27. package/dist/entities/resource.js +0 -303
  28. package/dist/entities/stateful-parameter.d.ts +0 -29
  29. package/dist/entities/stateful-parameter.js +0 -46
  30. package/dist/entities/transform-parameter.d.ts +0 -4
  31. package/dist/entities/transform-parameter.js +0 -2
  32. package/dist/pty/vitest.config.d.ts +0 -2
  33. package/dist/pty/vitest.config.js +0 -11
  34. package/dist/resource/stateful-parameter.d.ts +0 -165
  35. package/dist/resource/stateful-parameter.js +0 -94
  36. package/dist/utils/spawn-2.d.ts +0 -5
  37. package/dist/utils/spawn-2.js +0 -7
  38. package/dist/utils/spawn.d.ts +0 -29
  39. package/dist/utils/spawn.js +0 -124
@@ -1,303 +0,0 @@
1
- import { Ajv } from 'ajv';
2
- import { ParameterOperation, ResourceOperation, } from 'codify-schemas';
3
- import { setsEqual, splitUserConfig } from '../utils/utils.js';
4
- import { Plan } from './plan.js';
5
- import { ResourceOptionsParser } from './resource-options.js';
6
- export class Resource {
7
- typeId;
8
- statefulParameters;
9
- transformParameters;
10
- resourceParameters;
11
- statefulParameterOrder;
12
- transformParameterOrder;
13
- dependencies;
14
- parameterOptions;
15
- options;
16
- defaultValues;
17
- ajv;
18
- schemaValidator;
19
- constructor(options) {
20
- this.typeId = options.type;
21
- this.dependencies = options.dependencies ?? [];
22
- this.options = options;
23
- if (this.options.schema) {
24
- this.ajv = new Ajv({
25
- allErrors: true,
26
- strict: true,
27
- strictRequired: false,
28
- });
29
- this.schemaValidator = this.ajv.compile(this.options.schema);
30
- }
31
- const parser = new ResourceOptionsParser(options);
32
- this.statefulParameters = parser.statefulParameters;
33
- this.transformParameters = parser.transformParameters;
34
- this.resourceParameters = parser.resourceParameters;
35
- this.parameterOptions = parser.changeSetParameterOptions;
36
- this.defaultValues = parser.defaultValues;
37
- this.statefulParameterOrder = parser.statefulParameterOrder;
38
- this.transformParameterOrder = parser.transformParameterOrder;
39
- }
40
- async onInitialize() { }
41
- async validate(parameters, resourceMetaData) {
42
- if (this.schemaValidator) {
43
- const isValid = this.schemaValidator(parameters);
44
- if (!isValid) {
45
- return {
46
- isValid: false,
47
- resourceName: resourceMetaData.name,
48
- resourceType: resourceMetaData.type,
49
- schemaValidationErrors: this.schemaValidator?.errors ?? [],
50
- };
51
- }
52
- }
53
- let isValid = true;
54
- let customValidationErrorMessage;
55
- try {
56
- await this.customValidation(parameters);
57
- }
58
- catch (error) {
59
- isValid = false;
60
- customValidationErrorMessage = error.message;
61
- }
62
- if (!isValid) {
63
- return {
64
- customValidationErrorMessage,
65
- isValid: false,
66
- resourceName: resourceMetaData.name,
67
- resourceType: resourceMetaData.type,
68
- schemaValidationErrors: this.schemaValidator?.errors ?? [],
69
- };
70
- }
71
- return {
72
- isValid: true,
73
- resourceName: resourceMetaData.name,
74
- resourceType: resourceMetaData.type,
75
- schemaValidationErrors: [],
76
- };
77
- }
78
- async plan(desiredConfig, currentConfig = null, statefulMode = false) {
79
- this.validatePlanInputs(desiredConfig, currentConfig, statefulMode);
80
- const planOptions = {
81
- parameterOptions: this.parameterOptions,
82
- statefulMode,
83
- };
84
- this.addDefaultValues(desiredConfig);
85
- await this.applyTransformParameters(desiredConfig);
86
- const parsedConfig = new ConfigParser(desiredConfig, currentConfig, this.statefulParameters, this.transformParameters);
87
- const { desiredParameters, nonStatefulParameters, resourceMetadata, statefulParameters, } = parsedConfig;
88
- const currentParameters = await this.refreshNonStatefulParameters(nonStatefulParameters);
89
- if (currentParameters === null || currentParameters === undefined) {
90
- return Plan.create(desiredParameters, null, resourceMetadata, planOptions);
91
- }
92
- const statefulCurrentParameters = await this.refreshStatefulParameters(statefulParameters, planOptions.statefulMode);
93
- return Plan.create(desiredParameters, { ...currentParameters, ...statefulCurrentParameters }, resourceMetadata, planOptions);
94
- }
95
- async apply(plan) {
96
- if (plan.getResourceType() !== this.typeId) {
97
- throw new Error(`Internal error: Plan set to wrong resource during apply. Expected ${this.typeId} but got: ${plan.getResourceType()}`);
98
- }
99
- switch (plan.changeSet.operation) {
100
- case ResourceOperation.CREATE: {
101
- return this._applyCreate(plan);
102
- }
103
- case ResourceOperation.MODIFY: {
104
- return this._applyModify(plan);
105
- }
106
- case ResourceOperation.RECREATE: {
107
- await this._applyDestroy(plan);
108
- return this._applyCreate(plan);
109
- }
110
- case ResourceOperation.DESTROY: {
111
- return this._applyDestroy(plan);
112
- }
113
- }
114
- }
115
- async _applyCreate(plan) {
116
- await this.applyCreate(plan);
117
- const statefulParameterChanges = plan.changeSet.parameterChanges
118
- .filter((pc) => this.statefulParameters.has(pc.name))
119
- .sort((a, b) => this.statefulParameterOrder.get(a.name) - this.statefulParameterOrder.get(b.name));
120
- for (const parameterChange of statefulParameterChanges) {
121
- const statefulParameter = this.statefulParameters.get(parameterChange.name);
122
- await statefulParameter.applyAdd(parameterChange.newValue, plan);
123
- }
124
- }
125
- async _applyModify(plan) {
126
- const parameterChanges = plan
127
- .changeSet
128
- .parameterChanges
129
- .filter((c) => c.operation !== ParameterOperation.NOOP);
130
- const statelessParameterChanges = parameterChanges
131
- .filter((pc) => !this.statefulParameters.has(pc.name));
132
- for (const pc of statelessParameterChanges) {
133
- await this.applyModify(pc, plan);
134
- }
135
- const statefulParameterChanges = parameterChanges
136
- .filter((pc) => this.statefulParameters.has(pc.name))
137
- .sort((a, b) => this.statefulParameterOrder.get(a.name) - this.statefulParameterOrder.get(b.name));
138
- for (const parameterChange of statefulParameterChanges) {
139
- const statefulParameter = this.statefulParameters.get(parameterChange.name);
140
- switch (parameterChange.operation) {
141
- case ParameterOperation.ADD: {
142
- await statefulParameter.applyAdd(parameterChange.newValue, plan);
143
- break;
144
- }
145
- case ParameterOperation.MODIFY: {
146
- await statefulParameter.applyModify(parameterChange.newValue, parameterChange.previousValue, false, plan);
147
- break;
148
- }
149
- case ParameterOperation.REMOVE: {
150
- await statefulParameter.applyRemove(parameterChange.previousValue, plan);
151
- break;
152
- }
153
- }
154
- }
155
- }
156
- async _applyDestroy(plan) {
157
- if (this.options.callStatefulParameterRemoveOnDestroy) {
158
- const statefulParameterChanges = plan.changeSet.parameterChanges
159
- .filter((pc) => this.statefulParameters.has(pc.name))
160
- .sort((a, b) => this.statefulParameterOrder.get(a.name) - this.statefulParameterOrder.get(b.name));
161
- for (const parameterChange of statefulParameterChanges) {
162
- const statefulParameter = this.statefulParameters.get(parameterChange.name);
163
- await statefulParameter.applyRemove(parameterChange.previousValue, plan);
164
- }
165
- }
166
- await this.applyDestroy(plan);
167
- }
168
- validateRefreshResults(refresh, desired) {
169
- if (!refresh) {
170
- return;
171
- }
172
- const desiredKeys = new Set(Object.keys(refresh));
173
- const refreshKeys = new Set(Object.keys(refresh));
174
- if (!setsEqual(desiredKeys, refreshKeys)) {
175
- throw new Error(`Resource ${this.typeId}
176
- refresh() must return back exactly the keys that were provided
177
- Missing: ${[...desiredKeys].filter((k) => !refreshKeys.has(k))};
178
- Additional: ${[...refreshKeys].filter(k => !desiredKeys.has(k))};`);
179
- }
180
- }
181
- async applyTransformParameters(desired) {
182
- if (!desired) {
183
- return;
184
- }
185
- const transformParameters = [...this.transformParameters.entries()]
186
- .sort(([keyA], [keyB]) => this.transformParameterOrder.get(keyA) - this.transformParameterOrder.get(keyB));
187
- for (const [key, transformParameter] of transformParameters) {
188
- if (desired[key] === undefined) {
189
- continue;
190
- }
191
- const transformedValue = await transformParameter.transform(desired[key]);
192
- if (Object.keys(transformedValue).some((k) => desired[k] !== undefined)) {
193
- throw new Error(`Transform parameter ${key} is attempting to override existing values ${JSON.stringify(transformedValue, null, 2)}`);
194
- }
195
- delete desired[key];
196
- for (const [tvKey, tvValue] of Object.entries(transformedValue)) {
197
- desired[tvKey] = tvValue;
198
- }
199
- }
200
- }
201
- addDefaultValues(desired) {
202
- if (!desired) {
203
- return;
204
- }
205
- for (const [key, defaultValue] of Object.entries(this.defaultValues)) {
206
- if (defaultValue !== undefined && desired[key] === undefined) {
207
- desired[key] = defaultValue;
208
- }
209
- }
210
- }
211
- async refreshNonStatefulParameters(resourceParameters) {
212
- const currentParameters = await this.refresh(resourceParameters);
213
- this.validateRefreshResults(currentParameters, resourceParameters);
214
- return currentParameters;
215
- }
216
- async refreshStatefulParameters(statefulParametersConfig, isStatefulMode) {
217
- const currentParameters = {};
218
- const sortedEntries = Object.entries(statefulParametersConfig)
219
- .sort(([key1], [key2]) => this.statefulParameterOrder.get(key1) - this.statefulParameterOrder.get(key2));
220
- for (const [key, desiredValue] of sortedEntries) {
221
- const statefulParameter = this.statefulParameters.get(key);
222
- if (!statefulParameter) {
223
- throw new Error(`Stateful parameter ${key} was not found`);
224
- }
225
- let currentValue = await statefulParameter.refresh(desiredValue ?? null);
226
- if (Array.isArray(currentValue)
227
- && Array.isArray(desiredValue)
228
- && !isStatefulMode
229
- && !statefulParameter.options.disableStatelessModeArrayFiltering) {
230
- currentValue = currentValue.filter((c) => desiredValue?.some((d) => {
231
- const parameterOptions = statefulParameter.options;
232
- if (parameterOptions && parameterOptions.isElementEqual) {
233
- return parameterOptions.isElementEqual(d, c);
234
- }
235
- return d === c;
236
- }));
237
- }
238
- currentParameters[key] = currentValue;
239
- }
240
- return currentParameters;
241
- }
242
- validatePlanInputs(desired, current, statefulMode) {
243
- if (!desired && !current) {
244
- throw new Error('Desired config and current config cannot both be missing');
245
- }
246
- if (!statefulMode && !desired) {
247
- throw new Error('Desired config must be provided in non-stateful mode');
248
- }
249
- }
250
- async customValidation(parameters) { }
251
- ;
252
- async applyModify(pc, plan) { }
253
- ;
254
- }
255
- class ConfigParser {
256
- desiredConfig;
257
- currentConfig;
258
- statefulParametersMap;
259
- transformParametersMap;
260
- constructor(desiredConfig, currentConfig, statefulParameters, transformParameters) {
261
- this.desiredConfig = desiredConfig;
262
- this.currentConfig = currentConfig;
263
- this.statefulParametersMap = statefulParameters;
264
- this.transformParametersMap = transformParameters;
265
- }
266
- get resourceMetadata() {
267
- const desiredMetadata = this.desiredConfig ? splitUserConfig(this.desiredConfig).resourceMetadata : undefined;
268
- const currentMetadata = this.currentConfig ? splitUserConfig(this.currentConfig).resourceMetadata : undefined;
269
- if (!desiredMetadata && !currentMetadata) {
270
- throw new Error(`Unable to parse resource metadata from ${this.desiredConfig}, ${this.currentConfig}`);
271
- }
272
- if (currentMetadata && desiredMetadata && (Object.keys(desiredMetadata).length !== Object.keys(currentMetadata).length
273
- || Object.entries(desiredMetadata).some(([key, value]) => currentMetadata[key] !== value))) {
274
- throw new Error(`The metadata for the current config does not match the desired config.
275
- Desired metadata:
276
- ${JSON.stringify(desiredMetadata, null, 2)}
277
-
278
- Current metadata:
279
- ${JSON.stringify(currentMetadata, null, 2)}`);
280
- }
281
- return desiredMetadata ?? currentMetadata;
282
- }
283
- get desiredParameters() {
284
- if (!this.desiredConfig) {
285
- return null;
286
- }
287
- const { parameters } = splitUserConfig(this.desiredConfig);
288
- return parameters;
289
- }
290
- get parameters() {
291
- const desiredParameters = this.desiredConfig ? splitUserConfig(this.desiredConfig).parameters : undefined;
292
- const currentParameters = this.currentConfig ? splitUserConfig(this.currentConfig).parameters : undefined;
293
- return { ...desiredParameters, ...currentParameters };
294
- }
295
- get nonStatefulParameters() {
296
- const { parameters } = this;
297
- return Object.fromEntries(Object.entries(parameters).filter(([key]) => !(this.statefulParametersMap.has(key) || this.transformParametersMap.has(key))));
298
- }
299
- get statefulParameters() {
300
- const { parameters } = this;
301
- return Object.fromEntries(Object.entries(parameters).filter(([key]) => this.statefulParametersMap.has(key)));
302
- }
303
- }
@@ -1,29 +0,0 @@
1
- import { Plan } from './plan.js';
2
- import { StringIndexedObject } from 'codify-schemas';
3
- export interface StatefulParameterOptions<V> {
4
- isEqual?: (desired: any, current: any) => boolean;
5
- disableStatelessModeArrayFiltering?: boolean;
6
- default?: V;
7
- }
8
- export interface ArrayStatefulParameterOptions<V> extends StatefulParameterOptions<V> {
9
- isEqual?: (desired: any[], current: any[]) => boolean;
10
- isElementEqual?: (desired: any, current: any) => boolean;
11
- }
12
- export declare abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
13
- readonly options: StatefulParameterOptions<V>;
14
- constructor(options?: StatefulParameterOptions<V>);
15
- abstract refresh(desired: V | null): Promise<V | null>;
16
- abstract applyAdd(valueToAdd: V, plan: Plan<T>): Promise<void>;
17
- abstract applyModify(newValue: V, previousValue: V, allowDeletes: boolean, plan: Plan<T>): Promise<void>;
18
- abstract applyRemove(valueToRemove: V, plan: Plan<T>): Promise<void>;
19
- }
20
- export declare abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any> {
21
- options: ArrayStatefulParameterOptions<V>;
22
- constructor(options?: ArrayStatefulParameterOptions<V>);
23
- applyAdd(valuesToAdd: V[], plan: Plan<T>): Promise<void>;
24
- applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void>;
25
- applyRemove(valuesToRemove: V[], plan: Plan<T>): Promise<void>;
26
- abstract refresh(desired: V[] | null): Promise<V[] | null>;
27
- abstract applyAddItem(item: V, plan: Plan<T>): Promise<void>;
28
- abstract applyRemoveItem(item: V, plan: Plan<T>): Promise<void>;
29
- }
@@ -1,46 +0,0 @@
1
- export class StatefulParameter {
2
- options;
3
- constructor(options = {}) {
4
- this.options = options;
5
- }
6
- }
7
- export class ArrayStatefulParameter extends StatefulParameter {
8
- options;
9
- constructor(options = {}) {
10
- super(options);
11
- this.options = options;
12
- }
13
- async applyAdd(valuesToAdd, plan) {
14
- for (const value of valuesToAdd) {
15
- await this.applyAddItem(value, plan);
16
- }
17
- }
18
- async applyModify(newValues, previousValues, allowDeletes, plan) {
19
- const options = this.options;
20
- const valuesToAdd = newValues.filter((n) => !previousValues.some((p) => {
21
- if (options.isElementEqual) {
22
- return options.isElementEqual(n, p);
23
- }
24
- return n === p;
25
- }));
26
- const valuesToRemove = previousValues.filter((p) => !newValues.some((n) => {
27
- if (options.isElementEqual) {
28
- return options.isElementEqual(n, p);
29
- }
30
- return n === p;
31
- }));
32
- for (const value of valuesToAdd) {
33
- await this.applyAddItem(value, plan);
34
- }
35
- if (allowDeletes) {
36
- for (const value of valuesToRemove) {
37
- await this.applyRemoveItem(value, plan);
38
- }
39
- }
40
- }
41
- async applyRemove(valuesToRemove, plan) {
42
- for (const value of valuesToRemove) {
43
- await this.applyRemoveItem(value, plan);
44
- }
45
- }
46
- }
@@ -1,4 +0,0 @@
1
- import { StringIndexedObject } from 'codify-schemas';
2
- export declare abstract class TransformParameter<T extends StringIndexedObject> {
3
- abstract transform(value: any): Promise<Partial<T>>;
4
- }
@@ -1,2 +0,0 @@
1
- export class TransformParameter {
2
- }
@@ -1,2 +0,0 @@
1
- declare const _default: import("vite").UserConfig;
2
- export default _default;
@@ -1,11 +0,0 @@
1
- import { defaultExclude, defineConfig } from 'vitest/config';
2
- export default defineConfig({
3
- test: {
4
- pool: 'forks',
5
- fileParallelism: false,
6
- exclude: [
7
- ...defaultExclude,
8
- './src/utils/test-utils.test.ts',
9
- ]
10
- },
11
- });
@@ -1,165 +0,0 @@
1
- import { StringIndexedObject } from 'codify-schemas';
2
- import { Plan } from '../plan/plan.js';
3
- import { ArrayParameterSetting, ParameterSetting } from './resource-settings.js';
4
- /**
5
- * A stateful parameter represents a parameter that holds state on the system (can be created, destroyed) but
6
- * is still tied to the overall lifecycle of a resource.
7
- *
8
- * **Examples include:**
9
- * 1. Homebrew formulas are stateful parameters. They can be installed and uninstalled but they are still tied to the
10
- * overall lifecycle of homebrew
11
- * 2. Nvm installed node versions are stateful parameters. Nvm can install and uninstall different versions of Node but
12
- * these versions are tied to the lifecycle of nvm. If nvm is uninstalled then so are the Node versions.
13
- */
14
- export declare abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
15
- /**
16
- * Parameter settings for the stateful parameter. Stateful parameters share the same parameter settings as
17
- * regular parameters except that they cannot be of type 'stateful'. See {@link ParameterSetting} for more
18
- * information on available settings.
19
- *
20
- * @return The parameter settings
21
- */
22
- getSettings(): ParameterSetting;
23
- /**
24
- * Refresh the status of the stateful parameter on the system. This method works similarly to {@link Resource.refresh}.
25
- * Return the value of the stateful parameter or null if not found.
26
- *
27
- * @param desired The desired value of the user.
28
- * @param config The desired config
29
- *
30
- * @return The value of the stateful parameter currently on the system or null if not found
31
- */
32
- abstract refresh(desired: V | null, config: Partial<T>): Promise<V | null>;
33
- /**
34
- * Create the stateful parameter on the system. This method is similar {@link Resource.create} except that its only
35
- * applicable to the stateful parameter. For resource `CREATE` operations, this method will be called after the
36
- * resource is successfully created. The add method is called when a ParameterChange is ADD in a plan. The add
37
- * method is only called when the stateful parameter does not currently exist.
38
- *
39
- * **Example (Homebrew formula):**
40
- * 1. Add is called with a value of:
41
- * ```
42
- * ['jq', 'jenv']
43
- * ```
44
- * 2. Add handles the request by calling `brew install --formulae jq jenv`
45
- *
46
- * @param valueToAdd The desired value of the stateful parameter.
47
- * @param plan The overall plan that contains the ADD
48
- */
49
- abstract add(valueToAdd: V, plan: Plan<T>): Promise<void>;
50
- /**
51
- * Modify the state of a stateful parameter on the system. This method is similar to {@link Resource.modify} except that its only
52
- * applicable to the stateful parameter.
53
- *
54
- * **Example (Git email parameter):**
55
- * 1. Add is called with a value of:
56
- * ```
57
- * newValue: 'email+new@gmail.com', previousValue: 'email+old@gmail.com'
58
- * ```
59
- * 2. Modify handles the request by calling `git config --global user.email email+new@gmail.com`
60
- *
61
- * @param newValue The desired value of the stateful parameter
62
- * @param previousValue The current value of the stateful parameter
63
- * @param plan The overall plan
64
- */
65
- abstract modify(newValue: V, previousValue: V, plan: Plan<T>): Promise<void>;
66
- /**
67
- * Create the stateful parameter on the system. This method is similar {@link Resource.destroy} except that its only
68
- * applicable to the stateful parameter. The remove method is only called when the stateful parameter already currently exist.
69
- * This method corresponds to REMOVE parameter operations in a plan.
70
- * For resource `DESTORY`, this method is only called if the {@link ResourceSettings.removeStatefulParametersBeforeDestroy}
71
- * is set to true. This method will be called before the resource is destroyed.
72
- *
73
- * **Example (Homebrew formula):**
74
- * 1. Remove is called with a value of:
75
- * ```
76
- * ['jq', 'jenv']
77
- * ```
78
- * 2. Remove handles the request by calling `brew uninstall --formulae jq jenv`
79
- *
80
- * @param valueToRemove The value to remove from the stateful parameter.
81
- * @param plan The overall plan that contains the REMOVE
82
- */
83
- abstract remove(valueToRemove: V, plan: Plan<T>): Promise<void>;
84
- }
85
- /**
86
- * A specialized version of {@link StatefulParameter } that is used for stateful parameters which are arrays.
87
- * A stateful parameter represents a parameter that holds state on the system (can be created, destroyed) but
88
- * is still tied to the overall lifecycle of a resource.
89
- *
90
- * **Examples:**
91
- * - Homebrew formulas are arrays
92
- * - Pyenv python versions are arrays
93
- */
94
- export declare abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any> {
95
- /**
96
- * Parameter level settings. Type must be 'array'.
97
- */
98
- getSettings(): ArrayParameterSetting;
99
- /**
100
- * It is not recommended to override the `add` method. A addItem helper method is available to operate on
101
- * individual elements of the desired array. See {@link StatefulParameter.add} for more info.
102
- *
103
- * @param valuesToAdd The array of values to add
104
- * @param plan The overall plan
105
- *
106
- */
107
- add(valuesToAdd: V[], plan: Plan<T>): Promise<void>;
108
- /**
109
- * It is not recommended to override the `modify` method. `addItem` and `removeItem` will be called accordingly based
110
- * on the modifications. See {@link StatefulParameter.modify} for more info.
111
- *
112
- * @param newValues The new array value
113
- * @param previousValues The previous array value
114
- * @param plan The overall plan
115
- */
116
- modify(newValues: V[], previousValues: V[], plan: Plan<T>): Promise<void>;
117
- /**
118
- * It is not recommended to override the `remove` method. A removeItem helper method is available to operate on
119
- * individual elements of the desired array. See {@link StatefulParameter.remove} for more info.
120
- *
121
- * @param valuesToAdd The array of values to add
122
- * @param plan The overall plan
123
- *
124
- */
125
- remove(valuesToRemove: V[], plan: Plan<T>): Promise<void>;
126
- /**
127
- * See {@link StatefulParameter.refresh} for more info.
128
- *
129
- * @param desired The desired value to refresh
130
- * @return The current value on the system or null if not found.
131
- */
132
- abstract refresh(desired: V[] | null, config: Partial<T>): Promise<V[] | null>;
133
- /**
134
- * Helper method that gets called when individual elements of the array need to be added. See {@link StatefulParameter.add}
135
- * for more information.
136
- *
137
- * Example (Homebrew formula):
138
- * 1. The stateful parameter receives an input of:
139
- * ```
140
- * ['jq', 'jenv', 'docker']
141
- * ```
142
- * 2. Internally the stateful parameter will iterate the array and call `addItem` for each element
143
- * 3. Override addItem and install each formula using `brew install --formula jq`
144
- *
145
- * @param item The item to add (install)
146
- * @param plan The overall plan
147
- */
148
- abstract addItem(item: V, plan: Plan<T>): Promise<void>;
149
- /**
150
- * Helper method that gets called when individual elements of the array need to be removed. See {@link StatefulParameter.remove}
151
- * for more information.
152
- *
153
- * Example (Homebrew formula):
154
- * 1. The stateful parameter receives an input of:
155
- * ```
156
- * ['jq', 'jenv', 'docker']
157
- * ```
158
- * 2. Internally the stateful parameter will iterate the array and call `removeItem` for each element
159
- * 3. Override removeItem and uninstall each formula using `brew uninstall --formula jq`
160
- *
161
- * @param item The item to remove (uninstall)
162
- * @param plan The overall plan
163
- */
164
- abstract removeItem(item: V, plan: Plan<T>): Promise<void>;
165
- }
@@ -1,94 +0,0 @@
1
- /**
2
- * A stateful parameter represents a parameter that holds state on the system (can be created, destroyed) but
3
- * is still tied to the overall lifecycle of a resource.
4
- *
5
- * **Examples include:**
6
- * 1. Homebrew formulas are stateful parameters. They can be installed and uninstalled but they are still tied to the
7
- * overall lifecycle of homebrew
8
- * 2. Nvm installed node versions are stateful parameters. Nvm can install and uninstall different versions of Node but
9
- * these versions are tied to the lifecycle of nvm. If nvm is uninstalled then so are the Node versions.
10
- */
11
- export class StatefulParameter {
12
- /**
13
- * Parameter settings for the stateful parameter. Stateful parameters share the same parameter settings as
14
- * regular parameters except that they cannot be of type 'stateful'. See {@link ParameterSetting} for more
15
- * information on available settings.
16
- *
17
- * @return The parameter settings
18
- */
19
- getSettings() {
20
- return {};
21
- }
22
- }
23
- /**
24
- * A specialized version of {@link StatefulParameter } that is used for stateful parameters which are arrays.
25
- * A stateful parameter represents a parameter that holds state on the system (can be created, destroyed) but
26
- * is still tied to the overall lifecycle of a resource.
27
- *
28
- * **Examples:**
29
- * - Homebrew formulas are arrays
30
- * - Pyenv python versions are arrays
31
- */
32
- export class ArrayStatefulParameter extends StatefulParameter {
33
- /**
34
- * Parameter level settings. Type must be 'array'.
35
- */
36
- getSettings() {
37
- return { type: 'array' };
38
- }
39
- /**
40
- * It is not recommended to override the `add` method. A addItem helper method is available to operate on
41
- * individual elements of the desired array. See {@link StatefulParameter.add} for more info.
42
- *
43
- * @param valuesToAdd The array of values to add
44
- * @param plan The overall plan
45
- *
46
- */
47
- async add(valuesToAdd, plan) {
48
- for (const value of valuesToAdd) {
49
- await this.addItem(value, plan);
50
- }
51
- }
52
- /**
53
- * It is not recommended to override the `modify` method. `addItem` and `removeItem` will be called accordingly based
54
- * on the modifications. See {@link StatefulParameter.modify} for more info.
55
- *
56
- * @param newValues The new array value
57
- * @param previousValues The previous array value
58
- * @param plan The overall plan
59
- */
60
- async modify(newValues, previousValues, plan) {
61
- // TODO: I don't think this works with duplicate elements. Solve at another time
62
- const valuesToAdd = newValues.filter((n) => !previousValues.some((p) => {
63
- if (this.getSettings()?.isElementEqual) {
64
- return this.getSettings().isElementEqual(n, p);
65
- }
66
- return n === p;
67
- }));
68
- const valuesToRemove = previousValues.filter((p) => !newValues.some((n) => {
69
- if (this.getSettings().isElementEqual) {
70
- return this.getSettings().isElementEqual(n, p);
71
- }
72
- return n === p;
73
- }));
74
- for (const value of valuesToAdd) {
75
- await this.addItem(value, plan);
76
- }
77
- for (const value of valuesToRemove) {
78
- await this.removeItem(value, plan);
79
- }
80
- }
81
- /**
82
- * It is not recommended to override the `remove` method. A removeItem helper method is available to operate on
83
- * individual elements of the desired array. See {@link StatefulParameter.remove} for more info.
84
- *
85
- * @param valuesToAdd The array of values to add
86
- * @param plan The overall plan
87
- *
88
- */
89
- async remove(valuesToRemove, plan) {
90
- for (const value of valuesToRemove) {
91
- await this.removeItem(value, plan);
92
- }
93
- }
94
- }
@@ -1,5 +0,0 @@
1
- import { Shell } from 'zx';
2
- export declare class ShellContext implements Shell {
3
- zx: Shell;
4
- static create(): ShellContext;
5
- }
@@ -1,7 +0,0 @@
1
- import { $ } from 'zx';
2
- export class ShellContext {
3
- zx = $({ shell: true });
4
- static create() {
5
- return new ShellContext();
6
- }
7
- }