codify-plugin-lib 1.0.49 → 1.0.51

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.
@@ -1,26 +1,26 @@
1
1
  import { Plan } from './plan.js';
2
2
  import { StringIndexedObject } from 'codify-schemas';
3
- export interface StatefulParameterConfiguration<T> {
3
+ export interface StatefulParameterOptions<T> {
4
4
  name: keyof T;
5
5
  isEqual?: (desired: any, current: any) => boolean;
6
6
  disableStatelessModeArrayFiltering?: boolean;
7
7
  }
8
- export interface ArrayStatefulParameterConfiguration<T> extends StatefulParameterConfiguration<T> {
8
+ export interface ArrayStatefulParameterOptions<T> extends StatefulParameterOptions<T> {
9
9
  isEqual?: (desired: any[], current: any[]) => boolean;
10
10
  isElementEqual?: (desired: any, current: any) => boolean;
11
11
  }
12
12
  export declare abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
13
13
  readonly name: keyof T;
14
- readonly configuration: StatefulParameterConfiguration<T>;
15
- protected constructor(configuration: StatefulParameterConfiguration<T>);
14
+ readonly options: StatefulParameterOptions<T>;
15
+ protected constructor(options: StatefulParameterOptions<T>);
16
16
  abstract refresh(desired: V | null): Promise<V | null>;
17
17
  abstract applyAdd(valueToAdd: V, plan: Plan<T>): Promise<void>;
18
18
  abstract applyModify(newValue: V, previousValue: V, allowDeletes: boolean, plan: Plan<T>): Promise<void>;
19
19
  abstract applyRemove(valueToRemove: V, plan: Plan<T>): Promise<void>;
20
20
  }
21
21
  export declare abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any> {
22
- configuration: ArrayStatefulParameterConfiguration<T>;
23
- constructor(configuration: ArrayStatefulParameterConfiguration<T>);
22
+ options: ArrayStatefulParameterOptions<T>;
23
+ constructor(options: ArrayStatefulParameterOptions<T>);
24
24
  applyAdd(valuesToAdd: V[], plan: Plan<T>): Promise<void>;
25
25
  applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void>;
26
26
  applyRemove(valuesToRemove: V[], plan: Plan<T>): Promise<void>;
@@ -1,16 +1,16 @@
1
1
  export class StatefulParameter {
2
2
  name;
3
- configuration;
4
- constructor(configuration) {
5
- this.name = configuration.name;
6
- this.configuration = configuration;
3
+ options;
4
+ constructor(options) {
5
+ this.name = options.name;
6
+ this.options = options;
7
7
  }
8
8
  }
9
9
  export class ArrayStatefulParameter extends StatefulParameter {
10
- configuration;
11
- constructor(configuration) {
12
- super(configuration);
13
- this.configuration = configuration;
10
+ options;
11
+ constructor(options) {
12
+ super(options);
13
+ this.options = options;
14
14
  }
15
15
  async applyAdd(valuesToAdd, plan) {
16
16
  for (const value of valuesToAdd) {
@@ -18,16 +18,16 @@ export class ArrayStatefulParameter extends StatefulParameter {
18
18
  }
19
19
  }
20
20
  async applyModify(newValues, previousValues, allowDeletes, plan) {
21
- const configuration = this.configuration;
21
+ const options = this.options;
22
22
  const valuesToAdd = newValues.filter((n) => !previousValues.some((p) => {
23
- if ((configuration).isElementEqual) {
24
- return configuration.isElementEqual(n, p);
23
+ if (options.isElementEqual) {
24
+ return options.isElementEqual(n, p);
25
25
  }
26
26
  return n === p;
27
27
  }));
28
28
  const valuesToRemove = previousValues.filter((p) => !newValues.some((n) => {
29
- if ((configuration).isElementEqual) {
30
- return configuration.isElementEqual(n, p);
29
+ if (options.isElementEqual) {
30
+ return options.isElementEqual(n, p);
31
31
  }
32
32
  return n === p;
33
33
  }));
@@ -0,0 +1,4 @@
1
+ import { StringIndexedObject } from 'codify-schemas';
2
+ export declare abstract class TransformParameter<T extends StringIndexedObject> {
3
+ abstract transform(value: any): Promise<Partial<T>>;
4
+ }
@@ -0,0 +1,2 @@
1
+ export class TransformParameter {
2
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-lib",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -1,5 +1,5 @@
1
1
  import { ParameterOperation, ResourceOperation, StringIndexedObject } from 'codify-schemas';
2
- import { ParameterConfiguration } from './plan-types.js';
2
+ import { ParameterOptions } from './plan-types.js';
3
3
 
4
4
  export interface ParameterChange<T extends StringIndexedObject> {
5
5
  name: keyof T & string;
@@ -61,12 +61,12 @@ export class ChangeSet<T extends StringIndexedObject> {
61
61
  static calculateParameterChangeSet<T extends StringIndexedObject>(
62
62
  desired: T | null,
63
63
  current: T | null,
64
- options: { statefulMode: boolean, parameterConfigurations?: Record<keyof T, ParameterConfiguration> },
64
+ options: { statefulMode: boolean, parameterOptions?: Record<keyof T, ParameterOptions> },
65
65
  ): ParameterChange<T>[] {
66
66
  if (options.statefulMode) {
67
- return ChangeSet.calculateStatefulModeChangeSet(desired, current, options.parameterConfigurations);
67
+ return ChangeSet.calculateStatefulModeChangeSet(desired, current, options.parameterOptions);
68
68
  } else {
69
- return ChangeSet.calculateStatelessModeChangeSet(desired, current, options.parameterConfigurations);
69
+ return ChangeSet.calculateStatelessModeChangeSet(desired, current, options.parameterOptions);
70
70
  }
71
71
  }
72
72
 
@@ -88,10 +88,10 @@ export class ChangeSet<T extends StringIndexedObject> {
88
88
  static isSame(
89
89
  desired: unknown,
90
90
  current: unknown,
91
- configuration?: ParameterConfiguration,
91
+ options?: ParameterOptions,
92
92
  ): boolean {
93
- if (configuration?.isEqual) {
94
- return configuration.isEqual(desired, current);
93
+ if (options?.isEqual) {
94
+ return options.isEqual(desired, current);
95
95
  }
96
96
 
97
97
  if (Array.isArray(desired) && Array.isArray(current)) {
@@ -102,9 +102,9 @@ export class ChangeSet<T extends StringIndexedObject> {
102
102
  return false;
103
103
  }
104
104
 
105
- if (configuration?.isElementEqual) {
105
+ if (options?.isElementEqual) {
106
106
  return sortedDesired.every((value, index) =>
107
- configuration.isElementEqual!(value, sortedCurrent[index])
107
+ options.isElementEqual!(value, sortedCurrent[index])
108
108
  );
109
109
  }
110
110
 
@@ -119,7 +119,7 @@ export class ChangeSet<T extends StringIndexedObject> {
119
119
  private static calculateStatefulModeChangeSet<T extends StringIndexedObject>(
120
120
  desired: T | null,
121
121
  current: T | null,
122
- parameterConfigurations?: Record<keyof T, ParameterConfiguration>,
122
+ parameterOptions?: Record<keyof T, ParameterOptions>,
123
123
  ): ParameterChange<T>[] {
124
124
  const parameterChangeSet = new Array<ParameterChange<T>>();
125
125
 
@@ -139,7 +139,7 @@ export class ChangeSet<T extends StringIndexedObject> {
139
139
  continue;
140
140
  }
141
141
 
142
- if (!ChangeSet.isSame(_desired[k], _current[k], parameterConfigurations?.[k])) {
142
+ if (!ChangeSet.isSame(_desired[k], _current[k], parameterOptions?.[k])) {
143
143
  parameterChangeSet.push({
144
144
  name: k,
145
145
  previousValue: v,
@@ -184,7 +184,7 @@ export class ChangeSet<T extends StringIndexedObject> {
184
184
  private static calculateStatelessModeChangeSet<T extends StringIndexedObject>(
185
185
  desired: T | null,
186
186
  current: T | null,
187
- parameterConfigurations?: Record<keyof T, ParameterConfiguration>,
187
+ parameterOptions?: Record<keyof T, ParameterOptions>,
188
188
  ): ParameterChange<T>[] {
189
189
  const parameterChangeSet = new Array<ParameterChange<T>>();
190
190
 
@@ -203,7 +203,7 @@ export class ChangeSet<T extends StringIndexedObject> {
203
203
  continue;
204
204
  }
205
205
 
206
- if (!ChangeSet.isSame(_desired[k], _current[k], parameterConfigurations?.[k])) {
206
+ if (!ChangeSet.isSame(_desired[k], _current[k], parameterOptions?.[k])) {
207
207
  parameterChangeSet.push({
208
208
  name: k,
209
209
  previousValue: _current[k],
@@ -3,7 +3,7 @@ import { ResourceOperation } from 'codify-schemas';
3
3
  /**
4
4
  * Customize properties for specific parameters. This will alter the way the library process changes to the parameter.
5
5
  */
6
- export interface ParameterConfiguration {
6
+ export interface ParameterOptions {
7
7
  /**
8
8
  * Chose if the resource should be re-created or modified if this parameter is changed. Defaults to re-create.
9
9
  */
@@ -20,7 +20,7 @@ export interface ParameterConfiguration {
20
20
  isStatefulParameter?: boolean;
21
21
  }
22
22
 
23
- export interface PlanConfiguration<T> {
23
+ export interface PlanOptions<T> {
24
24
  statefulMode: boolean;
25
- parameterConfigurations?: Record<keyof T, ParameterConfiguration>;
25
+ parameterOptions?: Record<keyof T, ParameterOptions>;
26
26
  }
@@ -140,7 +140,7 @@ function createResource(): Resource<any> {
140
140
  constructor() {
141
141
  super({
142
142
  type: 'type',
143
- parameterConfigurations: {
143
+ parameterOptions: {
144
144
  propA: {
145
145
  defaultValue: 'defaultA'
146
146
  }
@@ -8,7 +8,7 @@ import {
8
8
  StringIndexedObject,
9
9
  } from 'codify-schemas';
10
10
  import { randomUUID } from 'crypto';
11
- import { ParameterConfiguration, PlanConfiguration } from './plan-types.js';
11
+ import { ParameterOptions, PlanOptions } from './plan-types.js';
12
12
 
13
13
  export class Plan<T extends StringIndexedObject> {
14
14
  id: string;
@@ -25,11 +25,11 @@ export class Plan<T extends StringIndexedObject> {
25
25
  desiredParameters: Partial<T> | null,
26
26
  currentParameters: Partial<T> | null,
27
27
  resourceMetadata: ResourceConfig,
28
- configuration: PlanConfiguration<T>
28
+ options: PlanOptions<T>
29
29
  ): Plan<T> {
30
- const parameterConfigurations = configuration.parameterConfigurations ?? {} as Record<keyof T, ParameterConfiguration>;
30
+ const parameterOptions = options.parameterOptions ?? {} as Record<keyof T, ParameterOptions>;
31
31
  const statefulParameterNames = new Set(
32
- [...Object.entries(parameterConfigurations)]
32
+ [...Object.entries(parameterOptions)]
33
33
  .filter(([k, v]) => v.isStatefulParameter)
34
34
  .map(([k, v]) => k)
35
35
  );
@@ -40,7 +40,7 @@ export class Plan<T extends StringIndexedObject> {
40
40
  const parameterChangeSet = ChangeSet.calculateParameterChangeSet(
41
41
  desiredParameters,
42
42
  currentParameters,
43
- { statefulMode: configuration.statefulMode, parameterConfigurations }
43
+ { statefulMode: options.statefulMode, parameterOptions }
44
44
  );
45
45
 
46
46
  let resourceOperation: ResourceOperation;
@@ -55,8 +55,8 @@ export class Plan<T extends StringIndexedObject> {
55
55
  let newOperation: ResourceOperation;
56
56
  if (statefulParameterNames.has(curr.name)) {
57
57
  newOperation = ResourceOperation.MODIFY // All stateful parameters are modify only
58
- } else if (parameterConfigurations[curr.name]?.planOperation) {
59
- newOperation = parameterConfigurations[curr.name].planOperation!;
58
+ } else if (parameterOptions[curr.name]?.planOperation) {
59
+ newOperation = parameterOptions[curr.name].planOperation!;
60
60
  } else {
61
61
  newOperation = ResourceOperation.RECREATE; // Default to Re-create. Should handle the majority of use cases
62
62
  }
@@ -42,7 +42,7 @@ export class Plugin {
42
42
  }
43
43
 
44
44
  const { parameters } = splitUserConfig(config);
45
- const validateResult = await this.resources.get(config.type)!.validate(parameters);
45
+ const validateResult = await this.resources.get(config.type)!.validateResource(parameters);
46
46
 
47
47
  validationResults.push({
48
48
  ...validateResult,
@@ -0,0 +1,156 @@
1
+ import { StringIndexedObject } from 'codify-schemas';
2
+ import { StatefulParameter } from './stateful-parameter.js';
3
+ import { TransformParameter } from './transform-parameter.js';
4
+ import { ResourceParameterOptions } from './resource-types.js';
5
+ import { ParameterOptions } from './plan-types.js';
6
+
7
+ export interface ResourceOptions<T extends StringIndexedObject> {
8
+
9
+ /**
10
+ * The id of the resource.
11
+ */
12
+ type: string;
13
+
14
+ /**
15
+ * Schema to validate user configs with. Must be in the format JSON Schema 2020-12
16
+ */
17
+ schema?: unknown
18
+
19
+ /**
20
+ * If true, statefulParameter.applyRemove() will be called before resource destruction.
21
+ * Defaults to false.
22
+ */
23
+ callStatefulParameterRemoveOnDestroy?: boolean,
24
+
25
+ /**
26
+ * An array of type ids of resources that this resource depends on. This affects the order in which the resources are
27
+ * planned and applied.
28
+ */
29
+ dependencies?: string[];
30
+
31
+ /**
32
+ * Additional options for configuring parameters.
33
+ */
34
+ parameterOptions?: Partial<Record<keyof T,
35
+ ResourceParameterOptions
36
+ | ResourceStatefulParameterOptions<T>
37
+ | ResourceTransformParameterOptions<T>
38
+ >>
39
+ }
40
+
41
+ export interface ResourceStatefulParameterOptions<T extends StringIndexedObject> {
42
+ statefulParameter: StatefulParameter<T, T[keyof T]>;
43
+ order?: number;
44
+ }
45
+
46
+ export interface ResourceTransformParameterOptions<T extends StringIndexedObject> {
47
+ transformParameter: TransformParameter<T>;
48
+ order?: number;
49
+ }
50
+
51
+ export class ResourceOptionsParser<T extends StringIndexedObject> {
52
+ private options: ResourceOptions<T>;
53
+
54
+ constructor(options: ResourceOptions<T>) {
55
+ this.options = options;
56
+ }
57
+
58
+ get statefulParameters(): Map<keyof T, StatefulParameter<T, T[keyof T]>> {
59
+ const statefulParameters = Object.entries(this.options.parameterOptions ?? {})
60
+ .filter(([, p]) => p?.hasOwnProperty('statefulParameter'))
61
+ .map(([k, v]) => [k, v as ResourceStatefulParameterOptions<T>] as const)
62
+ .map(([k, v]) => [k, v.statefulParameter] as const)
63
+
64
+ return new Map(statefulParameters);
65
+ }
66
+
67
+ get transformParameters(): Map<keyof T, TransformParameter<T>> {
68
+ const transformParameters =
69
+ Object.entries(this.options.parameterOptions ?? {})
70
+ .filter(([, p]) => p?.hasOwnProperty('transformParameter'))
71
+ .map(([k, v]) => [k, v as ResourceTransformParameterOptions<T>] as const)
72
+ .map(([k, v]) => [k, v.transformParameter] as const)
73
+
74
+ return new Map(transformParameters);
75
+ }
76
+
77
+ get resourceParameters(): Map<keyof T, ResourceParameterOptions> {
78
+ const resourceParameters =
79
+ Object.entries(this.options.parameterOptions ?? {})
80
+ .filter(([, p]) => !(p?.hasOwnProperty('statefulParameter') || p?.hasOwnProperty('transformParameter')))
81
+ .map(([k, v]) => [k, v as ResourceParameterOptions] as const)
82
+
83
+ return new Map(resourceParameters);
84
+ }
85
+
86
+ get changeSetParameterOptions(): Record<keyof T, ParameterOptions> {
87
+ const resourceParameters = Object.fromEntries(
88
+ [...this.resourceParameters.entries()]
89
+ .map(([name, value]) => ([name, { ...value, isStatefulParameter: false }]))
90
+ );
91
+
92
+ const statefulParameters = [...this.statefulParameters.entries()]
93
+ ?.reduce((obj, sp) => {
94
+ return {
95
+ ...obj,
96
+ [sp[0]]: {
97
+ ...sp[1].options,
98
+ isStatefulParameter: true,
99
+ }
100
+ }
101
+ }, {} as Record<keyof T, ParameterOptions>)
102
+
103
+ return {
104
+ ...resourceParameters,
105
+ ...statefulParameters,
106
+ }
107
+ }
108
+
109
+ get defaultValues(): Partial<Record<keyof T, unknown>> {
110
+ if (!this.options.parameterOptions) {
111
+ return {};
112
+ }
113
+
114
+ return Object.fromEntries(
115
+ [...this.resourceParameters.entries()]
116
+ .filter(([, rp]) => rp.defaultValue !== undefined)
117
+ .map(([name, rp]) => [name, rp.defaultValue])
118
+ ) as Partial<Record<keyof T, unknown>>;
119
+ }
120
+
121
+ get statefulParameterOrder(): Map<keyof T, number> {
122
+ const entries = Object.entries(this.options.parameterOptions ?? {})
123
+ .filter(([, v]) => v?.hasOwnProperty('statefulParameter'))
124
+ .map(([k, v]) => [k, v as ResourceStatefulParameterOptions<T>] as const)
125
+
126
+ const orderedEntries = entries.filter(([, v]) => v.order !== undefined)
127
+ const unorderedEntries = entries.filter(([, v]) => v.order === undefined)
128
+
129
+ orderedEntries.sort((a, b) => a[1].order! - b[1].order!);
130
+
131
+ const resultArray = [
132
+ ...orderedEntries.map(([k]) => k),
133
+ ...unorderedEntries.map(([k]) => k)
134
+ ]
135
+
136
+ return new Map(resultArray.map((key, idx) => [key, idx]));
137
+ }
138
+
139
+ get transformParameterOrder(): Map<keyof T, number> {
140
+ const entries = Object.entries(this.options.parameterOptions ?? {})
141
+ .filter(([, v]) => v?.hasOwnProperty('transformParameter'))
142
+ .map(([k, v]) => [k, v as ResourceTransformParameterOptions<T>] as const)
143
+
144
+ const orderedEntries = entries.filter(([, v]) => v.order !== undefined)
145
+ const unorderedEntries = entries.filter(([, v]) => v.order === undefined)
146
+
147
+ orderedEntries.sort((a, b) => a[1].order! - b[1].order!);
148
+
149
+ const resultArray = [
150
+ ...orderedEntries.map(([k]) => k),
151
+ ...unorderedEntries.map(([k]) => k)
152
+ ]
153
+
154
+ return new Map(resultArray.map((key, idx) => [key, idx]));
155
+ }
156
+ }