@kapeta/local-cluster-service 0.32.0 → 0.32.1

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.32.1](https://github.com/kapetacom/local-cluster-service/compare/v0.32.0...v0.32.1) (2023-12-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Several smaller fixes ([4036345](https://github.com/kapetacom/local-cluster-service/commit/40363457597d36c97481e94e646a6b45d113bb09))
7
+
1
8
  # [0.32.0](https://github.com/kapetacom/local-cluster-service/compare/v0.31.0...v0.32.0) (2023-12-20)
2
9
 
3
10
 
@@ -20,6 +20,24 @@ const cacheManager_1 = require("./cacheManager");
20
20
  const node_events_1 = require("node:events");
21
21
  const assetManager_1 = require("./assetManager");
22
22
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
23
+ let definitions;
24
+ let definitionTimeout;
25
+ function getDefinitionsDebounced() {
26
+ if (definitionTimeout) {
27
+ clearTimeout(definitionTimeout);
28
+ definitionTimeout = undefined;
29
+ }
30
+ if (!definitions) {
31
+ definitions = local_cluster_config_1.default.getDefinitions();
32
+ }
33
+ else {
34
+ definitionTimeout = setTimeout(() => {
35
+ definitionTimeout = undefined;
36
+ definitions = undefined;
37
+ }, 500);
38
+ }
39
+ return definitions;
40
+ }
23
41
  class RepositoryWatcher extends node_events_1.EventEmitter {
24
42
  watcher;
25
43
  disabled = false;
@@ -186,7 +204,7 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
186
204
  }
187
205
  async checkForChange(assetIdentity, sourceOfChange) {
188
206
  const ymlPath = node_path_1.default.join(this.getRepositoryPath(assetIdentity), 'kapeta.yml');
189
- const newDefinitions = local_cluster_config_1.default.getDefinitions();
207
+ const newDefinitions = getDefinitionsDebounced();
190
208
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
191
209
  let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
192
210
  const ymlExists = await this.exists(ymlPath);
@@ -265,11 +283,17 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
265
283
  }
266
284
  catch (e) { }
267
285
  if (symbolicLink) {
268
- const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
269
- if (await this.exists(realPath)) {
270
- //console.log('Watching symlink target %s => %s', path, realPath);
271
- this.watcher?.add(realPath);
272
- this.symbolicLinks[path] = realPath;
286
+ try {
287
+ const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
288
+ if (await this.exists(realPath)) {
289
+ //console.log('Watching symlink target %s => %s', path, realPath);
290
+ this.watcher?.add(realPath);
291
+ this.symbolicLinks[path] = realPath;
292
+ }
293
+ }
294
+ catch (e) {
295
+ // Remove the symlink - it's broken
296
+ await fs_extra_1.default.remove(path);
273
297
  }
274
298
  }
275
299
  }
@@ -24,10 +24,13 @@ const node_os_1 = __importDefault(require("node:os"));
24
24
  const CACHE_TTL = 60 * 60 * 1000; // 1 hour
25
25
  const UPGRADE_CHECK_INTERVAL = 10 * 60 * 1000; // 10 minutes
26
26
  const toKey = (ref) => `assetManager:asset:${ref}`;
27
+ function filterExists(asset) {
28
+ return fs_extra_1.default.existsSync(asset.path);
29
+ }
27
30
  function enrichAsset(asset) {
28
31
  return {
29
32
  ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
30
- editable: asset.version === 'local',
33
+ editable: asset.version === 'local', //Only local versions are editable
31
34
  exists: true,
32
35
  version: asset.version,
33
36
  kind: asset.definition.kind,
@@ -81,7 +84,7 @@ class AssetManager {
81
84
  assetKinds.push('core/plan');
82
85
  }
83
86
  const assets = await definitionsManager_1.definitionsManager.getDefinitions(assetKinds);
84
- return assets.map(enrichAsset);
87
+ return assets.filter(filterExists).map(enrichAsset);
85
88
  }
86
89
  async getPlans() {
87
90
  return this.getAssets(['core/plan']);
@@ -131,9 +131,9 @@ class DefinitionsManager {
131
131
  const definitions = await this.getDefinitions();
132
132
  return definitions.find((d) => {
133
133
  if (!uri.version) {
134
- return d.definition.metadata.name === uri.fullName;
134
+ return d.definition.metadata.name.toLowerCase() === uri.fullName.toLowerCase();
135
135
  }
136
- return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
136
+ return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).equals(uri);
137
137
  });
138
138
  }
139
139
  async getLatestDefinition(name) {
@@ -25,7 +25,7 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
25
25
  const definitionsManager_1 = require("./definitionsManager");
26
26
  const taskManager_1 = require("./taskManager");
27
27
  const CHECK_INTERVAL = 5000;
28
- const DEFAULT_HEALTH_PORT_TYPE = 'rest';
28
+ const DEFAULT_HEALTH_PORT_TYPE = 'http';
29
29
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
30
30
  class InstanceManager {
31
31
  _interval = undefined;
@@ -198,7 +198,7 @@ class InstanceManager {
198
198
  }
199
199
  getHealthUrl(info, address) {
200
200
  let healthUrl = null;
201
- let health = info.health;
201
+ let health = info.health ?? '/.kapeta/health';
202
202
  if (health) {
203
203
  if (health.startsWith('/')) {
204
204
  health = health.substring(1);
@@ -183,7 +183,7 @@ class RepositoryManager extends node_events_1.EventEmitter {
183
183
  if (await definitionsManager_1.definitionsManager.exists(ref)) {
184
184
  return;
185
185
  }
186
- throw new Error(`Failed to install asset: ${ref}`);
186
+ throw new Error(`Failed to find asset after installation: ${ref}. Please try again`);
187
187
  };
188
188
  };
189
189
  const tasks = [];
@@ -20,6 +20,24 @@ const cacheManager_1 = require("./cacheManager");
20
20
  const node_events_1 = require("node:events");
21
21
  const assetManager_1 = require("./assetManager");
22
22
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
23
+ let definitions;
24
+ let definitionTimeout;
25
+ function getDefinitionsDebounced() {
26
+ if (definitionTimeout) {
27
+ clearTimeout(definitionTimeout);
28
+ definitionTimeout = undefined;
29
+ }
30
+ if (!definitions) {
31
+ definitions = local_cluster_config_1.default.getDefinitions();
32
+ }
33
+ else {
34
+ definitionTimeout = setTimeout(() => {
35
+ definitionTimeout = undefined;
36
+ definitions = undefined;
37
+ }, 500);
38
+ }
39
+ return definitions;
40
+ }
23
41
  class RepositoryWatcher extends node_events_1.EventEmitter {
24
42
  watcher;
25
43
  disabled = false;
@@ -186,7 +204,7 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
186
204
  }
187
205
  async checkForChange(assetIdentity, sourceOfChange) {
188
206
  const ymlPath = node_path_1.default.join(this.getRepositoryPath(assetIdentity), 'kapeta.yml');
189
- const newDefinitions = local_cluster_config_1.default.getDefinitions();
207
+ const newDefinitions = getDefinitionsDebounced();
190
208
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
191
209
  let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
192
210
  const ymlExists = await this.exists(ymlPath);
@@ -265,11 +283,17 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
265
283
  }
266
284
  catch (e) { }
267
285
  if (symbolicLink) {
268
- const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
269
- if (await this.exists(realPath)) {
270
- //console.log('Watching symlink target %s => %s', path, realPath);
271
- this.watcher?.add(realPath);
272
- this.symbolicLinks[path] = realPath;
286
+ try {
287
+ const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
288
+ if (await this.exists(realPath)) {
289
+ //console.log('Watching symlink target %s => %s', path, realPath);
290
+ this.watcher?.add(realPath);
291
+ this.symbolicLinks[path] = realPath;
292
+ }
293
+ }
294
+ catch (e) {
295
+ // Remove the symlink - it's broken
296
+ await fs_extra_1.default.remove(path);
273
297
  }
274
298
  }
275
299
  }
@@ -24,10 +24,13 @@ const node_os_1 = __importDefault(require("node:os"));
24
24
  const CACHE_TTL = 60 * 60 * 1000; // 1 hour
25
25
  const UPGRADE_CHECK_INTERVAL = 10 * 60 * 1000; // 10 minutes
26
26
  const toKey = (ref) => `assetManager:asset:${ref}`;
27
+ function filterExists(asset) {
28
+ return fs_extra_1.default.existsSync(asset.path);
29
+ }
27
30
  function enrichAsset(asset) {
28
31
  return {
29
32
  ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
30
- editable: asset.version === 'local',
33
+ editable: asset.version === 'local', //Only local versions are editable
31
34
  exists: true,
32
35
  version: asset.version,
33
36
  kind: asset.definition.kind,
@@ -81,7 +84,7 @@ class AssetManager {
81
84
  assetKinds.push('core/plan');
82
85
  }
83
86
  const assets = await definitionsManager_1.definitionsManager.getDefinitions(assetKinds);
84
- return assets.map(enrichAsset);
87
+ return assets.filter(filterExists).map(enrichAsset);
85
88
  }
86
89
  async getPlans() {
87
90
  return this.getAssets(['core/plan']);
@@ -131,9 +131,9 @@ class DefinitionsManager {
131
131
  const definitions = await this.getDefinitions();
132
132
  return definitions.find((d) => {
133
133
  if (!uri.version) {
134
- return d.definition.metadata.name === uri.fullName;
134
+ return d.definition.metadata.name.toLowerCase() === uri.fullName.toLowerCase();
135
135
  }
136
- return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
136
+ return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).equals(uri);
137
137
  });
138
138
  }
139
139
  async getLatestDefinition(name) {
@@ -25,7 +25,7 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
25
25
  const definitionsManager_1 = require("./definitionsManager");
26
26
  const taskManager_1 = require("./taskManager");
27
27
  const CHECK_INTERVAL = 5000;
28
- const DEFAULT_HEALTH_PORT_TYPE = 'rest';
28
+ const DEFAULT_HEALTH_PORT_TYPE = 'http';
29
29
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
30
30
  class InstanceManager {
31
31
  _interval = undefined;
@@ -198,7 +198,7 @@ class InstanceManager {
198
198
  }
199
199
  getHealthUrl(info, address) {
200
200
  let healthUrl = null;
201
- let health = info.health;
201
+ let health = info.health ?? '/.kapeta/health';
202
202
  if (health) {
203
203
  if (health.startsWith('/')) {
204
204
  health = health.substring(1);
@@ -183,7 +183,7 @@ class RepositoryManager extends node_events_1.EventEmitter {
183
183
  if (await definitionsManager_1.definitionsManager.exists(ref)) {
184
184
  return;
185
185
  }
186
- throw new Error(`Failed to install asset: ${ref}`);
186
+ throw new Error(`Failed to find asset after installation: ${ref}. Please try again`);
187
187
  };
188
188
  };
189
189
  const tasks = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.32.0",
3
+ "version": "0.32.1",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -15,6 +15,7 @@ import { SourceOfChange, WatchEventName } from './types';
15
15
  import { cacheManager } from './cacheManager';
16
16
  import { EventEmitter } from 'node:events';
17
17
  import { assetManager } from './assetManager';
18
+ import { definitionsManager } from './definitionsManager';
18
19
 
19
20
  interface AssetIdentity {
20
21
  handle: string;
@@ -22,6 +23,27 @@ interface AssetIdentity {
22
23
  version: string;
23
24
  }
24
25
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
26
+
27
+ let definitions: DefinitionInfo[] | undefined;
28
+ let definitionTimeout: NodeJS.Timeout | undefined;
29
+
30
+ function getDefinitionsDebounced() {
31
+ if (definitionTimeout) {
32
+ clearTimeout(definitionTimeout);
33
+ definitionTimeout = undefined;
34
+ }
35
+ if (!definitions) {
36
+ definitions = ClusterConfiguration.getDefinitions();
37
+ } else {
38
+ definitionTimeout = setTimeout(() => {
39
+ definitionTimeout = undefined;
40
+ definitions = undefined;
41
+ }, 500);
42
+ }
43
+
44
+ return definitions;
45
+ }
46
+
25
47
  export class RepositoryWatcher extends EventEmitter {
26
48
  private watcher?: FSWatcher;
27
49
  private disabled: boolean = false;
@@ -208,7 +230,8 @@ export class RepositoryWatcher extends EventEmitter {
208
230
 
209
231
  private async checkForChange(assetIdentity: AssetIdentity, sourceOfChange: SourceOfChange) {
210
232
  const ymlPath = Path.join(this.getRepositoryPath(assetIdentity), 'kapeta.yml');
211
- const newDefinitions = ClusterConfiguration.getDefinitions();
233
+ const newDefinitions = getDefinitionsDebounced();
234
+
212
235
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
213
236
  let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
214
237
  const ymlExists = await this.exists(ymlPath);
@@ -290,11 +313,16 @@ export class RepositoryWatcher extends EventEmitter {
290
313
  } catch (e) {}
291
314
 
292
315
  if (symbolicLink) {
293
- const realPath = Path.join(await FS.realpath(path), 'kapeta.yml');
294
- if (await this.exists(realPath)) {
295
- //console.log('Watching symlink target %s => %s', path, realPath);
296
- this.watcher?.add(realPath);
297
- this.symbolicLinks[path] = realPath;
316
+ try {
317
+ const realPath = Path.join(await FS.realpath(path), 'kapeta.yml');
318
+ if (await this.exists(realPath)) {
319
+ //console.log('Watching symlink target %s => %s', path, realPath);
320
+ this.watcher?.add(realPath);
321
+ this.symbolicLinks[path] = realPath;
322
+ }
323
+ } catch (e) {
324
+ // Remove the symlink - it's broken
325
+ await FS.remove(path);
298
326
  }
299
327
  }
300
328
  } catch (e) {
@@ -36,6 +36,10 @@ export interface EnrichedAsset {
36
36
  ymlPath: string;
37
37
  }
38
38
 
39
+ function filterExists(asset: DefinitionInfo): boolean {
40
+ return FS.existsSync(asset.path);
41
+ }
42
+
39
43
  function enrichAsset(asset: DefinitionInfo): EnrichedAsset {
40
44
  return {
41
45
  ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
@@ -101,7 +105,7 @@ class AssetManager {
101
105
 
102
106
  const assets = await definitionsManager.getDefinitions(assetKinds);
103
107
 
104
- return assets.map(enrichAsset);
108
+ return assets.filter(filterExists).map(enrichAsset);
105
109
  }
106
110
 
107
111
  async getPlans(): Promise<EnrichedAsset[]> {
@@ -164,9 +164,9 @@ class DefinitionsManager {
164
164
  const definitions = await this.getDefinitions();
165
165
  return definitions.find((d) => {
166
166
  if (!uri.version) {
167
- return d.definition.metadata.name === uri.fullName;
167
+ return d.definition.metadata.name.toLowerCase() === uri.fullName.toLowerCase();
168
168
  }
169
- return parseKapetaUri(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
169
+ return parseKapetaUri(`${d.definition.metadata.name}:${d.version}`).equals(uri);
170
170
  });
171
171
  }
172
172
 
@@ -27,7 +27,7 @@ import { definitionsManager } from './definitionsManager';
27
27
  import { Task, taskManager } from './taskManager';
28
28
 
29
29
  const CHECK_INTERVAL = 5000;
30
- const DEFAULT_HEALTH_PORT_TYPE = 'rest';
30
+ const DEFAULT_HEALTH_PORT_TYPE = 'http';
31
31
 
32
32
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
33
33
 
@@ -264,7 +264,7 @@ export class InstanceManager {
264
264
 
265
265
  private getHealthUrl(info: Omit<InstanceInfo, 'systemId' | 'instanceId'>, address: string) {
266
266
  let healthUrl = null;
267
- let health = info.health;
267
+ let health = info.health ?? '/.kapeta/health';
268
268
  if (health) {
269
269
  if (health.startsWith('/')) {
270
270
  health = health.substring(1);
@@ -209,7 +209,7 @@ class RepositoryManager extends EventEmitter {
209
209
  if (await definitionsManager.exists(ref)) {
210
210
  return;
211
211
  }
212
- throw new Error(`Failed to install asset: ${ref}`);
212
+ throw new Error(`Failed to find asset after installation: ${ref}. Please try again`);
213
213
  };
214
214
  };
215
215