@kapeta/local-cluster-service 0.19.1 → 0.19.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.19.2](https://github.com/kapetacom/local-cluster-service/compare/v0.19.1...v0.19.2) (2023-09-05)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Control boot order and reload code gen targets when repo changes ([#68](https://github.com/kapetacom/local-cluster-service/issues/68)) ([5557259](https://github.com/kapetacom/local-cluster-service/commit/5557259dda10f509a2b8cc45c0b4a4631e1d975a))
7
+
1
8
  ## [0.19.1](https://github.com/kapetacom/local-cluster-service/compare/v0.19.0...v0.19.1) (2023-09-03)
2
9
 
3
10
 
package/dist/cjs/index.js CHANGED
@@ -28,6 +28,7 @@ const repositoryManager_1 = require("./src/repositoryManager");
28
28
  const commandLineUtils_1 = require("./src/utils/commandLineUtils");
29
29
  const DefaultProviderInstaller_1 = require("./src/utils/DefaultProviderInstaller");
30
30
  const authManager_1 = require("./src/authManager");
31
+ const codeGeneratorManager_1 = require("./src/codeGeneratorManager");
31
32
  let currentServer = null;
32
33
  function createServer() {
33
34
  const app = (0, express_1.default)();
@@ -109,6 +110,7 @@ exports.default = {
109
110
  console.error('Could not ping docker runtime: ' + e.toString() + '. Make sure docker is running and working.');
110
111
  }
111
112
  await DefaultProviderInstaller_1.defaultProviderInstaller.checkForDefault();
113
+ await codeGeneratorManager_1.codeGeneratorManager.initialize();
112
114
  const clusterPort = storageService_1.storageService.get('cluster', 'port');
113
115
  if (clusterPort) {
114
116
  clusterService_1.clusterService.setClusterServicePort(clusterPort);
@@ -1,5 +1,7 @@
1
+ /// <reference types="node" />
1
2
  import { SourceOfChange } from './types';
2
- export declare class RepositoryWatcher {
3
+ import { EventEmitter } from 'node:events';
4
+ export declare class RepositoryWatcher extends EventEmitter {
3
5
  private watcher?;
4
6
  private disabled;
5
7
  private readonly baseDir;
@@ -13,8 +13,9 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
13
13
  const lodash_1 = __importDefault(require("lodash"));
14
14
  const socketManager_1 = require("./socketManager");
15
15
  const cacheManager_1 = require("./cacheManager");
16
+ const node_events_1 = require("node:events");
16
17
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
17
- class RepositoryWatcher {
18
+ class RepositoryWatcher extends node_events_1.EventEmitter {
18
19
  watcher;
19
20
  disabled = false;
20
21
  baseDir;
@@ -22,6 +23,7 @@ class RepositoryWatcher {
22
23
  symbolicLinks = {};
23
24
  sourceOfChange = new Map();
24
25
  constructor() {
26
+ super();
25
27
  this.baseDir = local_cluster_config_1.default.getRepositoryBasedir();
26
28
  }
27
29
  setDisabled(disabled) {
@@ -204,6 +206,7 @@ class RepositoryWatcher {
204
206
  this.allDefinitions = newDefinitions;
205
207
  //console.log('Asset changed', payload);
206
208
  socketManager_1.socketManager.emitGlobal('asset-change', payload);
209
+ this.emit('change', payload);
207
210
  cacheManager_1.cacheManager.flush();
208
211
  }
209
212
  async exists(path) {
@@ -234,8 +237,13 @@ class RepositoryWatcher {
234
237
  try {
235
238
  // Make sure we're not watching the symlink target
236
239
  await this.removeSymlinkTarget(path);
237
- const stat = await fs_extra_1.default.lstat(path);
238
- if (stat.isSymbolicLink()) {
240
+ let symbolicLink = false;
241
+ try {
242
+ const stat = await fs_extra_1.default.lstat(path);
243
+ symbolicLink = stat.isSymbolicLink();
244
+ }
245
+ catch (e) { }
246
+ if (symbolicLink) {
239
247
  const realPath = `${await fs_extra_1.default.realpath(path)}/kapeta.yml`;
240
248
  if (await this.exists(realPath)) {
241
249
  //console.log('Watching symlink target %s => %s', path, realPath);
@@ -1,6 +1,8 @@
1
1
  import { BlockDefinition } from '@kapeta/schemas';
2
2
  declare class CodeGeneratorManager {
3
+ private ensureLanguageTargetInRegistry;
3
4
  reload(): Promise<void>;
5
+ initialize(): Promise<void>;
4
6
  canGenerateCode(yamlContent: BlockDefinition): Promise<boolean>;
5
7
  generate(yamlFile: string, yamlContent: BlockDefinition): Promise<void>;
6
8
  }
@@ -7,27 +7,51 @@ exports.codeGeneratorManager = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const codegen_1 = require("@kapeta/codegen");
9
9
  const definitionsManager_1 = require("./definitionsManager");
10
+ const assetManager_1 = require("./assetManager");
11
+ const utils_1 = require("./utils/utils");
12
+ const repositoryManager_1 = require("./repositoryManager");
10
13
  const TARGET_KIND = 'core/language-target';
11
14
  const BLOCK_TYPE_KIND = 'core/block-type';
12
15
  class CodeGeneratorManager {
16
+ async ensureLanguageTargetInRegistry(path, version, definition) {
17
+ const key = `${definition.metadata.name}:${version}`;
18
+ try {
19
+ if (await codegen_1.registry.get(key)) {
20
+ return;
21
+ }
22
+ }
23
+ catch (e) { }
24
+ try {
25
+ const target = require(path);
26
+ if (target.default) {
27
+ codegen_1.registry.register(key, target.default);
28
+ }
29
+ else {
30
+ codegen_1.registry.register(key, target);
31
+ }
32
+ }
33
+ catch (e) {
34
+ console.error('Failed to load target: %s', key, e);
35
+ }
36
+ }
13
37
  async reload() {
14
38
  codegen_1.registry.reset();
15
39
  const languageTargets = await definitionsManager_1.definitionsManager.getDefinitions(TARGET_KIND);
16
40
  for (const languageTarget of languageTargets) {
17
- const key = `${languageTarget.definition.metadata.name}:${languageTarget.version}`;
41
+ await this.ensureLanguageTargetInRegistry(languageTarget.path, languageTarget.version, languageTarget.definition);
42
+ }
43
+ }
44
+ async initialize() {
45
+ await this.reload();
46
+ repositoryManager_1.repositoryManager.on('change', async () => {
47
+ // Reload code generators when the repository changes
18
48
  try {
19
- const target = require(languageTarget.path);
20
- if (target.default) {
21
- codegen_1.registry.register(key, target.default);
22
- }
23
- else {
24
- codegen_1.registry.register(key, target);
25
- }
49
+ await this.reload();
26
50
  }
27
51
  catch (e) {
28
- console.error('Failed to load target: %s', key, e);
52
+ console.error('Failed to reload code generators', e);
29
53
  }
30
- }
54
+ });
31
55
  }
32
56
  async canGenerateCode(yamlContent) {
33
57
  if (!yamlContent.spec.target?.kind) {
@@ -39,6 +63,18 @@ class CodeGeneratorManager {
39
63
  return !!(yamlContent && yamlContent.kind && blockTypeKinds.indexOf(yamlContent.kind.toLowerCase()) > -1);
40
64
  }
41
65
  async generate(yamlFile, yamlContent) {
66
+ if (!yamlContent.spec.target?.kind) {
67
+ //Not all block types have targets
68
+ return;
69
+ }
70
+ const targetRef = (0, utils_1.normalizeKapetaUri)(yamlContent.spec.target?.kind);
71
+ // Automatically downloads target if not available
72
+ const targetAsset = await assetManager_1.assetManager.getAsset(targetRef);
73
+ if (!targetAsset) {
74
+ console.error('Language target not found: %s', yamlContent.spec.target?.kind);
75
+ return;
76
+ }
77
+ await this.ensureLanguageTargetInRegistry(targetAsset?.path, targetAsset?.version, targetAsset?.data);
42
78
  const baseDir = path_1.default.dirname(yamlFile);
43
79
  console.log('Generating code for path: %s', baseDir);
44
80
  const codeGenerator = new codegen_1.BlockCodeGenerator(yamlContent);
@@ -50,4 +86,3 @@ class CodeGeneratorManager {
50
86
  }
51
87
  }
52
88
  exports.codeGeneratorManager = new CodeGeneratorManager();
53
- exports.codeGeneratorManager.reload();
@@ -1,6 +1,8 @@
1
+ /// <reference types="node" />
1
2
  import { Task } from './taskManager';
2
3
  import { SourceOfChange } from './types';
3
- declare class RepositoryManager {
4
+ import { EventEmitter } from 'node:events';
5
+ declare class RepositoryManager extends EventEmitter {
4
6
  private _registryService;
5
7
  private watcher;
6
8
  constructor();
@@ -13,6 +13,7 @@ const utils_1 = require("./utils/utils");
13
13
  const progressListener_1 = require("./progressListener");
14
14
  const RepositoryWatcher_1 = require("./RepositoryWatcher");
15
15
  const cacheManager_1 = require("./cacheManager");
16
+ const node_events_1 = require("node:events");
16
17
  const EVENT_DEFAULT_PROVIDERS_START = 'default-providers-start';
17
18
  const EVENT_DEFAULT_PROVIDERS_END = 'default-providers-end';
18
19
  const DEFAULT_PROVIDERS = [
@@ -29,13 +30,17 @@ const DEFAULT_PROVIDERS = [
29
30
  'kapeta/language-target-nodejs',
30
31
  'kapeta/language-target-java-spring-boot',
31
32
  ];
32
- class RepositoryManager {
33
+ class RepositoryManager extends node_events_1.EventEmitter {
33
34
  _registryService;
34
35
  watcher;
35
36
  constructor() {
37
+ super();
36
38
  this._registryService = new nodejs_registry_utils_1.RegistryService(nodejs_registry_utils_1.Config.data.registry.url);
37
39
  this.watcher = new RepositoryWatcher_1.RepositoryWatcher();
38
40
  this.listenForChanges();
41
+ this.watcher.on('change', (file, source) => {
42
+ this.emit('change', file, source);
43
+ });
39
44
  }
40
45
  listenForChanges() {
41
46
  this.watcher.watch();
package/dist/esm/index.js CHANGED
@@ -28,6 +28,7 @@ const repositoryManager_1 = require("./src/repositoryManager");
28
28
  const commandLineUtils_1 = require("./src/utils/commandLineUtils");
29
29
  const DefaultProviderInstaller_1 = require("./src/utils/DefaultProviderInstaller");
30
30
  const authManager_1 = require("./src/authManager");
31
+ const codeGeneratorManager_1 = require("./src/codeGeneratorManager");
31
32
  let currentServer = null;
32
33
  function createServer() {
33
34
  const app = (0, express_1.default)();
@@ -109,6 +110,7 @@ exports.default = {
109
110
  console.error('Could not ping docker runtime: ' + e.toString() + '. Make sure docker is running and working.');
110
111
  }
111
112
  await DefaultProviderInstaller_1.defaultProviderInstaller.checkForDefault();
113
+ await codeGeneratorManager_1.codeGeneratorManager.initialize();
112
114
  const clusterPort = storageService_1.storageService.get('cluster', 'port');
113
115
  if (clusterPort) {
114
116
  clusterService_1.clusterService.setClusterServicePort(clusterPort);
@@ -1,5 +1,7 @@
1
+ /// <reference types="node" />
1
2
  import { SourceOfChange } from './types';
2
- export declare class RepositoryWatcher {
3
+ import { EventEmitter } from 'node:events';
4
+ export declare class RepositoryWatcher extends EventEmitter {
3
5
  private watcher?;
4
6
  private disabled;
5
7
  private readonly baseDir;
@@ -13,8 +13,9 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
13
13
  const lodash_1 = __importDefault(require("lodash"));
14
14
  const socketManager_1 = require("./socketManager");
15
15
  const cacheManager_1 = require("./cacheManager");
16
+ const node_events_1 = require("node:events");
16
17
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
17
- class RepositoryWatcher {
18
+ class RepositoryWatcher extends node_events_1.EventEmitter {
18
19
  watcher;
19
20
  disabled = false;
20
21
  baseDir;
@@ -22,6 +23,7 @@ class RepositoryWatcher {
22
23
  symbolicLinks = {};
23
24
  sourceOfChange = new Map();
24
25
  constructor() {
26
+ super();
25
27
  this.baseDir = local_cluster_config_1.default.getRepositoryBasedir();
26
28
  }
27
29
  setDisabled(disabled) {
@@ -204,6 +206,7 @@ class RepositoryWatcher {
204
206
  this.allDefinitions = newDefinitions;
205
207
  //console.log('Asset changed', payload);
206
208
  socketManager_1.socketManager.emitGlobal('asset-change', payload);
209
+ this.emit('change', payload);
207
210
  cacheManager_1.cacheManager.flush();
208
211
  }
209
212
  async exists(path) {
@@ -234,8 +237,13 @@ class RepositoryWatcher {
234
237
  try {
235
238
  // Make sure we're not watching the symlink target
236
239
  await this.removeSymlinkTarget(path);
237
- const stat = await fs_extra_1.default.lstat(path);
238
- if (stat.isSymbolicLink()) {
240
+ let symbolicLink = false;
241
+ try {
242
+ const stat = await fs_extra_1.default.lstat(path);
243
+ symbolicLink = stat.isSymbolicLink();
244
+ }
245
+ catch (e) { }
246
+ if (symbolicLink) {
239
247
  const realPath = `${await fs_extra_1.default.realpath(path)}/kapeta.yml`;
240
248
  if (await this.exists(realPath)) {
241
249
  //console.log('Watching symlink target %s => %s', path, realPath);
@@ -1,6 +1,8 @@
1
1
  import { BlockDefinition } from '@kapeta/schemas';
2
2
  declare class CodeGeneratorManager {
3
+ private ensureLanguageTargetInRegistry;
3
4
  reload(): Promise<void>;
5
+ initialize(): Promise<void>;
4
6
  canGenerateCode(yamlContent: BlockDefinition): Promise<boolean>;
5
7
  generate(yamlFile: string, yamlContent: BlockDefinition): Promise<void>;
6
8
  }
@@ -7,27 +7,51 @@ exports.codeGeneratorManager = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const codegen_1 = require("@kapeta/codegen");
9
9
  const definitionsManager_1 = require("./definitionsManager");
10
+ const assetManager_1 = require("./assetManager");
11
+ const utils_1 = require("./utils/utils");
12
+ const repositoryManager_1 = require("./repositoryManager");
10
13
  const TARGET_KIND = 'core/language-target';
11
14
  const BLOCK_TYPE_KIND = 'core/block-type';
12
15
  class CodeGeneratorManager {
16
+ async ensureLanguageTargetInRegistry(path, version, definition) {
17
+ const key = `${definition.metadata.name}:${version}`;
18
+ try {
19
+ if (await codegen_1.registry.get(key)) {
20
+ return;
21
+ }
22
+ }
23
+ catch (e) { }
24
+ try {
25
+ const target = require(path);
26
+ if (target.default) {
27
+ codegen_1.registry.register(key, target.default);
28
+ }
29
+ else {
30
+ codegen_1.registry.register(key, target);
31
+ }
32
+ }
33
+ catch (e) {
34
+ console.error('Failed to load target: %s', key, e);
35
+ }
36
+ }
13
37
  async reload() {
14
38
  codegen_1.registry.reset();
15
39
  const languageTargets = await definitionsManager_1.definitionsManager.getDefinitions(TARGET_KIND);
16
40
  for (const languageTarget of languageTargets) {
17
- const key = `${languageTarget.definition.metadata.name}:${languageTarget.version}`;
41
+ await this.ensureLanguageTargetInRegistry(languageTarget.path, languageTarget.version, languageTarget.definition);
42
+ }
43
+ }
44
+ async initialize() {
45
+ await this.reload();
46
+ repositoryManager_1.repositoryManager.on('change', async () => {
47
+ // Reload code generators when the repository changes
18
48
  try {
19
- const target = require(languageTarget.path);
20
- if (target.default) {
21
- codegen_1.registry.register(key, target.default);
22
- }
23
- else {
24
- codegen_1.registry.register(key, target);
25
- }
49
+ await this.reload();
26
50
  }
27
51
  catch (e) {
28
- console.error('Failed to load target: %s', key, e);
52
+ console.error('Failed to reload code generators', e);
29
53
  }
30
- }
54
+ });
31
55
  }
32
56
  async canGenerateCode(yamlContent) {
33
57
  if (!yamlContent.spec.target?.kind) {
@@ -39,6 +63,18 @@ class CodeGeneratorManager {
39
63
  return !!(yamlContent && yamlContent.kind && blockTypeKinds.indexOf(yamlContent.kind.toLowerCase()) > -1);
40
64
  }
41
65
  async generate(yamlFile, yamlContent) {
66
+ if (!yamlContent.spec.target?.kind) {
67
+ //Not all block types have targets
68
+ return;
69
+ }
70
+ const targetRef = (0, utils_1.normalizeKapetaUri)(yamlContent.spec.target?.kind);
71
+ // Automatically downloads target if not available
72
+ const targetAsset = await assetManager_1.assetManager.getAsset(targetRef);
73
+ if (!targetAsset) {
74
+ console.error('Language target not found: %s', yamlContent.spec.target?.kind);
75
+ return;
76
+ }
77
+ await this.ensureLanguageTargetInRegistry(targetAsset?.path, targetAsset?.version, targetAsset?.data);
42
78
  const baseDir = path_1.default.dirname(yamlFile);
43
79
  console.log('Generating code for path: %s', baseDir);
44
80
  const codeGenerator = new codegen_1.BlockCodeGenerator(yamlContent);
@@ -50,4 +86,3 @@ class CodeGeneratorManager {
50
86
  }
51
87
  }
52
88
  exports.codeGeneratorManager = new CodeGeneratorManager();
53
- exports.codeGeneratorManager.reload();
@@ -1,6 +1,8 @@
1
+ /// <reference types="node" />
1
2
  import { Task } from './taskManager';
2
3
  import { SourceOfChange } from './types';
3
- declare class RepositoryManager {
4
+ import { EventEmitter } from 'node:events';
5
+ declare class RepositoryManager extends EventEmitter {
4
6
  private _registryService;
5
7
  private watcher;
6
8
  constructor();
@@ -13,6 +13,7 @@ const utils_1 = require("./utils/utils");
13
13
  const progressListener_1 = require("./progressListener");
14
14
  const RepositoryWatcher_1 = require("./RepositoryWatcher");
15
15
  const cacheManager_1 = require("./cacheManager");
16
+ const node_events_1 = require("node:events");
16
17
  const EVENT_DEFAULT_PROVIDERS_START = 'default-providers-start';
17
18
  const EVENT_DEFAULT_PROVIDERS_END = 'default-providers-end';
18
19
  const DEFAULT_PROVIDERS = [
@@ -29,13 +30,17 @@ const DEFAULT_PROVIDERS = [
29
30
  'kapeta/language-target-nodejs',
30
31
  'kapeta/language-target-java-spring-boot',
31
32
  ];
32
- class RepositoryManager {
33
+ class RepositoryManager extends node_events_1.EventEmitter {
33
34
  _registryService;
34
35
  watcher;
35
36
  constructor() {
37
+ super();
36
38
  this._registryService = new nodejs_registry_utils_1.RegistryService(nodejs_registry_utils_1.Config.data.registry.url);
37
39
  this.watcher = new RepositoryWatcher_1.RepositoryWatcher();
38
40
  this.listenForChanges();
41
+ this.watcher.on('change', (file, source) => {
42
+ this.emit('change', file, source);
43
+ });
39
44
  }
40
45
  listenForChanges() {
41
46
  this.watcher.watch();
package/index.ts CHANGED
@@ -24,6 +24,7 @@ import { repositoryManager } from './src/repositoryManager';
24
24
  import { ensureCLI } from './src/utils/commandLineUtils';
25
25
  import { defaultProviderInstaller } from './src/utils/DefaultProviderInstaller';
26
26
  import { authManager } from './src/authManager';
27
+ import { codeGeneratorManager } from './src/codeGeneratorManager';
27
28
 
28
29
  export type LocalClusterService = HTTP.Server & { host?: string; port?: number };
29
30
 
@@ -125,6 +126,7 @@ export default {
125
126
  }
126
127
 
127
128
  await defaultProviderInstaller.checkForDefault();
129
+ await codeGeneratorManager.initialize();
128
130
 
129
131
  const clusterPort = storageService.get('cluster', 'port');
130
132
  if (clusterPort) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.19.1",
3
+ "version": "0.19.2",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -8,6 +8,7 @@ import _ from 'lodash';
8
8
  import { socketManager } from './socketManager';
9
9
  import { SourceOfChange, WatchEventName } from './types';
10
10
  import { cacheManager } from './cacheManager';
11
+ import { EventEmitter } from 'node:events';
11
12
 
12
13
  interface AssetIdentity {
13
14
  handle: string;
@@ -15,7 +16,7 @@ interface AssetIdentity {
15
16
  version: string;
16
17
  }
17
18
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
18
- export class RepositoryWatcher {
19
+ export class RepositoryWatcher extends EventEmitter {
19
20
  private watcher?: FSWatcher;
20
21
  private disabled: boolean = false;
21
22
  private readonly baseDir: string;
@@ -23,6 +24,7 @@ export class RepositoryWatcher {
23
24
  private symbolicLinks: { [link: string]: string } = {};
24
25
  private sourceOfChange: Map<string, SourceOfChange> = new Map();
25
26
  constructor() {
27
+ super();
26
28
  this.baseDir = ClusterConfiguration.getRepositoryBasedir();
27
29
  }
28
30
 
@@ -228,6 +230,7 @@ export class RepositoryWatcher {
228
230
 
229
231
  //console.log('Asset changed', payload);
230
232
  socketManager.emitGlobal('asset-change', payload);
233
+ this.emit('change', payload);
231
234
 
232
235
  cacheManager.flush();
233
236
  }
@@ -261,8 +264,13 @@ export class RepositoryWatcher {
261
264
  try {
262
265
  // Make sure we're not watching the symlink target
263
266
  await this.removeSymlinkTarget(path);
264
- const stat = await FS.lstat(path);
265
- if (stat.isSymbolicLink()) {
267
+ let symbolicLink = false;
268
+ try {
269
+ const stat = await FS.lstat(path);
270
+ symbolicLink = stat.isSymbolicLink();
271
+ } catch (e) {}
272
+
273
+ if (symbolicLink) {
266
274
  const realPath = `${await FS.realpath(path)}/kapeta.yml`;
267
275
  if (await this.exists(realPath)) {
268
276
  //console.log('Watching symlink target %s => %s', path, realPath);
@@ -1,29 +1,58 @@
1
1
  import Path from 'path';
2
2
  import { registry as Targets, BlockCodeGenerator, CodeWriter } from '@kapeta/codegen';
3
- import ClusterConfiguration from '@kapeta/local-cluster-config';
4
3
  import { BlockDefinition } from '@kapeta/schemas';
5
4
  import { definitionsManager } from './definitionsManager';
5
+ import { Definition } from '@kapeta/local-cluster-config';
6
+ import { assetManager } from './assetManager';
7
+ import { normalizeKapetaUri } from './utils/utils';
8
+ import { repositoryManager } from './repositoryManager';
6
9
 
7
10
  const TARGET_KIND = 'core/language-target';
8
11
  const BLOCK_TYPE_KIND = 'core/block-type';
9
12
 
10
13
  class CodeGeneratorManager {
14
+ private async ensureLanguageTargetInRegistry(path: string, version: string, definition: Definition) {
15
+ const key = `${definition.metadata.name}:${version}`;
16
+
17
+ try {
18
+ if (await Targets.get(key)) {
19
+ return;
20
+ }
21
+ } catch (e) {}
22
+
23
+ try {
24
+ const target = require(path);
25
+ if (target.default) {
26
+ Targets.register(key, target.default);
27
+ } else {
28
+ Targets.register(key, target);
29
+ }
30
+ } catch (e) {
31
+ console.error('Failed to load target: %s', key, e);
32
+ }
33
+ }
11
34
  async reload() {
12
35
  Targets.reset();
13
36
  const languageTargets = await definitionsManager.getDefinitions(TARGET_KIND);
14
37
  for (const languageTarget of languageTargets) {
15
- const key = `${languageTarget.definition.metadata.name}:${languageTarget.version}`;
38
+ await this.ensureLanguageTargetInRegistry(
39
+ languageTarget.path,
40
+ languageTarget.version,
41
+ languageTarget.definition
42
+ );
43
+ }
44
+ }
45
+
46
+ async initialize() {
47
+ await this.reload();
48
+ repositoryManager.on('change', async () => {
49
+ // Reload code generators when the repository changes
16
50
  try {
17
- const target = require(languageTarget.path);
18
- if (target.default) {
19
- Targets.register(key, target.default);
20
- } else {
21
- Targets.register(key, target);
22
- }
51
+ await this.reload();
23
52
  } catch (e) {
24
- console.error('Failed to load target: %s', key, e);
53
+ console.error('Failed to reload code generators', e);
25
54
  }
26
- }
55
+ });
27
56
  }
28
57
 
29
58
  async canGenerateCode(yamlContent: BlockDefinition): Promise<boolean> {
@@ -40,6 +69,22 @@ class CodeGeneratorManager {
40
69
  }
41
70
 
42
71
  async generate(yamlFile: string, yamlContent: BlockDefinition) {
72
+ if (!yamlContent.spec.target?.kind) {
73
+ //Not all block types have targets
74
+ return;
75
+ }
76
+
77
+ const targetRef = normalizeKapetaUri(yamlContent.spec.target?.kind);
78
+
79
+ // Automatically downloads target if not available
80
+ const targetAsset = await assetManager.getAsset(targetRef);
81
+
82
+ if (!targetAsset) {
83
+ console.error('Language target not found: %s', yamlContent.spec.target?.kind);
84
+ return;
85
+ }
86
+
87
+ await this.ensureLanguageTargetInRegistry(targetAsset?.path, targetAsset?.version, targetAsset?.data);
43
88
  const baseDir = Path.dirname(yamlFile);
44
89
  console.log('Generating code for path: %s', baseDir);
45
90
  const codeGenerator = new BlockCodeGenerator(yamlContent);
@@ -55,4 +100,3 @@ class CodeGeneratorManager {
55
100
  }
56
101
 
57
102
  export const codeGeneratorManager = new CodeGeneratorManager();
58
- codeGeneratorManager.reload();
@@ -9,6 +9,7 @@ import { ProgressListener } from './progressListener';
9
9
  import { RepositoryWatcher } from './RepositoryWatcher';
10
10
  import { SourceOfChange } from './types';
11
11
  import { cacheManager } from './cacheManager';
12
+ import { EventEmitter } from 'node:events';
12
13
 
13
14
  const EVENT_DEFAULT_PROVIDERS_START = 'default-providers-start';
14
15
  const EVENT_DEFAULT_PROVIDERS_END = 'default-providers-end';
@@ -28,14 +29,19 @@ const DEFAULT_PROVIDERS = [
28
29
  'kapeta/language-target-java-spring-boot',
29
30
  ];
30
31
 
31
- class RepositoryManager {
32
+ class RepositoryManager extends EventEmitter {
32
33
  private _registryService: RegistryService;
33
34
  private watcher: RepositoryWatcher;
34
35
 
35
36
  constructor() {
37
+ super();
36
38
  this._registryService = new RegistryService(Config.data.registry.url);
37
39
  this.watcher = new RepositoryWatcher();
38
40
  this.listenForChanges();
41
+
42
+ this.watcher.on('change', (file: string, source: SourceOfChange) => {
43
+ this.emit('change', file, source);
44
+ });
39
45
  }
40
46
 
41
47
  listenForChanges() {