@kapeta/local-cluster-service 0.6.0 → 0.7.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.
Files changed (193) hide show
  1. package/.eslintrc.cjs +17 -0
  2. package/.github/workflows/main.yml +22 -22
  3. package/.prettierignore +4 -0
  4. package/.vscode/launch.json +2 -4
  5. package/CHANGELOG.md +14 -0
  6. package/definitions.d.ts +17 -35
  7. package/dist/cjs/index.d.ts +27 -0
  8. package/dist/cjs/index.js +126 -0
  9. package/dist/cjs/package.json +1 -0
  10. package/dist/cjs/src/assetManager.d.ts +31 -0
  11. package/dist/cjs/src/assetManager.js +153 -0
  12. package/dist/cjs/src/assets/routes.d.ts +3 -0
  13. package/dist/cjs/src/assets/routes.js +117 -0
  14. package/dist/cjs/src/clusterService.d.ts +40 -0
  15. package/dist/cjs/src/clusterService.js +114 -0
  16. package/dist/cjs/src/codeGeneratorManager.d.ts +8 -0
  17. package/dist/cjs/src/codeGeneratorManager.js +53 -0
  18. package/dist/cjs/src/config/routes.d.ts +3 -0
  19. package/dist/cjs/src/config/routes.js +126 -0
  20. package/dist/cjs/src/configManager.d.ts +36 -0
  21. package/dist/cjs/src/configManager.js +110 -0
  22. package/dist/cjs/src/containerManager.d.ts +89 -0
  23. package/dist/cjs/src/containerManager.js +365 -0
  24. package/dist/cjs/src/filesystem/routes.d.ts +3 -0
  25. package/dist/cjs/src/filesystem/routes.js +69 -0
  26. package/dist/cjs/src/filesystemManager.d.ts +15 -0
  27. package/dist/cjs/src/filesystemManager.js +87 -0
  28. package/dist/cjs/src/identities/routes.d.ts +3 -0
  29. package/dist/cjs/src/identities/routes.js +18 -0
  30. package/dist/cjs/src/instanceManager.d.ts +56 -0
  31. package/dist/cjs/src/instanceManager.js +424 -0
  32. package/dist/cjs/src/instances/routes.d.ts +3 -0
  33. package/dist/cjs/src/instances/routes.js +134 -0
  34. package/dist/cjs/src/middleware/cors.d.ts +2 -0
  35. package/dist/cjs/src/middleware/cors.js +10 -0
  36. package/dist/cjs/src/middleware/kapeta.d.ts +11 -0
  37. package/dist/cjs/src/middleware/kapeta.js +17 -0
  38. package/dist/cjs/src/middleware/stringBody.d.ts +5 -0
  39. package/dist/cjs/src/middleware/stringBody.js +14 -0
  40. package/dist/cjs/src/networkManager.d.ts +32 -0
  41. package/dist/cjs/src/networkManager.js +109 -0
  42. package/dist/cjs/src/operatorManager.d.ts +36 -0
  43. package/dist/cjs/src/operatorManager.js +165 -0
  44. package/dist/cjs/src/progressListener.d.ts +20 -0
  45. package/dist/cjs/src/progressListener.js +91 -0
  46. package/dist/cjs/src/providerManager.d.ts +9 -0
  47. package/dist/cjs/src/providerManager.js +51 -0
  48. package/dist/cjs/src/providers/routes.d.ts +3 -0
  49. package/dist/cjs/src/providers/routes.js +42 -0
  50. package/dist/cjs/src/proxy/routes.d.ts +3 -0
  51. package/dist/cjs/src/proxy/routes.js +111 -0
  52. package/dist/cjs/src/proxy/types/rest.d.ts +4 -0
  53. package/dist/cjs/src/proxy/types/rest.js +114 -0
  54. package/dist/cjs/src/proxy/types/web.d.ts +4 -0
  55. package/dist/cjs/src/proxy/types/web.js +53 -0
  56. package/dist/cjs/src/repositoryManager.d.ts +17 -0
  57. package/dist/cjs/src/repositoryManager.js +215 -0
  58. package/dist/cjs/src/serviceManager.d.ts +29 -0
  59. package/dist/cjs/src/serviceManager.js +99 -0
  60. package/dist/cjs/src/socketManager.d.ts +14 -0
  61. package/dist/cjs/src/socketManager.js +53 -0
  62. package/dist/cjs/src/storageService.d.ts +17 -0
  63. package/dist/cjs/src/storageService.js +74 -0
  64. package/dist/cjs/src/traffic/routes.d.ts +3 -0
  65. package/dist/cjs/src/traffic/routes.js +18 -0
  66. package/dist/cjs/src/types.d.ts +88 -0
  67. package/dist/cjs/src/types.js +2 -0
  68. package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +29 -0
  69. package/dist/cjs/src/utils/BlockInstanceRunner.js +468 -0
  70. package/dist/cjs/src/utils/LogData.d.ts +19 -0
  71. package/dist/cjs/src/utils/LogData.js +43 -0
  72. package/dist/cjs/src/utils/pathTemplateParser.d.ts +26 -0
  73. package/dist/cjs/src/utils/pathTemplateParser.js +121 -0
  74. package/dist/cjs/src/utils/utils.d.ts +1 -0
  75. package/dist/cjs/src/utils/utils.js +18 -0
  76. package/dist/cjs/start.d.ts +1 -0
  77. package/dist/cjs/start.js +12 -0
  78. package/dist/esm/index.d.ts +27 -0
  79. package/dist/esm/index.js +121 -0
  80. package/dist/esm/package.json +1 -0
  81. package/dist/esm/src/assetManager.d.ts +31 -0
  82. package/{src → dist/esm/src}/assetManager.js +22 -60
  83. package/dist/esm/src/assets/routes.d.ts +3 -0
  84. package/{src → dist/esm/src}/assets/routes.js +21 -36
  85. package/dist/esm/src/clusterService.d.ts +40 -0
  86. package/{src → dist/esm/src}/clusterService.js +14 -37
  87. package/dist/esm/src/codeGeneratorManager.d.ts +8 -0
  88. package/{src → dist/esm/src}/codeGeneratorManager.js +15 -24
  89. package/dist/esm/src/config/routes.d.ts +3 -0
  90. package/dist/esm/src/config/routes.js +121 -0
  91. package/dist/esm/src/configManager.d.ts +36 -0
  92. package/{src → dist/esm/src}/configManager.js +11 -40
  93. package/dist/esm/src/containerManager.d.ts +89 -0
  94. package/{src → dist/esm/src}/containerManager.js +81 -182
  95. package/dist/esm/src/filesystem/routes.d.ts +3 -0
  96. package/dist/esm/src/filesystem/routes.js +64 -0
  97. package/dist/esm/src/filesystemManager.d.ts +15 -0
  98. package/{src → dist/esm/src}/filesystemManager.js +20 -28
  99. package/dist/esm/src/identities/routes.d.ts +3 -0
  100. package/dist/esm/src/identities/routes.js +13 -0
  101. package/dist/esm/src/instanceManager.d.ts +56 -0
  102. package/{src → dist/esm/src}/instanceManager.js +94 -175
  103. package/dist/esm/src/instances/routes.d.ts +3 -0
  104. package/{src → dist/esm/src}/instances/routes.js +31 -70
  105. package/dist/esm/src/middleware/cors.d.ts +2 -0
  106. package/{src → dist/esm/src}/middleware/cors.js +2 -3
  107. package/dist/esm/src/middleware/kapeta.d.ts +11 -0
  108. package/{src → dist/esm/src}/middleware/kapeta.js +3 -7
  109. package/dist/esm/src/middleware/stringBody.d.ts +5 -0
  110. package/{src → dist/esm/src}/middleware/stringBody.js +2 -3
  111. package/dist/esm/src/networkManager.d.ts +32 -0
  112. package/{src → dist/esm/src}/networkManager.js +16 -33
  113. package/dist/esm/src/operatorManager.d.ts +36 -0
  114. package/{src → dist/esm/src}/operatorManager.js +35 -91
  115. package/dist/esm/src/progressListener.d.ts +20 -0
  116. package/dist/esm/src/progressListener.js +88 -0
  117. package/dist/esm/src/providerManager.d.ts +9 -0
  118. package/dist/esm/src/providerManager.js +45 -0
  119. package/dist/esm/src/providers/routes.d.ts +3 -0
  120. package/{src → dist/esm/src}/providers/routes.js +10 -16
  121. package/dist/esm/src/proxy/routes.d.ts +3 -0
  122. package/dist/esm/src/proxy/routes.js +106 -0
  123. package/dist/esm/src/proxy/types/rest.d.ts +4 -0
  124. package/dist/esm/src/proxy/types/rest.js +107 -0
  125. package/dist/esm/src/proxy/types/web.d.ts +4 -0
  126. package/{src → dist/esm/src}/proxy/types/web.js +13 -35
  127. package/dist/esm/src/repositoryManager.d.ts +17 -0
  128. package/dist/esm/src/repositoryManager.js +209 -0
  129. package/dist/esm/src/serviceManager.d.ts +29 -0
  130. package/{src → dist/esm/src}/serviceManager.js +12 -42
  131. package/dist/esm/src/socketManager.d.ts +14 -0
  132. package/{src → dist/esm/src}/socketManager.js +19 -23
  133. package/dist/esm/src/storageService.d.ts +17 -0
  134. package/{src → dist/esm/src}/storageService.js +8 -27
  135. package/dist/esm/src/traffic/routes.d.ts +3 -0
  136. package/{src → dist/esm/src}/traffic/routes.js +4 -9
  137. package/dist/esm/src/types.d.ts +88 -0
  138. package/dist/esm/src/types.js +1 -0
  139. package/dist/esm/src/utils/BlockInstanceRunner.d.ts +29 -0
  140. package/{src → dist/esm/src}/utils/BlockInstanceRunner.js +137 -256
  141. package/dist/esm/src/utils/LogData.d.ts +19 -0
  142. package/{src → dist/esm/src}/utils/LogData.js +11 -22
  143. package/dist/esm/src/utils/pathTemplateParser.d.ts +26 -0
  144. package/{src → dist/esm/src}/utils/pathTemplateParser.js +21 -40
  145. package/dist/esm/src/utils/utils.d.ts +1 -0
  146. package/dist/esm/src/utils/utils.js +11 -0
  147. package/dist/esm/start.d.ts +1 -0
  148. package/dist/esm/start.js +7 -0
  149. package/index.ts +147 -0
  150. package/package.json +106 -74
  151. package/src/assetManager.ts +191 -0
  152. package/src/assets/routes.ts +132 -0
  153. package/src/clusterService.ts +134 -0
  154. package/src/codeGeneratorManager.ts +57 -0
  155. package/src/config/routes.ts +159 -0
  156. package/src/configManager.ts +148 -0
  157. package/src/containerManager.ts +466 -0
  158. package/src/filesystem/routes.ts +74 -0
  159. package/src/filesystemManager.ts +93 -0
  160. package/src/identities/routes.ts +20 -0
  161. package/src/instanceManager.ts +503 -0
  162. package/src/instances/routes.ts +164 -0
  163. package/src/middleware/cors.ts +9 -0
  164. package/src/middleware/kapeta.ts +27 -0
  165. package/src/middleware/stringBody.ts +16 -0
  166. package/src/networkManager.ts +137 -0
  167. package/src/operatorManager.ts +221 -0
  168. package/src/progressListener.ts +102 -0
  169. package/src/{providerManager.js → providerManager.ts} +15 -31
  170. package/src/providers/routes.ts +46 -0
  171. package/src/proxy/routes.ts +148 -0
  172. package/src/proxy/types/{rest.js → rest.ts} +30 -30
  173. package/src/proxy/types/web.ts +60 -0
  174. package/src/{repositoryManager.js → repositoryManager.ts} +45 -73
  175. package/src/serviceManager.ts +120 -0
  176. package/src/socketManager.ts +57 -0
  177. package/src/storageService.ts +88 -0
  178. package/src/traffic/routes.ts +18 -0
  179. package/src/types.ts +97 -0
  180. package/src/utils/BlockInstanceRunner.ts +555 -0
  181. package/src/utils/LogData.ts +47 -0
  182. package/src/utils/pathTemplateParser.ts +138 -0
  183. package/src/utils/utils.ts +12 -0
  184. package/start.ts +8 -0
  185. package/tsconfig.json +13 -0
  186. package/index.js +0 -127
  187. package/src/config/routes.js +0 -160
  188. package/src/filesystem/routes.js +0 -74
  189. package/src/identities/routes.js +0 -19
  190. package/src/progressListener.js +0 -82
  191. package/src/proxy/routes.js +0 -126
  192. package/src/utils/utils.js +0 -13
  193. package/start.js +0 -7
