@kapeta/local-cluster-service 0.6.1 → 0.7.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.
Files changed (192) 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 +218 -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/{src → dist/esm/src}/config/routes.js +40 -89
  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 +88 -179
  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 +212 -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} +49 -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/filesystem/routes.js +0 -74
  188. package/src/identities/routes.js +0 -19
  189. package/src/progressListener.js +0 -82
  190. package/src/proxy/routes.js +0 -126
  191. package/src/utils/utils.js +0 -13
  192. package/start.js +0 -7
@@ -1,52 +1,36 @@
1
- const FS = require('fs');
2
- const Path = require('path');
3
- const FSExtra = require('fs-extra');
4
- const repositoryManager = require('./repositoryManager');
5
- const ClusterConfiguration = require('@kapeta/local-cluster-config').default;
1
+ import Path from 'path';
2
+ import FSExtra from 'fs-extra';
3
+ import { repositoryManager } from './repositoryManager';
4
+ import ClusterConfiguration from '@kapeta/local-cluster-config';
5
+ import { StringMap } from './types';
6
6
 
7
7
  class ProviderManager {
8
+ private _webAssetCache: StringMap;
8
9
  constructor() {
9
10
  this._webAssetCache = {};
10
11
  }
11
12
 
12
13
  getWebProviders() {
13
- return ClusterConfiguration.getProviderDefinitions().filter(
14
- (providerDefinition) => providerDefinition.hasWeb
15
- );
14
+ return ClusterConfiguration.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
16
15
  }
17
16
 
18
- async getAsset(handle, name, version, sourceMap = false) {
17
+ async getAsset(handle: string, name: string, version: string, sourceMap: boolean = false) {
19
18
  const fullName = `${handle}/${name}`;
20
- const id = `${handle}/${name}/${version}/web.js${
21
- sourceMap ? '.map' : ''
22
- }`;
19
+ const id = `${handle}/${name}/${version}/web.js${sourceMap ? '.map' : ''}`;
23
20
 
24
- if (
25
- this._webAssetCache[id] &&
26
- (await FSExtra.pathExists(this._webAssetCache[id]))
27
- ) {
21
+ if (this._webAssetCache[id] && (await FSExtra.pathExists(this._webAssetCache[id]))) {
28
22
  return FSExtra.readFile(this._webAssetCache[id], 'utf8');
29
23
  }
30
24
 
31
25
  await repositoryManager.ensureAsset(handle, name, version);
32
26
 
33
- const installedProvider = this.getWebProviders().find(
34
- (providerDefinition) => {
35
- return (
36
- providerDefinition.definition.metadata.name === fullName &&
37
- providerDefinition.version === version
38
- );
39
- }
40
- );
27
+ const installedProvider = this.getWebProviders().find((providerDefinition) => {
28
+ return providerDefinition.definition.metadata.name === fullName && providerDefinition.version === version;
29
+ });
41
30
 
42
31
  if (installedProvider) {
43
32
  //Check locally installed providers
44
- const path = Path.join(
45
- installedProvider.path,
46
- 'web',
47
- handle,
48
- `${name}.js${sourceMap ? '.map' : ''}`
49
- );
33
+ const path = Path.join(installedProvider.path, 'web', handle, `${name}.js${sourceMap ? '.map' : ''}`);
50
34
  if (await FSExtra.pathExists(path)) {
51
35
  this._webAssetCache[id] = path;
52
36
 
@@ -75,4 +59,4 @@ if (providerDefinitions.length > 0) {
75
59
  console.log('## No providers found ##');
76
60
  }
77
61
 
78
- module.exports = new ProviderManager();
62
+ export const providerManager = new ProviderManager();
@@ -0,0 +1,46 @@
1
+ import Router from 'express-promise-router';
2
+ import { providerManager } from '../providerManager';
3
+
4
+ import { corsHandler } from '../middleware/cors';
5
+ import { Request, Response } from 'express';
6
+
7
+ const router = Router();
8
+
9
+ router.use('/', corsHandler);
10
+
11
+ router.get('/', async (req: Request, res: Response) => {
12
+ const result = await providerManager.getWebProviders();
13
+
14
+ res.send(result);
15
+ });
16
+
17
+ router.get('/asset/:handle/:name/:version/web.js', async (req: Request, res: Response) => {
18
+ const { handle, name, version } = req.params;
19
+ let result = await providerManager.getAsset(handle, name, version);
20
+
21
+ if (!result) {
22
+ res.status(404).send('');
23
+ } else {
24
+ if (version !== 'local') {
25
+ res.setHeader('Cache-Control', 'max-age=31536000, immutable');
26
+ }
27
+ res.send(result.toString().replace(`${name}.js.map`, 'web.js.map'));
28
+ }
29
+ });
30
+
31
+ router.get('/asset/:handle/:name/:version/web.js.map', async (req: Request, res: Response) => {
32
+ const { handle, name, version } = req.params;
33
+ const result = await providerManager.getAsset(handle, name, version, true);
34
+
35
+ if (!result) {
36
+ res.status(404).send('');
37
+ } else {
38
+ // Only cache successful requests
39
+ if (version !== 'local') {
40
+ res.setHeader('Cache-Control', 'max-age=31536000, immutable');
41
+ }
42
+ res.send(result);
43
+ }
44
+ });
45
+
46
+ export default router;
@@ -0,0 +1,148 @@
1
+ import Router from 'express-promise-router';
2
+ import { Request, Response } from 'express';
3
+ import { Resource } from '@kapeta/schemas';
4
+ import { proxyRestRequest } from './types/rest';
5
+ import { proxyWebRequest } from './types/web';
6
+ import { ProxyRequestHandler } from '../types';
7
+ import { stringBody, StringBodyRequest } from '../middleware/stringBody';
8
+ import { serviceManager } from '../serviceManager';
9
+ import { clusterService } from '../clusterService';
10
+ import { assetManager } from '../assetManager';
11
+
12
+ import _ from 'lodash';
13
+
14
+ const router = Router();
15
+ /**
16
+ * @var {{[key:string]:ProxyRequestHandler}}
17
+ */
18
+ const TYPE_HANDLERS: { [p: string]: ProxyRequestHandler } = {
19
+ rest: proxyRestRequest,
20
+ web: proxyWebRequest,
21
+ };
22
+
23
+ function getResource(resources: Resource[], resourceName: string) {
24
+ return resources.find((resource) => {
25
+ return resource.metadata.name.toLowerCase() === resourceName.toLowerCase();
26
+ });
27
+ }
28
+
29
+ router.use('/:systemId/:consumerInstanceId/:consumerResourceName', stringBody);
30
+
31
+ router.all(
32
+ '/:systemId/:consumerInstanceId/:consumerResourceName/:type/*',
33
+ async (req: StringBodyRequest, res: Response) => {
34
+ try {
35
+ const typeHandler = TYPE_HANDLERS[req.params.type.toLowerCase()];
36
+ if (!typeHandler) {
37
+ res.status(401).send({ error: 'Unknown connection type: ' + req.params.type });
38
+ return;
39
+ }
40
+
41
+ const plan = await assetManager.getPlan(req.params.systemId);
42
+
43
+ // We can find the connection by the consumer information alone since
44
+ // only 1 provider can be connected to a consumer resource at a time
45
+ const connection = _.find(plan.spec.connections, (connection) => {
46
+ return (
47
+ connection.consumer.blockId.toLowerCase() === req.params.consumerInstanceId.toLowerCase() &&
48
+ connection.consumer.resourceName.toLowerCase() === req.params.consumerResourceName.toLowerCase()
49
+ );
50
+ });
51
+
52
+ if (!connection) {
53
+ res.status(401).send({
54
+ error: `No connection found for consumer "${req.params.consumerInstanceId}::${req.params.consumerResourceName}"`,
55
+ });
56
+ return;
57
+ }
58
+
59
+ const toBlockInstance = _.find(plan.spec.blocks, (blockInstance) => {
60
+ return blockInstance.id.toLowerCase() === connection.consumer.blockId.toLowerCase();
61
+ });
62
+
63
+ if (!toBlockInstance) {
64
+ res.status(401).send({ error: `Block instance not found "${req.params.consumerInstanceId}` });
65
+ return;
66
+ }
67
+
68
+ const toBlockAsset = await assetManager.getAsset(toBlockInstance.block.ref);
69
+
70
+ if (!toBlockAsset) {
71
+ res.status(401).send({ error: `Block asset not found "${toBlockInstance.block.ref}` });
72
+ return;
73
+ }
74
+
75
+ const consumerResource = getResource(toBlockAsset.data.spec.consumers, req.params.consumerResourceName);
76
+
77
+ if (!consumerResource) {
78
+ res.status(401).send({
79
+ error: `Block resource not found "${req.params.consumerInstanceId}::${req.params.consumerResourceName}`,
80
+ });
81
+ return;
82
+ }
83
+
84
+ const basePath = clusterService.getProxyPath(
85
+ req.params.systemId,
86
+ req.params.consumerInstanceId,
87
+ req.params.consumerResourceName,
88
+ req.params.type
89
+ );
90
+
91
+ const fromBlockInstance = _.find(plan.spec.blocks, (blockInstance) => {
92
+ return blockInstance.id.toLowerCase() === connection.provider.blockId.toLowerCase();
93
+ });
94
+
95
+ if (!fromBlockInstance) {
96
+ res.status(401).send({ error: `Block instance not found "${connection.provider.blockId}` });
97
+ return;
98
+ }
99
+
100
+ const fromBlockAsset = await assetManager.getAsset(fromBlockInstance.block.ref);
101
+
102
+ if (!fromBlockAsset) {
103
+ res.status(401).send({ error: `Block asset not found "${fromBlockInstance.block.ref}` });
104
+ return;
105
+ }
106
+
107
+ const providerResource = getResource(fromBlockAsset.data.spec.providers, connection.provider.resourceName);
108
+
109
+ if (!providerResource) {
110
+ res.status(401).send({
111
+ error: `Block resource not found "${connection.provider.blockId}::${connection.provider.resourceName}`,
112
+ });
113
+ return;
114
+ }
115
+
116
+ //Get target address
117
+ let address = await serviceManager.getProviderAddress(
118
+ req.params.systemId,
119
+ connection.provider.blockId,
120
+ req.params.type
121
+ );
122
+
123
+ while (address.endsWith('/')) {
124
+ address = address.substring(0, address.length - 1);
125
+ }
126
+
127
+ /*
128
+ Get the path the consumer requested.
129
+ Note that this might not match the path the destination is expecting so we need to identify the method
130
+ that is being called and identify the destination path from the connection.
131
+ */
132
+ const consumerPath = req.originalUrl.substring(basePath.length - 1);
133
+
134
+ typeHandler(req, res, {
135
+ consumerPath,
136
+ address,
137
+ consumerResource,
138
+ providerResource,
139
+ connection,
140
+ });
141
+ } catch (err: any) {
142
+ console.warn('Failed to process proxy request', err);
143
+ res.status(400).send({ error: err.message });
144
+ }
145
+ }
146
+ );
147
+
148
+ export default router;
@@ -1,13 +1,16 @@
1
- const request = require('request');
2
- const Path = require('path');
3
- const _ = require('lodash');
4
-
5
- const pathTemplateParser = require('../../utils/pathTemplateParser');
6
- const networkManager = require('../../networkManager');
7
- const socketManager = require('../../socketManager');
8
-
9
-
10
- function getRestMethodId(restResource, httpMethod, httpPath) {
1
+ import _ from 'lodash';
2
+ import request from 'request';
3
+ import Path from 'path';
4
+ import { pathTemplateParser } from '../../utils/pathTemplateParser';
5
+ import { networkManager } from '../../networkManager';
6
+
7
+ import { socketManager } from '../../socketManager';
8
+ import { Request, Response } from 'express';
9
+ import { ProxyRequestInfo, SimpleRequest, StringMap } from '../../types';
10
+ import { StringBodyRequest } from '../../middleware/stringBody';
11
+ import { Resource } from '@kapeta/schemas';
12
+
13
+ function getRestMethodId(restResource: Resource, httpMethod: string, httpPath: string) {
11
14
  return _.findKey(restResource.spec.methods, (method) => {
12
15
  let methodType = method.method ? method.method.toUpperCase() : 'GET';
13
16
 
@@ -24,7 +27,6 @@ function getRestMethodId(restResource, httpMethod, httpPath) {
24
27
  const pathTemplate = pathTemplateParser(path);
25
28
 
26
29
  return pathTemplate.matches(httpPath);
27
-
28
30
  });
29
31
  }
30
32
 
@@ -34,7 +36,7 @@ function getRestMethodId(restResource, httpMethod, httpPath) {
34
36
  * @param opts {ProxyRequestInfo}
35
37
  * @return {{consumerMethod: *, providerMethod: *}}
36
38
  */
37
- function resolveMethods(req, opts) {
39
+ function resolveMethods(req: Request, opts: ProxyRequestInfo) {
38
40
  const consumerMethodId = getRestMethodId(opts.consumerResource, req.method, opts.consumerPath);
39
41
 
40
42
  if (!consumerMethodId) {
@@ -73,24 +75,23 @@ function resolveMethods(req, opts) {
73
75
 
74
76
  return {
75
77
  consumerMethod,
76
- providerMethod
78
+ providerMethod,
77
79
  };
78
80
  }
79
81
 
80
- /**
81
- *
82
- * @param req {Request}
83
- * @param res {Response}
84
- * @param opts {ProxyRequestInfo}
85
- */
86
- module.exports = function proxyRestRequest(req, res, opts) {
87
-
88
- let {consumerMethod, providerMethod} = resolveMethods(req, opts);
82
+ export function proxyRestRequest(req: StringBodyRequest, res: Response, opts: ProxyRequestInfo) {
83
+ let { consumerMethod, providerMethod } = resolveMethods(req, opts);
89
84
 
90
85
  const consumerPathTemplate = pathTemplateParser(consumerMethod.path);
91
86
  const providerPathTemplate = pathTemplateParser(providerMethod.path);
92
87
 
93
88
  const pathVariables = consumerPathTemplate.parse(opts.consumerPath);
89
+ if (!pathVariables) {
90
+ res.status(400).send({
91
+ error: `Path did not match any patterns: "${opts.consumerPath}"`,
92
+ });
93
+ return;
94
+ }
94
95
 
95
96
  let providerPath = providerPathTemplate.create(pathVariables);
96
97
 
@@ -108,11 +109,11 @@ module.exports = function proxyRestRequest(req, res, opts) {
108
109
 
109
110
  console.log('Proxy request to provider: %s => %s [rest]', opts.consumerPath, opts.address + providerPath);
110
111
 
111
- const reqOpts = {
112
+ const reqOpts: SimpleRequest = {
112
113
  method: providerMethod.method || 'GET',
113
114
  url: opts.address + providerPath,
114
115
  body: req.stringBody,
115
- headers: requestHeaders
116
+ headers: requestHeaders as StringMap,
116
117
  };
117
118
 
118
119
  const traffic = networkManager.addRequest(
@@ -125,12 +126,12 @@ module.exports = function proxyRestRequest(req, res, opts) {
125
126
 
126
127
  socketManager.emit(traffic.connectionId, 'traffic_start', traffic);
127
128
 
128
- request(reqOpts, function(err, response, responseBody) {
129
+ request(reqOpts, function (err, response, responseBody) {
129
130
  if (err) {
130
131
  traffic.asError(err);
131
132
  socketManager.emit(traffic.connectionId, 'traffic_end', traffic);
132
133
 
133
- res.status(500).send({error: '' + err});
134
+ res.status(500).send({ error: '' + err });
134
135
  return;
135
136
  }
136
137
 
@@ -146,8 +147,8 @@ module.exports = function proxyRestRequest(req, res, opts) {
146
147
 
147
148
  traffic.withResponse({
148
149
  code: response.statusCode,
149
- headers: response.headers,
150
- body: responseBody
150
+ headers: response.headers as StringMap,
151
+ body: responseBody,
151
152
  });
152
153
 
153
154
  socketManager.emit(traffic.connectionId, 'traffic_end', traffic);
@@ -158,5 +159,4 @@ module.exports = function proxyRestRequest(req, res, opts) {
158
159
 
159
160
  res.end();
160
161
  });
161
-
162
- };
162
+ }
@@ -0,0 +1,60 @@
1
+ import request from 'request';
2
+ import _ from 'lodash';
3
+ import { networkManager } from '../../networkManager';
4
+ import { socketManager } from '../../socketManager';
5
+ import { Request, Response } from 'express';
6
+ import { ProxyRequestInfo, SimpleRequest, StringMap } from '../../types';
7
+ import { StringBodyRequest } from '../../middleware/stringBody';
8
+
9
+ export function proxyWebRequest(req: StringBodyRequest, res: Response, opts: ProxyRequestInfo) {
10
+ const requestHeaders = _.clone(req.headers);
11
+
12
+ delete requestHeaders['content-length'];
13
+ delete requestHeaders['content-encoding'];
14
+ delete requestHeaders['connection'];
15
+ delete requestHeaders['host'];
16
+ delete requestHeaders['origin'];
17
+
18
+ const sourceBasePath = opts.consumerResource.spec.path;
19
+ const targetBasePath = opts.providerResource.spec.path;
20
+ let path = opts.consumerPath;
21
+ if (opts.consumerPath.startsWith(sourceBasePath)) {
22
+ path = path.replace(sourceBasePath, targetBasePath);
23
+ }
24
+
25
+ console.log('Proxy request to provider: %s => %s%s [web]', opts.consumerPath, opts.address, path);
26
+
27
+ const reqOpts: SimpleRequest = {
28
+ method: req.method,
29
+ url: opts.address + path,
30
+ headers: requestHeaders as StringMap,
31
+ body: req.stringBody,
32
+ };
33
+
34
+ const traffic = networkManager.addRequest(req.params.systemId, opts.connection, reqOpts);
35
+
36
+ socketManager.emit(traffic.connectionId, 'traffic_start', traffic);
37
+ const proxyReq = request(reqOpts);
38
+
39
+ proxyReq.on('error', function (err) {
40
+ traffic.asError(err);
41
+ socketManager.emit(traffic.connectionId, 'traffic_end', traffic);
42
+ if (!res.headersSent) {
43
+ res.status(500).send({ error: '' + err });
44
+ }
45
+ });
46
+
47
+ proxyReq.on('response', function (response) {
48
+ //TODO: Include the response body in the traffic object when it is not a stream
49
+ traffic.withResponse({
50
+ code: response.statusCode,
51
+ headers: response.headers as StringMap,
52
+ body: null,
53
+ });
54
+
55
+ socketManager.emit(traffic.connectionId, 'traffic_end', traffic);
56
+ });
57
+
58
+ //We need to pipe the proxy response to the client response to handle sockets and event streams
59
+ proxyReq.pipe(res);
60
+ }
@@ -1,21 +1,24 @@
1
- const ClusterConfiguration = require('@kapeta/local-cluster-config').default;
2
- const FS = require('node:fs');
3
- const FSExtra = require('fs-extra');
4
- const Path = require('node:path');
5
- const socketManager = require('./socketManager');
6
- const {
7
- Actions,
8
- RegistryService,
9
- Config,
10
- } = require('@kapeta/nodejs-registry-utils');
11
- const progressListener = require('./progressListener');
12
- const os = require('os');
13
- const { parseKapetaUri } = require('@kapeta/nodejs-utils');
14
- const INSTALL_ATTEMPTED = {};
1
+ import FS from 'node:fs';
2
+ import os from 'node:os';
3
+ import Path from 'node:path';
4
+ import FSExtra, { FSWatcher } from 'fs-extra';
5
+ import ClusterConfiguration from '@kapeta/local-cluster-config';
6
+ import { parseKapetaUri } from '@kapeta/nodejs-utils';
7
+ import { socketManager } from './socketManager';
8
+ import { progressListener } from './progressListener';
9
+ import { Dependency } from '@kapeta/schemas';
10
+ import { Actions, Config, RegistryService } from '@kapeta/nodejs-registry-utils';
11
+
12
+ const INSTALL_ATTEMPTED: { [p: string]: boolean } = {};
15
13
 
16
14
  class RepositoryManager {
15
+ private changeEventsEnabled: boolean;
16
+ private _registryService: RegistryService;
17
+ private _cache: { [key: string]: boolean };
18
+ private watcher?: FSWatcher;
19
+ private _installQueue: (() => Promise<void>)[];
20
+ private _processing: boolean = false;
17
21
  constructor() {
18
- this.watcher = null;
19
22
  this.changeEventsEnabled = true;
20
23
  this.listenForChanges();
21
24
  this._registryService = new RegistryService(Config.data.registry.url);
@@ -23,7 +26,7 @@ class RepositoryManager {
23
26
  this._installQueue = [];
24
27
  }
25
28
 
26
- setChangeEventsEnabled(enabled) {
29
+ setChangeEventsEnabled(enabled: boolean) {
27
30
  this.changeEventsEnabled = enabled;
28
31
  }
29
32
 
@@ -35,22 +38,21 @@ class RepositoryManager {
35
38
 
36
39
  let allDefinitions = ClusterConfiguration.getDefinitions();
37
40
 
38
- console.log(
39
- 'Watching local repository for provider changes: %s',
40
- baseDir
41
- );
41
+ console.log('Watching local repository for provider changes: %s', baseDir);
42
42
  try {
43
43
  this.watcher = FS.watch(baseDir, { recursive: true });
44
44
  } catch (e) {
45
45
  // Fallback to run without watch mode due to potential platform issues.
46
46
  // https://nodejs.org/docs/latest/api/fs.html#caveats
47
- console.log(
48
- 'Unable to watch for changes. Changes to assets will not update automatically.'
49
- );
47
+ console.log('Unable to watch for changes. Changes to assets will not update automatically.');
50
48
  return;
51
49
  }
52
50
  this.watcher.on('change', (eventType, filename) => {
53
- const [handle, name, version] = filename.split(/\//g);
51
+ if (!filename) {
52
+ return;
53
+ }
54
+
55
+ const [handle, name, version] = filename.toString().split(/\//g);
54
56
  if (!name || !version) {
55
57
  return;
56
58
  }
@@ -59,21 +61,11 @@ class RepositoryManager {
59
61
  return;
60
62
  }
61
63
 
62
- const ymlPath = Path.join(
63
- baseDir,
64
- handle,
65
- name,
66
- version,
67
- 'kapeta.yml'
68
- );
64
+ const ymlPath = Path.join(baseDir, handle, name, version, 'kapeta.yml');
69
65
  const newDefinitions = ClusterConfiguration.getDefinitions();
70
66
 
71
- const newDefinition = newDefinitions.find(
72
- (d) => d.ymlPath === ymlPath
73
- );
74
- let currentDefinition = allDefinitions.find(
75
- (d) => d.ymlPath === ymlPath
76
- );
67
+ const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
68
+ let currentDefinition = allDefinitions.find((d) => d.ymlPath === ymlPath);
77
69
  const ymlExists = FS.existsSync(ymlPath);
78
70
  let type;
79
71
  if (ymlExists) {
@@ -112,32 +104,23 @@ class RepositoryManager {
112
104
  }
113
105
 
114
106
  stopListening() {
107
+ if (!this.watcher) {
108
+ return;
109
+ }
115
110
  this.watcher.close();
116
- this.watcher = null;
111
+ this.watcher = undefined;
117
112
  }
118
113
 
119
- /**
120
- *
121
- * @param {string[]} refs
122
- * @return {Promise<void>}
123
- * @private
124
- */
125
- async _install(refs) {
114
+ private async _install(refs: string[]): Promise<void> {
126
115
  //We make sure to only install one asset at a time - otherwise unexpected things might happen
127
- const out = new Promise((resolve, reject) => {
116
+ const out = new Promise<void>((resolve, reject) => {
128
117
  this._installQueue.push(async () => {
129
118
  try {
130
- const normalizedRefs = refs.map(
131
- (ref) => parseKapetaUri(ref).id
132
- );
133
- const filteredRefs = normalizedRefs.filter(
134
- (ref) => !INSTALL_ATTEMPTED[ref]
135
- );
119
+ const normalizedRefs = refs.map((ref) => parseKapetaUri(ref).id);
120
+ const filteredRefs = normalizedRefs.filter((ref) => !INSTALL_ATTEMPTED[ref]);
136
121
  console.log(filteredRefs);
137
122
  if (filteredRefs.length > 0) {
138
- filteredRefs.forEach(
139
- (ref) => (INSTALL_ATTEMPTED[ref] = true)
140
- );
123
+ filteredRefs.forEach((ref) => (INSTALL_ATTEMPTED[ref] = true));
141
124
  //Auto-install missing asset
142
125
  try {
143
126
  //We change to a temp dir to avoid issues with the current working directory
@@ -148,16 +131,12 @@ class RepositoryManager {
148
131
  type: 'start',
149
132
  refs,
150
133
  });
151
- await Actions.install(
152
- progressListener,
153
- normalizedRefs,
154
- {}
155
- );
134
+ await Actions.install(progressListener, normalizedRefs, {});
156
135
  socketManager.emit(`install`, 'install:action', {
157
136
  type: 'done',
158
137
  refs,
159
138
  });
160
- } catch (e) {
139
+ } catch (e: any) {
161
140
  socketManager.emit(`install`, 'install:action', {
162
141
  type: 'failed',
163
142
  refs,
@@ -189,27 +168,27 @@ class RepositoryManager {
189
168
  try {
190
169
  while (this._installQueue.length > 0) {
191
170
  const item = this._installQueue.shift();
192
-
193
- await item();
171
+ if (item) {
172
+ await item();
173
+ }
194
174
  }
195
175
  } finally {
196
176
  this._processing = false;
197
177
  }
198
178
  }
199
179
 
200
- async ensureAsset(handle, name, version) {
180
+ async ensureAsset(handle: string, name: string, version: string) {
201
181
  const fullName = `${handle}/${name}`;
202
182
  const ref = `${fullName}:${version}`;
203
183
 
204
184
  if (version === 'local') {
205
185
  //TODO: Get dependencies for local asset
206
- return null;
186
+ return;
207
187
  }
208
188
 
209
189
  const definitions = ClusterConfiguration.getDefinitions();
210
190
  const installedAsset = definitions.find(
211
- (d) =>
212
- d.definition.metadata.name === fullName && d.version === version
191
+ (d) => d.definition.metadata.name === fullName && d.version === version
213
192
  );
214
193
 
215
194
  if (installedAsset && this._cache[ref] === true) {
@@ -222,10 +201,7 @@ class RepositoryManager {
222
201
 
223
202
  let assetVersion;
224
203
  try {
225
- assetVersion = await this._registryService.getVersion(
226
- fullName,
227
- version
228
- );
204
+ assetVersion = await this._registryService.getVersion(fullName, version);
229
205
  if (!assetVersion) {
230
206
  this._cache[ref] = false;
231
207
  return;
@@ -244,11 +220,11 @@ class RepositoryManager {
244
220
  await this._install([ref]);
245
221
  } else {
246
222
  //Ensure dependencies are installed
247
- const refs = assetVersion.dependencies.map((dep) => dep.name);
223
+ const refs = assetVersion.dependencies.map((dep: Dependency) => dep.name);
248
224
  console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
249
225
  await this._install(refs);
250
226
  }
251
227
  }
252
228
  }
253
229
 
254
- module.exports = new RepositoryManager();
230
+ export const repositoryManager = new RepositoryManager();