codify-plugin-lib 1.0.141 → 1.0.143

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.
@@ -71,7 +71,7 @@ export class MessageHandler {
71
71
  const result = await SupportedRequests[message.cmd].handler(this.plugin, message.data);
72
72
  const responseValidator = this.responseValidators.get(message.cmd);
73
73
  if (responseValidator && !responseValidator(result)) {
74
- throw new Error(`Plugin: ${this.plugin}. Malformed response data: ${JSON.stringify(responseValidator.errors, null, 2)}`);
74
+ throw new Error(`Plugin: ${this.plugin.name}. Malformed response data: ${JSON.stringify(responseValidator.errors, null, 2)}. Received ${JSON.stringify(result, null, 2)}`);
75
75
  }
76
76
  process.send({
77
77
  cmd: message.cmd + '_Response',
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?.requiredParameters ?? settings.schema?.required ?? []
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];
@@ -43,8 +43,8 @@ export class Plugin {
43
43
  ?? null);
44
44
  const allowMultiple = resource.settings.allowMultiple !== undefined
45
45
  ? (typeof resource.settings.allowMultiple === 'boolean'
46
- ? { requiredParameters: schema?.required ?? [] }
47
- : { requiredParameters: resource.settings.allowMultiple.requiredParameters ?? schema?.required ?? [] }) : undefined;
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,
@@ -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
- requiredParameters?: string[];
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.
@@ -54,6 +54,10 @@ const ParameterTransformationDefaults = {
54
54
  'string': {
55
55
  to: String,
56
56
  from: String,
57
+ },
58
+ 'boolean': {
59
+ to: Boolean,
60
+ from: Boolean,
57
61
  }
58
62
  };
59
63
  export function resolveParameterTransformFn(parameter) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-lib",
3
- "version": "1.0.141",
3
+ "version": "1.0.143",
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.69",
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",
@@ -106,7 +106,7 @@ export class MessageHandler {
106
106
 
107
107
  const responseValidator = this.responseValidators.get(message.cmd);
108
108
  if (responseValidator && !responseValidator(result)) {
109
- throw new Error(`Plugin: ${this.plugin}. Malformed response data: ${JSON.stringify(responseValidator.errors, null, 2)}`)
109
+ throw new Error(`Plugin: ${this.plugin.name}. Malformed response data: ${JSON.stringify(responseValidator.errors, null, 2)}. Received ${JSON.stringify(result, null, 2)}`);
110
110
  }
111
111
 
112
112
  process.send!({
@@ -241,7 +241,7 @@ describe('Plan entity tests', () => {
241
241
  propB: { type: 'string', canModify: true },
242
242
  },
243
243
  allowMultiple: {
244
- requiredParameters: ['propA']
244
+ identifyingParameters: ['propA']
245
245
  }
246
246
  }
247
247
  }
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?.requiredParameters ?? (settings.schema?.required as string[]) ?? []
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
  });
@@ -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
- ? { requiredParameters: schema?.required ?? [] }
78
- : { requiredParameters: resource.settings.allowMultiple.requiredParameters ?? schema?.required ?? [] }
77
+ ? { identifyingParameters: schema?.required ?? [] }
78
+ : { identifyingParameters: resource.settings.allowMultiple.identifyingParameters ?? schema?.required ?? [] }
79
79
  ) : undefined
80
80
 
81
81
  return {
@@ -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
- requiredParameters?: string[]
45
+ identifyingParameters?: string[]
46
46
 
47
47
  /**
48
48
  * If multiple copies are allowed then a matcher must be defined to match the desired
@@ -368,6 +368,10 @@ const ParameterTransformationDefaults: Partial<Record<ParameterSettingType, Inpu
368
368
  'string': {
369
369
  to: String,
370
370
  from: String,
371
+ },
372
+ 'boolean': {
373
+ to: Boolean,
374
+ from: Boolean,
371
375
  }
372
376
  }
373
377