@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,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,17 @@ 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
+ const [handle, name, version] = filename.toString().split(/\//g);
54
52
  if (!name || !version) {
55
53
  return;
56
54
  }
@@ -59,21 +57,11 @@ class RepositoryManager {
59
57
  return;
60
58
  }
61
59
 
62
- const ymlPath = Path.join(
63
- baseDir,
64
- handle,
65
- name,
66
- version,
67
- 'kapeta.yml'
68
- );
60
+ const ymlPath = Path.join(baseDir, handle, name, version, 'kapeta.yml');
69
61
  const newDefinitions = ClusterConfiguration.getDefinitions();
70
62
 
71
- const newDefinition = newDefinitions.find(
72
- (d) => d.ymlPath === ymlPath
73
- );
74
- let currentDefinition = allDefinitions.find(
75
- (d) => d.ymlPath === ymlPath
76
- );
63
+ const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
64
+ let currentDefinition = allDefinitions.find((d) => d.ymlPath === ymlPath);
77
65
  const ymlExists = FS.existsSync(ymlPath);
78
66
  let type;
79
67
  if (ymlExists) {
@@ -112,32 +100,23 @@ class RepositoryManager {
112
100
  }
113
101
 
114
102
  stopListening() {
103
+ if (!this.watcher) {
104
+ return;
105
+ }
115
106
  this.watcher.close();
116
- this.watcher = null;
107
+ this.watcher = undefined;
117
108
  }
118
109
 
119
- /**
120
- *
121
- * @param {string[]} refs
122
- * @return {Promise<void>}
123
- * @private
124
- */
125
- async _install(refs) {
110
+ private async _install(refs: string[]): Promise<void> {
126
111
  //We make sure to only install one asset at a time - otherwise unexpected things might happen
127
- const out = new Promise((resolve, reject) => {
112
+ const out = new Promise<void>((resolve, reject) => {
128
113
  this._installQueue.push(async () => {
129
114
  try {
130
- const normalizedRefs = refs.map(
131
- (ref) => parseKapetaUri(ref).id
132
- );
133
- const filteredRefs = normalizedRefs.filter(
134
- (ref) => !INSTALL_ATTEMPTED[ref]
135
- );
115
+ const normalizedRefs = refs.map((ref) => parseKapetaUri(ref).id);
116
+ const filteredRefs = normalizedRefs.filter((ref) => !INSTALL_ATTEMPTED[ref]);
136
117
  console.log(filteredRefs);
137
118
  if (filteredRefs.length > 0) {
138
- filteredRefs.forEach(
139
- (ref) => (INSTALL_ATTEMPTED[ref] = true)
140
- );
119
+ filteredRefs.forEach((ref) => (INSTALL_ATTEMPTED[ref] = true));
141
120
  //Auto-install missing asset
142
121
  try {
143
122
  //We change to a temp dir to avoid issues with the current working directory
@@ -148,16 +127,12 @@ class RepositoryManager {
148
127
  type: 'start',
149
128
  refs,
150
129
  });
151
- await Actions.install(
152
- progressListener,
153
- normalizedRefs,
154
- {}
155
- );
130
+ await Actions.install(progressListener, normalizedRefs, {});
156
131
  socketManager.emit(`install`, 'install:action', {
157
132
  type: 'done',
158
133
  refs,
159
134
  });
160
- } catch (e) {
135
+ } catch (e: any) {
161
136
  socketManager.emit(`install`, 'install:action', {
162
137
  type: 'failed',
163
138
  refs,
@@ -189,27 +164,27 @@ class RepositoryManager {
189
164
  try {
190
165
  while (this._installQueue.length > 0) {
191
166
  const item = this._installQueue.shift();
192
-
193
- await item();
167
+ if (item) {
168
+ await item();
169
+ }
194
170
  }
195
171
  } finally {
196
172
  this._processing = false;
197
173
  }
198
174
  }
199
175
 
200
- async ensureAsset(handle, name, version) {
176
+ async ensureAsset(handle: string, name: string, version: string) {
201
177
  const fullName = `${handle}/${name}`;
202
178
  const ref = `${fullName}:${version}`;
203
179
 
204
180
  if (version === 'local') {
205
181
  //TODO: Get dependencies for local asset
206
- return null;
182
+ return;
207
183
  }
208
184
 
209
185
  const definitions = ClusterConfiguration.getDefinitions();
210
186
  const installedAsset = definitions.find(
211
- (d) =>
212
- d.definition.metadata.name === fullName && d.version === version
187
+ (d) => d.definition.metadata.name === fullName && d.version === version
213
188
  );
214
189
 
215
190
  if (installedAsset && this._cache[ref] === true) {
@@ -222,10 +197,7 @@ class RepositoryManager {
222
197
 
223
198
  let assetVersion;
224
199
  try {
225
- assetVersion = await this._registryService.getVersion(
226
- fullName,
227
- version
228
- );
200
+ assetVersion = await this._registryService.getVersion(fullName, version);
229
201
  if (!assetVersion) {
230
202
  this._cache[ref] = false;
231
203
  return;
@@ -244,11 +216,11 @@ class RepositoryManager {
244
216
  await this._install([ref]);
245
217
  } else {
246
218
  //Ensure dependencies are installed
247
- const refs = assetVersion.dependencies.map((dep) => dep.name);
219
+ const refs = assetVersion.dependencies.map((dep: Dependency) => dep.name);
248
220
  console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
249
221
  await this._install(refs);
250
222
  }
251
223
  }
252
224
  }
253
225
 
254
- module.exports = new RepositoryManager();
226
+ export const repositoryManager = new RepositoryManager();