codify-plugin-lib 1.0.31 → 1.0.33

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,11 +1,11 @@
1
1
  import { Resource } from './resource.js';
2
- import { ApplyRequestData, PlanRequestData, PlanResponseData, ResourceConfig, ValidateRequestData, ValidateResponseData } from 'codify-schemas';
2
+ import { ApplyRequestData, InitializeResponseData, PlanRequestData, PlanResponseData, ResourceConfig, ValidateRequestData, ValidateResponseData } from 'codify-schemas';
3
3
  import { Plan } from './plan.js';
4
4
  export declare class Plugin {
5
5
  resources: Map<string, Resource<ResourceConfig>>;
6
6
  planStorage: Map<string, Plan<ResourceConfig>>;
7
7
  constructor(resources: Map<string, Resource<ResourceConfig>>);
8
- onInitialize(): Promise<void>;
8
+ initialize(): Promise<InitializeResponseData>;
9
9
  validate(data: ValidateRequestData): Promise<ValidateResponseData>;
10
10
  plan(data: PlanRequestData): Promise<PlanResponseData>;
11
11
  apply(data: ApplyRequestData): Promise<void>;
@@ -5,17 +5,34 @@ export class Plugin {
5
5
  this.resources = resources;
6
6
  this.planStorage = new Map();
7
7
  }
8
- async onInitialize() {
8
+ async initialize() {
9
+ for (const resource of this.resources.values()) {
10
+ await resource.onInitialize();
11
+ }
12
+ return {
13
+ resourceDefinitions: [...this.resources.values()]
14
+ .map((r) => ({
15
+ type: r.getTypeId(),
16
+ dependencies: r.getDependencyTypeIds(),
17
+ }))
18
+ };
9
19
  }
10
20
  async validate(data) {
21
+ const totalErrors = [];
11
22
  for (const config of data.configs) {
12
23
  if (!this.resources.has(config.type)) {
13
24
  throw new Error(`Resource type not found: ${config.type}`);
14
25
  }
15
- await this.resources.get(config.type).validate(config);
26
+ const error = await this.resources.get(config.type).validate(config);
27
+ if (error) {
28
+ totalErrors.push(error);
29
+ }
16
30
  }
17
31
  await this.crossValidateResources(data.configs);
18
- return null;
32
+ return {
33
+ isValid: true,
34
+ errors: totalErrors.length !== 0 ? totalErrors : null,
35
+ };
19
36
  }
20
37
  async plan(data) {
21
38
  if (!this.resources.has(data.type)) {
@@ -7,11 +7,12 @@ export declare abstract class Resource<T extends ResourceConfig> {
7
7
  private statefulParameters;
8
8
  constructor(dependencies?: Resource<any>[]);
9
9
  abstract getTypeId(): string;
10
+ getDependencyTypeIds(): string[];
10
11
  onInitialize(): Promise<void>;
11
12
  plan(desiredConfig: T): Promise<Plan<T>>;
12
13
  apply(plan: Plan<T>): Promise<void>;
13
14
  protected registerStatefulParameter(parameter: StatefulParameter<T, keyof T>): void;
14
- abstract validate(config: unknown): Promise<boolean>;
15
+ abstract validate(config: unknown): Promise<string | undefined>;
15
16
  abstract getCurrentConfig(desiredConfig: T): Promise<T | null>;
16
17
  abstract calculateOperation(change: ParameterChange): ResourceOperation.MODIFY | ResourceOperation.RECREATE;
17
18
  abstract applyCreate(plan: Plan<T>): Promise<void>;
@@ -7,9 +7,11 @@ export class Resource {
7
7
  constructor(dependencies = []) {
8
8
  this.dependencies = dependencies;
9
9
  }
10
+ getDependencyTypeIds() {
11
+ return this.dependencies.map((d) => d.getTypeId());
12
+ }
10
13
  async onInitialize() { }
11
14
  async plan(desiredConfig) {
12
- await this.validate(desiredConfig);
13
15
  const currentConfig = await this.getCurrentConfig(desiredConfig);
14
16
  if (!currentConfig) {
15
17
  return Plan.create(ChangeSet.createForNullCurrentConfig(desiredConfig), desiredConfig);
package/dist/index.js CHANGED
@@ -7,7 +7,6 @@ export * from './entities/stateful-parameter.js';
7
7
  export * from './utils/test-utils.js';
8
8
  export * from './utils/utils.js';
9
9
  export async function runPlugin(plugin) {
10
- await plugin.onInitialize();
11
10
  const messageHandler = new MessageHandler(plugin);
12
11
  process.on('message', (message) => messageHandler.onMessage(message));
13
12
  }
@@ -1,7 +1,12 @@
1
1
  import addFormats from 'ajv-formats';
2
- import { IpcMessageSchema, ResourceSchema, ValidateRequestDataSchema, ValidateResponseDataSchema, MessageStatus, PlanRequestDataSchema, PlanResponseDataSchema, ApplyRequestDataSchema, ApplyResponseDataSchema } from 'codify-schemas';
2
+ import { ApplyRequestDataSchema, ApplyResponseDataSchema, InitializeRequestDataSchema, InitializeResponseDataSchema, IpcMessageSchema, MessageStatus, PlanRequestDataSchema, PlanResponseDataSchema, ResourceSchema, ValidateRequestDataSchema, ValidateResponseDataSchema } from 'codify-schemas';
3
3
  import Ajv2020 from 'ajv/dist/2020.js';
4
4
  const SupportedRequests = {
5
+ 'initialize': {
6
+ requestValidator: InitializeRequestDataSchema,
7
+ responseValidator: InitializeResponseDataSchema,
8
+ handler: async (plugin) => plugin.initialize()
9
+ },
5
10
  'validate': {
6
11
  requestValidator: ValidateRequestDataSchema,
7
12
  responseValidator: ValidateResponseDataSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-lib",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -14,7 +14,7 @@
14
14
  "dependencies": {
15
15
  "ajv": "^8.12.0",
16
16
  "ajv-formats": "^2.1.1",
17
- "codify-schemas": "1.0.21",
17
+ "codify-schemas": "1.0.28",
18
18
  "@npmcli/promise-spawn": "^7.0.1"
19
19
  },
20
20
  "devDependencies": {
@@ -1,6 +1,7 @@
1
1
  import { Resource } from './resource.js';
2
2
  import {
3
3
  ApplyRequestData,
4
+ InitializeResponseData,
4
5
  PlanRequestData,
5
6
  PlanResponseData,
6
7
  ResourceConfig,
@@ -18,21 +19,38 @@ export class Plugin {
18
19
  this.planStorage = new Map();
19
20
  }
20
21
 
21
- async onInitialize(): Promise<void> {
22
+ async initialize(): Promise<InitializeResponseData> {
23
+ for (const resource of this.resources.values()) {
24
+ await resource.onInitialize();
25
+ }
22
26
 
27
+ return {
28
+ resourceDefinitions: [...this.resources.values()]
29
+ .map((r) => ({
30
+ type: r.getTypeId(),
31
+ dependencies: r.getDependencyTypeIds(),
32
+ }))
33
+ }
23
34
  }
24
35
 
25
36
  async validate(data: ValidateRequestData): Promise<ValidateResponseData> {
37
+ const totalErrors = [];
26
38
  for (const config of data.configs) {
27
39
  if (!this.resources.has(config.type)) {
28
40
  throw new Error(`Resource type not found: ${config.type}`);
29
41
  }
30
42
 
31
- await this.resources.get(config.type)!.validate(config);
43
+ const error = await this.resources.get(config.type)!.validate(config);
44
+ if (error) {
45
+ totalErrors.push(error);
46
+ }
32
47
  }
33
48
 
34
49
  await this.crossValidateResources(data.configs);
35
- return null;
50
+ return {
51
+ isValid: true,
52
+ errors: totalErrors.length !== 0 ? totalErrors : null,
53
+ }
36
54
  }
37
55
 
38
56
  async plan(data: PlanRequestData): Promise<PlanResponseData> {
@@ -1,10 +1,10 @@
1
- import { Resource } from './resource';
1
+ import { Resource } from './resource.js';
2
2
  import { ParameterOperation, ResourceConfig, ResourceOperation } from 'codify-schemas';
3
- import { ChangeSet, ParameterChange } from './change-set';
3
+ import { ChangeSet, ParameterChange } from './change-set.js';
4
4
  import { spy } from 'sinon';
5
- import { Plan } from './plan';
6
- import { StatefulParameter } from './stateful-parameter';
7
- import { describe, it, expect } from 'vitest'
5
+ import { Plan } from './plan.js';
6
+ import { StatefulParameter } from './stateful-parameter.js';
7
+ import { describe, expect, it } from 'vitest'
8
8
 
9
9
  class TestResource extends Resource<TestConfig> {
10
10
  applyCreate(plan: Plan<TestConfig>): Promise<void> {
@@ -27,12 +27,12 @@ class TestResource extends Resource<TestConfig> {
27
27
  return ResourceOperation.MODIFY;
28
28
  }
29
29
 
30
- async getCurrentConfig(): Promise<TestConfig> {
31
- return Promise.resolve(undefined);
30
+ async getCurrentConfig(): Promise<TestConfig | null> {
31
+ return null;
32
32
  }
33
33
 
34
- validate(config: ResourceConfig): Promise<boolean> {
35
- return Promise.resolve(false);
34
+ async validate(config: ResourceConfig): Promise<string | undefined> {
35
+ return undefined;
36
36
  }
37
37
 
38
38
  getTypeId(): string {
@@ -127,7 +127,7 @@ describe('Resource tests', () => {
127
127
  return ResourceOperation.MODIFY;
128
128
  }
129
129
 
130
- async getCurrentConfig(): Promise<TestConfig> {
130
+ async getCurrentConfig(): Promise<TestConfig | null> {
131
131
  return null;
132
132
  }
133
133
  }
@@ -230,8 +230,8 @@ describe('Resource tests', () => {
230
230
  return Promise.resolve(undefined);
231
231
  }
232
232
 
233
- getCurrent(): Promise<TestConfig["propA"]> {
234
- return Promise.resolve(undefined);
233
+ async getCurrent(): Promise<TestConfig["propA"]> {
234
+ return '';
235
235
  }
236
236
  }
237
237
 
@@ -298,8 +298,8 @@ describe('Resource tests', () => {
298
298
  return Promise.resolve(undefined);
299
299
  }
300
300
 
301
- getCurrent(): Promise<TestConfig["propA"]> {
302
- return Promise.resolve(undefined);
301
+ async getCurrent(): Promise<TestConfig["propA"]> {
302
+ return '';
303
303
  }
304
304
  }
305
305
 
@@ -13,13 +13,15 @@ export abstract class Resource<T extends ResourceConfig> {
13
13
 
14
14
  abstract getTypeId(): string;
15
15
 
16
+ getDependencyTypeIds(): string[] {
17
+ return this.dependencies.map((d) => d.getTypeId())
18
+ }
19
+
16
20
  async onInitialize(): Promise<void> {}
17
21
 
18
22
  // TODO: Add state in later.
19
23
  // Calculate change set from current config -> state -> desired in the future
20
24
  async plan(desiredConfig: T): Promise<Plan<T>> {
21
- await this.validate(desiredConfig);
22
-
23
25
  const currentConfig = await this.getCurrentConfig(desiredConfig);
24
26
  if (!currentConfig) {
25
27
  return Plan.create(ChangeSet.createForNullCurrentConfig(desiredConfig), desiredConfig);
@@ -114,7 +116,7 @@ export abstract class Resource<T extends ResourceConfig> {
114
116
  this.statefulParameters.set(parameter.name as string, parameter);
115
117
  }
116
118
 
117
- abstract validate(config: unknown): Promise<boolean>;
119
+ abstract validate(config: unknown): Promise<string | undefined>;
118
120
 
119
121
  abstract getCurrentConfig(desiredConfig: T): Promise<T | null>;
120
122
 
package/src/index.ts CHANGED
@@ -11,8 +11,6 @@ export * from './utils/test-utils.js'
11
11
  export * from './utils/utils.js'
12
12
 
13
13
  export async function runPlugin(plugin: Plugin) {
14
- await plugin.onInitialize();
15
-
16
14
  const messageHandler = new MessageHandler(plugin);
17
15
  process.on('message', (message) => messageHandler.onMessage(message))
18
16
  }
@@ -1,20 +1,27 @@
1
1
  import { Plugin } from '../entities/plugin.js';
2
2
  import addFormats from 'ajv-formats';
3
3
  import {
4
+ ApplyRequestDataSchema,
5
+ ApplyResponseDataSchema,
6
+ InitializeRequestDataSchema,
7
+ InitializeResponseDataSchema,
4
8
  IpcMessage,
5
9
  IpcMessageSchema,
6
- ResourceSchema,
7
- ValidateRequestDataSchema,
8
- ValidateResponseDataSchema,
9
10
  MessageStatus,
10
11
  PlanRequestDataSchema,
11
12
  PlanResponseDataSchema,
12
- ApplyRequestDataSchema,
13
- ApplyResponseDataSchema
13
+ ResourceSchema,
14
+ ValidateRequestDataSchema,
15
+ ValidateResponseDataSchema
14
16
  } from 'codify-schemas';
15
17
  import Ajv2020, { SchemaObject, ValidateFunction } from 'ajv/dist/2020.js';
16
18
 
17
19
  const SupportedRequests: Record<string, { requestValidator: SchemaObject; responseValidator: SchemaObject; handler: (plugin: Plugin, data: any) => Promise<unknown> }> = {
20
+ 'initialize': {
21
+ requestValidator: InitializeRequestDataSchema,
22
+ responseValidator: InitializeResponseDataSchema,
23
+ handler: async (plugin: Plugin) => plugin.initialize()
24
+ },
18
25
  'validate': {
19
26
  requestValidator: ValidateRequestDataSchema,
20
27
  responseValidator: ValidateResponseDataSchema,