@@ -1,62 +1,52 @@
1
- const { Docker } = require('node-docker-api');
2
- const path = require('path');
3
- const _ = require('lodash');
4
- const os = require('os');
5
- const Path = require('path');
6
- const storageService = require('./storageService');
7
- const mkdirp = require('mkdirp');
8
- const { parseKapetaUri } = require('@kapeta/nodejs-utils');
9
-
10
- const ClusterConfiguration = require('@kapeta/local-cluster-config').default;
11
-
1
+ import Path from 'path';
2
+ import { storageService } from './storageService';
3
+ import os from 'os';
4
+ import _ from 'lodash';
5
+ import FSExtra from 'fs-extra';
6
+ import { Docker } from 'node-docker-api';
7
+ import { parseKapetaUri } from '@kapeta/nodejs-utils';
8
+ import ClusterConfiguration from '@kapeta/local-cluster-config';
12
9
  const LABEL_PORT_PREFIX = 'kapeta_port-';
13
-
14
10
  const NANO_SECOND = 1000000;
15
11
  const HEALTH_CHECK_INTERVAL = 2000;
16
12
  const HEALTH_CHECK_MAX = 30;
17
13
  const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
18
14
  const IMAGE_PULL_CACHE = {};
19
-
20
-
21
- const promisifyStream = (stream) =>
22
- new Promise((resolve, reject) => {
23
- stream.on('data', (d) => console.log(d.toString()));
24
- stream.on('end', resolve);
25
- stream.on('error', reject);
26
- });
27
-
15
+ const promisifyStream = (stream) => new Promise((resolve, reject) => {
16
+ stream.on('data', (d) => console.log(d.toString()));
17
+ stream.on('end', resolve);
18
+ stream.on('error', reject);
19
+ });
28
20
  class ContainerManager {
21
+ _docker;
22
+ _alive;
23
+ _mountDir;
29
24
  constructor() {
30
25
  this._docker = null;
31
26
  this._alive = false;
32
27
  this._mountDir = Path.join(storageService.getKapetaBasedir(), 'mounts');
33
- mkdirp.sync(this._mountDir);
28
+ FSExtra.mkdirpSync(this._mountDir);
34
29
  }
35
-
36
30
  async initialize() {
37
31
  // Use the value from cluster-service.yml if configured
38
32
  const dockerConfig = ClusterConfiguration.getDockerConfig();
39
- const connectOptions =
40
- Object.keys(dockerConfig).length > 0
41
- ? [dockerConfig]
42
- : [
43
- // use defaults: DOCKER_HOST etc from env, if available
44
- undefined,
45
- // default linux
46
- { socketPath: '/var/run/docker.sock' },
47
- // default macOS
48
- {
49
- socketPath: path.join(
50
- os.homedir(),
51
- '.docker/run/docker.sock'
52
- ),
53
- },
54
- // Default http
55
- { protocol: 'http', host: 'localhost', port: 2375 },
56
- { protocol: 'https', host: 'localhost', port: 2376 },
57
- { protocol: 'http', host: '127.0.0.1', port: 2375 },
58
- { protocol: 'https', host: '127.0.0.1', port: 2376 },
59
- ];
33
+ const connectOptions = Object.keys(dockerConfig).length > 0
34
+ ? [dockerConfig]
35
+ : [
36
+ // use defaults: DOCKER_HOST etc from env, if available
37
+ undefined,
38
+ // default linux
39
+ { socketPath: '/var/run/docker.sock' },
40
+ // default macOS
41
+ {
42
+ socketPath: Path.join(os.homedir(), '.docker/run/docker.sock'),
43
+ },
44
+ // Default http
45
+ { protocol: 'http', host: 'localhost', port: 2375 },
46
+ { protocol: 'https', host: 'localhost', port: 2376 },
47
+ { protocol: 'http', host: '127.0.0.1', port: 2375 },
48
+ { protocol: 'https', host: '127.0.0.1', port: 2376 },
49
+ ];
60
50
  for (const opts of connectOptions) {
61
51
  try {
62
52
  const client = new Docker(opts);
@@ -64,49 +54,38 @@ class ContainerManager {
64
54
  this._docker = client;
65
55
  this._alive = true;
66
56
  return;
67
- } catch (err) {
57
+ }
58
+ catch (err) {
68
59
  // silently ignore bad configs
69
60
  }
70
61
  }
71
-
72
62
  throw new Error('Could not connect to docker daemon. Please make sure docker is running and working.');
73
63
  }
74
-
75
64
  isAlive() {
76
65
  return this._alive;
77
66
  }
78
-
79
67
  getMountPoint(kind, mountName) {
80
68
  const kindUri = parseKapetaUri(kind);
81
- return Path.join(
82
- this._mountDir,
83
- kindUri.handle,
84
- kindUri.name,
85
- mountName
86
- );
69
+ return Path.join(this._mountDir, kindUri.handle, kindUri.name, mountName);
87
70
  }
88
-
89
71
  createMounts(kind, mountOpts) {
90
72
  const mounts = {};
91
-
92
73
  _.forEach(mountOpts, (containerPath, mountName) => {
93
74
  const hostPath = this.getMountPoint(kind, mountName);
94
- mkdirp.sync(hostPath);
75
+ FSExtra.mkdirpSync(hostPath);
95
76
  mounts[containerPath] = hostPath;
96
77
  });
97
78
  return mounts;
98
79
  }
99
-
100
80
  async ping() {
101
81
  try {
102
82
  const pingResult = await this.docker().ping();
103
83
  if (pingResult !== 'OK') {
104
84
  throw new Error(`Ping failed: ${pingResult}`);
105
85
  }
106
- } catch (e) {
107
- throw new Error(
108
- `Docker not running. Please start the docker daemon before running this command. Error: ${e.message}`
109
- );
86
+ }
87
+ catch (e) {
88
+ throw new Error(`Docker not running. Please start the docker daemon before running this command. Error: ${e.message}`);
110
89
  }
111
90
  }
112
91
  docker() {
@@ -115,20 +94,17 @@ class ContainerManager {
115
94
  }
116
95
  return this._docker;
117
96
  }
118
-
119
97
  async getContainerByName(containerName) {
120
98
  const containers = await this.docker().container.list({ all: true });
121
99
  return containers.find((container) => {
122
100
  return container.data.Names.indexOf(`/${containerName}`) > -1;
123
101
  });
124
102
  }
125
-
126
103
  async pull(image, cacheForMS = IMAGE_PULL_CACHE_TTL) {
127
104
  let [imageName, tag] = image.split(/:/);
128
105
  if (!tag) {
129
106
  tag = 'latest';
130
107
  }
131
-
132
108
  if (tag !== 'latest') {
133
109
  if (IMAGE_PULL_CACHE[image]) {
134
110
  const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
@@ -136,33 +112,26 @@ class ContainerManager {
136
112
  return;
137
113
  }
138
114
  }
139
-
140
115
  const imageTagList = (await this.docker().image.list())
141
- .filter(image => !!image.data.RepoTags)
142
- .map(image => image.data.RepoTags);
116
+ .map((image) => image.data)
117
+ .filter((imageData) => !!imageData.RepoTags)
118
+ .map((imageData) => imageData.RepoTags);
143
119
  if (imageTagList.some((imageTags) => imageTags.indexOf(image) > -1)) {
144
120
  console.log('Image found: %s', image);
145
121
  return;
146
122
  }
147
123
  console.log('Image not found: %s', image);
148
124
  }
149
-
150
125
  console.log('Pulling image: %s', image);
151
126
  await this.docker()
152
- .image.create(
153
- {},
154
- {
155
- fromImage: imageName,
156
- tag: tag,
157
- }
158
- )
127
+ .image.create({}, {
128
+ fromImage: imageName,
129
+ tag: tag,
130
+ })
159
131
  .then((stream) => promisifyStream(stream));
160
-
161
132
  IMAGE_PULL_CACHE[image] = Date.now();
162
-
163
133
  console.log('Image pulled: %s', image);
164
134
  }
165
-
166
135
  toDockerMounts(mounts) {
167
136
  const Mounts = [];
168
137
  _.forEach(mounts, (Source, Target) => {
@@ -174,41 +143,24 @@ class ContainerManager {
174
143
  Consistency: 'consistent',
175
144
  });
176
145
  });
177
-
178
146
  return Mounts;
179
147
  }
180
-
181
148
  toDockerHealth(health) {
182
149
  return {
183
150
  Test: ['CMD-SHELL', health.cmd],
184
- Interval: health.interval
185
- ? health.interval * NANO_SECOND
186
- : 5000 * NANO_SECOND,
187
- Timeout: health.timeout
188
- ? health.timeout * NANO_SECOND
189
- : 15000 * NANO_SECOND,
151
+ Interval: health.interval ? health.interval * NANO_SECOND : 5000 * NANO_SECOND,
152
+ Timeout: health.timeout ? health.timeout * NANO_SECOND : 15000 * NANO_SECOND,
190
153
  Retries: health.retries || 10,
191
154
  };
192
155
  }
193
-
194
- /**
195
- *
196
- * @param {string} image
197
- * @param {string} name
198
- * @param {{ports:{},mounts:{},env:{}}} opts
199
- * @return {Promise<ContainerInfo>}
200
- */
201
156
  async run(image, name, opts) {
202
157
  const PortBindings = {};
203
158
  const Env = [];
204
159
  const Labels = {
205
160
  kapeta: 'true',
206
161
  };
207
-
208
162
  await this.pull(image);
209
-
210
163
  const ExposedPorts = {};
211
-
212
164
  _.forEach(opts.ports, (portInfo, containerPort) => {
213
165
  ExposedPorts['' + containerPort] = {};
214
166
  PortBindings['' + containerPort] = [
@@ -217,18 +169,13 @@ class ContainerManager {
217
169
  HostIp: '127.0.0.1',
218
170
  },
219
171
  ];
220
-
221
172
  Labels[LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
222
173
  });
223
-
224
174
  const Mounts = this.toDockerMounts(opts.mounts);
225
-
226
175
  _.forEach(opts.env, (value, name) => {
227
176
  Env.push(name + '=' + value);
228
177
  });
229
-
230
178
  let HealthCheck = undefined;
231
-
232
179
  if (opts.health) {
233
180
  HealthCheck = this.toDockerHealth(opts.health);
234
181
  }
@@ -238,7 +185,6 @@ class ContainerManager {
238
185
  Hostname: name + '.kapeta',
239
186
  Labels,
240
187
  Cmd: opts.cmd,
241
-
242
188
  ExposedPorts,
243
189
  Env,
244
190
  HealthCheck,
@@ -247,86 +193,73 @@ class ContainerManager {
247
193
  Mounts,
248
194
  },
249
195
  });
250
-
251
196
  if (opts.health) {
252
197
  await this.waitForHealthy(dockerContainer);
253
198
  }
254
-
255
199
  return new ContainerInfo(dockerContainer);
256
200
  }
257
-
258
201
  async startContainer(opts) {
259
202
  const dockerContainer = await this.docker().container.create(opts);
260
203
  await dockerContainer.start();
261
204
  return dockerContainer;
262
205
  }
263
-
264
- async waitForReady(container, attempt) {
206
+ async waitForReady(container, attempt = 0) {
265
207
  if (!attempt) {
266
208
  attempt = 0;
267
209
  }
268
-
269
210
  if (attempt >= HEALTH_CHECK_MAX) {
270
- throw new Error(
271
- 'Container did not become ready within the timeout'
272
- );
211
+ throw new Error('Container did not become ready within the timeout');
273
212
  }
274
-
275
213
  if (await this._isReady(container)) {
276
214
  return;
277
215
  }
278
-
279
216
  return new Promise((resolve, reject) => {
280
217
  setTimeout(async () => {
281
218
  try {
282
219
  await this.waitForReady(container, attempt + 1);
283
220
  resolve();
284
- } catch (err) {
221
+ }
222
+ catch (err) {
285
223
  reject(err);
286
224
  }
287
225
  }, HEALTH_CHECK_INTERVAL);
288
226
  });
289
227
  }
290
-
291
228
  async waitForHealthy(container, attempt) {
292
229
  if (!attempt) {
293
230
  attempt = 0;
294
231
  }
295
-
296
232
  if (attempt >= HEALTH_CHECK_MAX) {
297
- throw new Error(
298
- 'Container did not become healthy within the timeout'
299
- );
233
+ throw new Error('Container did not become healthy within the timeout');
300
234
  }
301
-
302
235
  if (await this._isHealthy(container)) {
303
236
  return;
304
237
  }
305
-
306
238
  return new Promise((resolve, reject) => {
307
239
  setTimeout(async () => {
308
240
  try {
309
- await this.waitForHealthy(container, attempt + 1);
241
+ await this.waitForHealthy(container, (attempt ?? 0) + 1);
310
242
  resolve();
311
- } catch (err) {
243
+ }
244
+ catch (err) {
312
245
  reject(err);
313
246
  }
314
247
  }, HEALTH_CHECK_INTERVAL);
315
248
  });
316
249
  }
317
-
318
250
  async _isReady(container) {
319
251
  const info = await container.status();
320
- if (info?.data?.State?.Status === 'exited') {
252
+ const infoData = info?.data;
253
+ if (infoData?.State?.Status === 'exited') {
321
254
  throw new Error('Container exited unexpectedly');
322
255
  }
323
- return info?.data?.State?.Running;
256
+ return infoData?.State?.Running ?? false;
324
257
  }
325
258
  async _isHealthy(container) {
326
259
  const info = await container.status();
327
- return info?.data?.State?.Health?.Status === 'healthy';
260
+ const infoData = info?.data;
261
+ return infoData?.State?.Health?.Status === 'healthy';
328
262
  }
329
-
330
263
  /**
331
264
  *
332
265
  * @param name
@@ -334,24 +267,22 @@ class ContainerManager {
334
267
  */
335
268
  async get(name) {
336
269
  let dockerContainer = null;
337
-
338
270
  try {
339
271
  dockerContainer = await this.docker().container.get(name);
340
272
  await dockerContainer.status();
341
- } catch (err) {
273
+ }
274
+ catch (err) {
342
275
  //Ignore
343
276
  dockerContainer = null;
344
277
  }
345
-
346
278
  if (!dockerContainer) {
347
279
  return null;
348
280
  }
349
-
350
281
  return new ContainerInfo(dockerContainer);
351
282
  }
352
283
  }
353
-
354
- class ContainerInfo {
284
+ export class ContainerInfo {
285
+ _container;
355
286
  /**
356
287
  *
357
288
  * @param {Container} dockerContainer
@@ -364,96 +295,64 @@ class ContainerInfo {
364
295
  */
365
296
  this._container = dockerContainer;
366
297
  }
367
-
368
298
  get native() {
369
299
  return this._container;
370
300
  }
371
-
372
301
  async isRunning() {
373
302
  const inspectResult = await this.getStatus();
374
-
375
303
  if (!inspectResult || !inspectResult.State) {
376
304
  return false;
377
305
  }
378
-
379
306
  return inspectResult.State.Running || inspectResult.State.Restarting;
380
307
  }
381
-
382
308
  async start() {
383
309
  await this._container.start();
384
310
  }
385
-
386
311
  async restart() {
387
312
  await this._container.restart();
388
313
  }
389
-
390
314
  async stop() {
391
315
  await this._container.stop();
392
316
  }
393
-
394
317
  async remove(opts) {
395
- await this._container.delete({ force: !!opts.force });
318
+ await this._container.delete({ force: !!opts?.force });
396
319
  }
397
-
398
320
  async getPort(type) {
399
321
  const ports = await this.getPorts();
400
-
401
- if (ports[type]) {
322
+ if (ports && ports[type]) {
402
323
  return ports[type];
403
324
  }
404
-
405
325
  return null;
406
326
  }
407
-
408
327
  async getStatus() {
409
328
  const result = await this._container.status();
410
-
411
329
  return result ? result.data : null;
412
330
  }
413
-
414
331
  async getPorts() {
415
332
  const inspectResult = await this.getStatus();
416
-
417
- if (
418
- !inspectResult ||
419
- !inspectResult.Config ||
420
- !inspectResult.Config.Labels
421
- ) {
333
+ if (!inspectResult || !inspectResult.Config || !inspectResult.Config.Labels) {
422
334
  return false;
423
335
  }
424
-
425
336
  const portTypes = {};
426
337
  const ports = {};
427
-
428
338
  _.forEach(inspectResult.Config.Labels, (portType, name) => {
429
339
  if (!name.startsWith(LABEL_PORT_PREFIX)) {
430
340
  return;
431
341
  }
432
-
433
342
  const hostPort = name.substr(LABEL_PORT_PREFIX.length);
434
-
435
343
  portTypes[hostPort] = portType;
436
344
  });
437
-
438
- _.forEach(
439
- inspectResult.HostConfig.PortBindings,
440
- (portBindings, containerPortSpec) => {
441
- let [containerPort, protocol] = containerPortSpec.split(/\//);
442
-
443
- const hostPort = portBindings[0].HostPort;
444
-
445
- const portType = portTypes[hostPort];
446
-
447
- ports[portType] = {
448
- containerPort,
449
- protocol,
450
- hostPort,
451
- };
452
- }
453
- );
454
-
345
+ _.forEach(inspectResult.HostConfig.PortBindings, (portBindings, containerPortSpec) => {
346
+ let [containerPort, protocol] = containerPortSpec.split(/\//);
347
+ const hostPort = portBindings[0].HostPort;
348
+ const portType = portTypes[hostPort];
349
+ ports[portType] = {
350
+ containerPort,
351
+ protocol,
352
+ hostPort,
353
+ };
354
+ });
455
355
  return ports;
456
356
  }
457
357
  }
458
-
459
- module.exports = new ContainerManager();
358
+ export const containerManager = new ContainerManager();
@@ -0,0 +1,3 @@
1
+ /// <reference types="express" />
2
+ declare let router: import("express").Router;
3
+ export default router;
@@ -0,0 +1,64 @@
1
+ import Router from 'express-promise-router';
2
+ import { stringBody } from '../middleware/stringBody';
3
+ import { filesystemManager } from '../filesystemManager';
4
+ import { corsHandler } from '../middleware/cors';
5
+ let router = Router();
6
+ router.use('/', corsHandler);
7
+ router.get('/root', (req, res) => {
8
+ res.send(filesystemManager.getRootFolder());
9
+ });
10
+ router.get('/project/root', (req, res) => {
11
+ res.send(filesystemManager.getProjectRootFolder());
12
+ });
13
+ router.use('/project/root', stringBody);
14
+ router.post('/project/root', (req, res) => {
15
+ filesystemManager.setProjectRootFolder(req.stringBody ?? '');
16
+ res.sendStatus(204);
17
+ });
18
+ router.use('/', (req, res, next) => {
19
+ if (!req.query.path) {
20
+ res.status(400).send({ error: 'Missing required query parameter "path"' });
21
+ return;
22
+ }
23
+ next();
24
+ });
25
+ router.get('/list', async (req, res) => {
26
+ let pathArg = req.query.path;
27
+ try {
28
+ res.send(await filesystemManager.readDirectory(pathArg));
29
+ }
30
+ catch (err) {
31
+ res.status(400).send({ error: '' + err });
32
+ }
33
+ });
34
+ router.get('/readfile', async (req, res) => {
35
+ let pathArg = req.query.path;
36
+ try {
37
+ res.send(await filesystemManager.readFile(pathArg));
38
+ }
39
+ catch (err) {
40
+ res.status(400).send({ error: '' + err });
41
+ }
42
+ });
43
+ router.put('/mkdir', async (req, res) => {
44
+ let pathArg = req.query.path;
45
+ try {
46
+ await filesystemManager.createFolder(pathArg);
47
+ res.sendStatus(204);
48
+ }
49
+ catch (err) {
50
+ res.status(400).send({ error: '' + err });
51
+ }
52
+ });
53
+ router.use('/writefile', stringBody);
54
+ router.post('/writefile', async (req, res) => {
55
+ let pathArg = req.query.path;
56
+ try {
57
+ await filesystemManager.writeFile(pathArg, req.stringBody ?? '');
58
+ res.sendStatus(204);
59
+ }
60
+ catch (err) {
61
+ res.status(400).send({ error: '' + err });
62
+ }
63
+ });
64
+ export default router;
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ declare class FilesystemManager {
3
+ writeFile(path: string, data: string | Buffer): Promise<void>;
4
+ createFolder(path: string): Promise<void>;
5
+ readDirectory(path: string): Promise<{
6
+ path: string;
7
+ folder: boolean;
8
+ }[]>;
9
+ readFile(path: string): Promise<Buffer>;
10
+ getRootFolder(): string;
11
+ getProjectRootFolder(): string | undefined;
12
+ setProjectRootFolder(folder: string): void;
13
+ }
14
+ export declare const filesystemManager: FilesystemManager;
15
+ export {};