@kapeta/local-cluster-service 0.15.3 → 0.16.0
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 +7 -0
- package/dist/cjs/src/RepositoryWatcher.d.ts +22 -0
- package/dist/cjs/src/RepositoryWatcher.js +273 -0
- package/dist/cjs/src/assetManager.js +31 -18
- package/dist/cjs/src/instanceManager.js +4 -1
- package/dist/cjs/src/repositoryManager.d.ts +4 -4
- package/dist/cjs/src/repositoryManager.js +18 -91
- package/dist/esm/src/RepositoryWatcher.d.ts +22 -0
- package/dist/esm/src/RepositoryWatcher.js +266 -0
- package/dist/esm/src/assetManager.js +32 -19
- package/dist/esm/src/instanceManager.js +4 -1
- package/dist/esm/src/repositoryManager.d.ts +4 -4
- package/dist/esm/src/repositoryManager.js +18 -91
- package/package.json +2 -2
- package/src/RepositoryWatcher.ts +304 -0
- package/src/assetManager.ts +35 -21
- package/src/identities/routes.ts +0 -1
- package/src/instanceManager.ts +4 -1
- package/src/repositoryManager.ts +21 -95
@@ -0,0 +1,266 @@
|
|
1
|
+
import chokidar from 'chokidar';
|
2
|
+
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
3
|
+
import FS from 'fs-extra';
|
4
|
+
import Path from 'node:path';
|
5
|
+
import YAML from 'yaml';
|
6
|
+
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
7
|
+
import _ from 'lodash';
|
8
|
+
import { socketManager } from './socketManager';
|
9
|
+
import { definitionsManager } from './definitionsManager';
|
10
|
+
import { assetManager } from './assetManager';
|
11
|
+
function clearAllCaches() {
|
12
|
+
definitionsManager.clearCache();
|
13
|
+
assetManager.clearCache();
|
14
|
+
}
|
15
|
+
const KAPETA_YML_RX = /^kapeta.ya?ml$/;
|
16
|
+
export class RepositoryWatcher {
|
17
|
+
watcher;
|
18
|
+
disabled = false;
|
19
|
+
baseDir;
|
20
|
+
allDefinitions = [];
|
21
|
+
symbolicLinks = {};
|
22
|
+
ignoredFiles = new Set();
|
23
|
+
constructor() {
|
24
|
+
this.baseDir = ClusterConfiguration.getRepositoryBasedir();
|
25
|
+
}
|
26
|
+
setDisabled(disabled) {
|
27
|
+
this.disabled = disabled;
|
28
|
+
}
|
29
|
+
watch() {
|
30
|
+
if (!FS.existsSync(this.baseDir)) {
|
31
|
+
FS.mkdirpSync(this.baseDir);
|
32
|
+
}
|
33
|
+
this.allDefinitions = ClusterConfiguration.getDefinitions();
|
34
|
+
try {
|
35
|
+
this.watcher = chokidar.watch(this.baseDir, {
|
36
|
+
followSymlinks: false,
|
37
|
+
ignorePermissionErrors: true,
|
38
|
+
disableGlobbing: true,
|
39
|
+
persistent: true,
|
40
|
+
depth: 2,
|
41
|
+
ignored: (path) => this.ignoreFile(path),
|
42
|
+
});
|
43
|
+
this.watcher.on('all', this.handleFileChange.bind(this));
|
44
|
+
this.watcher.on('error', (error) => {
|
45
|
+
console.log('Error watching repository', error);
|
46
|
+
});
|
47
|
+
this.watcher.on('ready', () => {
|
48
|
+
console.log('Watching local repository for provider changes: %s', this.baseDir);
|
49
|
+
});
|
50
|
+
}
|
51
|
+
catch (e) {
|
52
|
+
// Fallback to run without watch mode due to potential platform issues.
|
53
|
+
// https://nodejs.org/docs/latest/api/fs.html#caveats
|
54
|
+
console.log('Unable to watch for changes. Changes to assets will not update automatically.', e);
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
async ignoreChangesFor(file) {
|
59
|
+
this.ignoredFiles.add(file);
|
60
|
+
const realPath = await FS.realpath(file);
|
61
|
+
if (realPath !== file) {
|
62
|
+
this.ignoredFiles.add(realPath);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
async resumeChangedFor(file) {
|
66
|
+
this.ignoredFiles.delete(file);
|
67
|
+
const realPath = await FS.realpath(file);
|
68
|
+
if (realPath !== file) {
|
69
|
+
this.ignoredFiles.delete(realPath);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
async unwatch() {
|
73
|
+
if (!this.watcher) {
|
74
|
+
return;
|
75
|
+
}
|
76
|
+
this.symbolicLinks = {};
|
77
|
+
await this.watcher.close();
|
78
|
+
this.watcher = undefined;
|
79
|
+
}
|
80
|
+
async getAssetIdentity(path) {
|
81
|
+
const baseName = Path.basename(path);
|
82
|
+
let handle, name, version;
|
83
|
+
if (path.startsWith(this.baseDir)) {
|
84
|
+
const relativePath = Path.relative(this.baseDir, path);
|
85
|
+
// Inside the repo we can use the path to determine the handle, name and version
|
86
|
+
[handle, name, version] = relativePath.split(/\//g);
|
87
|
+
if (!handle || !name || !version) {
|
88
|
+
// Do nothing with this
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
return {
|
92
|
+
handle,
|
93
|
+
name,
|
94
|
+
version,
|
95
|
+
};
|
96
|
+
}
|
97
|
+
if (!KAPETA_YML_RX.test(baseName)) {
|
98
|
+
// Do nothing with this
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
// Outside the repo we need to use the file content to determine the handle, name
|
102
|
+
// Version is always 'local'
|
103
|
+
version = 'local';
|
104
|
+
try {
|
105
|
+
const definition = YAML.parse((await FS.readFile(path)).toString());
|
106
|
+
const uri = parseKapetaUri(definition.metadata.name);
|
107
|
+
handle = uri.handle;
|
108
|
+
name = uri.name;
|
109
|
+
return {
|
110
|
+
handle,
|
111
|
+
name,
|
112
|
+
version,
|
113
|
+
};
|
114
|
+
}
|
115
|
+
catch (e) {
|
116
|
+
// Ignore issues in the YML file
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
async handleFileChange(eventName, path) {
|
121
|
+
if (!path) {
|
122
|
+
return;
|
123
|
+
}
|
124
|
+
if (this.ignoredFiles.has(path)) {
|
125
|
+
return;
|
126
|
+
}
|
127
|
+
//console.log('File changed', eventName, path);
|
128
|
+
const assetIdentity = await this.getAssetIdentity(path);
|
129
|
+
if (!assetIdentity) {
|
130
|
+
return;
|
131
|
+
}
|
132
|
+
if (this.disabled) {
|
133
|
+
return;
|
134
|
+
}
|
135
|
+
// If this is false it's because we're watching a symlink target
|
136
|
+
const withinRepo = path.startsWith(this.baseDir);
|
137
|
+
if (withinRepo && assetIdentity.version === 'local' && path.endsWith('/local')) {
|
138
|
+
// This is likely a symlink target
|
139
|
+
if (eventName === 'add') {
|
140
|
+
//console.log('Checking if we should add symlink target', handle, name, version, path);
|
141
|
+
await this.addSymlinkTarget(path);
|
142
|
+
}
|
143
|
+
if (eventName === 'unlink') {
|
144
|
+
await this.removeSymlinkTarget(path);
|
145
|
+
}
|
146
|
+
if (eventName === 'change') {
|
147
|
+
await this.updateSymlinkTarget(path);
|
148
|
+
}
|
149
|
+
}
|
150
|
+
await this.checkForChange(assetIdentity);
|
151
|
+
}
|
152
|
+
async checkForChange(assetIdentity) {
|
153
|
+
const ymlPath = Path.join(this.baseDir, assetIdentity.handle, assetIdentity.name, assetIdentity.version, 'kapeta.yml');
|
154
|
+
const newDefinitions = ClusterConfiguration.getDefinitions();
|
155
|
+
const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
|
156
|
+
let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
|
157
|
+
const ymlExists = await this.exists(ymlPath);
|
158
|
+
let type;
|
159
|
+
if (ymlExists) {
|
160
|
+
if (currentDefinition) {
|
161
|
+
if (newDefinition && _.isEqual(currentDefinition, newDefinition)) {
|
162
|
+
//Definition was not changed
|
163
|
+
return;
|
164
|
+
}
|
165
|
+
type = 'updated';
|
166
|
+
}
|
167
|
+
else if (newDefinition) {
|
168
|
+
type = 'added';
|
169
|
+
currentDefinition = newDefinition;
|
170
|
+
}
|
171
|
+
else {
|
172
|
+
//Other definition was added / updated - ignore
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
else {
|
177
|
+
if (currentDefinition) {
|
178
|
+
const ref = parseKapetaUri(`${currentDefinition.definition.metadata.name}:${currentDefinition.version}`).id;
|
179
|
+
//Something was removed
|
180
|
+
type = 'removed';
|
181
|
+
}
|
182
|
+
else {
|
183
|
+
//Other definition was removed - ignore
|
184
|
+
return;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
const payload = {
|
188
|
+
type,
|
189
|
+
definition: newDefinition?.definition ?? currentDefinition?.definition,
|
190
|
+
asset: assetIdentity,
|
191
|
+
};
|
192
|
+
this.allDefinitions = newDefinitions;
|
193
|
+
//console.log('Asset changed', payload);
|
194
|
+
socketManager.emitGlobal('asset-change', payload);
|
195
|
+
clearAllCaches();
|
196
|
+
}
|
197
|
+
async exists(path) {
|
198
|
+
try {
|
199
|
+
await FS.access(path);
|
200
|
+
return true;
|
201
|
+
}
|
202
|
+
catch (e) {
|
203
|
+
return false;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
async removeSymlinkTarget(path) {
|
207
|
+
if (this.symbolicLinks[path]) {
|
208
|
+
//console.log('Unwatching symlink target %s => %s', path, this.symbolicLinks[path]);
|
209
|
+
this.watcher?.unwatch(this.symbolicLinks[path]);
|
210
|
+
delete this.symbolicLinks[path];
|
211
|
+
}
|
212
|
+
}
|
213
|
+
async updateSymlinkTarget(path) {
|
214
|
+
if (this.symbolicLinks[path]) {
|
215
|
+
//console.log('Updating symlink target %s => %s', path, this.symbolicLinks[path]);
|
216
|
+
this.watcher?.unwatch(this.symbolicLinks[path]);
|
217
|
+
delete this.symbolicLinks[path];
|
218
|
+
await this.addSymlinkTarget(path);
|
219
|
+
}
|
220
|
+
}
|
221
|
+
async addSymlinkTarget(path) {
|
222
|
+
try {
|
223
|
+
// Make sure we're not watching the symlink target
|
224
|
+
await this.removeSymlinkTarget(path);
|
225
|
+
const stat = await FS.lstat(path);
|
226
|
+
if (stat.isSymbolicLink()) {
|
227
|
+
const realPath = `${await FS.realpath(path)}/kapeta.yml`;
|
228
|
+
if (await this.exists(realPath)) {
|
229
|
+
//console.log('Watching symlink target %s => %s', path, realPath);
|
230
|
+
this.watcher?.add(realPath);
|
231
|
+
this.symbolicLinks[path] = realPath;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
235
|
+
catch (e) {
|
236
|
+
// Ignore
|
237
|
+
console.warn('Failed to check local symlink target', e);
|
238
|
+
}
|
239
|
+
}
|
240
|
+
ignoreFile(path) {
|
241
|
+
if (!path.startsWith(this.baseDir)) {
|
242
|
+
return false;
|
243
|
+
}
|
244
|
+
if (path.includes('/node_modules/')) {
|
245
|
+
return true;
|
246
|
+
}
|
247
|
+
const filename = Path.basename(path);
|
248
|
+
if (filename.startsWith('.')) {
|
249
|
+
return true;
|
250
|
+
}
|
251
|
+
const relativePath = Path.relative(this.baseDir, path).split(Path.sep);
|
252
|
+
try {
|
253
|
+
if (FS.statSync(path).isDirectory()) {
|
254
|
+
if (relativePath.length > 3) {
|
255
|
+
return true;
|
256
|
+
}
|
257
|
+
return false;
|
258
|
+
}
|
259
|
+
}
|
260
|
+
catch (e) {
|
261
|
+
// Didn't exist - dont ignore
|
262
|
+
return false;
|
263
|
+
}
|
264
|
+
return !/^kapeta\.ya?ml$/.test(filename);
|
265
|
+
}
|
266
|
+
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import Path from 'node:path';
|
2
|
-
import FS from '
|
3
|
-
import FSExtra from 'fs-extra';
|
2
|
+
import FS from 'fs-extra';
|
4
3
|
import YAML from 'yaml';
|
5
4
|
import NodeCache from 'node-cache';
|
6
5
|
import { codeGeneratorManager } from './codeGeneratorManager';
|
@@ -11,6 +10,10 @@ import { Actions } from '@kapeta/nodejs-registry-utils';
|
|
11
10
|
import { definitionsManager } from './definitionsManager';
|
12
11
|
import { normalizeKapetaUri } from './utils/utils';
|
13
12
|
import { taskManager } from './taskManager';
|
13
|
+
function clearAllCaches() {
|
14
|
+
definitionsManager.clearCache();
|
15
|
+
assetManager.clearCache();
|
16
|
+
}
|
14
17
|
function enrichAsset(asset) {
|
15
18
|
return {
|
16
19
|
ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
|
@@ -97,19 +100,16 @@ class AssetManager {
|
|
97
100
|
return asset;
|
98
101
|
}
|
99
102
|
async createAsset(path, yaml) {
|
100
|
-
if (FS.
|
103
|
+
if (await FS.pathExists(path)) {
|
101
104
|
throw new Error('File already exists: ' + path);
|
102
105
|
}
|
103
106
|
const dirName = Path.dirname(path);
|
104
|
-
if (!FS.
|
105
|
-
|
107
|
+
if (!(await FS.pathExists(dirName))) {
|
108
|
+
await FS.mkdirp(dirName);
|
106
109
|
}
|
107
|
-
|
108
|
-
FS.writeFileSync(path, YAML.stringify(yaml));
|
110
|
+
await FS.writeFile(path, YAML.stringify(yaml));
|
109
111
|
const asset = await this.importFile(path);
|
110
|
-
|
111
|
-
this.cache.flushAll();
|
112
|
-
definitionsManager.clearCache();
|
112
|
+
clearAllCaches();
|
113
113
|
const ref = `kapeta://${yaml.metadata.name}:local`;
|
114
114
|
this.maybeGenerateCode(ref, path, yaml);
|
115
115
|
return asset;
|
@@ -125,11 +125,23 @@ class AssetManager {
|
|
125
125
|
if (!asset.ymlPath) {
|
126
126
|
throw new Error('Attempted to update corrupted asset: ' + ref);
|
127
127
|
}
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
128
|
+
const path = asset.ymlPath;
|
129
|
+
try {
|
130
|
+
await repositoryManager.ignoreChangesFor(path);
|
131
|
+
await FS.writeFile(asset.ymlPath, YAML.stringify(yaml));
|
132
|
+
console.log('Wrote to ' + asset.ymlPath);
|
133
|
+
clearAllCaches();
|
134
|
+
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
135
|
+
}
|
136
|
+
finally {
|
137
|
+
//We need to wait a bit for the disk to settle before we can resume watching
|
138
|
+
setTimeout(async () => {
|
139
|
+
try {
|
140
|
+
await repositoryManager.resumeChangedFor(path);
|
141
|
+
}
|
142
|
+
catch (e) { }
|
143
|
+
}, 500);
|
144
|
+
}
|
133
145
|
}
|
134
146
|
maybeGenerateCode(ref, ymlPath, block) {
|
135
147
|
ref = normalizeKapetaUri(ref);
|
@@ -148,14 +160,15 @@ class AssetManager {
|
|
148
160
|
if (filePath.startsWith('file://')) {
|
149
161
|
filePath = filePath.substring('file://'.length);
|
150
162
|
}
|
151
|
-
if (!FS.
|
163
|
+
if (!(await FS.pathExists(filePath))) {
|
152
164
|
throw new Error('File not found: ' + filePath);
|
153
165
|
}
|
154
|
-
const
|
166
|
+
const content = await FS.readFile(filePath);
|
167
|
+
const assetInfos = YAML.parseAllDocuments(content.toString()).map((doc) => doc.toJSON());
|
155
168
|
await Actions.link(new ProgressListener(), Path.dirname(filePath));
|
156
169
|
const version = 'local';
|
157
170
|
const refs = assetInfos.map((assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`);
|
158
|
-
|
171
|
+
clearAllCaches();
|
159
172
|
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
160
173
|
}
|
161
174
|
async unregisterAsset(ref) {
|
@@ -163,7 +176,7 @@ class AssetManager {
|
|
163
176
|
if (!asset) {
|
164
177
|
throw new Error('Asset does not exists: ' + ref);
|
165
178
|
}
|
166
|
-
|
179
|
+
clearAllCaches();
|
167
180
|
await Actions.uninstall(new ProgressListener(), [asset.ref]);
|
168
181
|
}
|
169
182
|
async installAsset(ref) {
|
@@ -51,7 +51,10 @@ export class InstanceManager {
|
|
51
51
|
return [];
|
52
52
|
}
|
53
53
|
const plan = planInfo.definition;
|
54
|
-
|
54
|
+
if (!plan?.spec?.blocks) {
|
55
|
+
return [];
|
56
|
+
}
|
57
|
+
const instanceIds = plan.spec?.blocks?.map((block) => block.id) || [];
|
55
58
|
return this._instances.filter((instance) => instance.systemId === systemId && instanceIds.includes(instance.instanceId));
|
56
59
|
}
|
57
60
|
getInstance(systemId, instanceId) {
|
@@ -1,13 +1,13 @@
|
|
1
1
|
import { Task } from './taskManager';
|
2
2
|
declare class RepositoryManager {
|
3
|
-
private changeEventsEnabled;
|
4
3
|
private _registryService;
|
5
4
|
private _cache;
|
6
|
-
private watcher
|
5
|
+
private watcher;
|
7
6
|
constructor();
|
8
|
-
setChangeEventsEnabled(enabled: boolean): void;
|
9
7
|
listenForChanges(): void;
|
10
|
-
stopListening(): void
|
8
|
+
stopListening(): Promise<void>;
|
9
|
+
ignoreChangesFor(file: string): Promise<void>;
|
10
|
+
resumeChangedFor(file: string): Promise<void>;
|
11
11
|
ensureDefaultProviders(): void;
|
12
12
|
private _install;
|
13
13
|
ensureAsset(handle: string, name: string, version: string, wait?: boolean): Promise<undefined | Task[]>;
|
@@ -1,17 +1,16 @@
|
|
1
|
-
import FS from 'node:fs';
|
2
1
|
import os from 'node:os';
|
3
|
-
import Path from 'node:path';
|
4
|
-
import watch from 'recursive-watch';
|
5
|
-
import FSExtra from 'fs-extra';
|
6
|
-
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
7
|
-
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
8
2
|
import { socketManager } from './socketManager';
|
9
3
|
import { Actions, Config, RegistryService } from '@kapeta/nodejs-registry-utils';
|
10
4
|
import { definitionsManager } from './definitionsManager';
|
11
5
|
import { taskManager } from './taskManager';
|
12
6
|
import { normalizeKapetaUri } from './utils/utils';
|
13
|
-
import { assetManager } from './assetManager';
|
14
7
|
import { ProgressListener } from './progressListener';
|
8
|
+
import { RepositoryWatcher } from './RepositoryWatcher';
|
9
|
+
import { assetManager } from './assetManager';
|
10
|
+
function clearAllCaches() {
|
11
|
+
definitionsManager.clearCache();
|
12
|
+
assetManager.clearCache();
|
13
|
+
}
|
15
14
|
const EVENT_DEFAULT_PROVIDERS_START = 'default-providers-start';
|
16
15
|
const EVENT_DEFAULT_PROVIDERS_END = 'default-providers-end';
|
17
16
|
const DEFAULT_PROVIDERS = [
|
@@ -30,92 +29,26 @@ const DEFAULT_PROVIDERS = [
|
|
30
29
|
];
|
31
30
|
const INSTALL_ATTEMPTED = {};
|
32
31
|
class RepositoryManager {
|
33
|
-
changeEventsEnabled;
|
34
32
|
_registryService;
|
35
33
|
_cache;
|
36
34
|
watcher;
|
37
35
|
constructor() {
|
38
|
-
this.changeEventsEnabled = true;
|
39
|
-
this.listenForChanges();
|
40
36
|
this._registryService = new RegistryService(Config.data.registry.url);
|
41
37
|
this._cache = {};
|
42
|
-
|
43
|
-
|
44
|
-
this.changeEventsEnabled = enabled;
|
38
|
+
this.watcher = new RepositoryWatcher();
|
39
|
+
this.listenForChanges();
|
45
40
|
}
|
46
41
|
listenForChanges() {
|
47
|
-
|
48
|
-
if (!FS.existsSync(baseDir)) {
|
49
|
-
FSExtra.mkdirpSync(baseDir);
|
50
|
-
}
|
51
|
-
let allDefinitions = ClusterConfiguration.getDefinitions();
|
52
|
-
console.log('Watching local repository for provider changes: %s', baseDir);
|
53
|
-
try {
|
54
|
-
this.watcher = watch(baseDir, (filename) => {
|
55
|
-
if (!filename) {
|
56
|
-
return;
|
57
|
-
}
|
58
|
-
const [handle, name, version] = filename.toString().split(/\//g);
|
59
|
-
if (!name || !version) {
|
60
|
-
return;
|
61
|
-
}
|
62
|
-
if (!this.changeEventsEnabled) {
|
63
|
-
return;
|
64
|
-
}
|
65
|
-
const ymlPath = Path.join(baseDir, handle, name, version, 'kapeta.yml');
|
66
|
-
const newDefinitions = ClusterConfiguration.getDefinitions();
|
67
|
-
const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
|
68
|
-
let currentDefinition = allDefinitions.find((d) => d.ymlPath === ymlPath);
|
69
|
-
const ymlExists = FS.existsSync(ymlPath);
|
70
|
-
let type;
|
71
|
-
if (ymlExists) {
|
72
|
-
if (currentDefinition) {
|
73
|
-
type = 'updated';
|
74
|
-
}
|
75
|
-
else if (newDefinition) {
|
76
|
-
type = 'added';
|
77
|
-
currentDefinition = newDefinition;
|
78
|
-
}
|
79
|
-
else {
|
80
|
-
//Other definition was added / updated - ignore
|
81
|
-
return;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
else {
|
85
|
-
if (currentDefinition) {
|
86
|
-
const ref = parseKapetaUri(`${currentDefinition.definition.metadata.name}:${currentDefinition.version}`).id;
|
87
|
-
delete INSTALL_ATTEMPTED[ref];
|
88
|
-
//Something was removed
|
89
|
-
type = 'removed';
|
90
|
-
}
|
91
|
-
else {
|
92
|
-
//Other definition was removed - ignore
|
93
|
-
return;
|
94
|
-
}
|
95
|
-
}
|
96
|
-
const payload = {
|
97
|
-
type,
|
98
|
-
definition: currentDefinition?.definition,
|
99
|
-
asset: { handle, name, version },
|
100
|
-
};
|
101
|
-
allDefinitions = newDefinitions;
|
102
|
-
socketManager.emit(`assets`, 'changed', payload);
|
103
|
-
definitionsManager.clearCache();
|
104
|
-
});
|
105
|
-
}
|
106
|
-
catch (e) {
|
107
|
-
// Fallback to run without watch mode due to potential platform issues.
|
108
|
-
// https://nodejs.org/docs/latest/api/fs.html#caveats
|
109
|
-
console.log('Unable to watch for changes. Changes to assets will not update automatically.', e);
|
110
|
-
return;
|
111
|
-
}
|
42
|
+
this.watcher.watch();
|
112
43
|
}
|
113
|
-
stopListening() {
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
this.watcher();
|
118
|
-
|
44
|
+
async stopListening() {
|
45
|
+
return this.watcher.unwatch();
|
46
|
+
}
|
47
|
+
ignoreChangesFor(file) {
|
48
|
+
return this.watcher.ignoreChangesFor(file);
|
49
|
+
}
|
50
|
+
resumeChangedFor(file) {
|
51
|
+
return this.watcher.resumeChangedFor(file);
|
119
52
|
}
|
120
53
|
ensureDefaultProviders() {
|
121
54
|
socketManager.emitGlobal(EVENT_DEFAULT_PROVIDERS_START, { providers: DEFAULT_PROVIDERS });
|
@@ -140,19 +73,13 @@ class RepositoryManager {
|
|
140
73
|
try {
|
141
74
|
//We change to a temp dir to avoid issues with the current working directory
|
142
75
|
process.chdir(os.tmpdir());
|
143
|
-
//Disable change events while installing
|
144
|
-
this.setChangeEventsEnabled(false);
|
145
76
|
await Actions.install(new ProgressListener(), [ref], {});
|
146
77
|
}
|
147
78
|
catch (e) {
|
148
79
|
console.error(`Failed to install asset: ${ref}`, e);
|
149
80
|
throw e;
|
150
81
|
}
|
151
|
-
|
152
|
-
this.setChangeEventsEnabled(true);
|
153
|
-
}
|
154
|
-
definitionsManager.clearCache();
|
155
|
-
assetManager.clearCache();
|
82
|
+
clearAllCaches();
|
156
83
|
//console.log(`Asset installed: ${ref}`);
|
157
84
|
};
|
158
85
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@kapeta/local-cluster-service",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.16.0",
|
4
4
|
"description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
|
5
5
|
"type": "commonjs",
|
6
6
|
"exports": {
|
@@ -53,6 +53,7 @@
|
|
53
53
|
"@kapeta/sdk-config": "<2",
|
54
54
|
"@kapeta/web-microfrontend": "^0.2.1",
|
55
55
|
"async-lock": "^1.4.0",
|
56
|
+
"chokidar": "^3.5.3",
|
56
57
|
"express": "4.17.1",
|
57
58
|
"express-promise-router": "^4.1.1",
|
58
59
|
"fs-extra": "^11.1.0",
|
@@ -62,7 +63,6 @@
|
|
62
63
|
"node-cache": "^5.1.2",
|
63
64
|
"node-docker-api": "1.1.22",
|
64
65
|
"node-uuid": "^1.4.8",
|
65
|
-
"recursive-watch": "^1.1.4",
|
66
66
|
"request": "2.88.2",
|
67
67
|
"request-promise": "4.2.6",
|
68
68
|
"socket.io": "^4.5.2",
|