codify-plugin-lib 1.0.131 → 1.0.133
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/.github/workflows/unit-test-ci.yaml +1 -2
- package/dist/plan/plan.d.ts +1 -3
- package/dist/plan/plan.js +31 -9
- package/dist/plugin/plugin.js +1 -1
- package/dist/resource/parsed-resource-settings.d.ts +5 -3
- package/dist/resource/parsed-resource-settings.js +6 -7
- package/dist/resource/resource-controller.d.ts +1 -0
- package/dist/resource/resource-controller.js +23 -5
- package/dist/resource/resource-settings.d.ts +36 -14
- package/dist/resource/resource-settings.js +43 -11
- package/dist/stateful-parameter/stateful-parameter-controller.js +2 -3
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +3 -0
- package/package.json +3 -2
- package/src/plan/plan.test.ts +114 -0
- package/src/plan/plan.ts +38 -9
- package/src/plugin/plugin.test.ts +47 -3
- package/src/plugin/plugin.ts +1 -1
- package/src/pty/background-pty.test.ts +16 -15
- package/src/pty/index.test.ts +6 -9
- package/src/resource/parsed-resource-settings.test.ts +4 -4
- package/src/resource/parsed-resource-settings.ts +12 -9
- package/src/resource/resource-controller.ts +33 -5
- package/src/resource/resource-settings.test.ts +87 -14
- package/src/resource/resource-settings.ts +91 -27
- package/src/stateful-parameter/stateful-parameter-controller.ts +2 -3
- package/src/utils/test-utils.test.ts +6 -0
- package/src/utils/utils.ts +4 -0
- package/vitest.config.ts +2 -3
- package/src/pty/vitest.config.ts +0 -11
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import { JSONSchemaType } from 'ajv';
|
|
1
2
|
import { StringIndexedObject } from 'codify-schemas';
|
|
2
3
|
import isObjectsEqual from 'lodash.isequal'
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
|
|
5
6
|
import { ArrayStatefulParameter, StatefulParameter } from '../stateful-parameter/stateful-parameter.js';
|
|
6
|
-
import { areArraysEqual, untildify } from '../utils/utils.js';
|
|
7
|
+
import { areArraysEqual, tildify, untildify } from '../utils/utils.js';
|
|
8
|
+
|
|
9
|
+
export interface InputTransformation {
|
|
10
|
+
to: (input: any) => Promise<any> | any;
|
|
11
|
+
from: (current: any) => Promise<any> | any;
|
|
12
|
+
}
|
|
7
13
|
|
|
8
14
|
/**
|
|
9
15
|
* The configuration and settings for a resource.
|
|
@@ -18,7 +24,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
18
24
|
/**
|
|
19
25
|
* Schema to validate user configs with. Must be in the format JSON Schema draft07
|
|
20
26
|
*/
|
|
21
|
-
schema?:
|
|
27
|
+
schema?: JSONSchemaType<T | any>;
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
30
|
* Allow multiple of the same resource to unique. Set truthy if
|
|
@@ -27,6 +33,17 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
27
33
|
*/
|
|
28
34
|
allowMultiple?: {
|
|
29
35
|
|
|
36
|
+
/**
|
|
37
|
+
* A set of parameters that uniquely identifies a resource. The value of these parameters is used to determine which
|
|
38
|
+
* resource is which when multiple can exist at the same time. Defaults to the required parameters inside the json
|
|
39
|
+
* schema.
|
|
40
|
+
*
|
|
41
|
+
* For example:
|
|
42
|
+
* If paramA is required, then if resource1.paramA === resource2.paramA then are the same resource.
|
|
43
|
+
* If resource1.paramA !== resource1.paramA, then they are different.
|
|
44
|
+
*/
|
|
45
|
+
requiredParameters?: string[]
|
|
46
|
+
|
|
30
47
|
/**
|
|
31
48
|
* If multiple copies are allowed then a matcher must be defined to match the desired
|
|
32
49
|
* config with one of the resources currently existing on the system. Return null if there is no match.
|
|
@@ -36,8 +53,8 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
36
53
|
*
|
|
37
54
|
* @return The matched resource.
|
|
38
55
|
*/
|
|
39
|
-
matcher
|
|
40
|
-
}
|
|
56
|
+
matcher?: (desired: Partial<T>, current: Partial<T>[],) => Partial<T>
|
|
57
|
+
} | boolean
|
|
41
58
|
|
|
42
59
|
/**
|
|
43
60
|
* If true, {@link StatefulParameter} remove() will be called before resource destruction. This is useful
|
|
@@ -67,9 +84,9 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
67
84
|
inputTransformation?: (desired: Partial<T>) => Promise<unknown> | unknown;
|
|
68
85
|
|
|
69
86
|
/**
|
|
70
|
-
* Customize the import behavior of the resource. By default, <code>codify import</code> will call
|
|
71
|
-
* every parameter set to null and return the result of the refresh as the imported config. It looks for required parameters
|
|
72
|
-
* in the schema and will prompt the user for these values before performing the import.
|
|
87
|
+
* Customize the import and destory behavior of the resource. By default, <code>codify import</code> and <code>codify destroy</code> will call
|
|
88
|
+
* `refresh()` with every parameter set to null and return the result of the refresh as the imported config. It looks for required parameters
|
|
89
|
+
* in the schema and will prompt the user for these values before performing the import or destroy.
|
|
73
90
|
*
|
|
74
91
|
* <b>Example:</b><br>
|
|
75
92
|
* Resource `alias` with parameters
|
|
@@ -85,7 +102,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
85
102
|
* { type: 'alias', alias: 'user-input', value: 'git push' }
|
|
86
103
|
* ```
|
|
87
104
|
*/
|
|
88
|
-
|
|
105
|
+
importAndDestroy?: {
|
|
89
106
|
|
|
90
107
|
/**
|
|
91
108
|
* Customize the required parameters needed to import this resource. By default, the `requiredParameters` are taken
|
|
@@ -96,7 +113,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
96
113
|
* the required parameters change the behaviour of the refresh (for example for the `alias` resource, the `alias` parmaeter
|
|
97
114
|
* chooses which alias the resource is managing).
|
|
98
115
|
*
|
|
99
|
-
* See {@link
|
|
116
|
+
* See {@link importAndDestroy} for more information on how importing works.
|
|
100
117
|
*/
|
|
101
118
|
requiredParameters?: Array<Partial<keyof T>>;
|
|
102
119
|
|
|
@@ -107,14 +124,14 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
107
124
|
* By default all parameters (except for {@link requiredParameters }) are passed in with the value `null`. The passed
|
|
108
125
|
* in value can be customized using {@link defaultRefreshValues}
|
|
109
126
|
*
|
|
110
|
-
* See {@link
|
|
127
|
+
* See {@link importAndDestroy} for more information on how importing works.
|
|
111
128
|
*/
|
|
112
129
|
refreshKeys?: Array<Partial<keyof T>>;
|
|
113
130
|
|
|
114
131
|
/**
|
|
115
132
|
* Customize the value that is passed into refresh when importing. This must only contain keys found in {@link refreshKeys}.
|
|
116
133
|
*
|
|
117
|
-
* See {@link
|
|
134
|
+
* See {@link importAndDestroy} for more information on how importing works.
|
|
118
135
|
*/
|
|
119
136
|
defaultRefreshValues?: Partial<T>
|
|
120
137
|
}
|
|
@@ -166,12 +183,13 @@ export interface DefaultParameterSetting {
|
|
|
166
183
|
default?: unknown;
|
|
167
184
|
|
|
168
185
|
/**
|
|
169
|
-
* A transformation of the input value for this parameter.
|
|
170
|
-
*
|
|
186
|
+
* A transformation of the input value for this parameter. Two transformations need to be provided: to (from desired to
|
|
187
|
+
* the internal type), and from (from the internal type back to desired). All transformations need to be bi-directional
|
|
188
|
+
* to support imports properly
|
|
171
189
|
*
|
|
172
190
|
* @param input The original parameter value from the desired config.
|
|
173
191
|
*/
|
|
174
|
-
inputTransformation?:
|
|
192
|
+
inputTransformation?: InputTransformation;
|
|
175
193
|
|
|
176
194
|
/**
|
|
177
195
|
* Customize the equality comparison for a parameter. This is used in the diffing algorithm for generating the plan.
|
|
@@ -233,6 +251,12 @@ export interface ArrayParameterSetting extends DefaultParameterSetting {
|
|
|
233
251
|
* Defaults to true.
|
|
234
252
|
*/
|
|
235
253
|
filterInStatelessMode?: ((desired: any[], current: any[]) => any[]) | boolean,
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The type of the array item. See {@link ParameterSettingType} for the available options. This value
|
|
257
|
+
* is mainly used to determine the equality method when performing diffing.
|
|
258
|
+
*/
|
|
259
|
+
itemType?: ParameterSettingType,
|
|
236
260
|
}
|
|
237
261
|
|
|
238
262
|
/**
|
|
@@ -273,10 +297,7 @@ export function resolveEqualsFn(parameter: ParameterSetting): (desired: unknown,
|
|
|
273
297
|
const isEqual = resolveFnFromEqualsFnOrString(parameter.isEqual);
|
|
274
298
|
|
|
275
299
|
if (parameter.type === 'array') {
|
|
276
|
-
|
|
277
|
-
const isElementEqual = resolveFnFromEqualsFnOrString(arrayParameter.isElementEqual);
|
|
278
|
-
|
|
279
|
-
return isEqual ?? areArraysEqual.bind(areArraysEqual, isElementEqual)
|
|
300
|
+
return isEqual ?? areArraysEqual.bind(areArraysEqual, resolveElementEqualsFn(parameter as ArrayParameterSetting))
|
|
280
301
|
}
|
|
281
302
|
|
|
282
303
|
if (parameter.type === 'stateful') {
|
|
@@ -286,6 +307,21 @@ export function resolveEqualsFn(parameter: ParameterSetting): (desired: unknown,
|
|
|
286
307
|
return isEqual ?? ParameterEqualsDefaults[parameter.type as ParameterSettingType] ?? (((a, b) => a === b));
|
|
287
308
|
}
|
|
288
309
|
|
|
310
|
+
export function resolveElementEqualsFn(parameter: ArrayParameterSetting): (desired: unknown, current: unknown) => boolean {
|
|
311
|
+
if (parameter.isElementEqual) {
|
|
312
|
+
const elementEq = resolveFnFromEqualsFnOrString(parameter.isElementEqual);
|
|
313
|
+
if (elementEq) {
|
|
314
|
+
return elementEq;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (parameter.itemType && ParameterEqualsDefaults[parameter.itemType]) {
|
|
319
|
+
return ParameterEqualsDefaults[parameter.itemType]!
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return (a, b) => a === b;
|
|
323
|
+
}
|
|
324
|
+
|
|
289
325
|
// This resolves the fn if it is a string.
|
|
290
326
|
// A string can be specified to use a default equals method
|
|
291
327
|
export function resolveFnFromEqualsFnOrString(
|
|
@@ -303,19 +339,47 @@ export function resolveFnFromEqualsFnOrString(
|
|
|
303
339
|
return fnOrString as ((a: unknown, b: unknown) => boolean) | undefined;
|
|
304
340
|
}
|
|
305
341
|
|
|
306
|
-
const ParameterTransformationDefaults: Partial<Record<ParameterSettingType,
|
|
307
|
-
'directory':
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return (sp.definition?.getSettings()?.inputTransformation)
|
|
311
|
-
? (sp.definition.getSettings().inputTransformation!(a))
|
|
312
|
-
: a;
|
|
342
|
+
const ParameterTransformationDefaults: Partial<Record<ParameterSettingType, InputTransformation>> = {
|
|
343
|
+
'directory': {
|
|
344
|
+
to: (a: unknown) => path.resolve(untildify(String(a))),
|
|
345
|
+
from: (a: unknown) => tildify(String(a)),
|
|
313
346
|
},
|
|
314
|
-
'string':
|
|
347
|
+
'string': {
|
|
348
|
+
to: String,
|
|
349
|
+
from: String,
|
|
350
|
+
}
|
|
315
351
|
}
|
|
316
352
|
|
|
317
353
|
export function resolveParameterTransformFn(
|
|
318
354
|
parameter: ParameterSetting
|
|
319
|
-
):
|
|
355
|
+
): InputTransformation | undefined {
|
|
356
|
+
|
|
357
|
+
if (parameter.type === 'stateful' && !parameter.inputTransformation) {
|
|
358
|
+
const sp = (parameter as StatefulParameterSetting).definition.getSettings();
|
|
359
|
+
if (sp.inputTransformation) {
|
|
360
|
+
return (parameter as StatefulParameterSetting).definition?.getSettings()?.inputTransformation
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return sp.type ? ParameterTransformationDefaults[sp.type] : undefined;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (parameter.type === 'array'
|
|
367
|
+
&& (parameter as ArrayParameterSetting).itemType
|
|
368
|
+
&& ParameterTransformationDefaults[(parameter as ArrayParameterSetting).itemType!]
|
|
369
|
+
&& !parameter.inputTransformation
|
|
370
|
+
) {
|
|
371
|
+
const itemType = (parameter as ArrayParameterSetting).itemType!;
|
|
372
|
+
const itemTransformation = ParameterTransformationDefaults[itemType]!;
|
|
373
|
+
|
|
374
|
+
return {
|
|
375
|
+
to(input: unknown[]) {
|
|
376
|
+
return input.map((i) => itemTransformation.to(i))
|
|
377
|
+
},
|
|
378
|
+
from(input: unknown[]) {
|
|
379
|
+
return input.map((i) => itemTransformation.from(i))
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
320
384
|
return parameter.inputTransformation ?? ParameterTransformationDefaults[parameter.type as ParameterSettingType] ?? undefined;
|
|
321
385
|
}
|
|
@@ -5,8 +5,8 @@ import { ParsedArrayParameterSetting, ParsedParameterSetting, } from '../resourc
|
|
|
5
5
|
import {
|
|
6
6
|
ArrayParameterSetting,
|
|
7
7
|
ParameterSetting,
|
|
8
|
+
resolveElementEqualsFn,
|
|
8
9
|
resolveEqualsFn,
|
|
9
|
-
resolveFnFromEqualsFnOrString
|
|
10
10
|
} from '../resource/resource-settings.js';
|
|
11
11
|
import { ArrayStatefulParameter, StatefulParameter } from './stateful-parameter.js';
|
|
12
12
|
|
|
@@ -31,8 +31,7 @@ export class StatefulParameterController<T extends StringIndexedObject, V extend
|
|
|
31
31
|
this.parsedSettings = (this.isArrayStatefulParameter || this.settings.type === 'array') ? {
|
|
32
32
|
...this.settings,
|
|
33
33
|
isEqual: resolveEqualsFn(this.settings),
|
|
34
|
-
isElementEqual:
|
|
35
|
-
?? ((a: unknown, b: unknown) => a === b)
|
|
34
|
+
isElementEqual: resolveElementEqualsFn(this.settings as ArrayParameterSetting)
|
|
36
35
|
} as ParsedParameterSetting : {
|
|
37
36
|
...this.settings,
|
|
38
37
|
isEqual: resolveEqualsFn(this.settings),
|
|
@@ -5,6 +5,7 @@ import { Resource } from '../resource/resource.js';
|
|
|
5
5
|
import { CreatePlan, DestroyPlan } from '../plan/plan-types.js';
|
|
6
6
|
import { ArrayStatefulParameter, StatefulParameter } from '../stateful-parameter/stateful-parameter.js';
|
|
7
7
|
import { ParsedResourceSettings } from '../resource/parsed-resource-settings.js';
|
|
8
|
+
import { describe, it } from 'vitest';
|
|
8
9
|
|
|
9
10
|
export function testPlan<T extends StringIndexedObject>(params: {
|
|
10
11
|
desired?: Partial<T> | null;
|
|
@@ -85,3 +86,8 @@ export class TestArrayStatefulParameter extends ArrayStatefulParameter<TestConfi
|
|
|
85
86
|
return Promise.resolve(undefined);
|
|
86
87
|
}
|
|
87
88
|
}
|
|
89
|
+
|
|
90
|
+
describe('Empty tests', () => {
|
|
91
|
+
it('empty', () => {
|
|
92
|
+
})
|
|
93
|
+
})
|
package/src/utils/utils.ts
CHANGED
|
@@ -33,6 +33,10 @@ export function untildify(pathWithTilde: string) {
|
|
|
33
33
|
return homeDirectory ? pathWithTilde.replace(/^~(?=$|\/|\\)/, homeDirectory) : pathWithTilde;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export function tildify(pathWithTilde: string) {
|
|
37
|
+
return homeDirectory ? pathWithTilde.replace(homeDirectory, '~') : pathWithTilde;
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
export function areArraysEqual(
|
|
37
41
|
isElementEqual: ((desired: unknown, current: unknown) => boolean) | undefined,
|
|
38
42
|
desired: unknown,
|
package/vitest.config.ts
CHANGED