codify-plugin-lib 1.0.140 → 1.0.142
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/plan/plan.js +1 -1
- package/dist/plugin/plugin.js +3 -2
- package/dist/resource/resource-controller.d.ts +1 -0
- package/dist/resource/resource-controller.js +14 -0
- package/dist/resource/resource-settings.d.ts +8 -1
- package/dist/resource/resource-settings.js +4 -0
- package/package.json +2 -2
- package/src/plan/plan.test.ts +1 -1
- package/src/plan/plan.ts +1 -1
- package/src/plugin/plugin.test.ts +42 -0
- package/src/plugin/plugin.ts +3 -2
- package/src/resource/resource-controller.test.ts +35 -0
- package/src/resource/resource-controller.ts +19 -0
- package/src/resource/resource-settings.ts +13 -2
package/dist/plan/plan.js
CHANGED
|
@@ -159,7 +159,7 @@ export class Plan {
|
|
|
159
159
|
const matcher = typeof settings.allowMultiple === 'boolean' || !settings.allowMultiple.matcher
|
|
160
160
|
? ((desired, currentArr) => {
|
|
161
161
|
const requiredParameters = typeof settings.allowMultiple === 'object'
|
|
162
|
-
? settings.allowMultiple?.
|
|
162
|
+
? settings.allowMultiple?.identifyingParameters ?? settings.schema?.required ?? []
|
|
163
163
|
: settings.schema?.required ?? [];
|
|
164
164
|
const matched = currentArr.filter((c) => requiredParameters.every((key) => {
|
|
165
165
|
const currentParameter = c[key];
|
package/dist/plugin/plugin.js
CHANGED
|
@@ -43,14 +43,15 @@ export class Plugin {
|
|
|
43
43
|
?? null);
|
|
44
44
|
const allowMultiple = resource.settings.allowMultiple !== undefined
|
|
45
45
|
? (typeof resource.settings.allowMultiple === 'boolean'
|
|
46
|
-
? {
|
|
47
|
-
: {
|
|
46
|
+
? { identifyingParameters: schema?.required ?? [] }
|
|
47
|
+
: { identifyingParameters: resource.settings.allowMultiple.identifyingParameters ?? schema?.required ?? [] }) : undefined;
|
|
48
48
|
return {
|
|
49
49
|
plugin: this.name,
|
|
50
50
|
type: data.type,
|
|
51
51
|
dependencies: resource.dependencies,
|
|
52
52
|
schema: schema,
|
|
53
53
|
importAndDestroy: {
|
|
54
|
+
preventImport: resource.settings.importAndDestroy?.preventImport,
|
|
54
55
|
requiredParameters: requiredPropertyNames,
|
|
55
56
|
},
|
|
56
57
|
import: {
|
|
@@ -25,6 +25,7 @@ export declare class ResourceController<T extends StringIndexedObject> {
|
|
|
25
25
|
private validateRefreshResults;
|
|
26
26
|
private applyTransformParameters;
|
|
27
27
|
private addDefaultValues;
|
|
28
|
+
private removeDefaultValues;
|
|
28
29
|
private refreshNonStatefulParameters;
|
|
29
30
|
private refreshStatefulParameters;
|
|
30
31
|
private validatePlanInputs;
|
|
@@ -147,6 +147,9 @@ export class ResourceController {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
async import(core, parameters) {
|
|
150
|
+
if (this.settings.importAndDestroy?.preventImport) {
|
|
151
|
+
throw new Error(`Type: ${this.typeId} cannot be imported`);
|
|
152
|
+
}
|
|
150
153
|
this.addDefaultValues(parameters);
|
|
151
154
|
await this.applyTransformParameters(parameters);
|
|
152
155
|
// Use refresh parameters if specified, otherwise try to refresh as many parameters as possible here
|
|
@@ -176,6 +179,7 @@ export class ResourceController {
|
|
|
176
179
|
const statefulCurrentParameters = await this.refreshStatefulParameters(allStatefulParameters, parametersToRefresh);
|
|
177
180
|
const resultParameters = { ...currentParametersArray[0], ...statefulCurrentParameters };
|
|
178
181
|
await this.applyTransformParameters(resultParameters, true);
|
|
182
|
+
this.removeDefaultValues(resultParameters, parameters);
|
|
179
183
|
return [{ core, parameters: resultParameters }];
|
|
180
184
|
}
|
|
181
185
|
async applyCreate(plan) {
|
|
@@ -268,6 +272,16 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
268
272
|
}
|
|
269
273
|
}
|
|
270
274
|
}
|
|
275
|
+
removeDefaultValues(newConfig, originalConfig) {
|
|
276
|
+
if (!newConfig) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
for (const [key, defaultValue] of Object.entries(this.parsedSettings.defaultValues)) {
|
|
280
|
+
if (defaultValue !== undefined && (newConfig[key] === defaultValue || originalConfig[key] === undefined || originalConfig[key] === null)) {
|
|
281
|
+
delete newConfig[key];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
271
285
|
async refreshNonStatefulParameters(resourceParameters) {
|
|
272
286
|
const result = await this.resource.refresh(resourceParameters);
|
|
273
287
|
const currentParametersArray = Array.isArray(result) || result === null
|
|
@@ -32,7 +32,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
32
32
|
* If paramA is required, then if resource1.paramA === resource2.paramA then are the same resource.
|
|
33
33
|
* If resource1.paramA !== resource1.paramA, then they are different.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
identifyingParameters?: string[];
|
|
36
36
|
/**
|
|
37
37
|
* If multiple copies are allowed then a matcher must be defined to match the desired
|
|
38
38
|
* config with one of the resources currently existing on the system. Return null if there is no match.
|
|
@@ -87,6 +87,13 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
87
87
|
* ```
|
|
88
88
|
*/
|
|
89
89
|
importAndDestroy?: {
|
|
90
|
+
/**
|
|
91
|
+
* Can this resources be imported? If set to false then the codifyCLI will skip over/not consider this
|
|
92
|
+
* resource valid for imports. Defaults to true.
|
|
93
|
+
*
|
|
94
|
+
* Resources that can't be imported in the core library for example are: action resources
|
|
95
|
+
*/
|
|
96
|
+
preventImport?: boolean;
|
|
90
97
|
/**
|
|
91
98
|
* Customize the required parameters needed to import this resource. By default, the `requiredParameters` are taken
|
|
92
99
|
* from the JSON schema. The `requiredParameters` parameter must be declared if a complex required is declared in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codify-plugin-lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.142",
|
|
4
4
|
"description": "Library plugin library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"ajv": "^8.12.0",
|
|
18
18
|
"ajv-formats": "^2.1.1",
|
|
19
|
-
"codify-schemas": "1.0.
|
|
19
|
+
"codify-schemas": "1.0.70",
|
|
20
20
|
"@npmcli/promise-spawn": "^7.0.1",
|
|
21
21
|
"@homebridge/node-pty-prebuilt-multiarch": "^0.12.0-beta.5",
|
|
22
22
|
"uuid": "^10.0.0",
|
package/src/plan/plan.test.ts
CHANGED
package/src/plan/plan.ts
CHANGED
|
@@ -263,7 +263,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
263
263
|
const matcher = typeof settings.allowMultiple === 'boolean' || !settings.allowMultiple.matcher
|
|
264
264
|
? ((desired: Partial<T>, currentArr: Array<Partial<T>>) => {
|
|
265
265
|
const requiredParameters = typeof settings.allowMultiple === 'object'
|
|
266
|
-
? settings.allowMultiple?.
|
|
266
|
+
? settings.allowMultiple?.identifyingParameters ?? (settings.schema?.required as string[]) ?? []
|
|
267
267
|
: (settings.schema?.required as string[]) ?? []
|
|
268
268
|
|
|
269
269
|
const matched = currentArr.filter((c) => requiredParameters.every((key) => {
|
|
@@ -324,4 +324,46 @@ describe('Plugin tests', () => {
|
|
|
324
324
|
|
|
325
325
|
console.log(result);
|
|
326
326
|
})
|
|
327
|
+
|
|
328
|
+
it('Returns allowMultiple for getResourceInfo', async () => {
|
|
329
|
+
const resource = spy(new class extends TestResource {
|
|
330
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
331
|
+
return {
|
|
332
|
+
...super.getSettings(),
|
|
333
|
+
allowMultiple: {
|
|
334
|
+
identifyingParameters: ['path', 'paths']
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
341
|
+
|
|
342
|
+
const resourceInfo = await testPlugin.getResourceInfo({
|
|
343
|
+
type: 'testResource',
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
expect(resourceInfo.allowMultiple?.requiredParameters).toMatchObject([
|
|
347
|
+
'path', 'paths'
|
|
348
|
+
])
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
it('Returns an empty array by default for allowMultiple for getResourceInfo', async () => {
|
|
352
|
+
const resource = spy(new class extends TestResource {
|
|
353
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
354
|
+
return {
|
|
355
|
+
...super.getSettings(),
|
|
356
|
+
allowMultiple: true
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
362
|
+
|
|
363
|
+
const resourceInfo = await testPlugin.getResourceInfo({
|
|
364
|
+
type: 'testResource',
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
expect(resourceInfo.allowMultiple?.requiredParameters).toMatchObject([])
|
|
368
|
+
})
|
|
327
369
|
});
|
package/src/plugin/plugin.ts
CHANGED
|
@@ -74,8 +74,8 @@ export class Plugin {
|
|
|
74
74
|
|
|
75
75
|
const allowMultiple = resource.settings.allowMultiple !== undefined
|
|
76
76
|
? (typeof resource.settings.allowMultiple === 'boolean'
|
|
77
|
-
? {
|
|
78
|
-
: {
|
|
77
|
+
? { identifyingParameters: schema?.required ?? [] }
|
|
78
|
+
: { identifyingParameters: resource.settings.allowMultiple.identifyingParameters ?? schema?.required ?? [] }
|
|
79
79
|
) : undefined
|
|
80
80
|
|
|
81
81
|
return {
|
|
@@ -84,6 +84,7 @@ export class Plugin {
|
|
|
84
84
|
dependencies: resource.dependencies,
|
|
85
85
|
schema: schema as Record<string, unknown> | undefined,
|
|
86
86
|
importAndDestroy: {
|
|
87
|
+
preventImport: resource.settings.importAndDestroy?.preventImport,
|
|
87
88
|
requiredParameters: requiredPropertyNames,
|
|
88
89
|
},
|
|
89
90
|
import: {
|
|
@@ -711,4 +711,39 @@ describe('Resource tests', () => {
|
|
|
711
711
|
}
|
|
712
712
|
})
|
|
713
713
|
})
|
|
714
|
+
|
|
715
|
+
it('Applies removes default values if they remain default for imports', async () => {
|
|
716
|
+
const resource = new class extends TestResource {
|
|
717
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
718
|
+
return {
|
|
719
|
+
id: 'resourceType',
|
|
720
|
+
parameterSettings: {
|
|
721
|
+
propA: { type: 'string', default: 'defaultValue' },
|
|
722
|
+
propB: { type: 'boolean', default: true }
|
|
723
|
+
},
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
async refresh(parameters: Partial<TestConfig>): Promise<Partial<TestConfig> | null> {
|
|
728
|
+
return {
|
|
729
|
+
propA: 'defaultValue',
|
|
730
|
+
propB: false,
|
|
731
|
+
propC: 'newPropC'
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
const controller = new ResourceController(resource);
|
|
737
|
+
const plan = await controller.import({ type: 'resourceType' }, {});
|
|
738
|
+
|
|
739
|
+
expect(plan![0]).toMatchObject({
|
|
740
|
+
'core': {
|
|
741
|
+
'type': 'resourceType'
|
|
742
|
+
},
|
|
743
|
+
'parameters': {
|
|
744
|
+
propB: false,
|
|
745
|
+
propC: 'newPropC'
|
|
746
|
+
}
|
|
747
|
+
})
|
|
748
|
+
})
|
|
714
749
|
});
|
|
@@ -214,6 +214,10 @@ export class ResourceController<T extends StringIndexedObject> {
|
|
|
214
214
|
core: ResourceConfig,
|
|
215
215
|
parameters: Partial<T>
|
|
216
216
|
): Promise<Array<ResourceJson> | null> {
|
|
217
|
+
if (this.settings.importAndDestroy?.preventImport) {
|
|
218
|
+
throw new Error(`Type: ${this.typeId} cannot be imported`);
|
|
219
|
+
}
|
|
220
|
+
|
|
217
221
|
this.addDefaultValues(parameters);
|
|
218
222
|
await this.applyTransformParameters(parameters);
|
|
219
223
|
|
|
@@ -257,6 +261,8 @@ export class ResourceController<T extends StringIndexedObject> {
|
|
|
257
261
|
const resultParameters = { ...currentParametersArray[0], ...statefulCurrentParameters };
|
|
258
262
|
|
|
259
263
|
await this.applyTransformParameters(resultParameters, true);
|
|
264
|
+
this.removeDefaultValues(resultParameters, parameters)
|
|
265
|
+
|
|
260
266
|
return [{ core, parameters: resultParameters }];
|
|
261
267
|
}
|
|
262
268
|
|
|
@@ -373,6 +379,19 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
373
379
|
}
|
|
374
380
|
}
|
|
375
381
|
|
|
382
|
+
private removeDefaultValues(newConfig: Partial<T> | null, originalConfig: Partial<T>): void {
|
|
383
|
+
if (!newConfig) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
for (const [key, defaultValue] of Object.entries(this.parsedSettings.defaultValues)) {
|
|
388
|
+
if (defaultValue !== undefined && (newConfig[key] === defaultValue || originalConfig[key] === undefined || originalConfig[key] === null)) {
|
|
389
|
+
delete newConfig[key];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
}
|
|
394
|
+
|
|
376
395
|
private async refreshNonStatefulParameters(resourceParameters: Partial<T>): Promise<Array<Partial<T>> | null> {
|
|
377
396
|
const result = await this.resource.refresh(resourceParameters);
|
|
378
397
|
|
|
@@ -42,7 +42,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
42
42
|
* If paramA is required, then if resource1.paramA === resource2.paramA then are the same resource.
|
|
43
43
|
* If resource1.paramA !== resource1.paramA, then they are different.
|
|
44
44
|
*/
|
|
45
|
-
|
|
45
|
+
identifyingParameters?: string[]
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* If multiple copies are allowed then a matcher must be defined to match the desired
|
|
@@ -103,6 +103,13 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
103
103
|
* ```
|
|
104
104
|
*/
|
|
105
105
|
importAndDestroy?: {
|
|
106
|
+
/**
|
|
107
|
+
* Can this resources be imported? If set to false then the codifyCLI will skip over/not consider this
|
|
108
|
+
* resource valid for imports. Defaults to true.
|
|
109
|
+
*
|
|
110
|
+
* Resources that can't be imported in the core library for example are: action resources
|
|
111
|
+
*/
|
|
112
|
+
preventImport?: boolean;
|
|
106
113
|
|
|
107
114
|
/**
|
|
108
115
|
* Customize the required parameters needed to import this resource. By default, the `requiredParameters` are taken
|
|
@@ -133,7 +140,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
133
140
|
*
|
|
134
141
|
* See {@link importAndDestroy} for more information on how importing works.
|
|
135
142
|
*/
|
|
136
|
-
defaultRefreshValues?: Partial<T
|
|
143
|
+
defaultRefreshValues?: Partial<T>;
|
|
137
144
|
}
|
|
138
145
|
}
|
|
139
146
|
|
|
@@ -361,6 +368,10 @@ const ParameterTransformationDefaults: Partial<Record<ParameterSettingType, Inpu
|
|
|
361
368
|
'string': {
|
|
362
369
|
to: String,
|
|
363
370
|
from: String,
|
|
371
|
+
},
|
|
372
|
+
'boolean': {
|
|
373
|
+
to: Boolean,
|
|
374
|
+
from: Boolean,
|
|
364
375
|
}
|
|
365
376
|
}
|
|
366
377
|
|